diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-09-06 14:25:20 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-09-06 14:25:20 +0300 |
commit | 780d2bb8a7eca4fdbdf70fbd51c0bdbae5b0057e (patch) | |
tree | b7447115f45de0f03bbe18c26fc0866367483066 /storage | |
parent | db9e41ddc31f2e705a54132cf69c781e1cc60f07 (diff) | |
parent | 18af13b88ba580562981a190c25da128a2e9db26 (diff) | |
download | mariadb-git-780d2bb8a7eca4fdbdf70fbd51c0bdbae5b0057e.tar.gz |
Merge 10.4 into 10.5
Diffstat (limited to 'storage')
68 files changed, 2558 insertions, 1879 deletions
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index feef8db70ec..100df891621 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -73,6 +73,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 @@ -308,6 +312,30 @@ 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") + IF(UNIX) +# INCLUDE_DIRECTORIES(${CPPRESTSDK_INCLUDE_DIR}) +# 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) + add_definitions(-DREST_SUPPORT) + ELSE(NOT cpprestsdk_FOUND) + MESSAGE(STATUS "=====> cpprestsdk package not found") + ENDIF (cpprestsdk_FOUND) +ENDIF(CONNECT_WITH_REST) + +# # XMAP # @@ -326,7 +354,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() @@ -334,7 +362,7 @@ ENDIF() IF(MSVC AND (CMAKE_CXX_FLAGS MATCHES "/MP")) # domdoc.cpp uses compiler directive #import which is not compatible - # with the /MP option, resulting in compiler error C2813.´ + # with the /MP option, resulting in compiler error C2813. # Remove /MP for this file. SET(src_list ${CONNECT_SOURCES}) LIST(FIND src_list domdoc.cpp idx) @@ -347,8 +375,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) # Install some extra files that belong to connect engine @@ -377,3 +405,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 972a1e72403..3c736941b6f 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 - - if (trace(1)) - htrc(" adding string(%d): '%s'\n", Nval, strp); + } // endif Type -//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 - - if (trace(1)) - htrc(" adding SHORT(%d): %hd\n", Nval, n); + } // endif Type -//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 (trace(1)) - htrc(" adding (%d) from xp=%p\n", Nval, xp); +{ + if (Type != xp->GetResultType()) { + sprintf(g->Message, MSG(ADD_BAD_TYPE), + GetTypeName(xp->GetResultType()), GetTypeName(Type)); + return true; + } // endif Type -//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. */ @@ -975,7 +956,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; @@ -990,11 +971,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, "("); @@ -1003,19 +982,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); @@ -1037,19 +1014,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/connect.h b/storage/connect/connect.h index cf0373ba635..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 02110-1335 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/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 2b47162bb34..6939e6948f9 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 02110-1335 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 @@ -238,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); @@ -350,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: @@ -581,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), @@ -988,11 +995,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 @@ -1024,6 +1031,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; @@ -1127,48 +1147,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<size_t>(pv - pk), sizeof(key) - 1); + n= MY_MIN(static_cast<size_t>(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; @@ -1216,9 +1236,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); @@ -1249,7 +1273,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); @@ -1314,7 +1338,7 @@ char *ha_connect::GetRealString(PCSZ s) { char *sv; - if (IsPartitioned() && s && partname && *partname) { + if (IsPartitioned() && s && *partname) { sv= (char*)PlugSubAlloc(xp->g, NULL, 0); sprintf(sv, s, partname); PlugSubAlloc(xp->g, NULL, strlen(sv) + 1); @@ -1343,8 +1367,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); @@ -1365,7 +1389,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, "*")) { @@ -1494,7 +1518,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; @@ -1546,7 +1570,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: @@ -1811,7 +1835,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) @@ -2051,10 +2075,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; @@ -2180,9 +2204,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()); @@ -2431,7 +2455,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; @@ -2542,7 +2566,7 @@ const char *ha_connect::GetValStr(OPVAL vop, bool neg) switch (vop) { case OP_EQ: - val= " = "; + val= "= "; break; case OP_NE: val= " <> "; @@ -2815,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; @@ -2832,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) @@ -2891,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; @@ -2905,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 @@ -2924,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(), @@ -2940,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 */ @@ -3001,12 +3025,12 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) } else { bool h; - fnm = filp->Chk(pField->field->field_name.str, &h); + fnm= filp->Chk(pField->field->field_name.str, &h); if (h && i && !ishav) return NULL; // Having should be col VOP arg else - ishav = h; + ishav= h; } // endif's @@ -3053,7 +3077,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 @@ -3111,37 +3135,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; @@ -3165,7 +3189,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)); @@ -3179,11 +3203,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)) @@ -3233,21 +3257,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) @@ -3261,7 +3285,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) @@ -3311,8 +3335,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"); @@ -3322,32 +3346,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 @@ -3375,7 +3399,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); @@ -3484,32 +3508,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) @@ -4209,7 +4233,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; @@ -4291,12 +4315,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) { @@ -4439,6 +4463,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, const char *dbn, bool case TAB_XML: case TAB_INI: case TAB_VEC: + case TAB_REST: case TAB_JSON: if (options->filename && *options->filename) { if (!quick) { @@ -4575,14 +4600,14 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd, // newmode= MODE_UPDATE; // To be checked // break; case SQLCOM_DELETE_MULTI: - *cras = true; + *cras= true; // fall through case SQLCOM_DELETE: case SQLCOM_TRUNCATE: newmode= MODE_DELETE; break; case SQLCOM_UPDATE_MULTI: - *cras = true; + *cras= true; // fall through case SQLCOM_UPDATE: newmode= MODE_UPDATE; @@ -4612,7 +4637,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)); @@ -4727,15 +4752,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); @@ -4811,7 +4836,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); @@ -4948,7 +4973,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 @@ -5035,7 +5060,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; } @@ -5312,7 +5337,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); @@ -5356,9 +5381,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("'"); @@ -5510,13 +5535,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 __attribute__((unused)) = 0, rc = 0, mul = 0; -//PCSZ tabtyp = NULL; + int port= 0, mxr __attribute__((unused)) = 0, rc= 0, mul= 0; +//PCSZ tabtyp= NULL; #if defined(ODBC_SUPPORT) POPARM sop= NULL; PCSZ ucnc= NULL; @@ -5526,7 +5551,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; @@ -5544,7 +5568,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); @@ -5555,7 +5580,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; @@ -5578,7 +5603,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")); @@ -5593,7 +5618,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"; @@ -5606,14 +5631,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) { @@ -5623,39 +5658,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 @@ -5663,13 +5698,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); @@ -5678,13 +5713,13 @@ 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.str); sjp = (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM)); @@ -5700,9 +5735,9 @@ static int connect_assisted_discovery(handlerton *, THD* thd, 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 @@ -5711,7 +5746,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) @@ -5719,55 +5754,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.str); 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; // fall through case TAB_PRX: case TAB_TBL: @@ -5777,12 +5812,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"); @@ -5791,24 +5826,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); @@ -5819,12 +5863,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) { @@ -5832,23 +5876,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: @@ -5856,21 +5900,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); @@ -5885,23 +5929,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); @@ -5911,56 +5955,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"); @@ -5968,33 +6017,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 __attribute__((unused)) = NULL; - char *tn = NULL; + char *tn= NULL; // Not a catalog table if (!qrp->Nblin) { @@ -6003,57 +6052,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 @@ -6062,19 +6111,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: @@ -6083,10 +6132,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 @@ -6097,10 +6146,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)", @@ -6109,12 +6158,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: @@ -6129,10 +6178,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 @@ -6142,7 +6191,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)", @@ -6151,12 +6200,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: @@ -6165,43 +6214,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: @@ -6270,7 +6319,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, TABLE *st= table; // Probably unuseful THD *thd= ha_thd(); LEX_CSTRING cnc = table_arg->s->connect_string; -#ifdef WITH_PARTITION_STORAGE_ENGINE +#if defined(WITH_PARTITION_STORAGE_ENGINE) partition_info *part_info= table_arg->part_info; #else // !WITH_PARTITION_STORAGE_ENGINE #define part_info 0 @@ -6396,7 +6445,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(); @@ -6479,7 +6528,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); @@ -6681,15 +6730,15 @@ int ha_connect::create(const char *name, TABLE *table_arg, #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); + 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)); @@ -6708,7 +6757,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, } // endif fn } // endif zipped -#endif // ZIP_SUPPORT +#endif // ZIP_SUPPORT // To check whether indexes have to be made or remade if (!g->Xchk) { @@ -6758,7 +6807,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, @@ -7102,7 +7151,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. @@ -7334,7 +7383,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 53e666d534d..06de375ef58 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 02110-1335 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file ha_connect.h Author Olivier Bertrand diff --git a/storage/connect/inihandl.cpp b/storage/connect/inihandl.cpp index c39c94fb30d..ab6d5db4f0a 100644 --- a/storage/connect/inihandl.cpp +++ b/storage/connect/inihandl.cpp @@ -192,7 +192,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/jsonudf.cpp b/storage/connect/jsonudf.cpp index c634d722c31..b1e32394de0 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 . */ /*********************************************************************************/ @@ -1685,7 +1685,7 @@ static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i) } // endif *s if (n < 1) - return (char*) "Key"; + return (PCSZ) "Key"; if (!b) { if ((p = (PSZ)PlgDBSubAlloc(g, NULL, n + 1))) { @@ -1702,7 +1702,7 @@ static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i) return (char*) s; } // endif count - return (char*) "Key"; + return (PCSZ) "Key"; } // end of MakeKey /*********************************************************************************/ diff --git a/storage/connect/libdoc.cpp b/storage/connect/libdoc.cpp index 089b1197e58..c1eaa6766cc 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/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) ((a<b)?(a):(b)) +#endif // MY_GLOBAL_H diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index 6d3e9a346c5..411e96e3dc8 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -16,9 +16,9 @@ /*************** 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" /***********************************************************************/ @@ -117,11 +120,11 @@ char *GetPluginDir(void) /***********************************************************************/ TABTYPE GetTypeID(const char *type) { - return (!type) ? TAB_UNDEF + return (!type) ? TAB_UNDEF : (!stricmp(type, "DOS")) ? TAB_DOS : (!stricmp(type, "FIX")) ? TAB_FIX : (!stricmp(type, "BIN")) ? TAB_BIN - : (!stricmp(type, "CSV")) ? TAB_CSV + : (!stricmp(type, "CSV")) ? TAB_CSV : (!stricmp(type, "FMT")) ? TAB_FMT : (!stricmp(type, "DBF")) ? TAB_DBF #if defined(XML_SUPPORT) @@ -133,30 +136,30 @@ TABTYPE GetTypeID(const char *type) : (!stricmp(type, "ODBC")) ? TAB_ODBC #endif #if defined(JAVA_SUPPORT) - : (!stricmp(type, "JDBC")) ? TAB_JDBC + : (!stricmp(type, "JDBC")) ? TAB_JDBC #endif #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) - : (!stricmp(type, "MONGO") && MongoEnabled()) ? TAB_MONGO + : (!stricmp(type, "MONGO") && MongoEnabled()) ? TAB_MONGO #endif - : (!stricmp(type, "MYSQL")) ? TAB_MYSQL + : (!stricmp(type, "MYSQL")) ? TAB_MYSQL : (!stricmp(type, "MYPRX")) ? TAB_MYSQL : (!stricmp(type, "DIR")) ? TAB_DIR #if defined(__WIN__) - : (!stricmp(type, "MAC")) ? TAB_MAC - : (!stricmp(type, "WMI")) ? TAB_WMI + : (!stricmp(type, "MAC")) ? TAB_MAC + : (!stricmp(type, "WMI")) ? TAB_WMI #endif - : (!stricmp(type, "TBL")) ? TAB_TBL - : (!stricmp(type, "XCOL")) ? TAB_XCL - : (!stricmp(type, "OCCUR")) ? TAB_OCCUR + : (!stricmp(type, "TBL")) ? TAB_TBL + : (!stricmp(type, "XCOL")) ? TAB_XCL + : (!stricmp(type, "OCCUR")) ? TAB_OCCUR : (!stricmp(type, "CATLG")) ? TAB_PRX // Legacy : (!stricmp(type, "PROXY")) ? TAB_PRX : (!stricmp(type, "PIVOT")) ? TAB_PIVOT : (!stricmp(type, "VIR")) ? TAB_VIR : (!stricmp(type, "JSON")) ? TAB_JSON #if defined(ZIP_SUPPORT) - : (!stricmp(type, "ZIP")) ? TAB_ZIP + : (!stricmp(type, "ZIP")) ? TAB_ZIP #endif - : (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY; + : (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY; } // end of GetTypeID /***********************************************************************/ @@ -166,18 +169,19 @@ bool IsFileType(TABTYPE type) { bool isfile; - switch (type) { + switch (type) { case TAB_DOS: case TAB_FIX: case TAB_BIN: - case TAB_CSV: + case TAB_CSV: case TAB_FMT: case TAB_DBF: case TAB_XML: case TAB_INI: case TAB_VEC: case TAB_JSON: -// case TAB_ZIP: + case TAB_REST: + // case TAB_ZIP: isfile= true; break; default: @@ -195,7 +199,7 @@ bool IsExactType(TABTYPE type) { bool exact; - switch (type) { + switch (type) { case TAB_FIX: case TAB_BIN: case TAB_DBF: @@ -220,7 +224,7 @@ bool IsTypeNullable(TABTYPE type) { bool nullable; - switch (type) { + switch (type) { case TAB_MAC: case TAB_DIR: nullable= false; @@ -240,7 +244,7 @@ bool IsTypeFixed(TABTYPE type) { bool fix; - switch (type) { + switch (type) { case TAB_FIX: case TAB_BIN: case TAB_VEC: @@ -262,7 +266,7 @@ bool IsTypeIndexable(TABTYPE type) { bool idx; - switch (type) { + switch (type) { case TAB_DOS: case TAB_CSV: case TAB_FMT: @@ -288,7 +292,7 @@ int GetIndexType(TABTYPE type) { int xtyp; - switch (type) { + switch (type) { case TAB_DOS: case TAB_CSV: case TAB_FMT: @@ -301,9 +305,9 @@ int GetIndexType(TABTYPE type) break; case TAB_MYSQL: case TAB_ODBC: - case TAB_JDBC: - case TAB_MONGO: - xtyp= 2; + case TAB_JDBC: + case TAB_MONGO: + xtyp= 2; break; case TAB_VIR: xtyp= 3; @@ -375,7 +379,7 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info) return NULL; } else PlugSetPath(soname, module, GetPluginDir()); - + // The exported name is always in uppercase for (int i = 0; ; i++) { c = subtype[i]; @@ -452,7 +456,7 @@ CATALOG::CATALOG(void) memset(&Ctb, 0, sizeof(CURTAB)); Cbuf= NULL; Cblen= 0; - DefHuge= false; + DefHuge= false; } // end of CATALOG constructor /* -------------------------- Class MYCAT ---------------------------- */ @@ -462,7 +466,7 @@ CATALOG::CATALOG(void) /***********************************************************************/ MYCAT::MYCAT(PHC hc) : CATALOG() { - Hc= hc; + Hc= hc; DefHuge= false; } // end of MYCAT constructor @@ -479,16 +483,23 @@ void MYCAT::Reset(void) /***********************************************************************/ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR type, PRELDEF *) - { - if (trace(1)) - printf("GetTableDesc: name=%s am=%s\n", tablep->GetName(), SVP(type)); +{ + PRELDEF tdp= NULL; + + 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","*"); - // If not specified get the type of this table - if (!type) - type= Hc->GetStringOption("Type","*"); + tdp= MakeTableDesc(g, tablep, type); - return MakeTableDesc(g, tablep, type); - } // end of GetTableDesc + if (trace(1)) + htrc("GetTableDesc: tdp=%p\n", tdp); + + return tdp; +} // end of GetTableDesc /***********************************************************************/ /* MakeTableDesc: make a table/view description. */ @@ -497,18 +508,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. */ /*********************************************************************/ - tc= GetTypeID(am); + if (!am) { + tc= Hc->GetRealType(); + am= Hc->GetStringOption("Type","*"); + } else + tc= GetTypeID(am); switch (tc) { case TAB_FIX: @@ -523,46 +538,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; +#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 @@ -575,26 +596,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/mycat.h b/storage/connect/mycat.h index e5a0b783b82..818e535b32d 100644 --- a/storage/connect/mycat.h +++ b/storage/connect/mycat.h @@ -14,7 +14,7 @@ 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,6 +50,8 @@ struct ha_table_option_struct { const char *filter; const char *oplist; const char *data_charset; + const char *http; + const char *uri; ulonglong lrecl; ulonglong elements; //ulonglong estimate; 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/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 <errno.h> #include <stddef.h> #include "os.h" diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index 5446e0d2a07..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,6 +82,7 @@ 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 */ TAB_NIY = 30}; /* Table not implemented yet */ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */ @@ -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/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: */ /* ----------------------- */ @@ -111,21 +111,31 @@ ACTIVITY defActivity = { /* Describes activity and language */ #endif // UNIX /**************************************************************************/ -/* Tracing output function. */ +/* Conditional tracing output function. */ /**************************************************************************/ -void htrc(char const *fmt, ...) - { - va_list ap; - va_start (ap, fmt); +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 -//if (trace == 1) -// vfprintf(debug, fmt, ap); -//else - vfprintf(stderr, fmt, ap); +/**************************************************************************/ +/* Tracing output function. */ +/**************************************************************************/ +void htrc(char const* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); - 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(); - - switch (tc) { - case TAB_VEC: - cdp->SetOffset(0); // Not to have shift - case TAB_BIN: - // BIN/VEC are packed by default + 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 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(); - - 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); + 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); return NULL; } // endif getdef #else // !__WIN__ const char *error = NULL; - + #if 0 // Don't know what all this stuff does - Dl_info dl_info; + Dl_info dl_info; - // The OEM lib must retrieve exported CONNECT variables + // 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<b)?(a):(b)) +#endif // MY_GLOBAL_H
\ No newline at end of file diff --git a/storage/connect/restget.cpp b/storage/connect/restget.cpp new file mode 100644 index 00000000000..6b184ae6926 --- /dev/null +++ b/storage/connect/restget.cpp @@ -0,0 +1,94 @@ +/************* Restget C++ Program Source Code File (.CPP) *************/ +/* Adapted from the sample program of the Casablanca tutorial. */ +/* Copyright Olivier Bertrand 2019. */ +/***********************************************************************/ +#include <cpprest/filestream.h> +#include <cpprest/http_client.h> +#if defined(MARIADB) +#include <my_global.h> +#else +#include "mini-global.h" +#define _OS_H_INCLUDED // Prevent os.h to be called +#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; + bool xt = trace(515); + auto fileStream = std::make_shared<ostream>(); + + if (!http || !fn) { + strcpy(g->Message, "Missing http or filename"); + return 2; + } // endif + + if (xt) + htrc("restGetFile: fn=%s\n", fn); + + // Open stream to output file. + pplx::task<void> requestTask = fstream::open_ostream(to_string_t(fn)) + .then([=](ostream outFile) { + *fileStream= outFile; + + if (xt) + htrc("Outfile isopen=%d\n", outFile.is_open()); + + // 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 (xt) + htrc("Received response status code:%u\n", + response.status_code()); + + // Write response body into the file. + return response.body().read_to_end(fileStream->streambuf()); + }) + + // Close the file stream. + .then([=](size_t n) { + if (xt) + htrc("Return size=%u\n", n); + + return fileStream->close(); + }); + + // Wait for all the outstanding I/O to complete and handle any exceptions + try { + requestTask.wait(); + + if (xt) + htrc("In Wait\n"); + + } catch (const std::exception &e) { + if (xt) + htrc("Error exception: %s\n", e.what()); + sprintf(g->Message, "Error exception: %s", e.what()); + rc= 1; + } // end try/catch + + if (xt) + htrc("restget done: rc=%d\n", rc); + + return rc; +} // end of restGetFile diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp index 4d9a46b6af5..847fd515860 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -193,7 +193,7 @@ PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info) if (tdp->Zipped) tcvp = new(g)TDBCSV(tdp, new(g)UNZFAM(tdp)); else -#endif +#endif // ZIP_SUPPORT tcvp = new(g) TDBCSV(tdp, new(g) DOSFAM(tdp)); tcvp->SetMode(MODE_READ); diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index 3576f7ef0d5..4d834bcf9e0 100644 --- a/storage/connect/tabjdbc.cpp +++ b/storage/connect/tabjdbc.cpp @@ -643,7 +643,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 1a7dbd485c6..a96b7fe46d5 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,382 +159,382 @@ 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); - - if (level) { - lvl = atoi(level); - lvl = (lvl > 16) ? 16 : lvl; - } else - lvl = 0; - - sep = GetStringTableOption(g, topt, "Separator", "."); - - /*********************************************************************/ - /* Open the input file. */ - /*********************************************************************/ - tdp = new(g) JSONDEF; + 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; + + sep = GetStringTableOption(g, topt, "Separator", "."); + + /*********************************************************************/ + /* 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); - - 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); - - 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 (trace(1)) - htrc("File %s objname=%s pretty=%d lvl=%d\n", - tdp->Fn, tdp->Objname, tdp->Pretty, lvl); - - if (tdp->Uri) { + tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL); + + 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); + + 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 (trace(1)) + htrc("File %s objname=%s pretty=%d lvl=%d\n", + tdp->Fn, tdp->Objname, tdp->Pretty, lvl); + + 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)); - - 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 - } - - tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF); - - if (tdp->Zipped) { + } else + tjsp = new(g) TDBJSON(tdp, new(g) MAPFAM(tdp)); + + 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 + } + + tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF); + + 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 - - } else - tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp)); - - 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); - - 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 - - } // endif pretty - - 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; - - 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; - - if (Find(g, jpp->GetVal(), colname, MY_MIN(lvl, 0))) - goto err; - - } // endfor jpp - - // 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 - - } else - jsp = tjsp->GetDoc()->GetValue(i); - - if (!(row = (jsp) ? jsp->GetObject() : NULL)) - break; - - } // endfor i - - if (tdp->Pretty != 2) - tjnp->CloseDB(g); - - return n; + } // endif Driver + + } else + tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp)); + + 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); + + 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 + + } // endif pretty + + 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; + + 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; + + if (Find(g, jpp->GetVal(), colname, MY_MIN(lvl, 0))) + goto err; + + } // endfor jpp + + // 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 + + } else + jsp = tjsp->GetDoc()->GetValue(i); + + if (!(row = (jsp) ? jsp->GetObject() : NULL)) + break; + + } // endfor i + + if (tdp->Pretty != 2) + tjnp->CloseDB(g); + + 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; - - 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(); - - switch (jsp->GetType()) { - case TYPE_JOB: - job = (PJOB)jsp; - - 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 (Find(g, jrp->GetVal(), k, j + 1)) - return true; - - *p = *pc = 0; - } // endfor jrp - - 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); - - 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 (all) - strncat(strncat(colname, "_", 64), buf, 64); - - } else - strncat(fmt, (tdp->Uri ? sep : "[*]"), 128); - - if (Find(g, jar->GetValue(k), "", j)) - return true; - - *p = *pc = 0; - } // endfor k - - 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; - - AddColumn(g); - return false; -} // end of Find + 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); + + p = fmt + strlen(fmt); + jsp = jvp->GetJson(); + + switch (jsp->GetType()) { + case TYPE_JOB: + job = (PJOB)jsp; + + 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 (Find(g, jrp->GetVal(), k, j + 1)) + return true; + + *p = *pc = 0; + } // endfor jrp + + 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); + + 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 (all) + strncat(strncat(colname, "_", 64), buf, 64); + + } else + strncat(fmt, (tdp->Uri ? sep : "[*]"), 128); + + if (Find(g, jar->GetValue(k), "", j)) + return true; + + *p = *pc = 0; + } // endfor k + + 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; + + AddColumn(g); + return false; +} // end of Find void JSONDISC::AddColumn(PGLOBAL g) { - 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; - - 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 - - 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)); - - 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; - - n++; - } // endif jcp - - if (jcp) - pjcp = jcp; + 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; + + 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 + + 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)); + + 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; + + n++; + } // endif jcp + + if (jcp) + pjcp = jcp; } // end of AddColumn @@ -550,13 +550,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 /***********************************************************************/ @@ -564,41 +564,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 uri when called from REST OEM module - 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 /***********************************************************************/ @@ -606,6 +606,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); @@ -620,47 +623,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); @@ -670,7 +673,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); @@ -678,41 +681,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 - - } else { - if (Zipped) { + 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) { #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) @@ -740,16 +743,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 @@ -763,7 +766,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; @@ -779,7 +782,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; @@ -788,7 +791,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; @@ -862,33 +865,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) { @@ -913,15 +916,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 /***********************************************************************/ @@ -971,27 +974,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; - - // 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; - - } // endif ReadDB + } 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); + + 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 return rc; } // end of ReadDB @@ -1001,68 +1004,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 /***********************************************************************/ @@ -1097,11 +1100,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 ------------------------------ */ @@ -1113,12 +1116,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; @@ -1130,14 +1133,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 @@ -1155,7 +1158,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 @@ -1181,130 +1184,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]; - - //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 - - } else - b = true; - - // 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; - - } // 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 - - 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 - - } 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 - - } 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); - - 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 - - if (jnp->Valp) - MulVal = AllocateValue(g, jnp->Valp); - - return false; + int n; + bool dg = true, b = false; + PJNODE jnp = &Nodes[i]; + + //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 + + } else + b = true; + + // 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; + + } // 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 + + 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 + + } 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 + + } 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); + + 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 + + if (jnp->Valp) + MulVal = AllocateValue(g, jnp->Valp); + + return false; } // end of SetArrayOptions /***********************************************************************/ @@ -1315,87 +1318,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; - - 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 - - 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++; - - // 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)); - - // 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; - - } // endif p1 - - 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; - - } 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 - - Nod = i; + char *p, *p1 = NULL, *p2 = NULL, *pbuf = NULL; + int i; + bool a; + + 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 + + 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++; + + // 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)); + + // 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; + + } // endif p1 + + 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; + + } 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 + + Nod = i; fin: - MulVal = AllocateValue(g, Value); - Parsed = true; - return false; + MulVal = AllocateValue(g, Value); + Parsed = true; + return false; } // end of ParseJpath /***********************************************************************/ @@ -1403,66 +1406,66 @@ fin: /***********************************************************************/ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj) { - 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; - - 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++; - - 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; - - *p2++ = '.'; - break; - case '[': - if (*(p2 - 1) != '.') - *p2++ = '.'; - - i = 1; - break; - case '*': - if (*(p2 - 1) == '.' && !*(p1 + 1)) { - p2--; // Suppress last :* - break; - } // endif p2 - - default: - *p2++ = *p1; - break; - } // endswitch p1; - - *p2 = 0; - return mgopath; - } else - return NULL; + 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; + + 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++; + + 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; + + *p2++ = '.'; + break; + case '[': + if (*(p2 - 1) != '.') + *p2++ = '.'; + + i = 1; + break; + case '*': + if (*(p2 - 1) == '.' && !*(p1 + 1)) { + p2--; // Suppress last :* + break; + } // endif p2 + + default: + *p2++ = *p1; + break; + } // endswitch p1; + + *p2 = 0; + return mgopath; + } else + return NULL; } // end of GetJpath @@ -1471,7 +1474,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 @@ -1486,22 +1489,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); @@ -1511,16 +1514,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 + vp->Reset(); + vp->SetNull(true); + } // endswitch Type - } else { - vp->Reset(); - vp->SetNull(true); - } // endif val + } else { + vp->Reset(); + vp->SetNull(true); + } // endif val } // end of SetJsonValue @@ -1532,8 +1535,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) @@ -1580,11 +1583,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: @@ -1613,17 +1616,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)); @@ -1638,7 +1641,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; @@ -1649,58 +1652,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; @@ -1715,16 +1718,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); @@ -1754,8 +1757,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: @@ -1766,19 +1769,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: @@ -1828,10 +1831,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. */ @@ -1865,8 +1868,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) @@ -1888,10 +1891,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); @@ -1982,7 +1985,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; @@ -2011,70 +2014,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++; - - /*********************************************************************/ - /* 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 - - 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 - - } 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 - - 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); - - if (!val) { - sprintf(g->Message, "Cannot find array value %d", i); - return RC_FX; - } // endif val - - } // endif - - jsp = val->GetJson(); - } // endfor objpath - - } // endif 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; + + 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); + + 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++; + + } // endif objpath + + 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); + + if (!val) { + sprintf(g->Message, "Cannot find array value %d", i); + return RC_FX; + } // endif val + + } // endif + + jsp = val->GetJson(); + } // endfor 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; @@ -2152,7 +2155,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. */ @@ -2230,11 +2233,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 /***********************************************************************/ @@ -2244,7 +2247,7 @@ int TDBJSON::ReadDB(PGLOBAL) { int rc; - N++; + N++; if (NextSame) { SameRow = NextSame; @@ -2355,8 +2358,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 new file mode 100644 index 00000000000..9e1a643c89f --- /dev/null +++ b/storage/connect/tabrest.cpp @@ -0,0 +1,201 @@ +/*************** Rest C++ Program Source Code File (.CPP) **************/ +/* PROGRAM NAME: Rest Version 1.5 */ +/* (C) Copyright to the author Olivier BERTRAND 2018 - 2019 */ +/* 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 <my_global.h> // 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: */ +/* 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 "tabdos.h" +#include "plgxml.h" +#include "tabxml.h" +#include "tabjson.h" +#include "tabfmt.h" +#include "tabrest.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__ + +#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 + 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"); +#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); + 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 + 1]; + int rc = 0, n; + LPCSTR ftype; + +#if defined(MARIADB) + ftype = GetStringCatInfo(g, "Type", "JSON"); +#else // !MARIADB + // OEM tables must specify the file type + ftype = GetStringCatInfo(g, "Ftype", "JSON"); +#endif // !MARIADB + + if (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; + + 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()); + strncat(strcpy(filename, GetPath()), Fn, _MAX_PATH); + + // Retrieve the file from the web and copy it locally + rc = restGetFile(g, Http, Uri, filename); + + 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 + + // Do make the table/view definition + if (Tdp && Tdp->Define(g, Cat, Name, Schema, "REST")) + Tdp = NULL; // Error occured + + if (trace(515)) + htrc("Tdp defined\n", rc); + + // 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 (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"); + 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 b2dbdd70e06..1150824464f 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -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/user_connect.cc b/storage/connect/user_connect.cc index dec50aa8e6c..8abd33079d6 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 02110-1335 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 af40a88cea0..53064e620f2 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 02110-1335 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file user_connect.h diff --git a/storage/heap/hp_scan.c b/storage/heap/hp_scan.c index 3315cb05b3f..f07efe6cf67 100644 --- a/storage/heap/hp_scan.c +++ b/storage/heap/hp_scan.c @@ -50,7 +50,9 @@ int heap_scan(register HP_INFO *info, uchar *record) } else { - info->next_block+=share->block.records_in_block; + /* increase next_block to the next records_in_block boundary */ + ulong rem= info->next_block % share->block.records_in_block; + info->next_block+=share->block.records_in_block - rem; if (info->next_block >= share->records+share->deleted) { info->next_block= share->records+share->deleted; diff --git a/storage/innobase/btr/btr0scrub.cc b/storage/innobase/btr/btr0scrub.cc index 67c06016c72..3c367fb2784 100644 --- a/storage/innobase/btr/btr0scrub.cc +++ b/storage/innobase/btr/btr0scrub.cc @@ -626,13 +626,8 @@ btr_scrub_get_table_and_index( scrub_data->current_table = NULL; } - /* argument to dict_table_open_on_index_id */ - bool dict_locked = true; - /* open table based on index_id */ - dict_table_t* table = dict_table_open_on_index_id( - index_id, - dict_locked); + dict_table_t* table = dict_table_open_on_index_id(index_id); if (table != NULL) { /* mark table as being scrubbed */ diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index c655d7a1587..ae13e5790d5 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1068,14 +1068,8 @@ buf_page_is_corrupted( size_t checksum_field2 = 0; uint32_t crc32 = 0; bool crc32_inited = false; - ulint zip_size = 0; bool crc32_chksum = false; - - zip_size = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags); - if (zip_size) { - zip_size = (UNIV_ZIP_SIZE_MIN >> 1) << zip_size; - } - + const ulint zip_size = fil_space_t::zip_size(fsp_flags); ulint page_type = mach_read_from_2(read_buf + FIL_PAGE_TYPE); /* We can trust page type if page compression is set on tablespace diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index b5bd73ed5ec..fea537166f9 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -266,7 +266,7 @@ dict_table_try_drop_aborted( if (table == NULL) { table = dict_table_open_on_id_low( - table_id, DICT_ERR_IGNORE_NONE, FALSE); + table_id, DICT_ERR_IGNORE_FK_NOKEY, FALSE); } else { ut_ad(table->id == table_id); } @@ -750,7 +750,7 @@ dict_table_open_on_id( table_id, table_op == DICT_TABLE_OP_LOAD_TABLESPACE ? DICT_ERR_IGNORE_RECOVER_LOCK - : DICT_ERR_IGNORE_NONE, + : DICT_ERR_IGNORE_FK_NOKEY, table_op == DICT_TABLE_OP_OPEN_ONLY_IF_CACHED); if (table != NULL) { @@ -896,7 +896,7 @@ dict_table_open_on_name( if (table != NULL) { /* If table is encrypted or corrupted */ - if (ignore_err == DICT_ERR_IGNORE_NONE + if (!(ignore_err & ~DICT_ERR_IGNORE_FK_NOKEY) && !table->is_readable()) { /* Make life easy for drop table. */ dict_sys.prevent_eviction(table); @@ -2764,11 +2764,6 @@ dict_index_build_internal_fts( } /*====================== FOREIGN KEY PROCESSING ========================*/ -#define DB_FOREIGN_KEY_IS_PREFIX_INDEX 200 -#define DB_FOREIGN_KEY_COL_NOT_NULL 201 -#define DB_FOREIGN_KEY_COLS_NOT_EQUAL 202 -#define DB_FOREIGN_KEY_INDEX_NOT_FOUND 203 - /** Check whether the dict_table_t is a partition. A partitioned table on the SQL level is composed of InnoDB tables, where each InnoDB table is a [sub]partition including its secondary indexes @@ -2875,7 +2870,7 @@ dict_foreign_find_index( /*!< in: nonzero if none of the columns must be declared NOT NULL */ - ulint* error, /*!< out: error code */ + fkerr_t* error, /*!< out: error code */ ulint* err_col_no, /*!< out: column number where error happened */ @@ -2883,17 +2878,15 @@ dict_foreign_find_index( /*!< out: index where error happened */ { - dict_index_t* index; - ut_ad(mutex_own(&dict_sys.mutex)); if (error) { - *error = DB_FOREIGN_KEY_INDEX_NOT_FOUND; + *error = FK_INDEX_NOT_FOUND; } - index = dict_table_get_first_index(table); - - while (index != NULL) { + for (dict_index_t* index = dict_table_get_first_index(table); + index; + index = dict_table_get_next_index(index)) { if (types_idx != index && !index->to_be_dropped && !dict_index_is_online_ddl(index) @@ -2901,42 +2894,17 @@ dict_foreign_find_index( table, col_names, columns, n_cols, index, types_idx, check_charsets, check_null, - error, err_col_no,err_index)) { + error, err_col_no, err_index)) { if (error) { - *error = DB_SUCCESS; + *error = FK_SUCCESS; } return(index); } - - index = dict_table_get_next_index(index); } return(NULL); } -#ifdef WITH_WSREP -dict_index_t* -wsrep_dict_foreign_find_index( -/*====================*/ - dict_table_t* table, /*!< in: table */ - const char** col_names, /*!< in: column names, or NULL - to use table->col_names */ - const char** columns,/*!< in: array of column names */ - ulint n_cols, /*!< in: number of columns */ - dict_index_t* types_idx, /*!< in: NULL or an index to whose types the - column types must match */ - ibool check_charsets, - /*!< in: whether to check charsets. - only has an effect if types_idx != NULL */ - ulint check_null) - /*!< in: nonzero if none of the columns must - be declared NOT NULL */ -{ - return dict_foreign_find_index( - table, col_names, columns, n_cols, types_idx, check_charsets, - check_null, NULL, NULL, NULL); -} -#endif /* WITH_WSREP */ /**********************************************************************//** Report an error in a foreign key definition. */ static @@ -3033,15 +3001,11 @@ dict_foreign_add_to_cache( } if (ref_table && !for_in_cache->referenced_table) { - ulint index_error; - ulint err_col; - dict_index_t *err_index=NULL; - index = dict_foreign_find_index( ref_table, NULL, for_in_cache->referenced_col_names, for_in_cache->n_fields, for_in_cache->foreign_index, - check_charsets, false, &index_error, &err_col, &err_index); + check_charsets, false); if (index == NULL && !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) { @@ -3073,10 +3037,6 @@ dict_foreign_add_to_cache( } if (for_table && !for_in_cache->foreign_table) { - ulint index_error; - ulint err_col; - dict_index_t *err_index=NULL; - index = dict_foreign_find_index( for_table, col_names, for_in_cache->foreign_col_names, @@ -3084,8 +3044,7 @@ dict_foreign_add_to_cache( for_in_cache->referenced_index, check_charsets, for_in_cache->type & (DICT_FOREIGN_ON_DELETE_SET_NULL - | DICT_FOREIGN_ON_UPDATE_SET_NULL), - &index_error, &err_col, &err_index); + | DICT_FOREIGN_ON_UPDATE_SET_NULL)); if (index == NULL && !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) { @@ -3797,7 +3756,7 @@ dict_foreign_push_index_error( const char* latest_foreign, /*!< in: start of latest foreign key constraint name */ const char** columns, /*!< in: foreign key columns */ - ulint index_error, /*!< in: error code */ + fkerr_t index_error, /*!< in: error code */ ulint err_col, /*!< in: column where error happened */ dict_index_t* err_index, /*!< in: index where error happened @@ -3806,37 +3765,37 @@ dict_foreign_push_index_error( FILE* ef) /*!< in: output stream */ { switch (index_error) { - case DB_FOREIGN_KEY_INDEX_NOT_FOUND: { + case FK_SUCCESS: + break; + case FK_INDEX_NOT_FOUND: fprintf(ef, - "%s table '%s' with foreign key constraint" + "%s table %s with foreign key constraint" " failed. There is no index in the referenced" " table where the referenced columns appear" " as the first columns near '%s'.\n", operation, create_name, latest_foreign); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, - "%s table '%s' with foreign key constraint" + "%s table %s with foreign key constraint" " failed. There is no index in the referenced" " table where the referenced columns appear" " as the first columns near '%s'.", operation, create_name, latest_foreign); - break; - } - case DB_FOREIGN_KEY_IS_PREFIX_INDEX: { + return; + case FK_IS_PREFIX_INDEX: fprintf(ef, - "%s table '%s' with foreign key constraint" + "%s table %s with foreign key constraint" " failed. There is only prefix index in the referenced" " table where the referenced columns appear" " as the first columns near '%s'.\n", operation, create_name, latest_foreign); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, - "%s table '%s' with foreign key constraint" + "%s table %s with foreign key constraint" " failed. There is only prefix index in the referenced" " table where the referenced columns appear" " as the first columns near '%s'.", operation, create_name, latest_foreign); - break; - } - case DB_FOREIGN_KEY_COL_NOT_NULL: { + return; + case FK_COL_NOT_NULL: fprintf(ef, "%s table %s with foreign key constraint" " failed. You have defined a SET NULL condition but " @@ -3847,9 +3806,8 @@ dict_foreign_push_index_error( " failed. You have defined a SET NULL condition but " "column '%s' on index is defined as NOT NULL near '%s'.", operation, create_name, columns[err_col], latest_foreign); - break; - } - case DB_FOREIGN_KEY_COLS_NOT_EQUAL: { + return; + case FK_COLS_NOT_EQUAL: dict_field_t* field; const char* col_name; field = dict_index_get_nth_field(err_index, err_col); @@ -3868,11 +3826,9 @@ dict_foreign_push_index_error( " failed. Field type or character set for column '%s' " "does not mach referenced column '%s' near '%s'.", operation, create_name, columns[err_col], col_name, latest_foreign); - break; - } - default: - ut_error; + return; } + DBUG_ASSERT(!"unknown error"); } /*********************************************************************//** @@ -3904,7 +3860,7 @@ dict_create_foreign_constraints_low( const char* start_of_latest_foreign = sql_string; const char* start_of_latest_set = NULL; FILE* ef = dict_foreign_err_file; - ulint index_error = DB_SUCCESS; + fkerr_t index_error = FK_SUCCESS; dict_index_t* err_index = NULL; ulint err_col; const char* constraint_name; @@ -6247,7 +6203,7 @@ dict_foreign_qualify_index( /*!< in: nonzero if none of the columns must be declared NOT NULL */ - ulint* error, /*!< out: error code */ + fkerr_t* error, /*!< out: error code */ ulint* err_col_no, /*!< out: column number where error happened */ @@ -6275,7 +6231,7 @@ dict_foreign_qualify_index( /* We do not accept column prefix indexes here */ if (error && err_col_no && err_index) { - *error = DB_FOREIGN_KEY_IS_PREFIX_INDEX; + *error = FK_IS_PREFIX_INDEX; *err_col_no = i; *err_index = (dict_index_t*)index; } @@ -6285,7 +6241,7 @@ dict_foreign_qualify_index( if (check_null && (field->col->prtype & DATA_NOT_NULL)) { if (error && err_col_no && err_index) { - *error = DB_FOREIGN_KEY_COL_NOT_NULL; + *error = FK_COL_NOT_NULL; *err_col_no = i; *err_index = (dict_index_t*)index; } @@ -6315,7 +6271,7 @@ dict_foreign_qualify_index( dict_index_get_nth_col(types_idx, i), check_charsets)) { if (error && err_col_no && err_index) { - *error = DB_FOREIGN_KEY_COLS_NOT_EQUAL; + *error = FK_COLS_NOT_EQUAL; *err_col_no = i; *err_index = (dict_index_t*)index; } diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 173e8121ee1..4adf886118b 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -3077,7 +3077,7 @@ func_exit: mem_heap_free(heap); ut_ad(!table - || ignore_err != DICT_ERR_IGNORE_NONE + || (ignore_err & ~DICT_ERR_IGNORE_FK_NOKEY) || !table->is_readable() || !table->corrupted); @@ -3766,29 +3766,14 @@ dict_load_table_id_on_index_id( return(found); } -UNIV_INTERN -dict_table_t* -dict_table_open_on_index_id( -/*========================*/ - index_id_t index_id, /*!< in: index id */ - bool dict_locked) /*!< in: dict locked */ +dict_table_t* dict_table_open_on_index_id(index_id_t index_id) { - if (!dict_locked) { - mutex_enter(&dict_sys.mutex); - } - - ut_ad(mutex_own(&dict_sys.mutex)); table_id_t table_id; dict_table_t * table = NULL; if (dict_load_table_id_on_index_id(index_id, &table_id)) { - bool local_dict_locked = true; - table = dict_table_open_on_id(table_id, - local_dict_locked, + table = dict_table_open_on_id(table_id, true, DICT_TABLE_OP_LOAD_TABLESPACE); } - if (!dict_locked) { - mutex_exit(&dict_sys.mutex); - } return table; } diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 50b73222607..ad74525be15 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -354,6 +354,34 @@ fil_space_destroy_crypt_data( } } +/** Fill crypt data information to the give page. +It should be called during ibd file creation. +@param[in] flags tablespace flags +@param[in,out] page first page of the tablespace */ +void +fil_space_crypt_t::fill_page0( + ulint flags, + byte* page) +{ + const uint len = sizeof(iv); + const ulint offset = FSP_HEADER_OFFSET + + fsp_header_get_encryption_offset( + fil_space_t::zip_size(flags)); + page0_offset = offset; + + memcpy(page + offset, CRYPT_MAGIC, MAGIC_SZ); + mach_write_to_1(page + offset + MAGIC_SZ, type); + mach_write_to_1(page + offset + MAGIC_SZ + 1, len); + memcpy(page + offset + MAGIC_SZ + 2, &iv, len); + + mach_write_to_4(page + offset + MAGIC_SZ + 2 + len, + min_key_version); + mach_write_to_4(page + offset + MAGIC_SZ + 2 + len + 4, + key_id); + mach_write_to_1(page + offset + MAGIC_SZ + 2 + len + 8, + encryption); +} + /****************************************************************** Write crypt data to a page (0) @param[in] space tablespace @@ -2488,9 +2516,11 @@ static void fil_crypt_rotation_list_fill() /* Protect the tablespace while we may release fil_system.mutex. */ space->n_pending_ops++; +#ifndef DBUG_OFF fil_space_t* s= fil_system.read_page0( space->id); ut_ad(!s || s == space); +#endif space->n_pending_ops--; if (!space->size) { /* Page 0 was not loaded. diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 0c00671214b..b46a5d33843 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -725,6 +725,7 @@ static void fil_flush_low(fil_space_t* space, bool metadata = false) switch (space->purpose) { case FIL_TYPE_TEMPORARY: ut_ad(0); // we already checked for this + /* fall through */ case FIL_TYPE_TABLESPACE: case FIL_TYPE_IMPORT: fil_n_pending_tablespace_flushes++; @@ -2927,8 +2928,6 @@ fil_ibd_create( byte* page; bool success; bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags) != 0; - fil_space_t* space = NULL; - fil_space_crypt_t *crypt_data = NULL; ut_ad(!is_system_tablespace(space_id)); ut_ad(!srv_read_only_mode); @@ -3019,6 +3018,19 @@ err_exit: fsp_header_init_fields(page, space_id, flags); mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id); + /* Create crypt data if the tablespace is either encrypted or user has + requested it to remain unencrypted. */ + fil_space_crypt_t *crypt_data = (mode != FIL_ENCRYPTION_DEFAULT + || srv_encrypt_tables) + ? fil_space_create_crypt_data(mode, key_id) + : NULL; + + if (crypt_data) { + /* Write crypt data information in page0 while creating + ibd file. */ + crypt_data->fill_page0(flags, page); + } + if (ulint zip_size = fil_space_t::zip_size(flags)) { page_zip_des_t page_zip; page_zip_set_size(&page_zip, zip_size); @@ -3066,15 +3078,9 @@ err_exit: } } - /* Create crypt data if the tablespace is either encrypted or user has - requested it to remain unencrypted. */ - if (mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF || - srv_encrypt_tables) { - crypt_data = fil_space_create_crypt_data(mode, key_id); - } - - space = fil_space_create(name, space_id, flags, FIL_TYPE_TABLESPACE, - crypt_data, mode); + fil_space_t* space = fil_space_create(name, space_id, flags, + FIL_TYPE_TABLESPACE, + crypt_data, mode); if (!space) { free(crypt_data); *err = DB_ERROR; diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index 4143e246f99..4869160b883 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -699,7 +699,8 @@ Datafile::find_space_id() /* For noncompressed pages, the page size must be equal to srv_page_size. */ - if (page_size == srv_page_size) { + if (page_size == srv_page_size + && !fil_space_t::zip_size(fsp_flags)) { noncompressed_ok = !buf_page_is_corrupted( false, page, fsp_flags); } @@ -707,7 +708,7 @@ Datafile::find_space_id() bool compressed_ok = false; if (srv_page_size <= UNIV_PAGE_SIZE_DEF - && page_size <= srv_page_size) { + && page_size == fil_space_t::zip_size(fsp_flags)) { compressed_ok = !buf_page_is_corrupted( false, page, fsp_flags); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 116625bbe11..9f4c04741b6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -218,6 +218,7 @@ extern my_bool srv_background_scrub_data_compressed; extern uint srv_background_scrub_data_interval; extern uint srv_background_scrub_data_check_interval; #ifdef UNIV_DEBUG +my_bool innodb_evict_tables_on_commit_debug; extern my_bool srv_scrub_force_testing; #endif @@ -2988,7 +2989,7 @@ static bool innobase_query_caching_table_check( const char* norm_name) { dict_table_t* table = dict_table_open_on_name( - norm_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); + norm_name, FALSE, FALSE, DICT_ERR_IGNORE_FK_NOKEY); if (table == NULL) { return false; @@ -5938,9 +5939,7 @@ ha_innobase::open(const char* name, int, uint) the rollback invoking dict_index_t::clear_instant_alter() while open table handles exist in client connections. */ - dict_table_t* ib_table; char norm_name[FN_REFLEN]; - dict_err_ignore_t ignore_err = DICT_ERR_IGNORE_NONE; DBUG_ENTER("ha_innobase::open"); @@ -5954,15 +5953,8 @@ ha_innobase::open(const char* name, int, uint) char* is_part = is_partition(norm_name); THD* thd = ha_thd(); - - /* Check whether FOREIGN_KEY_CHECKS is set to 0. If so, the table - can be opened even if some FK indexes are missing. If not, the table - can't be opened in the same situation */ - if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) { - ignore_err = DICT_ERR_IGNORE_FK_NOKEY; - } - - ib_table = open_dict_table(name, norm_name, is_part, ignore_err); + dict_table_t* ib_table = open_dict_table(name, norm_name, is_part, + DICT_ERR_IGNORE_FK_NOKEY); DEBUG_SYNC(thd, "ib_open_after_dict_open"); @@ -10001,17 +9993,6 @@ next_record: } #ifdef WITH_WSREP -extern dict_index_t* -wsrep_dict_foreign_find_index( -/*==========================*/ - dict_table_t* table, - const char** col_names, - const char** columns, - ulint n_cols, - dict_index_t* types_idx, - ibool check_charsets, - ulint check_null); - inline const char* wsrep_key_type_to_str(Wsrep_service_key_type type) @@ -10075,7 +10056,7 @@ wsrep_append_foreign_key( foreign->referenced_table_name_lookup); if (foreign->referenced_table) { foreign->referenced_index = - wsrep_dict_foreign_find_index( + dict_foreign_find_index( foreign->referenced_table, NULL, foreign->referenced_col_names, foreign->n_fields, @@ -10089,7 +10070,7 @@ wsrep_append_foreign_key( if (foreign->foreign_table) { foreign->foreign_index = - wsrep_dict_foreign_find_index( + dict_foreign_find_index( foreign->foreign_table, NULL, foreign->foreign_col_names, foreign->n_fields, @@ -13028,8 +13009,8 @@ innobase_rename_table( row_mysql_lock_data_dictionary(trx); } - dict_table_t* table = dict_table_open_on_name(norm_from, TRUE, FALSE, - DICT_ERR_IGNORE_NONE); + dict_table_t* table = dict_table_open_on_name( + norm_from, TRUE, FALSE, DICT_ERR_IGNORE_FK_NOKEY); /* Since DICT_BG_YIELD has sleep for 250 milliseconds, Convert lock_wait_timeout unit from second to 250 milliseconds */ @@ -14149,7 +14130,7 @@ ha_innobase::defragment_table( normalize_table_name(norm_name, name); table = dict_table_open_on_name(norm_name, FALSE, - FALSE, DICT_ERR_IGNORE_NONE); + FALSE, DICT_ERR_IGNORE_FK_NOKEY); for (index = dict_table_get_first_index(table); index; index = dict_table_get_next_index(index)) { @@ -19394,6 +19375,11 @@ static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug, " but the each purges were not done yet.", NULL, NULL, FALSE); +static MYSQL_SYSVAR_BOOL(evict_tables_on_commit_debug, + innodb_evict_tables_on_commit_debug, PLUGIN_VAR_OPCMDARG, + "On transaction commit, try to evict tables from the data dictionary cache.", + NULL, NULL, FALSE); + static MYSQL_SYSVAR_UINT(data_file_size_debug, srv_sys_space_size_debug, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, @@ -19755,6 +19741,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(trx_rseg_n_slots_debug), MYSQL_SYSVAR(limit_optimistic_insert_debug), MYSQL_SYSVAR(trx_purge_view_update_only_debug), + MYSQL_SYSVAR(evict_tables_on_commit_debug), MYSQL_SYSVAR(data_file_size_debug), MYSQL_SYSVAR(fil_make_page_dirty_debug), MYSQL_SYSVAR(saved_page_number_debug), diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 3d8f068b188..f280c735e05 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -3181,7 +3181,7 @@ innobase_col_to_mysql( case DATA_SYS: /* These column types should never be shipped to MySQL. */ ut_ad(0); - + /* fall through */ case DATA_FLOAT: case DATA_DOUBLE: case DATA_DECIMAL: @@ -9935,8 +9935,7 @@ commit_cache_rebuild( /** Set of column numbers */ typedef std::set<ulint, std::less<ulint>, ut_allocator<ulint> > col_set; -/** Store the column number of the columns in a list belonging -to indexes which are not being dropped. +/** Collect (not instantly dropped) columns from dropped indexes @param[in] ctx In-place ALTER TABLE context @param[in, out] drop_col_list list which will be set, containing columns which is part of index being dropped @@ -9945,7 +9944,7 @@ to indexes which are not being dropped. being dropped */ static void -get_col_list_to_be_dropped( +collect_columns_from_dropped_indexes( const ha_innobase_inplace_ctx* ctx, col_set& drop_col_list, col_set& drop_v_col_list) @@ -9966,6 +9965,12 @@ get_col_list_to_be_dropped( } else { ulint col_no = dict_col_get_no(idx_col); + if (ctx->col_map + && ctx->col_map[col_no] + == ULINT_UNDEFINED) { + // this column was instantly dropped + continue; + } drop_col_list.insert(col_no); } } @@ -10282,25 +10287,21 @@ commit_cache_norebuild( col_set drop_list; col_set v_drop_list; - col_set::const_iterator col_it; /* Check if the column, part of an index to be dropped is part of any other index which is not being dropped. If it so, then set the ord_part of the column to 0. */ - get_col_list_to_be_dropped(ctx, drop_list, v_drop_list); + collect_columns_from_dropped_indexes(ctx, drop_list, v_drop_list); - for (col_it = drop_list.begin(); col_it != drop_list.end(); ++col_it) { - if (!check_col_exists_in_indexes(ctx->new_table, - *col_it, false)) { - ctx->new_table->cols[*col_it].ord_part = 0; + for (ulint col : drop_list) { + if (!check_col_exists_in_indexes(ctx->new_table, col, false)) { + ctx->new_table->cols[col].ord_part = 0; } } - for (col_it = v_drop_list.begin(); - col_it != v_drop_list.end(); ++col_it) { - if (!check_col_exists_in_indexes(ctx->new_table, - *col_it, true)) { - ctx->new_table->v_cols[*col_it].m_col.ord_part = 0; + for (ulint col : v_drop_list) { + if (!check_col_exists_in_indexes(ctx->new_table, col, true)) { + ctx->new_table->v_cols[col].m_col.ord_part = 0; } } diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 99b6971f603..32782c27b55 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -116,12 +116,7 @@ dict_table_open_on_id( /**********************************************************************//** Returns a table object based on table id. @return table, NULL if does not exist */ -UNIV_INTERN -dict_table_t* -dict_table_open_on_index_id( -/*==================*/ - table_id_t table_id, /*!< in: table id */ - bool dict_locked) /*!< in: TRUE=data dictionary locked */ +dict_table_t* dict_table_open_on_index_id(index_id_t index_id) __attribute__((warn_unused_result)); /********************************************************************//** Decrements the count of open handles to a table. */ @@ -489,6 +484,21 @@ dict_table_open_on_name( dict_err_ignore_t ignore_err) MY_ATTRIBUTE((warn_unused_result)); +/** Outcome of dict_foreign_find_index() or dict_foreign_qualify_index() */ +enum fkerr_t +{ + /** A backing index was found for a FOREIGN KEY constraint */ + FK_SUCCESS = 0, + /** There is no index that covers the columns in the constraint. */ + FK_INDEX_NOT_FOUND, + /** The index is for a prefix index, not a full column. */ + FK_IS_PREFIX_INDEX, + /** A condition of SET NULL conflicts with a NOT NULL column. */ + FK_COL_NOT_NULL, + /** The column types do not match */ + FK_COLS_NOT_EQUAL +}; + /*********************************************************************//** Tries to find an index whose first fields are the columns in the array, in the same order and is not marked for deletion and is not the same @@ -515,11 +525,11 @@ dict_foreign_find_index( /*!< in: nonzero if none of the columns must be declared NOT NULL */ - ulint* error, /*!< out: error code */ - ulint* err_col_no, + fkerr_t* error = NULL, /*!< out: error code */ + ulint* err_col_no = NULL, /*!< out: column number where error happened */ - dict_index_t** err_index) + dict_index_t** err_index = NULL) /*!< out: index where error happened */ @@ -595,7 +605,7 @@ dict_foreign_qualify_index( /*!< in: nonzero if none of the columns must be declared NOT NULL */ - ulint* error, /*!< out: error code */ + fkerr_t* error, /*!< out: error code */ ulint* err_col_no, /*!< out: column number where error happened */ diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h index 9f6edb0351f..d0e1ddaa664 100644 --- a/storage/innobase/include/dict0types.h +++ b/storage/innobase/include/dict0types.h @@ -66,11 +66,11 @@ Note: please define the IGNORE_ERR_* as bits, so their value can be or-ed together */ enum dict_err_ignore_t { DICT_ERR_IGNORE_NONE = 0, /*!< no error to ignore */ - DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root - page is FIL_NULL or incorrect value */ - DICT_ERR_IGNORE_CORRUPT = 2, /*!< skip corrupted indexes */ - DICT_ERR_IGNORE_FK_NOKEY = 4, /*!< ignore error if any foreign + DICT_ERR_IGNORE_FK_NOKEY = 1, /*!< ignore error if any foreign key is missing */ + DICT_ERR_IGNORE_INDEX_ROOT = 2, /*!< ignore error if index root + page is FIL_NULL or incorrect value */ + DICT_ERR_IGNORE_CORRUPT = 4, /*!< skip corrupted indexes */ DICT_ERR_IGNORE_RECOVER_LOCK = 8, /*!< Used when recovering table locks for resurrected transactions. diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h index 7a54cb4d53f..79924edceb4 100644 --- a/storage/innobase/include/fil0crypt.h +++ b/storage/innobase/include/fil0crypt.h @@ -178,6 +178,12 @@ struct fil_space_crypt_t : st_encryption_scheme return (encryption == FIL_ENCRYPTION_OFF); } + /** Fill crypt data information to the give page. + It should be called during ibd file creation. + @param[in] flags tablespace flags + @param[in,out] page first page of the tablespace */ + void fill_page0(ulint flags, byte* page); + /** Write crypt data to a page (0) @param[in] space tablespace @param[in,out] page0 first page of the tablespace diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index d6188362e9a..e972fffa5bf 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -539,6 +539,7 @@ extern my_bool srv_ibuf_disable_background_merge; #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ #ifdef UNIV_DEBUG +extern my_bool innodb_evict_tables_on_commit_debug; extern my_bool srv_sync_debug; extern my_bool srv_purge_view_update_only_debug; diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 4175128217b..437459865fe 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -644,11 +644,8 @@ public: { mutex_enter(&element->mutex); lf_hash_search_unpin(pins); - trx= element->trx; - if (!trx); - else if (UNIV_UNLIKELY(trx_id != trx->id)) - trx= NULL; - else { + if ((trx= element->trx)) { + DBUG_ASSERT(trx_id == trx->id); if (do_ref_count) trx->reference(); ut_d(validate_element(trx)); diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 7e7558aff32..dc7a66ea317 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1217,9 +1217,7 @@ lock_sec_rec_some_has_impl( /* Some transaction may have an implicit x-lock on the record only if the max trx id for the page >= min trx id for the trx list, or - database recovery is running. We do not write the changes of a page - max trx id to the log, and therefore during recovery, this value - for a page may be incorrect. */ + database recovery is running. */ if (max_trx_id < trx_sys.get_min_trx_id()) { @@ -6192,9 +6190,6 @@ lock_trx_release_locks( /*--------------------------------------*/ trx_mutex_enter(trx); trx->state = TRX_STATE_COMMITTED_IN_MEMORY; - /* Ensure that rw_trx_hash_t::find() will no longer find - this transaction. */ - trx->id = 0; trx_mutex_exit(trx); /*--------------------------------------*/ diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 75e6b500c07..2c255478969 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -753,7 +753,7 @@ mtr_t::Command::prepare_write() switch (m_impl->m_log_mode) { case MTR_LOG_SHORT_INSERTS: ut_ad(0); - /* fall through (write no redo log) */ + /* fall through */ case MTR_LOG_NO_REDO: case MTR_LOG_NONE: ut_ad(m_impl->m_log.size() == 0); diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index a036821cab1..64e38f7ff2f 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -871,8 +871,12 @@ row_ins_foreign_report_add_err( fk_str = dict_print_info_on_foreign_key_in_create_format(trx, foreign, TRUE); fputs(fk_str.c_str(), ef); - fprintf(ef, " in parent table, in index %s", - foreign->foreign_index->name()); + if (foreign->foreign_index) { + fprintf(ef, " in parent table, in index %s", + foreign->foreign_index->name()); + } else { + fputs(" in parent table", ef); + } if (entry) { fputs(" tuple:\n", ef); /* TODO: DB_TRX_ID and DB_ROLL_PTR may be uninitialized. @@ -1656,34 +1660,51 @@ row_ins_check_foreign_constraint( || !check_table->is_readable() || check_index == NULL) { - if (!srv_read_only_mode && check_ref) { - FILE* ef = dict_foreign_err_file; - std::string fk_str; - - row_ins_set_detailed(trx, foreign); - - row_ins_foreign_trx_print(trx); - - fputs("Foreign key constraint fails for table ", ef); - ut_print_name(ef, trx, - foreign->foreign_table_name); - fputs(":\n", ef); - fk_str = dict_print_info_on_foreign_key_in_create_format( - trx, foreign, TRUE); - fputs(fk_str.c_str(), ef); - fprintf(ef, "\nTrying to add to index %s tuple:\n", - foreign->foreign_index->name()); + FILE* ef = dict_foreign_err_file; + std::string fk_str; + + row_ins_set_detailed(trx, foreign); + row_ins_foreign_trx_print(trx); + + fputs("Foreign key constraint fails for table ", ef); + ut_print_name(ef, trx, check_ref + ? foreign->foreign_table_name + : foreign->referenced_table_name); + fputs(":\n", ef); + fk_str = dict_print_info_on_foreign_key_in_create_format( + trx, foreign, TRUE); + fputs(fk_str.c_str(), ef); + if (check_ref) { + if (foreign->foreign_index) { + fprintf(ef, "\nTrying to add to index %s" + " tuple:\n", + foreign->foreign_index->name()); + } else { + fputs("\nTrying to add tuple:\n", ef); + } dtuple_print(ef, entry); fputs("\nBut the parent table ", ef); - ut_print_name(ef, trx, - foreign->referenced_table_name); - fputs("\nor its .ibd file does" + ut_print_name(ef, trx, foreign->referenced_table_name); + fputs("\nor its .ibd file or the required index does" " not currently exist!\n", ef); - mutex_exit(&dict_foreign_err_mutex); - err = DB_NO_REFERENCED_ROW; + } else { + if (foreign->referenced_index) { + fprintf(ef, "\nTrying to modify index %s" + " tuple:\n", + foreign->referenced_index->name()); + } else { + fputs("\nTrying to modify tuple:\n", ef); + } + dtuple_print(ef, entry); + fputs("\nBut the referencing table ", ef); + ut_print_name(ef, trx, foreign->foreign_table_name); + fputs("\nor its .ibd file or the required index does" + " not currently exist!\n", ef); + err = DB_ROW_IS_REFERENCED; } + mutex_exit(&dict_foreign_err_mutex); goto exit_func; } @@ -1949,6 +1970,7 @@ row_ins_check_foreign_constraints( /*==============================*/ dict_table_t* table, /*!< in: table */ dict_index_t* index, /*!< in: index */ + bool pk, /*!< in: index->is_primary() */ dtuple_t* entry, /*!< in: index entry for index */ que_thr_t* thr) /*!< in: query thread */ { @@ -1957,6 +1979,8 @@ row_ins_check_foreign_constraints( trx_t* trx; ibool got_s_lock = FALSE; + DBUG_ASSERT(index->is_primary() == pk); + trx = thr_get_trx(thr); DEBUG_SYNC_C_IF_THD(thr_get_trx(thr)->mysql_thd, @@ -1968,7 +1992,8 @@ row_ins_check_foreign_constraints( foreign = *it; - if (foreign->foreign_index == index) { + if (foreign->foreign_index == index + || (pk && !foreign->foreign_index)) { dict_table_t* ref_table = NULL; dict_table_t* referenced_table = foreign->referenced_table; @@ -3177,7 +3202,7 @@ row_ins_clust_index_entry( if (!index->table->foreign_set.empty()) { err = row_ins_check_foreign_constraints( - index->table, index, entry, thr); + index->table, index, true, entry, thr); if (err != DB_SUCCESS) { DBUG_RETURN(err); @@ -3276,7 +3301,7 @@ row_ins_sec_index_entry( if (!index->table->foreign_set.empty()) { err = row_ins_check_foreign_constraints(index->table, index, - entry, thr); + false, entry, thr); if (err != DB_SUCCESS) { return(err); diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 1a10657cf99..fb0a376dd34 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -1795,6 +1795,7 @@ row_log_table_apply_insert( break; default: ut_ad(0); + /* fall through */ case DB_INVALID_NULL: ut_ad(row == NULL); return(error); @@ -2082,6 +2083,7 @@ row_log_table_apply_update( break; default: ut_ad(0); + /* fall through */ case DB_INVALID_NULL: ut_ad(row == NULL); return(error); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index f3f6cf9ed77..7e593d1ebec 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1419,11 +1419,13 @@ row_insert_for_mysql( &blob_heap); if (ins_mode != ROW_INS_NORMAL) { +#ifndef DBUG_OFF ut_ad(table->vers_start != table->vers_end); const mysql_row_templ_t* t = prebuilt->get_template_by_col(table->vers_end); ut_ad(t); ut_ad(t->mysql_col_len == 8); +#endif if (ins_mode == ROW_INS_HISTORICAL) { set_tuple_col_8(node->row, table->vers_end, trx->id, @@ -1431,9 +1433,11 @@ row_insert_for_mysql( } else /* ROW_INS_VERSIONED */ { set_tuple_col_8(node->row, table->vers_end, TRX_ID_MAX, node->vers_end_buf); +#ifndef DBUG_OFF t = prebuilt->get_template_by_col(table->vers_start); ut_ad(t); ut_ad(t->mysql_col_len == 8); +#endif set_tuple_col_8(node->row, table->vers_start, trx->id, node->vers_start_buf); } @@ -2878,7 +2882,7 @@ row_discard_tablespace_begin( dict_table_t* table; table = dict_table_open_on_name( - name, TRUE, FALSE, DICT_ERR_IGNORE_NONE); + name, TRUE, FALSE, DICT_ERR_IGNORE_FK_NOKEY); if (table) { dict_stats_wait_bg_to_stop_using_table(table, trx); @@ -3262,7 +3266,7 @@ row_drop_table_from_cache( dict_sys.remove(table); - if (dict_load_table(tablename, true, DICT_ERR_IGNORE_NONE)) { + if (dict_load_table(tablename, true, DICT_ERR_IGNORE_FK_NOKEY)) { ib::error() << "Not able to remove table " << ut_get_name(trx, tablename) << " from the dictionary cache!"; @@ -4174,7 +4178,7 @@ row_rename_table_for_mysql( dict_locked = trx->dict_operation_lock_mode == RW_X_LATCH; table = dict_table_open_on_name(old_name, dict_locked, FALSE, - DICT_ERR_IGNORE_NONE); + DICT_ERR_IGNORE_FK_NOKEY); /* We look for pattern #P# to see if the table is partitioned MySQL table. */ @@ -4222,7 +4226,7 @@ row_rename_table_for_mysql( par_case_name, old_name, FALSE); #endif table = dict_table_open_on_name(par_case_name, dict_locked, FALSE, - DICT_ERR_IGNORE_NONE); + DICT_ERR_IGNORE_FK_NOKEY); } if (!table) { diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index cfed0804373..88dea6c7995 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -566,6 +566,7 @@ row_undo_ins( switch (node->rec_type) { default: ut_ad(!"wrong undo record type"); + /* fall through */ case TRX_UNDO_INSERT_REC: /* Skip the clustered index (the first index) */ node->index = dict_table_get_next_index(node->index); diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 5266b467091..8b1ddfc36a6 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -987,21 +987,20 @@ row_upd_build_difference_binary( TABLE* mysql_table, dberr_t* error) { - upd_field_t* upd_field; ulint len; upd_t* update; ulint n_diff; - ulint i; ulint offsets_[REC_OFFS_NORMAL_SIZE]; - ulint n_fld = dtuple_get_n_fields(entry); - ulint n_v_fld = dtuple_get_n_v_fields(entry); + const ulint n_v_fld = dtuple_get_n_v_fields(entry); rec_offs_init(offsets_); /* This function is used only for a clustered index */ ut_a(dict_index_is_clust(index)); ut_ad(!index->table->skip_alter_undo); + ut_ad(entry->n_fields <= index->n_fields); + ut_ad(entry->n_fields >= index->n_core_fields); - update = upd_create(n_fld + n_v_fld, heap); + update = upd_create(index->n_fields + n_v_fld, heap); n_diff = 0; @@ -1012,7 +1011,7 @@ row_upd_build_difference_binary( ut_ad(rec_offs_validate(rec, index, offsets)); } - for (i = 0; i < n_fld; i++) { + for (ulint i = 0; i < entry->n_fields; i++) { const byte* data = rec_get_nth_cfield(rec, index, offsets, i, &len); const dfield_t* dfield = dtuple_get_nth_field(entry, i); @@ -1027,17 +1026,22 @@ row_upd_build_difference_binary( if (!dfield_is_ext(dfield) != !rec_offs_nth_extern(offsets, i) || !dfield_data_is_binary_equal(dfield, len, data)) { - - upd_field = upd_get_nth_field(update, n_diff); - - dfield_copy(&(upd_field->new_val), dfield); - - upd_field_set_field_no(upd_field, i, index); - - n_diff++; + upd_field_t* uf = upd_get_nth_field(update, n_diff++); + dfield_copy(&uf->new_val, dfield); + upd_field_set_field_no(uf, i, index); } } + for (ulint i = entry->n_fields; i < index->n_fields; i++) { + upd_field_t* uf = upd_get_nth_field(update, n_diff++); + const dict_col_t* col = dict_index_get_nth_col(index, i); + /* upd_create() zero-initialized uf */ + uf->new_val.data = const_cast<byte*>(col->instant_value(&len)); + uf->new_val.len = static_cast<unsigned>(len); + dict_col_copy_type(col, &uf->new_val.type); + upd_field_set_field_no(uf, i, index); + } + /* Check the virtual columns updates. Even if there is no non-virtual column (base columns) change, we will still need to build the indexed virtual column value so that undo log would log them ( @@ -1062,7 +1066,7 @@ row_upd_build_difference_binary( &mysql_table, &record, &vcol_storage); - for (i = 0; i < n_v_fld; i++) { + for (ulint i = 0; i < n_v_fld; i++) { const dict_v_col_t* col = dict_table_get_nth_v_col(index->table, i); @@ -1090,24 +1094,16 @@ row_upd_build_difference_binary( entry, i); if (!dfield_data_is_binary_equal( - dfield, vfield->len, - static_cast<byte*>(vfield->data))) { - upd_field = upd_get_nth_field(update, n_diff); - - upd_field->old_v_val = static_cast<dfield_t*>( - mem_heap_alloc( - heap, - sizeof *upd_field->old_v_val)); - - dfield_copy(upd_field->old_v_val, vfield); - - dfield_copy(&(upd_field->new_val), dfield); - - upd_field_set_v_field_no( - upd_field, i, index); - - n_diff++; - + dfield, vfield->len, + static_cast<byte*>(vfield->data))) { + upd_field_t* uf = upd_get_nth_field(update, + n_diff++); + uf->old_v_val = static_cast<dfield_t*>( + mem_heap_alloc(heap, + sizeof *uf->old_v_val)); + dfield_copy(uf->old_v_val, vfield); + dfield_copy(&uf->new_val, dfield); + upd_field_set_v_field_no(uf, i, index); } } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 00fbac10c82..58172bccc84 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2171,6 +2171,19 @@ files_checked: is at most one data dictionary transaction active at a time. */ if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) { + /* If the following call is ever + removed, the first-time + ha_innobase::open() must hold (or + acquire and release) a table lock that + conflicts with + trx_resurrect_table_locks(), to ensure + that any recovered incomplete ALTER + TABLE will have been rolled + back. Otherwise, dict_table_t::instant + could be cleared by rollback invoking + dict_index_t::clear_instant_alter() + while open table handles exist in + client connections. */ trx_rollback_recovered(false); } } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 1ed5a8dff47..46a0581025e 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -497,6 +497,7 @@ trx_free_at_shutdown(trx_t *trx) transaction was never committed and therefore lock_trx_release() was not called. */ trx->lock.table_locks.clear(); + trx->id = 0; trx_free(trx); } @@ -1239,6 +1240,22 @@ trx_update_mod_tables_timestamp( const time_t now = time(NULL); trx_mod_tables_t::const_iterator end = trx->mod_tables.end(); +#ifdef UNIV_DEBUG +# if MYSQL_VERSION_ID >= 100405 +# define dict_sys_mutex dict_sys.mutex +# else +# define dict_sys_mutex dict_sys->mutex +# endif + + const bool preserve_tables = !innodb_evict_tables_on_commit_debug + || trx->is_recovered /* avoid trouble with XA recovery */ +# if 1 /* if dict_stats_exec_sql() were not playing dirty tricks */ + || mutex_own(&dict_sys_mutex) +# else /* this would be more proper way to do it */ + || trx->dict_operation_lock_mode || trx->dict_operation +# endif + ; +#endif for (trx_mod_tables_t::const_iterator it = trx->mod_tables.begin(); it != end; @@ -1252,7 +1269,27 @@ trx_update_mod_tables_timestamp( "garbage" in table->update_time is justified because protecting it with a latch here would be too performance intrusive. */ - it->first->update_time = now; + dict_table_t* table = it->first; + table->update_time = now; +#ifdef UNIV_DEBUG + if (preserve_tables || table->get_ref_count()) { + /* do not evict when committing DDL operations + or if some other transaction is holding the + table handle */ + continue; + } + /* recheck while holding the mutex that blocks + table->acquire() */ + mutex_enter(&dict_sys_mutex); + if (!table->get_ref_count()) { +# if MYSQL_VERSION_ID >= 100405 + dict_sys.remove(table, true); +# else + dict_table_remove_from_cache_low(table, true); +# endif + } + mutex_exit(&dict_sys_mutex); +#endif } trx->mod_tables.clear(); @@ -1337,10 +1374,8 @@ trx_commit_in_memory( trx_sys.deregister_rw(trx); } - /* trx->id will be cleared in lock_trx_release_locks(trx). */ - ut_ad(trx->read_only || !trx->rsegs.m_redo.rseg || trx->id); lock_trx_release_locks(trx); - ut_ad(trx->id == 0); + ut_ad(trx->read_only || !trx->rsegs.m_redo.rseg || trx->id); /* Remove the transaction from the list of active transactions now that it no longer holds any user locks. */ @@ -1360,6 +1395,8 @@ trx_commit_in_memory( UT_LIST_REMOVE(trx->lock.evicted_tables, table); dict_mem_table_free(table); } + + trx->id = 0; } ut_ad(!trx->rsegs.m_redo.undo); diff --git a/storage/maria/ma_ft_nlq_search.c b/storage/maria/ma_ft_nlq_search.c index 7becf1d7136..f7aa3afec9a 100644 --- a/storage/maria/ma_ft_nlq_search.c +++ b/storage/maria/ma_ft_nlq_search.c @@ -79,13 +79,13 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) MARIA_KEY key; float tmp_weight; DBUG_ENTER("walk_and_match"); - LINT_INIT_STRUCT(subkeys); word->weight=LWS_FOR_QUERY; _ma_ft_make_key(info, &key, aio->keynr, keybuff, word, 0); key.data_length-= HA_FT_WLEN; doc_cnt=0; + subkeys.i= 0; if (share->lock_key_trees) mysql_rwlock_rdlock(&share->keyinfo[aio->keynr].root_lock); diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index 6c36c327d81..3e433b71761 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -77,13 +77,13 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) uint extra= HA_FT_WLEN + info->s->rec_reflength; float tmp_weight; DBUG_ENTER("walk_and_match"); - LINT_INIT_STRUCT(subkeys); word->weight=LWS_FOR_QUERY; keylen=_ft_make_key(info,aio->keynr,keybuff,word,0); keylen-=HA_FT_WLEN; doc_cnt=0; + subkeys.i= 0; if (share->concurrent_insert) mysql_rwlock_rdlock(&share->key_root_lock[aio->keynr]); diff --git a/storage/perfschema/pfs_instr.cc b/storage/perfschema/pfs_instr.cc index b6736cf3102..f90c6475f22 100644 --- a/storage/perfschema/pfs_instr.cc +++ b/storage/perfschema/pfs_instr.cc @@ -1265,7 +1265,6 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, char dirbuffer[FN_REFLEN]; size_t dirlen; const char *normalized_filename; - int normalized_length; dirlen= dirname_length(safe_filename); if (dirlen == 0) @@ -1296,7 +1295,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, *buf_end= '\0'; normalized_filename= buffer; - normalized_length= (int)strlen(normalized_filename); + uint normalized_length= static_cast<uint>(strlen(normalized_filename)); PFS_file **entry; uint retry_count= 0; @@ -1345,7 +1344,7 @@ search: pfs->m_class= klass; pfs->m_enabled= klass->m_enabled && flag_global_instrumentation; pfs->m_timed= klass->m_timed; - strncpy(pfs->m_filename, normalized_filename, normalized_length); + strncpy(pfs->m_filename, normalized_filename, normalized_length + 1); pfs->m_filename[normalized_length]= '\0'; pfs->m_filename_length= normalized_length; pfs->m_file_stat.m_open_count= 1; diff --git a/storage/rocksdb/mysql-test/rocksdb/include/index_merge1.inc b/storage/rocksdb/mysql-test/rocksdb/include/index_merge1.inc index 91bcc68adb4..b5cf7bff763 100644 --- a/storage/rocksdb/mysql-test/rocksdb/include/index_merge1.inc +++ b/storage/rocksdb/mysql-test/rocksdb/include/index_merge1.inc @@ -58,6 +58,10 @@ while ($1) eval set @d=@d*2; dec $1; } +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} --enable_query_log analyze table t0; @@ -329,6 +333,10 @@ alter table t2 add index i321(key3, key2, key1); -- disable_query_log -- disable_result_log analyze table t2; +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} -- enable_result_log -- enable_query_log @@ -371,6 +379,10 @@ insert into t4 select key1,key1,key1 div 10, key1 % 10, key1 % 10, key1 from t0; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t4; -- enable_result_log -- enable_query_log @@ -397,6 +409,10 @@ insert into t1 select * from t0; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -463,6 +479,10 @@ update t3 set key9=key1,keyA=key1,keyB=key1,keyC=key1; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t3; -- enable_result_log -- enable_query_log @@ -486,6 +506,10 @@ update t0 set key8=123 where key1 < 3 or key2 < 4; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t0; -- enable_result_log -- enable_query_log @@ -496,6 +520,10 @@ select * from t0 where key1 < 3 or key2 < 4; delete from t0 where key1 < 3 or key2 < 4; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t0; -- enable_result_log -- enable_query_log @@ -509,6 +537,10 @@ create table t4 (a int); insert into t4 values (1),(4),(3); -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t4; -- enable_result_log -- enable_query_log @@ -533,6 +565,10 @@ select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 update t0 set key1=1; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t0; -- enable_result_log -- enable_query_log @@ -556,6 +592,10 @@ update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t0; -- enable_result_log -- enable_query_log @@ -612,6 +652,10 @@ select count(*) from t1; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -652,6 +696,10 @@ create table t3 ( -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t0; analyze table t1; analyze table t2; @@ -733,6 +781,10 @@ insert into t2 select * from t1; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; analyze table t2; -- enable_result_log @@ -787,6 +839,10 @@ insert into t3 values (1,1,'data'); -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t0; analyze table t1; analyze table t2; @@ -822,6 +878,10 @@ INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log diff --git a/storage/rocksdb/mysql-test/rocksdb/include/index_merge2.inc b/storage/rocksdb/mysql-test/rocksdb/include/index_merge2.inc index 9fd2390c401..7e5cec40a80 100644 --- a/storage/rocksdb/mysql-test/rocksdb/include/index_merge2.inc +++ b/storage/rocksdb/mysql-test/rocksdb/include/index_merge2.inc @@ -43,6 +43,10 @@ while ($1) -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -68,6 +72,10 @@ alter table t1 add primary key (str1, zeroval, str2, str3); -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -101,6 +109,10 @@ while ($1) -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -143,6 +155,10 @@ select count(*) from t1; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t2; -- enable_result_log -- enable_query_log @@ -379,6 +395,10 @@ update t1 set key2=key1,key3=key1; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -417,6 +437,10 @@ INSERT INTO t1 VALUES -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -472,6 +496,10 @@ INSERT INTO t1 VALUES (1,1,'a'), (2,2,'b'); -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log diff --git a/storage/rocksdb/mysql-test/rocksdb/include/index_merge_ror.inc b/storage/rocksdb/mysql-test/rocksdb/include/index_merge_ror.inc index ed270802db1..21219d1aa95 100644 --- a/storage/rocksdb/mysql-test/rocksdb/include/index_merge_ror.inc +++ b/storage/rocksdb/mysql-test/rocksdb/include/index_merge_ror.inc @@ -119,6 +119,10 @@ select count(*) from t1; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t0; analyze table t1; -- enable_result_log @@ -141,6 +145,10 @@ insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 100, 100, 'key4 -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -193,6 +201,10 @@ update t1 set key1=200,key2=200 where key1=100 and key2=100; delete from t1 where key1=200 and key2=200; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -210,6 +222,10 @@ delete from t1 where key3=100 and key4=100; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -236,6 +252,10 @@ insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -250,6 +270,10 @@ insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, -1, 200,'key4') -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -264,6 +288,10 @@ insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 200, -1,'key3') -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -392,6 +420,10 @@ select count(a) from t2 where b='BBBBBBBB'; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t2; -- enable_result_log -- enable_query_log @@ -405,6 +437,10 @@ select count(a) from t2 ignore index(a,b) where a='AAAAAAAA' and b='AAAAAAAA'; insert into t2 values ('ab', 'ab', 'uh', 'oh'); -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t2; -- enable_result_log -- enable_query_log diff --git a/storage/rocksdb/mysql-test/rocksdb/include/index_merge_ror_cpk.inc b/storage/rocksdb/mysql-test/rocksdb/include/index_merge_ror_cpk.inc index 9f1e2d77621..f0d18a50bff 100644 --- a/storage/rocksdb/mysql-test/rocksdb/include/index_merge_ror_cpk.inc +++ b/storage/rocksdb/mysql-test/rocksdb/include/index_merge_ror_cpk.inc @@ -68,6 +68,10 @@ set autocommit=1; -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; -- enable_result_log -- enable_query_log @@ -159,6 +163,10 @@ WHERE (SELECT COUNT(*) FROM t2 WHERE t2.f3 = 'h' AND t2.f2 = t1.f1) = 0 AND t1.f -- disable_query_log -- disable_result_log +if ($engine_type == RocksDB) +{ + set global rocksdb_force_flush_memtable_now=1; +} analyze table t1; analyze table t2; -- enable_result_log diff --git a/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result b/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result index e0248737381..b34ec78cd03 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result @@ -23,10 +23,11 @@ INDEX i8(key8) ); analyze table t0; Table Op Msg_type Msg_text +test.t0 analyze status Engine-independent statistics collected test.t0 analyze status OK explain select * from t0 where key1 < 3 or key1 > 1020; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t0 range i1 i1 4 NULL 2 Using index condition; Using where +1 SIMPLE t0 range i1 i1 4 NULL 4 Using index condition explain select * from t0 where key1 < 3 or key2 > 1020; id select_type table type possible_keys key key_len ref rows Extra @@ -267,12 +268,12 @@ select * from t0,t1 where (t0.key1=t1.key1) and (t0.key1=3 or t0.key2<4) and t1.key1=2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t0 ref i1,i2 i1 4 const 2 Using where -1 SIMPLE t1 ref i1 i1 4 const 1 +1 SIMPLE t1 ref i1 i1 4 const 2 explain select * from t0,t1 where t0.key1 = 5 and (t1.key1 = t0.key1 or t1.key8 = t0.key1); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t0 ref i1 i1 4 const 1 -1 SIMPLE t1 index_merge i1,i8 i1,i8 4,4 NULL 2 Using union(i1,i8); Using where; Using join buffer (flat, BNL join) +1 SIMPLE t0 ref i1 i1 4 const 2 +1 SIMPLE t1 index_merge i1,i8 i1,i8 4,4 NULL 4 Using union(i1,i8); Using where; Using join buffer (flat, BNL join) explain select * from t0,t1 where t0.key1 < 3 and (t1.key1 = t0.key1 or t1.key8 = t0.key1); id select_type table type possible_keys key key_len ref rows Extra @@ -286,7 +287,7 @@ id select_type table type possible_keys key key_len ref rows Extra NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL explain select * from (select * from t1 where key1 = 3 or key2 =3) as Z where key8 >5; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge i1,i2,i8 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where +1 SIMPLE t1 index_merge i1,i2,i8 i1,i2 4,4 NULL 4 Using union(i1,i2); Using where create table t3 like t0; insert into t3 select * from t0; alter table t3 add key9 int not null, add index i9(key9); @@ -392,10 +393,10 @@ count(*) 8704 explain select * from t1 WHERE cola = 'foo' AND colb = 'bar'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge cola,colb cola,colb 3,3 NULL # Using intersect(cola,colb); Using where +1 SIMPLE t1 ref cola,colb cola 3 const # Using index condition; Using where explain select * from t1 force index(cola,colb) WHERE cola = 'foo' AND colb = 'bar'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge cola,colb cola,colb 3,3 NULL # Using intersect(cola,colb); Using where +1 SIMPLE t1 ref cola,colb cola 3 const # Using index condition; Using where drop table t1; CREATE TABLE t1(a INT); INSERT INTO t1 VALUES(1); @@ -478,7 +479,7 @@ a filler b must use union, not sort-union: explain select * from t2 where a=4 or b=4; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 index_merge a,b a,b 5,5 NULL # Using union(a,b); Using where +1 SIMPLE t2 ALL a,b NULL NULL NULL # Using where select * from t2 where a=4 or b=4; a filler b 4 4 0 @@ -603,7 +604,7 @@ count(*) 64801 explain select key1,key2 from t1 where key1=100 and key2=100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2 key2,key1 5,5 NULL # Using intersect(key2,key1); Using where; Using index +1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL # Using intersect(key1,key2); Using where; Using index select key1,key2 from t1 where key1=100 and key2=100; key1 key2 100 100 @@ -789,7 +790,7 @@ show warnings; Level Code Message explain select pk from t1 where key1 = 1 and key2 = 1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref key1,key2 key1 5 const 2 Using where +1 SIMPLE t1 index_merge key1,key2 key2,key1 4,5 NULL 1 Using intersect(key2,key1); Using where; Using index select pk from t1 where key2 = 1 and key1 = 1; pk 26 @@ -826,6 +827,7 @@ insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b) select key1a, key1b, key2a, key2b, key3a, key3b from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select count(*) from t1; count(*) @@ -1057,7 +1059,7 @@ SELECT a FROM t1 WHERE c = 1 AND b = 1 AND d = 1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref c,bd c 5 const 2 Using where +1 SIMPLE t1 index_merge c,bd c,bd 5,10 NULL 1 Using intersect(c,bd); Using where; Using index CREATE TABLE t2 ( a INT ) SELECT a FROM t1 @@ -1288,7 +1290,7 @@ primary key (pk1, pk2) ); explain select * from t1 where pk1 = 1 and pk2 < 80 and key1=0; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range PRIMARY,key1 key1 12 NULL ROWS Using index condition +1 SIMPLE t1 range PRIMARY,key1 PRIMARY 8 NULL ROWS Using where select * from t1 where pk1 = 1 and pk2 < 80 and key1=0; pk1 pk2 key1 key2 pktail1ok pktail2ok pktail3bad pktail4bad pktail5bad pk2copy badkey filler1 filler2 1 10 0 0 0 0 0 0 0 10 0 filler-data-10 filler2 @@ -1321,16 +1323,16 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref key1 key1 4 const ROWS Using where explain select * from t1 where pk1 < 7500 and key1 = 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range PRIMARY,key1 key1 8 NULL ROWS Using index condition +1 SIMPLE t1 range PRIMARY,key1 PRIMARY 4 NULL ROWS Using where explain select * from t1 where pktail1ok=1 and key1=10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,pktail1ok key1,pktail1ok 4,4 NULL 1 Using intersect(key1,pktail1ok); Using where +1 SIMPLE t1 ref key1,pktail1ok key1 4 const 2 Using where explain select * from t1 where pktail2ok=1 and key1=10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,pktail2ok key1,pktail2ok 4,4 NULL 1 Using intersect(key1,pktail2ok); Using where +1 SIMPLE t1 ref key1,pktail2ok key1 4 const 2 Using where explain select * from t1 where (pktail2ok=1 and pk1< 50000) or key1=10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge PRIMARY,key1,pktail2ok PRIMARY,key1 4,4 NULL ROWS Using union(PRIMARY,key1); Using where +1 SIMPLE t1 index_merge PRIMARY,key1,pktail2ok pktail2ok,key1 8,4 NULL ROWS Using sort_union(pktail2ok,key1); Using where explain select * from t1 where pktail3bad=1 and key1=10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref key1,pktail3bad EITHER_KEY 4 const ROWS Using where @@ -1393,7 +1395,7 @@ EXPLAIN SELECT t1.f1 FROM t1 WHERE (SELECT COUNT(*) FROM t2 WHERE t2.f3 = 'h' AND t2.f2 = t1.f1) = 0 AND t1.f1 = 2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 const PRIMARY PRIMARY 4 const 1 Using index -2 SUBQUERY t2 ref f2,f3 f2 5 const 1 Using where +2 SUBQUERY t2 index_merge f2,f3 f3,f2 2,5 NULL 1 Using intersect(f3,f2); Using where; Using index DROP TABLE t1,t2; set global rocksdb_force_flush_memtable_now=1; # @@ -1412,5 +1414,5 @@ INSERT INTO t1 SELECT id + 8, id2 + 8, id3 +8 FROM t1; INSERT INTO t1 SELECT id + 16, 7, 0 FROM t1; EXPLAIN SELECT SQL_NO_CACHE count(*) FROM t1 WHERE id2=7 AND id3=0; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref id2,id3,covering_index covering_index 8 const,const 1 Using index +1 SIMPLE t1 ref id2,id3,covering_index covering_index 8 const,const 2 Using index DROP TABLE t1; diff --git a/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test b/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test index 67b2d5f96d7..e084b57fbda 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test @@ -1,6 +1,8 @@ --source include/have_rocksdb.inc --source include/not_valgrind.inc +--let $restart_noprint=2 + --echo # --echo # Test how MyRocks behaves when RocksDB reports corrupted data. --echo # diff --git a/storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug.test b/storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug.test index b17548063d9..99e28f3b55e 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug.test @@ -3,6 +3,8 @@ --source include/have_log_bin.inc --source include/not_valgrind.inc +--let $restart_noprint=2 + --echo # --echo # Testing upgrading from server without merges for auto_increment --echo # to new server with such support. diff --git a/storage/rocksdb/mysql-test/rocksdb/t/disabled.def b/storage/rocksdb/mysql-test/rocksdb/t/disabled.def index 5115056acdd..e2c7f143250 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/disabled.def +++ b/storage/rocksdb/mysql-test/rocksdb/t/disabled.def @@ -85,8 +85,6 @@ rpl_row_triggers : Requires read-free slave. compact_deletes: MDEV-12663 : rocksdb.compact_deletes times out and causes other tests to fail blind_delete_without_tx_api: MDEV-12286: rocksdb.blind_delete_without_tx_api test fails -unique_check: wrong error number -autoinc_vars_thread: debug sync point wait timed out information_schema: MDEV-14372: unstable testcase ## @@ -94,9 +92,6 @@ information_schema: MDEV-14372: unstable testcase ## mysqlbinlog_gtid_skip_empty_trans_rocksdb : MariaRocks: requires GTIDs -autoinc_debug: Fails with wrong results drop_table: Hangs on shutdown -allow_to_start_after_corruption : result difference and assertion failure -index_merge_rocksdb2 : result difference rocksdb_range2 : result difference, update after MDEV-16746 is fixed add_index_inplace: FORCE INDEX gives wrong count diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index 337a1dc22a1..9cf10df4189 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -2285,7 +2285,8 @@ int ha_sphinx::HandleMysqlError ( MYSQL * pConn, int iErrCode ) CSphSEThreadTable * pTable = GetTls (); if ( pTable ) { - strncpy ( pTable->m_tStats.m_sLastMessage, mysql_error ( pConn ), sizeof ( pTable->m_tStats.m_sLastMessage ) ); + strncpy ( pTable->m_tStats.m_sLastMessage, mysql_error ( pConn ), sizeof pTable->m_tStats.m_sLastMessage - 1 ); + pTable->m_tStats.m_sLastMessage[sizeof pTable->m_tStats.m_sLastMessage - 1] = '\0'; pTable->m_tStats.m_bLastError = true; } @@ -2552,7 +2553,8 @@ bool ha_sphinx::UnpackSchema () CSphSEThreadTable * pTable = GetTls (); if ( pTable ) { - strncpy ( pTable->m_tStats.m_sLastMessage, sMessage, sizeof(pTable->m_tStats.m_sLastMessage) ); + strncpy ( pTable->m_tStats.m_sLastMessage, sMessage, sizeof pTable->m_tStats.m_sLastMessage - 1 ); + pTable->m_tStats.m_sLastMessage[sizeof pTable->m_tStats.m_sLastMessage - 1] = '\0'; pTable->m_tStats.m_bLastError = ( uStatus==SEARCHD_ERROR ); } @@ -2973,7 +2975,8 @@ int ha_sphinx::index_read ( byte * buf, const byte * key, uint key_len, enum ha_ SPH_RET ( HA_ERR_END_OF_FILE ); } - strncpy ( pTable->m_tStats.m_sLastMessage, sMessage, sizeof(pTable->m_tStats.m_sLastMessage) ); + strncpy ( pTable->m_tStats.m_sLastMessage, sMessage, sizeof pTable->m_tStats.m_sLastMessage - 1 ); + pTable->m_tStats.m_sLastMessage[sizeof pTable->m_tStats.m_sLastMessage - 1] = '\0'; SafeDeleteArray ( sMessage ); if ( uRespStatus!=SEARCHD_WARNING ) diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_master_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_master_tokudb.result index 83578f20404..6982078d2b8 100644 --- a/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_master_tokudb.result +++ b/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_master_tokudb.result @@ -468,7 +468,7 @@ INSERT INTO t10 () VALUES(1,@b1,DEFAULT,'Kyle',DEFAULT), connection slave; include/wait_for_slave_sql_error_and_skip.inc [errno=1677] -Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'' +Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5 octets) character set latin1'' *** Drop t10 *** connection master; @@ -510,7 +510,7 @@ INSERT INTO t11 () VALUES(1,@b1,'Testing is fun','Kyle',DEFAULT), connection slave; include/wait_for_slave_sql_error_and_skip.inc [errno=1677] -Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'blob' to type 'varchar(254)'' +Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'blob' to type 'varchar(254 octets) character set latin1'' *** Drop t11 *** connection master; diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_slave_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_slave_tokudb.result index 3f29138b946..318d5496255 100644 --- a/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_slave_tokudb.result +++ b/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_slave_tokudb.result @@ -64,7 +64,7 @@ a b c connection slave; START SLAVE; include/wait_for_slave_sql_error.inc [errno=1677] -Last_SQL_Error = 'Column 2 of table 'test.t2' cannot be converted from type 'char(10)' to type 'char(5)'' +Last_SQL_Error = 'Column 2 of table 'test.t2' cannot be converted from type 'char(10 octets)' to type 'char(5 octets) character set latin1'' STOP SLAVE; RESET SLAVE; SELECT * FROM t2 ORDER BY a; @@ -160,7 +160,7 @@ INSERT INTO t5 () VALUES(1,'Kyle',200.23,1,'b1b1',23.00098), ******************************************** connection slave; include/wait_for_slave_sql_error_and_skip.inc [errno=1677] -Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'varchar(6)' to type 'char(5)'' +Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'varchar(6 octets)' to type 'char(5 octets) character set latin1'' *** Drop t5 *** connection master; DROP TABLE t5; @@ -188,7 +188,7 @@ INSERT INTO t6 () VALUES(1,'Kyle',200.23,1), ******************************************** connection slave; include/wait_for_slave_sql_error.inc [errno=1677] -Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'varchar(6)' to type 'char(5)'' +Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'varchar(6 octets)' to type 'char(5 octets) character set latin1'' *** Drop t6 *** include/rpl_reset.inc connection master; @@ -310,7 +310,7 @@ INSERT INTO t10 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); ******************************************** connection slave; include/wait_for_slave_sql_error_and_skip.inc [errno=1677] -Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'char(5)' to type 'double'' +Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'char(5 octets)' to type 'double'' *** Drop t10 *** connection master; DROP TABLE t10; @@ -338,7 +338,7 @@ INSERT INTO t11 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); ******************************************** connection slave; include/wait_for_slave_sql_error_and_skip.inc [errno=1677] -Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'varchar(254)' to type 'int(11)'' +Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'varchar(254 octets)' to type 'int(11)'' *** Drop t11 *** connection master; DROP TABLE t11; diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_row_basic_3tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_row_basic_3tokudb.result index 32a42143180..e638a1aab12 100644 --- a/storage/tokudb/mysql-test/rpl/r/rpl_row_basic_3tokudb.result +++ b/storage/tokudb/mysql-test/rpl/r/rpl_row_basic_3tokudb.result @@ -565,7 +565,7 @@ INSERT INTO t5 VALUES (1, "", 1); INSERT INTO t5 VALUES (2, repeat(_utf8'a', 255), 2); connection slave; include/wait_for_slave_sql_error.inc [errno=1677] -Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'char(255)' to type 'char(16)'' +Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'char(765 octets)' to type 'char(48 octets) character set utf8'' include/rpl_reset.inc [expecting slave to stop] connection master; @@ -573,7 +573,7 @@ INSERT INTO t6 VALUES (1, "", 1); INSERT INTO t6 VALUES (2, repeat(_utf8'a', 255), 2); connection slave; include/wait_for_slave_sql_error.inc [errno=1677] -Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'char(255)' to type 'char(128)'' +Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'char(765 octets)' to type 'char(384 octets) character set utf8'' include/rpl_reset.inc [expecting slave to replicate correctly] connection master; |