Commit caff19ad authored by Olivier Bertrand's avatar Olivier Bertrand

- Copy Mongo2.jar and Mongo3.jar in plugin directory

  modified:   storage/connect/CMakeLists.txt
  modified:   storage/connect/javaconn.cpp

- Check privileges while creating tables with Discovery
  modified:   storage/connect/ha_connect.cc

- Calculate LRECL for JSON tables created with Discovery
  modified:   storage/connect/tabjson.cpp

- Use CreateProcess (Windows) or fork/exec (linux)
  to retrieve the result from REST queries
  modified:   storage/connect/tabrest.cpp

- Typo
  modified:   storage/connect/jmgoconn.cpp
parent e85006e6
...@@ -409,6 +409,10 @@ IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND) ...@@ -409,6 +409,10 @@ IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND)
INSTALL(FILES INSTALL(FILES
${CMAKE_CURRENT_SOURCE_DIR}/JavaWrappers.jar ${CMAKE_CURRENT_SOURCE_DIR}/JavaWrappers.jar
${CMAKE_CURRENT_BINARY_DIR}/JdbcInterface.jar ${CMAKE_CURRENT_BINARY_DIR}/JdbcInterface.jar
IF(CONNECT_WITH_MONGO)
${CMAKE_CURRENT_SOURCE_DIR}/Mongo2.jar
${CMAKE_CURRENT_SOURCE_DIR}/Mongo3.jar
ENDIF()
DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine) DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine)
ENDIF() ENDIF()
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
...@@ -170,7 +170,7 @@ ...@@ -170,7 +170,7 @@
#define JSONMAX 10 // JSON Default max grp size #define JSONMAX 10 // JSON Default max grp size
extern "C" { extern "C" {
char version[]= "Version 1.07.0002 January 27, 2021"; char version[]= "Version 1.07.0002 March 22, 2021";
#if defined(__WIN__) #if defined(__WIN__)
char compver[]= "Version 1.07.0002 " __DATE__ " " __TIME__; char compver[]= "Version 1.07.0002 " __DATE__ " " __TIME__;
char slash= '\\'; char slash= '\\';
...@@ -277,6 +277,10 @@ static handler *connect_create_handler(handlerton *hton, ...@@ -277,6 +277,10 @@ static handler *connect_create_handler(handlerton *hton,
TABLE_SHARE *table, TABLE_SHARE *table,
MEM_ROOT *mem_root); MEM_ROOT *mem_root);
static bool checkPrivileges(THD* thd, TABTYPE type, PTOS options,
const char* db, TABLE* table = NULL,
bool quick = false);
static int connect_assisted_discovery(handlerton *hton, THD* thd, static int connect_assisted_discovery(handlerton *hton, THD* thd,
TABLE_SHARE *table_s, TABLE_SHARE *table_s,
HA_CREATE_INFO *info); HA_CREATE_INFO *info);
...@@ -757,10 +761,10 @@ DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR name, LPCSTR dir) ...@@ -757,10 +761,10 @@ DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR name, LPCSTR dir)
used by the default rename_table and delete_table method in used by the default rename_table and delete_table method in
handler.cc. handler.cc.
For engines that have two file name extentions (separate meta/index file For engines that have two file name extensions (separate meta/index file
and data file), the order of elements is relevant. First element of engine and data file), the order of elements is relevant. First element of engine
file name extentions array should be meta/index file extention. Second file name extensions array should be meta/index file extension. Second
element - data file extention. This order is assumed by element - data file extension. This order is assumed by
prepare_for_repair() when REPAIR TABLE ... USE_FRM is issued. prepare_for_repair() when REPAIR TABLE ... USE_FRM is issued.
@see @see
...@@ -1296,9 +1300,9 @@ PCSZ GetStringTableOption(PGLOBAL g, PTOS options, PCSZ opname, PCSZ sdef) ...@@ -1296,9 +1300,9 @@ PCSZ GetStringTableOption(PGLOBAL g, PTOS options, PCSZ opname, PCSZ sdef)
else if (!stricmp(opname, "Data_charset")) else if (!stricmp(opname, "Data_charset"))
opval= options->data_charset; opval= options->data_charset;
else if (!stricmp(opname, "Http") || !stricmp(opname, "URL")) else if (!stricmp(opname, "Http") || !stricmp(opname, "URL"))
opval = options->http; opval= options->http;
else if (!stricmp(opname, "Uri")) else if (!stricmp(opname, "Uri"))
opval = options->uri; opval= options->uri;
if (!opval && options->oplist) if (!opval && options->oplist)
opval= GetListOption(g, opname, options->oplist); opval= GetListOption(g, opname, options->oplist);
...@@ -1612,7 +1616,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) ...@@ -1612,7 +1616,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
pcf->Opt= (fop) ? (int)fop->opt : 0; pcf->Opt= (fop) ? (int)fop->opt : 0;
if (fp->field_length >= 0) { if (fp->field_length >= 0) {
pcf->Length = fp->field_length; pcf->Length= fp->field_length;
// length is bytes for Connect, not characters // length is bytes for Connect, not characters
if (!strnicmp(chset, "utf8", 4)) if (!strnicmp(chset, "utf8", 4))
...@@ -1627,7 +1631,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) ...@@ -1627,7 +1631,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
pcf->Offset= (int)fop->offset; pcf->Offset= (int)fop->offset;
pcf->Freq= (int)fop->freq; pcf->Freq= (int)fop->freq;
pcf->Datefmt= (char*)fop->dateformat; pcf->Datefmt= (char*)fop->dateformat;
pcf->Fieldfmt = fop->fieldformat ? (char*)fop->fieldformat pcf->Fieldfmt= fop->fieldformat ? (char*)fop->fieldformat
: fop->jsonpath ? (char*)fop->jsonpath : (char*)fop->xmlpath; : fop->jsonpath ? (char*)fop->jsonpath : (char*)fop->xmlpath;
} else { } else {
pcf->Offset= -1; pcf->Offset= -1;
...@@ -4511,11 +4515,9 @@ int ha_connect::delete_all_rows() ...@@ -4511,11 +4515,9 @@ int ha_connect::delete_all_rows()
} // end of delete_all_rows } // end of delete_all_rows
bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick) static bool checkPrivileges(THD *thd, TABTYPE type, PTOS options,
const char *db, TABLE *table, bool quick)
{ {
const char *db= (dbn && *dbn) ? dbn : NULL;
TABTYPE type=GetRealType(options);
switch (type) { switch (type) {
case TAB_UNDEF: case TAB_UNDEF:
// case TAB_CATLG: // case TAB_CATLG:
...@@ -4598,6 +4600,15 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick) ...@@ -4598,6 +4600,15 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
my_printf_error(ER_UNKNOWN_ERROR, "check_privileges failed", MYF(0)); my_printf_error(ER_UNKNOWN_ERROR, "check_privileges failed", MYF(0));
return true; return true;
} // end of checkPrivileges
// Check whether the user has required (file) privileges
bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
{
const char *db= (dbn && *dbn) ? dbn : NULL;
TABTYPE type=GetRealType(options);
return checkPrivileges(thd, type, options, db, table, quick);
} // end of check_privileges } // end of check_privileges
// Check that two indexes are equivalent // Check that two indexes are equivalent
...@@ -5727,6 +5738,29 @@ static int connect_assisted_discovery(handlerton *, THD* thd, ...@@ -5727,6 +5738,29 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
#endif // REST_SUPPORT #endif // REST_SUPPORT
} // endif ttp } // endif ttp
if (fn && *fn)
switch (ttp) {
case TAB_FMT:
case TAB_DBF:
case TAB_XML:
case TAB_INI:
case TAB_VEC:
case TAB_REST:
case TAB_JSON:
#if defined(BSON_SUPPORT)
case TAB_BSON:
#endif // BSON_SUPPORT
if (checkPrivileges(thd, ttp, topt, db)) {
strcpy(g->Message, "This operation requires the FILE privilege");
rc= HA_ERR_INTERNAL_ERROR;
goto err;
} // endif check_privileges
break;
default:
break;
} // endswitch ttp
if (!tab) { if (!tab) {
if (ttp == TAB_TBL) { if (ttp == TAB_TBL) {
// Make tab the first table of the list // Make tab the first table of the list
......
/************ Javaconn C++ Functions Source Code File (.CPP) ***********/ /************ Javaconn C++ Functions Source Code File (.CPP) ***********/
/* Name: JAVAConn.CPP Version 1.0 */ /* Name: JAVAConn.CPP Version 1.1 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2017 */ /* (C) Copyright to the author Olivier BERTRAND 2017 - 2021 */
/* */ /* */
/* This file contains the JAVA connection classes functions. */ /* This file contains the JAVA connection classes functions. */
/***********************************************************************/ /***********************************************************************/
...@@ -400,24 +400,35 @@ bool JAVAConn::Open(PGLOBAL g) ...@@ -400,24 +400,35 @@ bool JAVAConn::Open(PGLOBAL g)
jpop->Append(ClassPath); jpop->Append(ClassPath);
} // endif ClassPath } // endif ClassPath
#if 0
// Java source will be compiled as a jar file installed in the plugin dir // Java source will be compiled as a jar file installed in the plugin dir
jpop->Append(sep); jpop->Append(sep);
jpop->Append(GetPluginDir()); jpop->Append(GetPluginDir());
jpop->Append("JdbcInterface.jar"); jpop->Append("JdbcInterface.jar");
#endif // 0
// All wrappers are pre-compiled in JavaWrappers.jar in the plugin dir // All wrappers are pre-compiled in JavaWrappers.jar in the plugin dir
jpop->Append(sep); jpop->Append(sep);
jpop->Append(GetPluginDir()); jpop->Append(GetPluginDir());
jpop->Append("JavaWrappers.jar"); jpop->Append("JavaWrappers.jar");
#if defined(MONGO_SUPPORT)
jpop->Append(sep);
jpop->Append(GetPluginDir());
jpop->Append("Mongo3.jar");
jpop->Append(sep);
jpop->Append(GetPluginDir());
jpop->Append("Mongo2.jar");
#endif // MONGO_SUPPORT
if ((cp = getenv("CLASSPATH"))) { if ((cp = getenv("CLASSPATH"))) {
jpop->Append(sep); jpop->Append(sep);
jpop->Append(cp); jpop->Append(cp);
} // endif cp } // endif cp
if (trace(1)) { if (trace(1)) {
htrc("ClassPath=%s\n", ClassPath); htrc("ClassPath=%s\n", ClassPath ? ClassPath : "null");
htrc("CLASSPATH=%s\n", cp); htrc("CLASSPATH=%s\n", cp ? cp : "null");
htrc("%s\n", jpop->GetStr()); htrc("%s\n", jpop->GetStr());
} // endif trace } // endif trace
......
...@@ -121,20 +121,21 @@ JMgoConn::JMgoConn(PGLOBAL g, PCSZ collname, PCSZ wrapper) ...@@ -121,20 +121,21 @@ JMgoConn::JMgoConn(PGLOBAL g, PCSZ collname, PCSZ wrapper)
/***********************************************************************/ /***********************************************************************/
void JMgoConn::AddJars(PSTRG jpop, char sep) void JMgoConn::AddJars(PSTRG jpop, char sep)
{ {
#if defined(BSON_SUPPORT) #if defined(DEVELOPMENT)
if (m_Version == 2) { if (m_Version == 2) {
jpop->Append(sep); jpop->Append(sep);
// jpop->Append("C:/Eclipse/workspace/MongoWrap2/bin"); // jpop->Append("C:/Eclipse/workspace/MongoWrap2/bin");
jpop->Append(sep); // jpop->Append(sep);
jpop->Append("C:/mongo-java-driver/mongo-java-driver-2.13.3.jar"); jpop->Append("C:/mongo-java-driver/mongo-java-driver-2.13.3.jar");
} else { } else {
jpop->Append(sep); jpop->Append(sep);
// jpop->Append("C:/Eclipse/workspace/MongoWrap3/bin"); // jpop->Append("C:/Eclipse/workspace/MongoWrap3/bin");
// jpop->Append(sep);
// jpop->Append("C:/Program Files/MariaDB 10.1/lib/plugin/JavaWrappers.jar"); // jpop->Append("C:/Program Files/MariaDB 10.1/lib/plugin/JavaWrappers.jar");
jpop->Append(sep); // jpop->Append(sep);
jpop->Append("C:/mongo-java-driver/mongo-java-driver-3.4.2.jar"); jpop->Append("C:/mongo-java-driver/mongo-java-driver-3.4.2.jar");
} // endif m_Version } // endif m_Version
#endif // BSON_SUPPORT #endif // DEVELOPMENT
} // end of AddJars } // end of AddJars
/***********************************************************************/ /***********************************************************************/
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
/* Include relevant sections of the MariaDB header file. */ /* Include relevant sections of the MariaDB header file. */
/***********************************************************************/ /***********************************************************************/
#include <my_global.h> #include <my_global.h>
#include <mysqld.h>
#include <sql_error.h>
/***********************************************************************/ /***********************************************************************/
/* Include application header files: */ /* Include application header files: */
...@@ -168,6 +170,7 @@ JSONDISC::JSONDISC(PGLOBAL g, uint *lg) ...@@ -168,6 +170,7 @@ JSONDISC::JSONDISC(PGLOBAL g, uint *lg)
int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
{ {
char filename[_MAX_PATH]; char filename[_MAX_PATH];
size_t reclg = 0;
bool mgo = (GetTypeID(topt->type) == TAB_MONGO); bool mgo = (GetTypeID(topt->type) == TAB_MONGO);
PGLOBAL G = NULL; PGLOBAL G = NULL;
...@@ -252,7 +255,7 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) ...@@ -252,7 +255,7 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetArrayValue(0) : NULL; jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetArrayValue(0) : NULL;
} else { } else {
if (!((tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0)))) { if (!((tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0)))) {
if (!mgo) { if (!mgo && !tdp->Uri) {
sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty); sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty);
return 0; return 0;
} else } else
...@@ -315,7 +318,9 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) ...@@ -315,7 +318,9 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
case RC_FX: case RC_FX:
goto err; goto err;
default: default:
// jsp = tjnp->FindRow(g); // FindRow was done in ReadDB if (tdp->Pretty != 2)
reclg = strlen(tjnp->To_Line);
jsp = tjnp->Row; jsp = tjnp->Row;
} // endswitch ReadDB } // endswitch ReadDB
...@@ -366,7 +371,9 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) ...@@ -366,7 +371,9 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
case RC_FX: case RC_FX:
goto err; goto err;
default: default:
// jsp = tjnp->FindRow(g); if (tdp->Pretty != 2 && reclg < strlen(tjnp->To_Line))
reclg = strlen(tjnp->To_Line);
jsp = tjnp->Row; jsp = tjnp->Row;
} // endswitch ReadDB } // endswitch ReadDB
...@@ -378,8 +385,12 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) ...@@ -378,8 +385,12 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
} // endfor i } // endfor i
if (tdp->Pretty != 2) if (tdp->Pretty != 2) {
if (!topt->lrecl)
topt->lrecl = reclg + 10;
tjnp->CloseDB(g); tjnp->CloseDB(g);
} // endif Pretty
return n; return n;
......
/************** tabrest C++ Program Source Code File (.CPP) ************/ /************** tabrest C++ Program Source Code File (.CPP) ************/
/* PROGRAM NAME: tabrest Version 1.8 */ /* PROGRAM NAME: tabrest Version 1.9 */
/* (C) Copyright to the author Olivier BERTRAND 2018 - 2020 */ /* (C) Copyright to the author Olivier BERTRAND 2018 - 2021 */
/* This program is the REST Web API support for MariaDB. */ /* This program is the REST Web API support for MariaDB. */
/* When compiled without MARIADB defined, it is the EOM module code. */ /* When compiled without MARIADB defined, it is the EOM module code. */
/* The way Connect handles NOSQL data returned by REST queries is */ /* The way Connect handles NOSQL data returned by REST queries is */
...@@ -53,10 +53,10 @@ ...@@ -53,10 +53,10 @@
#define PUSH_WARNING(M) htrc(M) #define PUSH_WARNING(M) htrc(M)
#endif #endif
#if defined(__WIN__) || defined(_WINDOWS) #if 0
#define popen _popen #define popen _popen
#define pclose _pclose #define pclose _pclose
#endif #endif // 0
static XGETREST getRestFnc = NULL; static XGETREST getRestFnc = NULL;
static int Xcurl(PGLOBAL g, PCSZ Http, PCSZ Uri, PCSZ filename); static int Xcurl(PGLOBAL g, PCSZ Http, PCSZ Uri, PCSZ filename);
...@@ -93,34 +93,87 @@ PTABDEF __stdcall GetREST(PGLOBAL g, void *memp) ...@@ -93,34 +93,87 @@ PTABDEF __stdcall GetREST(PGLOBAL g, void *memp)
/***********************************************************************/ /***********************************************************************/
int Xcurl(PGLOBAL g, PCSZ Http, PCSZ Uri, PCSZ filename) int Xcurl(PGLOBAL g, PCSZ Http, PCSZ Uri, PCSZ filename)
{ {
char buf[1024]; char buf[512];
int rc; int rc = 0;
FILE *pipe; FILE *pipe;
if ((pipe = popen("curl --version", "r"))) {
if (trace(515))
while (fgets(buf, sizeof(buf), pipe)) {
htrc("%s", buf);
} // endwhile
pclose(pipe);
} else {
sprintf(g->Message, "curl not available, errno=%d", errno);
return 1;
} // endif pipe
if (strchr(filename, '"')) {
strcpy(g->Message, "Invalid file name");
return 1;
} // endif filename
if (Uri) { if (Uri) {
if (*Uri == '/' || Http[strlen(Http) - 1] == '/') if (*Uri == '/' || Http[strlen(Http) - 1] == '/')
sprintf(buf, "curl \"%s%s\" -o %s", Http, Uri, filename); sprintf(buf, "%s%s", Http, Uri);
else else
sprintf(buf, "curl \"%s/%s\" -o %s", Http, Uri, filename); sprintf(buf, "%s/%s", Http, Uri);
} else } else
sprintf(buf, "curl \"%s\" -o %s", Http, filename); strcpy(buf, Http);
if ((pipe = popen(buf, "rt"))) { #if defined(__WIN__)
if (trace(515)) char cmd[1024];
while (fgets(buf, sizeof(buf), pipe)) { STARTUPINFO si;
htrc("%s", buf); PROCESS_INFORMATION pi;
} // endwhile
pclose(pipe); sprintf(cmd, "curl \"%s\" -o \"%s\"", buf, filename);
rc = 0;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
// Wait until child process exits.
WaitForSingleObject(pi.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
} else { } else {
sprintf(g->Message, "curl failed, errno =%d", errno); sprintf(g->Message, "CreateProcess curl failed (%d)", GetLastError());
rc = 1; rc = 1;
} // endif pipe } // endif CreateProcess
#else // !__WIN__
char fn[600];
int rcd;
pid_t pID = vfork();
sprintf(fn, "-o%s", filename);
if (pID == 0) {
// Code executed by child process
execlp("curl", "curl", buf, fn, (char*)NULL);
// If execlp() is successful, we should not reach this next line.
strcpy(g->Message, explain_execlp());
rc = 1;
exit(rc);
} // endif execlp
} else if (pID < 0) {
// failed to fork
strcpy(g->Message, "Failed to fork");
rc = 1;
} else {
// Parent process
wait(0); // Wait for the child to terminate
} // endif pID
#endif // !__WIN__
return rc; return rc;
} // end od Xcurl } // end of Xcurl
/***********************************************************************/ /***********************************************************************/
/* GetREST: load the Rest lib and get the Rest function. */ /* GetREST: load the Rest lib and get the Rest function. */
...@@ -319,7 +372,7 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -319,7 +372,7 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
} // endelse } // endelse
if (rc) { if (rc) {
strcpy(g->Message, "Cannot access to curl nor casablanca"); // strcpy(g->Message, "Cannot access to curl nor casablanca");
return true; return true;
} else switch (n) { } else switch (n) {
case 1: Tdp = new (g) JSONDEF; break; case 1: Tdp = new (g) JSONDEF; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment