diff options
author | Nikita Malyavin <nikitamalyavin@gmail.com> | 2021-05-05 23:03:01 +0300 |
---|---|---|
committer | Nikita Malyavin <nikitamalyavin@gmail.com> | 2021-05-05 23:03:01 +0300 |
commit | 509e4990af4d99e9d3c790eabe1c1705ae910b55 (patch) | |
tree | 02d4ca9409711baef3ec163adc402f2c380df7c8 /storage/connect/tabrest.cpp | |
parent | 0cc811c633d1fe5290b10fa49fad0a4b889383fa (diff) | |
parent | 4f143a88bcb36e94e9edba8a3c5b4a350dcd9bf9 (diff) | |
download | mariadb-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.cpp | 208 |
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; |