summaryrefslogtreecommitdiff
path: root/storage/connect/tabrest.cpp
diff options
context:
space:
mode:
authorNikita Malyavin <nikitamalyavin@gmail.com>2021-05-05 23:03:01 +0300
committerNikita Malyavin <nikitamalyavin@gmail.com>2021-05-05 23:03:01 +0300
commit509e4990af4d99e9d3c790eabe1c1705ae910b55 (patch)
tree02d4ca9409711baef3ec163adc402f2c380df7c8 /storage/connect/tabrest.cpp
parent0cc811c633d1fe5290b10fa49fad0a4b889383fa (diff)
parent4f143a88bcb36e94e9edba8a3c5b4a350dcd9bf9 (diff)
downloadmariadb-git-509e4990af4d99e9d3c790eabe1c1705ae910b55.tar.gz
Merge branch bb-10.3-release into bb-10.4-release
Diffstat (limited to 'storage/connect/tabrest.cpp')
-rw-r--r--storage/connect/tabrest.cpp208
1 files changed, 101 insertions, 107 deletions
diff --git a/storage/connect/tabrest.cpp b/storage/connect/tabrest.cpp
index 1efda6e3bca..4b6bb6a9e62 100644
--- a/storage/connect/tabrest.cpp
+++ b/storage/connect/tabrest.cpp
@@ -1,8 +1,7 @@
/************** tabrest C++ Program Source Code File (.CPP) ************/
-/* PROGRAM NAME: tabrest Version 1.8 */
-/* (C) Copyright to the author Olivier BERTRAND 2018 - 2020 */
+/* PROGRAM NAME: tabrest Version 2.0 */
+/* (C) Copyright to the author Olivier BERTRAND 2018 - 2021 */
/* This program is the REST Web API support for MariaDB. */
-/* When compiled without MARIADB defined, it is the EOM module code. */
/* The way Connect handles NOSQL data returned by REST queries is */
/* just by retrieving it as a file and then leave the existing data */
/* type tables (JSON, XML or CSV) process it as usual. */
@@ -11,23 +10,13 @@
/***********************************************************************/
/* Definitions needed by the included files. */
/***********************************************************************/
-#if defined(MARIADB)
#include <my_global.h> // All MariaDB stuff
#include <mysqld.h>
#include <sql_error.h>
-#else // !MARIADB OEM module
-#include "mini-global.h"
-#define _MAX_PATH 260
-#if !defined(REST_SOURCE)
-#if defined(__WIN__) || defined(_WINDOWS)
-#include <windows.h>
-#else // !__WIN__
-#define __stdcall
-#include <dlfcn.h> // dlopen(), dlclose(), dlsym() ...
-#endif // !__WIN__
-#endif // !REST_SOURCE
-#define _OS_H_INCLUDED // Prevent os.h to be called
-#endif // !MARIADB
+#if !defined(__WIN__) && !defined(_WINDOWS)
+#include <sys/types.h>
+#include <sys/wait.h>
+#endif // !__WIN__ && !_WINDOWS
/***********************************************************************/
/* Include application header files: */
@@ -53,74 +42,98 @@
#define PUSH_WARNING(M) htrc(M)
#endif
-#if defined(__WIN__) || defined(_WINDOWS)
-#define popen _popen
-#define pclose _pclose
-#endif
-
static XGETREST getRestFnc = NULL;
static int Xcurl(PGLOBAL g, PCSZ Http, PCSZ Uri, PCSZ filename);
-#if !defined(MARIADB)
-/***********************************************************************/
-/* DB static variables. */
-/***********************************************************************/
-int TDB::Tnum;
-int DTVAL::Shift;
-int CSORT::Limit = 0;
-double CSORT::Lg2 = log(2.0);
-size_t CSORT::Cpn[1000] = { 0 };
-
-/***********************************************************************/
-/* These functions are exported from the REST library. */
-/***********************************************************************/
-extern "C" {
- PTABDEF __stdcall GetREST(PGLOBAL, void*);
- PQRYRES __stdcall ColREST(PGLOBAL, PTOS, char*, char*, bool);
-} // extern "C"
-
-/***********************************************************************/
-/* This function returns a table definition class. */
-/***********************************************************************/
-PTABDEF __stdcall GetREST(PGLOBAL g, void *memp)
-{
- return new(g, memp) RESTDEF;
-} // end of GetREST
-#endif // !MARIADB
-
/***********************************************************************/
/* Xcurl: retrieve the REST answer by executing cURL. */
/***********************************************************************/
int Xcurl(PGLOBAL g, PCSZ Http, PCSZ Uri, PCSZ filename)
{
- char buf[1024];
- int rc;
- FILE *pipe;
+ char buf[512];
+ int rc = 0;
+
+ if (strchr(filename, '"')) {
+ strcpy(g->Message, "Invalid file name");
+ return 1;
+ } // endif filename
if (Uri) {
if (*Uri == '/' || Http[strlen(Http) - 1] == '/')
- sprintf(buf, "curl %s%s -o %s", Http, Uri, filename);
+ sprintf(buf, "%s%s", Http, Uri);
else
- sprintf(buf, "curl %s/%s -o %s", Http, Uri, filename);
+ sprintf(buf, "%s/%s", Http, Uri);
} else
- sprintf(buf, "curl %s -o %s", Http, filename);
+ strcpy(buf, Http);
+
+#if defined(__WIN__)
+ char cmd[1024];
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ sprintf(cmd, "curl \"%s\" -o \"%s\"", buf, filename);
+
+ 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 {
+ sprintf(g->Message, "CreateProcess curl failed (%d)", GetLastError());
+ rc = 1;
+ } // endif CreateProcess
+#else // !__WIN__
+ char fn[600];
+ pid_t pID;
- if ((pipe = popen(buf, "rt"))) {
- if (trace(515))
- while (fgets(buf, sizeof(buf), pipe)) {
- htrc("%s", buf);
- } // endwhile
+ // Check if curl package is availabe by executing subprocess
+ FILE *f= popen("command -v curl", "r");
- pclose(pipe);
- rc = 0;
+ if (!f) {
+ strcpy(g->Message, "Problem in allocating memory.");
+ return 1;
} else {
- sprintf(g->Message, "curl failed, errno =%d", errno);
+ char temp_buff[50];
+ size_t len = fread(temp_buff,1, 50, f);
+
+ if(!len) {
+ strcpy(g->Message, "Curl not installed.");
+ return 1;
+ } else
+ pclose(f);
+
+ } // endif f
+
+ 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, "Unsuccessful execlp from vfork()");
+ exit(1);
+ } else if (pID < 0) {
+ // failed to fork
+ strcpy(g->Message, "Failed to fork");
rc = 1;
- } // endif pipe
+ } else {
+ // Parent process
+ wait(NULL); // Wait for the child to terminate
+ } // endif pID
+#endif // !__WIN__
return rc;
-} // end od Xcurl
+} // end of Xcurl
/***********************************************************************/
/* GetREST: load the Rest lib and get the Rest function. */
@@ -130,7 +143,7 @@ XGETREST GetRestFunction(PGLOBAL g)
if (getRestFnc)
return getRestFnc;
-#if !defined(MARIADB) || !defined(REST_SOURCE)
+#if !defined(REST_SOURCE)
if (trace(515))
htrc("Looking for GetRest library\n");
@@ -183,9 +196,9 @@ XGETREST GetRestFunction(PGLOBAL g)
return NULL;
} // endif getdef
#endif // !__WIN__
-#else
+#else // REST_SOURCE
getRestFnc = restGetFile;
-#endif
+#endif // REST_SOURCE
return getRestFnc;
} // end of GetRestFunction
@@ -193,30 +206,21 @@ XGETREST GetRestFunction(PGLOBAL g)
/***********************************************************************/
/* Return the columns definition to MariaDB. */
/***********************************************************************/
-#if defined(MARIADB)
PQRYRES RESTColumns(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
-#else // !MARIADB
-PQRYRES __stdcall ColREST(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
-#endif // !MARIADB
{
PQRYRES qrp= NULL;
char filename[_MAX_PATH + 1]; // MAX PATH ???
int rc;
- bool curl = false;
PCSZ http, uri, fn, ftype;
- XGETREST grf = GetRestFunction(g);
+ XGETREST grf = NULL;
+ bool curl = GetBooleanTableOption(g, tp, "Curl", false);
- if (!grf)
+ if (!curl && !(grf = GetRestFunction(g)))
curl = true;
http = GetStringTableOption(g, tp, "Http", NULL);
uri = GetStringTableOption(g, tp, "Uri", NULL);
-#if defined(MARIADB)
ftype = GetStringTableOption(g, tp, "Type", "JSON");
-#else // !MARIADB
- // OEM tables must specify the file type
- ftype = GetStringTableOption(g, tp, "Ftype", "JSON");
-#endif // !MARIADB
fn = GetStringTableOption(g, tp, "Filename", NULL);
if (!fn) {
@@ -230,28 +234,25 @@ PQRYRES __stdcall ColREST(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
filename[n + i] = tolower(ftype[i]);
fn = filename;
- tp->filename = PlugDup(g, fn);
+ tp->subtype = PlugDup(g, fn);
sprintf(g->Message, "No file name. Table will use %s", fn);
PUSH_WARNING(g->Message);
} // endif fn
// We used the file name relative to recorded datapath
PlugSetPath(filename, fn, db);
- curl = GetBooleanTableOption(g, tp, "Curl", curl);
+ remove(filename);
// Retrieve the file from the web and copy it locally
if (curl)
rc = Xcurl(g, http, uri, filename);
- else if (grf)
+ else
rc = grf(g->Message, trace(515), http, uri, filename);
- else {
- strcpy(g->Message, "Cannot access to curl nor casablanca");
- rc = 1;
- } // endif !grf
- if (rc)
+ if (rc) {
+ strcpy(g->Message, "Cannot access to curl nor casablanca");
return NULL;
- else if (!stricmp(ftype, "JSON"))
+ } else if (!stricmp(ftype, "JSON"))
qrp = JSONColumns(g, db, NULL, tp, info);
else if (!stricmp(ftype, "CSV"))
qrp = CSVColumns(g, NULL, tp, info);
@@ -274,19 +275,15 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
char filename[_MAX_PATH + 1];
int rc = 0, n;
- bool curl = false, xt = trace(515);
+ bool xt = trace(515);
LPCSTR ftype;
- XGETREST grf = GetRestFunction(g);
+ XGETREST grf = NULL;
+ bool curl = GetBoolCatInfo("Curl", false);
- if (!grf)
+ if (!curl && !(grf = GetRestFunction(g)))
curl = true;
-#if defined(MARIADB)
ftype = GetStringCatInfo(g, "Type", "JSON");
-#else // !MARIADB
- // OEM tables must specify the file type
- ftype = GetStringCatInfo(g, "Ftype", "JSON");
-#endif // !MARIADB
if (xt)
htrc("ftype = %s am = %s\n", ftype, SVP(am));
@@ -309,24 +306,21 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
// We used the file name relative to recorded datapath
PlugSetPath(filename, Fn, GetPath());
-
- curl = GetBoolCatInfo("Curl", curl);
+ remove(filename);
// Retrieve the file from the web and copy it locally
if (curl) {
rc = Xcurl(g, Http, Uri, filename);
xtrc(515, "Return from Xcurl: rc=%d\n", rc);
- } else if (grf) {
+ } else {
rc = grf(g->Message, xt, Http, Uri, filename);
xtrc(515, "Return from restGetFile: rc=%d\n", rc);
- } else {
- strcpy(g->Message, "Cannot access to curl nor casablanca");
- rc = 1;
- } // endif !grf
+ } // endelse
- if (rc)
- return true;
- else switch (n) {
+ if (rc) {
+ // strcpy(g->Message, "Cannot access to curl nor casablanca");
+ return true;
+ } else switch (n) {
case 1: Tdp = new (g) JSONDEF; break;
#if defined(XML_SUPPORT)
case 2: Tdp = new (g) XMLDEF; break;