From e4797a991f7597892608e9327adfc1ca7841e62d Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 30 Jul 2019 22:45:04 +0200 Subject: [PATCH 01/11] In CONNECT version 1.6.10 NOSQL facility is enhanced by a new way to retrieve NOSQL data. In addition to files and Mongo collections, JSON as well as XML and CSV data can be retrieved from the net as answers from REST queries. Because it uses and external package (cpprestsdk) this is currently available only to MariaDB servers compiled from source. -- Add the REST support when Microsoft Casablanca package (cpprestsdk) is installed. -- Also include some changes specific to MariaDB 10.3. modified: storage/connect/CMakeLists.txt -- Add conditional REST support -- Added string options HTTP and URI. -- Added added internal table type TAB_REST. modified: storage/connect/ha_connect.cc modified: storage/connect/mycat.cc modified: storage/connect/mycat.h modified: storage/connect/plgdbsem.h -- Fix MDEV-19648 Variable connect_conv_size doesn't change -- Change Variable wrong block parameter from 8169 to 1. -- Also change connect_conv_size default value to 1024. modified: storage/connect/ha_connect.cc -- Avoid possible buffer overflow -- In particular by the function ShowValue. modified: storage/connect/tabdos.cpp modified: storage/connect/tabfmt.cpp modified: storage/connect/value.cpp modified: storage/connect/value.h -- Add some cast to avoid some compiler warnings modified: storage/connect/filamdbf.cpp -- Fix some C++ error modified: storage/connect/javaconn.cpp modified: storage/connect/jmgoconn.cpp modified: storage/connect/plugutil.cpp -- Miscellaneous Typo and warning suppressing changes modified: storage/connect/connect.cpp modified: storage/connect/connect.h modified: storage/connect/filamvct.cpp modified: storage/connect/inihandl.cpp modified: storage/connect/jsonudf.cpp modified: storage/connect/libdoc.cpp modified: storage/connect/tabjson.cpp modified: storage/connect/tabtbl.cpp modified: storage/connect/tabxml.cpp modified: storage/connect/user_connect.cc modified: storage/connect/user_connect.h -- Update failing test results and disbling modified: storage/connect/mysql-test/connect/disabled.def modified: storage/connect/mysql-test/connect/r/dir.result modified: storage/connect/mysql-test/connect/r/grant.result modified: storage/connect/mysql-test/connect/r/jdbc.result modified: storage/connect/mysql-test/connect/r/jdbc_postgresql.result modified: storage/connect/mysql-test/connect/r/xml.result modified: storage/connect/mysql-test/connect/r/xml2.result modified: storage/connect/mysql-test/connect/r/xml2_mult.result modified: storage/connect/mysql-test/connect/r/xml_mult.result -- Add an option modified: storage/connect/mysql-test/connect/t/grant.test --- storage/connect/CMakeLists.txt | 33 +- storage/connect/connect.h | 2 +- storage/connect/ha_connect.cc | 633 +++++++++++++++++--------------- storage/connect/ha_connect.h | 6 +- storage/connect/inihandl.cpp | 4 +- storage/connect/jmgoconn.cpp | 5 +- storage/connect/jsonudf.cpp | 8 +- storage/connect/libdoc.cpp | 2 +- storage/connect/mycat.cc | 31 +- storage/connect/mycat.h | 6 +- storage/connect/plgdbsem.h | 4 +- storage/connect/restget.cpp | 87 +++++ storage/connect/tabjdbc.cpp | 4 +- storage/connect/tabjson.cpp | 2 +- storage/connect/tabrest.cpp | 133 +++++++ storage/connect/tabrest.h | 29 ++ storage/connect/tabtbl.cpp | 4 +- storage/connect/tabxml.cpp | 2 +- storage/connect/user_connect.cc | 2 +- storage/connect/user_connect.h | 2 +- 20 files changed, 664 insertions(+), 335 deletions(-) create mode 100644 storage/connect/restget.cpp create mode 100644 storage/connect/tabrest.cpp create mode 100644 storage/connect/tabrest.h diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index c8747f889c6..8fc7cf695e7 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -11,7 +11,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA SET(CONNECT_PLUGIN_STATIC "connect") SET(CONNECT_PLUGIN_DYNAMIC "connect") @@ -69,6 +69,10 @@ ELSE(NOT UNIX) # Add exception handling to the CONNECT project) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") SET(IPHLPAPI_LIBRARY iphlpapi.lib) + IF(MSVC AND (CMAKE_CXX_COMPILER_ID MATCHES Clang)) + # Connect does not work with clang-cl + RETURN() + ENDIF() ENDIF(UNIX) @@ -109,7 +113,6 @@ IF(CONNECT_WITH_LIBXML2) FIND_PACKAGE(LibXml2) IF (LIBXML2_FOUND) INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) - SET(ZLIB_LIBRARY "z") # see ZLIB_INCLUDE_DIR below SET(XML_LIBRARY ${LIBXML2_LIBRARIES}) SET(CONNECT_SOURCES ${CONNECT_SOURCES} libdoc.cpp libdoc.h) add_definitions(-DLIBXML2_SUPPORT) @@ -301,6 +304,24 @@ IF(CONNECT_WITH_MONGO) ENDIF(CONNECT_WITH_MONGO) +# +# REST +# + +OPTION(CONNECT_WITH_REST "Compile CONNECT storage engine with REST support" ON) + +IF(CONNECT_WITH_REST) + MESSAGE(STATUS "=====> REST support is ON") + FIND_PACKAGE(cpprestsdk) + IF (cpprestsdk_FOUND) + MESSAGE(STATUS "=====> cpprestsdk found") + SET(CONNECT_SOURCES ${CONNECT_SOURCES} tabrest.cpp restget.cpp tabrest.h) + add_definitions(-DREST_SUPPORT) + ELSE(NOT cpprestsdk_FOUND) + MESSAGE(STATUS "=====> cpprestsdk package not found") + ENDIF (cpprestsdk_FOUND) +ENDIF(CONNECT_WITH_REST) + # # XMAP # @@ -326,14 +347,6 @@ IF(NOT TARGET connect) RETURN() ENDIF() -# Don't link with bundled zlib and systel libxml2 at the same time. -# System libxml2 uses system zlib, might conflict with the bundled one. -IF (XML_LIBRARY AND BUILD_BUNDLED_ZLIB) - GET_PROPERTY(INCS TARGET connect PROPERTY INCLUDE_DIRECTORIES) - LIST(REMOVE_ITEM INCS ${ZLIB_INCLUDE_DIR}) - SET_PROPERTY(TARGET connect PROPERTY INCLUDE_DIRECTORIES ${INCS}) -ENDIF() - IF(WIN32) IF (libmongoc-1.0_FOUND) SET_TARGET_PROPERTIES(connect PROPERTIES LINK_FLAGS diff --git a/storage/connect/connect.h b/storage/connect/connect.h index 2bca8bf54cb..3a60cd40160 100644 --- a/storage/connect/connect.h +++ b/storage/connect/connect.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /**************** Cnt H Declares Source Code File (.H) *****************/ /* Name: CONNECT.H Version 2.4 */ diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 191230cb03c..e7d1b5f0e86 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file ha_connect.cc @@ -164,15 +164,15 @@ /***********************************************************************/ /* Initialize the ha_connect static members. */ /***********************************************************************/ -#define SZCONV 8192 +#define SZCONV 1024 // Default converted text size #define SZWORK 67108864 // Default work area size 64M #define SZWMIN 4194304 // Minimum work area size 4M #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.06.0009 January 27, 2019"; + char version[]= "Version 1.06.0010 June 01, 2019"; #if defined(__WIN__) - char compver[]= "Version 1.06.0009 " __DATE__ " " __TIME__; + char compver[]= "Version 1.06.0010 " __DATE__ " " __TIME__; char slash= '\\'; #else // !__WIN__ char slash= '/'; @@ -211,14 +211,14 @@ char *GetUserVariable(PGLOBAL g, const uchar *varname) { char buf[1024]; bool b; - THD *thd = current_thd; - CHARSET_INFO *cs = system_charset_info; - String *str = NULL, tmp(buf, sizeof(buf), cs); - HASH uvars = thd->user_vars; - user_var_entry *uvar = (user_var_entry*)my_hash_search(&uvars, varname, 0); + THD *thd= current_thd; + CHARSET_INFO *cs= system_charset_info; + String *str= NULL, tmp(buf, sizeof(buf), cs); + HASH uvars= thd->user_vars; + user_var_entry *uvar= (user_var_entry*)my_hash_search(&uvars, varname, 0); if (uvar) - str = uvar->val_str(&b, &tmp, NOT_FIXED_DEC); + str= uvar->val_str(&b, &tmp, NOT_FIXED_DEC); return str ? PlugDup(g, str->ptr()) : NULL; }; // end of GetUserVariable @@ -231,6 +231,9 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); PQRYRES VirColumns(PGLOBAL g, bool info); PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info); PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info); +#if defined(REST_SUPPORT) +PQRYRES RESTColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); +#endif // REST_SUPPORT #if defined(JAVA_SUPPORT) PQRYRES MGOColumns(PGLOBAL g, PCSZ db, PCSZ url, PTOS topt, bool info); #endif // JAVA_SUPPORT @@ -352,7 +355,7 @@ static MYSQL_THDVAR_UINT(work_size, static MYSQL_THDVAR_INT(conv_size, PLUGIN_VAR_RQCMDARG, // opt "Size used when converting TEXT columns.", - NULL, NULL, SZCONV, 0, 65500, 8192); + NULL, NULL, SZCONV, 0, 65500, 1); /** Type conversion: @@ -583,7 +586,9 @@ ha_create_table_option connect_table_option_list[]= HA_TOPTION_STRING("FILTER", filter), HA_TOPTION_STRING("OPTION_LIST", oplist), HA_TOPTION_STRING("DATA_CHARSET", data_charset), - HA_TOPTION_NUMBER("LRECL", lrecl, 0, 0, INT_MAX32, 1), + HA_TOPTION_STRING("HTTP", http), + HA_TOPTION_STRING("URI", uri), + HA_TOPTION_NUMBER("LRECL", lrecl, 0, 0, INT_MAX32, 1), HA_TOPTION_NUMBER("BLOCK_SIZE", elements, 0, 0, INT_MAX32, 1), //HA_TOPTION_NUMBER("ESTIMATE", estimate, 0, 0, INT_MAX32, 1), HA_TOPTION_NUMBER("MULTIPLE", multiple, 0, 0, 3, 1), @@ -991,11 +996,11 @@ static PCONNECT GetUser(THD *thd, PCONNECT xp) pthread_mutex_unlock(&usrmut); if (!xp) { - xp = new user_connect(thd); + xp= new user_connect(thd); if (xp->user_init()) { delete xp; - xp = NULL; + xp= NULL; } // endif user_init } // endif xp @@ -1027,6 +1032,19 @@ TABTYPE ha_connect::GetRealType(PTOS pos) if (type == TAB_UNDEF) type= pos->srcdef ? TAB_MYSQL : pos->tabname ? TAB_PRX : TAB_DOS; +#if defined(REST_SUPPORT) + else if (pos->http) + switch (type) { + case TAB_JSON: + case TAB_XML: + case TAB_CSV: + type = TAB_REST; + break; + case TAB_REST: + type = TAB_NIY; + break; + } // endswitch type +#endif // REST_SUPPORT } else type= TAB_UNDEF; @@ -1130,48 +1148,48 @@ PCSZ GetListOption(PGLOBAL g, PCSZ opname, PCSZ oplist, PCSZ def) return (char*)def; char key[16], val[256]; - char *pv, *pn, *pk = (char*)oplist; - PCSZ opval = def; + char *pv, *pn, *pk= (char*)oplist; + PCSZ opval= def; int n; while (*pk == ' ') pk++; - for (; pk; pk = pn) { - pn = strchr(pk, ','); - pv = strchr(pk, '='); + for (; pk; pk= pn) { + pn= strchr(pk, ','); + pv= strchr(pk, '='); if (pv && (!pn || pv < pn)) { - n = MY_MIN(static_cast(pv - pk), sizeof(key) - 1); + n= MY_MIN(static_cast(pv - pk), sizeof(key) - 1); memcpy(key, pk, n); while (n && key[n - 1] == ' ') n--; - key[n] = 0; + key[n]= 0; while (*(++pv) == ' '); - n = MY_MIN((pn ? pn - pv : strlen(pv)), sizeof(val) - 1); + n= MY_MIN((pn ? pn - pv : strlen(pv)), sizeof(val) - 1); memcpy(val, pv, n); while (n && val[n - 1] == ' ') n--; - val[n] = 0; + val[n]= 0; } else { - n = MY_MIN((pn ? pn - pk : strlen(pk)), sizeof(key) - 1); + n= MY_MIN((pn ? pn - pk : strlen(pk)), sizeof(key) - 1); memcpy(key, pk, n); while (n && key[n - 1] == ' ') n--; - key[n] = 0; - val[0] = 0; + key[n]= 0; + val[0]= 0; } // endif pv if (!stricmp(opname, key)) { - opval = PlugDup(g, val); + opval= PlugDup(g, val); break; } else if (!pn) break; @@ -1219,9 +1237,13 @@ PCSZ GetStringTableOption(PGLOBAL g, PTOS options, PCSZ opname, PCSZ sdef) else if (!stricmp(opname, "Colist")) opval= options->colist; else if (!stricmp(opname, "Filter")) - opval = options->filter; + opval= options->filter; else if (!stricmp(opname, "Data_charset")) opval= options->data_charset; + else if (!stricmp(opname, "Http") || !stricmp(opname, "URL")) + opval = options->http; + else if (!stricmp(opname, "Uri")) + opval = options->uri; if (!opval && options->oplist) opval= GetListOption(g, opname, options->oplist); @@ -1252,7 +1274,7 @@ bool GetBooleanTableOption(PGLOBAL g, PTOS options, PCSZ opname, bool bdef) else if (!stricmp(opname, "Header")) opval= (options->header != 0); // Is Boolean for some table types else if (!stricmp(opname, "Zipped")) - opval = options->zipped; + opval= options->zipped; else if (options->oplist) if ((pv= GetListOption(g, opname, options->oplist))) opval= (!*pv || *pv == 'y' || *pv == 'Y' || atoi(pv) != 0); @@ -1346,8 +1368,8 @@ PCSZ ha_connect::GetStringOption(PCSZ opname, PCSZ sdef) } else if (!stricmp(opname, "Query_String")) { // This escapes everything and returns a wrong query -// opval = thd_query_string(table->in_use)->str; - opval = (PCSZ)PlugSubAlloc(xp->g, NULL, +// opval= thd_query_string(table->in_use)->str; + opval= (PCSZ)PlugSubAlloc(xp->g, NULL, thd_query_string(table->in_use)->length + 1); strcpy((char*)opval, thd_query_string(table->in_use)->str); // sprintf((char*)opval, "%s", thd_query_string(table->in_use)->str); @@ -1368,7 +1390,7 @@ PCSZ ha_connect::GetStringOption(PCSZ opname, PCSZ sdef) || !stricmp(opname, "filename") || !stricmp(opname, "optname") || !stricmp(opname, "entry"))) - opval = GetRealString(opval); + opval= GetRealString(opval); if (!opval) { if (sdef && !strcmp(sdef, "*")) { @@ -1497,7 +1519,7 @@ PFOS ha_connect::GetFieldOptionStruct(Field *fdp) void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) { const char *cp; - char *chset, v = 0; + char *chset, v= 0; ha_field_option_struct *fop; Field* fp; Field* *fldp; @@ -1549,7 +1571,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) pcf->Fieldfmt= NULL; } // endif fop - chset = (char *)fp->charset()->name; + chset= (char *)fp->charset()->name; switch (fp->type()) { case MYSQL_TYPE_BLOB: @@ -1817,7 +1839,7 @@ const char *ha_connect::GetTableName(void) { const char *path= tshp ? tshp->path.str : table_share->path.str; const char *name= strrchr(path, slash); - return name ? name+1 : path; + return name ? name + 1 : path; } // end of GetTableName char *ha_connect::GetPartName(void) @@ -2055,10 +2077,10 @@ bool ha_connect::CheckColumnList(PGLOBAL g) } catch (int n) { if (trace(1)) htrc("Exception %d: %s\n", n, g->Message); - brc = true; + brc= true; } catch (const char *msg) { strcpy(g->Message, msg); - brc = true; + brc= true; } // end catch return brc; @@ -2185,9 +2207,9 @@ int ha_connect::MakeRecord(char *buf) rc= fp->store(p, strlen(p), charset, CHECK_FIELD_WARN); break; case TYPE_BIN: - p = value->GetCharValue(); - charset = &my_charset_bin; - rc = fp->store(p, strlen(p), charset, CHECK_FIELD_WARN); + p= value->GetCharValue(); + charset= &my_charset_bin; + rc= fp->store(p, strlen(p), charset, CHECK_FIELD_WARN); break; case TYPE_DOUBLE: rc= fp->store(value->GetFloatValue()); @@ -2436,7 +2458,7 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q, kfp= &table->key_info[active_index]; old_map= dbug_tmp_use_all_columns(table, table->write_set); - for (i = 0; i <= 1; i++) { + for (i= 0; i <= 1; i++) { if (ranges[i] == NULL) continue; @@ -2547,7 +2569,7 @@ const char *ha_connect::GetValStr(OPVAL vop, bool neg) switch (vop) { case OP_EQ: - val= " = "; + val= "= "; break; case OP_NE: val= " <> "; @@ -2817,7 +2839,7 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond) /***********************************************************************/ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) { - AMT tty = filp->Type; + AMT tty= filp->Type; char *body= filp->Body; char *havg= filp->Having; unsigned int i; @@ -2834,7 +2856,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) if (cond->type() == COND::COND_ITEM) { char *pb0, *pb1, *pb2, *ph0= 0, *ph1= 0, *ph2= 0; - bool bb = false, bh = false; + bool bb= false, bh= false; Item_cond *cond_item= (Item_cond *)cond; if (x) @@ -2893,13 +2915,13 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) bb |= filp->Bd; bh |= filp->Hv; - filp->Bd = filp->Hv = false; + filp->Bd= filp->Hv= false; } else return NULL; if (bb) { strcpy(pb1, ")"); - filp->Bd = bb; + filp->Bd= bb; } else *pb0= 0; @@ -2907,13 +2929,13 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) if (bb && bh && vop == OP_OR) { // Cannot or'ed a where clause with a having clause bb= bh= 0; - *pb0 = 0; - *ph0 = 0; + *pb0= 0; + *ph0= 0; } else if (bh) { strcpy(ph1, ")"); filp->Hv= bh; } else - *ph0 = 0; + *ph0= 0; } // endif havg @@ -2926,7 +2948,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) Item_func *condf= (Item_func *)cond; Item* *args= condf->arguments(); - filp->Bd = filp->Hv = false; + filp->Bd= filp->Hv= false; if (trace(1)) htrc("Func type=%d argnum=%d\n", condf->functype(), @@ -2942,10 +2964,10 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) case Item_func::GT_FUNC: vop= OP_GT; break; case Item_func::LIKE_FUNC: vop= OP_LIKE; - neg = ((Item_func_opt_neg *)condf)->negated; + neg= ((Item_func_opt_neg *)condf)->negated; break; case Item_func::ISNOTNULL_FUNC: - neg = true; + neg= true; // fall through case Item_func::ISNULL_FUNC: vop= OP_NULL; break; case Item_func::IN_FUNC: vop= OP_IN; /* fall through */ @@ -3003,12 +3025,12 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) } else { bool h; - fnm = filp->Chk(pField->field->field_name, &h); + fnm= filp->Chk(pField->field->field_name, &h); if (h && i && !ishav) return NULL; // Having should be col VOP arg else - ishav = h; + ishav= h; } // endif's @@ -3059,7 +3081,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) if (!x) { const char *p; - char *s = (ishav) ? havg : body; + char *s= (ishav) ? havg : body; uint j, k, n; // Append the value to the filter @@ -3116,37 +3138,37 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) strcat(s, "'}"); break; default: - j = strlen(s); - s[j++] = '\''; - p = res->ptr(); - n = res->length(); + j= strlen(s); + s[j++]= '\''; + p= res->ptr(); + n= res->length(); - for (k = 0; k < n; k++) { + for (k= 0; k < n; k++) { if (p[k] == '\'') - s[j++] = '\''; + s[j++]= '\''; - s[j++] = p[k]; + s[j++]= p[k]; } // endfor k - s[j++] = '\''; - s[j] = 0; + s[j++]= '\''; + s[j]= 0; } // endswitch field type } else { - j = strlen(s); - s[j++] = '\''; - p = res->ptr(); - n = res->length(); + j= strlen(s); + s[j++]= '\''; + p= res->ptr(); + n= res->length(); - for (k = 0; k < n; k++) { + for (k= 0; k < n; k++) { if (p[k] == '\'') - s[j++] = '\''; + s[j++]= '\''; - s[j++] = p[k]; + s[j++]= p[k]; } // endfor k - s[j++] = '\''; - s[j] = 0; + s[j++]= '\''; + s[j]= 0; } // endif tty break; @@ -3170,7 +3192,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) } // endif's Type if (!x) { - char *s = (ishav) ? havg : body; + char *s= (ishav) ? havg : body; if (!i) strcat(s, GetValStr(vop, neg)); @@ -3184,11 +3206,11 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) } // endfor i if (x) - filp->Op = vop; + filp->Op= vop; else if (ishav) - filp->Hv = true; + filp->Hv= true; else - filp->Bd = true; + filp->Bd= true; } else { if (trace(1)) @@ -3238,21 +3260,21 @@ const COND *ha_connect::cond_push(const COND *cond) PCFIL filp; int rc; - if ((filp = tdbp->GetCondFil()) && tdbp->GetCond() == cond && + if ((filp= tdbp->GetCondFil()) && tdbp->GetCond() == cond && filp->Idx == active_index && filp->Type == tty) goto fin; - filp = new(g) CONDFIL(active_index, tty); - rc = filp->Init(g, this); + filp= new(g) CONDFIL(active_index, tty); + rc= filp->Init(g, this); if (rc == RC_INFO) { - filp->Having = (char*)PlugSubAlloc(g, NULL, 256); - *filp->Having = 0; + filp->Having= (char*)PlugSubAlloc(g, NULL, 256); + *filp->Having= 0; } else if (rc == RC_FX) goto fin; - filp->Body = (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0); - *filp->Body = 0; + filp->Body= (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0); + *filp->Body= 0; if (CheckCond(g, filp, cond)) { if (filp->Having && strlen(filp->Having) > 255) @@ -3266,7 +3288,7 @@ const COND *ha_connect::cond_push(const COND *cond) if (!x) PlugSubAlloc(g, NULL, strlen(filp->Body) + 1); else - cond = NULL; // Does this work? + cond= NULL; // Does this work? tdbp->SetCondFil(filp); } else if (x && cond) @@ -3316,8 +3338,8 @@ ha_rows ha_connect::records() int ha_connect::check(THD* thd, HA_CHECK_OPT* check_opt) { - int rc = HA_ADMIN_OK; - PGLOBAL g = ((table && table->in_use) ? GetPlug(table->in_use, xp) : + int rc= HA_ADMIN_OK; + PGLOBAL g= ((table && table->in_use) ? GetPlug(table->in_use, xp) : (xp) ? xp->g : NULL); DBUG_ENTER("ha_connect::check"); @@ -3327,32 +3349,32 @@ int ha_connect::check(THD* thd, HA_CHECK_OPT* check_opt) // Do not close the table if it was opened yet (possible?) if (IsOpened()) { if (IsPartitioned() && CheckColumnList(g)) // map can have been changed - rc = HA_ADMIN_CORRUPT; + rc= HA_ADMIN_CORRUPT; else if (tdbp->OpenDB(g)) // Rewind table - rc = HA_ADMIN_CORRUPT; + rc= HA_ADMIN_CORRUPT; } else if (xp->CheckQuery(valid_query_id)) { - tdbp = NULL; // Not valid anymore + tdbp= NULL; // Not valid anymore if (OpenTable(g, false)) - rc = HA_ADMIN_CORRUPT; + rc= HA_ADMIN_CORRUPT; } else // possible? DBUG_RETURN(HA_ADMIN_INTERNAL_ERROR); if (rc == HA_ADMIN_OK) { - TABTYPE type = GetTypeID(GetStringOption("Type", "*")); + TABTYPE type= GetTypeID(GetStringOption("Type", "*")); if (IsFileType(type)) { if (check_opt->flags & T_MEDIUM) { // TO DO do { - if ((rc = CntReadNext(g, tdbp)) == RC_FX) + if ((rc= CntReadNext(g, tdbp)) == RC_FX) break; } while (rc != RC_EF); - rc = (rc == RC_EF) ? HA_ADMIN_OK : HA_ADMIN_CORRUPT; + rc= (rc == RC_EF) ? HA_ADMIN_OK : HA_ADMIN_CORRUPT; } else if (check_opt->flags & T_EXTEND) { // TO DO } // endif's flags @@ -3380,7 +3402,7 @@ bool ha_connect::get_error_message(int error, String* buf) DBUG_ENTER("ha_connect::get_error_message"); if (xp && xp->g) { - PGLOBAL g = xp->g; + PGLOBAL g= xp->g; if (trace(1)) htrc("GEM(%d): %s\n", error, g->Message); @@ -3489,32 +3511,32 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT*) try { // Ignore error on the opt file dup->Check &= ~CHK_OPT; - tdbp = GetTDB(g); + tdbp= GetTDB(g); dup->Check |= CHK_OPT; if (tdbp && !tdbp->IsRemote()) { - bool dop = IsTypeIndexable(GetRealType(NULL)); - bool dox = (tdbp->GetDef()->Indexable() == 1); + bool dop= IsTypeIndexable(GetRealType(NULL)); + bool dox= (tdbp->GetDef()->Indexable() == 1); - if ((rc = ((PTDBASE)tdbp)->ResetTableOpt(g, dop, dox))) { + if ((rc= ((PTDBASE)tdbp)->ResetTableOpt(g, dop, dox))) { if (rc == RC_INFO) { push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); - rc = 0; + rc= 0; } else - rc = HA_ERR_CRASHED_ON_USAGE; // Table must be repaired + rc= HA_ERR_CRASHED_ON_USAGE; // Table must be repaired } // endif rc } else if (!tdbp) - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; } catch (int n) { if (trace(1)) htrc("Exception %d: %s\n", n, g->Message); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; } catch (const char *msg) { strcpy(g->Message, msg); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; } // end catch if (rc) @@ -4214,7 +4236,7 @@ int ha_connect::rnd_pos(uchar *buf, uchar *pos) tdbp->SetFilter(NULL); rc= rnd_next(buf); } else { - PGLOBAL g = GetPlug((table) ? table->in_use : NULL, xp); + PGLOBAL g= GetPlug((table) ? table->in_use : NULL, xp); // strcpy(g->Message, "Not supported by this table type"); my_message(ER_ILLEGAL_HA, g->Message, MYF(0)); rc= HA_ERR_INTERNAL_ERROR; @@ -4298,12 +4320,12 @@ int ha_connect::info(uint flag) } else DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen - if (!(tdbp = GetTDB(g))) { + if (!(tdbp= GetTDB(g))) { my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } // endif tdbp - valid_info = false; + valid_info= false; } // endif tdbp if (!valid_info) { @@ -4446,6 +4468,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick) case TAB_XML: case TAB_INI: case TAB_VEC: + case TAB_REST: case TAB_JSON: if (options->filename && *options->filename) { if (!quick) { @@ -4582,13 +4605,13 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd, // newmode= MODE_UPDATE; // To be checked // break; case SQLCOM_DELETE_MULTI: - *cras = true; + *cras= true; case SQLCOM_DELETE: case SQLCOM_TRUNCATE: newmode= MODE_DELETE; break; case SQLCOM_UPDATE_MULTI: - *cras = true; + *cras= true; case SQLCOM_UPDATE: newmode= MODE_UPDATE; break; @@ -4616,7 +4639,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd, break; // } // endif partitioned case SQLCOM_REPAIR: // TODO implement it - newmode = MODE_UPDATE; + newmode= MODE_UPDATE; break; default: htrc("Unsupported sql_command=%d\n", thd_sql_command(thd)); @@ -4731,15 +4754,15 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type) if (CloseTable(g)) { // Make error a warning to avoid crash push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); - rc = 0; + rc= 0; } // endif Close - locked = 0; - xmod = MODE_ANY; // For info commands + locked= 0; + xmod= MODE_ANY; // For info commands DBUG_RETURN(rc); } // endif MODE_ANY - newmode = CheckMode(g, thd, newmode, &chk, &cras); + newmode= CheckMode(g, thd, newmode, &chk, &cras); if (newmode == MODE_ERROR) DBUG_RETURN(HA_ERR_INTERNAL_ERROR); @@ -4815,7 +4838,7 @@ int ha_connect::external_lock(THD *thd, int lock_type) DBUG_RETURN(0); } else if (g->Xchk) { if (!tdbp) { - if (!(tdbp = GetTDB(g))) { + if (!(tdbp= GetTDB(g))) { // DBUG_RETURN(HA_ERR_INTERNAL_ERROR); causes assert error push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); DBUG_RETURN(0); @@ -4952,7 +4975,7 @@ int ha_connect::external_lock(THD *thd, int lock_type) int ha_connect::check_stmt(PGLOBAL g, MODE newmode, bool cras) { - int rc = 0; + int rc= 0; DBUG_ENTER("ha_connect::check_stmt"); // If this is the start of a new query, cleanup the previous one @@ -5039,7 +5062,7 @@ THR_LOCK_DATA **ha_connect::store_lock(THD *, { if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) lock.type=lock_type; - *to++ = &lock; + *to++= &lock; return to; } @@ -5316,7 +5339,7 @@ static bool add_field(String *sql, const char *field_name, int typ, int len, int dec, char *key, uint tm, const char *rem, char *dft, char *xtra, char *fmt, int flag, bool dbf, char v) { - char var = (len > 255) ? 'V' : v; + char var= (len > 255) ? 'V' : v; bool q, error= false; const char *type= PLGtoMYSQLtype(typ, dbf, var); @@ -5360,9 +5383,9 @@ static bool add_field(String *sql, const char *field_name, int typ, int len, error|= sql->append(" DEFAULT "); if (typ == TYPE_DATE) - q = (strspn(dft, "0123456789 -:/") == strlen(dft)); + q= (strspn(dft, "0123456789 -:/") == strlen(dft)); else - q = !IsTypeNum(typ); + q= !IsTypeNum(typ); if (q) { error|= sql->append("'"); @@ -5514,13 +5537,13 @@ static int connect_assisted_discovery(handlerton *, THD* thd, PCSZ fncn= "?"; PCSZ user, fn, db, host, pwd, sep, tbl, src; PCSZ col, ocl, rnk, pic, fcl, skc, zfn; - char *tab, *dsn, *shm, *dpath; + char *tab, *dsn, *shm, *dpath, *url; #if defined(__WIN__) PCSZ nsp= NULL, cls= NULL; #endif // __WIN__ //int hdr, mxe; - int port = 0, mxr = 0, rc = 0, mul = 0, lrecl = 0; -//PCSZ tabtyp = NULL; + int port= 0, mxr= 0, rc= 0, mul= 0, lrecl= 0; +//PCSZ tabtyp= NULL; #if defined(ODBC_SUPPORT) POPARM sop= NULL; PCSZ ucnc= NULL; @@ -5530,7 +5553,6 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #if defined(JAVA_SUPPORT) PJPARM sjp= NULL; PCSZ driver= NULL; - char *url= NULL; #endif // JAVA_SUPPORT uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL); bool bif, ok= false, dbf= false; @@ -5550,7 +5572,8 @@ static int connect_assisted_discovery(handlerton *, THD* thd, String sql(buf, sizeof(buf), system_charset_info); sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info); - user= host= pwd= tbl= src= col= ocl= pic= fcl= skc= rnk= zfn= dsn= NULL; + user = host = pwd = tbl = src = col = ocl = pic = fcl = skc = rnk = zfn = NULL; + dsn = url = NULL; // Get the useful create options ttp= GetTypeID(topt->type); @@ -5561,7 +5584,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, fncn= topt->catfunc; fnc= GetFuncID(fncn); sep= topt->separator; - mul = (int)topt->multiple; + mul= (int)topt->multiple; tbl= topt->tablist; col= topt->colist; @@ -5584,7 +5607,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #endif // __WIN__ port= atoi(GetListOption(g, "port", topt->oplist, "0")); #if defined(ODBC_SUPPORT) -// tabtyp = GetListOption(g, "Tabtype", topt->oplist, NULL); +// tabtyp= GetListOption(g, "Tabtype", topt->oplist, NULL); mxr= atoi(GetListOption(g,"maxres", topt->oplist, "0")); cto= atoi(GetListOption(g,"ConnectTimeout", topt->oplist, "-1")); qto= atoi(GetListOption(g,"QueryTimeout", topt->oplist, "-1")); @@ -5599,7 +5622,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0")); #endif // PROMPT_OK #if defined(ZIP_SUPPORT) - zfn = GetListOption(g, "Zipfile", topt->oplist, NULL); + zfn= GetListOption(g, "Zipfile", topt->oplist, NULL); #endif // ZIP_SUPPORT } else { host= "localhost"; @@ -5612,14 +5635,24 @@ static int connect_assisted_discovery(handlerton *, THD* thd, try { // Check table type if (ttp == TAB_UNDEF) { - topt->type = (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS"; - ttp = GetTypeID(topt->type); + topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS"; + ttp= GetTypeID(topt->type); sprintf(g->Message, "No table_type. Was set to %s", topt->type); push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); } else if (ttp == TAB_NIY) { sprintf(g->Message, "Unsupported table type %s", topt->type); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; +#if defined(REST_SUPPORT) + } else if (topt->http) { + switch (ttp) { + case TAB_JSON: + case TAB_XML: + case TAB_CSV: + ttp = TAB_REST; + break; + } // endswitch type +#endif // REST_SUPPORT } // endif ttp if (!tab) { @@ -5629,39 +5662,39 @@ static int connect_assisted_discovery(handlerton *, THD* thd, if (!tbl) { strcpy(g->Message, "Missing table list"); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif tbl - tab = PlugDup(g, tbl); + tab= PlugDup(g, tbl); - if ((p = strchr(tab, ','))) - *p = 0; + if ((p= strchr(tab, ','))) + *p= 0; - if ((p = strchr(tab, '.'))) { - *p = 0; - db = tab; - tab = p + 1; + if ((p= strchr(tab, '.'))) { + *p= 0; + db= tab; + tab= p + 1; } // endif p } else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL))) - tab = (char*)table_s->table_name.str; // Default value + tab= (char*)table_s->table_name.str; // Default value } // endif tab switch (ttp) { #if defined(ODBC_SUPPORT) case TAB_ODBC: - dsn = strz(g, create_info->connect_string); + dsn= strz(g, create_info->connect_string); if (fnc & (FNC_DSN | FNC_DRIVER)) { - ok = true; + ok= true; #if defined(PROMPT_OK) } else if (!stricmp(thd->main_security_ctx.host, "localhost") && cop == 1) { - if ((dsn = ODBCCheckConnection(g, dsn, cop)) != NULL) { + if ((dsn= ODBCCheckConnection(g, dsn, cop)) != NULL) { thd->make_lex_string(&create_info->connect_string, dsn, strlen(dsn)); - ok = true; + ok= true; } // endif dsn #endif // PROMPT_OK @@ -5669,13 +5702,13 @@ static int connect_assisted_discovery(handlerton *, THD* thd, sprintf(g->Message, "Missing %s connection string", topt->type); } else { // Store ODBC additional parameters - sop = (POPARM)PlugSubAlloc(g, NULL, sizeof(ODBCPARM)); - sop->User = (char*)user; - sop->Pwd = (char*)pwd; - sop->Cto = cto; - sop->Qto = qto; - sop->UseCnc = cnc; - ok = true; + sop= (POPARM)PlugSubAlloc(g, NULL, sizeof(ODBCPARM)); + sop->User= (char*)user; + sop->Pwd= (char*)pwd; + sop->Cto= cto; + sop->Qto= qto; + sop->UseCnc= cnc; + ok= true; } // endif's supfnc |= (FNC_TABLE | FNC_DSN | FNC_DRIVER); @@ -5684,31 +5717,31 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #if defined(JAVA_SUPPORT) case TAB_JDBC: if (fnc & FNC_DRIVER) { - ok = true; - } else if (!(url = strz(g, create_info->connect_string))) { + ok= true; + } else if (!(url= strz(g, create_info->connect_string))) { strcpy(g->Message, "Missing URL"); } else { // Store JDBC additional parameters int rc; - PJDBCDEF jdef = new(g) JDBCDEF(); + PJDBCDEF jdef= new(g) JDBCDEF(); jdef->SetName(create_info->alias); - sjp = (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM)); - sjp->Driver = driver; - // sjp->Properties = prop; - sjp->Fsize = 0; - sjp->Scrollable = false; + sjp= (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM)); + sjp->Driver= driver; + // sjp->Properties= prop; + sjp->Fsize= 0; + sjp->Scrollable= false; - if ((rc = jdef->ParseURL(g, url, false)) == RC_OK) { - sjp->Url = url; - sjp->User = (char*)user; - sjp->Pwd = (char*)pwd; - ok = true; + if ((rc= jdef->ParseURL(g, url, false)) == RC_OK) { + sjp->Url= url; + sjp->User= (char*)user; + sjp->Pwd= (char*)pwd; + ok= true; } else if (rc == RC_NF) { if (jdef->GetTabname()) - tab = (char*)jdef->GetTabname(); + tab= (char*)jdef->GetTabname(); - ok = jdef->SetParms(sjp); + ok= jdef->SetParms(sjp); } // endif rc } // endif's @@ -5717,7 +5750,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, break; #endif // JAVA_SUPPORT case TAB_DBF: - dbf = true; + dbf= true; // fall through case TAB_CSV: if (!fn && fnc != FNC_NO) @@ -5725,55 +5758,55 @@ static int connect_assisted_discovery(handlerton *, THD* thd, else if (sep && strlen(sep) > 1) sprintf(g->Message, "Invalid separator %s", sep); else - ok = true; + ok= true; break; case TAB_MYSQL: - ok = true; + ok= true; if (create_info->connect_string.str && create_info->connect_string.length) { - PMYDEF mydef = new(g) MYSQLDEF(); + PMYDEF mydef= new(g) MYSQLDEF(); - dsn = strz(g, create_info->connect_string); + dsn= strz(g, create_info->connect_string); mydef->SetName(create_info->alias); if (!mydef->ParseURL(g, dsn, false)) { if (mydef->GetHostname()) - host = mydef->GetHostname(); + host= mydef->GetHostname(); if (mydef->GetUsername()) - user = mydef->GetUsername(); + user= mydef->GetUsername(); if (mydef->GetPassword()) - pwd = mydef->GetPassword(); + pwd= mydef->GetPassword(); if (mydef->GetTabschema()) - db = mydef->GetTabschema(); + db= mydef->GetTabschema(); if (mydef->GetTabname()) - tab = (char*)mydef->GetTabname(); + tab= (char*)mydef->GetTabname(); if (mydef->GetPortnumber()) - port = mydef->GetPortnumber(); + port= mydef->GetPortnumber(); } else - ok = false; + ok= false; } else if (!user) - user = "root"; + user= "root"; if (ok && CheckSelf(g, table_s, host, db, tab, src, port)) - ok = false; + ok= false; break; #if defined(__WIN__) case TAB_WMI: - ok = true; + ok= true; break; #endif // __WIN__ case TAB_PIVOT: - supfnc = FNC_NO; + supfnc= FNC_NO; case TAB_PRX: case TAB_TBL: case TAB_XCL: @@ -5782,12 +5815,12 @@ static int connect_assisted_discovery(handlerton *, THD* thd, (!db || !stricmp(db, table_s->db.str))) sprintf(g->Message, "A %s table cannot refer to itself", topt->type); else - ok = true; + ok= true; break; case TAB_OEM: if (topt->module && topt->subtype) - ok = true; + ok= true; else strcpy(g->Message, "Missing OEM module or subtype"); @@ -5796,24 +5829,33 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case TAB_XML: #endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT case TAB_JSON: - dsn = strz(g, create_info->connect_string); + dsn= strz(g, create_info->connect_string); if (!fn && !zfn && !mul && !dsn) sprintf(g->Message, "Missing %s file name", topt->type); else - ok = true; + ok= true; break; #if defined(JAVA_SUPPORT) case TAB_MONGO: if (!topt->tabname) - topt->tabname = tab; + topt->tabname= tab; - ok = true; + ok= true; break; #endif // JAVA_SUPPORT +#if defined(REST_SUPPORT) + case TAB_REST: + if (!topt->http) + sprintf(g->Message, "Missing %s HTTP address", topt->type); + else + ok = true; + + break; +#endif // REST_SUPPORT case TAB_VIR: - ok = true; + ok= true; break; default: sprintf(g->Message, "Cannot get column info for table type %s", topt->type); @@ -5824,12 +5866,12 @@ static int connect_assisted_discovery(handlerton *, THD* thd, if (ok && !(supfnc & fnc)) { sprintf(g->Message, "Unsupported catalog function %s for table type %s", fncn, topt->type); - ok = false; + ok= false; } // endif supfnc if (src && fnc != FNC_NO) { strcpy(g->Message, "Cannot make catalog table from srcdef"); - ok = false; + ok= false; } // endif src if (ok) { @@ -5837,23 +5879,23 @@ static int connect_assisted_discovery(handlerton *, THD* thd, char *dft, *xtra, *key, *fmt; int i, len, prec, dec, typ, flg; - if (!(dpath = SetPath(g, table_s->db.str))) { - rc = HA_ERR_INTERNAL_ERROR; + if (!(dpath= SetPath(g, table_s->db.str))) { + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif dpath if (src && ttp != TAB_PIVOT && ttp != TAB_ODBC && ttp != TAB_JDBC) { - qrp = SrcColumns(g, host, db, user, pwd, src, port); + qrp= SrcColumns(g, host, db, user, pwd, src, port); if (qrp && ttp == TAB_OCCUR) if (OcrSrcCols(g, qrp, col, ocl, rnk)) { - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif OcrSrcCols } else switch (ttp) { case TAB_DBF: - qrp = DBFColumns(g, dpath, fn, fnc == FNC_COL); + qrp= DBFColumns(g, dpath, fn, fnc == FNC_COL); break; #if defined(ODBC_SUPPORT) case TAB_ODBC: @@ -5861,21 +5903,21 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case FNC_NO: case FNC_COL: if (src) { - qrp = ODBCSrcCols(g, dsn, (char*)src, sop); - src = NULL; // for next tests + qrp= ODBCSrcCols(g, dsn, (char*)src, sop); + src= NULL; // for next tests } else - qrp = ODBCColumns(g, dsn, shm, tab, NULL, + qrp= ODBCColumns(g, dsn, shm, tab, NULL, mxr, fnc == FNC_COL, sop); break; case FNC_TABLE: - qrp = ODBCTables(g, dsn, shm, tab, NULL, mxr, true, sop); + qrp= ODBCTables(g, dsn, shm, tab, NULL, mxr, true, sop); break; case FNC_DSN: - qrp = ODBCDataSources(g, mxr, true); + qrp= ODBCDataSources(g, mxr, true); break; case FNC_DRIVER: - qrp = ODBCDrivers(g, mxr, true); + qrp= ODBCDrivers(g, mxr, true); break; default: sprintf(g->Message, "invalid catfunc %s", fncn); @@ -5890,23 +5932,23 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case FNC_NO: case FNC_COL: if (src) { - qrp = JDBCSrcCols(g, (char*)src, sjp); - src = NULL; // for next tests + qrp= JDBCSrcCols(g, (char*)src, sjp); + src= NULL; // for next tests } else - qrp = JDBCColumns(g, shm, tab, NULL, mxr, fnc == FNC_COL, sjp); + qrp= JDBCColumns(g, shm, tab, NULL, mxr, fnc == FNC_COL, sjp); break; case FNC_TABLE: -// qrp = JDBCTables(g, shm, tab, tabtyp, mxr, true, sjp); - qrp = JDBCTables(g, shm, tab, NULL, mxr, true, sjp); +// qrp= JDBCTables(g, shm, tab, tabtyp, mxr, true, sjp); + qrp= JDBCTables(g, shm, tab, NULL, mxr, true, sjp); break; #if 0 case FNC_DSN: - qrp = JDBCDataSources(g, mxr, true); + qrp= JDBCDataSources(g, mxr, true); break; #endif // 0 case FNC_DRIVER: - qrp = JDBCDrivers(g, mxr, true); + qrp= JDBCDrivers(g, mxr, true); break; default: sprintf(g->Message, "invalid catfunc %s", fncn); @@ -5916,56 +5958,61 @@ static int connect_assisted_discovery(handlerton *, THD* thd, break; #endif // JAVA_SUPPORT case TAB_MYSQL: - qrp = MyColumns(g, thd, host, db, user, pwd, tab, + qrp= MyColumns(g, thd, host, db, user, pwd, tab, NULL, port, fnc == FNC_COL); break; case TAB_CSV: - qrp = CSVColumns(g, dpath, topt, fnc == FNC_COL); + qrp= CSVColumns(g, dpath, topt, fnc == FNC_COL); break; #if defined(__WIN__) case TAB_WMI: - qrp = WMIColumns(g, nsp, cls, fnc == FNC_COL); + qrp= WMIColumns(g, nsp, cls, fnc == FNC_COL); break; #endif // __WIN__ case TAB_PRX: case TAB_TBL: case TAB_XCL: case TAB_OCCUR: - bif = fnc == FNC_COL; - qrp = TabColumns(g, thd, db, tab, bif); + bif= fnc == FNC_COL; + qrp= TabColumns(g, thd, db, tab, bif); if (!qrp && bif && fnc != FNC_COL) // tab is a view - qrp = MyColumns(g, thd, host, db, user, pwd, tab, NULL, port, false); + qrp= MyColumns(g, thd, host, db, user, pwd, tab, NULL, port, false); if (qrp && ttp == TAB_OCCUR && fnc != FNC_COL) if (OcrColumns(g, qrp, col, ocl, rnk)) { - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif OcrColumns break; case TAB_PIVOT: - qrp = PivotColumns(g, tab, src, pic, fcl, skc, host, db, user, pwd, port); + qrp= PivotColumns(g, tab, src, pic, fcl, skc, host, db, user, pwd, port); break; case TAB_VIR: - qrp = VirColumns(g, fnc == FNC_COL); + qrp= VirColumns(g, fnc == FNC_COL); break; case TAB_JSON: - qrp = JSONColumns(g, db, dsn, topt, fnc == FNC_COL); + qrp= JSONColumns(g, db, dsn, topt, fnc == FNC_COL); break; #if defined(JAVA_SUPPORT) case TAB_MONGO: - url = strz(g, create_info->connect_string); - qrp = MGOColumns(g, db, url, topt, fnc == FNC_COL); + url= strz(g, create_info->connect_string); + qrp= MGOColumns(g, db, url, topt, fnc == FNC_COL); break; #endif // JAVA_SUPPORT #if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT) case TAB_XML: - qrp = XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL); + qrp= XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL); break; #endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT +#if defined(REST_SUPPORT) + case TAB_REST: + qrp = RESTColumns(g, topt, tab, (char *)db, fnc == FNC_COL); + break; +#endif // REST_SUPPORT case TAB_OEM: - qrp = OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL); + qrp= OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL); break; default: strcpy(g->Message, "System error during assisted discovery"); @@ -5973,33 +6020,33 @@ static int connect_assisted_discovery(handlerton *, THD* thd, } // endswitch ttp if (!qrp) { - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif !qrp if (fnc != FNC_NO || src || ttp == TAB_PIVOT) { // Catalog like table - for (crp = qrp->Colresp; !rc && crp; crp = crp->Next) { - cnm = (ttp == TAB_PIVOT) ? crp->Name : encode(g, crp->Name); - typ = crp->Type; - len = crp->Length; - dec = crp->Prec; - flg = crp->Flag; - v = (crp->Kdata->IsUnsigned()) ? 'U' : crp->Var; - tm = (crp->Kdata->IsNullable()) ? 0 : NOT_NULL_FLAG; + for (crp= qrp->Colresp; !rc && crp; crp= crp->Next) { + cnm= (ttp == TAB_PIVOT) ? crp->Name : encode(g, crp->Name); + typ= crp->Type; + len= crp->Length; + dec= crp->Prec; + flg= crp->Flag; + v= (crp->Kdata->IsUnsigned()) ? 'U' : crp->Var; + tm= (crp->Kdata->IsNullable()) ? 0 : NOT_NULL_FLAG; if (!len && typ == TYPE_STRING) - len = 256; // STRBLK's have 0 length + len= 256; // STRBLK's have 0 length // Now add the field if (add_field(&sql, cnm, typ, len, dec, NULL, tm, NULL, NULL, NULL, NULL, flg, dbf, v)) - rc = HA_ERR_OUT_OF_MEM; + rc= HA_ERR_OUT_OF_MEM; } // endfor crp } else { - char *schem = NULL; - char *tn = NULL; + char *schem= NULL; + char *tn= NULL; // Not a catalog table if (!qrp->Nblin) { @@ -6008,57 +6055,57 @@ static int connect_assisted_discovery(handlerton *, THD* thd, else strcpy(g->Message, "Fail to retrieve columns"); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif !nblin - for (i = 0; !rc && i < qrp->Nblin; i++) { - typ = len = prec = dec = 0; - tm = NOT_NULL_FLAG; - cnm = (char*)"noname"; - dft = xtra = key = fmt = tn = NULL; - v = ' '; - rem = NULL; + for (i= 0; !rc && i < qrp->Nblin; i++) { + typ= len= prec= dec= 0; + tm= NOT_NULL_FLAG; + cnm= (char*)"noname"; + dft= xtra= key= fmt= tn= NULL; + v= ' '; + rem= NULL; - for (crp = qrp->Colresp; crp; crp = crp->Next) + for (crp= qrp->Colresp; crp; crp= crp->Next) switch (crp->Fld) { case FLD_NAME: if (ttp == TAB_PRX || (ttp == TAB_CSV && topt->data_charset && (!stricmp(topt->data_charset, "UTF8") || !stricmp(topt->data_charset, "UTF-8")))) - cnm = crp->Kdata->GetCharValue(i); + cnm= crp->Kdata->GetCharValue(i); else - cnm = encode(g, crp->Kdata->GetCharValue(i)); + cnm= encode(g, crp->Kdata->GetCharValue(i)); break; case FLD_TYPE: - typ = crp->Kdata->GetIntValue(i); - v = (crp->Nulls) ? crp->Nulls[i] : 0; + typ= crp->Kdata->GetIntValue(i); + v= (crp->Nulls) ? crp->Nulls[i] : 0; break; case FLD_TYPENAME: - tn = crp->Kdata->GetCharValue(i); + tn= crp->Kdata->GetCharValue(i); break; case FLD_PREC: // PREC must be always before LENGTH - len = prec = crp->Kdata->GetIntValue(i); + len= prec= crp->Kdata->GetIntValue(i); break; case FLD_LENGTH: - len = crp->Kdata->GetIntValue(i); + len= crp->Kdata->GetIntValue(i); break; case FLD_SCALE: - dec = (!crp->Kdata->IsNull(i)) ? crp->Kdata->GetIntValue(i) : -1; + dec= (!crp->Kdata->IsNull(i)) ? crp->Kdata->GetIntValue(i) : -1; break; case FLD_NULL: if (crp->Kdata->GetIntValue(i)) - tm = 0; // Nullable + tm= 0; // Nullable break; case FLD_FORMAT: - fmt = (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL; + fmt= (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL; break; case FLD_REM: - rem = crp->Kdata->GetCharValue(i); + rem= crp->Kdata->GetCharValue(i); break; // case FLD_CHARSET: // No good because remote table is already translated @@ -6067,19 +6114,19 @@ static int connect_assisted_discovery(handlerton *, THD* thd, // break; case FLD_DEFAULT: - dft = crp->Kdata->GetCharValue(i); + dft= crp->Kdata->GetCharValue(i); break; case FLD_EXTRA: - xtra = crp->Kdata->GetCharValue(i); + xtra= crp->Kdata->GetCharValue(i); // Auto_increment is not supported yet if (!stricmp(xtra, "AUTO_INCREMENT")) - xtra = NULL; + xtra= NULL; break; case FLD_KEY: if (ttp == TAB_VIR) - key = crp->Kdata->GetCharValue(i); + key= crp->Kdata->GetCharValue(i); break; case FLD_SCHEM: @@ -6088,10 +6135,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, if (schem && stricmp(schem, crp->Kdata->GetCharValue(i))) { sprintf(g->Message, "Several %s tables found, specify DBNAME", tab); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } else if (!schem) - schem = crp->Kdata->GetCharValue(i); + schem= crp->Kdata->GetCharValue(i); } // endif ttp #endif // ODBC_SUPPORT || JAVA_SUPPORT @@ -6102,10 +6149,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #if defined(ODBC_SUPPORT) if (ttp == TAB_ODBC) { int plgtyp; - bool w = false; // Wide character type + bool w= false; // Wide character type // typ must be PLG type, not SQL type - if (!(plgtyp = TranslateSQLType(typ, dec, prec, v, w))) { + if (!(plgtyp= TranslateSQLType(typ, dec, prec, v, w))) { if (GetTypeConv() == TPC_SKIP) { // Skip this column sprintf(g->Message, "Column %s skipped (unsupported type %d)", @@ -6114,12 +6161,12 @@ static int connect_assisted_discovery(handlerton *, THD* thd, continue; } else { sprintf(g->Message, "Unsupported SQL type %d", typ); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif type_conv } else - typ = plgtyp; + typ= plgtyp; switch (typ) { case TYPE_STRING: @@ -6134,10 +6181,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, prec += (dec + 2); // To be safe break; case TYPE_DECIM: - prec = len; + prec= len; break; default: - dec = 0; + dec= 0; } // endswitch typ } else @@ -6147,7 +6194,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, int plgtyp; // typ must be PLG type, not SQL type - if (!(plgtyp = TranslateJDBCType(typ, tn, dec, prec, v))) { + if (!(plgtyp= TranslateJDBCType(typ, tn, dec, prec, v))) { if (GetTypeConv() == TPC_SKIP) { // Skip this column sprintf(g->Message, "Column %s skipped (unsupported type %d)", @@ -6156,12 +6203,12 @@ static int connect_assisted_discovery(handlerton *, THD* thd, continue; } else { sprintf(g->Message, "Unsupported SQL type %d", typ); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif type_conv } else - typ = plgtyp; + typ= plgtyp; switch (typ) { case TYPE_DOUBLE: @@ -6170,43 +6217,43 @@ static int connect_assisted_discovery(handlerton *, THD* thd, prec += (dec + 2); // To be safe break; default: - dec = 0; + dec= 0; } // endswitch typ } else #endif // ODBC_SUPPORT // Make the arguments as required by add_fields if (typ == TYPE_DOUBLE) - prec = len; + prec= len; if (typ == TYPE_DATE) - prec = 0; + prec= 0; // Now add the field if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra, fmt, 0, dbf, v)) - rc = HA_ERR_OUT_OF_MEM; + rc= HA_ERR_OUT_OF_MEM; } // endfor i } // endif fnc if (!rc) - rc = init_table_share(thd, table_s, create_info, &sql); + rc= init_table_share(thd, table_s, create_info, &sql); //g->jump_level--; //PopUser(xp); //return rc; } else { - rc = HA_ERR_UNSUPPORTED; + rc= HA_ERR_UNSUPPORTED; } // endif ok } catch (int n) { if (trace(1)) htrc("Exception %d: %s\n", n, g->Message); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; } catch (const char *msg) { strcpy(g->Message, msg); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; } // end catch err: @@ -6274,9 +6321,9 @@ int ha_connect::create(const char *name, TABLE *table_arg, TABTYPE type; TABLE *st= table; // Probably unuseful THD *thd= ha_thd(); - LEX_STRING cnc = table_arg->s->connect_string; -#ifdef WITH_PARTITION_STORAGE_ENGINE - partition_info *part_info= table_arg->part_info; + LEX_STRING cnc= table_arg->s->connect_string; +#if defined(WITH_PARTITION_STORAGE_ENGINE) + partition_info *part_info= table_arg->part_info; #else // !WITH_PARTITION_STORAGE_ENGINE #define part_info 0 #endif // !WITH_PARTITION_STORAGE_ENGINE @@ -6401,7 +6448,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, host= mydef->GetHostname(); if (mydef->GetTabschema()) - db = mydef->GetTabschema(); + db= mydef->GetTabschema(); if (mydef->GetTabname()) tab= mydef->GetTabname(); @@ -6484,7 +6531,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, } // endif type JSON if (type == TAB_CSV) { - const char *sep = options->separator; + const char *sep= options->separator; if (sep && strlen(sep) > 1) { sprintf(g->Message, "Invalid separator %s", sep); @@ -6685,15 +6732,15 @@ int ha_connect::create(const char *name, TABLE *table_arg, if (options->zipped) { // Check whether the zip entry must be made from a file - PCSZ fn = GetListOption(g, "Load", options->oplist, NULL); + PCSZ fn= GetListOption(g, "Load", options->oplist, NULL); if (fn) { char zbuf[_MAX_PATH], buf[_MAX_PATH], dbpath[_MAX_PATH]; - PCSZ entry = GetListOption(g, "Entry", options->oplist, NULL); - PCSZ a = GetListOption(g, "Append", options->oplist, "NO"); - bool append = *a == '1' || *a == 'Y' || *a == 'y' || !stricmp(a, "ON"); - PCSZ m = GetListOption(g, "Mulentries", options->oplist, "NO"); - bool mul = *m == '1' || *m == 'Y' || *m == 'y' || !stricmp(m, "ON"); + PCSZ entry= GetListOption(g, "Entry", options->oplist, NULL); + PCSZ a= GetListOption(g, "Append", options->oplist, "NO"); + bool append= *a == '1' || *a == 'Y' || *a == 'y' || !stricmp(a, "ON"); + PCSZ m= GetListOption(g, "Mulentries", options->oplist, "NO"); + bool mul= *m == '1' || *m == 'Y' || *m == 'y' || !stricmp(m, "ON"); if (!entry && !mul) { my_message(ER_UNKNOWN_ERROR, "Missing entry name", MYF(0)); @@ -6761,7 +6808,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, if (SetDataPath(g, table_arg->s->db.str)) { my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; } else if (cat) { if (part_info) strncpy(partname, @@ -7103,7 +7150,7 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table, /* ALTER TABLE tbl_name CONVERT TO CHARACTER SET .. and - ALTER TABLE table_name DEFAULT CHARSET = .. most likely + ALTER TABLE table_name DEFAULT CHARSET= .. most likely change column charsets and so not supported in-place through old API. @@ -7335,7 +7382,7 @@ maria_declare_plugin(connect) 0x0106, /* version number (1.06) */ NULL, /* status variables */ connect_system_variables, /* system variables */ - "1.06.0009", /* string version */ + "1.06.0010", /* string version */ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ } maria_declare_plugin_end; diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h index ea495557fcf..9a12ef94431 100644 --- a/storage/connect/ha_connect.h +++ b/storage/connect/ha_connect.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file ha_connect.h Author Olivier Bertrand @@ -32,6 +32,10 @@ /****************************************************************************/ #include "mycat.h" +#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) +bool MongoEnabled(void); +#endif // JAVA_SUPPORT || CMGO_SUPPORT + /****************************************************************************/ /* Structures used to pass info between CONNECT and ha_connect. */ /****************************************************************************/ diff --git a/storage/connect/inihandl.cpp b/storage/connect/inihandl.cpp index 8a911cb05c0..8e79aeac7ef 100644 --- a/storage/connect/inihandl.cpp +++ b/storage/connect/inihandl.cpp @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #include "my_global.h" @@ -194,7 +194,7 @@ static void PROFILE_Save( FILE *file, PROFILESECTION *section ) } for (key = section->key; key; key = key->next) - if (key->name[0]) { + if (key->name && key->name[0]) { fprintf(file, "%s", SVP(key->name)); if (key->value) diff --git a/storage/connect/jmgoconn.cpp b/storage/connect/jmgoconn.cpp index bd1ddadd80d..c80800bd897 100644 --- a/storage/connect/jmgoconn.cpp +++ b/storage/connect/jmgoconn.cpp @@ -272,7 +272,7 @@ bool JMgoConn::MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options, if (MakeSelector(g, filp, s)) { strcpy(g->Message, "Failed making selector"); - return NULL; + return true; } else s->Append('}'); @@ -340,7 +340,7 @@ bool JMgoConn::MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options, if (MakeSelector(g, filp, s)) { strcpy(g->Message, "Failed making selector"); - return NULL; + return true; } // endif Selector tdbp->SetFilter(NULL); // Not needed anymore @@ -813,4 +813,3 @@ PSZ JMgoConn::GetColumnValue(PSZ path) return fld; } // end of GetColumnValue - diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index df9c7200416..dad86d51040 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -1,6 +1,6 @@ /****************** jsonudf C++ Program Source Code File (.CPP) ******************/ -/* PROGRAM NAME: jsonudf Version 1.7 */ -/* (C) Copyright to the author Olivier BERTRAND 2015-2018 */ +/* PROGRAM NAME: jsonudf Version 1.8 */ +/* (C) Copyright to the author Olivier BERTRAND 2015-2019 */ /* This program are the JSON User Defined Functions . */ /*********************************************************************************/ @@ -1686,7 +1686,7 @@ static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i) } // endif *s if (n < 1) - return "Key"; + return (PCSZ) "Key"; if (!b) { if ((p = (PSZ)PlgDBSubAlloc(g, NULL, n + 1))) { @@ -1703,7 +1703,7 @@ static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i) return s; } // endif count - return "Key"; + return (PCSZ) "Key"; } // end of MakeKey /*********************************************************************************/ diff --git a/storage/connect/libdoc.cpp b/storage/connect/libdoc.cpp index 9b30b315441..58b0267bd6d 100644 --- a/storage/connect/libdoc.cpp +++ b/storage/connect/libdoc.cpp @@ -1035,7 +1035,7 @@ PXNODE XML2NODE::AddChildNode(PGLOBAL g, PCSZ name, PXNODE np) // If name has the format m[n] only m is taken as node name if ((p = strchr(pn, '['))) - p = BufAlloc(g, pn, p - pn); + p = BufAlloc(g, pn, int(p - pn)); else p = pn; diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index 5aef6d9c660..5c67b92ec36 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -11,14 +11,14 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /*************** Mycat CC Program Source Code File (.CC) ***************/ /* PROGRAM NAME: MYCAT */ /* ------------- */ -/* Version 1.6 */ +/* Version 1.7 */ /* */ -/* Author: Olivier Bertrand 2012 - 2018 */ +/* Author: Olivier Bertrand 2012 - 2019 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -93,6 +93,9 @@ #if defined(ZIP_SUPPORT) #include "tabzip.h" #endif // ZIP_SUPPORT +#if defined(REST_SUPPORT) +#include "tabrest.h" +#endif // REST_SUPPORT #include "mycat.h" /***********************************************************************/ @@ -160,7 +163,7 @@ TABTYPE GetTypeID(const char *type) #if defined(ZIP_SUPPORT) : (!stricmp(type, "ZIP")) ? TAB_ZIP #endif - : (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY; + : (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY; } // end of GetTypeID /***********************************************************************/ @@ -181,6 +184,7 @@ bool IsFileType(TABTYPE type) case TAB_INI: case TAB_VEC: case TAB_JSON: + case TAB_REST: // case TAB_ZIP: isfile= true; break; @@ -488,8 +492,8 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep, printf("GetTableDesc: name=%s am=%s\n", tablep->GetName(), SVP(type)); // If not specified get the type of this table - if (!type) - type= Hc->GetStringOption("Type","*"); + //if (!type) + // type= Hc->GetStringOption("Type","*"); return MakeTableDesc(g, tablep, type); } // end of GetTableDesc @@ -501,8 +505,8 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep, PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am) { TABTYPE tc; - LPCSTR name = (PSZ)PlugDup(g, tablep->GetName()); - LPCSTR schema = (PSZ)PlugDup(g, tablep->GetSchema()); + LPCSTR name= (PSZ)PlugDup(g, tablep->GetName()); + LPCSTR schema= (PSZ)PlugDup(g, tablep->GetSchema()); PRELDEF tdp= NULL; if (trace(1)) @@ -512,7 +516,11 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am) /*********************************************************************/ /* Get a unique enum identifier for types. */ /*********************************************************************/ - tc= GetTypeID(am); + if (!am) { + tc = Hc->GetRealType(); + am = Hc->GetStringOption("Type", "*"); + } else + tc = GetTypeID(am); switch (tc) { case TAB_FIX: @@ -549,8 +557,11 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am) case TAB_VIR: tdp= new(g) VIRDEF; break; case TAB_JSON: tdp= new(g) JSONDEF; break; #if defined(ZIP_SUPPORT) - case TAB_ZIP: tdp = new(g) ZIPDEF; break; + case TAB_ZIP: tdp= new(g) ZIPDEF; break; #endif // ZIP_SUPPORT +#if defined(REST_SUPPORT) + case TAB_REST: tdp= new(g) RESTDEF; break; +#endif // REST_SUPPORT #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) case TAB_MONGO: if (MongoEnabled()) { diff --git a/storage/connect/mycat.h b/storage/connect/mycat.h index f0f889722dd..b306d4acbe0 100644 --- a/storage/connect/mycat.h +++ b/storage/connect/mycat.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /**************** MYCAT H Declares Source Code File (.H) ***************/ /* Name: MYCAT.H Version 2.3 */ @@ -50,7 +50,9 @@ struct ha_table_option_struct { const char *filter; const char *oplist; const char *data_charset; - ulonglong lrecl; + const char *http; + const char *uri; + ulonglong lrecl; ulonglong elements; //ulonglong estimate; ulonglong multiple; diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index 5446e0d2a07..14b8549beb0 100644 --- a/storage/connect/plgdbsem.h +++ b/storage/connect/plgdbsem.h @@ -82,7 +82,8 @@ enum TABTYPE {TAB_UNDEF = 0, /* Table of undefined type */ TAB_JDBC = 26, /* Table accessed via JDBC */ TAB_ZIP = 27, /* ZIP file info table */ TAB_MONGO = 28, /* Table retrieved from MongoDB */ - TAB_NIY = 30}; /* Table not implemented yet */ + TAB_REST = 29, /* Table retrieved from Rest query */ + TAB_NIY = 30}; /* Table not implemented yet */ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */ TYPE_AM_ROWID = 1, /* ROWID type (special column) */ @@ -400,6 +401,7 @@ typedef class VCTDEF *PVCTDEF; typedef class PIVOTDEF *PPIVOTDEF; typedef class DOMDEF *PDOMDEF; typedef class DIRDEF *PDIRDEF; +typedef class RESTDEF *PRESTDEF; typedef class OEMDEF *POEMDEF; typedef class COLCRT *PCOLCRT; typedef class COLDEF *PCOLDEF; diff --git a/storage/connect/restget.cpp b/storage/connect/restget.cpp new file mode 100644 index 00000000000..955e5f97fbc --- /dev/null +++ b/storage/connect/restget.cpp @@ -0,0 +1,87 @@ +/************* Restget C++ Program Source Code File (.CPP) *************/ +/* Adapted from the sample program of the Casablanca tutorial. */ +/* Copyright Olivier Bertrand 2019. */ +/***********************************************************************/ +#include +#include +#if defined(MARIADB) +#include +#else +#include "mini_global.h" +#endif + +using namespace utility::conversions; // String conversions utilities +using namespace web; // Common features like URIs. +using namespace web::http; // Common HTTP functionality +using namespace web::http::client; // HTTP client features +using namespace concurrency::streams; // Asynchronous streams + +#include "global.h" + + +/***********************************************************************/ +/* Make a local copy of the requested file. */ +/***********************************************************************/ +int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn) +{ + int rc= 0; + auto fileStream= std::make_shared(); + + if (!http || !fn) { + strcpy(g->Message, "Missing http or filename"); + return 2; + } // endif + + //std::string sfn(fn); + //auto wfn= to_string_t(sfn); + //rc= 0; + + // Open stream to output file. + pplx::task requestTask= + fstream::open_ostream(to_string_t(fn)) + .then([=](ostream outFile) { + *fileStream= outFile; + + // Create http_client to send the request. + http_client client(to_string_t(http)); + + if (uri) + { + // Build request URI and start the request. + uri_builder builder(to_string_t(uri)); + return client.request(methods::GET, builder.to_string()); + } + else + return client.request(methods::GET); + }) + + // Handle response headers arriving. + .then([=](http_response response) { +#if defined(DEVELOPMENT) + fprintf(stderr, "Received response status code:%u\n", + response.status_code()); +#endif // DEVELOPMENT + + // Write response body into the file. + return response.body().read_to_end(fileStream->streambuf()); + }) + + // Close the file stream. + .then([=](size_t) { return fileStream->close(); }); + + // Wait for all the outstanding I/O to complete and handle any exceptions + try + { + requestTask.wait(); + } + catch (const std::exception &e) + { +#if defined(DEVELOPMENT) + fprintf(stderr, "Error exception: %s\n", e.what()); +#endif // DEVELOPMENT + sprintf(g->Message, "Error exception: %s", e.what()); + rc= 1; + } // end try/catch + + return rc; +} // end of restGetFile \ No newline at end of file diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index 789daff6fcd..06b6b3a9730 100644 --- a/storage/connect/tabjdbc.cpp +++ b/storage/connect/tabjdbc.cpp @@ -641,7 +641,9 @@ bool TDBJDBC::OpenDB(PGLOBAL g) Cnp->InitValue(g); if ((n = Jcp->GetResultSize(Query->GetStr(), Cnp)) < 0) { - sprintf(g->Message, "Cannot get result size rc=%d", n); + char* msg = PlugDup(g, g->Message); + + sprintf(g->Message, "Get result size: %s (rc=%d)", msg, n); return true; } else if (n) { Jcp->m_Rows = n; diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index afab52aa282..a8f76900cb4 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -572,7 +572,7 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Sep = *GetStringCatInfo(g, "Separator", "."); Accept = GetBoolCatInfo("Accept", false); - // Don't use url as uri when called from REST OEM module + // Don't use url as MONGO uri when called from REST if (stricmp(am, "REST") && (Uri = GetStringCatInfo(g, "Connect", NULL))) { #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) Collname = GetStringCatInfo(g, "Name", diff --git a/storage/connect/tabrest.cpp b/storage/connect/tabrest.cpp new file mode 100644 index 00000000000..e800411a36d --- /dev/null +++ b/storage/connect/tabrest.cpp @@ -0,0 +1,133 @@ +/*************** Rest C++ Program Source Code File (.CPP) **************/ +/* PROGRAM NAME: Rest Version 1.3 */ +/* (C) Copyright to the author Olivier BERTRAND 2018 - 2019 */ +/* This program is the REST OEM (Web API support) module definition. */ +/***********************************************************************/ + +/***********************************************************************/ +/* Definitions needed by the included files. */ +/***********************************************************************/ +#include // All MariaDB stuff + +/***********************************************************************/ +/* Include application header files: */ +/* global.h is header containing all global declarations. */ +/* plgdbsem.h is header containing the DB application declarations. */ +/* (x)table.h is header containing the TDBASE declarations. */ +/***********************************************************************/ +#include "global.h" +#include "plgdbsem.h" +#include "xtable.h" +#include "filamtxt.h" +#include "plgxml.h" +#include "tabdos.h" +#include "tabfmt.h" +#include "tabjson.h" +#include "tabrest.h" +#include "tabxml.h" + +/***********************************************************************/ +/* Get the file from the Web. */ +/***********************************************************************/ +int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn); + +#if defined(__WIN__) +static PCSZ slash= "\\"; +#else // !__WIN__ +static PCSZ slash= "/"; +#define stricmp strcasecmp +#endif // !__WIN__ + +/***********************************************************************/ +/* Return the columns definition to MariaDB. */ +/***********************************************************************/ +PQRYRES RESTColumns(PGLOBAL g, PTOS tp, char *tab, char *db, bool info) +{ + PQRYRES qrp= NULL; + char filename[_MAX_PATH]; + PCSZ http, uri, fn, ftype; + + http= GetStringTableOption(g, tp, "Http", NULL); + uri= GetStringTableOption(g, tp, "Uri", NULL); + fn= GetStringTableOption(g, tp, "Filename", "rest.json"); + ftype = GetStringTableOption(g, tp, "Type", "JSON"); + + // We used the file name relative to recorded datapath + strcat(strcat(strcat(strcpy(filename, "."), slash), db), slash); + strncat(filename, fn, _MAX_PATH); + + // Retrieve the file from the web and copy it locally + if (http && restGetFile(g, http, uri, filename)) { + // sprintf(g->Message, "Failed to get file at %s", http); + } else if (!stricmp(ftype, "XML")) + qrp= XMLColumns(g, db, tab, tp, info); + else if (!stricmp(ftype, "JSON")) + qrp= JSONColumns(g, db, NULL, tp, info); + else if (!stricmp(ftype, "CSV")) + qrp= CSVColumns(g, NULL, tp, info); + else + sprintf(g->Message, "Usupported file type %s", ftype); + + return qrp; +} // end of RESTColumns + +/* -------------------------- Class RESTDEF -------------------------- */ + +/***********************************************************************/ +/* DefineAM: define specific AM block values. */ +/***********************************************************************/ +bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) +{ + char filename[_MAX_PATH]; + TABTYPE type= GetTypeID(am); + + switch (type) { + case TAB_JSON: + case TAB_XML: + case TAB_CSV: + break; + default: + sprintf(g->Message, "Unsupported REST table type %s", am); + return true; + } // endswitch type + + Http= GetStringCatInfo(g, "Http", NULL); + Uri= GetStringCatInfo(g, "Uri", NULL); + Fn= GetStringCatInfo(g, "Filename", "rest.json"); + + // We used the file name relative to recorded datapath + PlugSetPath(filename, Fn, GetPath()); + + // Retrieve the file from the web and copy it locally + if (Http && restGetFile(g, Http, Uri, filename)) {} + else if (type == TAB_JSON) + Tdp= new (g) JSONDEF; + else if (type == TAB_XML) + Tdp= new (g) XMLDEF; + else if (type == TAB_CSV) + Tdp= new (g) CSVDEF; + else + sprintf(g->Message, "Unsupported REST table type %s", am); + + // Do make the table/view definition + if (Tdp && Tdp->Define(g, Cat, Name, Schema, "REST")) + Tdp= NULL; // Error occured + + // Return true in case of error + return (Tdp == NULL); +} // end of DefineAM + +/***********************************************************************/ +/* GetTable: makes a new Table Description Block. */ +/***********************************************************************/ +PTDB RESTDEF::GetTable(PGLOBAL g, MODE m) +{ + if (m != MODE_READ && m != MODE_READX) { + strcpy(g->Message, "REST tables are currently read only"); + return NULL; + } // endif m + + return Tdp->GetTable(g, m); // Leave file type do the job +} // end of GetTable + +/* ---------------------- End of Class RESTDEF ----------------------- */ diff --git a/storage/connect/tabrest.h b/storage/connect/tabrest.h new file mode 100644 index 00000000000..1725f256079 --- /dev/null +++ b/storage/connect/tabrest.h @@ -0,0 +1,29 @@ +/*************** TabRest H Declares Source Code File (.H) **************/ +/* Name: tabrest.h Version 1.0 */ +/* (C) Copyright to the author Olivier BERTRAND 2019 */ +/* This file contains the common tabrest classes declares. */ +/***********************************************************************/ +#pragma once + +/***********************************************************************/ +/* Restest table. */ +/***********************************************************************/ +class RESTDEF : public TABDEF { /* Table description */ +public: + // Constructor + RESTDEF(void) { Tdp = NULL; Http = Uri = Fn = NULL; } + + // Implementation + virtual const char *GetType(void) { return "REST"; } + + // Methods + virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff); + virtual PTDB GetTable(PGLOBAL g, MODE m); + +protected: + // Members + PRELDEF Tdp; + PCSZ Http; /* Web connection HTTP */ + PCSZ Uri; /* Web connection URI */ + PCSZ Fn; /* The intermediate file name */ +}; // end of class RESTDEF diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index e194568ccf8..1150824464f 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -232,7 +232,7 @@ bool TDBTBL::InitTableList(PGLOBAL g) { int n; uint sln; - char *scs; + const char *scs; PTABLE tp, tabp; PCOL colp; PTBLDEF tdp = (PTBLDEF)To_Def; @@ -281,7 +281,7 @@ bool TDBTBL::InitTableList(PGLOBAL g) } // endfor tp - hc->get_table()->s->connect_string.str = scs; + hc->get_table()->s->connect_string.str = (char*)scs; hc->get_table()->s->connect_string.length = sln; //NumTables = n; diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp index d808bd5ecd4..19490d350e8 100644 --- a/storage/connect/tabxml.cpp +++ b/storage/connect/tabxml.cpp @@ -1880,7 +1880,7 @@ void XMULCOL::ReadColumn(PGLOBAL g) if (N > Tdbp->Limit) { N = Tdbp->Limit; - sprintf(g->Message, "Mutiple values limited to %d", Tdbp->Limit); + sprintf(g->Message, "Multiple values limited to %d", Tdbp->Limit); PushWarning(g, Tdbp); } // endif N diff --git a/storage/connect/user_connect.cc b/storage/connect/user_connect.cc index d366e0222df..c25443ef7ef 100644 --- a/storage/connect/user_connect.cc +++ b/storage/connect/user_connect.cc @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file user_connect.cc diff --git a/storage/connect/user_connect.h b/storage/connect/user_connect.h index 983d9adc478..2670c5bcebc 100644 --- a/storage/connect/user_connect.h +++ b/storage/connect/user_connect.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file user_connect.h From d302cb3534f4b4e8a5ae6e293b6ef2c2c9180862 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 31 Jul 2019 11:17:59 +0200 Subject: [PATCH 02/11] Typo --- .../connect/mysql-test/connect/r/jdbc_postgresql.result | 2 +- storage/connect/mysql-test/connect/r/xml2_mult.result | 8 ++++---- storage/connect/mysql-test/connect/r/xml_mult.result | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/storage/connect/mysql-test/connect/r/jdbc_postgresql.result b/storage/connect/mysql-test/connect/r/jdbc_postgresql.result index bec1dc8725b..07cc3c465ea 100644 --- a/storage/connect/mysql-test/connect/r/jdbc_postgresql.result +++ b/storage/connect/mysql-test/connect/r/jdbc_postgresql.result @@ -1,4 +1,4 @@ -SET GLOBAL connect_class_path='C:/MariaDB-10.0/MariaDB/storage/connect/mysql-test/connect/std_data/JavaWrappers.jar;C:/Jconnectors/postgresql-42.2.1.jar'; +SET GLOBAL connect_class_path='C:/MariaDB-10.2/MariaDB/storage/connect/mysql-test/connect/std_data/JavaWrappers.jar;C:/Jconnectors/postgresql-42.2.1.jar'; CREATE TABLE t2 ( command varchar(128) not null, number int(5) not null flag=1, diff --git a/storage/connect/mysql-test/connect/r/xml2_mult.result b/storage/connect/mysql-test/connect/r/xml2_mult.result index a9592e986c0..87d1118edd5 100644 --- a/storage/connect/mysql-test/connect/r/xml2_mult.result +++ b/storage/connect/mysql-test/connect/r/xml2_mult.result @@ -51,14 +51,14 @@ WEB XQuery Kick Start en Per Bothner 2003 49.99 WEB XQuery Kick Start en Kurt Cagle 2003 49.99 WEB Learning XML en Erik T. Ray 2003 39.95 Warnings: -Warning 1105 Mutiple values limited to 3 +Warning 1105 Multiple values limited to 3 # One line lost because the where clause is applied only on the first 3 rows SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%'; category title author price CHILDREN Harry Potter J K. Rowling 29.99 WEB XQuery Kick Start James McGovern 49.99 Warnings: -Warning 1105 Mutiple values limited to 3 +Warning 1105 Multiple values limited to 3 # # Testing concatenated values # @@ -91,12 +91,12 @@ CHILDREN Harry Potter en J K. Rowling 2005 29.99 WEB XQuery Kick Start en James McGovern, Per Bothner, Kurt Cagle, James Linn 2003 49.99 WEB Learning XML en Erik T. Ray 2003 39.95 Warnings: -Warning 1105 Mutiple values limited to 4 +Warning 1105 Multiple values limited to 4 # The where clause is applied on the concatenated column result SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%'; category title author price CHILDREN Harry Potter J K. Rowling 29.99 WEB XQuery Kick Start James McGovern, Per Bothner, Kurt Cagle, James Linn 49.99 Warnings: -Warning 1105 Mutiple values limited to 4 +Warning 1105 Multiple values limited to 4 DROP TABLE bookstore; diff --git a/storage/connect/mysql-test/connect/r/xml_mult.result b/storage/connect/mysql-test/connect/r/xml_mult.result index d89debadfab..9922b40060c 100644 --- a/storage/connect/mysql-test/connect/r/xml_mult.result +++ b/storage/connect/mysql-test/connect/r/xml_mult.result @@ -49,14 +49,14 @@ WEB XQuery Kick Start en Per Bothner 2003 49.99 WEB XQuery Kick Start en Kurt Cagle 2003 49.99 WEB Learning XML en Erik T. Ray 2003 39.95 Warnings: -Warning 1105 Mutiple values limited to 3 +Warning 1105 Multiple values limited to 3 # One line lost because the where clause is applied only on the first 3 rows SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%'; category title author price CHILDREN Harry Potter J K. Rowling 29.99 WEB XQuery Kick Start James McGovern 49.99 Warnings: -Warning 1105 Mutiple values limited to 3 +Warning 1105 Multiple values limited to 3 # # Testing concatenated values # @@ -89,12 +89,12 @@ CHILDREN Harry Potter en J K. Rowling 2005 29.99 WEB XQuery Kick Start en James McGovern, Per Bothner, Kurt Cagle, James Linn 2003 49.99 WEB Learning XML en Erik T. Ray 2003 39.95 Warnings: -Warning 1105 Mutiple values limited to 4 +Warning 1105 Multiple values limited to 4 # The where clause is applied on the concatenated column result SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%'; category title author price CHILDREN Harry Potter J K. Rowling 29.99 WEB XQuery Kick Start James McGovern, Per Bothner, Kurt Cagle, James Linn 49.99 Warnings: -Warning 1105 Mutiple values limited to 4 +Warning 1105 Multiple values limited to 4 DROP TABLE bookstore; From 4d93c7f3b0bfc59da369702c2eca725f1e362305 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 17 Aug 2019 16:58:58 +0200 Subject: [PATCH 03/11] In CONNECT version 1.6.10 NOSQL facility is enhanced by a new way to retrieve NOSQL data. In addition to files and Mongo collections, JSON as well as XML and CSV data can be retrieved from the net as answers from REST queries. Because it uses and external package (cpprestsdk) this is currently available only to MariaDB servers compiled from source. -- Add compile flags needed on Windows /MD or /MDd (debug) -- Also include some changes needed on Linux modified: storage/connect/CMakeLists.txt - Add the xtrc tracing function modified: storage/connect/global.h modified: storage/connect/plugutil.cpp - Modify tracing to use xtrc and some typo modified: storage/connect/array.cpp modified: storage/connect/block.h modified: storage/connect/restget.cpp - Fix compilation error when ZIP is not supported modified: storage/connect/ha_connect.cc modified: storage/connect/tabfmt.cpp - Add some tracing + typo modified: storage/connect/mycat.cc modified: storage/connect/tabjson.cpp - Add conditional code based on MARIADB This to be able to use the same code in CONNECT and EOM modules modified: storage/connect/osutil.h modified: storage/connect/tabrest.cpp - Replace PlugSetPath by some concat (crashed on Fedora) + typo modified: storage/connect/reldef.cpp - Try to fix test failures modified: zlib/CMakeLists.txt --- storage/connect/CMakeLists.txt | 17 +- storage/connect/array.cpp | 127 +-- storage/connect/block.h | 4 +- storage/connect/global.h | 1 + storage/connect/ha_connect.cc | 4 + storage/connect/mini-global.h | 33 + storage/connect/mycat.cc | 161 +-- storage/connect/osutil.h | 4 + storage/connect/plugutil.cpp | 38 +- storage/connect/reldef.cpp | 297 +++--- storage/connect/rest.def | 4 + storage/connect/rest.h | 33 + storage/connect/restget.cpp | 94 +- storage/connect/tabfmt.cpp | 2 + storage/connect/tabjson.cpp | 1709 ++++++++++++++++---------------- storage/connect/tabrest.cpp | 155 ++- zlib/CMakeLists.txt | 4 +- 17 files changed, 1427 insertions(+), 1260 deletions(-) create mode 100644 storage/connect/mini-global.h create mode 100644 storage/connect/rest.def create mode 100644 storage/connect/rest.h diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 8fc7cf695e7..6fd3b5e3018 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -68,6 +68,10 @@ ELSE(NOT UNIX) tabwmi.cpp tabwmi.h tabmac.cpp tabmac.h macutil.cpp macutil.h) # Add exception handling to the CONNECT project) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd") + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD") + SET(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MD") SET(IPHLPAPI_LIBRARY iphlpapi.lib) IF(MSVC AND (CMAKE_CXX_COMPILER_ID MATCHES Clang)) # Connect does not work with clang-cl @@ -315,6 +319,12 @@ IF(CONNECT_WITH_REST) FIND_PACKAGE(cpprestsdk) IF (cpprestsdk_FOUND) MESSAGE(STATUS "=====> cpprestsdk found") + IF(UNIX) +# INCLUDE_DIRECTORIES(${CPPRESTSDK_INCLUDE_DIR}) +# Edit next line to set the path to libcpprest.so + SET(REST_LIBRARY -L/usr/lib64 -lcpprest) + MESSAGE (STATUS ${REST_LIBRARY}) + ENDIF(UNIX) SET(CONNECT_SOURCES ${CONNECT_SOURCES} tabrest.cpp restget.cpp tabrest.h) add_definitions(-DREST_SUPPORT) ELSE(NOT cpprestsdk_FOUND) @@ -341,7 +351,7 @@ MYSQL_ADD_PLUGIN(connect ${CONNECT_SOURCES} COMPONENT connect-engine RECOMPILE_FOR_EMBEDDED LINK_LIBRARIES ${ZLIB_LIBRARY} ${XML_LIBRARY} ${ICONV_LIBRARY} - ${ODBC_LIBRARY} ${JDBC_LIBRARY} ${MONGOC_LIBRARY} ${IPHLPAPI_LIBRARY}) + ${ODBC_LIBRARY} ${JDBC_LIBRARY} ${MONGOC_LIBRARY} ${IPHLPAPI_LIBRARY} ${REST_LIBRARY}) IF(NOT TARGET connect) RETURN() @@ -349,8 +359,8 @@ ENDIF() IF(WIN32) IF (libmongoc-1.0_FOUND) - SET_TARGET_PROPERTIES(connect PROPERTIES LINK_FLAGS - "/DELAYLOAD:libbson-1.0.dll /DELAYLOAD:libmongoc-1.0.dll") + SET_TARGET_PROPERTIES(connect PROPERTIES LINK_FLAGS + "/DELAYLOAD:libbson-1.0.dll /DELAYLOAD:libmongoc-1.0.dll") ENDIF(libmongoc-1.0_FOUND) ENDIF(WIN32) @@ -377,3 +387,4 @@ IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND) ${CMAKE_CURRENT_BINARY_DIR}/JdbcInterface.jar DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine) ENDIF() + diff --git a/storage/connect/array.cpp b/storage/connect/array.cpp index cd1785b48ac..3478342a788 100644 --- a/storage/connect/array.cpp +++ b/storage/connect/array.cpp @@ -1,7 +1,7 @@ /************* Array C++ Functions Source Code File (.CPP) *************/ /* Name: ARRAY.CPP Version 2.3 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2005-2017 */ +/* (C) Copyright to the author Olivier BERTRAND 2005-2019 */ /* */ /* This file contains the XOBJECT derived class ARRAY functions. */ /* ARRAY is used for elaborate type of processing, such as sorting */ @@ -67,7 +67,7 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp); // avoid gcc warning /* MakeValueArray: Makes a value array from a value list. */ /***********************************************************************/ PARRAY MakeValueArray(PGLOBAL g, PPARM pp) - { +{ int n, valtyp = 0; size_t len = 0; PARRAY par; @@ -82,8 +82,7 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp) if ((valtyp = pp->Type) != TYPE_STRING) len = 1; - if (trace(1)) - htrc("valtyp=%d len=%d\n", valtyp, len); + xtrc(1, "valtyp=%d len=%d\n", valtyp, len); /*********************************************************************/ /* Firstly check the list and count the number of values in it. */ @@ -127,13 +126,13 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp) // Integer stored inside pp->Value par->AddValue(g, parmp->Intval); break; - } // endswitch valtyp + } // endswitch valtyp /*********************************************************************/ /* Send back resulting array. */ /*********************************************************************/ return par; - } // end of MakeValueArray +} // end of MakeValueArray /* -------------------------- Class ARRAY ---------------------------- */ @@ -151,6 +150,9 @@ ARRAY::ARRAY(PGLOBAL g, int type, int size, int length, int prec) Type = type; Xsize = -1; Len = 1; + X = 0; + Inf = 0; + Sup = 0; switch (type) { case TYPE_STRING: @@ -281,130 +283,109 @@ void ARRAY::Empty(void) /* Add a string element to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, PSZ strp) - { +{ if (Type != TYPE_STRING) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "CHAR"); return true; - } // endif Type + } // endif Type - if (trace(1)) - htrc(" adding string(%d): '%s'\n", Nval, strp); - -//Value->SetValue_psz(strp); -//Vblp->SetValue(valp, Nval++); + xtrc(1, " adding string(%d): '%s'\n", Nval, strp); Vblp->SetValue(strp, Nval++); return false; - } // end of AddValue +} // end of AddValue /***********************************************************************/ /* Add a char pointer element to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, void *p) - { +{ if (Type != TYPE_PCHAR) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "PCHAR"); return true; - } // endif Type - - if (trace(1)) - htrc(" adding pointer(%d): %p\n", Nval, p); + } // endif Type + xtrc(1, " adding pointer(%d): %p\n", Nval, p); Vblp->SetValue((PSZ)p, Nval++); return false; - } // end of AddValue +} // end of AddValue /***********************************************************************/ /* Add a short integer element to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, short n) - { +{ if (Type != TYPE_SHORT) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "SHORT"); return true; - } // endif Type + } // endif Type - if (trace(1)) - htrc(" adding SHORT(%d): %hd\n", Nval, n); - -//Value->SetValue(n); -//Vblp->SetValue(valp, Nval++); + xtrc(1, " adding SHORT(%d): %hd\n", Nval, n); Vblp->SetValue(n, Nval++); return false; - } // end of AddValue +} // end of AddValue /***********************************************************************/ /* Add an integer element to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, int n) - { +{ if (Type != TYPE_INT) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "INTEGER"); return true; - } // endif Type + } // endif Type - if (trace(1)) - htrc(" adding int(%d): %d\n", Nval, n); - -//Value->SetValue(n); -//Vblp->SetValue(valp, Nval++); + xtrc(1, " adding int(%d): %d\n", Nval, n); Vblp->SetValue(n, Nval++); return false; - } // end of AddValue +} // end of AddValue /***********************************************************************/ /* Add a double float element to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, double d) - { +{ if (Type != TYPE_DOUBLE) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "DOUBLE"); return true; - } // endif Type - - if (trace(1)) - htrc(" adding float(%d): %lf\n", Nval, d); + } // endif Type + xtrc(1, " adding float(%d): %lf\n", Nval, d); Value->SetValue(d); Vblp->SetValue(Value, Nval++); return false; - } // end of AddValue +} // end of AddValue /***********************************************************************/ /* Add the value of a XOBJECT block to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, PXOB xp) - { - if (Type != xp->GetResultType()) { - sprintf(g->Message, MSG(ADD_BAD_TYPE), - GetTypeName(xp->GetResultType()), GetTypeName(Type)); - return true; - } // endif Type +{ + if (Type != xp->GetResultType()) { + sprintf(g->Message, MSG(ADD_BAD_TYPE), + GetTypeName(xp->GetResultType()), GetTypeName(Type)); + return true; + } // endif Type - if (trace(1)) - htrc(" adding (%d) from xp=%p\n", Nval, xp); - -//AddValue(xp->GetValue()); - Vblp->SetValue(xp->GetValue(), Nval++); - return false; - } // end of AddValue + xtrc(1, " adding (%d) from xp=%p\n", Nval, xp); + Vblp->SetValue(xp->GetValue(), Nval++); + return false; +} // end of AddValue /***********************************************************************/ /* Add a value to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, PVAL vp) - { +{ if (Type != vp->GetType()) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(vp->GetType()), GetTypeName(Type)); return true; - } // endif Type - - if (trace(1)) - htrc(" adding (%d) from vp=%p\n", Nval, vp); + } // endif Type + xtrc(1, " adding (%d) from vp=%p\n", Nval, vp); Vblp->SetValue(vp, Nval++); return false; - } // end of AddValue +} // end of AddValue /***********************************************************************/ /* Retrieve the nth value of the array. */ @@ -973,7 +954,7 @@ int ARRAY::BlockTest(PGLOBAL, int opc, int opm, /* MakeArrayList: Makes a value list from an SQL IN array (in work). */ /***********************************************************************/ PSZ ARRAY::MakeArrayList(PGLOBAL g) - { +{ char *p, *tp; int i; size_t z, len = 2; @@ -988,11 +969,9 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g) Value->SetValue_pvblk(Vblp, i); Value->Prints(g, tp, z); len += strlen(tp); - } // enfor i - - if (trace(1)) - htrc("Arraylist: len=%d\n", len); + } // enfor i + xtrc(1, "Arraylist: len=%d\n", len); p = (char *)PlugSubAlloc(g, NULL, len); strcpy(p, "("); @@ -1001,19 +980,17 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g) Value->Prints(g, tp, z); strcat(p, tp); strcat(p, (++i == Nval) ? ")" : ","); - } // enfor i - - if (trace(1)) - htrc("Arraylist: newlen=%d\n", strlen(p)); + } // enfor i + xtrc(1, "Arraylist: newlen=%d\n", strlen(p)); return p; - } // end of MakeArrayList +} // end of MakeArrayList /***********************************************************************/ /* Make file output of ARRAY contents. */ /***********************************************************************/ void ARRAY::Printf(PGLOBAL g, FILE *f, uint n) - { +{ char m[64]; int lim = MY_MIN(Nval,10); @@ -1035,19 +1012,19 @@ void ARRAY::Printf(PGLOBAL g, FILE *f, uint n) } else fprintf(f, "%sVALLST: numval=%d\n", m, Nval); - } // end of Printf +} // end of Printf /***********************************************************************/ /* Make string output of ARRAY contents. */ /***********************************************************************/ void ARRAY::Prints(PGLOBAL, char *ps, uint z) - { +{ if (z < 16) return; sprintf(ps, "ARRAY: type=%d\n", Type); // More to be implemented later - } // end of Prints +} // end of Prints /* -------------------------- Class MULAR ---------------------------- */ diff --git a/storage/connect/block.h b/storage/connect/block.h index 737c74c1293..2ca9586ee3f 100644 --- a/storage/connect/block.h +++ b/storage/connect/block.h @@ -38,9 +38,7 @@ typedef class BLOCK *PBLOCK; class DllExport BLOCK { public: void * operator new(size_t size, PGLOBAL g, void *p = NULL) { - if (trace(256)) - htrc("New BLOCK: size=%d g=%p p=%p\n", size, g, p); - + xtrc(256, "New BLOCK: size=%d g=%p p=%p\n", size, g, p); return (PlugSubAlloc(g, p, size)); } // end of new diff --git a/storage/connect/global.h b/storage/connect/global.h index dc1e149745f..fd26c87b800 100644 --- a/storage/connect/global.h +++ b/storage/connect/global.h @@ -224,6 +224,7 @@ DllExport void *PlugSubAlloc(PGLOBAL, void *, size_t); DllExport char *PlugDup(PGLOBAL g, const char *str); DllExport void *MakePtr(void *, OFFSET); DllExport void htrc(char const *fmt, ...); +DllExport void xtrc(uint, char const* fmt, ...); DllExport uint GetTraceValue(void); #if defined(__cplusplus) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index e7d1b5f0e86..be7c6548181 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -241,7 +241,9 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v); void PushWarning(PGLOBAL g, THD *thd, int level); bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, PCSZ host, PCSZ db, PCSZ tab, PCSZ src, int port); +#if defined(ZIP_SUPPORT) bool ZipLoadFile(PGLOBAL, PCSZ, PCSZ, PCSZ, bool, bool); +#endif // ZIP_SUPPORT bool ExactInfo(void); #if defined(CMGO_SUPPORT) //void mongo_init(bool); @@ -6730,6 +6732,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, if (trace(1)) htrc("xchk=%p createas=%d\n", g->Xchk, g->Createas); +#if defined(ZIP_SUPPORT) if (options->zipped) { // Check whether the zip entry must be made from a file PCSZ fn= GetListOption(g, "Load", options->oplist, NULL); @@ -6759,6 +6762,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, } // endif fn } // endif zipped +#endif // ZIP_SUPPORT // To check whether indexes have to be made or remade if (!g->Xchk) { diff --git a/storage/connect/mini-global.h b/storage/connect/mini-global.h new file mode 100644 index 00000000000..f712795827c --- /dev/null +++ b/storage/connect/mini-global.h @@ -0,0 +1,33 @@ +/***********************************************************************/ +/* Definitions needed by the included files. */ +/***********************************************************************/ +#if !defined(MY_GLOBAL_H) +#define MY_GLOBAL_H +typedef unsigned int uint; +typedef unsigned int uint32; +typedef unsigned short ushort; +typedef unsigned long ulong; +typedef unsigned long DWORD; +typedef char *LPSTR; +typedef const char *LPCSTR; +typedef int BOOL; +#if defined(_WINDOWS) +typedef void *HANDLE; +#else +typedef int HANDLE; +#endif +typedef char *PSZ; +typedef const char *PCSZ; +typedef unsigned char BYTE; +typedef unsigned char uchar; +typedef long long longlong; +typedef unsigned long long ulonglong; +typedef char my_bool; +struct charset_info_st {}; +typedef const charset_info_st CHARSET_INFO; +#define FALSE 0 +#define TRUE 1 +#define Item char +#define MY_MAX(a,b) ((a>b)?(a):(b)) +#define MY_MIN(a,b) ((aGetName(), SVP(type)); +{ + PRELDEF tdp= NULL; - // If not specified get the type of this table + if (trace(1)) + htrc("GetTableDesc: name=%s am=%s\n", tablep->GetName(), SVP(type)); + + // If not specified get the type of this table //if (!type) // type= Hc->GetStringOption("Type","*"); - return MakeTableDesc(g, tablep, type); - } // end of GetTableDesc + tdp= MakeTableDesc(g, tablep, type); + + if (trace(1)) + htrc("GetTableDesc: tdp=%p\n", tdp); + + return tdp; +} // end of GetTableDesc /***********************************************************************/ /* MakeTableDesc: make a table/view description. */ @@ -505,22 +510,22 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep, PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am) { TABTYPE tc; - LPCSTR name= (PSZ)PlugDup(g, tablep->GetName()); - LPCSTR schema= (PSZ)PlugDup(g, tablep->GetSchema()); + LPCSTR name= (PSZ)PlugDup(g, tablep->GetName()); + LPCSTR schema= (PSZ)PlugDup(g, tablep->GetSchema()); PRELDEF tdp= NULL; - if (trace(1)) - printf("MakeTableDesc: name=%s schema=%s am=%s\n", - name, SVP(schema), SVP(am)); + if (trace(1)) + htrc("MakeTableDesc: name=%s schema=%s am=%s\n", + name, SVP(schema), SVP(am)); /*********************************************************************/ /* Get a unique enum identifier for types. */ /*********************************************************************/ - if (!am) { - tc = Hc->GetRealType(); - am = Hc->GetStringOption("Type", "*"); - } else - tc = GetTypeID(am); + if (!am) { + tc= Hc->GetRealType(); + am= Hc->GetStringOption("Type","*"); + } else + tc= GetTypeID(am); switch (tc) { case TAB_FIX: @@ -535,49 +540,52 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am) case TAB_XML: tdp= new(g) XMLDEF; break; #endif // XML_SUPPORT #if defined(VCT_SUPPORT) - case TAB_VEC: tdp = new(g) VCTDEF; break; + case TAB_VEC: tdp = new(g) VCTDEF; break; #endif // VCT_SUPPORT #if defined(ODBC_SUPPORT) case TAB_ODBC: tdp= new(g) ODBCDEF; break; #endif // ODBC_SUPPORT #if defined(JAVA_SUPPORT) - case TAB_JDBC: tdp= new(g) JDBCDEF; break; + case TAB_JDBC: tdp= new(g) JDBCDEF; break; #endif // JAVA_SUPPORT #if defined(__WIN__) case TAB_MAC: tdp= new(g) MACDEF; break; case TAB_WMI: tdp= new(g) WMIDEF; break; #endif // __WIN__ case TAB_OEM: tdp= new(g) OEMDEF; break; - case TAB_TBL: tdp= new(g) TBLDEF; break; - case TAB_XCL: tdp= new(g) XCLDEF; break; - case TAB_PRX: tdp= new(g) PRXDEF; break; - case TAB_OCCUR: tdp= new(g) OCCURDEF; break; - case TAB_MYSQL: tdp= new(g) MYSQLDEF; break; + case TAB_TBL: tdp= new(g) TBLDEF; break; + case TAB_XCL: tdp= new(g) XCLDEF; break; + case TAB_PRX: tdp= new(g) PRXDEF; break; + case TAB_OCCUR: tdp= new(g) OCCURDEF; break; + case TAB_MYSQL: tdp= new(g) MYSQLDEF; break; case TAB_PIVOT: tdp= new(g) PIVOTDEF; break; case TAB_VIR: tdp= new(g) VIRDEF; break; case TAB_JSON: tdp= new(g) JSONDEF; break; #if defined(ZIP_SUPPORT) - case TAB_ZIP: tdp= new(g) ZIPDEF; break; + case TAB_ZIP: tdp = new(g) ZIPDEF; break; #endif // ZIP_SUPPORT #if defined(REST_SUPPORT) - case TAB_REST: tdp= new(g) RESTDEF; break; + case TAB_REST: tdp= new (g) RESTDEF; break; #endif // REST_SUPPORT #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) - case TAB_MONGO: - if (MongoEnabled()) { - tdp = new(g) MGODEF; - break; - } // endif enabled - // fall through + case TAB_MONGO: + if (MongoEnabled()) { + tdp = new(g) MGODEF; + break; + } // endif enabled + // fall through #endif // JAVA_SUPPORT || CMGO_SUPPORT - default: - sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name); + default: + sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name); } // endswitch // Do make the table/view definition if (tdp && tdp->Define(g, this, name, schema, am)) tdp= NULL; + if (trace(1)) + htrc("Table %s made\n", am); + return tdp; } // end of MakeTableDesc @@ -590,26 +598,29 @@ PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type) PTDB tdbp= NULL; // LPCSTR name= tablep->GetName(); - if (trace(1)) - printf("GetTableDB: name=%s\n", tablep->GetName()); + if (trace(1)) + htrc("GetTableDB: name=%s\n", tablep->GetName()); // Look for the description of the requested table tdp= GetTableDesc(g, tablep, type); if (tdp) { - if (trace(1)) - printf("tdb=%p type=%s\n", tdp, tdp->GetType()); + if (trace(1)) + htrc("tdb=%p type=%s\n", tdp, tdp->GetType()); + + if (tablep->GetSchema()) + tdp->Database = SetPath(g, tablep->GetSchema()); + + if (trace(2)) + htrc("Going to get table...\n"); - if (tablep->GetSchema()) - tdp->Database = SetPath(g, tablep->GetSchema()); - tdbp= tdp->GetTable(g, mode); - } // endif tdp + } // endif tdp if (tdbp) { - if (trace(1)) - printf("tdbp=%p name=%s amtype=%d\n", tdbp, tdbp->GetName(), - tdbp->GetAmType()); + if (trace(1)) + htrc("tdbp=%p name=%s amtype=%d\n", tdbp, tdbp->GetName(), + tdbp->GetAmType()); tablep->SetTo_Tdb(tdbp); tdbp->SetTable(tablep); tdbp->SetMode(mode); diff --git a/storage/connect/osutil.h b/storage/connect/osutil.h index 7e6b8823b9b..380e7bebb22 100644 --- a/storage/connect/osutil.h +++ b/storage/connect/osutil.h @@ -3,7 +3,11 @@ #define __OSUTIL_H__ #if defined(UNIX) || defined(UNIV_LINUX) +#if defined(MARIADB) #include "my_global.h" +#else +#include "mini-global.h" +#endif #include #include #include "os.h" diff --git a/storage/connect/plugutil.cpp b/storage/connect/plugutil.cpp index 6790e7eb45c..e74937b942a 100644 --- a/storage/connect/plugutil.cpp +++ b/storage/connect/plugutil.cpp @@ -2,11 +2,11 @@ /* */ /* PROGRAM NAME: PLUGUTIL */ /* ------------- */ -/* Version 3.0 */ +/* Version 3.1 */ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 1993-2017 */ +/* (C) Copyright to the author Olivier BERTRAND 1993-2019 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -110,22 +110,32 @@ ACTIVITY defActivity = { /* Describes activity and language */ #include "rcmsg.h" #endif // UNIX +/**************************************************************************/ +/* Conditional tracing output function. */ +/**************************************************************************/ +void xtrc(uint x, char const *fmt, ...) +{ + if (GetTraceValue() & x) { + va_list ap; + va_start(ap, fmt); + + vfprintf(stderr, fmt, ap); + va_end(ap); + } // endif x + +} // end of xtrc + /**************************************************************************/ /* Tracing output function. */ /**************************************************************************/ -void htrc(char const *fmt, ...) - { - va_list ap; - va_start (ap, fmt); +void htrc(char const* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); - -//if (trace == 1) -// vfprintf(debug, fmt, ap); -//else - vfprintf(stderr, fmt, ap); - - va_end (ap); - } // end of htrc + vfprintf(stderr, fmt, ap); + va_end(ap); +} // end of htrc /***********************************************************************/ /* Plug initialization routine. */ diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 30d8063d1a6..8ba8aac3621 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -81,51 +81,51 @@ RELDEF::RELDEF(void) /* This function return a pointer to the Table Option Struct. */ /***********************************************************************/ PTOS RELDEF::GetTopt(void) - { - return Hc->GetTableOptionStruct(); - } // end of GetTopt + { + return Hc->GetTableOptionStruct(); + } // end of GetTopt /***********************************************************************/ /* This function sets an integer table information. */ /***********************************************************************/ bool RELDEF::SetIntCatInfo(PCSZ what, int n) - { - return Hc->SetIntegerOption(what, n); - } // end of SetIntCatInfo + { + return Hc->SetIntegerOption(what, n); + } // end of SetIntCatInfo /***********************************************************************/ /* This function returns integer table information. */ /***********************************************************************/ int RELDEF::GetIntCatInfo(PCSZ what, int idef) - { - int n= Hc->GetIntegerOption(what); + { + int n= Hc->GetIntegerOption(what); - return (n == NO_IVAL) ? idef : n; - } // end of GetIntCatInfo + return (n == NO_IVAL) ? idef : n; + } // end of GetIntCatInfo /***********************************************************************/ /* This function returns Boolean table information. */ /***********************************************************************/ bool RELDEF::GetBoolCatInfo(PCSZ what, bool bdef) - { - bool b= Hc->GetBooleanOption(what, bdef); + { + bool b= Hc->GetBooleanOption(what, bdef); - return b; - } // end of GetBoolCatInfo + return b; + } // end of GetBoolCatInfo /***********************************************************************/ /* This function returns size catalog information. */ /***********************************************************************/ int RELDEF::GetSizeCatInfo(PCSZ what, PCSZ sdef) - { - char c; - PCSZ s; + { + char c; + PCSZ s; int i, n= 0; - if (!(s= Hc->GetStringOption(what))) - s= sdef; + if (!(s= Hc->GetStringOption(what))) + s= sdef; - if ((i= sscanf(s, " %d %c ", &n, &c)) == 2) + if ((i= sscanf(s, " %d %c ", &n, &c)) == 2) switch (toupper(c)) { case 'M': n *= 1024; @@ -141,41 +141,41 @@ int RELDEF::GetSizeCatInfo(PCSZ what, PCSZ sdef) /* This function sets char table information in buf. */ /***********************************************************************/ int RELDEF::GetCharCatInfo(PCSZ what, PCSZ sdef, char *buf, int size) - { - PCSZ s= Hc->GetStringOption(what); + { + PCSZ s= Hc->GetStringOption(what); - strncpy(buf, ((s) ? s : sdef), size); - return size; - } // end of GetCharCatInfo + strncpy(buf, ((s) ? s : sdef), size); + return size; + } // end of GetCharCatInfo /***********************************************************************/ /* To be used by any TDB's. */ /***********************************************************************/ bool RELDEF::Partitioned(void) - { - return Hc->IsPartitioned(); - } // end of Partitioned + { + return Hc->IsPartitioned(); + } // end of Partitioned /***********************************************************************/ /* This function returns string table information. */ /* Default parameter is "*" to get the handler default. */ /***********************************************************************/ char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef) - { - char *sval = NULL; - PCSZ name, s= Hc->GetStringOption(what, sdef); - - if (s) { + { + char *sval = NULL; + PCSZ name, s= Hc->GetStringOption(what, sdef); + + if (s) { if (!Hc->IsPartitioned() || (stricmp(what, "filename") && stricmp(what, "tabname") && stricmp(what, "connect"))) - sval= PlugDup(g, s); + sval= PlugDup(g, s); else sval= (char*)s; } else if (!stricmp(what, "filename")) { // Return default file name - PCSZ ftype= Hc->GetStringOption("Type", "*"); + PCSZ ftype= Hc->GetStringOption("Type", "*"); int i, n; if (IsFileType(GetTypeID(ftype))) { @@ -183,7 +183,7 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef) sval= (char*)PlugSubAlloc(g, NULL, strlen(name) + 12); strcat(strcpy(sval, name), "."); n= strlen(sval); - + // Fold ftype to lower case for (i= 0; i < 12; i++) if (!ftype[i]) { @@ -196,8 +196,8 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef) } // endif s - return sval; - } // end of GetStringCatInfo + return sval; + } // end of GetStringCatInfo /* --------------------------- Class TABDEF -------------------------- */ @@ -223,14 +223,14 @@ TABDEF::TABDEF(void) /***********************************************************************/ /* Define: initialize the table definition block from XDB file. */ /***********************************************************************/ -bool TABDEF::Define(PGLOBAL g, PCATLG cat, - LPCSTR name, LPCSTR schema, LPCSTR am) +bool TABDEF::Define(PGLOBAL g, PCATLG cat, + LPCSTR name, LPCSTR schema, LPCSTR am) { int poff = 0; - Hc = ((MYCAT*)cat)->GetHandler(); - Name = (PSZ)name; - Schema = (PSZ)Hc->GetDBName(schema); + Hc = ((MYCAT*)cat)->GetHandler(); + Name = (PSZ)name; + Schema = (PSZ)Hc->GetDBName(schema); Cat = cat; Catfunc = GetFuncID(GetStringCatInfo(g, "Catfunc", NULL)); Elemt = GetIntCatInfo("Elements", 0); @@ -263,14 +263,14 @@ PCSZ TABDEF::GetPath(void) /* This function returns column table information. */ /***********************************************************************/ int TABDEF::GetColCatInfo(PGLOBAL g) - { - char *type= GetStringCatInfo(g, "Type", "*"); + { + char *type= GetStringCatInfo(g, "Type", "*"); char c, fty, eds; - int i, n, loff, poff, nof, nlg; - void *field= NULL; + int i, n, loff, poff, nof, nlg; + void *field= NULL; TABTYPE tc; PCOLDEF cdp, lcdp= NULL, tocols= NULL; - PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO)); + PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO)); memset(pcf, 0, sizeof(COLINFO)); @@ -278,33 +278,33 @@ int TABDEF::GetColCatInfo(PGLOBAL g) tc= (Catfunc == FNC_NO) ? GetTypeID(type) : TAB_PRX; // Take care of the column definitions - i= poff= nof= nlg= 0; + i= poff= nof= nlg= 0; #if defined(__WIN__) - // Offsets of HTML and DIR tables start from 0, DBF at 1 - loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0; + // Offsets of HTML and DIR tables start from 0, DBF at 1 + loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0; #else // !__WIN__ - // Offsets of HTML tables start from 0, DIR and DBF at 1 - loff = (tc == TAB_DBF || tc == TAB_DIR) ? 1 : (tc == TAB_XML) ? -1 : 0; + // Offsets of HTML tables start from 0, DIR and DBF at 1 + loff = (tc == TAB_DBF || tc == TAB_DIR) ? 1 : (tc == TAB_XML) ? -1 : 0; #endif // !__WIN__ while (true) { - // Default Offset depends on table type - switch (tc) { + // Default Offset depends on table type + switch (tc) { case TAB_DOS: case TAB_FIX: case TAB_BIN: case TAB_VEC: case TAB_DBF: - poff= loff + nof; // Default next offset - nlg= MY_MAX(nlg, poff); // Default lrecl + poff= loff + nof; // Default next offset + nlg= MY_MAX(nlg, poff); // Default lrecl break; case TAB_CSV: case TAB_FMT: - nlg+= nof; + nlg+= nof; case TAB_DIR: case TAB_XML: - poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1); + poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1); break; case TAB_INI: case TAB_MAC: @@ -316,39 +316,39 @@ int TABDEF::GetColCatInfo(PGLOBAL g) poff = 0; // Offset represents an independant flag break; default: // VCT PLG ODBC JDBC MYSQL WMI... - poff = 0; // NA + poff = 0; // NA break; - } // endswitch tc + } // endswitch tc -// do { - field= Hc->GetColumnOption(g, field, pcf); +// do { + field= Hc->GetColumnOption(g, field, pcf); // } while (field && (*pcf->Name =='*' /*|| pcf->Flags & U_VIRTUAL*/)); - if (tc == TAB_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) { - // DBF date format defaults to 'YYYMMDD' - pcf->Datefmt= "YYYYMMDD"; - pcf->Length= 8; - } // endif tc + if (tc == TAB_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) { + // DBF date format defaults to 'YYYMMDD' + pcf->Datefmt= "YYYYMMDD"; + pcf->Length= 8; + } // endif tc - if (!field) - break; + if (!field) + break; // Allocate the column description block cdp= new(g) COLDEF; if ((nof= cdp->Define(g, NULL, pcf, poff)) < 0) - return -1; // Error, probably unhandled type - else - loff= cdp->GetOffset(); + return -1; // Error, probably unhandled type + else + loff= cdp->GetOffset(); - switch (tc) { - case TAB_VEC: - cdp->SetOffset(0); // Not to have shift - case TAB_BIN: - // BIN/VEC are packed by default + switch (tc) { + case TAB_VEC: + cdp->SetOffset(0); // Not to have shift + case TAB_BIN: + // BIN/VEC are packed by default if (nof) { - // Field width is the internal representation width - // that can also depend on the column format + // Field width is the internal representation width + // that can also depend on the column format fty = cdp->Decode ? 'C' : 'X'; eds = 0; n = 0; @@ -371,38 +371,38 @@ int TABDEF::GetColCatInfo(PGLOBAL g) if (n) nof = n; else switch (fty) { - case 'X': + case 'X': if (eds && IsTypeChar(cdp->Buf_Type)) nof = sizeof(longlong); else nof= cdp->Clen; break; - case 'C': break; - case 'R': - case 'F': nof = sizeof(float); break; - case 'I': nof = sizeof(int); break; - case 'D': nof = sizeof(double); break; - case 'S': nof = sizeof(short); break; - case 'T': nof = sizeof(char); break; - case 'G': nof = sizeof(longlong); break; - default: /* Wrong format */ + case 'C': break; + case 'R': + case 'F': nof = sizeof(float); break; + case 'I': nof = sizeof(int); break; + case 'D': nof = sizeof(double); break; + case 'S': nof = sizeof(short); break; + case 'T': nof = sizeof(char); break; + case 'G': nof = sizeof(longlong); break; + default: /* Wrong format */ sprintf(g->Message, "Invalid format %c", fty); return -1; - } // endswitch fty + } // endswitch fty } // endif nof default: - break; - } // endswitch tc + break; + } // endswitch tc - if (lcdp) - lcdp->SetNext(cdp); - else - tocols= cdp; + if (lcdp) + lcdp->SetNext(cdp); + else + tocols= cdp; - lcdp= cdp; + lcdp= cdp; i++; } // endwhile @@ -410,31 +410,31 @@ int TABDEF::GetColCatInfo(PGLOBAL g) if (i != GetDegree()) SetDegree(i); - if (GetDefType() == TYPE_AM_DOS) { - int ending, recln= 0; + if (GetDefType() == TYPE_AM_DOS) { + int ending, recln= 0; - // Was commented because sometimes ending is 0 even when - // not specified (for instance if quoted is specified) -// if ((ending= Hc->GetIntegerOption("Ending")) < 0) { - if ((ending= Hc->GetIntegerOption("Ending")) <= 0) { + // Was commented because sometimes ending is 0 even when + // not specified (for instance if quoted is specified) +// if ((ending= Hc->GetIntegerOption("Ending")) < 0) { + if ((ending= Hc->GetIntegerOption("Ending")) <= 0) { ending= (tc == TAB_BIN || tc == TAB_VEC) ? 0 : CRLF; - Hc->SetIntegerOption("Ending", ending); - } // endif ending + Hc->SetIntegerOption("Ending", ending); + } // endif ending - // Calculate the default record size - switch (tc) { + // Calculate the default record size + switch (tc) { case TAB_FIX: case TAB_BIN: recln= nlg + ending; // + length of line ending break; case TAB_VEC: recln= nlg; - + // if ((k= (pak < 0) ? 8 : pak) > 1) // See above for detailed comment // Round up lrecl to multiple of 8 or pak // recln= ((recln + k - 1) / k) * k; - + break; case TAB_DOS: case TAB_DBF: @@ -443,26 +443,30 @@ int TABDEF::GetColCatInfo(PGLOBAL g) case TAB_CSV: case TAB_FMT: // The number of separators (assuming an extra one can exist) -// recln= poff * ((qotd) ? 3 : 1); to be investigated - recln= nlg + poff * 3; // To be safe +// recln= poff * ((qotd) ? 3 : 1); to be investigated + recln= nlg + poff * 3; // To be safe default: break; } // endswitch tc - // lrecl must be at least recln to avoid buffer overflow - if (trace(1)) - htrc("Lrecl: Calculated=%d defined=%d\n", - recln, Hc->GetIntegerOption("Lrecl")); + // lrecl must be at least recln to avoid buffer overflow + if (trace(1)) + htrc("Lrecl: Calculated=%d defined=%d\n", + recln, Hc->GetIntegerOption("Lrecl")); - recln = MY_MAX(recln, Hc->GetIntegerOption("Lrecl")); - Hc->SetIntegerOption("Lrecl", recln); - ((PDOSDEF)this)->SetLrecl(recln); - } // endif Lrecl + recln = MY_MAX(recln, Hc->GetIntegerOption("Lrecl")); + Hc->SetIntegerOption("Lrecl", recln); + ((PDOSDEF)this)->SetLrecl(recln); - // Attach the column definition to the tabdef - SetCols(tocols); - return poff; - } // end of GetColCatInfo + if (trace(1)) + htrc("Lrecl set to %d\n", recln); + + } // endif Lrecl + + // Attach the column definition to the tabdef + SetCols(tocols); + return poff; + } // end of GetColCatInfo /***********************************************************************/ /* SetIndexInfo: retrieve index description from the table structure. */ @@ -487,16 +491,17 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) PCATLG cat = Cat; /*********************************************************************/ - /* Ensure that the .dll doesn't have a path. */ - /* This is done to ensure that only approved dll from the system */ + /* Ensure that the module name doesn't have a path. */ + /* This is done to ensure that only approved libs from the system */ /* directories are used (to make this even remotely secure). */ /*********************************************************************/ if (check_valid_path(Module, strlen(Module))) { strcpy(g->Message, "Module cannot contain a path"); return NULL; } else - PlugSetPath(soname, Module, GetPluginDir()); - +// PlugSetPath(soname, Module, GetPluginDir()); // Crashes on Fedora + strncat(strcpy(soname, GetPluginDir()), Module, _MAX_PATH); + #if defined(__WIN__) // Is the DLL already loaded? if (!Hdll && !(Hdll = GetModuleHandle(soname))) @@ -522,31 +527,31 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) // Get the function returning an instance of the external DEF class if (!(getdef = (XGETDEF)GetProcAddress((HINSTANCE)Hdll, getname))) { - char buf[256]; - DWORD rc = GetLastError(); + char buf[256]; + DWORD rc = GetLastError(); - sprintf(g->Message, MSG(PROCADD_ERROR), rc, getname); - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, - (LPTSTR)buf, sizeof(buf), NULL); - strcat(strcat(g->Message, ": "), buf); - FreeLibrary((HMODULE)Hdll); + sprintf(g->Message, MSG(PROCADD_ERROR), rc, getname); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, + (LPTSTR)buf, sizeof(buf), NULL); + strcat(strcat(g->Message, ": "), buf); + FreeLibrary((HMODULE)Hdll); return NULL; } // endif getdef #else // !__WIN__ const char *error = NULL; - -#if 0 // Don't know what all this stuff does - Dl_info dl_info; - // The OEM lib must retrieve exported CONNECT variables +#if 0 // Don't know what all this stuff does + Dl_info dl_info; + + // The OEM lib must retrieve exported CONNECT variables if (dladdr(&connect_hton, &dl_info)) { if (dlopen(dl_info.dli_fname, RTLD_NOLOAD | RTLD_NOW | RTLD_GLOBAL) == 0) { error = dlerror(); sprintf(g->Message, "dlopen failed: %s, OEM not supported", SVP(error)); return NULL; } // endif dlopen - + } else { error = dlerror(); sprintf(g->Message, "dladdr failed: %s, OEM not supported", SVP(error)); @@ -626,7 +631,7 @@ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int) char *desc = (char*)PlugSubAlloc(g, NULL, strlen(Module) + strlen(Subtype) + 3); sprintf(desc, "%s(%s)", Module, Subtype); - Desc = desc; + Desc = desc; return false; } // end of DefineAM @@ -701,17 +706,17 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode) txfp = new(g) FIXFAM(defp); } else if (rfm == RECFM_VCT) { #if defined(VCT_SUPPORT) - assert(Pxdef->GetDefType() == TYPE_AM_VCT); + assert(Pxdef->GetDefType() == TYPE_AM_VCT); if (map) txfp = new(g) VCMFAM((PVCTDEF)defp); else txfp = new(g) VCTFAM((PVCTDEF)defp); #else // !VCT_SUPPORT - strcpy(g->Message, "VCT no more supported"); - return NULL; + strcpy(g->Message, "VCT no more supported"); + return NULL; #endif // !VCT_SUPPORT - } // endif's + } // endif's ((PTDBDOS)tdbp)->SetTxfp(txfp); } // endif Txfp diff --git a/storage/connect/rest.def b/storage/connect/rest.def new file mode 100644 index 00000000000..71c76740af9 --- /dev/null +++ b/storage/connect/rest.def @@ -0,0 +1,4 @@ +LIBRARY REST2 +EXPORTS + GetREST @1 + ColREST @2 diff --git a/storage/connect/rest.h b/storage/connect/rest.h new file mode 100644 index 00000000000..f1d77e0a279 --- /dev/null +++ b/storage/connect/rest.h @@ -0,0 +1,33 @@ +/***********************************************************************/ +/* Definitions needed by the included files. */ +/***********************************************************************/ +#if !defined(MY_GLOBAL_H) +#define MY_GLOBAL_H +typedef unsigned int uint; +typedef unsigned int uint32; +typedef unsigned short ushort; +typedef unsigned long ulong; +typedef unsigned long DWORD; +typedef char *LPSTR; +typedef const char *LPCSTR; +typedef int BOOL; +#if defined(_WINDOWS) +typedef void *HANDLE; +#else +typedef int HANDLE; +#endif +typedef char *PSZ; +typedef const char *PCSZ; +typedef unsigned char BYTE; +typedef unsigned char uchar; +typedef long long longlong; +typedef unsigned long long ulonglong; +typedef char my_bool; +struct charset_info_st {}; +typedef const charset_info_st CHARSET_INFO; +#define FALSE 0 +#define TRUE 1 +#define Item char +#define MY_MAX(a,b) ((a>b)?(a):(b)) +#define MY_MIN(a,b) ((a #else -#include "mini_global.h" +#include "mini-global.h" +#define _OS_H_INCLUDED // Prevent os.h to be called #endif using namespace utility::conversions; // String conversions utilities @@ -18,70 +19,71 @@ using namespace concurrency::streams; // Asynchronous streams #include "global.h" +static uint xt = 0; // Used by lamda expressions /***********************************************************************/ /* Make a local copy of the requested file. */ /***********************************************************************/ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn) { - int rc= 0; - auto fileStream= std::make_shared(); + int rc = 0; + auto fileStream = std::make_shared(); - if (!http || !fn) { - strcpy(g->Message, "Missing http or filename"); - return 2; - } // endif + if (!http || !fn) { + strcpy(g->Message, "Missing http or filename"); + return 2; + } // endif - //std::string sfn(fn); - //auto wfn= to_string_t(sfn); - //rc= 0; + xt = GetTraceValue(); + xtrc(515, "restGetFile: fn=%s\n", fn); // Open stream to output file. - pplx::task requestTask= - fstream::open_ostream(to_string_t(fn)) - .then([=](ostream outFile) { - *fileStream= outFile; + pplx::task requestTask = fstream::open_ostream(to_string_t(fn)) + .then([=](ostream outFile) { + *fileStream= outFile; - // Create http_client to send the request. - http_client client(to_string_t(http)); + if (xt & 515) + htrc("Outfile isopen=%d\n", outFile.is_open()); - if (uri) - { - // Build request URI and start the request. - uri_builder builder(to_string_t(uri)); - return client.request(methods::GET, builder.to_string()); - } - else - return client.request(methods::GET); - }) + // Create http_client to send the request. + http_client client(to_string_t(http)); - // Handle response headers arriving. - .then([=](http_response response) { -#if defined(DEVELOPMENT) - fprintf(stderr, "Received response status code:%u\n", - response.status_code()); -#endif // DEVELOPMENT + if (uri) { + // Build request URI and start the request. + uri_builder builder(to_string_t(uri)); + return client.request(methods::GET, builder.to_string()); + } else + return client.request(methods::GET); + }) - // Write response body into the file. - return response.body().read_to_end(fileStream->streambuf()); - }) + // Handle response headers arriving. + .then([=](http_response response) { + if (xt & 515) + htrc("Received response status code:%u\n", + response.status_code()); - // Close the file stream. - .then([=](size_t) { return fileStream->close(); }); + // Write response body into the file. + return response.body().read_to_end(fileStream->streambuf()); + }) + + // Close the file stream. + .then([=](size_t n) { + if (xt & 515) + htrc("Return size=%u\n", n); + + return fileStream->close(); + }); // Wait for all the outstanding I/O to complete and handle any exceptions - try - { + try { requestTask.wait(); - } - catch (const std::exception &e) - { -#if defined(DEVELOPMENT) - fprintf(stderr, "Error exception: %s\n", e.what()); -#endif // DEVELOPMENT - sprintf(g->Message, "Error exception: %s", e.what()); + xtrc(515, "In Wait\n"); + } catch (const std::exception &e) { + xtrc(515, "Error exception: %s\n", e.what()); + sprintf(g->Message, "Error exception: %s", e.what()); rc= 1; } // end try/catch + xtrc(515, "restget done: rc=%d\n", rc); return rc; -} // end of restGetFile \ No newline at end of file +} // end of restGetFile diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp index 02720a3089a..746382178fb 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -189,9 +189,11 @@ PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info) htrc("File %s Sep=%c Qot=%c Header=%d maxerr=%d\n", SVP(tdp->Fn), tdp->Sep, tdp->Qot, tdp->Header, tdp->Maxerr); +#if defined(ZIP_SUPPORT) if (tdp->Zipped) tcvp = new(g)TDBCSV(tdp, new(g)UNZFAM(tdp)); else +#endif // ZIP_SUPPORT tcvp = new(g) TDBCSV(tdp, new(g) DOSFAM(tdp)); tcvp->SetMode(MODE_READ); diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index a8f76900cb4..0b282345c8a 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -71,15 +71,15 @@ char *GetJsonNull(void); /***********************************************************************/ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) { - static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, + static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING}; - static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, + static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT}; static unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0}; - int i, n = 0; + int i, n = 0; int ncol = sizeof(buftyp) / sizeof(int); - PJCL jcp; - JSONDISC *pjdc = NULL; + PJCL jcp; + JSONDISC *pjdc = NULL; PQRYRES qrp; PCOLRES crp; @@ -89,15 +89,15 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) goto skipit; } // endif info - if (GetIntegerTableOption(g, topt, "Multiple", 0)) { - strcpy(g->Message, "Cannot find column definition for multiple table"); - return NULL; - } // endif Multiple + if (GetIntegerTableOption(g, topt, "Multiple", 0)) { + strcpy(g->Message, "Cannot find column definition for multiple table"); + return NULL; + } // endif Multiple - pjdc = new(g) JSONDISC(g, length); + pjdc = new(g) JSONDISC(g, length); - if (!(n = pjdc->GetColumns(g, db, dsn, topt))) - return NULL; + if (!(n = pjdc->GetColumns(g, db, dsn, topt))) + return NULL; skipit: if (trace(1)) @@ -110,8 +110,8 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) buftyp, fldtyp, length, false, false); crp = qrp->Colresp->Next->Next->Next->Next->Next->Next; - crp->Name = PlugDup(g, "Nullable"); - crp->Next->Name = PlugDup(g, "Jpath"); + crp->Name = PlugDup(g, "Nullable"); + crp->Next->Name = PlugDup(g, "Jpath"); if (info || !qrp) return qrp; @@ -122,8 +122,8 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) /* Now get the results into blocks. */ /*********************************************************************/ for (i = 0, jcp = pjdc->fjcp; jcp; i++, jcp = jcp->Next) { - if (jcp->Type == TYPE_UNKNOWN) - jcp->Type = TYPE_STRING; // Void column + if (jcp->Type == TYPE_UNKNOWN) + jcp->Type = TYPE_STRING; // Void column crp = qrp->Colresp; // Column Name crp->Kdata->SetValue(jcp->Name, i); @@ -159,380 +159,380 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) /***********************************************************************/ JSONDISC::JSONDISC(PGLOBAL g, uint *lg) { - length = lg; - jcp = fjcp = pjcp = NULL; - tjnp = NULL; - jpp = NULL; - tjsp = NULL; - jsp = NULL; - row = NULL; - sep = NULL; - i = n = bf = ncol = lvl = 0; - all = false; -} // end of JSONDISC constructor + length = lg; + jcp = fjcp = pjcp = NULL; + tjnp = NULL; + jpp = NULL; + tjsp = NULL; + jsp = NULL; + row = NULL; + sep = NULL; + i = n = bf = ncol = lvl = 0; + all = false; +} // end of JSONDISC constructor int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) { - char filename[_MAX_PATH]; - bool mgo = (GetTypeID(topt->type) == TAB_MONGO); - PCSZ level = GetStringTableOption(g, topt, "Level", NULL); + char filename[_MAX_PATH]; + bool mgo = (GetTypeID(topt->type) == TAB_MONGO); + PCSZ level = GetStringTableOption(g, topt, "Level", NULL); - if (level) { - lvl = atoi(level); - lvl = (lvl > 16) ? 16 : lvl; - } else - lvl = 0; + if (level) { + lvl = atoi(level); + lvl = (lvl > 16) ? 16 : lvl; + } else + lvl = 0; - sep = GetStringTableOption(g, topt, "Separator", "."); + sep = GetStringTableOption(g, topt, "Separator", "."); - /*********************************************************************/ - /* Open the input file. */ - /*********************************************************************/ - tdp = new(g) JSONDEF; + /*********************************************************************/ + /* Open the input file. */ + /*********************************************************************/ + tdp = new(g) JSONDEF; #if defined(ZIP_SUPPORT) - tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL); - tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false); + tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL); + tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false); #endif // ZIP_SUPPORT - tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL); + tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL); - if (!(tdp->Database = SetPath(g, db))) - return 0; + if (!(tdp->Database = SetPath(g, db))) + return 0; - tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); - tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; - tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2); - tdp->Xcol = GetStringTableOption(g, topt, "Expand", NULL); - tdp->Accept = GetBooleanTableOption(g, topt, "Accept", false); - tdp->Uri = (dsn && *dsn ? dsn : NULL); + tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); + tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; + tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2); + tdp->Xcol = GetStringTableOption(g, topt, "Expand", NULL); + tdp->Accept = GetBooleanTableOption(g, topt, "Accept", false); + tdp->Uri = (dsn && *dsn ? dsn : NULL); - if (!tdp->Fn && !tdp->Uri) { - strcpy(g->Message, MSG(MISSING_FNAME)); - return 0; - } // endif Fn + if (!tdp->Fn && !tdp->Uri) { + strcpy(g->Message, MSG(MISSING_FNAME)); + return 0; + } // endif Fn - if (tdp->Fn) { - // We used the file name relative to recorded datapath - PlugSetPath(filename, tdp->Fn, tdp->GetPath()); - tdp->Fn = PlugDup(g, filename); - } // endif Fn + if (tdp->Fn) { + // We used the file name relative to recorded datapath + PlugSetPath(filename, tdp->Fn, tdp->GetPath()); + tdp->Fn = PlugDup(g, filename); + } // endif Fn - if (trace(1)) - htrc("File %s objname=%s pretty=%d lvl=%d\n", - tdp->Fn, tdp->Objname, tdp->Pretty, lvl); + if (trace(1)) + htrc("File %s objname=%s pretty=%d lvl=%d\n", + tdp->Fn, tdp->Objname, tdp->Pretty, lvl); - if (tdp->Uri) { + if (tdp->Uri) { #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) - tdp->Collname = GetStringTableOption(g, topt, "Name", NULL); - tdp->Collname = GetStringTableOption(g, topt, "Tabname", tdp->Collname); - tdp->Schema = GetStringTableOption(g, topt, "Dbname", "test"); - tdp->Options = (PSZ)GetStringTableOption(g, topt, "Colist", "all"); - tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false); - tdp->Driver = (PSZ)GetStringTableOption(g, topt, "Driver", NULL); - tdp->Version = GetIntegerTableOption(g, topt, "Version", 3); - tdp->Wrapname = (PSZ)GetStringTableOption(g, topt, "Wrapper", - (tdp->Version == 2) ? "Mongo2Interface" : "Mongo3Interface"); - tdp->Pretty = 0; + tdp->Collname = GetStringTableOption(g, topt, "Name", NULL); + tdp->Collname = GetStringTableOption(g, topt, "Tabname", tdp->Collname); + tdp->Schema = GetStringTableOption(g, topt, "Dbname", "test"); + tdp->Options = (PSZ)GetStringTableOption(g, topt, "Colist", "all"); + tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false); + tdp->Driver = (PSZ)GetStringTableOption(g, topt, "Driver", NULL); + tdp->Version = GetIntegerTableOption(g, topt, "Version", 3); + tdp->Wrapname = (PSZ)GetStringTableOption(g, topt, "Wrapper", + (tdp->Version == 2) ? "Mongo2Interface" : "Mongo3Interface"); + tdp->Pretty = 0; #else // !MONGO_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); - return 0; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); + return 0; #endif // !MONGO_SUPPORT - } // endif Uri + } // endif Uri - if (tdp->Pretty == 2) { - if (tdp->Zipped) { + if (tdp->Pretty == 2) { + if (tdp->Zipped) { #if defined(ZIP_SUPPORT) - tjsp = new(g) TDBJSON(tdp, new(g) UNZFAM(tdp)); + tjsp = new(g) TDBJSON(tdp, new(g) UNZFAM(tdp)); #else // !ZIP_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); - return 0; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); + return 0; #endif // !ZIP_SUPPORT - } else - tjsp = new(g) TDBJSON(tdp, new(g) MAPFAM(tdp)); + } else + tjsp = new(g) TDBJSON(tdp, new(g) MAPFAM(tdp)); - if (tjsp->MakeDocument(g)) - return 0; + if (tjsp->MakeDocument(g)) + return 0; - jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetValue(0) : NULL; - } else { - if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0))) - if (!mgo) { - sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty); - return 0; - } else - tdp->Lrecl = 8192; // Should be enough + jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetValue(0) : NULL; + } else { + if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0))) + if (!mgo) { + sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty); + return 0; + } else + tdp->Lrecl = 8192; // Should be enough - tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF); + tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF); - if (tdp->Zipped) { + if (tdp->Zipped) { #if defined(ZIP_SUPPORT) - tjnp = new(g)TDBJSN(tdp, new(g) UNZFAM(tdp)); + tjnp = new(g)TDBJSN(tdp, new(g) UNZFAM(tdp)); #else // !ZIP_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); - return NULL; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); + return NULL; #endif // !ZIP_SUPPORT - } else if (tdp->Uri) { - if (tdp->Driver && toupper(*tdp->Driver) == 'C') { + } else if (tdp->Uri) { + if (tdp->Driver && toupper(*tdp->Driver) == 'C') { #if defined(CMGO_SUPPORT) - tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp)); + tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp)); #else - sprintf(g->Message, "Mongo %s Driver not available", "C"); - return 0; + sprintf(g->Message, "Mongo %s Driver not available", "C"); + return 0; #endif - } else if (tdp->Driver && toupper(*tdp->Driver) == 'J') { + } else if (tdp->Driver && toupper(*tdp->Driver) == 'J') { #if defined(JAVA_SUPPORT) - tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp)); + tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp)); #else - sprintf(g->Message, "Mongo %s Driver not available", "Java"); - return 0; + sprintf(g->Message, "Mongo %s Driver not available", "Java"); + return 0; #endif - } else { // Driver not specified + } else { // Driver not specified #if defined(CMGO_SUPPORT) - tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp)); + tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp)); #elif defined(JAVA_SUPPORT) - tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp)); + tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp)); #else - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); - return 0; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); + return 0; #endif - } // endif Driver + } // endif Driver - } else - tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp)); + } else + tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp)); - tjnp->SetMode(MODE_READ); + tjnp->SetMode(MODE_READ); - // Allocate the parse work memory - PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); - memset(G, 0, sizeof(GLOBAL)); - G->Sarea_Size = tdp->Lrecl * 10; - G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size); - PlugSubSet(G->Sarea, G->Sarea_Size); - G->jump_level = 0; - tjnp->SetG(G); + // Allocate the parse work memory + PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); + memset(G, 0, sizeof(GLOBAL)); + G->Sarea_Size = tdp->Lrecl * 10; + G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size); + PlugSubSet(G->Sarea, G->Sarea_Size); + G->jump_level = 0; + tjnp->SetG(G); - if (tjnp->OpenDB(g)) - return 0; + if (tjnp->OpenDB(g)) + return 0; - switch (tjnp->ReadDB(g)) { - case RC_EF: - strcpy(g->Message, "Void json table"); - case RC_FX: - goto err; - default: - jsp = tjnp->GetRow(); - } // endswitch ReadDB + switch (tjnp->ReadDB(g)) { + case RC_EF: + strcpy(g->Message, "Void json table"); + case RC_FX: + goto err; + default: + jsp = tjnp->GetRow(); + } // endswitch ReadDB - } // endif pretty + } // endif pretty - if (!(row = (jsp) ? jsp->GetObject() : NULL)) { - strcpy(g->Message, "Can only retrieve columns from object rows"); - goto err; - } // endif row + if (!(row = (jsp) ? jsp->GetObject() : NULL)) { + strcpy(g->Message, "Can only retrieve columns from object rows"); + goto err; + } // endif row - all = GetBooleanTableOption(g, topt, "Fullarray", false); - jcol.Name = jcol.Fmt = NULL; - jcol.Next = NULL; - jcol.Found = true; - colname[0] = 0; + all = GetBooleanTableOption(g, topt, "Fullarray", false); + jcol.Name = jcol.Fmt = NULL; + jcol.Next = NULL; + jcol.Found = true; + colname[0] = 0; - if (!tdp->Uri) { - fmt[0] = '$'; - fmt[1] = '.'; - bf = 2; - } // endif Uri + if (!tdp->Uri) { + fmt[0] = '$'; + fmt[1] = '.'; + bf = 2; + } // endif Uri - /*********************************************************************/ - /* Analyse the JSON tree and define columns. */ - /*********************************************************************/ - for (i = 1; ; i++) { - for (jpp = row->GetFirst(); jpp; jpp = jpp->GetNext()) { - strncpy(colname, jpp->GetKey(), 64); - fmt[bf] = 0; + /*********************************************************************/ + /* Analyse the JSON tree and define columns. */ + /*********************************************************************/ + for (i = 1; ; i++) { + for (jpp = row->GetFirst(); jpp; jpp = jpp->GetNext()) { + strncpy(colname, jpp->GetKey(), 64); + fmt[bf] = 0; - if (Find(g, jpp->GetVal(), colname, MY_MIN(lvl, 0))) - goto err; + if (Find(g, jpp->GetVal(), colname, MY_MIN(lvl, 0))) + goto err; - } // endfor jpp + } // endfor jpp - // Missing column can be null - for (jcp = fjcp; jcp; jcp = jcp->Next) { - jcp->Cbn |= !jcp->Found; - jcp->Found = false; - } // endfor jcp + // Missing column can be null + for (jcp = fjcp; jcp; jcp = jcp->Next) { + jcp->Cbn |= !jcp->Found; + jcp->Found = false; + } // endfor jcp - if (tdp->Pretty != 2) { - // Read next record - switch (tjnp->ReadDB(g)) { - case RC_EF: - jsp = NULL; - break; - case RC_FX: - goto err; - default: - jsp = tjnp->GetRow(); - } // endswitch ReadDB + if (tdp->Pretty != 2) { + // Read next record + switch (tjnp->ReadDB(g)) { + case RC_EF: + jsp = NULL; + break; + case RC_FX: + goto err; + default: + jsp = tjnp->GetRow(); + } // endswitch ReadDB - } else - jsp = tjsp->GetDoc()->GetValue(i); + } else + jsp = tjsp->GetDoc()->GetValue(i); - if (!(row = (jsp) ? jsp->GetObject() : NULL)) - break; + if (!(row = (jsp) ? jsp->GetObject() : NULL)) + break; - } // endfor i + } // endfor i - if (tdp->Pretty != 2) - tjnp->CloseDB(g); + if (tdp->Pretty != 2) + tjnp->CloseDB(g); - return n; + return n; err: - if (tdp->Pretty != 2) - tjnp->CloseDB(g); + if (tdp->Pretty != 2) + tjnp->CloseDB(g); - return 0; -} // end of GetColumns + return 0; +} // end of GetColumns bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j) { - char *p, *pc = colname + strlen(colname); - int ars; - PJOB job; - PJAR jar; + char *p, *pc = colname + strlen(colname); + int ars; + PJOB job; + PJAR jar; - if ((valp = jvp ? jvp->GetValue() : NULL)) { - jcol.Type = valp->GetType(); - jcol.Len = valp->GetValLen(); - jcol.Scale = valp->GetValPrec(); - jcol.Cbn = valp->IsNull(); - } else if (!jvp || jvp->IsNull()) { - jcol.Type = TYPE_UNKNOWN; - jcol.Len = jcol.Scale = 0; - jcol.Cbn = true; - } else if (j < lvl) { - if (!fmt[bf]) - strcat(fmt, colname); + if ((valp = jvp ? jvp->GetValue() : NULL)) { + jcol.Type = valp->GetType(); + jcol.Len = valp->GetValLen(); + jcol.Scale = valp->GetValPrec(); + jcol.Cbn = valp->IsNull(); + } else if (!jvp || jvp->IsNull()) { + jcol.Type = TYPE_UNKNOWN; + jcol.Len = jcol.Scale = 0; + jcol.Cbn = true; + } else if (j < lvl) { + if (!fmt[bf]) + strcat(fmt, colname); - p = fmt + strlen(fmt); - jsp = jvp->GetJson(); + p = fmt + strlen(fmt); + jsp = jvp->GetJson(); - switch (jsp->GetType()) { - case TYPE_JOB: - job = (PJOB)jsp; + switch (jsp->GetType()) { + case TYPE_JOB: + job = (PJOB)jsp; - for (PJPR jrp = job->GetFirst(); jrp; jrp = jrp->GetNext()) { - PCSZ k = jrp->GetKey(); + for (PJPR jrp = job->GetFirst(); jrp; jrp = jrp->GetNext()) { + PCSZ k = jrp->GetKey(); - if (*k != '$') { - strncat(strncat(fmt, sep, 128), k, 128); - strncat(strncat(colname, "_", 64), k, 64); - } // endif Key + if (*k != '$') { + strncat(strncat(fmt, sep, 128), k, 128); + strncat(strncat(colname, "_", 64), k, 64); + } // endif Key - if (Find(g, jrp->GetVal(), k, j + 1)) - return true; + if (Find(g, jrp->GetVal(), k, j + 1)) + return true; - *p = *pc = 0; - } // endfor jrp + *p = *pc = 0; + } // endfor jrp - return false; - case TYPE_JAR: - jar = (PJAR)jsp; + return false; + case TYPE_JAR: + jar = (PJAR)jsp; - if (all || (tdp->Xcol && !stricmp(tdp->Xcol, key))) - ars = jar->GetSize(false); - else - ars = MY_MIN(jar->GetSize(false), 1); + if (all || (tdp->Xcol && !stricmp(tdp->Xcol, key))) + ars = jar->GetSize(false); + else + ars = MY_MIN(jar->GetSize(false), 1); - for (int k = 0; k < ars; k++) { - if (!tdp->Xcol || stricmp(tdp->Xcol, key)) { - sprintf(buf, "%d", k); + for (int k = 0; k < ars; k++) { + if (!tdp->Xcol || stricmp(tdp->Xcol, key)) { + sprintf(buf, "%d", k); - if (tdp->Uri) - strncat(strncat(fmt, sep, 128), buf, 128); - else - strncat(strncat(strncat(fmt, "[", 128), buf, 128), "]", 128); + if (tdp->Uri) + strncat(strncat(fmt, sep, 128), buf, 128); + else + strncat(strncat(strncat(fmt, "[", 128), buf, 128), "]", 128); - if (all) - strncat(strncat(colname, "_", 64), buf, 64); + if (all) + strncat(strncat(colname, "_", 64), buf, 64); - } else - strncat(fmt, (tdp->Uri ? sep : "[*]"), 128); + } else + strncat(fmt, (tdp->Uri ? sep : "[*]"), 128); - if (Find(g, jar->GetValue(k), "", j)) - return true; + if (Find(g, jar->GetValue(k), "", j)) + return true; - *p = *pc = 0; - } // endfor k + *p = *pc = 0; + } // endfor k - return false; - default: - sprintf(g->Message, "Logical error after %s", fmt); - return true; - } // endswitch Type + return false; + default: + sprintf(g->Message, "Logical error after %s", fmt); + return true; + } // endswitch Type - } else if (lvl >= 0) { - jcol.Type = TYPE_STRING; - jcol.Len = 256; - jcol.Scale = 0; - jcol.Cbn = true; - } else - return false; + } else if (lvl >= 0) { + jcol.Type = TYPE_STRING; + jcol.Len = 256; + jcol.Scale = 0; + jcol.Cbn = true; + } else + return false; - AddColumn(g); - return false; -} // end of Find + AddColumn(g); + return false; +} // end of Find void JSONDISC::AddColumn(PGLOBAL g) { - bool b = fmt[bf] != 0; // True if formatted + bool b = fmt[bf] != 0; // True if formatted - // Check whether this column was already found - for (jcp = fjcp; jcp; jcp = jcp->Next) - if (!strcmp(colname, jcp->Name)) - break; + // Check whether this column was already found + for (jcp = fjcp; jcp; jcp = jcp->Next) + if (!strcmp(colname, jcp->Name)) + break; - if (jcp) { - if (jcp->Type != jcol.Type) { - if (jcp->Type == TYPE_UNKNOWN) - jcp->Type = jcol.Type; - else if (jcol.Type != TYPE_UNKNOWN) - jcp->Type = TYPE_STRING; + if (jcp) { + if (jcp->Type != jcol.Type) { + if (jcp->Type == TYPE_UNKNOWN) + jcp->Type = jcol.Type; + else if (jcol.Type != TYPE_UNKNOWN) + jcp->Type = TYPE_STRING; - } // endif Type + } // endif Type - if (b && (!jcp->Fmt || strlen(jcp->Fmt) < strlen(fmt))) { - jcp->Fmt = PlugDup(g, fmt); - length[7] = MY_MAX(length[7], strlen(fmt)); - } // endif fmt + if (b && (!jcp->Fmt || strlen(jcp->Fmt) < strlen(fmt))) { + jcp->Fmt = PlugDup(g, fmt); + length[7] = MY_MAX(length[7], strlen(fmt)); + } // endif fmt - jcp->Len = MY_MAX(jcp->Len, jcol.Len); - jcp->Scale = MY_MAX(jcp->Scale, jcol.Scale); - jcp->Cbn |= jcol.Cbn; - jcp->Found = true; - } else if (jcol.Type != TYPE_UNKNOWN || tdp->Accept) { - // New column - jcp = (PJCL)PlugSubAlloc(g, NULL, sizeof(JCOL)); - *jcp = jcol; - jcp->Cbn |= (i > 1); - jcp->Name = PlugDup(g, colname); - length[0] = MY_MAX(length[0], strlen(colname)); + jcp->Len = MY_MAX(jcp->Len, jcol.Len); + jcp->Scale = MY_MAX(jcp->Scale, jcol.Scale); + jcp->Cbn |= jcol.Cbn; + jcp->Found = true; + } else if (jcol.Type != TYPE_UNKNOWN || tdp->Accept) { + // New column + jcp = (PJCL)PlugSubAlloc(g, NULL, sizeof(JCOL)); + *jcp = jcol; + jcp->Cbn |= (i > 1); + jcp->Name = PlugDup(g, colname); + length[0] = MY_MAX(length[0], strlen(colname)); - if (b) { - jcp->Fmt = PlugDup(g, fmt); - length[7] = MY_MAX(length[7], strlen(fmt)); - } else - jcp->Fmt = NULL; + if (b) { + jcp->Fmt = PlugDup(g, fmt); + length[7] = MY_MAX(length[7], strlen(fmt)); + } else + jcp->Fmt = NULL; - if (pjcp) { - jcp->Next = pjcp->Next; - pjcp->Next = jcp; - } else - fjcp = jcp; + if (pjcp) { + jcp->Next = pjcp->Next; + pjcp->Next = jcp; + } else + fjcp = jcp; - n++; - } // endif jcp + n++; + } // endif jcp - if (jcp) - pjcp = jcp; + if (jcp) + pjcp = jcp; } // end of AddColumn @@ -548,13 +548,13 @@ JSONDEF::JSONDEF(void) Limit = 1; Base = 0; Strict = false; - Sep = '.'; - Uri = NULL; - Collname = Options = Filter = NULL; - Pipe = false; - Driver = NULL; - Version = 0; - Wrapname = NULL; + Sep = '.'; + Uri = NULL; + Collname = Options = Filter = NULL; + Pipe = false; + Driver = NULL; + Version = 0; + Wrapname = NULL; } // end of JSONDEF constructor /***********************************************************************/ @@ -562,41 +562,41 @@ JSONDEF::JSONDEF(void) /***********************************************************************/ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { - Schema = GetStringCatInfo(g, "DBname", Schema); - Jmode = (JMODE)GetIntCatInfo("Jmode", MODE_OBJECT); + Schema = GetStringCatInfo(g, "DBname", Schema); + Jmode = (JMODE)GetIntCatInfo("Jmode", MODE_OBJECT); Objname = GetStringCatInfo(g, "Object", NULL); Xcol = GetStringCatInfo(g, "Expand", NULL); Pretty = GetIntCatInfo("Pretty", 2); Limit = GetIntCatInfo("Limit", 10); Base = GetIntCatInfo("Base", 0) ? 1 : 0; - Sep = *GetStringCatInfo(g, "Separator", "."); - Accept = GetBoolCatInfo("Accept", false); + Sep = *GetStringCatInfo(g, "Separator", "."); + Accept = GetBoolCatInfo("Accept", false); - // Don't use url as MONGO uri when called from REST - if (stricmp(am, "REST") && (Uri = GetStringCatInfo(g, "Connect", NULL))) { + // Don't use url as MONGO uri when called from REST + if (stricmp(am, "REST") && (Uri = GetStringCatInfo(g, "Connect", NULL))) { #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) - Collname = GetStringCatInfo(g, "Name", - (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); - Collname = GetStringCatInfo(g, "Tabname", Collname); - Options = GetStringCatInfo(g, "Colist", NULL); - Filter = GetStringCatInfo(g, "Filter", NULL); - Pipe = GetBoolCatInfo("Pipeline", false); - Driver = GetStringCatInfo(g, "Driver", NULL); - Version = GetIntCatInfo("Version", 3); - Pretty = 0; + Collname = GetStringCatInfo(g, "Name", + (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); + Collname = GetStringCatInfo(g, "Tabname", Collname); + Options = GetStringCatInfo(g, "Colist", NULL); + Filter = GetStringCatInfo(g, "Filter", NULL); + Pipe = GetBoolCatInfo("Pipeline", false); + Driver = GetStringCatInfo(g, "Driver", NULL); + Version = GetIntCatInfo("Version", 3); + Pretty = 0; #if defined(JAVA_SUPPORT) - if (Version == 2) - Wrapname = GetStringCatInfo(g, "Wrapper", "Mongo2Interface"); - else - Wrapname = GetStringCatInfo(g, "Wrapper", "Mongo3Interface"); + if (Version == 2) + Wrapname = GetStringCatInfo(g, "Wrapper", "Mongo2Interface"); + else + Wrapname = GetStringCatInfo(g, "Wrapper", "Mongo3Interface"); #endif // JAVA_SUPPORT #else // !MONGO_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); - return true; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); + return true; #endif // !MONGO_SUPPORT - } // endif Uri + } // endif Uri - return DOSDEF::DefineAM(g, (Uri ? "XMGO" : "DOS"), poff); + return DOSDEF::DefineAM(g, (Uri ? "XMGO" : "DOS"), poff); } // end of DefineAM /***********************************************************************/ @@ -604,6 +604,9 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) /***********************************************************************/ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) { + if (trace(1)) + htrc("JSON GetTable Pretty=%d Uri=%s\n", Pretty, SVP(Uri)); + if (Catfunc == FNC_COL) return new(g)TDBJCL(this); @@ -618,47 +621,47 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) !(tmp == TMP_FORCE && (m == MODE_UPDATE || m == MODE_DELETE)); - if (Uri) { - if (Driver && toupper(*Driver) == 'C') { + if (Uri) { + if (Driver && toupper(*Driver) == 'C') { #if defined(CMGO_SUPPORT) - txfp = new(g) CMGFAM(this); + txfp = new(g) CMGFAM(this); #else - sprintf(g->Message, "Mongo %s Driver not available", "C"); - return NULL; + sprintf(g->Message, "Mongo %s Driver not available", "C"); + return NULL; #endif - } else if (Driver && toupper(*Driver) == 'J') { + } else if (Driver && toupper(*Driver) == 'J') { #if defined(JAVA_SUPPORT) - txfp = new(g) JMGFAM(this); + txfp = new(g) JMGFAM(this); #else - sprintf(g->Message, "Mongo %s Driver not available", "Java"); - return NULL; + sprintf(g->Message, "Mongo %s Driver not available", "Java"); + return NULL; #endif - } else { // Driver not specified + } else { // Driver not specified #if defined(CMGO_SUPPORT) - txfp = new(g) CMGFAM(this); + txfp = new(g) CMGFAM(this); #elif defined(JAVA_SUPPORT) - txfp = new(g) JMGFAM(this); -#else // !MONGO_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); - return NULL; + txfp = new(g) JMGFAM(this); +#else // !MONGO_SUPPORT + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); + return NULL; #endif // !MONGO_SUPPORT - } // endif Driver + } // endif Driver - } else if (Zipped) { + } else if (Zipped) { #if defined(ZIP_SUPPORT) - if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { - txfp = new(g) UNZFAM(this); - } else if (m == MODE_INSERT) { - txfp = new(g) ZIPFAM(this); - } else { - strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); - return NULL; - } // endif's m + if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { + txfp = new(g) UNZFAM(this); + } else if (m == MODE_INSERT) { + txfp = new(g) ZIPFAM(this); + } else { + strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); + return NULL; + } // endif's m #else // !ZIP_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); - return NULL; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); + return NULL; #endif // !ZIP_SUPPORT - } else if (Compressed) { + } else if (Compressed) { #if defined(GZ_SUPPORT) if (Compressed == 1) txfp = new(g) GZFAM(this); @@ -668,7 +671,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "GZ"); return NULL; #endif // !GZ_SUPPORT - } else if (map) + } else if (map) txfp = new(g) MAPFAM(this); else txfp = new(g) DOSFAM(this); @@ -676,41 +679,41 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) // Txfp must be set for TDBDOS tdbp = new(g) TDBJSN(this, txfp); - if (Lrecl) { - // Allocate the parse work memory - PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); - memset(G, 0, sizeof(GLOBAL)); - G->Sarea_Size = Lrecl * 10; - G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size); - PlugSubSet(G->Sarea, G->Sarea_Size); - G->jump_level = 0; - ((TDBJSN*)tdbp)->G = G; - } else { - strcpy(g->Message, "LRECL is not defined"); - return NULL; - } // endif Lrecl + if (Lrecl) { + // Allocate the parse work memory + PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); + memset(G, 0, sizeof(GLOBAL)); + G->Sarea_Size = Lrecl * 10; + G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size); + PlugSubSet(G->Sarea, G->Sarea_Size); + G->jump_level = 0; + ((TDBJSN*)tdbp)->G = G; + } else { + strcpy(g->Message, "LRECL is not defined"); + return NULL; + } // endif Lrecl - } else { - if (Zipped) { + } else { + if (Zipped) { #if defined(ZIP_SUPPORT) - if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { - txfp = new(g) UNZFAM(this); - } else if (m == MODE_INSERT) { - strcpy(g->Message, "INSERT supported only for zipped JSON when pretty=0"); - return NULL; - } else { - strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); - return NULL; - } // endif's m + if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { + txfp = new(g) UNZFAM(this); + } else if (m == MODE_INSERT) { + strcpy(g->Message, "INSERT supported only for zipped JSON when pretty=0"); + return NULL; + } else { + strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); + return NULL; + } // endif's m #else // !ZIP_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); - return NULL; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); + return NULL; #endif // !ZIP_SUPPORT - } else - txfp = new(g) MAPFAM(this); + } else + txfp = new(g) MAPFAM(this); tdbp = new(g) TDBJSON(this, txfp); - ((TDBJSON*)tdbp)->G = g; + ((TDBJSON*)tdbp)->G = g; } // endif Pretty if (Multiple) @@ -738,16 +741,16 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp) Limit = tdp->Limit; Pretty = tdp->Pretty; B = tdp->Base ? 1 : 0; - Sep = tdp->Sep; + Sep = tdp->Sep; Strict = tdp->Strict; } else { Jmode = MODE_OBJECT; Objname = NULL; - Xcol = NULL; + Xcol = NULL; Limit = 1; Pretty = 0; B = 0; - Sep = '.'; + Sep = '.'; Strict = false; } // endif tdp @@ -761,7 +764,7 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp) TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) { - G = NULL; + G = NULL; Top = tdbp->Top; Row = tdbp->Row; Val = tdbp->Val; @@ -777,7 +780,7 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) SameRow = tdbp->SameRow; Xval = tdbp->Xval; B = tdbp->B; - Sep = tdbp->Sep; + Sep = tdbp->Sep; Pretty = tdbp->Pretty; Strict = tdbp->Strict; Comma = tdbp->Comma; @@ -786,7 +789,7 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) // Used for update PTDB TDBJSN::Clone(PTABS t) { - G = NULL; + G = NULL; PTDB tp; PJCOL cp1, cp2; PGLOBAL g = t->G; @@ -860,33 +863,33 @@ PJSON TDBJSN::FindRow(PGLOBAL g) PJSON jsp = Row; PJVAL val = NULL; - for (objpath = PlugDup(g, Objname); jsp && objpath; objpath = p) { - if ((p = strchr(objpath, Sep))) - *p++ = 0; + for (objpath = PlugDup(g, Objname); jsp && objpath; objpath = p) { + if ((p = strchr(objpath, Sep))) + *p++ = 0; - if (*objpath != '[' && !IsNum(objpath)) { // objpass is a key - val = (jsp->GetType() == TYPE_JOB) ? - jsp->GetObject()->GetValue(objpath) : NULL; - } else { - if (*objpath == '[') { - if (objpath[strlen(objpath) - 1] == ']') - objpath++; - else - return NULL; - } // endif [ + if (*objpath != '[' && !IsNum(objpath)) { // objpass is a key + val = (jsp->GetType() == TYPE_JOB) ? + jsp->GetObject()->GetValue(objpath) : NULL; + } else { + if (*objpath == '[') { + if (objpath[strlen(objpath) - 1] == ']') + objpath++; + else + return NULL; + } // endif [ - val = (jsp->GetType() == TYPE_JAR) ? - jsp->GetArray()->GetValue(atoi(objpath) - B) : NULL; - } // endif objpath + val = (jsp->GetType() == TYPE_JAR) ? + jsp->GetArray()->GetValue(atoi(objpath) - B) : NULL; + } // endif objpath - jsp = (val) ? val->GetJson() : NULL; - } // endfor objpath + jsp = (val) ? val->GetJson() : NULL; + } // endfor objpath return jsp; } // end of FindRow /***********************************************************************/ -/* OpenDB: Data Base open routine for JSN access method. */ +/* OpenDB: Data Base open routine for JSN access method. */ /***********************************************************************/ bool TDBJSN::OpenDB(PGLOBAL g) { @@ -911,15 +914,15 @@ bool TDBJSN::OpenDB(PGLOBAL g) return true; } // endswitch Jmode - } // endif Use + } // endif Use - if (TDBDOS::OpenDB(g)) - return true; + if (TDBDOS::OpenDB(g)) + return true; - if (Xcol) - To_Filter = NULL; // Imcompatible + if (Xcol) + To_Filter = NULL; // Imcompatible - return false; + return false; } // end of OpenDB /***********************************************************************/ @@ -969,27 +972,27 @@ int TDBJSN::ReadDB(PGLOBAL g) NextSame = 0; M++; return RC_OK; - } else if ((rc = TDBDOS::ReadDB(g)) == RC_OK) { - if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) - // Deferred reading failed - return rc; + } else if ((rc = TDBDOS::ReadDB(g)) == RC_OK) { + if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) + // Deferred reading failed + return rc; - // Recover the memory used for parsing - PlugSubSet(G->Sarea, G->Sarea_Size); + // Recover the memory used for parsing + PlugSubSet(G->Sarea, G->Sarea_Size); - if ((Row = ParseJson(G, To_Line, strlen(To_Line), &Pretty, &Comma))) { - Row = FindRow(g); - SameRow = 0; - Fpos++; - M = 1; - rc = RC_OK; - } else if (Pretty != 1 || strcmp(To_Line, "]")) { - strcpy(g->Message, G->Message); - rc = RC_FX; - } else - rc = RC_EF; + if ((Row = ParseJson(G, To_Line, strlen(To_Line), &Pretty, &Comma))) { + Row = FindRow(g); + SameRow = 0; + Fpos++; + M = 1; + rc = RC_OK; + } else if (Pretty != 1 || strcmp(To_Line, "]")) { + strcpy(g->Message, G->Message); + rc = RC_FX; + } else + rc = RC_EF; - } // endif ReadDB + } // endif ReadDB return rc; } // end of ReadDB @@ -999,68 +1002,68 @@ int TDBJSN::ReadDB(PGLOBAL g) /***********************************************************************/ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) { - if (Objname) { - if (!Val) { - // Parse and allocate Objname item(s) - char *p; - char *objpath = PlugDup(g, Objname); - int i; - PJOB objp; - PJAR arp; - PJVAL val = NULL; + if (Objname) { + if (!Val) { + // Parse and allocate Objname item(s) + char *p; + char *objpath = PlugDup(g, Objname); + int i; + PJOB objp; + PJAR arp; + PJVAL val = NULL; - Top = NULL; + Top = NULL; - for (; objpath; objpath = p) { - if ((p = strchr(objpath, Sep))) - *p++ = 0; + for (; objpath; objpath = p) { + if ((p = strchr(objpath, Sep))) + *p++ = 0; - if (*objpath != '[' && !IsNum(objpath)) { - objp = new(g) JOBJECT; + if (*objpath != '[' && !IsNum(objpath)) { + objp = new(g) JOBJECT; - if (!Top) - Top = objp; + if (!Top) + Top = objp; - if (val) - val->SetValue(objp); + if (val) + val->SetValue(objp); - val = new(g) JVALUE; - objp->SetValue(g, val, objpath); - } else { - if (*objpath == '[') { - // Old style - if (objpath[strlen(objpath) - 1] != ']') { - sprintf(g->Message, "Invalid Table path %s", Objname); - return RC_FX; - } else - objpath++; + val = new(g) JVALUE; + objp->SetValue(g, val, objpath); + } else { + if (*objpath == '[') { + // Old style + if (objpath[strlen(objpath) - 1] != ']') { + sprintf(g->Message, "Invalid Table path %s", Objname); + return RC_FX; + } else + objpath++; - } // endif objpath + } // endif objpath - arp = new(g) JARRAY; + arp = new(g) JARRAY; - if (!Top) - Top = arp; + if (!Top) + Top = arp; - if (val) - val->SetValue(arp); + if (val) + val->SetValue(arp); - val = new(g) JVALUE; - i = atoi(objpath) - B; - arp->SetValue(g, val, i); - arp->InitArray(g); - } // endif objpath + val = new(g) JVALUE; + i = atoi(objpath) - B; + arp->SetValue(g, val, i); + arp->InitArray(g); + } // endif objpath - } // endfor p + } // endfor p - Val = val; - } // endif Val + Val = val; + } // endif Val - Val->SetValue(jsp); - } else - Top = jsp; + Val->SetValue(jsp); + } else + Top = jsp; - return RC_OK; + return RC_OK; } // end of MakeTopTree /***********************************************************************/ @@ -1095,11 +1098,11 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) /***********************************************************************/ int TDBJSN::WriteDB(PGLOBAL g) { - int rc = TDBDOS::WriteDB(g); + int rc = TDBDOS::WriteDB(g); - PlugSubSet(G->Sarea, G->Sarea_Size); - Row->Clear(); - return rc; + PlugSubSet(G->Sarea, G->Sarea_Size); + Row->Clear(); + return rc; } // end of WriteDB /* ---------------------------- JSONCOL ------------------------------ */ @@ -1111,12 +1114,12 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) : DOSCOL(g, cdp, tdbp, cprec, i, "DOS") { Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); - G = Tjp->G; + G = Tjp->G; Jpath = cdp->GetFmt(); MulVal = NULL; Nodes = NULL; Nod = 0; - Sep = Tjp->Sep; + Sep = Tjp->Sep; Xnod = -1; Xpd = false; Parsed = false; @@ -1128,14 +1131,14 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) /***********************************************************************/ JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp) { - G = col1->G; + G = col1->G; Tjp = col1->Tjp; Jpath = col1->Jpath; MulVal = col1->MulVal; Nodes = col1->Nodes; Nod = col1->Nod; - Sep = col1->Sep; - Xnod = col1->Xnod; + Sep = col1->Sep; + Xnod = col1->Xnod; Xpd = col1->Xpd; Parsed = col1->Parsed; } // end of JSONCOL copy constructor @@ -1153,7 +1156,7 @@ bool JSONCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) return true; Tjp = (TDBJSN*)To_Tdb; - G = Tjp->G; + G = Tjp->G; return false; } // end of SetBuffer @@ -1179,130 +1182,130 @@ bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b) /***********************************************************************/ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) { - int n; - bool dg = true, b = false; - PJNODE jnp = &Nodes[i]; + int n; + bool dg = true, b = false; + PJNODE jnp = &Nodes[i]; - //if (*p == '[') p++; // Old syntax .[ or :[ - n = (int)strlen(p); + //if (*p == '[') p++; // Old syntax .[ or :[ + n = (int)strlen(p); - if (*p) { - if (p[n - 1] == ']') { - p[--n] = 0; - } else if (!IsNum(p)) { - // Wrong array specification - sprintf(g->Message, "Invalid array specification %s for %s", p, Name); - return true; - } // endif p + if (*p) { + if (p[n - 1] == ']') { + p[--n] = 0; + } else if (!IsNum(p)) { + // Wrong array specification + sprintf(g->Message, "Invalid array specification %s for %s", p, Name); + return true; + } // endif p - } else - b = true; + } else + b = true; - // To check whether a numeric Rank was specified - dg = IsNum(p); + // To check whether a numeric Rank was specified + dg = IsNum(p); - if (!n) { - // Default specifications - if (CheckExpand(g, i, nm, false)) - return true; - else if (jnp->Op != OP_EXP) { - if (b) { - // Return 1st value (B is the index base) - jnp->Rank = Tjp->B; - jnp->Op = OP_EQ; - } else if (!Value->IsTypeNum()) { - jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING); - jnp->Op = OP_CNC; - } else - jnp->Op = OP_ADD; + if (!n) { + // Default specifications + if (CheckExpand(g, i, nm, false)) + return true; + else if (jnp->Op != OP_EXP) { + if (b) { + // Return 1st value (B is the index base) + jnp->Rank = Tjp->B; + jnp->Op = OP_EQ; + } else if (!Value->IsTypeNum()) { + jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING); + jnp->Op = OP_CNC; + } else + jnp->Op = OP_ADD; - } // endif OP + } // endif OP - } else if (dg) { - // Return nth value - jnp->Rank = atoi(p) - Tjp->B; - jnp->Op = OP_EQ; - } else if (n == 1) { - // Set the Op value; - if (Sep == ':') - switch (*p) { - case '*': *p = 'x'; break; - case 'x': - case 'X': *p = '*'; break; // Expand this array - default: break; - } // endswitch p + } else if (dg) { + // Return nth value + jnp->Rank = atoi(p) - Tjp->B; + jnp->Op = OP_EQ; + } else if (n == 1) { + // Set the Op value; + if (Sep == ':') + switch (*p) { + case '*': *p = 'x'; break; + case 'x': + case 'X': *p = '*'; break; // Expand this array + default: break; + } // endswitch p - switch (*p) { - case '+': jnp->Op = OP_ADD; break; - case 'x': jnp->Op = OP_MULT; break; - case '>': jnp->Op = OP_MAX; break; - case '<': jnp->Op = OP_MIN; break; - case '!': jnp->Op = OP_SEP; break; // Average - case '#': jnp->Op = OP_NUM; break; - case '*': // Expand this array - if (!Tjp->Xcol && nm) { - Xpd = true; - jnp->Op = OP_EXP; - Tjp->Xval = i; - Tjp->Xcol = nm; - } else if (CheckExpand(g, i, nm, true)) - return true; + switch (*p) { + case '+': jnp->Op = OP_ADD; break; + case 'x': jnp->Op = OP_MULT; break; + case '>': jnp->Op = OP_MAX; break; + case '<': jnp->Op = OP_MIN; break; + case '!': jnp->Op = OP_SEP; break; // Average + case '#': jnp->Op = OP_NUM; break; + case '*': // Expand this array + if (!Tjp->Xcol && nm) { + Xpd = true; + jnp->Op = OP_EXP; + Tjp->Xval = i; + Tjp->Xcol = nm; + } else if (CheckExpand(g, i, nm, true)) + return true; - break; - default: - sprintf(g->Message, - "Invalid function specification %c for %s", *p, Name); - return true; - } // endswitch *p + break; + default: + sprintf(g->Message, + "Invalid function specification %c for %s", *p, Name); + return true; + } // endswitch *p - } else if (*p == '"' && p[n - 1] == '"') { - // This is a concat specification - jnp->Op = OP_CNC; + } else if (*p == '"' && p[n - 1] == '"') { + // This is a concat specification + jnp->Op = OP_CNC; - if (n > 2) { - // Set concat intermediate string - p[n - 1] = 0; - jnp->CncVal = AllocateValue(g, p + 1, TYPE_STRING); - } // endif n + if (n > 2) { + // Set concat intermediate string + p[n - 1] = 0; + jnp->CncVal = AllocateValue(g, p + 1, TYPE_STRING); + } // endif n - } else { - sprintf(g->Message, "Wrong array specification for %s", Name); - return true; - } // endif's + } else { + sprintf(g->Message, "Wrong array specification for %s", Name); + return true; + } // endif's - // For calculated arrays, a local Value must be used - switch (jnp->Op) { - case OP_NUM: - jnp->Valp = AllocateValue(g, TYPE_INT); - break; - case OP_ADD: - case OP_MULT: - case OP_SEP: - if (!IsTypeChar(Buf_Type)) - jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision()); - else - jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2); + // For calculated arrays, a local Value must be used + switch (jnp->Op) { + case OP_NUM: + jnp->Valp = AllocateValue(g, TYPE_INT); + break; + case OP_ADD: + case OP_MULT: + case OP_SEP: + if (!IsTypeChar(Buf_Type)) + jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision()); + else + jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2); - break; - case OP_MIN: - case OP_MAX: - jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision()); - break; - case OP_CNC: - if (IsTypeChar(Buf_Type)) - jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision()); - else - jnp->Valp = AllocateValue(g, TYPE_STRING, 512); + break; + case OP_MIN: + case OP_MAX: + jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision()); + break; + case OP_CNC: + if (IsTypeChar(Buf_Type)) + jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision()); + else + jnp->Valp = AllocateValue(g, TYPE_STRING, 512); - break; - default: - break; - } // endswitch Op + break; + default: + break; + } // endswitch Op - if (jnp->Valp) - MulVal = AllocateValue(g, jnp->Valp); + if (jnp->Valp) + MulVal = AllocateValue(g, jnp->Valp); - return false; + return false; } // end of SetArrayOptions /***********************************************************************/ @@ -1313,87 +1316,87 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) /***********************************************************************/ bool JSONCOL::ParseJpath(PGLOBAL g) { - char *p, *p1 = NULL, *p2 = NULL, *pbuf = NULL; - int i; - bool a, mul = false; + char *p, *p1 = NULL, *p2 = NULL, *pbuf = NULL; + int i; + bool a, mul = false; - if (Parsed) - return false; // Already done - else if (InitValue(g)) - return true; - else if (!Jpath) - Jpath = Name; + if (Parsed) + return false; // Already done + else if (InitValue(g)) + return true; + else if (!Jpath) + Jpath = Name; - if (To_Tdb->GetOrig()) { - // This is an updated column, get nodes from origin - for (PJCOL colp = (PJCOL)Tjp->GetColumns(); colp; - colp = (PJCOL)colp->GetNext()) - if (!stricmp(Name, colp->GetName())) { - Nod = colp->Nod; - Nodes = colp->Nodes; - Xpd = colp->Xpd; - goto fin; - } // endif Name + if (To_Tdb->GetOrig()) { + // This is an updated column, get nodes from origin + for (PJCOL colp = (PJCOL)Tjp->GetColumns(); colp; + colp = (PJCOL)colp->GetNext()) + if (!stricmp(Name, colp->GetName())) { + Nod = colp->Nod; + Nodes = colp->Nodes; + Xpd = colp->Xpd; + goto fin; + } // endif Name - sprintf(g->Message, "Cannot parse updated column %s", Name); - return true; - } // endif To_Orig + sprintf(g->Message, "Cannot parse updated column %s", Name); + return true; + } // endif To_Orig - pbuf = PlugDup(g, Jpath); - if (*pbuf == '$') pbuf++; - if (*pbuf == Sep) pbuf++; - if (*pbuf == '[') p1 = pbuf++; + pbuf = PlugDup(g, Jpath); + if (*pbuf == '$') pbuf++; + if (*pbuf == Sep) pbuf++; + if (*pbuf == '[') p1 = pbuf++; - // Estimate the required number of nodes - for (i = 0, p = pbuf; (p = NextChr(p, Sep)); i++, p++) - Nod++; // One path node found + // Estimate the required number of nodes + for (i = 0, p = pbuf; (p = NextChr(p, Sep)); i++, p++) + Nod++; // One path node found - Nodes = (PJNODE)PlugSubAlloc(g, NULL, (++Nod) * sizeof(JNODE)); - memset(Nodes, 0, (Nod) * sizeof(JNODE)); + Nodes = (PJNODE)PlugSubAlloc(g, NULL, (++Nod) * sizeof(JNODE)); + memset(Nodes, 0, (Nod) * sizeof(JNODE)); - // Analyze the Jpath for this column - for (i = 0, p = pbuf; p && i < Nod; i++, p = (p2 ? p2 : NULL)) { - a = (p1 != NULL); - p1 = strchr(p, '['); - p2 = strchr(p, Sep); + // Analyze the Jpath for this column + for (i = 0, p = pbuf; p && i < Nod; i++, p = (p2 ? p2 : NULL)) { + a = (p1 != NULL); + p1 = strchr(p, '['); + p2 = strchr(p, Sep); - if (!p2) - p2 = p1; - else if (p1) { - if (p1 < p2) - p2 = p1; - else if (p1 == p2 + 1) - *p2++ = 0; // Old syntax .[ or :[ - else - p1 = NULL; + if (!p2) + p2 = p1; + else if (p1) { + if (p1 < p2) + p2 = p1; + else if (p1 == p2 + 1) + *p2++ = 0; // Old syntax .[ or :[ + else + p1 = NULL; - } // endif p1 + } // endif p1 - if (p2) - *p2++ = 0; + if (p2) + *p2++ = 0; - // Jpath must be explicit - if (a || *p == 0 || *p == '[' || IsNum(p)) { - // Analyse intermediate array processing - if (SetArrayOptions(g, p, i, Nodes[i - 1].Key)) - return true; + // Jpath must be explicit + if (a || *p == 0 || *p == '[' || IsNum(p)) { + // Analyse intermediate array processing + if (SetArrayOptions(g, p, i, Nodes[i - 1].Key)) + return true; - } else if (*p == '*') { - // Return JSON - Nodes[i].Op = OP_XX; - } else { - Nodes[i].Key = p; - Nodes[i].Op = OP_EXIST; - } // endif's + } else if (*p == '*') { + // Return JSON + Nodes[i].Op = OP_XX; + } else { + Nodes[i].Key = p; + Nodes[i].Op = OP_EXIST; + } // endif's - } // endfor i, p + } // endfor i, p - Nod = i; + Nod = i; fin: - MulVal = AllocateValue(g, Value); - Parsed = true; - return false; + MulVal = AllocateValue(g, Value); + Parsed = true; + return false; } // end of ParseJpath /***********************************************************************/ @@ -1401,66 +1404,66 @@ fin: /***********************************************************************/ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj) { - if (Jpath) { - char *p1, *p2, *mgopath; - int i = 0; + if (Jpath) { + char *p1, *p2, *mgopath; + int i = 0; - if (strcmp(Jpath, "*")) { - p1 = Jpath; - if (*p1 == '$') p1++; - if (*p1 == '.') p1++; - mgopath = PlugDup(g, p1); - } else - return NULL; + if (strcmp(Jpath, "*")) { + p1 = Jpath; + if (*p1 == '$') p1++; + if (*p1 == '.') p1++; + mgopath = PlugDup(g, p1); + } else + return NULL; - for (p1 = p2 = mgopath; *p1; p1++) - if (i) { // Inside [] - if (isdigit(*p1)) { - if (!proj) - *p2++ = *p1; + for (p1 = p2 = mgopath; *p1; p1++) + if (i) { // Inside [] + if (isdigit(*p1)) { + if (!proj) + *p2++ = *p1; - } else if (*p1 == ']' && i == 1) { - if (proj && p1[1] == '.') - p1++; + } else if (*p1 == ']' && i == 1) { + if (proj && p1[1] == '.') + p1++; - i = 0; - } else if (*p1 == '.' && i == 2) { - if (!proj) - *p2++ = '.'; + i = 0; + } else if (*p1 == '.' && i == 2) { + if (!proj) + *p2++ = '.'; - i = 0; - } else if (!proj) - return NULL; - - } else switch (*p1) { - case ':': - case '.': - if (isdigit(p1[1])) - i = 2; + i = 0; + } else if (!proj) + return NULL; - *p2++ = '.'; - break; - case '[': - if (*(p2 - 1) != '.') - *p2++ = '.'; + } else switch (*p1) { + case ':': + case '.': + if (isdigit(p1[1])) + i = 2; - i = 1; - break; - case '*': - if (*(p2 - 1) == '.' && !*(p1 + 1)) { - p2--; // Suppress last :* - break; - } // endif p2 + *p2++ = '.'; + break; + case '[': + if (*(p2 - 1) != '.') + *p2++ = '.'; - default: - *p2++ = *p1; - break; - } // endswitch p1; + i = 1; + break; + case '*': + if (*(p2 - 1) == '.' && !*(p1 + 1)) { + p2--; // Suppress last :* + break; + } // endif p2 - *p2 = 0; - return mgopath; - } else - return NULL; + default: + *p2++ = *p1; + break; + } // endswitch p1; + + *p2 = 0; + return mgopath; + } else + return NULL; } // end of GetJpath @@ -1469,7 +1472,7 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj) /***********************************************************************/ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp) { - if (Value->IsTypeNum()) { + if (Value->IsTypeNum()) { strcpy(g->Message, "Cannot make Json for a numeric column"); Value->Reset(); } else @@ -1484,22 +1487,22 @@ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp) void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) { if (val) { - vp->SetNull(false); + vp->SetNull(false); switch (val->GetValType()) { case TYPE_STRG: case TYPE_INTG: - case TYPE_BINT: - case TYPE_DBL: - case TYPE_DTM: - vp->SetValue_pval(val->GetValue()); + case TYPE_BINT: + case TYPE_DBL: + case TYPE_DTM: + vp->SetValue_pval(val->GetValue()); break; case TYPE_BOOL: if (vp->IsTypeNum()) vp->SetValue(val->GetInteger() ? 1 : 0); else vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false")); - + break; case TYPE_JAR: SetJsonValue(g, vp, val->GetArray()->GetValue(0), n); @@ -1509,16 +1512,16 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) vp->SetValue_psz(val->GetObject()->GetText(g, NULL)); break; // } // endif Type - - default: - vp->Reset(); - vp->SetNull(true); - } // endswitch Type - } else { - vp->Reset(); - vp->SetNull(true); - } // endif val + default: + vp->Reset(); + vp->SetNull(true); + } // endswitch Type + + } else { + vp->Reset(); + vp->SetNull(true); + } // endif val } // end of SetJsonValue @@ -1530,8 +1533,8 @@ void JSONCOL::ReadColumn(PGLOBAL g) if (!Tjp->SameRow || Xnod >= Tjp->SameRow) Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0)); - if (Xpd && Value->IsNull() && !((PJDEF)Tjp->To_Def)->Accept) - throw("Null expandable JSON value"); + if (Xpd && Value->IsNull() && !((PJDEF)Tjp->To_Def)->Accept) + throw("Null expandable JSON value"); // Set null when applicable if (!Nullable) @@ -1579,11 +1582,11 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i) else return CalculateArray(g, arp, i); - } else { - // Unexpected array, unwrap it as [0] - val = arp->GetValue(0); - i--; - } // endif's + } else { + // Unexpected array, unwrap it as [0] + val = arp->GetValue(0); + i--; + } // endif's break; case TYPE_JVAL: @@ -1612,17 +1615,17 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n) PJVAL jvp; JVALUE jval; - if (!ars) { - Value->Reset(); - Value->SetNull(true); - Tjp->NextSame = 0; - return Value; - } // endif ars + if (!ars) { + Value->Reset(); + Value->SetNull(true); + Tjp->NextSame = 0; + return Value; + } // endif ars if (!(jvp = arp->GetValue((Nodes[n].Rx = Nodes[n].Nx)))) { strcpy(g->Message, "Logical error expanding array"); - throw 666; - } // endif jvp + throw 666; + } // endif jvp if (n < Nod - 1 && jvp->GetJson()) { jval.SetValue(GetColumnValue(g, jvp->GetJson(), n + 1)); @@ -1637,7 +1640,7 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n) Xnod = n; Tjp->NextSame = Xnod; - } // endif NextSame + } // endif NextSame SetJsonValue(g, Value, jvp, n); return Value; @@ -1648,58 +1651,58 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n) /***********************************************************************/ PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n) { - int i, ars, nv = 0, nextsame = Tjp->NextSame; - bool err; + int i, ars, nv = 0, nextsame = Tjp->NextSame; + bool err; OPVAL op = Nodes[n].Op; PVAL val[2], vp = Nodes[n].Valp; PJVAL jvrp, jvp; JVALUE jval; vp->Reset(); - ars = MY_MIN(Tjp->Limit, arp->size()); + ars = MY_MIN(Tjp->Limit, arp->size()); - if (trace(1)) - htrc("CalculateArray: size=%d op=%d nextsame=%d\n", - ars, op, nextsame); + if (trace(1)) + htrc("CalculateArray: size=%d op=%d nextsame=%d\n", + ars, op, nextsame); - for (i = 0; i < ars; i++) { - jvrp = arp->GetValue(i); + for (i = 0; i < ars; i++) { + jvrp = arp->GetValue(i); - if (trace(1)) - htrc("i=%d nv=%d\n", i, nv); + if (trace(1)) + htrc("i=%d nv=%d\n", i, nv); - if (!jvrp->IsNull() || (op == OP_CNC && GetJsonNull())) do { - if (jvrp->IsNull()) { - jvrp->Value = AllocateValue(g, GetJsonNull(), TYPE_STRING); - jvp = jvrp; - } else if (n < Nod - 1 && jvrp->GetJson()) { + if (!jvrp->IsNull() || (op == OP_CNC && GetJsonNull())) do { + if (jvrp->IsNull()) { + jvrp->Value = AllocateValue(g, GetJsonNull(), TYPE_STRING); + jvp = jvrp; + } else if (n < Nod - 1 && jvrp->GetJson()) { Tjp->NextSame = nextsame; jval.SetValue(GetColumnValue(g, jvrp->GetJson(), n + 1)); jvp = &jval; } else jvp = jvrp; - - if (trace(1)) - htrc("jvp=%s null=%d\n", - jvp->GetString(g), jvp->IsNull() ? 1 : 0); - if (!nv++) { + if (trace(1)) + htrc("jvp=%s null=%d\n", + jvp->GetString(g), jvp->IsNull() ? 1 : 0); + + if (!nv++) { SetJsonValue(g, vp, jvp, n); continue; } else SetJsonValue(g, MulVal, jvp, n); - if (!MulVal->IsNull()) { - switch (op) { + if (!MulVal->IsNull()) { + switch (op) { case OP_CNC: if (Nodes[n].CncVal) { val[0] = Nodes[n].CncVal; err = vp->Compute(g, val, 1, op); } // endif CncVal - + val[0] = MulVal; err = vp->Compute(g, val, 1, op); - break; + break; // case OP_NUM: case OP_SEP: val[0] = Nodes[n].Valp; @@ -1714,16 +1717,16 @@ PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n) if (err) vp->Reset(); - - if (trace(1)) { - char buf(32); - htrc("vp='%s' err=%d\n", - vp->GetCharString(&buf), err ? 1 : 0); + if (trace(1)) { + char buf(32); - } // endif trace + htrc("vp='%s' err=%d\n", + vp->GetCharString(&buf), err ? 1 : 0); - } // endif Null + } // endif trace + + } // endif Null } while (Tjp->NextSame > nextsame); @@ -1753,8 +1756,8 @@ PJSON JSONCOL::GetRow(PGLOBAL g) PJAR arp; PJSON nwr, row = Tjp->Row; - for (int i = 0; i < Nod && row; i++) { - if (Nodes[i+1].Op == OP_XX) + for (int i = 0; i < Nod && row; i++) { + if (Nodes[i+1].Op == OP_XX) break; else switch (row->GetType()) { case TYPE_JOB: @@ -1765,19 +1768,19 @@ PJSON JSONCOL::GetRow(PGLOBAL g) val = ((PJOB)row)->GetValue(Nodes[i].Key); break; case TYPE_JAR: - arp = (PJAR)row; + arp = (PJAR)row; - if (!Nodes[i].Key) { + if (!Nodes[i].Key) { if (Nodes[i].Op == OP_EQ) val = arp->GetValue(Nodes[i].Rank); else val = arp->GetValue(Nodes[i].Rx); } else { - // Unexpected array, unwrap it as [0] - val = arp->GetValue(0); - i--; - } // endif Nodes + // Unexpected array, unwrap it as [0] + val = arp->GetValue(0); + i--; + } // endif Nodes break; case TYPE_JVAL: @@ -1827,10 +1830,10 @@ PJSON JSONCOL::GetRow(PGLOBAL g) /***********************************************************************/ void JSONCOL::WriteColumn(PGLOBAL g) { - if (Xpd && Tjp->Pretty < 2) { - strcpy(g->Message, "Cannot write expanded column when Pretty is not 2"); - throw 666; - } // endif Xpd + if (Xpd && Tjp->Pretty < 2) { + strcpy(g->Message, "Cannot write expanded column when Pretty is not 2"); + throw 666; + } // endif Xpd /*********************************************************************/ /* Check whether this node must be written. */ @@ -1864,8 +1867,8 @@ void JSONCOL::WriteColumn(PGLOBAL g) if (!(jsp = ParseJson(G, s, (int)strlen(s)))) { strcpy(g->Message, s); - throw 666; - } // endif jsp + throw 666; + } // endif jsp if (arp) { if (Nod > 1 && Nodes[Nod-2].Op == OP_EQ) @@ -1887,10 +1890,10 @@ void JSONCOL::WriteColumn(PGLOBAL g) // fall through case TYPE_DATE: case TYPE_INT: - case TYPE_TINY: - case TYPE_SHORT: - case TYPE_BIGINT: - case TYPE_DOUBLE: + case TYPE_TINY: + case TYPE_SHORT: + case TYPE_BIGINT: + case TYPE_DOUBLE: if (arp) { if (Nodes[Nod-1].Op == OP_EQ) arp->SetValue(G, new(G) JVALUE(G, Value), Nodes[Nod-1].Rank); @@ -1981,7 +1984,7 @@ int TDBJSON::MakeDocument(PGLOBAL g) return RC_OK; /*********************************************************************/ - /* Create the mapping file object in mode read. */ + /* Create the mapping file object in mode read. */ /*********************************************************************/ Mode = MODE_READ; @@ -2010,70 +2013,70 @@ int TDBJSON::MakeDocument(PGLOBAL g) if (!jsp && g->Message[0]) return RC_FX; - if ((objpath = PlugDup(g, Objname))) { - if (*objpath == '$') objpath++; - if (*objpath == '.') objpath++; + if ((objpath = PlugDup(g, Objname))) { + if (*objpath == '$') objpath++; + if (*objpath == '.') objpath++; - /*********************************************************************/ - /* Find the table in the tree structure. */ - /*********************************************************************/ - for (; jsp && objpath; objpath = p) { - if ((p = strchr(objpath, Sep))) - *p++ = 0; + /*********************************************************************/ + /* Find the table in the tree structure. */ + /*********************************************************************/ + for (; jsp && objpath; objpath = p) { + if ((p = strchr(objpath, Sep))) + *p++ = 0; - if (*objpath != '[' && !IsNum(objpath)) { - // objpass is a key - if (jsp->GetType() != TYPE_JOB) { - strcpy(g->Message, "Table path does not match the json file"); - return RC_FX; - } // endif Type + if (*objpath != '[' && !IsNum(objpath)) { + // objpass is a key + if (jsp->GetType() != TYPE_JOB) { + strcpy(g->Message, "Table path does not match the json file"); + return RC_FX; + } // endif Type - key = objpath; - objp = jsp->GetObject(); - arp = NULL; - val = objp->GetValue(key); + key = objpath; + objp = jsp->GetObject(); + arp = NULL; + val = objp->GetValue(key); - if (!val || !(jsp = val->GetJson())) { - sprintf(g->Message, "Cannot find object key %s", key); - return RC_FX; - } // endif val + if (!val || !(jsp = val->GetJson())) { + sprintf(g->Message, "Cannot find object key %s", key); + return RC_FX; + } // endif val - } else { - if (*objpath == '[') { - // Old style - if (objpath[strlen(objpath) - 1] != ']') { - sprintf(g->Message, "Invalid Table path %s", Objname); - return RC_FX; - } else - objpath++; + } else { + if (*objpath == '[') { + // Old style + if (objpath[strlen(objpath) - 1] != ']') { + sprintf(g->Message, "Invalid Table path %s", Objname); + return RC_FX; + } else + objpath++; - } // endif objpath + } // endif objpath - if (jsp->GetType() != TYPE_JAR) { - strcpy(g->Message, "Table path does not match the json file"); - return RC_FX; - } // endif Type + if (jsp->GetType() != TYPE_JAR) { + strcpy(g->Message, "Table path does not match the json file"); + return RC_FX; + } // endif Type - arp = jsp->GetArray(); - objp = NULL; - i = atoi(objpath) - B; - val = arp->GetValue(i); + arp = jsp->GetArray(); + objp = NULL; + i = atoi(objpath) - B; + val = arp->GetValue(i); - if (!val) { - sprintf(g->Message, "Cannot find array value %d", i); - return RC_FX; - } // endif val + if (!val) { + sprintf(g->Message, "Cannot find array value %d", i); + return RC_FX; + } // endif val - } // endif + } // endif - jsp = val->GetJson(); - } // endfor objpath + jsp = val->GetJson(); + } // endfor objpath - } // endif objpath + } // endif objpath if (jsp && jsp->GetType() == TYPE_JAR) Doc = jsp->GetArray(); - else { + else { // The table is void or is just one object or one value Doc = new(g) JARRAY; @@ -2149,7 +2152,7 @@ int TDBJSON::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool) } else return RC_OK; - } // end of MakeIndex + } // end of MakeIndex /***********************************************************************/ /* Return the position in the table. */ @@ -2227,11 +2230,11 @@ bool TDBJSON::OpenDB(PGLOBAL g) return true; } // endswitch Jmode - if (Xcol) - To_Filter = NULL; // Imcompatible + if (Xcol) + To_Filter = NULL; // Imcompatible - Use = USE_OPEN; - return false; + Use = USE_OPEN; + return false; } // end of OpenDB /***********************************************************************/ @@ -2241,7 +2244,7 @@ int TDBJSON::ReadDB(PGLOBAL) { int rc; - N++; + N++; if (NextSame) { SameRow = NextSame; @@ -2352,8 +2355,8 @@ void TDBJSON::CloseDB(PGLOBAL g) TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp) { Topt = tdp->GetTopt(); - Db = tdp->Schema; - Dsn = tdp->Uri; + Db = tdp->Schema; + Dsn = tdp->Uri; } // end of TDBJCL constructor /***********************************************************************/ diff --git a/storage/connect/tabrest.cpp b/storage/connect/tabrest.cpp index e800411a36d..eef90f0dc1d 100644 --- a/storage/connect/tabrest.cpp +++ b/storage/connect/tabrest.cpp @@ -1,13 +1,23 @@ /*************** Rest C++ Program Source Code File (.CPP) **************/ -/* PROGRAM NAME: Rest Version 1.3 */ +/* PROGRAM NAME: Rest Version 1.5 */ /* (C) Copyright to the author Olivier BERTRAND 2018 - 2019 */ -/* This program is the REST OEM (Web API support) module definition. */ +/* This program is the REST Web API support for MariaDB. */ +/* When compiled without MARIADB defined, it is the EOM module code. */ /***********************************************************************/ /***********************************************************************/ /* Definitions needed by the included files. */ /***********************************************************************/ +#if defined(MARIADB) #include // All MariaDB stuff +#else // !MARIADB OEM module +#include "mini-global.h" +#define _MAX_PATH 260 +#if !defined(__WIN__) +#define __stdcall +#endif // !__WIN__ +#define _OS_H_INCLUDED // Prevent os.h to be called +#endif // !MARIADB /***********************************************************************/ /* Include application header files: */ @@ -19,12 +29,12 @@ #include "plgdbsem.h" #include "xtable.h" #include "filamtxt.h" -#include "plgxml.h" #include "tabdos.h" -#include "tabfmt.h" -#include "tabjson.h" -#include "tabrest.h" +#include "plgxml.h" #include "tabxml.h" +#include "tabjson.h" +#include "tabfmt.h" +#include "tabrest.h" /***********************************************************************/ /* Get the file from the Web. */ @@ -32,25 +42,61 @@ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn); #if defined(__WIN__) -static PCSZ slash= "\\"; +static PCSZ slash = "\\"; #else // !__WIN__ -static PCSZ slash= "/"; +static PCSZ slash = "/"; #define stricmp strcasecmp #endif // !__WIN__ +#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 + /***********************************************************************/ /* 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]; + char filename[_MAX_PATH + 1]; // MAX PATH ??? PCSZ http, uri, fn, ftype; - http= GetStringTableOption(g, tp, "Http", NULL); - uri= GetStringTableOption(g, tp, "Uri", NULL); - fn= GetStringTableOption(g, tp, "Filename", "rest.json"); + http = GetStringTableOption(g, tp, "Http", NULL); + uri = GetStringTableOption(g, tp, "Uri", NULL); + fn = GetStringTableOption(g, tp, "Filename", "rest.json"); +#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 // We used the file name relative to recorded datapath strcat(strcat(strcat(strcpy(filename, "."), slash), db), slash); @@ -60,11 +106,11 @@ PQRYRES RESTColumns(PGLOBAL g, PTOS tp, char *tab, char *db, bool info) if (http && restGetFile(g, http, uri, filename)) { // sprintf(g->Message, "Failed to get file at %s", http); } else if (!stricmp(ftype, "XML")) - qrp= XMLColumns(g, db, tab, tp, info); + qrp = XMLColumns(g, db, tab, tp, info); else if (!stricmp(ftype, "JSON")) - qrp= JSONColumns(g, db, NULL, tp, info); + qrp = JSONColumns(g, db, NULL, tp, info); else if (!stricmp(ftype, "CSV")) - qrp= CSVColumns(g, NULL, tp, info); + qrp = CSVColumns(g, NULL, tp, info); else sprintf(g->Message, "Usupported file type %s", ftype); @@ -78,40 +124,59 @@ PQRYRES RESTColumns(PGLOBAL g, PTOS tp, char *tab, char *db, bool info) /***********************************************************************/ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { - char filename[_MAX_PATH]; - TABTYPE type= GetTypeID(am); + char filename[_MAX_PATH + 1]; + int rc = 0, n; + LPCSTR ftype; - switch (type) { - case TAB_JSON: - case TAB_XML: - case TAB_CSV: - break; - default: - sprintf(g->Message, "Unsupported REST table type %s", am); - return true; - } // endswitch type +#if defined(MARIADB) + ftype = GetStringCatInfo(g, "Type", "JSON"); +#else // !MARIADB + // OEM tables must specify the file type + ftype = GetStringCatInfo(g, "Ftype", "JSON"); +#endif // !MARIADB - Http= GetStringCatInfo(g, "Http", NULL); - Uri= GetStringCatInfo(g, "Uri", NULL); - Fn= GetStringCatInfo(g, "Filename", "rest.json"); + if (trace(1)) + htrc("ftype = %s am = %s\n", ftype, SVP(am)); + + n = (!stricmp(ftype, "JSON")) ? 1 + : (!stricmp(ftype, "XML")) ? 2 + : (!stricmp(ftype, "CSV")) ? 3 : 0; + + if (n == 0) { + htrc("DefineAM: Unsupported REST table type %s", am); + sprintf(g->Message, "Unsupported REST table type %s", am); + return true; + } // endif n + + Http = GetStringCatInfo(g, "Http", NULL); + Uri = GetStringCatInfo(g, "Uri", NULL); + Fn = GetStringCatInfo(g, "Filename", "rest.json"); // We used the file name relative to recorded datapath - PlugSetPath(filename, Fn, GetPath()); + //PlugSetPath(filename, Fn, GetPath()); + strncat(strcpy(filename, GetPath()), Fn, _MAX_PATH); // Retrieve the file from the web and copy it locally - if (Http && restGetFile(g, Http, Uri, filename)) {} - else if (type == TAB_JSON) - Tdp= new (g) JSONDEF; - else if (type == TAB_XML) - Tdp= new (g) XMLDEF; - else if (type == TAB_CSV) - Tdp= new (g) CSVDEF; - else - sprintf(g->Message, "Unsupported REST table type %s", am); + rc = restGetFile(g, Http, Uri, filename); + + if (trace(1)) + htrc("Return from restGetFile: rc=%d\n", rc); + + if (rc) + return true; + else switch (n) { + case 1: Tdp = new (g) JSONDEF; break; + case 2: Tdp = new (g) XMLDEF; break; + case 3: Tdp = new (g) CSVDEF; break; + default: Tdp = NULL; + } // endswitch n // Do make the table/view definition if (Tdp && Tdp->Define(g, Cat, Name, Schema, "REST")) - Tdp= NULL; // Error occured + Tdp = NULL; // Error occured + + if (trace(1)) + htrc("Tdp defined\n", rc); // Return true in case of error return (Tdp == NULL); @@ -122,10 +187,12 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) /***********************************************************************/ PTDB RESTDEF::GetTable(PGLOBAL g, MODE m) { - if (m != MODE_READ && m != MODE_READX) { - strcpy(g->Message, "REST tables are currently read only"); - return NULL; - } // endif m + xtrc(515, "REST GetTable mode=%d\n", m); + + if (m != MODE_READ && m != MODE_READX) { + strcpy(g->Message, "REST tables are currently read only"); + return NULL; + } // endif m return Tdp->GetTable(g, m); // Leave file type do the job } // end of GetTable diff --git a/zlib/CMakeLists.txt b/zlib/CMakeLists.txt index 0c224e7ce22..0a6cb036ba4 100644 --- a/zlib/CMakeLists.txt +++ b/zlib/CMakeLists.txt @@ -1,4 +1,3 @@ - # Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. # # This program is free software; you can redistribute it and/or modify @@ -146,3 +145,6 @@ elseif(UNIX) set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") endif() endif() + + +RESTRICT_SYMBOL_EXPORTS(zlib) From c0f9042500b5034b3f6fff96321dfa9eeb36957d Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 19 Aug 2019 18:06:34 +0200 Subject: [PATCH 04/11] Some small changes. =================== - Modify tracing to use htrc to be compatible with old versions when this code is used to make an EOM module. modified: storage/connect/restget.cpp modified: storage/connect/tabrest.cpp - Path apparently not needed for the cpprest lib on Linux modified: storage/connect/CMakeLists.txt --- storage/connect/CMakeLists.txt | 4 ++-- storage/connect/restget.cpp | 25 ++++++++++++-------- storage/connect/tabrest.cpp | 43 +++++++++++++++++----------------- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 6fd3b5e3018..fd006e104c1 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -321,8 +321,8 @@ IF(CONNECT_WITH_REST) MESSAGE(STATUS "=====> cpprestsdk found") IF(UNIX) # INCLUDE_DIRECTORIES(${CPPRESTSDK_INCLUDE_DIR}) -# Edit next line to set the path to libcpprest.so - SET(REST_LIBRARY -L/usr/lib64 -lcpprest) +# If needed edit next line to set the path to libcpprest.so + SET(REST_LIBRARY -lcpprest) MESSAGE (STATUS ${REST_LIBRARY}) ENDIF(UNIX) SET(CONNECT_SOURCES ${CONNECT_SOURCES} tabrest.cpp restget.cpp tabrest.h) diff --git a/storage/connect/restget.cpp b/storage/connect/restget.cpp index d5ceb7b8a39..6b184ae6926 100644 --- a/storage/connect/restget.cpp +++ b/storage/connect/restget.cpp @@ -19,14 +19,13 @@ using namespace concurrency::streams; // Asynchronous streams #include "global.h" -static uint xt = 0; // Used by lamda expressions - /***********************************************************************/ /* Make a local copy of the requested file. */ /***********************************************************************/ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn) { int rc = 0; + bool xt = trace(515); auto fileStream = std::make_shared(); if (!http || !fn) { @@ -34,15 +33,15 @@ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn) return 2; } // endif - xt = GetTraceValue(); - xtrc(515, "restGetFile: fn=%s\n", fn); + if (xt) + htrc("restGetFile: fn=%s\n", fn); // Open stream to output file. pplx::task requestTask = fstream::open_ostream(to_string_t(fn)) .then([=](ostream outFile) { *fileStream= outFile; - if (xt & 515) + if (xt) htrc("Outfile isopen=%d\n", outFile.is_open()); // Create http_client to send the request. @@ -58,7 +57,7 @@ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn) // Handle response headers arriving. .then([=](http_response response) { - if (xt & 515) + if (xt) htrc("Received response status code:%u\n", response.status_code()); @@ -68,7 +67,7 @@ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn) // Close the file stream. .then([=](size_t n) { - if (xt & 515) + if (xt) htrc("Return size=%u\n", n); return fileStream->close(); @@ -77,13 +76,19 @@ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn) // Wait for all the outstanding I/O to complete and handle any exceptions try { requestTask.wait(); - xtrc(515, "In Wait\n"); + + if (xt) + htrc("In Wait\n"); + } catch (const std::exception &e) { - xtrc(515, "Error exception: %s\n", e.what()); + if (xt) + htrc("Error exception: %s\n", e.what()); sprintf(g->Message, "Error exception: %s", e.what()); rc= 1; } // end try/catch - xtrc(515, "restget done: rc=%d\n", rc); + if (xt) + htrc("restget done: rc=%d\n", rc); + return rc; } // end of restGetFile diff --git a/storage/connect/tabrest.cpp b/storage/connect/tabrest.cpp index eef90f0dc1d..9e1a643c89f 100644 --- a/storage/connect/tabrest.cpp +++ b/storage/connect/tabrest.cpp @@ -92,10 +92,10 @@ PQRYRES __stdcall ColREST(PGLOBAL g, PTOS tp, char *tab, char *db, bool info) uri = GetStringTableOption(g, tp, "Uri", NULL); fn = GetStringTableOption(g, tp, "Filename", "rest.json"); #if defined(MARIADB) - ftype = GetStringTableOption(g, tp, "Type", "JSON"); + ftype = GetStringTableOption(g, tp, "Type", "JSON"); #else // !MARIADB - // OEM tables must specify the file type - ftype = GetStringTableOption(g, tp, "Ftype", "JSON"); + // OEM tables must specify the file type + ftype = GetStringTableOption(g, tp, "Ftype", "JSON"); #endif // !MARIADB // We used the file name relative to recorded datapath @@ -126,21 +126,21 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { char filename[_MAX_PATH + 1]; int rc = 0, n; - LPCSTR ftype; + LPCSTR ftype; #if defined(MARIADB) - ftype = GetStringCatInfo(g, "Type", "JSON"); + ftype = GetStringCatInfo(g, "Type", "JSON"); #else // !MARIADB // OEM tables must specify the file type ftype = GetStringCatInfo(g, "Ftype", "JSON"); #endif // !MARIADB - if (trace(1)) - htrc("ftype = %s am = %s\n", ftype, SVP(am)); + if (trace(515)) + htrc("ftype = %s am = %s\n", ftype, SVP(am)); - n = (!stricmp(ftype, "JSON")) ? 1 - : (!stricmp(ftype, "XML")) ? 2 - : (!stricmp(ftype, "CSV")) ? 3 : 0; + n = (!stricmp(ftype, "JSON")) ? 1 + : (!stricmp(ftype, "XML")) ? 2 + : (!stricmp(ftype, "CSV")) ? 3 : 0; if (n == 0) { htrc("DefineAM: Unsupported REST table type %s", am); @@ -159,24 +159,24 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) // Retrieve the file from the web and copy it locally rc = restGetFile(g, Http, Uri, filename); - if (trace(1)) - htrc("Return from restGetFile: rc=%d\n", rc); + if (trace(515)) + htrc("Return from restGetFile: rc=%d\n", rc); if (rc) return true; - else switch (n) { - case 1: Tdp = new (g) JSONDEF; break; - case 2: Tdp = new (g) XMLDEF; break; - case 3: Tdp = new (g) CSVDEF; break; - default: Tdp = NULL; - } // endswitch n + else switch (n) { + case 1: Tdp = new (g) JSONDEF; break; + case 2: Tdp = new (g) XMLDEF; break; + case 3: Tdp = new (g) CSVDEF; break; + default: Tdp = NULL; + } // endswitch n // Do make the table/view definition if (Tdp && Tdp->Define(g, Cat, Name, Schema, "REST")) Tdp = NULL; // Error occured - if (trace(1)) - htrc("Tdp defined\n", rc); + if (trace(515)) + htrc("Tdp defined\n", rc); // Return true in case of error return (Tdp == NULL); @@ -187,7 +187,8 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) /***********************************************************************/ PTDB RESTDEF::GetTable(PGLOBAL g, MODE m) { - xtrc(515, "REST GetTable mode=%d\n", m); + if (trace(515)) + htrc("REST GetTable mode=%d\n", m); if (m != MODE_READ && m != MODE_READX) { strcpy(g->Message, "REST tables are currently read only"); From 6c593cd35868cb47eb9d4a712575668a243f3186 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 22 Aug 2019 23:34:42 +0200 Subject: [PATCH 05/11] Typo --- storage/connect/connect.cc | 3 ++- storage/connect/mycat.h | 10 +++++----- storage/connect/plgdbsem.h | 8 ++++---- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index 21bca637eab..b1078de8eaa 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /***********************************************************************/ /* Author Olivier BERTRAND bertrandop@gmail.com 2004-2017 */ @@ -33,6 +33,7 @@ /* plgdbsem.h is header containing the DB applic. declarations. */ /***********************************************************************/ #define DONT_DEFINE_VOID +#include #include "handler.h" #undef OFFSET diff --git a/storage/connect/mycat.h b/storage/connect/mycat.h index b306d4acbe0..818e535b32d 100644 --- a/storage/connect/mycat.h +++ b/storage/connect/mycat.h @@ -11,10 +11,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /**************** MYCAT H Declares Source Code File (.H) ***************/ -/* Name: MYCAT.H Version 2.3 */ +/* Name: MYCAT.H Version 2.4 */ /* Author: Olivier Bertrand */ /* This file contains the CONNECT plugin MYCAT class definitions. */ /***********************************************************************/ @@ -50,9 +50,9 @@ struct ha_table_option_struct { const char *filter; const char *oplist; const char *data_charset; - const char *http; - const char *uri; - ulonglong lrecl; + const char *http; + const char *uri; + ulonglong lrecl; ulonglong elements; //ulonglong estimate; ulonglong multiple; diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index 14b8549beb0..f10ae209e9d 100644 --- a/storage/connect/plgdbsem.h +++ b/storage/connect/plgdbsem.h @@ -1,7 +1,7 @@ /************** PlgDBSem H Declares Source Code File (.H) **************/ -/* Name: PLGDBSEM.H Version 3.7 */ +/* Name: PLGDBSEM.H Version 3.8 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 1998-2017 */ +/* (C) Copyright to the author Olivier BERTRAND 1998-2019 */ /* */ /* This file contains the CONNECT storage engine definitions. */ /***********************************************************************/ @@ -82,8 +82,8 @@ enum TABTYPE {TAB_UNDEF = 0, /* Table of undefined type */ TAB_JDBC = 26, /* Table accessed via JDBC */ TAB_ZIP = 27, /* ZIP file info table */ TAB_MONGO = 28, /* Table retrieved from MongoDB */ - TAB_REST = 29, /* Table retrieved from Rest query */ - TAB_NIY = 30}; /* Table not implemented yet */ + TAB_REST = 29, /* Table retrieved from Rest */ + TAB_NIY = 30}; /* Table not implemented yet */ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */ TYPE_AM_ROWID = 1, /* ROWID type (special column) */ From a3e49c0d36c0347e9dee43f9996ca7c407836a51 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 27 Aug 2019 23:01:12 +0300 Subject: [PATCH 06/11] MDEV-18501 Partition pruning doesn't work for historical queries (cleanup) Cleanup removes useless allocation. --- sql/partition_info.cc | 9 +-------- sql/partition_info.h | 3 +-- sql/sql_yacc.yy | 8 ++++---- sql/sql_yacc_ora.yy | 8 ++++---- 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/sql/partition_info.cc b/sql/partition_info.cc index ba6fc8a49ec..65cf0298f4f 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -1473,15 +1473,8 @@ void partition_info::print_no_partition_found(TABLE *table_arg, myf errflag) FALSE Success */ -bool partition_info::set_part_expr(THD *thd, char *start_token, Item *item_ptr, - char *end_token, bool is_subpart) +bool partition_info::set_part_expr(THD *thd, Item *item_ptr, bool is_subpart) { - size_t expr_len= end_token - start_token; - char *func_string= (char*) thd->memdup(start_token, expr_len); - - if (unlikely(!func_string)) - return TRUE; - if (is_subpart) { list_of_subpart_fields= FALSE; diff --git a/sql/partition_info.h b/sql/partition_info.h index d6a6214c172..253e88174dd 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -366,8 +366,7 @@ public: void init_col_val(part_column_list_val *col_val, Item *item); int reorganize_into_single_field_col_val(THD *thd); part_column_list_val *add_column_value(THD *thd); - bool set_part_expr(THD *thd, char *start_token, Item *item_ptr, - char *end_token, bool is_subpart); + bool set_part_expr(THD *thd, Item *item_ptr, bool is_subpart); bool set_up_charset_field_preps(THD *thd); bool check_partition_field_length(); bool init_column_part(THD *thd); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c1b2fd2294b..563de8a0368 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5541,10 +5541,10 @@ part_column_list: part_func: - '(' remember_name part_func_expr remember_end ')' + '(' part_func_expr ')' { partition_info *part_info= Lex->part_info; - if (unlikely(part_info->set_part_expr(thd, $2 + 1, $3, $4, FALSE))) + if (unlikely(part_info->set_part_expr(thd, $2, FALSE))) MYSQL_YYABORT; part_info->num_columns= 1; part_info->column_list= FALSE; @@ -5552,9 +5552,9 @@ part_func: ; sub_part_func: - '(' remember_name part_func_expr remember_end ')' + '(' part_func_expr ')' { - if (unlikely(Lex->part_info->set_part_expr(thd, $2 + 1, $3, $4, TRUE))) + if (unlikely(Lex->part_info->set_part_expr(thd, $2, TRUE))) MYSQL_YYABORT; } ; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 28d3d1bf90b..b31f2a0f890 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -5387,10 +5387,10 @@ part_column_list: part_func: - '(' remember_name part_func_expr remember_end ')' + '(' part_func_expr ')' { partition_info *part_info= Lex->part_info; - if (unlikely(part_info->set_part_expr(thd, $2 + 1, $3, $4, FALSE))) + if (unlikely(part_info->set_part_expr(thd, $2, FALSE))) MYSQL_YYABORT; part_info->num_columns= 1; part_info->column_list= FALSE; @@ -5398,9 +5398,9 @@ part_func: ; sub_part_func: - '(' remember_name part_func_expr remember_end ')' + '(' part_func_expr ')' { - if (unlikely(Lex->part_info->set_part_expr(thd, $2 + 1, $3, $4, TRUE))) + if (unlikely(Lex->part_info->set_part_expr(thd, $2, TRUE))) MYSQL_YYABORT; } ; From c3f35ea55a7150b186284e2ef717d12e6f81e13e Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Wed, 28 Aug 2019 11:57:16 +0300 Subject: [PATCH 07/11] MDEV-18501 Partition pruning doesn't work for historical queries (refactoring) SYSTEM_TYPE partitioning: COLUMN properties removed. Partitioning is now pure RANGE based on UNIX_TIMESTAMP(row_end). DECIMAL type is now allowed as RANGE partitioning, we can partition by UNIX_TIMESTAMP() (but not for DATETIME which depends on local timezone of course). --- mysql-test/main/partition_range.result | 27 ++++++++++++++++++++++++++ mysql-test/main/partition_range.test | 27 ++++++++++++++++++++++++++ sql/partition_element.h | 23 ++++++---------------- sql/partition_info.cc | 22 ++++++++++----------- sql/partition_info.h | 4 ++-- sql/sql_lex.cc | 4 ++-- sql/sql_partition.cc | 16 +++++++-------- 7 files changed, 83 insertions(+), 40 deletions(-) diff --git a/mysql-test/main/partition_range.result b/mysql-test/main/partition_range.result index 7ae029d488c..00171e3e0bd 100644 --- a/mysql-test/main/partition_range.result +++ b/mysql-test/main/partition_range.result @@ -981,4 +981,31 @@ a MAX(b) SHOW status LIKE 'handler_read_key'; Variable_name Value Handler_read_key 4 +# +# MDEV-18501 Partition pruning doesn't work for historical queries +# +set time_zone= '+00:00'; +create or replace table t1 (d datetime(6)) +partition by range (unix_timestamp(d)) ( +partition p0 values less than (1), +partition p1 values less than (maxvalue)); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +# DECIMAL functions are now allowed, partitioning is done by integer part +create or replace table t1 (d timestamp(6)) +partition by range (unix_timestamp(d)) ( +partition p0 values less than (946684801), +partition p1 values less than (maxvalue)); +insert into t1 values +# go to p0 +('2000-01-01 00:00:00'), +('2000-01-01 00:00:00.000001'), +# goes to p1 +('2000-01-01 00:00:01'); +select * from t1 partition (p0); +d +2000-01-01 00:00:00.000000 +2000-01-01 00:00:00.000001 +select * from t1 partition (p1); +d +2000-01-01 00:00:01.000000 DROP TABLE t1, t2; diff --git a/mysql-test/main/partition_range.test b/mysql-test/main/partition_range.test index 3ff03248d88..628602ffa25 100644 --- a/mysql-test/main/partition_range.test +++ b/mysql-test/main/partition_range.test @@ -971,4 +971,31 @@ SELECT a, MAX(b) FROM t2 WHERE a IN (10, 100) GROUP BY a; --echo # Should be no more than 4 reads. SHOW status LIKE 'handler_read_key'; +--echo # +--echo # MDEV-18501 Partition pruning doesn't work for historical queries +--echo # +set time_zone= '+00:00'; +let $ts= `select unix_timestamp('2000-01-01 00:00:00') + 1`; + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +create or replace table t1 (d datetime(6)) +partition by range (unix_timestamp(d)) ( + partition p0 values less than (1), + partition p1 values less than (maxvalue)); + +--echo # DECIMAL functions are now allowed, partitioning is done by integer part +eval create or replace table t1 (d timestamp(6)) +partition by range (unix_timestamp(d)) ( + partition p0 values less than ($ts), + partition p1 values less than (maxvalue)); + +insert into t1 values + # go to p0 + ('2000-01-01 00:00:00'), + ('2000-01-01 00:00:00.000001'), + # goes to p1 + ('2000-01-01 00:00:01'); +select * from t1 partition (p0); +select * from t1 partition (p1); + DROP TABLE t1, t2; diff --git a/sql/partition_element.h b/sql/partition_element.h index a3eb6953be1..ff0d0d59fc4 100644 --- a/sql/partition_element.h +++ b/sql/partition_element.h @@ -98,7 +98,7 @@ enum stat_trx_field class partition_element :public Sql_alloc { public: - enum elem_type + enum elem_type_enum { CONVENTIONAL= 0, CURRENT, @@ -125,19 +125,7 @@ public: bool max_value; // MAXVALUE range uint32 id; bool empty; - - // TODO: subclass partition_element by partitioning type to avoid such semantic - // mixup - elem_type type() - { - return (elem_type)(int(signed_flag) << 1 | int(max_value)); - } - - void type(elem_type val) - { - max_value= (bool)(val & 1); - signed_flag= (bool)(val & 2); - } + elem_type_enum type; partition_element() : part_max_rows(0), part_min_rows(0), range_value(0), @@ -148,7 +136,8 @@ public: nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE), signed_flag(FALSE), max_value(FALSE), id(UINT_MAX32), - empty(true) + empty(true), + type(CONVENTIONAL) {} partition_element(partition_element *part_elem) : part_max_rows(part_elem->part_max_rows), @@ -164,13 +153,13 @@ public: nodegroup_id(part_elem->nodegroup_id), has_null_value(FALSE), id(part_elem->id), - empty(part_elem->empty) + empty(part_elem->empty), + type(CONVENTIONAL) {} ~partition_element() {} part_column_list_val& get_col_val(uint idx) { - DBUG_ASSERT(type() == CONVENTIONAL || list_val_list.elements == 1); part_elem_value *ev= list_val_list.head(); DBUG_ASSERT(ev); DBUG_ASSERT(ev->col_val_array); diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 65cf0298f4f..f9669931eab 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -894,15 +894,16 @@ bool partition_info::vers_setup_expression(THD * thd, uint32 alter_add) DBUG_ASSERT(part_type == VERSIONING_PARTITION); DBUG_ASSERT(table->versioned(VERS_TIMESTAMP)); - DBUG_ASSERT(num_columns == 1); if (!alter_add) { Field *row_end= table->vers_end_field(); - part_field_list.push_back(row_end->field_name.str, thd->mem_root); - DBUG_ASSERT(part_field_list.elements == 1); // needed in handle_list_of_fields() row_end->flags|= GET_FIXED_FIELDS_FLAG; + Name_resolution_context *context= &thd->lex->current_select->context; + Item *row_end_item= new (thd->mem_root) Item_field(thd, context, row_end); + Item *row_end_ts= new (thd->mem_root) Item_func_unix_timestamp(thd, row_end_item); + set_part_expr(thd, row_end_ts, false); } if (alter_add) @@ -911,12 +912,12 @@ bool partition_info::vers_setup_expression(THD * thd, uint32 alter_add) partition_element *el; for(uint32 id= 0; ((el= it++)); id++) { - DBUG_ASSERT(el->type() != partition_element::CONVENTIONAL); + DBUG_ASSERT(el->type != partition_element::CONVENTIONAL); /* Newly added element is inserted before AS_OF_NOW. */ - if (el->id == UINT_MAX32 || el->type() == partition_element::CURRENT) + if (el->id == UINT_MAX32 || el->type == partition_element::CURRENT) { el->id= id; - if (el->type() == partition_element::CURRENT) + if (el->type == partition_element::CURRENT) break; } } @@ -1343,13 +1344,13 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, } if (part_type == VERSIONING_PARTITION) { - if (part_elem->type() == partition_element::HISTORY) + if (part_elem->type == partition_element::HISTORY) { hist_parts++; } else { - DBUG_ASSERT(part_elem->type() == partition_element::CURRENT); + DBUG_ASSERT(part_elem->type == partition_element::CURRENT); now_parts++; } } @@ -2690,9 +2691,8 @@ bool check_partition_dirs(partition_info *part_info) bool partition_info::vers_init_info(THD * thd) { part_type= VERSIONING_PARTITION; - list_of_part_fields= TRUE; - column_list= TRUE; - num_columns= 1; + list_of_part_fields= true; + column_list= false; vers_info= new (thd->mem_root) Vers_part_info; if (unlikely(!vers_info)) return true; diff --git a/sql/partition_info.h b/sql/partition_info.h index 253e88174dd..2aed6cbc5db 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -55,11 +55,11 @@ struct Vers_part_info : public Sql_alloc if (now_part) { DBUG_ASSERT(now_part->id != UINT_MAX32); - DBUG_ASSERT(now_part->type() == partition_element::CURRENT); + DBUG_ASSERT(now_part->type == partition_element::CURRENT); if (hist_part) { DBUG_ASSERT(hist_part->id != UINT_MAX32); - DBUG_ASSERT(hist_part->type() == partition_element::HISTORY); + DBUG_ASSERT(hist_part->type == partition_element::HISTORY); } return true; } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 8d8ef73fcd1..1825ce7c1ce 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -8168,7 +8168,7 @@ bool LEX::part_values_current(THD *thd) create_last_non_select_table->table_name.str); return true; } - elem->type(partition_element::CURRENT); + elem->type= partition_element::CURRENT; DBUG_ASSERT(part_info->vers_info); part_info->vers_info->now_part= elem; if (unlikely(part_info->init_column_part(thd))) @@ -8202,7 +8202,7 @@ bool LEX::part_values_history(THD *thd) create_last_non_select_table->table_name.str); return true; } - elem->type(partition_element::HISTORY); + elem->type= partition_element::HISTORY; if (unlikely(part_info->init_column_part(thd))) return true; return false; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 34f8a4e3aee..ba6d0f14aeb 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1975,7 +1975,6 @@ bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind) } } DBUG_ASSERT(part_info->part_type != NOT_A_PARTITION); - DBUG_ASSERT(part_info->part_type != VERSIONING_PARTITION || part_info->column_list); /* Partition is defined. We need to verify that partitioning function is correct. @@ -2008,15 +2007,15 @@ bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind) { if (part_info->column_list) { - if (part_info->part_type == VERSIONING_PARTITION && - part_info->vers_setup_expression(thd)) - goto end; List_iterator it(part_info->part_field_list); if (unlikely(handle_list_of_fields(thd, it, table, part_info, FALSE))) goto end; } else { + if (part_info->part_type == VERSIONING_PARTITION && + part_info->vers_setup_expression(thd)) + goto end; if (unlikely(fix_fields_part_func(thd, part_info->part_expr, table, FALSE, is_create_table_ind))) goto end; @@ -2032,7 +2031,8 @@ bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind) goto end; } if (unlikely(!part_info->column_list && - part_info->part_expr->result_type() != INT_RESULT)) + part_info->part_expr->result_type() != INT_RESULT && + part_info->part_expr->result_type() != DECIMAL_RESULT)) { part_info->report_part_expr_error(FALSE); goto end; @@ -2541,7 +2541,7 @@ static int add_partition_values(String *str, partition_info *part_info, } else if (part_info->part_type == VERSIONING_PARTITION) { - switch (p_elem->type()) + switch (p_elem->type) { case partition_element::CURRENT: err+= str->append(STRING_WITH_LEN(" CURRENT")); @@ -5321,7 +5321,7 @@ that are reorganised. partition_element *el; while ((el= it++)) { - if (el->type() == partition_element::CURRENT) + if (el->type == partition_element::CURRENT) { it.remove(); now_part= el; @@ -5417,7 +5417,7 @@ that are reorganised. { if (tab_part_info->part_type == VERSIONING_PARTITION) { - if (part_elem->type() == partition_element::CURRENT) + if (part_elem->type == partition_element::CURRENT) { my_error(ER_VERS_WRONG_PARTS, MYF(0), table->s->table_name.str); goto err; From 6a490ca0fbcf0ceeaeee55bd6c98eb1ea8bcb8c5 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Wed, 28 Aug 2019 19:51:23 +0300 Subject: [PATCH 08/11] MDEV-18501 Partition pruning doesn't work for historical queries (fix) Pruning fix for SYSTEM_TIME INTERVAL partitioning. Allocating one more element in range_int_array for CURRENT partition is required for RANGE pruning to work correctly (get_partition_id_range_for_endpoint()). --- .../suite/versioning/r/partition_rotation.result | 2 +- sql/sql_lex.cc | 4 ---- sql/sql_partition.cc | 13 +++++++++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/versioning/r/partition_rotation.result b/mysql-test/suite/versioning/r/partition_rotation.result index 7e25f122238..82558085c02 100644 --- a/mysql-test/suite/versioning/r/partition_rotation.result +++ b/mysql-test/suite/versioning/r/partition_rotation.result @@ -47,7 +47,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL 2 Using where explain partitions select * from t1 for system_time as of '2001-02-04 10:20:30'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p1_p1sp0,p1_p1sp1,p0_p0sp0,p0_p0sp1,p2_p2sp0,p2_p2sp1,pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL # Using where +1 SIMPLE t1 p0_p0sp0,p0_p0sp1,p2_p2sp0,p2_p2sp1,pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL # Using where set @ts=(select row_end from t1 for system_time all where i=1); select * from t1 for system_time all where row_end = @ts; i diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 1825ce7c1ce..d3c98115659 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -8171,8 +8171,6 @@ bool LEX::part_values_current(THD *thd) elem->type= partition_element::CURRENT; DBUG_ASSERT(part_info->vers_info); part_info->vers_info->now_part= elem; - if (unlikely(part_info->init_column_part(thd))) - return true; return false; } @@ -8203,8 +8201,6 @@ bool LEX::part_values_history(THD *thd) return true; } elem->type= partition_element::HISTORY; - if (unlikely(part_info->init_column_part(thd))) - return true; return false; } diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index ba6d0f14aeb..f6afb7955b5 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1563,7 +1563,7 @@ static bool check_vers_constants(THD *thd, partition_info *part_info) return 0; part_info->range_int_array= - (longlong*) thd->alloc(hist_parts * sizeof(longlong)); + (longlong*) thd->alloc(part_info->num_parts * sizeof(longlong)); MYSQL_TIME ltime; List_iterator it(part_info->partitions); @@ -1582,6 +1582,9 @@ static bool check_vers_constants(THD *thd, partition_info *part_info) if (vers_info->hist_part->range_value <= thd->query_start()) vers_info->hist_part= el; } + DBUG_ASSERT(el == vers_info->now_part); + el->max_value= true; + part_info->range_int_array[el->id]= el->range_value= LONGLONG_MAX; return 0; err: my_error(ER_DATA_OUT_OF_RANGE, MYF(0), "TIMESTAMP", "INTERVAL"); @@ -7671,6 +7674,11 @@ static void set_up_range_analysis_info(partition_info *part_info) partitioning */ switch (part_info->part_type) { + case VERSIONING_PARTITION: + if (!part_info->vers_info->interval.is_set()) + { + break; + } case RANGE_PARTITION: case LIST_PARTITION: if (!part_info->column_list) @@ -8107,7 +8115,8 @@ static int get_part_iter_for_interval_via_mapping(partition_info *part_info, part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE; part_iter->ret_default_part= part_iter->ret_default_part_orig= FALSE; - if (part_info->part_type == RANGE_PARTITION) + if (part_info->part_type == RANGE_PARTITION || + part_info->part_type == VERSIONING_PARTITION) { if (part_info->part_charset_field_array) get_endpoint= get_partition_id_range_for_endpoint_charset; From d5a11a1f0208df87ee9885f5eb7a7427ee9a6f4a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 1 Sep 2019 13:27:32 +0200 Subject: [PATCH 09/11] C/C --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index dc271e5a1b9..7de639518ff 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit dc271e5a1b9d4074e2086b776a668b6b5614f2bc +Subproject commit 7de639518ffe56a99ac805654381d17f42796be2 From 1bbc593eaeeb2675ad3126e9753a5e945150b7ee Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 1 Sep 2019 15:42:23 +0300 Subject: [PATCH 10/11] Fixed compiler warning that broke builds gcc 7.4.1 --- sql/sql_partition.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index f6afb7955b5..a3dbadd9025 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -7676,9 +7676,8 @@ static void set_up_range_analysis_info(partition_info *part_info) switch (part_info->part_type) { case VERSIONING_PARTITION: if (!part_info->vers_info->interval.is_set()) - { break; - } + /* Fall through */ case RANGE_PARTITION: case LIST_PARTITION: if (!part_info->column_list) From 597b070f8254439aa5f555c6868f3d9b8d518238 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Sun, 1 Sep 2019 17:56:47 +0300 Subject: [PATCH 11/11] Compilation fix Caused by: MDEV-18501 Partition pruning doesn't work for historical queries (cleanup) --- sql/partition_info.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sql/partition_info.cc b/sql/partition_info.cc index f9669931eab..66ec6a70b12 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -2648,12 +2648,9 @@ part_column_list_val *partition_info::add_column_value(THD *thd) return NULL; } -bool partition_info::set_part_expr(THD *thd, char *start_token, Item *item_ptr, - char *end_token, bool is_subpart) +bool partition_info::set_part_expr(THD *thd, Item *item_ptr, bool is_subpart) { - (void)start_token; (void)item_ptr; - (void)end_token; (void)is_subpart; return FALSE; }