From dd30ba4c1bfbf7bd6c55a170ac6d718bdb10dab1 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 24 Aug 2019 16:14:24 +0200 Subject: [PATCH 01/15] In CONNECT version 1.6.10 NOSQL facility is enhanced by a new way to retrieve NOSQL data. In addition to files and Mongo collections, JSON as well as XML and CSV data can be retrieved from the net as answers from REST queries. Because it uses and external package (cpprestsdk) this is currently available only to MariaDB servers compiled from source. -- Add the REST support when Microsoft Casablanca package (cpprestsdk) is installed. -- Add compile flags needed on Windows /MD or /MDd (debug) -- Also include some changes specific to MariaDB 10.3. modified: storage/connect/CMakeLists.txt -- Add conditional REST support -- Added string options HTTP and URI. -- Added added internal table type TAB_REST. modified: storage/connect/ha_connect.cc modified: storage/connect/mycat.cc modified: storage/connect/mycat.h modified: storage/connect/plgdbsem.h -- Add conditional code based on the preprocessor definition MARIADB -- This to be able to use the same code in CONNECT and EOM modules modified: storage/connect/osutil.h modified: storage/connect/tabrest.cpp -- Add files for the REST OEM module added: storage/connect/mini-global.h added: storage/connect/rest.def -- Fix MDEV-19648 Variable connect_conv_size doesn't change -- Change Variable wrong block parameter from 8169 to 1. -- Also change connect_conv_size default value to 1024. modified: storage/connect/ha_connect.cc -- Fix compilation error when ZIP is not supported modified: storage/connect/ha_connect.cc modified: storage/connect/tabfmt.cpp -- Replace PlugSetPath by some concat (crashed on Fedora) + typo modified: storage/connect/reldef.cpp -- Avoid possible buffer overflow -- In particular by the function ShowValue. modified: storage/connect/tabdos.cpp modified: storage/connect/tabfmt.cpp modified: storage/connect/value.cpp modified: storage/connect/value.h -- Add some cast to avoid some compiler warnings modified: storage/connect/filamdbf.cpp -- Fix some C++ error modified: storage/connect/javaconn.cpp modified: storage/connect/jmgoconn.cpp modified: storage/connect/plugutil.cpp -- Add some tracing + typo modified: storage/connect/mycat.cc modified: storage/connect/tabjson.cpp -- Add the xtrc tracing function modified: storage/connect/global.h modified: storage/connect/plugutil.cpp -- Modify tracing to use xtrc and some typo modified: storage/connect/array.cpp modified: storage/connect/block.h -- Miscellaneous Typo and warning suppressing changes modified: storage/connect/connect.cpp modified: storage/connect/connect.h modified: storage/connect/filamvct.cpp modified: storage/connect/inihandl.cpp modified: storage/connect/jsonudf.cpp modified: storage/connect/libdoc.cpp modified: storage/connect/tabjson.cpp modified: storage/connect/tabtbl.cpp modified: storage/connect/tabxml.cpp modified: storage/connect/user_connect.cc modified: storage/connect/user_connect.h -- Update failing test results and disbling modified: storage/connect/mysql-test/connect/disabled.def modified: storage/connect/mysql-test/connect/r/dir.result modified: storage/connect/mysql-test/connect/r/grant.result modified: storage/connect/mysql-test/connect/r/jdbc.result modified: storage/connect/mysql-test/connect/r/jdbc_postgresql.result modified: storage/connect/mysql-test/connect/r/xml.result modified: storage/connect/mysql-test/connect/r/xml2.result modified: storage/connect/mysql-test/connect/r/xml2_mult.result modified: storage/connect/mysql-test/connect/r/xml_mult.result -- Add an option modified: storage/connect/mysql-test/connect/t/grant.test --- storage/connect/CMakeLists.txt | 50 +- storage/connect/array.cpp | 127 +-- storage/connect/block.h | 4 +- storage/connect/connect.cc | 3 +- storage/connect/connect.h | 2 +- storage/connect/global.h | 1 + storage/connect/ha_connect.cc | 637 ++++++------ storage/connect/ha_connect.h | 6 +- storage/connect/inihandl.cpp | 4 +- storage/connect/jmgoconn.cpp | 5 +- storage/connect/jsonudf.cpp | 8 +- storage/connect/libdoc.cpp | 2 +- storage/connect/mini-global.h | 33 + storage/connect/mycat.cc | 166 +-- storage/connect/mycat.h | 6 +- storage/connect/osutil.h | 4 + storage/connect/plgdbsem.h | 6 +- storage/connect/plugutil.cpp | 38 +- storage/connect/reldef.cpp | 297 +++--- storage/connect/rest.def | 4 + storage/connect/restget.cpp | 94 ++ storage/connect/tabfmt.cpp | 2 + storage/connect/tabjdbc.cpp | 26 +- storage/connect/tabjson.cpp | 1709 ++++++++++++++++--------------- storage/connect/tabrest.cpp | 201 ++++ storage/connect/tabrest.h | 29 + storage/connect/tabtbl.cpp | 4 +- storage/connect/tabxml.cpp | 2 +- storage/connect/user_connect.cc | 2 +- storage/connect/user_connect.h | 2 +- 30 files changed, 1975 insertions(+), 1499 deletions(-) create mode 100644 storage/connect/mini-global.h create mode 100644 storage/connect/rest.def create mode 100644 storage/connect/restget.cpp create mode 100644 storage/connect/tabrest.cpp create mode 100644 storage/connect/tabrest.h diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index c8747f889c6..fd006e104c1 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -11,7 +11,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA SET(CONNECT_PLUGIN_STATIC "connect") SET(CONNECT_PLUGIN_DYNAMIC "connect") @@ -68,7 +68,15 @@ 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 + RETURN() + ENDIF() ENDIF(UNIX) @@ -109,7 +117,6 @@ IF(CONNECT_WITH_LIBXML2) FIND_PACKAGE(LibXml2) IF (LIBXML2_FOUND) INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) - SET(ZLIB_LIBRARY "z") # see ZLIB_INCLUDE_DIR below SET(XML_LIBRARY ${LIBXML2_LIBRARIES}) SET(CONNECT_SOURCES ${CONNECT_SOURCES} libdoc.cpp libdoc.h) add_definitions(-DLIBXML2_SUPPORT) @@ -301,6 +308,30 @@ IF(CONNECT_WITH_MONGO) ENDIF(CONNECT_WITH_MONGO) +# +# REST +# + +OPTION(CONNECT_WITH_REST "Compile CONNECT storage engine with REST support" ON) + +IF(CONNECT_WITH_REST) + MESSAGE(STATUS "=====> REST support is ON") + FIND_PACKAGE(cpprestsdk) + IF (cpprestsdk_FOUND) + MESSAGE(STATUS "=====> cpprestsdk found") + 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 # @@ -320,24 +351,16 @@ 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() ENDIF() -# Don't link with bundled zlib and systel libxml2 at the same time. -# System libxml2 uses system zlib, might conflict with the bundled one. -IF (XML_LIBRARY AND BUILD_BUNDLED_ZLIB) - GET_PROPERTY(INCS TARGET connect PROPERTY INCLUDE_DIRECTORIES) - LIST(REMOVE_ITEM INCS ${ZLIB_INCLUDE_DIR}) - SET_PROPERTY(TARGET connect PROPERTY INCLUDE_DIRECTORIES ${INCS}) -ENDIF() - IF(WIN32) IF (libmongoc-1.0_FOUND) - SET_TARGET_PROPERTIES(connect PROPERTIES LINK_FLAGS - "/DELAYLOAD:libbson-1.0.dll /DELAYLOAD:libmongoc-1.0.dll") + SET_TARGET_PROPERTIES(connect PROPERTIES LINK_FLAGS + "/DELAYLOAD:libbson-1.0.dll /DELAYLOAD:libmongoc-1.0.dll") ENDIF(libmongoc-1.0_FOUND) ENDIF(WIN32) @@ -364,3 +387,4 @@ IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND) ${CMAKE_CURRENT_BINARY_DIR}/JdbcInterface.jar DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine) ENDIF() + diff --git a/storage/connect/array.cpp b/storage/connect/array.cpp index cd1785b48ac..3478342a788 100644 --- a/storage/connect/array.cpp +++ b/storage/connect/array.cpp @@ -1,7 +1,7 @@ /************* Array C++ Functions Source Code File (.CPP) *************/ /* Name: ARRAY.CPP Version 2.3 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2005-2017 */ +/* (C) Copyright to the author Olivier BERTRAND 2005-2019 */ /* */ /* This file contains the XOBJECT derived class ARRAY functions. */ /* ARRAY is used for elaborate type of processing, such as sorting */ @@ -67,7 +67,7 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp); // avoid gcc warning /* MakeValueArray: Makes a value array from a value list. */ /***********************************************************************/ PARRAY MakeValueArray(PGLOBAL g, PPARM pp) - { +{ int n, valtyp = 0; size_t len = 0; PARRAY par; @@ -82,8 +82,7 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp) if ((valtyp = pp->Type) != TYPE_STRING) len = 1; - if (trace(1)) - htrc("valtyp=%d len=%d\n", valtyp, len); + xtrc(1, "valtyp=%d len=%d\n", valtyp, len); /*********************************************************************/ /* Firstly check the list and count the number of values in it. */ @@ -127,13 +126,13 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp) // Integer stored inside pp->Value par->AddValue(g, parmp->Intval); break; - } // endswitch valtyp + } // endswitch valtyp /*********************************************************************/ /* Send back resulting array. */ /*********************************************************************/ return par; - } // end of MakeValueArray +} // end of MakeValueArray /* -------------------------- Class ARRAY ---------------------------- */ @@ -151,6 +150,9 @@ ARRAY::ARRAY(PGLOBAL g, int type, int size, int length, int prec) Type = type; Xsize = -1; Len = 1; + X = 0; + Inf = 0; + Sup = 0; switch (type) { case TYPE_STRING: @@ -281,130 +283,109 @@ void ARRAY::Empty(void) /* Add a string element to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, PSZ strp) - { +{ if (Type != TYPE_STRING) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "CHAR"); return true; - } // endif Type + } // endif Type - if (trace(1)) - htrc(" adding string(%d): '%s'\n", Nval, strp); - -//Value->SetValue_psz(strp); -//Vblp->SetValue(valp, Nval++); + xtrc(1, " adding string(%d): '%s'\n", Nval, strp); Vblp->SetValue(strp, Nval++); return false; - } // end of AddValue +} // end of AddValue /***********************************************************************/ /* Add a char pointer element to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, void *p) - { +{ if (Type != TYPE_PCHAR) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "PCHAR"); return true; - } // endif Type - - if (trace(1)) - htrc(" adding pointer(%d): %p\n", Nval, p); + } // endif Type + xtrc(1, " adding pointer(%d): %p\n", Nval, p); Vblp->SetValue((PSZ)p, Nval++); return false; - } // end of AddValue +} // end of AddValue /***********************************************************************/ /* Add a short integer element to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, short n) - { +{ if (Type != TYPE_SHORT) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "SHORT"); return true; - } // endif Type + } // endif Type - if (trace(1)) - htrc(" adding SHORT(%d): %hd\n", Nval, n); - -//Value->SetValue(n); -//Vblp->SetValue(valp, Nval++); + xtrc(1, " adding SHORT(%d): %hd\n", Nval, n); Vblp->SetValue(n, Nval++); return false; - } // end of AddValue +} // end of AddValue /***********************************************************************/ /* Add an integer element to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, int n) - { +{ if (Type != TYPE_INT) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "INTEGER"); return true; - } // endif Type + } // endif Type - if (trace(1)) - htrc(" adding int(%d): %d\n", Nval, n); - -//Value->SetValue(n); -//Vblp->SetValue(valp, Nval++); + xtrc(1, " adding int(%d): %d\n", Nval, n); Vblp->SetValue(n, Nval++); return false; - } // end of AddValue +} // end of AddValue /***********************************************************************/ /* Add a double float element to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, double d) - { +{ if (Type != TYPE_DOUBLE) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(Type), "DOUBLE"); return true; - } // endif Type - - if (trace(1)) - htrc(" adding float(%d): %lf\n", Nval, d); + } // endif Type + xtrc(1, " adding float(%d): %lf\n", Nval, d); Value->SetValue(d); Vblp->SetValue(Value, Nval++); return false; - } // end of AddValue +} // end of AddValue /***********************************************************************/ /* Add the value of a XOBJECT block to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, PXOB xp) - { - if (Type != xp->GetResultType()) { - sprintf(g->Message, MSG(ADD_BAD_TYPE), - GetTypeName(xp->GetResultType()), GetTypeName(Type)); - return true; - } // endif Type +{ + if (Type != xp->GetResultType()) { + sprintf(g->Message, MSG(ADD_BAD_TYPE), + GetTypeName(xp->GetResultType()), GetTypeName(Type)); + return true; + } // endif Type - if (trace(1)) - htrc(" adding (%d) from xp=%p\n", Nval, xp); - -//AddValue(xp->GetValue()); - Vblp->SetValue(xp->GetValue(), Nval++); - return false; - } // end of AddValue + xtrc(1, " adding (%d) from xp=%p\n", Nval, xp); + Vblp->SetValue(xp->GetValue(), Nval++); + return false; +} // end of AddValue /***********************************************************************/ /* Add a value to an array. */ /***********************************************************************/ bool ARRAY::AddValue(PGLOBAL g, PVAL vp) - { +{ if (Type != vp->GetType()) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(vp->GetType()), GetTypeName(Type)); return true; - } // endif Type - - if (trace(1)) - htrc(" adding (%d) from vp=%p\n", Nval, vp); + } // endif Type + xtrc(1, " adding (%d) from vp=%p\n", Nval, vp); Vblp->SetValue(vp, Nval++); return false; - } // end of AddValue +} // end of AddValue /***********************************************************************/ /* Retrieve the nth value of the array. */ @@ -973,7 +954,7 @@ int ARRAY::BlockTest(PGLOBAL, int opc, int opm, /* MakeArrayList: Makes a value list from an SQL IN array (in work). */ /***********************************************************************/ PSZ ARRAY::MakeArrayList(PGLOBAL g) - { +{ char *p, *tp; int i; size_t z, len = 2; @@ -988,11 +969,9 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g) Value->SetValue_pvblk(Vblp, i); Value->Prints(g, tp, z); len += strlen(tp); - } // enfor i - - if (trace(1)) - htrc("Arraylist: len=%d\n", len); + } // enfor i + xtrc(1, "Arraylist: len=%d\n", len); p = (char *)PlugSubAlloc(g, NULL, len); strcpy(p, "("); @@ -1001,19 +980,17 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g) Value->Prints(g, tp, z); strcat(p, tp); strcat(p, (++i == Nval) ? ")" : ","); - } // enfor i - - if (trace(1)) - htrc("Arraylist: newlen=%d\n", strlen(p)); + } // enfor i + xtrc(1, "Arraylist: newlen=%d\n", strlen(p)); return p; - } // end of MakeArrayList +} // end of MakeArrayList /***********************************************************************/ /* Make file output of ARRAY contents. */ /***********************************************************************/ void ARRAY::Printf(PGLOBAL g, FILE *f, uint n) - { +{ char m[64]; int lim = MY_MIN(Nval,10); @@ -1035,19 +1012,19 @@ void ARRAY::Printf(PGLOBAL g, FILE *f, uint n) } else fprintf(f, "%sVALLST: numval=%d\n", m, Nval); - } // end of Printf +} // end of Printf /***********************************************************************/ /* Make string output of ARRAY contents. */ /***********************************************************************/ void ARRAY::Prints(PGLOBAL, char *ps, uint z) - { +{ if (z < 16) return; sprintf(ps, "ARRAY: type=%d\n", Type); // More to be implemented later - } // end of Prints +} // end of Prints /* -------------------------- Class MULAR ---------------------------- */ diff --git a/storage/connect/block.h b/storage/connect/block.h index 737c74c1293..2ca9586ee3f 100644 --- a/storage/connect/block.h +++ b/storage/connect/block.h @@ -38,9 +38,7 @@ typedef class BLOCK *PBLOCK; class DllExport BLOCK { public: void * operator new(size_t size, PGLOBAL g, void *p = NULL) { - if (trace(256)) - htrc("New BLOCK: size=%d g=%p p=%p\n", size, g, p); - + xtrc(256, "New BLOCK: size=%d g=%p p=%p\n", size, g, p); return (PlugSubAlloc(g, p, size)); } // end of new diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index 21bca637eab..b1078de8eaa 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /***********************************************************************/ /* Author Olivier BERTRAND bertrandop@gmail.com 2004-2017 */ @@ -33,6 +33,7 @@ /* plgdbsem.h is header containing the DB applic. declarations. */ /***********************************************************************/ #define DONT_DEFINE_VOID +#include #include "handler.h" #undef OFFSET diff --git a/storage/connect/connect.h b/storage/connect/connect.h index 2bca8bf54cb..3a60cd40160 100644 --- a/storage/connect/connect.h +++ b/storage/connect/connect.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /**************** Cnt H Declares Source Code File (.H) *****************/ /* Name: CONNECT.H Version 2.4 */ diff --git a/storage/connect/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 191230cb03c..be7c6548181 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file ha_connect.cc @@ -164,15 +164,15 @@ /***********************************************************************/ /* Initialize the ha_connect static members. */ /***********************************************************************/ -#define SZCONV 8192 +#define SZCONV 1024 // Default converted text size #define SZWORK 67108864 // Default work area size 64M #define SZWMIN 4194304 // Minimum work area size 4M #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.06.0009 January 27, 2019"; + char version[]= "Version 1.06.0010 June 01, 2019"; #if defined(__WIN__) - char compver[]= "Version 1.06.0009 " __DATE__ " " __TIME__; + char compver[]= "Version 1.06.0010 " __DATE__ " " __TIME__; char slash= '\\'; #else // !__WIN__ char slash= '/'; @@ -211,14 +211,14 @@ char *GetUserVariable(PGLOBAL g, const uchar *varname) { char buf[1024]; bool b; - THD *thd = current_thd; - CHARSET_INFO *cs = system_charset_info; - String *str = NULL, tmp(buf, sizeof(buf), cs); - HASH uvars = thd->user_vars; - user_var_entry *uvar = (user_var_entry*)my_hash_search(&uvars, varname, 0); + THD *thd= current_thd; + CHARSET_INFO *cs= system_charset_info; + String *str= NULL, tmp(buf, sizeof(buf), cs); + HASH uvars= thd->user_vars; + user_var_entry *uvar= (user_var_entry*)my_hash_search(&uvars, varname, 0); if (uvar) - str = uvar->val_str(&b, &tmp, NOT_FIXED_DEC); + str= uvar->val_str(&b, &tmp, NOT_FIXED_DEC); return str ? PlugDup(g, str->ptr()) : NULL; }; // end of GetUserVariable @@ -231,6 +231,9 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); PQRYRES VirColumns(PGLOBAL g, bool info); PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info); PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info); +#if defined(REST_SUPPORT) +PQRYRES RESTColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); +#endif // REST_SUPPORT #if defined(JAVA_SUPPORT) PQRYRES MGOColumns(PGLOBAL g, PCSZ db, PCSZ url, PTOS topt, bool info); #endif // JAVA_SUPPORT @@ -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); @@ -352,7 +357,7 @@ static MYSQL_THDVAR_UINT(work_size, static MYSQL_THDVAR_INT(conv_size, PLUGIN_VAR_RQCMDARG, // opt "Size used when converting TEXT columns.", - NULL, NULL, SZCONV, 0, 65500, 8192); + NULL, NULL, SZCONV, 0, 65500, 1); /** Type conversion: @@ -583,7 +588,9 @@ ha_create_table_option connect_table_option_list[]= HA_TOPTION_STRING("FILTER", filter), HA_TOPTION_STRING("OPTION_LIST", oplist), HA_TOPTION_STRING("DATA_CHARSET", data_charset), - HA_TOPTION_NUMBER("LRECL", lrecl, 0, 0, INT_MAX32, 1), + HA_TOPTION_STRING("HTTP", http), + HA_TOPTION_STRING("URI", uri), + HA_TOPTION_NUMBER("LRECL", lrecl, 0, 0, INT_MAX32, 1), HA_TOPTION_NUMBER("BLOCK_SIZE", elements, 0, 0, INT_MAX32, 1), //HA_TOPTION_NUMBER("ESTIMATE", estimate, 0, 0, INT_MAX32, 1), HA_TOPTION_NUMBER("MULTIPLE", multiple, 0, 0, 3, 1), @@ -991,11 +998,11 @@ static PCONNECT GetUser(THD *thd, PCONNECT xp) pthread_mutex_unlock(&usrmut); if (!xp) { - xp = new user_connect(thd); + xp= new user_connect(thd); if (xp->user_init()) { delete xp; - xp = NULL; + xp= NULL; } // endif user_init } // endif xp @@ -1027,6 +1034,19 @@ TABTYPE ha_connect::GetRealType(PTOS pos) if (type == TAB_UNDEF) type= pos->srcdef ? TAB_MYSQL : pos->tabname ? TAB_PRX : TAB_DOS; +#if defined(REST_SUPPORT) + else if (pos->http) + switch (type) { + case TAB_JSON: + case TAB_XML: + case TAB_CSV: + type = TAB_REST; + break; + case TAB_REST: + type = TAB_NIY; + break; + } // endswitch type +#endif // REST_SUPPORT } else type= TAB_UNDEF; @@ -1130,48 +1150,48 @@ PCSZ GetListOption(PGLOBAL g, PCSZ opname, PCSZ oplist, PCSZ def) return (char*)def; char key[16], val[256]; - char *pv, *pn, *pk = (char*)oplist; - PCSZ opval = def; + char *pv, *pn, *pk= (char*)oplist; + PCSZ opval= def; int n; while (*pk == ' ') pk++; - for (; pk; pk = pn) { - pn = strchr(pk, ','); - pv = strchr(pk, '='); + for (; pk; pk= pn) { + pn= strchr(pk, ','); + pv= strchr(pk, '='); if (pv && (!pn || pv < pn)) { - n = MY_MIN(static_cast(pv - pk), sizeof(key) - 1); + n= MY_MIN(static_cast(pv - pk), sizeof(key) - 1); memcpy(key, pk, n); while (n && key[n - 1] == ' ') n--; - key[n] = 0; + key[n]= 0; while (*(++pv) == ' '); - n = MY_MIN((pn ? pn - pv : strlen(pv)), sizeof(val) - 1); + n= MY_MIN((pn ? pn - pv : strlen(pv)), sizeof(val) - 1); memcpy(val, pv, n); while (n && val[n - 1] == ' ') n--; - val[n] = 0; + val[n]= 0; } else { - n = MY_MIN((pn ? pn - pk : strlen(pk)), sizeof(key) - 1); + n= MY_MIN((pn ? pn - pk : strlen(pk)), sizeof(key) - 1); memcpy(key, pk, n); while (n && key[n - 1] == ' ') n--; - key[n] = 0; - val[0] = 0; + key[n]= 0; + val[0]= 0; } // endif pv if (!stricmp(opname, key)) { - opval = PlugDup(g, val); + opval= PlugDup(g, val); break; } else if (!pn) break; @@ -1219,9 +1239,13 @@ PCSZ GetStringTableOption(PGLOBAL g, PTOS options, PCSZ opname, PCSZ sdef) else if (!stricmp(opname, "Colist")) opval= options->colist; else if (!stricmp(opname, "Filter")) - opval = options->filter; + opval= options->filter; else if (!stricmp(opname, "Data_charset")) opval= options->data_charset; + else if (!stricmp(opname, "Http") || !stricmp(opname, "URL")) + opval = options->http; + else if (!stricmp(opname, "Uri")) + opval = options->uri; if (!opval && options->oplist) opval= GetListOption(g, opname, options->oplist); @@ -1252,7 +1276,7 @@ bool GetBooleanTableOption(PGLOBAL g, PTOS options, PCSZ opname, bool bdef) else if (!stricmp(opname, "Header")) opval= (options->header != 0); // Is Boolean for some table types else if (!stricmp(opname, "Zipped")) - opval = options->zipped; + opval= options->zipped; else if (options->oplist) if ((pv= GetListOption(g, opname, options->oplist))) opval= (!*pv || *pv == 'y' || *pv == 'Y' || atoi(pv) != 0); @@ -1346,8 +1370,8 @@ PCSZ ha_connect::GetStringOption(PCSZ opname, PCSZ sdef) } else if (!stricmp(opname, "Query_String")) { // This escapes everything and returns a wrong query -// opval = thd_query_string(table->in_use)->str; - opval = (PCSZ)PlugSubAlloc(xp->g, NULL, +// opval= thd_query_string(table->in_use)->str; + opval= (PCSZ)PlugSubAlloc(xp->g, NULL, thd_query_string(table->in_use)->length + 1); strcpy((char*)opval, thd_query_string(table->in_use)->str); // sprintf((char*)opval, "%s", thd_query_string(table->in_use)->str); @@ -1368,7 +1392,7 @@ PCSZ ha_connect::GetStringOption(PCSZ opname, PCSZ sdef) || !stricmp(opname, "filename") || !stricmp(opname, "optname") || !stricmp(opname, "entry"))) - opval = GetRealString(opval); + opval= GetRealString(opval); if (!opval) { if (sdef && !strcmp(sdef, "*")) { @@ -1497,7 +1521,7 @@ PFOS ha_connect::GetFieldOptionStruct(Field *fdp) void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) { const char *cp; - char *chset, v = 0; + char *chset, v= 0; ha_field_option_struct *fop; Field* fp; Field* *fldp; @@ -1549,7 +1573,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) pcf->Fieldfmt= NULL; } // endif fop - chset = (char *)fp->charset()->name; + chset= (char *)fp->charset()->name; switch (fp->type()) { case MYSQL_TYPE_BLOB: @@ -1817,7 +1841,7 @@ const char *ha_connect::GetTableName(void) { const char *path= tshp ? tshp->path.str : table_share->path.str; const char *name= strrchr(path, slash); - return name ? name+1 : path; + return name ? name + 1 : path; } // end of GetTableName char *ha_connect::GetPartName(void) @@ -2055,10 +2079,10 @@ bool ha_connect::CheckColumnList(PGLOBAL g) } catch (int n) { if (trace(1)) htrc("Exception %d: %s\n", n, g->Message); - brc = true; + brc= true; } catch (const char *msg) { strcpy(g->Message, msg); - brc = true; + brc= true; } // end catch return brc; @@ -2185,9 +2209,9 @@ int ha_connect::MakeRecord(char *buf) rc= fp->store(p, strlen(p), charset, CHECK_FIELD_WARN); break; case TYPE_BIN: - p = value->GetCharValue(); - charset = &my_charset_bin; - rc = fp->store(p, strlen(p), charset, CHECK_FIELD_WARN); + p= value->GetCharValue(); + charset= &my_charset_bin; + rc= fp->store(p, strlen(p), charset, CHECK_FIELD_WARN); break; case TYPE_DOUBLE: rc= fp->store(value->GetFloatValue()); @@ -2436,7 +2460,7 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q, kfp= &table->key_info[active_index]; old_map= dbug_tmp_use_all_columns(table, table->write_set); - for (i = 0; i <= 1; i++) { + for (i= 0; i <= 1; i++) { if (ranges[i] == NULL) continue; @@ -2547,7 +2571,7 @@ const char *ha_connect::GetValStr(OPVAL vop, bool neg) switch (vop) { case OP_EQ: - val= " = "; + val= "= "; break; case OP_NE: val= " <> "; @@ -2817,7 +2841,7 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond) /***********************************************************************/ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) { - AMT tty = filp->Type; + AMT tty= filp->Type; char *body= filp->Body; char *havg= filp->Having; unsigned int i; @@ -2834,7 +2858,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) if (cond->type() == COND::COND_ITEM) { char *pb0, *pb1, *pb2, *ph0= 0, *ph1= 0, *ph2= 0; - bool bb = false, bh = false; + bool bb= false, bh= false; Item_cond *cond_item= (Item_cond *)cond; if (x) @@ -2893,13 +2917,13 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) bb |= filp->Bd; bh |= filp->Hv; - filp->Bd = filp->Hv = false; + filp->Bd= filp->Hv= false; } else return NULL; if (bb) { strcpy(pb1, ")"); - filp->Bd = bb; + filp->Bd= bb; } else *pb0= 0; @@ -2907,13 +2931,13 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) if (bb && bh && vop == OP_OR) { // Cannot or'ed a where clause with a having clause bb= bh= 0; - *pb0 = 0; - *ph0 = 0; + *pb0= 0; + *ph0= 0; } else if (bh) { strcpy(ph1, ")"); filp->Hv= bh; } else - *ph0 = 0; + *ph0= 0; } // endif havg @@ -2926,7 +2950,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) Item_func *condf= (Item_func *)cond; Item* *args= condf->arguments(); - filp->Bd = filp->Hv = false; + filp->Bd= filp->Hv= false; if (trace(1)) htrc("Func type=%d argnum=%d\n", condf->functype(), @@ -2942,10 +2966,10 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) case Item_func::GT_FUNC: vop= OP_GT; break; case Item_func::LIKE_FUNC: vop= OP_LIKE; - neg = ((Item_func_opt_neg *)condf)->negated; + neg= ((Item_func_opt_neg *)condf)->negated; break; case Item_func::ISNOTNULL_FUNC: - neg = true; + neg= true; // fall through case Item_func::ISNULL_FUNC: vop= OP_NULL; break; case Item_func::IN_FUNC: vop= OP_IN; /* fall through */ @@ -3003,12 +3027,12 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) } else { bool h; - fnm = filp->Chk(pField->field->field_name, &h); + fnm= filp->Chk(pField->field->field_name, &h); if (h && i && !ishav) return NULL; // Having should be col VOP arg else - ishav = h; + ishav= h; } // endif's @@ -3059,7 +3083,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) if (!x) { const char *p; - char *s = (ishav) ? havg : body; + char *s= (ishav) ? havg : body; uint j, k, n; // Append the value to the filter @@ -3116,37 +3140,37 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) strcat(s, "'}"); break; default: - j = strlen(s); - s[j++] = '\''; - p = res->ptr(); - n = res->length(); + j= strlen(s); + s[j++]= '\''; + p= res->ptr(); + n= res->length(); - for (k = 0; k < n; k++) { + for (k= 0; k < n; k++) { if (p[k] == '\'') - s[j++] = '\''; + s[j++]= '\''; - s[j++] = p[k]; + s[j++]= p[k]; } // endfor k - s[j++] = '\''; - s[j] = 0; + s[j++]= '\''; + s[j]= 0; } // endswitch field type } else { - j = strlen(s); - s[j++] = '\''; - p = res->ptr(); - n = res->length(); + j= strlen(s); + s[j++]= '\''; + p= res->ptr(); + n= res->length(); - for (k = 0; k < n; k++) { + for (k= 0; k < n; k++) { if (p[k] == '\'') - s[j++] = '\''; + s[j++]= '\''; - s[j++] = p[k]; + s[j++]= p[k]; } // endfor k - s[j++] = '\''; - s[j] = 0; + s[j++]= '\''; + s[j]= 0; } // endif tty break; @@ -3170,7 +3194,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) } // endif's Type if (!x) { - char *s = (ishav) ? havg : body; + char *s= (ishav) ? havg : body; if (!i) strcat(s, GetValStr(vop, neg)); @@ -3184,11 +3208,11 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) } // endfor i if (x) - filp->Op = vop; + filp->Op= vop; else if (ishav) - filp->Hv = true; + filp->Hv= true; else - filp->Bd = true; + filp->Bd= true; } else { if (trace(1)) @@ -3238,21 +3262,21 @@ const COND *ha_connect::cond_push(const COND *cond) PCFIL filp; int rc; - if ((filp = tdbp->GetCondFil()) && tdbp->GetCond() == cond && + if ((filp= tdbp->GetCondFil()) && tdbp->GetCond() == cond && filp->Idx == active_index && filp->Type == tty) goto fin; - filp = new(g) CONDFIL(active_index, tty); - rc = filp->Init(g, this); + filp= new(g) CONDFIL(active_index, tty); + rc= filp->Init(g, this); if (rc == RC_INFO) { - filp->Having = (char*)PlugSubAlloc(g, NULL, 256); - *filp->Having = 0; + filp->Having= (char*)PlugSubAlloc(g, NULL, 256); + *filp->Having= 0; } else if (rc == RC_FX) goto fin; - filp->Body = (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0); - *filp->Body = 0; + filp->Body= (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0); + *filp->Body= 0; if (CheckCond(g, filp, cond)) { if (filp->Having && strlen(filp->Having) > 255) @@ -3266,7 +3290,7 @@ const COND *ha_connect::cond_push(const COND *cond) if (!x) PlugSubAlloc(g, NULL, strlen(filp->Body) + 1); else - cond = NULL; // Does this work? + cond= NULL; // Does this work? tdbp->SetCondFil(filp); } else if (x && cond) @@ -3316,8 +3340,8 @@ ha_rows ha_connect::records() int ha_connect::check(THD* thd, HA_CHECK_OPT* check_opt) { - int rc = HA_ADMIN_OK; - PGLOBAL g = ((table && table->in_use) ? GetPlug(table->in_use, xp) : + int rc= HA_ADMIN_OK; + PGLOBAL g= ((table && table->in_use) ? GetPlug(table->in_use, xp) : (xp) ? xp->g : NULL); DBUG_ENTER("ha_connect::check"); @@ -3327,32 +3351,32 @@ int ha_connect::check(THD* thd, HA_CHECK_OPT* check_opt) // Do not close the table if it was opened yet (possible?) if (IsOpened()) { if (IsPartitioned() && CheckColumnList(g)) // map can have been changed - rc = HA_ADMIN_CORRUPT; + rc= HA_ADMIN_CORRUPT; else if (tdbp->OpenDB(g)) // Rewind table - rc = HA_ADMIN_CORRUPT; + rc= HA_ADMIN_CORRUPT; } else if (xp->CheckQuery(valid_query_id)) { - tdbp = NULL; // Not valid anymore + tdbp= NULL; // Not valid anymore if (OpenTable(g, false)) - rc = HA_ADMIN_CORRUPT; + rc= HA_ADMIN_CORRUPT; } else // possible? DBUG_RETURN(HA_ADMIN_INTERNAL_ERROR); if (rc == HA_ADMIN_OK) { - TABTYPE type = GetTypeID(GetStringOption("Type", "*")); + TABTYPE type= GetTypeID(GetStringOption("Type", "*")); if (IsFileType(type)) { if (check_opt->flags & T_MEDIUM) { // TO DO do { - if ((rc = CntReadNext(g, tdbp)) == RC_FX) + if ((rc= CntReadNext(g, tdbp)) == RC_FX) break; } while (rc != RC_EF); - rc = (rc == RC_EF) ? HA_ADMIN_OK : HA_ADMIN_CORRUPT; + rc= (rc == RC_EF) ? HA_ADMIN_OK : HA_ADMIN_CORRUPT; } else if (check_opt->flags & T_EXTEND) { // TO DO } // endif's flags @@ -3380,7 +3404,7 @@ bool ha_connect::get_error_message(int error, String* buf) DBUG_ENTER("ha_connect::get_error_message"); if (xp && xp->g) { - PGLOBAL g = xp->g; + PGLOBAL g= xp->g; if (trace(1)) htrc("GEM(%d): %s\n", error, g->Message); @@ -3489,32 +3513,32 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT*) try { // Ignore error on the opt file dup->Check &= ~CHK_OPT; - tdbp = GetTDB(g); + tdbp= GetTDB(g); dup->Check |= CHK_OPT; if (tdbp && !tdbp->IsRemote()) { - bool dop = IsTypeIndexable(GetRealType(NULL)); - bool dox = (tdbp->GetDef()->Indexable() == 1); + bool dop= IsTypeIndexable(GetRealType(NULL)); + bool dox= (tdbp->GetDef()->Indexable() == 1); - if ((rc = ((PTDBASE)tdbp)->ResetTableOpt(g, dop, dox))) { + if ((rc= ((PTDBASE)tdbp)->ResetTableOpt(g, dop, dox))) { if (rc == RC_INFO) { push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); - rc = 0; + rc= 0; } else - rc = HA_ERR_CRASHED_ON_USAGE; // Table must be repaired + rc= HA_ERR_CRASHED_ON_USAGE; // Table must be repaired } // endif rc } else if (!tdbp) - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; } catch (int n) { if (trace(1)) htrc("Exception %d: %s\n", n, g->Message); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; } catch (const char *msg) { strcpy(g->Message, msg); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; } // end catch if (rc) @@ -4214,7 +4238,7 @@ int ha_connect::rnd_pos(uchar *buf, uchar *pos) tdbp->SetFilter(NULL); rc= rnd_next(buf); } else { - PGLOBAL g = GetPlug((table) ? table->in_use : NULL, xp); + PGLOBAL g= GetPlug((table) ? table->in_use : NULL, xp); // strcpy(g->Message, "Not supported by this table type"); my_message(ER_ILLEGAL_HA, g->Message, MYF(0)); rc= HA_ERR_INTERNAL_ERROR; @@ -4298,12 +4322,12 @@ int ha_connect::info(uint flag) } else DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen - if (!(tdbp = GetTDB(g))) { + if (!(tdbp= GetTDB(g))) { my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } // endif tdbp - valid_info = false; + valid_info= false; } // endif tdbp if (!valid_info) { @@ -4446,6 +4470,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick) case TAB_XML: case TAB_INI: case TAB_VEC: + case TAB_REST: case TAB_JSON: if (options->filename && *options->filename) { if (!quick) { @@ -4582,13 +4607,13 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd, // newmode= MODE_UPDATE; // To be checked // break; case SQLCOM_DELETE_MULTI: - *cras = true; + *cras= true; case SQLCOM_DELETE: case SQLCOM_TRUNCATE: newmode= MODE_DELETE; break; case SQLCOM_UPDATE_MULTI: - *cras = true; + *cras= true; case SQLCOM_UPDATE: newmode= MODE_UPDATE; break; @@ -4616,7 +4641,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd, break; // } // endif partitioned case SQLCOM_REPAIR: // TODO implement it - newmode = MODE_UPDATE; + newmode= MODE_UPDATE; break; default: htrc("Unsupported sql_command=%d\n", thd_sql_command(thd)); @@ -4731,15 +4756,15 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type) if (CloseTable(g)) { // Make error a warning to avoid crash push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); - rc = 0; + rc= 0; } // endif Close - locked = 0; - xmod = MODE_ANY; // For info commands + locked= 0; + xmod= MODE_ANY; // For info commands DBUG_RETURN(rc); } // endif MODE_ANY - newmode = CheckMode(g, thd, newmode, &chk, &cras); + newmode= CheckMode(g, thd, newmode, &chk, &cras); if (newmode == MODE_ERROR) DBUG_RETURN(HA_ERR_INTERNAL_ERROR); @@ -4815,7 +4840,7 @@ int ha_connect::external_lock(THD *thd, int lock_type) DBUG_RETURN(0); } else if (g->Xchk) { if (!tdbp) { - if (!(tdbp = GetTDB(g))) { + if (!(tdbp= GetTDB(g))) { // DBUG_RETURN(HA_ERR_INTERNAL_ERROR); causes assert error push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); DBUG_RETURN(0); @@ -4952,7 +4977,7 @@ int ha_connect::external_lock(THD *thd, int lock_type) int ha_connect::check_stmt(PGLOBAL g, MODE newmode, bool cras) { - int rc = 0; + int rc= 0; DBUG_ENTER("ha_connect::check_stmt"); // If this is the start of a new query, cleanup the previous one @@ -5039,7 +5064,7 @@ THR_LOCK_DATA **ha_connect::store_lock(THD *, { if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) lock.type=lock_type; - *to++ = &lock; + *to++= &lock; return to; } @@ -5316,7 +5341,7 @@ static bool add_field(String *sql, const char *field_name, int typ, int len, int dec, char *key, uint tm, const char *rem, char *dft, char *xtra, char *fmt, int flag, bool dbf, char v) { - char var = (len > 255) ? 'V' : v; + char var= (len > 255) ? 'V' : v; bool q, error= false; const char *type= PLGtoMYSQLtype(typ, dbf, var); @@ -5360,9 +5385,9 @@ static bool add_field(String *sql, const char *field_name, int typ, int len, error|= sql->append(" DEFAULT "); if (typ == TYPE_DATE) - q = (strspn(dft, "0123456789 -:/") == strlen(dft)); + q= (strspn(dft, "0123456789 -:/") == strlen(dft)); else - q = !IsTypeNum(typ); + q= !IsTypeNum(typ); if (q) { error|= sql->append("'"); @@ -5514,13 +5539,13 @@ static int connect_assisted_discovery(handlerton *, THD* thd, PCSZ fncn= "?"; PCSZ user, fn, db, host, pwd, sep, tbl, src; PCSZ col, ocl, rnk, pic, fcl, skc, zfn; - char *tab, *dsn, *shm, *dpath; + char *tab, *dsn, *shm, *dpath, *url; #if defined(__WIN__) PCSZ nsp= NULL, cls= NULL; #endif // __WIN__ //int hdr, mxe; - int port = 0, mxr = 0, rc = 0, mul = 0, lrecl = 0; -//PCSZ tabtyp = NULL; + int port= 0, mxr= 0, rc= 0, mul= 0, lrecl= 0; +//PCSZ tabtyp= NULL; #if defined(ODBC_SUPPORT) POPARM sop= NULL; PCSZ ucnc= NULL; @@ -5530,7 +5555,6 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #if defined(JAVA_SUPPORT) PJPARM sjp= NULL; PCSZ driver= NULL; - char *url= NULL; #endif // JAVA_SUPPORT uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL); bool bif, ok= false, dbf= false; @@ -5550,7 +5574,8 @@ static int connect_assisted_discovery(handlerton *, THD* thd, String sql(buf, sizeof(buf), system_charset_info); sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info); - user= host= pwd= tbl= src= col= ocl= pic= fcl= skc= rnk= zfn= dsn= NULL; + user = host = pwd = tbl = src = col = ocl = pic = fcl = skc = rnk = zfn = NULL; + dsn = url = NULL; // Get the useful create options ttp= GetTypeID(topt->type); @@ -5561,7 +5586,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, fncn= topt->catfunc; fnc= GetFuncID(fncn); sep= topt->separator; - mul = (int)topt->multiple; + mul= (int)topt->multiple; tbl= topt->tablist; col= topt->colist; @@ -5584,7 +5609,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #endif // __WIN__ port= atoi(GetListOption(g, "port", topt->oplist, "0")); #if defined(ODBC_SUPPORT) -// tabtyp = GetListOption(g, "Tabtype", topt->oplist, NULL); +// tabtyp= GetListOption(g, "Tabtype", topt->oplist, NULL); mxr= atoi(GetListOption(g,"maxres", topt->oplist, "0")); cto= atoi(GetListOption(g,"ConnectTimeout", topt->oplist, "-1")); qto= atoi(GetListOption(g,"QueryTimeout", topt->oplist, "-1")); @@ -5599,7 +5624,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0")); #endif // PROMPT_OK #if defined(ZIP_SUPPORT) - zfn = GetListOption(g, "Zipfile", topt->oplist, NULL); + zfn= GetListOption(g, "Zipfile", topt->oplist, NULL); #endif // ZIP_SUPPORT } else { host= "localhost"; @@ -5612,14 +5637,24 @@ static int connect_assisted_discovery(handlerton *, THD* thd, try { // Check table type if (ttp == TAB_UNDEF) { - topt->type = (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS"; - ttp = GetTypeID(topt->type); + topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS"; + ttp= GetTypeID(topt->type); sprintf(g->Message, "No table_type. Was set to %s", topt->type); push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); } else if (ttp == TAB_NIY) { sprintf(g->Message, "Unsupported table type %s", topt->type); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; +#if defined(REST_SUPPORT) + } else if (topt->http) { + switch (ttp) { + case TAB_JSON: + case TAB_XML: + case TAB_CSV: + ttp = TAB_REST; + break; + } // endswitch type +#endif // REST_SUPPORT } // endif ttp if (!tab) { @@ -5629,39 +5664,39 @@ static int connect_assisted_discovery(handlerton *, THD* thd, if (!tbl) { strcpy(g->Message, "Missing table list"); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif tbl - tab = PlugDup(g, tbl); + tab= PlugDup(g, tbl); - if ((p = strchr(tab, ','))) - *p = 0; + if ((p= strchr(tab, ','))) + *p= 0; - if ((p = strchr(tab, '.'))) { - *p = 0; - db = tab; - tab = p + 1; + if ((p= strchr(tab, '.'))) { + *p= 0; + db= tab; + tab= p + 1; } // endif p } else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL))) - tab = (char*)table_s->table_name.str; // Default value + tab= (char*)table_s->table_name.str; // Default value } // endif tab switch (ttp) { #if defined(ODBC_SUPPORT) case TAB_ODBC: - dsn = strz(g, create_info->connect_string); + dsn= strz(g, create_info->connect_string); if (fnc & (FNC_DSN | FNC_DRIVER)) { - ok = true; + ok= true; #if defined(PROMPT_OK) } else if (!stricmp(thd->main_security_ctx.host, "localhost") && cop == 1) { - if ((dsn = ODBCCheckConnection(g, dsn, cop)) != NULL) { + if ((dsn= ODBCCheckConnection(g, dsn, cop)) != NULL) { thd->make_lex_string(&create_info->connect_string, dsn, strlen(dsn)); - ok = true; + ok= true; } // endif dsn #endif // PROMPT_OK @@ -5669,13 +5704,13 @@ static int connect_assisted_discovery(handlerton *, THD* thd, sprintf(g->Message, "Missing %s connection string", topt->type); } else { // Store ODBC additional parameters - sop = (POPARM)PlugSubAlloc(g, NULL, sizeof(ODBCPARM)); - sop->User = (char*)user; - sop->Pwd = (char*)pwd; - sop->Cto = cto; - sop->Qto = qto; - sop->UseCnc = cnc; - ok = true; + sop= (POPARM)PlugSubAlloc(g, NULL, sizeof(ODBCPARM)); + sop->User= (char*)user; + sop->Pwd= (char*)pwd; + sop->Cto= cto; + sop->Qto= qto; + sop->UseCnc= cnc; + ok= true; } // endif's supfnc |= (FNC_TABLE | FNC_DSN | FNC_DRIVER); @@ -5684,31 +5719,31 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #if defined(JAVA_SUPPORT) case TAB_JDBC: if (fnc & FNC_DRIVER) { - ok = true; - } else if (!(url = strz(g, create_info->connect_string))) { + ok= true; + } else if (!(url= strz(g, create_info->connect_string))) { strcpy(g->Message, "Missing URL"); } else { // Store JDBC additional parameters int rc; - PJDBCDEF jdef = new(g) JDBCDEF(); + PJDBCDEF jdef= new(g) JDBCDEF(); jdef->SetName(create_info->alias); - sjp = (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM)); - sjp->Driver = driver; - // sjp->Properties = prop; - sjp->Fsize = 0; - sjp->Scrollable = false; + sjp= (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM)); + sjp->Driver= driver; + // sjp->Properties= prop; + sjp->Fsize= 0; + sjp->Scrollable= false; - if ((rc = jdef->ParseURL(g, url, false)) == RC_OK) { - sjp->Url = url; - sjp->User = (char*)user; - sjp->Pwd = (char*)pwd; - ok = true; + if ((rc= jdef->ParseURL(g, url, false)) == RC_OK) { + sjp->Url= url; + sjp->User= (char*)user; + sjp->Pwd= (char*)pwd; + ok= true; } else if (rc == RC_NF) { if (jdef->GetTabname()) - tab = (char*)jdef->GetTabname(); + tab= (char*)jdef->GetTabname(); - ok = jdef->SetParms(sjp); + ok= jdef->SetParms(sjp); } // endif rc } // endif's @@ -5717,7 +5752,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, break; #endif // JAVA_SUPPORT case TAB_DBF: - dbf = true; + dbf= true; // fall through case TAB_CSV: if (!fn && fnc != FNC_NO) @@ -5725,55 +5760,55 @@ static int connect_assisted_discovery(handlerton *, THD* thd, else if (sep && strlen(sep) > 1) sprintf(g->Message, "Invalid separator %s", sep); else - ok = true; + ok= true; break; case TAB_MYSQL: - ok = true; + ok= true; if (create_info->connect_string.str && create_info->connect_string.length) { - PMYDEF mydef = new(g) MYSQLDEF(); + PMYDEF mydef= new(g) MYSQLDEF(); - dsn = strz(g, create_info->connect_string); + dsn= strz(g, create_info->connect_string); mydef->SetName(create_info->alias); if (!mydef->ParseURL(g, dsn, false)) { if (mydef->GetHostname()) - host = mydef->GetHostname(); + host= mydef->GetHostname(); if (mydef->GetUsername()) - user = mydef->GetUsername(); + user= mydef->GetUsername(); if (mydef->GetPassword()) - pwd = mydef->GetPassword(); + pwd= mydef->GetPassword(); if (mydef->GetTabschema()) - db = mydef->GetTabschema(); + db= mydef->GetTabschema(); if (mydef->GetTabname()) - tab = (char*)mydef->GetTabname(); + tab= (char*)mydef->GetTabname(); if (mydef->GetPortnumber()) - port = mydef->GetPortnumber(); + port= mydef->GetPortnumber(); } else - ok = false; + ok= false; } else if (!user) - user = "root"; + user= "root"; if (ok && CheckSelf(g, table_s, host, db, tab, src, port)) - ok = false; + ok= false; break; #if defined(__WIN__) case TAB_WMI: - ok = true; + ok= true; break; #endif // __WIN__ case TAB_PIVOT: - supfnc = FNC_NO; + supfnc= FNC_NO; case TAB_PRX: case TAB_TBL: case TAB_XCL: @@ -5782,12 +5817,12 @@ static int connect_assisted_discovery(handlerton *, THD* thd, (!db || !stricmp(db, table_s->db.str))) sprintf(g->Message, "A %s table cannot refer to itself", topt->type); else - ok = true; + ok= true; break; case TAB_OEM: if (topt->module && topt->subtype) - ok = true; + ok= true; else strcpy(g->Message, "Missing OEM module or subtype"); @@ -5796,24 +5831,33 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case TAB_XML: #endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT case TAB_JSON: - dsn = strz(g, create_info->connect_string); + dsn= strz(g, create_info->connect_string); if (!fn && !zfn && !mul && !dsn) sprintf(g->Message, "Missing %s file name", topt->type); else - ok = true; + ok= true; break; #if defined(JAVA_SUPPORT) case TAB_MONGO: if (!topt->tabname) - topt->tabname = tab; + topt->tabname= tab; - ok = true; + ok= true; break; #endif // JAVA_SUPPORT +#if defined(REST_SUPPORT) + case TAB_REST: + if (!topt->http) + sprintf(g->Message, "Missing %s HTTP address", topt->type); + else + ok = true; + + break; +#endif // REST_SUPPORT case TAB_VIR: - ok = true; + ok= true; break; default: sprintf(g->Message, "Cannot get column info for table type %s", topt->type); @@ -5824,12 +5868,12 @@ static int connect_assisted_discovery(handlerton *, THD* thd, if (ok && !(supfnc & fnc)) { sprintf(g->Message, "Unsupported catalog function %s for table type %s", fncn, topt->type); - ok = false; + ok= false; } // endif supfnc if (src && fnc != FNC_NO) { strcpy(g->Message, "Cannot make catalog table from srcdef"); - ok = false; + ok= false; } // endif src if (ok) { @@ -5837,23 +5881,23 @@ static int connect_assisted_discovery(handlerton *, THD* thd, char *dft, *xtra, *key, *fmt; int i, len, prec, dec, typ, flg; - if (!(dpath = SetPath(g, table_s->db.str))) { - rc = HA_ERR_INTERNAL_ERROR; + if (!(dpath= SetPath(g, table_s->db.str))) { + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif dpath if (src && ttp != TAB_PIVOT && ttp != TAB_ODBC && ttp != TAB_JDBC) { - qrp = SrcColumns(g, host, db, user, pwd, src, port); + qrp= SrcColumns(g, host, db, user, pwd, src, port); if (qrp && ttp == TAB_OCCUR) if (OcrSrcCols(g, qrp, col, ocl, rnk)) { - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif OcrSrcCols } else switch (ttp) { case TAB_DBF: - qrp = DBFColumns(g, dpath, fn, fnc == FNC_COL); + qrp= DBFColumns(g, dpath, fn, fnc == FNC_COL); break; #if defined(ODBC_SUPPORT) case TAB_ODBC: @@ -5861,21 +5905,21 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case FNC_NO: case FNC_COL: if (src) { - qrp = ODBCSrcCols(g, dsn, (char*)src, sop); - src = NULL; // for next tests + qrp= ODBCSrcCols(g, dsn, (char*)src, sop); + src= NULL; // for next tests } else - qrp = ODBCColumns(g, dsn, shm, tab, NULL, + qrp= ODBCColumns(g, dsn, shm, tab, NULL, mxr, fnc == FNC_COL, sop); break; case FNC_TABLE: - qrp = ODBCTables(g, dsn, shm, tab, NULL, mxr, true, sop); + qrp= ODBCTables(g, dsn, shm, tab, NULL, mxr, true, sop); break; case FNC_DSN: - qrp = ODBCDataSources(g, mxr, true); + qrp= ODBCDataSources(g, mxr, true); break; case FNC_DRIVER: - qrp = ODBCDrivers(g, mxr, true); + qrp= ODBCDrivers(g, mxr, true); break; default: sprintf(g->Message, "invalid catfunc %s", fncn); @@ -5890,23 +5934,23 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case FNC_NO: case FNC_COL: if (src) { - qrp = JDBCSrcCols(g, (char*)src, sjp); - src = NULL; // for next tests + qrp= JDBCSrcCols(g, (char*)src, sjp); + src= NULL; // for next tests } else - qrp = JDBCColumns(g, shm, tab, NULL, mxr, fnc == FNC_COL, sjp); + qrp= JDBCColumns(g, shm, tab, NULL, mxr, fnc == FNC_COL, sjp); break; case FNC_TABLE: -// qrp = JDBCTables(g, shm, tab, tabtyp, mxr, true, sjp); - qrp = JDBCTables(g, shm, tab, NULL, mxr, true, sjp); +// qrp= JDBCTables(g, shm, tab, tabtyp, mxr, true, sjp); + qrp= JDBCTables(g, shm, tab, NULL, mxr, true, sjp); break; #if 0 case FNC_DSN: - qrp = JDBCDataSources(g, mxr, true); + qrp= JDBCDataSources(g, mxr, true); break; #endif // 0 case FNC_DRIVER: - qrp = JDBCDrivers(g, mxr, true); + qrp= JDBCDrivers(g, mxr, true); break; default: sprintf(g->Message, "invalid catfunc %s", fncn); @@ -5916,56 +5960,61 @@ static int connect_assisted_discovery(handlerton *, THD* thd, break; #endif // JAVA_SUPPORT case TAB_MYSQL: - qrp = MyColumns(g, thd, host, db, user, pwd, tab, + qrp= MyColumns(g, thd, host, db, user, pwd, tab, NULL, port, fnc == FNC_COL); break; case TAB_CSV: - qrp = CSVColumns(g, dpath, topt, fnc == FNC_COL); + qrp= CSVColumns(g, dpath, topt, fnc == FNC_COL); break; #if defined(__WIN__) case TAB_WMI: - qrp = WMIColumns(g, nsp, cls, fnc == FNC_COL); + qrp= WMIColumns(g, nsp, cls, fnc == FNC_COL); break; #endif // __WIN__ case TAB_PRX: case TAB_TBL: case TAB_XCL: case TAB_OCCUR: - bif = fnc == FNC_COL; - qrp = TabColumns(g, thd, db, tab, bif); + bif= fnc == FNC_COL; + qrp= TabColumns(g, thd, db, tab, bif); if (!qrp && bif && fnc != FNC_COL) // tab is a view - qrp = MyColumns(g, thd, host, db, user, pwd, tab, NULL, port, false); + qrp= MyColumns(g, thd, host, db, user, pwd, tab, NULL, port, false); if (qrp && ttp == TAB_OCCUR && fnc != FNC_COL) if (OcrColumns(g, qrp, col, ocl, rnk)) { - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif OcrColumns break; case TAB_PIVOT: - qrp = PivotColumns(g, tab, src, pic, fcl, skc, host, db, user, pwd, port); + qrp= PivotColumns(g, tab, src, pic, fcl, skc, host, db, user, pwd, port); break; case TAB_VIR: - qrp = VirColumns(g, fnc == FNC_COL); + qrp= VirColumns(g, fnc == FNC_COL); break; case TAB_JSON: - qrp = JSONColumns(g, db, dsn, topt, fnc == FNC_COL); + qrp= JSONColumns(g, db, dsn, topt, fnc == FNC_COL); break; #if defined(JAVA_SUPPORT) case TAB_MONGO: - url = strz(g, create_info->connect_string); - qrp = MGOColumns(g, db, url, topt, fnc == FNC_COL); + url= strz(g, create_info->connect_string); + qrp= MGOColumns(g, db, url, topt, fnc == FNC_COL); break; #endif // JAVA_SUPPORT #if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT) case TAB_XML: - qrp = XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL); + qrp= XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL); break; #endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT +#if defined(REST_SUPPORT) + case TAB_REST: + qrp = RESTColumns(g, topt, tab, (char *)db, fnc == FNC_COL); + break; +#endif // REST_SUPPORT case TAB_OEM: - qrp = OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL); + qrp= OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL); break; default: strcpy(g->Message, "System error during assisted discovery"); @@ -5973,33 +6022,33 @@ static int connect_assisted_discovery(handlerton *, THD* thd, } // endswitch ttp if (!qrp) { - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif !qrp if (fnc != FNC_NO || src || ttp == TAB_PIVOT) { // Catalog like table - for (crp = qrp->Colresp; !rc && crp; crp = crp->Next) { - cnm = (ttp == TAB_PIVOT) ? crp->Name : encode(g, crp->Name); - typ = crp->Type; - len = crp->Length; - dec = crp->Prec; - flg = crp->Flag; - v = (crp->Kdata->IsUnsigned()) ? 'U' : crp->Var; - tm = (crp->Kdata->IsNullable()) ? 0 : NOT_NULL_FLAG; + for (crp= qrp->Colresp; !rc && crp; crp= crp->Next) { + cnm= (ttp == TAB_PIVOT) ? crp->Name : encode(g, crp->Name); + typ= crp->Type; + len= crp->Length; + dec= crp->Prec; + flg= crp->Flag; + v= (crp->Kdata->IsUnsigned()) ? 'U' : crp->Var; + tm= (crp->Kdata->IsNullable()) ? 0 : NOT_NULL_FLAG; if (!len && typ == TYPE_STRING) - len = 256; // STRBLK's have 0 length + len= 256; // STRBLK's have 0 length // Now add the field if (add_field(&sql, cnm, typ, len, dec, NULL, tm, NULL, NULL, NULL, NULL, flg, dbf, v)) - rc = HA_ERR_OUT_OF_MEM; + rc= HA_ERR_OUT_OF_MEM; } // endfor crp } else { - char *schem = NULL; - char *tn = NULL; + char *schem= NULL; + char *tn= NULL; // Not a catalog table if (!qrp->Nblin) { @@ -6008,57 +6057,57 @@ static int connect_assisted_discovery(handlerton *, THD* thd, else strcpy(g->Message, "Fail to retrieve columns"); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif !nblin - for (i = 0; !rc && i < qrp->Nblin; i++) { - typ = len = prec = dec = 0; - tm = NOT_NULL_FLAG; - cnm = (char*)"noname"; - dft = xtra = key = fmt = tn = NULL; - v = ' '; - rem = NULL; + for (i= 0; !rc && i < qrp->Nblin; i++) { + typ= len= prec= dec= 0; + tm= NOT_NULL_FLAG; + cnm= (char*)"noname"; + dft= xtra= key= fmt= tn= NULL; + v= ' '; + rem= NULL; - for (crp = qrp->Colresp; crp; crp = crp->Next) + for (crp= qrp->Colresp; crp; crp= crp->Next) switch (crp->Fld) { case FLD_NAME: if (ttp == TAB_PRX || (ttp == TAB_CSV && topt->data_charset && (!stricmp(topt->data_charset, "UTF8") || !stricmp(topt->data_charset, "UTF-8")))) - cnm = crp->Kdata->GetCharValue(i); + cnm= crp->Kdata->GetCharValue(i); else - cnm = encode(g, crp->Kdata->GetCharValue(i)); + cnm= encode(g, crp->Kdata->GetCharValue(i)); break; case FLD_TYPE: - typ = crp->Kdata->GetIntValue(i); - v = (crp->Nulls) ? crp->Nulls[i] : 0; + typ= crp->Kdata->GetIntValue(i); + v= (crp->Nulls) ? crp->Nulls[i] : 0; break; case FLD_TYPENAME: - tn = crp->Kdata->GetCharValue(i); + tn= crp->Kdata->GetCharValue(i); break; case FLD_PREC: // PREC must be always before LENGTH - len = prec = crp->Kdata->GetIntValue(i); + len= prec= crp->Kdata->GetIntValue(i); break; case FLD_LENGTH: - len = crp->Kdata->GetIntValue(i); + len= crp->Kdata->GetIntValue(i); break; case FLD_SCALE: - dec = (!crp->Kdata->IsNull(i)) ? crp->Kdata->GetIntValue(i) : -1; + dec= (!crp->Kdata->IsNull(i)) ? crp->Kdata->GetIntValue(i) : -1; break; case FLD_NULL: if (crp->Kdata->GetIntValue(i)) - tm = 0; // Nullable + tm= 0; // Nullable break; case FLD_FORMAT: - fmt = (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL; + fmt= (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL; break; case FLD_REM: - rem = crp->Kdata->GetCharValue(i); + rem= crp->Kdata->GetCharValue(i); break; // case FLD_CHARSET: // No good because remote table is already translated @@ -6067,19 +6116,19 @@ static int connect_assisted_discovery(handlerton *, THD* thd, // break; case FLD_DEFAULT: - dft = crp->Kdata->GetCharValue(i); + dft= crp->Kdata->GetCharValue(i); break; case FLD_EXTRA: - xtra = crp->Kdata->GetCharValue(i); + xtra= crp->Kdata->GetCharValue(i); // Auto_increment is not supported yet if (!stricmp(xtra, "AUTO_INCREMENT")) - xtra = NULL; + xtra= NULL; break; case FLD_KEY: if (ttp == TAB_VIR) - key = crp->Kdata->GetCharValue(i); + key= crp->Kdata->GetCharValue(i); break; case FLD_SCHEM: @@ -6088,10 +6137,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, if (schem && stricmp(schem, crp->Kdata->GetCharValue(i))) { sprintf(g->Message, "Several %s tables found, specify DBNAME", tab); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } else if (!schem) - schem = crp->Kdata->GetCharValue(i); + schem= crp->Kdata->GetCharValue(i); } // endif ttp #endif // ODBC_SUPPORT || JAVA_SUPPORT @@ -6102,10 +6151,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #if defined(ODBC_SUPPORT) if (ttp == TAB_ODBC) { int plgtyp; - bool w = false; // Wide character type + bool w= false; // Wide character type // typ must be PLG type, not SQL type - if (!(plgtyp = TranslateSQLType(typ, dec, prec, v, w))) { + if (!(plgtyp= TranslateSQLType(typ, dec, prec, v, w))) { if (GetTypeConv() == TPC_SKIP) { // Skip this column sprintf(g->Message, "Column %s skipped (unsupported type %d)", @@ -6114,12 +6163,12 @@ static int connect_assisted_discovery(handlerton *, THD* thd, continue; } else { sprintf(g->Message, "Unsupported SQL type %d", typ); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif type_conv } else - typ = plgtyp; + typ= plgtyp; switch (typ) { case TYPE_STRING: @@ -6134,10 +6183,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, prec += (dec + 2); // To be safe break; case TYPE_DECIM: - prec = len; + prec= len; break; default: - dec = 0; + dec= 0; } // endswitch typ } else @@ -6147,7 +6196,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, int plgtyp; // typ must be PLG type, not SQL type - if (!(plgtyp = TranslateJDBCType(typ, tn, dec, prec, v))) { + if (!(plgtyp= TranslateJDBCType(typ, tn, dec, prec, v))) { if (GetTypeConv() == TPC_SKIP) { // Skip this column sprintf(g->Message, "Column %s skipped (unsupported type %d)", @@ -6156,12 +6205,12 @@ static int connect_assisted_discovery(handlerton *, THD* thd, continue; } else { sprintf(g->Message, "Unsupported SQL type %d", typ); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; goto err; } // endif type_conv } else - typ = plgtyp; + typ= plgtyp; switch (typ) { case TYPE_DOUBLE: @@ -6170,43 +6219,43 @@ static int connect_assisted_discovery(handlerton *, THD* thd, prec += (dec + 2); // To be safe break; default: - dec = 0; + dec= 0; } // endswitch typ } else #endif // ODBC_SUPPORT // Make the arguments as required by add_fields if (typ == TYPE_DOUBLE) - prec = len; + prec= len; if (typ == TYPE_DATE) - prec = 0; + prec= 0; // Now add the field if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra, fmt, 0, dbf, v)) - rc = HA_ERR_OUT_OF_MEM; + rc= HA_ERR_OUT_OF_MEM; } // endfor i } // endif fnc if (!rc) - rc = init_table_share(thd, table_s, create_info, &sql); + rc= init_table_share(thd, table_s, create_info, &sql); //g->jump_level--; //PopUser(xp); //return rc; } else { - rc = HA_ERR_UNSUPPORTED; + rc= HA_ERR_UNSUPPORTED; } // endif ok } catch (int n) { if (trace(1)) htrc("Exception %d: %s\n", n, g->Message); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; } catch (const char *msg) { strcpy(g->Message, msg); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; } // end catch err: @@ -6274,9 +6323,9 @@ int ha_connect::create(const char *name, TABLE *table_arg, TABTYPE type; TABLE *st= table; // Probably unuseful THD *thd= ha_thd(); - LEX_STRING cnc = table_arg->s->connect_string; -#ifdef WITH_PARTITION_STORAGE_ENGINE - partition_info *part_info= table_arg->part_info; + LEX_STRING cnc= table_arg->s->connect_string; +#if defined(WITH_PARTITION_STORAGE_ENGINE) + partition_info *part_info= table_arg->part_info; #else // !WITH_PARTITION_STORAGE_ENGINE #define part_info 0 #endif // !WITH_PARTITION_STORAGE_ENGINE @@ -6401,7 +6450,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, host= mydef->GetHostname(); if (mydef->GetTabschema()) - db = mydef->GetTabschema(); + db= mydef->GetTabschema(); if (mydef->GetTabname()) tab= mydef->GetTabname(); @@ -6484,7 +6533,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); @@ -6683,17 +6732,18 @@ int ha_connect::create(const char *name, TABLE *table_arg, if (trace(1)) htrc("xchk=%p createas=%d\n", g->Xchk, g->Createas); +#if defined(ZIP_SUPPORT) if (options->zipped) { // Check whether the zip entry must be made from a file - PCSZ fn = GetListOption(g, "Load", options->oplist, NULL); + 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)); @@ -6712,6 +6762,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, } // endif fn } // endif zipped +#endif // ZIP_SUPPORT // To check whether indexes have to be made or remade if (!g->Xchk) { @@ -6761,7 +6812,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, if (SetDataPath(g, table_arg->s->db.str)) { my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); - rc = HA_ERR_INTERNAL_ERROR; + rc= HA_ERR_INTERNAL_ERROR; } else if (cat) { if (part_info) strncpy(partname, @@ -7103,7 +7154,7 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table, /* ALTER TABLE tbl_name CONVERT TO CHARACTER SET .. and - ALTER TABLE table_name DEFAULT CHARSET = .. most likely + ALTER TABLE table_name DEFAULT CHARSET= .. most likely change column charsets and so not supported in-place through old API. @@ -7335,7 +7386,7 @@ maria_declare_plugin(connect) 0x0106, /* version number (1.06) */ NULL, /* status variables */ connect_system_variables, /* system variables */ - "1.06.0009", /* string version */ + "1.06.0010", /* string version */ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ } maria_declare_plugin_end; diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h index ea495557fcf..9a12ef94431 100644 --- a/storage/connect/ha_connect.h +++ b/storage/connect/ha_connect.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file ha_connect.h Author Olivier Bertrand @@ -32,6 +32,10 @@ /****************************************************************************/ #include "mycat.h" +#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) +bool MongoEnabled(void); +#endif // JAVA_SUPPORT || CMGO_SUPPORT + /****************************************************************************/ /* Structures used to pass info between CONNECT and ha_connect. */ /****************************************************************************/ diff --git a/storage/connect/inihandl.cpp b/storage/connect/inihandl.cpp index 8a911cb05c0..8e79aeac7ef 100644 --- a/storage/connect/inihandl.cpp +++ b/storage/connect/inihandl.cpp @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #include "my_global.h" @@ -194,7 +194,7 @@ static void PROFILE_Save( FILE *file, PROFILESECTION *section ) } for (key = section->key; key; key = key->next) - if (key->name[0]) { + if (key->name && key->name[0]) { fprintf(file, "%s", SVP(key->name)); if (key->value) diff --git a/storage/connect/jmgoconn.cpp b/storage/connect/jmgoconn.cpp index bd1ddadd80d..c80800bd897 100644 --- a/storage/connect/jmgoconn.cpp +++ b/storage/connect/jmgoconn.cpp @@ -272,7 +272,7 @@ bool JMgoConn::MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options, if (MakeSelector(g, filp, s)) { strcpy(g->Message, "Failed making selector"); - return NULL; + return true; } else s->Append('}'); @@ -340,7 +340,7 @@ bool JMgoConn::MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options, if (MakeSelector(g, filp, s)) { strcpy(g->Message, "Failed making selector"); - return NULL; + return true; } // endif Selector tdbp->SetFilter(NULL); // Not needed anymore @@ -813,4 +813,3 @@ PSZ JMgoConn::GetColumnValue(PSZ path) return fld; } // end of GetColumnValue - diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index df9c7200416..dad86d51040 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -1,6 +1,6 @@ /****************** jsonudf C++ Program Source Code File (.CPP) ******************/ -/* PROGRAM NAME: jsonudf Version 1.7 */ -/* (C) Copyright to the author Olivier BERTRAND 2015-2018 */ +/* PROGRAM NAME: jsonudf Version 1.8 */ +/* (C) Copyright to the author Olivier BERTRAND 2015-2019 */ /* This program are the JSON User Defined Functions . */ /*********************************************************************************/ @@ -1686,7 +1686,7 @@ static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i) } // endif *s if (n < 1) - return "Key"; + return (PCSZ) "Key"; if (!b) { if ((p = (PSZ)PlgDBSubAlloc(g, NULL, n + 1))) { @@ -1703,7 +1703,7 @@ static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i) return s; } // endif count - return "Key"; + return (PCSZ) "Key"; } // end of MakeKey /*********************************************************************************/ diff --git a/storage/connect/libdoc.cpp b/storage/connect/libdoc.cpp index 9b30b315441..58b0267bd6d 100644 --- a/storage/connect/libdoc.cpp +++ b/storage/connect/libdoc.cpp @@ -1035,7 +1035,7 @@ PXNODE XML2NODE::AddChildNode(PGLOBAL g, PCSZ name, PXNODE np) // If name has the format m[n] only m is taken as node name if ((p = strchr(pn, '['))) - p = BufAlloc(g, pn, p - pn); + p = BufAlloc(g, pn, int(p - pn)); else p = pn; diff --git a/storage/connect/mini-global.h b/storage/connect/mini-global.h new file mode 100644 index 00000000000..f712795827c --- /dev/null +++ b/storage/connect/mini-global.h @@ -0,0 +1,33 @@ +/***********************************************************************/ +/* Definitions needed by the included files. */ +/***********************************************************************/ +#if !defined(MY_GLOBAL_H) +#define MY_GLOBAL_H +typedef unsigned int uint; +typedef unsigned int uint32; +typedef unsigned short ushort; +typedef unsigned long ulong; +typedef unsigned long DWORD; +typedef char *LPSTR; +typedef const char *LPCSTR; +typedef int BOOL; +#if defined(_WINDOWS) +typedef void *HANDLE; +#else +typedef int HANDLE; +#endif +typedef char *PSZ; +typedef const char *PCSZ; +typedef unsigned char BYTE; +typedef unsigned char uchar; +typedef long long longlong; +typedef unsigned long long ulonglong; +typedef char my_bool; +struct charset_info_st {}; +typedef const charset_info_st CHARSET_INFO; +#define FALSE 0 +#define TRUE 1 +#define Item char +#define MY_MAX(a,b) ((a>b)?(a):(b)) +#define MY_MIN(a,b) ((aGetName(), SVP(type)); +{ + PRELDEF tdp= NULL; - // If not specified get the type of this table - if (!type) - type= Hc->GetStringOption("Type","*"); + if (trace(1)) + htrc("GetTableDesc: name=%s am=%s\n", tablep->GetName(), SVP(type)); - return MakeTableDesc(g, tablep, type); - } // end of GetTableDesc + // If not specified get the type of this table + //if (!type) + // type= Hc->GetStringOption("Type","*"); + + tdp= MakeTableDesc(g, tablep, type); + + if (trace(1)) + htrc("GetTableDesc: tdp=%p\n", tdp); + + return tdp; +} // end of GetTableDesc /***********************************************************************/ /* MakeTableDesc: make a table/view description. */ @@ -501,18 +510,22 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep, PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am) { TABTYPE tc; - LPCSTR name = (PSZ)PlugDup(g, tablep->GetName()); - LPCSTR schema = (PSZ)PlugDup(g, tablep->GetSchema()); + LPCSTR name= (PSZ)PlugDup(g, tablep->GetName()); + LPCSTR schema= (PSZ)PlugDup(g, tablep->GetSchema()); PRELDEF tdp= NULL; - if (trace(1)) - printf("MakeTableDesc: name=%s schema=%s am=%s\n", - name, SVP(schema), SVP(am)); + if (trace(1)) + htrc("MakeTableDesc: name=%s schema=%s am=%s\n", + name, SVP(schema), SVP(am)); /*********************************************************************/ /* Get a unique enum identifier for types. */ /*********************************************************************/ - tc= GetTypeID(am); + if (!am) { + tc= Hc->GetRealType(); + am= Hc->GetStringOption("Type","*"); + } else + tc= GetTypeID(am); switch (tc) { case TAB_FIX: @@ -527,46 +540,52 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am) case TAB_XML: tdp= new(g) XMLDEF; break; #endif // XML_SUPPORT #if defined(VCT_SUPPORT) - case TAB_VEC: tdp = new(g) VCTDEF; break; + case TAB_VEC: tdp = new(g) VCTDEF; break; #endif // VCT_SUPPORT #if defined(ODBC_SUPPORT) case TAB_ODBC: tdp= new(g) ODBCDEF; break; #endif // ODBC_SUPPORT #if defined(JAVA_SUPPORT) - case TAB_JDBC: tdp= new(g) JDBCDEF; break; + case TAB_JDBC: tdp= new(g) JDBCDEF; break; #endif // JAVA_SUPPORT #if defined(__WIN__) case TAB_MAC: tdp= new(g) MACDEF; break; case TAB_WMI: tdp= new(g) WMIDEF; break; #endif // __WIN__ case TAB_OEM: tdp= new(g) OEMDEF; break; - case TAB_TBL: tdp= new(g) TBLDEF; break; - case TAB_XCL: tdp= new(g) XCLDEF; break; - case TAB_PRX: tdp= new(g) PRXDEF; break; - case TAB_OCCUR: tdp= new(g) OCCURDEF; break; - case TAB_MYSQL: tdp= new(g) MYSQLDEF; break; + case TAB_TBL: tdp= new(g) TBLDEF; break; + case TAB_XCL: tdp= new(g) XCLDEF; break; + case TAB_PRX: tdp= new(g) PRXDEF; break; + case TAB_OCCUR: tdp= new(g) OCCURDEF; break; + case TAB_MYSQL: tdp= new(g) MYSQLDEF; break; case TAB_PIVOT: tdp= new(g) PIVOTDEF; break; case TAB_VIR: tdp= new(g) VIRDEF; break; case TAB_JSON: tdp= new(g) JSONDEF; break; #if defined(ZIP_SUPPORT) - case TAB_ZIP: tdp = new(g) ZIPDEF; break; + case TAB_ZIP: tdp = new(g) ZIPDEF; break; #endif // ZIP_SUPPORT +#if defined(REST_SUPPORT) + case TAB_REST: tdp= new (g) RESTDEF; break; +#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 @@ -579,26 +598,29 @@ PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type) PTDB tdbp= NULL; // LPCSTR name= tablep->GetName(); - if (trace(1)) - printf("GetTableDB: name=%s\n", tablep->GetName()); + if (trace(1)) + htrc("GetTableDB: name=%s\n", tablep->GetName()); // Look for the description of the requested table tdp= GetTableDesc(g, tablep, type); if (tdp) { - if (trace(1)) - printf("tdb=%p type=%s\n", tdp, tdp->GetType()); + if (trace(1)) + htrc("tdb=%p type=%s\n", tdp, tdp->GetType()); + + if (tablep->GetSchema()) + tdp->Database = SetPath(g, tablep->GetSchema()); + + if (trace(2)) + htrc("Going to get table...\n"); - if (tablep->GetSchema()) - tdp->Database = SetPath(g, tablep->GetSchema()); - tdbp= tdp->GetTable(g, mode); - } // endif tdp + } // endif tdp if (tdbp) { - if (trace(1)) - printf("tdbp=%p name=%s amtype=%d\n", tdbp, tdbp->GetName(), - tdbp->GetAmType()); + if (trace(1)) + htrc("tdbp=%p name=%s amtype=%d\n", tdbp, tdbp->GetName(), + tdbp->GetAmType()); tablep->SetTo_Tdb(tdbp); tdbp->SetTable(tablep); tdbp->SetMode(mode); diff --git a/storage/connect/mycat.h b/storage/connect/mycat.h index f0f889722dd..818e535b32d 100644 --- a/storage/connect/mycat.h +++ b/storage/connect/mycat.h @@ -11,10 +11,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /**************** MYCAT H Declares Source Code File (.H) ***************/ -/* Name: MYCAT.H Version 2.3 */ +/* 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/osutil.h b/storage/connect/osutil.h index 7e6b8823b9b..380e7bebb22 100644 --- a/storage/connect/osutil.h +++ b/storage/connect/osutil.h @@ -3,7 +3,11 @@ #define __OSUTIL_H__ #if defined(UNIX) || defined(UNIV_LINUX) +#if defined(MARIADB) #include "my_global.h" +#else +#include "mini-global.h" +#endif #include #include #include "os.h" diff --git a/storage/connect/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: */ /* ----------------------- */ @@ -110,22 +110,32 @@ ACTIVITY defActivity = { /* Describes activity and language */ #include "rcmsg.h" #endif // UNIX +/**************************************************************************/ +/* Conditional tracing output function. */ +/**************************************************************************/ +void xtrc(uint x, char const *fmt, ...) +{ + if (GetTraceValue() & x) { + va_list ap; + va_start(ap, fmt); + + vfprintf(stderr, fmt, ap); + va_end(ap); + } // endif x + +} // end of xtrc + /**************************************************************************/ /* Tracing output function. */ /**************************************************************************/ -void htrc(char const *fmt, ...) - { - va_list ap; - va_start (ap, fmt); +void htrc(char const* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); - -//if (trace == 1) -// vfprintf(debug, fmt, ap); -//else - vfprintf(stderr, fmt, ap); - - va_end (ap); - } // end of htrc + vfprintf(stderr, fmt, ap); + va_end(ap); +} // end of htrc /***********************************************************************/ /* Plug initialization routine. */ diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 30d8063d1a6..8ba8aac3621 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -81,51 +81,51 @@ RELDEF::RELDEF(void) /* This function return a pointer to the Table Option Struct. */ /***********************************************************************/ PTOS RELDEF::GetTopt(void) - { - return Hc->GetTableOptionStruct(); - } // end of GetTopt + { + return Hc->GetTableOptionStruct(); + } // end of GetTopt /***********************************************************************/ /* This function sets an integer table information. */ /***********************************************************************/ bool RELDEF::SetIntCatInfo(PCSZ what, int n) - { - return Hc->SetIntegerOption(what, n); - } // end of SetIntCatInfo + { + return Hc->SetIntegerOption(what, n); + } // end of SetIntCatInfo /***********************************************************************/ /* This function returns integer table information. */ /***********************************************************************/ int RELDEF::GetIntCatInfo(PCSZ what, int idef) - { - int n= Hc->GetIntegerOption(what); + { + int n= Hc->GetIntegerOption(what); - return (n == NO_IVAL) ? idef : n; - } // end of GetIntCatInfo + return (n == NO_IVAL) ? idef : n; + } // end of GetIntCatInfo /***********************************************************************/ /* This function returns Boolean table information. */ /***********************************************************************/ bool RELDEF::GetBoolCatInfo(PCSZ what, bool bdef) - { - bool b= Hc->GetBooleanOption(what, bdef); + { + bool b= Hc->GetBooleanOption(what, bdef); - return b; - } // end of GetBoolCatInfo + return b; + } // end of GetBoolCatInfo /***********************************************************************/ /* This function returns size catalog information. */ /***********************************************************************/ int RELDEF::GetSizeCatInfo(PCSZ what, PCSZ sdef) - { - char c; - PCSZ s; + { + char c; + PCSZ s; int i, n= 0; - if (!(s= Hc->GetStringOption(what))) - s= sdef; + if (!(s= Hc->GetStringOption(what))) + s= sdef; - if ((i= sscanf(s, " %d %c ", &n, &c)) == 2) + if ((i= sscanf(s, " %d %c ", &n, &c)) == 2) switch (toupper(c)) { case 'M': n *= 1024; @@ -141,41 +141,41 @@ int RELDEF::GetSizeCatInfo(PCSZ what, PCSZ sdef) /* This function sets char table information in buf. */ /***********************************************************************/ int RELDEF::GetCharCatInfo(PCSZ what, PCSZ sdef, char *buf, int size) - { - PCSZ s= Hc->GetStringOption(what); + { + PCSZ s= Hc->GetStringOption(what); - strncpy(buf, ((s) ? s : sdef), size); - return size; - } // end of GetCharCatInfo + strncpy(buf, ((s) ? s : sdef), size); + return size; + } // end of GetCharCatInfo /***********************************************************************/ /* To be used by any TDB's. */ /***********************************************************************/ bool RELDEF::Partitioned(void) - { - return Hc->IsPartitioned(); - } // end of Partitioned + { + return Hc->IsPartitioned(); + } // end of Partitioned /***********************************************************************/ /* This function returns string table information. */ /* Default parameter is "*" to get the handler default. */ /***********************************************************************/ char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef) - { - char *sval = NULL; - PCSZ name, s= Hc->GetStringOption(what, sdef); - - if (s) { + { + char *sval = NULL; + PCSZ name, s= Hc->GetStringOption(what, sdef); + + if (s) { if (!Hc->IsPartitioned() || (stricmp(what, "filename") && stricmp(what, "tabname") && stricmp(what, "connect"))) - sval= PlugDup(g, s); + sval= PlugDup(g, s); else sval= (char*)s; } else if (!stricmp(what, "filename")) { // Return default file name - PCSZ ftype= Hc->GetStringOption("Type", "*"); + PCSZ ftype= Hc->GetStringOption("Type", "*"); int i, n; if (IsFileType(GetTypeID(ftype))) { @@ -183,7 +183,7 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef) sval= (char*)PlugSubAlloc(g, NULL, strlen(name) + 12); strcat(strcpy(sval, name), "."); n= strlen(sval); - + // Fold ftype to lower case for (i= 0; i < 12; i++) if (!ftype[i]) { @@ -196,8 +196,8 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef) } // endif s - return sval; - } // end of GetStringCatInfo + return sval; + } // end of GetStringCatInfo /* --------------------------- Class TABDEF -------------------------- */ @@ -223,14 +223,14 @@ TABDEF::TABDEF(void) /***********************************************************************/ /* Define: initialize the table definition block from XDB file. */ /***********************************************************************/ -bool TABDEF::Define(PGLOBAL g, PCATLG cat, - LPCSTR name, LPCSTR schema, LPCSTR am) +bool TABDEF::Define(PGLOBAL g, PCATLG cat, + LPCSTR name, LPCSTR schema, LPCSTR am) { int poff = 0; - Hc = ((MYCAT*)cat)->GetHandler(); - Name = (PSZ)name; - Schema = (PSZ)Hc->GetDBName(schema); + Hc = ((MYCAT*)cat)->GetHandler(); + Name = (PSZ)name; + Schema = (PSZ)Hc->GetDBName(schema); Cat = cat; Catfunc = GetFuncID(GetStringCatInfo(g, "Catfunc", NULL)); Elemt = GetIntCatInfo("Elements", 0); @@ -263,14 +263,14 @@ PCSZ TABDEF::GetPath(void) /* This function returns column table information. */ /***********************************************************************/ int TABDEF::GetColCatInfo(PGLOBAL g) - { - char *type= GetStringCatInfo(g, "Type", "*"); + { + char *type= GetStringCatInfo(g, "Type", "*"); char c, fty, eds; - int i, n, loff, poff, nof, nlg; - void *field= NULL; + int i, n, loff, poff, nof, nlg; + void *field= NULL; TABTYPE tc; PCOLDEF cdp, lcdp= NULL, tocols= NULL; - PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO)); + PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO)); memset(pcf, 0, sizeof(COLINFO)); @@ -278,33 +278,33 @@ int TABDEF::GetColCatInfo(PGLOBAL g) tc= (Catfunc == FNC_NO) ? GetTypeID(type) : TAB_PRX; // Take care of the column definitions - i= poff= nof= nlg= 0; + i= poff= nof= nlg= 0; #if defined(__WIN__) - // Offsets of HTML and DIR tables start from 0, DBF at 1 - loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0; + // Offsets of HTML and DIR tables start from 0, DBF at 1 + loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0; #else // !__WIN__ - // Offsets of HTML tables start from 0, DIR and DBF at 1 - loff = (tc == TAB_DBF || tc == TAB_DIR) ? 1 : (tc == TAB_XML) ? -1 : 0; + // Offsets of HTML tables start from 0, DIR and DBF at 1 + loff = (tc == TAB_DBF || tc == TAB_DIR) ? 1 : (tc == TAB_XML) ? -1 : 0; #endif // !__WIN__ while (true) { - // Default Offset depends on table type - switch (tc) { + // Default Offset depends on table type + switch (tc) { case TAB_DOS: case TAB_FIX: case TAB_BIN: case TAB_VEC: case TAB_DBF: - poff= loff + nof; // Default next offset - nlg= MY_MAX(nlg, poff); // Default lrecl + poff= loff + nof; // Default next offset + nlg= MY_MAX(nlg, poff); // Default lrecl break; case TAB_CSV: case TAB_FMT: - nlg+= nof; + nlg+= nof; case TAB_DIR: case TAB_XML: - poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1); + poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1); break; case TAB_INI: case TAB_MAC: @@ -316,39 +316,39 @@ int TABDEF::GetColCatInfo(PGLOBAL g) poff = 0; // Offset represents an independant flag break; default: // VCT PLG ODBC JDBC MYSQL WMI... - poff = 0; // NA + poff = 0; // NA break; - } // endswitch tc + } // endswitch tc -// do { - field= Hc->GetColumnOption(g, field, pcf); +// do { + field= Hc->GetColumnOption(g, field, pcf); // } while (field && (*pcf->Name =='*' /*|| pcf->Flags & U_VIRTUAL*/)); - if (tc == TAB_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) { - // DBF date format defaults to 'YYYMMDD' - pcf->Datefmt= "YYYYMMDD"; - pcf->Length= 8; - } // endif tc + if (tc == TAB_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) { + // DBF date format defaults to 'YYYMMDD' + pcf->Datefmt= "YYYYMMDD"; + pcf->Length= 8; + } // endif tc - if (!field) - break; + if (!field) + break; // Allocate the column description block cdp= new(g) COLDEF; if ((nof= cdp->Define(g, NULL, pcf, poff)) < 0) - return -1; // Error, probably unhandled type - else - loff= cdp->GetOffset(); + return -1; // Error, probably unhandled type + else + loff= cdp->GetOffset(); - switch (tc) { - case TAB_VEC: - cdp->SetOffset(0); // Not to have shift - case TAB_BIN: - // BIN/VEC are packed by default + switch (tc) { + case TAB_VEC: + cdp->SetOffset(0); // Not to have shift + case TAB_BIN: + // BIN/VEC are packed by default if (nof) { - // Field width is the internal representation width - // that can also depend on the column format + // Field width is the internal representation width + // that can also depend on the column format fty = cdp->Decode ? 'C' : 'X'; eds = 0; n = 0; @@ -371,38 +371,38 @@ int TABDEF::GetColCatInfo(PGLOBAL g) if (n) nof = n; else switch (fty) { - case 'X': + case 'X': if (eds && IsTypeChar(cdp->Buf_Type)) nof = sizeof(longlong); else nof= cdp->Clen; break; - case 'C': break; - case 'R': - case 'F': nof = sizeof(float); break; - case 'I': nof = sizeof(int); break; - case 'D': nof = sizeof(double); break; - case 'S': nof = sizeof(short); break; - case 'T': nof = sizeof(char); break; - case 'G': nof = sizeof(longlong); break; - default: /* Wrong format */ + case 'C': break; + case 'R': + case 'F': nof = sizeof(float); break; + case 'I': nof = sizeof(int); break; + case 'D': nof = sizeof(double); break; + case 'S': nof = sizeof(short); break; + case 'T': nof = sizeof(char); break; + case 'G': nof = sizeof(longlong); break; + default: /* Wrong format */ sprintf(g->Message, "Invalid format %c", fty); return -1; - } // endswitch fty + } // endswitch fty } // endif nof default: - break; - } // endswitch tc + break; + } // endswitch tc - if (lcdp) - lcdp->SetNext(cdp); - else - tocols= cdp; + if (lcdp) + lcdp->SetNext(cdp); + else + tocols= cdp; - lcdp= cdp; + lcdp= cdp; i++; } // endwhile @@ -410,31 +410,31 @@ int TABDEF::GetColCatInfo(PGLOBAL g) if (i != GetDegree()) SetDegree(i); - if (GetDefType() == TYPE_AM_DOS) { - int ending, recln= 0; + if (GetDefType() == TYPE_AM_DOS) { + int ending, recln= 0; - // Was commented because sometimes ending is 0 even when - // not specified (for instance if quoted is specified) -// if ((ending= Hc->GetIntegerOption("Ending")) < 0) { - if ((ending= Hc->GetIntegerOption("Ending")) <= 0) { + // Was commented because sometimes ending is 0 even when + // not specified (for instance if quoted is specified) +// if ((ending= Hc->GetIntegerOption("Ending")) < 0) { + if ((ending= Hc->GetIntegerOption("Ending")) <= 0) { ending= (tc == TAB_BIN || tc == TAB_VEC) ? 0 : CRLF; - Hc->SetIntegerOption("Ending", ending); - } // endif ending + Hc->SetIntegerOption("Ending", ending); + } // endif ending - // Calculate the default record size - switch (tc) { + // Calculate the default record size + switch (tc) { case TAB_FIX: case TAB_BIN: recln= nlg + ending; // + length of line ending break; case TAB_VEC: recln= nlg; - + // if ((k= (pak < 0) ? 8 : pak) > 1) // See above for detailed comment // Round up lrecl to multiple of 8 or pak // recln= ((recln + k - 1) / k) * k; - + break; case TAB_DOS: case TAB_DBF: @@ -443,26 +443,30 @@ int TABDEF::GetColCatInfo(PGLOBAL g) case TAB_CSV: case TAB_FMT: // The number of separators (assuming an extra one can exist) -// recln= poff * ((qotd) ? 3 : 1); to be investigated - recln= nlg + poff * 3; // To be safe +// recln= poff * ((qotd) ? 3 : 1); to be investigated + recln= nlg + poff * 3; // To be safe default: break; } // endswitch tc - // lrecl must be at least recln to avoid buffer overflow - if (trace(1)) - htrc("Lrecl: Calculated=%d defined=%d\n", - recln, Hc->GetIntegerOption("Lrecl")); + // lrecl must be at least recln to avoid buffer overflow + if (trace(1)) + htrc("Lrecl: Calculated=%d defined=%d\n", + recln, Hc->GetIntegerOption("Lrecl")); - recln = MY_MAX(recln, Hc->GetIntegerOption("Lrecl")); - Hc->SetIntegerOption("Lrecl", recln); - ((PDOSDEF)this)->SetLrecl(recln); - } // endif Lrecl + recln = MY_MAX(recln, Hc->GetIntegerOption("Lrecl")); + Hc->SetIntegerOption("Lrecl", recln); + ((PDOSDEF)this)->SetLrecl(recln); - // Attach the column definition to the tabdef - SetCols(tocols); - return poff; - } // end of GetColCatInfo + if (trace(1)) + htrc("Lrecl set to %d\n", recln); + + } // endif Lrecl + + // Attach the column definition to the tabdef + SetCols(tocols); + return poff; + } // end of GetColCatInfo /***********************************************************************/ /* SetIndexInfo: retrieve index description from the table structure. */ @@ -487,16 +491,17 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) PCATLG cat = Cat; /*********************************************************************/ - /* Ensure that the .dll doesn't have a path. */ - /* This is done to ensure that only approved dll from the system */ + /* Ensure that the module name doesn't have a path. */ + /* This is done to ensure that only approved libs from the system */ /* directories are used (to make this even remotely secure). */ /*********************************************************************/ if (check_valid_path(Module, strlen(Module))) { strcpy(g->Message, "Module cannot contain a path"); return NULL; } else - PlugSetPath(soname, Module, GetPluginDir()); - +// PlugSetPath(soname, Module, GetPluginDir()); // Crashes on Fedora + strncat(strcpy(soname, GetPluginDir()), Module, _MAX_PATH); + #if defined(__WIN__) // Is the DLL already loaded? if (!Hdll && !(Hdll = GetModuleHandle(soname))) @@ -522,31 +527,31 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) // Get the function returning an instance of the external DEF class if (!(getdef = (XGETDEF)GetProcAddress((HINSTANCE)Hdll, getname))) { - char buf[256]; - DWORD rc = GetLastError(); + char buf[256]; + DWORD rc = GetLastError(); - sprintf(g->Message, MSG(PROCADD_ERROR), rc, getname); - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, - (LPTSTR)buf, sizeof(buf), NULL); - strcat(strcat(g->Message, ": "), buf); - FreeLibrary((HMODULE)Hdll); + sprintf(g->Message, MSG(PROCADD_ERROR), rc, getname); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, + (LPTSTR)buf, sizeof(buf), NULL); + strcat(strcat(g->Message, ": "), buf); + FreeLibrary((HMODULE)Hdll); return NULL; } // endif getdef #else // !__WIN__ const char *error = NULL; - -#if 0 // Don't know what all this stuff does - Dl_info dl_info; - // The OEM lib must retrieve exported CONNECT variables +#if 0 // Don't know what all this stuff does + Dl_info dl_info; + + // The OEM lib must retrieve exported CONNECT variables if (dladdr(&connect_hton, &dl_info)) { if (dlopen(dl_info.dli_fname, RTLD_NOLOAD | RTLD_NOW | RTLD_GLOBAL) == 0) { error = dlerror(); sprintf(g->Message, "dlopen failed: %s, OEM not supported", SVP(error)); return NULL; } // endif dlopen - + } else { error = dlerror(); sprintf(g->Message, "dladdr failed: %s, OEM not supported", SVP(error)); @@ -626,7 +631,7 @@ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int) char *desc = (char*)PlugSubAlloc(g, NULL, strlen(Module) + strlen(Subtype) + 3); sprintf(desc, "%s(%s)", Module, Subtype); - Desc = desc; + Desc = desc; return false; } // end of DefineAM @@ -701,17 +706,17 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode) txfp = new(g) FIXFAM(defp); } else if (rfm == RECFM_VCT) { #if defined(VCT_SUPPORT) - assert(Pxdef->GetDefType() == TYPE_AM_VCT); + assert(Pxdef->GetDefType() == TYPE_AM_VCT); if (map) txfp = new(g) VCMFAM((PVCTDEF)defp); else txfp = new(g) VCTFAM((PVCTDEF)defp); #else // !VCT_SUPPORT - strcpy(g->Message, "VCT no more supported"); - return NULL; + strcpy(g->Message, "VCT no more supported"); + return NULL; #endif // !VCT_SUPPORT - } // endif's + } // endif's ((PTDBDOS)tdbp)->SetTxfp(txfp); } // endif Txfp diff --git a/storage/connect/rest.def b/storage/connect/rest.def new file mode 100644 index 00000000000..71c76740af9 --- /dev/null +++ b/storage/connect/rest.def @@ -0,0 +1,4 @@ +LIBRARY REST2 +EXPORTS + GetREST @1 + ColREST @2 diff --git a/storage/connect/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 +#include +#if defined(MARIADB) +#include +#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(); + + 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 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 02720a3089a..746382178fb 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -189,9 +189,11 @@ PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info) htrc("File %s Sep=%c Qot=%c Header=%d maxerr=%d\n", SVP(tdp->Fn), tdp->Sep, tdp->Qot, tdp->Header, tdp->Maxerr); +#if defined(ZIP_SUPPORT) if (tdp->Zipped) tcvp = new(g)TDBCSV(tdp, new(g)UNZFAM(tdp)); else +#endif // ZIP_SUPPORT tcvp = new(g) TDBCSV(tdp, new(g) DOSFAM(tdp)); tcvp->SetMode(MODE_READ); diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index c6b2802c1f6..06b6b3a9730 100644 --- a/storage/connect/tabjdbc.cpp +++ b/storage/connect/tabjdbc.cpp @@ -72,7 +72,6 @@ #include "tabext.h" #include "tabjdbc.h" #include "tabmul.h" -//#include "reldef.h" #include "tabcol.h" #include "valblk.h" #include "ha_connect.h" @@ -89,6 +88,9 @@ extern int num_read, num_there, num_eq[2]; // Statistics /* External function. */ /***********************************************************************/ bool ExactInfo(void); +#if defined(DEVELOPMENT) +extern char *GetUserVariable(PGLOBAL g, const uchar *varname); +#endif // DEVELOPMENT /* -------------------------- Class JDBCDEF -------------------------- */ @@ -147,10 +149,6 @@ int JDBCDEF::ParseURL(PGLOBAL g, char *url, bool b) return RC_FX; Tabname = p; -// } else if (b) { -// // Otherwise, straight server name, -// Tabname = GetStringCatInfo(g, "Name", NULL); -// Tabname = GetStringCatInfo(g, "Tabname", Tabname); } // endif if (trace(1)) @@ -165,6 +163,11 @@ int JDBCDEF::ParseURL(PGLOBAL g, char *url, bool b) return RC_FX; } // endif server +#if defined(DEVELOPMENT) + if (*server->host == '@') { + Url = GetUserVariable(g, (const uchar*)&server->host[1]); + } else +#endif // 0 if (strncmp(server->host, "jdbc:", 5)) { // Now make the required URL Url = (PSZ)PlugSubAlloc(g, NULL, 0); @@ -191,6 +194,9 @@ int JDBCDEF::ParseURL(PGLOBAL g, char *url, bool b) if (!Password && server->password) Password = PlugDup(g, server->password); + Driver = PlugDup(g, GetListOption(g, "Driver", server->owner, NULL)); + Wrapname = PlugDup(g, GetListOption(g, "Wrapper", server->owner, NULL)); + Memory = atoi(GetListOption(g, "Memory", server->owner, "0")); return RC_NF; } // endif @@ -208,7 +214,6 @@ bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) if (EXTDEF::DefineAM(g, am, poff)) return true; - Driver = GetStringCatInfo(g, "Driver", NULL); Desc = Url = GetStringCatInfo(g, "Connect", NULL); if (!Url && !Catfunc) { @@ -228,7 +233,10 @@ bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) return true; } // endif rc - Wrapname = GetStringCatInfo(g, "Wrapper", NULL); + // Default values may have been set in ParseURL + Memory = GetIntCatInfo("Memory", Memory); + Driver = GetStringCatInfo(g, "Driver", Driver); + Wrapname = GetStringCatInfo(g, "Wrapper", Wrapname); return false; } // end of DefineAM @@ -633,7 +641,9 @@ bool TDBJDBC::OpenDB(PGLOBAL g) Cnp->InitValue(g); if ((n = Jcp->GetResultSize(Query->GetStr(), Cnp)) < 0) { - sprintf(g->Message, "Cannot get result size rc=%d", n); + char* msg = PlugDup(g, g->Message); + + sprintf(g->Message, "Get result size: %s (rc=%d)", msg, n); return true; } else if (n) { Jcp->m_Rows = n; diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index afab52aa282..0b282345c8a 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -71,15 +71,15 @@ char *GetJsonNull(void); /***********************************************************************/ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) { - static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, + static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING}; - static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, + static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT}; static unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0}; - int i, n = 0; + int i, n = 0; int ncol = sizeof(buftyp) / sizeof(int); - PJCL jcp; - JSONDISC *pjdc = NULL; + PJCL jcp; + JSONDISC *pjdc = NULL; PQRYRES qrp; PCOLRES crp; @@ -89,15 +89,15 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) goto skipit; } // endif info - if (GetIntegerTableOption(g, topt, "Multiple", 0)) { - strcpy(g->Message, "Cannot find column definition for multiple table"); - return NULL; - } // endif Multiple + if (GetIntegerTableOption(g, topt, "Multiple", 0)) { + strcpy(g->Message, "Cannot find column definition for multiple table"); + return NULL; + } // endif Multiple - pjdc = new(g) JSONDISC(g, length); + pjdc = new(g) JSONDISC(g, length); - if (!(n = pjdc->GetColumns(g, db, dsn, topt))) - return NULL; + if (!(n = pjdc->GetColumns(g, db, dsn, topt))) + return NULL; skipit: if (trace(1)) @@ -110,8 +110,8 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) buftyp, fldtyp, length, false, false); crp = qrp->Colresp->Next->Next->Next->Next->Next->Next; - crp->Name = PlugDup(g, "Nullable"); - crp->Next->Name = PlugDup(g, "Jpath"); + crp->Name = PlugDup(g, "Nullable"); + crp->Next->Name = PlugDup(g, "Jpath"); if (info || !qrp) return qrp; @@ -122,8 +122,8 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) /* Now get the results into blocks. */ /*********************************************************************/ for (i = 0, jcp = pjdc->fjcp; jcp; i++, jcp = jcp->Next) { - if (jcp->Type == TYPE_UNKNOWN) - jcp->Type = TYPE_STRING; // Void column + if (jcp->Type == TYPE_UNKNOWN) + jcp->Type = TYPE_STRING; // Void column crp = qrp->Colresp; // Column Name crp->Kdata->SetValue(jcp->Name, i); @@ -159,380 +159,380 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) /***********************************************************************/ JSONDISC::JSONDISC(PGLOBAL g, uint *lg) { - length = lg; - jcp = fjcp = pjcp = NULL; - tjnp = NULL; - jpp = NULL; - tjsp = NULL; - jsp = NULL; - row = NULL; - sep = NULL; - i = n = bf = ncol = lvl = 0; - all = false; -} // end of JSONDISC constructor + length = lg; + jcp = fjcp = pjcp = NULL; + tjnp = NULL; + jpp = NULL; + tjsp = NULL; + jsp = NULL; + row = NULL; + sep = NULL; + i = n = bf = ncol = lvl = 0; + all = false; +} // end of JSONDISC constructor int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) { - char filename[_MAX_PATH]; - bool mgo = (GetTypeID(topt->type) == TAB_MONGO); - PCSZ level = GetStringTableOption(g, topt, "Level", NULL); + char filename[_MAX_PATH]; + bool mgo = (GetTypeID(topt->type) == TAB_MONGO); + PCSZ level = GetStringTableOption(g, topt, "Level", NULL); - if (level) { - lvl = atoi(level); - lvl = (lvl > 16) ? 16 : lvl; - } else - lvl = 0; + if (level) { + lvl = atoi(level); + lvl = (lvl > 16) ? 16 : lvl; + } else + lvl = 0; - sep = GetStringTableOption(g, topt, "Separator", "."); + sep = GetStringTableOption(g, topt, "Separator", "."); - /*********************************************************************/ - /* Open the input file. */ - /*********************************************************************/ - tdp = new(g) JSONDEF; + /*********************************************************************/ + /* Open the input file. */ + /*********************************************************************/ + tdp = new(g) JSONDEF; #if defined(ZIP_SUPPORT) - tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL); - tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false); + tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL); + tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false); #endif // ZIP_SUPPORT - tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL); + tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL); - if (!(tdp->Database = SetPath(g, db))) - return 0; + if (!(tdp->Database = SetPath(g, db))) + return 0; - tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); - tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; - tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2); - tdp->Xcol = GetStringTableOption(g, topt, "Expand", NULL); - tdp->Accept = GetBooleanTableOption(g, topt, "Accept", false); - tdp->Uri = (dsn && *dsn ? dsn : NULL); + tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); + tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; + tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2); + tdp->Xcol = GetStringTableOption(g, topt, "Expand", NULL); + tdp->Accept = GetBooleanTableOption(g, topt, "Accept", false); + tdp->Uri = (dsn && *dsn ? dsn : NULL); - if (!tdp->Fn && !tdp->Uri) { - strcpy(g->Message, MSG(MISSING_FNAME)); - return 0; - } // endif Fn + if (!tdp->Fn && !tdp->Uri) { + strcpy(g->Message, MSG(MISSING_FNAME)); + return 0; + } // endif Fn - if (tdp->Fn) { - // We used the file name relative to recorded datapath - PlugSetPath(filename, tdp->Fn, tdp->GetPath()); - tdp->Fn = PlugDup(g, filename); - } // endif Fn + if (tdp->Fn) { + // We used the file name relative to recorded datapath + PlugSetPath(filename, tdp->Fn, tdp->GetPath()); + tdp->Fn = PlugDup(g, filename); + } // endif Fn - if (trace(1)) - htrc("File %s objname=%s pretty=%d lvl=%d\n", - tdp->Fn, tdp->Objname, tdp->Pretty, lvl); + if (trace(1)) + htrc("File %s objname=%s pretty=%d lvl=%d\n", + tdp->Fn, tdp->Objname, tdp->Pretty, lvl); - if (tdp->Uri) { + if (tdp->Uri) { #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) - tdp->Collname = GetStringTableOption(g, topt, "Name", NULL); - tdp->Collname = GetStringTableOption(g, topt, "Tabname", tdp->Collname); - tdp->Schema = GetStringTableOption(g, topt, "Dbname", "test"); - tdp->Options = (PSZ)GetStringTableOption(g, topt, "Colist", "all"); - tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false); - tdp->Driver = (PSZ)GetStringTableOption(g, topt, "Driver", NULL); - tdp->Version = GetIntegerTableOption(g, topt, "Version", 3); - tdp->Wrapname = (PSZ)GetStringTableOption(g, topt, "Wrapper", - (tdp->Version == 2) ? "Mongo2Interface" : "Mongo3Interface"); - tdp->Pretty = 0; + tdp->Collname = GetStringTableOption(g, topt, "Name", NULL); + tdp->Collname = GetStringTableOption(g, topt, "Tabname", tdp->Collname); + tdp->Schema = GetStringTableOption(g, topt, "Dbname", "test"); + tdp->Options = (PSZ)GetStringTableOption(g, topt, "Colist", "all"); + tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false); + tdp->Driver = (PSZ)GetStringTableOption(g, topt, "Driver", NULL); + tdp->Version = GetIntegerTableOption(g, topt, "Version", 3); + tdp->Wrapname = (PSZ)GetStringTableOption(g, topt, "Wrapper", + (tdp->Version == 2) ? "Mongo2Interface" : "Mongo3Interface"); + tdp->Pretty = 0; #else // !MONGO_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); - return 0; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); + return 0; #endif // !MONGO_SUPPORT - } // endif Uri + } // endif Uri - if (tdp->Pretty == 2) { - if (tdp->Zipped) { + if (tdp->Pretty == 2) { + if (tdp->Zipped) { #if defined(ZIP_SUPPORT) - tjsp = new(g) TDBJSON(tdp, new(g) UNZFAM(tdp)); + tjsp = new(g) TDBJSON(tdp, new(g) UNZFAM(tdp)); #else // !ZIP_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); - return 0; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); + return 0; #endif // !ZIP_SUPPORT - } else - tjsp = new(g) TDBJSON(tdp, new(g) MAPFAM(tdp)); + } else + tjsp = new(g) TDBJSON(tdp, new(g) MAPFAM(tdp)); - if (tjsp->MakeDocument(g)) - return 0; + if (tjsp->MakeDocument(g)) + return 0; - jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetValue(0) : NULL; - } else { - if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0))) - if (!mgo) { - sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty); - return 0; - } else - tdp->Lrecl = 8192; // Should be enough + jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetValue(0) : NULL; + } else { + if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0))) + if (!mgo) { + sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty); + return 0; + } else + tdp->Lrecl = 8192; // Should be enough - tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF); + tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF); - if (tdp->Zipped) { + if (tdp->Zipped) { #if defined(ZIP_SUPPORT) - tjnp = new(g)TDBJSN(tdp, new(g) UNZFAM(tdp)); + tjnp = new(g)TDBJSN(tdp, new(g) UNZFAM(tdp)); #else // !ZIP_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); - return NULL; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); + return NULL; #endif // !ZIP_SUPPORT - } else if (tdp->Uri) { - if (tdp->Driver && toupper(*tdp->Driver) == 'C') { + } else if (tdp->Uri) { + if (tdp->Driver && toupper(*tdp->Driver) == 'C') { #if defined(CMGO_SUPPORT) - tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp)); + tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp)); #else - sprintf(g->Message, "Mongo %s Driver not available", "C"); - return 0; + sprintf(g->Message, "Mongo %s Driver not available", "C"); + return 0; #endif - } else if (tdp->Driver && toupper(*tdp->Driver) == 'J') { + } else if (tdp->Driver && toupper(*tdp->Driver) == 'J') { #if defined(JAVA_SUPPORT) - tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp)); + tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp)); #else - sprintf(g->Message, "Mongo %s Driver not available", "Java"); - return 0; + sprintf(g->Message, "Mongo %s Driver not available", "Java"); + return 0; #endif - } else { // Driver not specified + } else { // Driver not specified #if defined(CMGO_SUPPORT) - tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp)); + tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp)); #elif defined(JAVA_SUPPORT) - tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp)); + tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp)); #else - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); - return 0; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); + return 0; #endif - } // endif Driver + } // endif Driver - } else - tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp)); + } else + tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp)); - tjnp->SetMode(MODE_READ); + tjnp->SetMode(MODE_READ); - // Allocate the parse work memory - PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); - memset(G, 0, sizeof(GLOBAL)); - G->Sarea_Size = tdp->Lrecl * 10; - G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size); - PlugSubSet(G->Sarea, G->Sarea_Size); - G->jump_level = 0; - tjnp->SetG(G); + // Allocate the parse work memory + PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); + memset(G, 0, sizeof(GLOBAL)); + G->Sarea_Size = tdp->Lrecl * 10; + G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size); + PlugSubSet(G->Sarea, G->Sarea_Size); + G->jump_level = 0; + tjnp->SetG(G); - if (tjnp->OpenDB(g)) - return 0; + if (tjnp->OpenDB(g)) + return 0; - switch (tjnp->ReadDB(g)) { - case RC_EF: - strcpy(g->Message, "Void json table"); - case RC_FX: - goto err; - default: - jsp = tjnp->GetRow(); - } // endswitch ReadDB + switch (tjnp->ReadDB(g)) { + case RC_EF: + strcpy(g->Message, "Void json table"); + case RC_FX: + goto err; + default: + jsp = tjnp->GetRow(); + } // endswitch ReadDB - } // endif pretty + } // endif pretty - if (!(row = (jsp) ? jsp->GetObject() : NULL)) { - strcpy(g->Message, "Can only retrieve columns from object rows"); - goto err; - } // endif row + if (!(row = (jsp) ? jsp->GetObject() : NULL)) { + strcpy(g->Message, "Can only retrieve columns from object rows"); + goto err; + } // endif row - all = GetBooleanTableOption(g, topt, "Fullarray", false); - jcol.Name = jcol.Fmt = NULL; - jcol.Next = NULL; - jcol.Found = true; - colname[0] = 0; + all = GetBooleanTableOption(g, topt, "Fullarray", false); + jcol.Name = jcol.Fmt = NULL; + jcol.Next = NULL; + jcol.Found = true; + colname[0] = 0; - if (!tdp->Uri) { - fmt[0] = '$'; - fmt[1] = '.'; - bf = 2; - } // endif Uri + if (!tdp->Uri) { + fmt[0] = '$'; + fmt[1] = '.'; + bf = 2; + } // endif Uri - /*********************************************************************/ - /* Analyse the JSON tree and define columns. */ - /*********************************************************************/ - for (i = 1; ; i++) { - for (jpp = row->GetFirst(); jpp; jpp = jpp->GetNext()) { - strncpy(colname, jpp->GetKey(), 64); - fmt[bf] = 0; + /*********************************************************************/ + /* Analyse the JSON tree and define columns. */ + /*********************************************************************/ + for (i = 1; ; i++) { + for (jpp = row->GetFirst(); jpp; jpp = jpp->GetNext()) { + strncpy(colname, jpp->GetKey(), 64); + fmt[bf] = 0; - if (Find(g, jpp->GetVal(), colname, MY_MIN(lvl, 0))) - goto err; + if (Find(g, jpp->GetVal(), colname, MY_MIN(lvl, 0))) + goto err; - } // endfor jpp + } // endfor jpp - // Missing column can be null - for (jcp = fjcp; jcp; jcp = jcp->Next) { - jcp->Cbn |= !jcp->Found; - jcp->Found = false; - } // endfor jcp + // Missing column can be null + for (jcp = fjcp; jcp; jcp = jcp->Next) { + jcp->Cbn |= !jcp->Found; + jcp->Found = false; + } // endfor jcp - if (tdp->Pretty != 2) { - // Read next record - switch (tjnp->ReadDB(g)) { - case RC_EF: - jsp = NULL; - break; - case RC_FX: - goto err; - default: - jsp = tjnp->GetRow(); - } // endswitch ReadDB + if (tdp->Pretty != 2) { + // Read next record + switch (tjnp->ReadDB(g)) { + case RC_EF: + jsp = NULL; + break; + case RC_FX: + goto err; + default: + jsp = tjnp->GetRow(); + } // endswitch ReadDB - } else - jsp = tjsp->GetDoc()->GetValue(i); + } else + jsp = tjsp->GetDoc()->GetValue(i); - if (!(row = (jsp) ? jsp->GetObject() : NULL)) - break; + if (!(row = (jsp) ? jsp->GetObject() : NULL)) + break; - } // endfor i + } // endfor i - if (tdp->Pretty != 2) - tjnp->CloseDB(g); + if (tdp->Pretty != 2) + tjnp->CloseDB(g); - return n; + return n; err: - if (tdp->Pretty != 2) - tjnp->CloseDB(g); + if (tdp->Pretty != 2) + tjnp->CloseDB(g); - return 0; -} // end of GetColumns + return 0; +} // end of GetColumns bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j) { - char *p, *pc = colname + strlen(colname); - int ars; - PJOB job; - PJAR jar; + char *p, *pc = colname + strlen(colname); + int ars; + PJOB job; + PJAR jar; - if ((valp = jvp ? jvp->GetValue() : NULL)) { - jcol.Type = valp->GetType(); - jcol.Len = valp->GetValLen(); - jcol.Scale = valp->GetValPrec(); - jcol.Cbn = valp->IsNull(); - } else if (!jvp || jvp->IsNull()) { - jcol.Type = TYPE_UNKNOWN; - jcol.Len = jcol.Scale = 0; - jcol.Cbn = true; - } else if (j < lvl) { - if (!fmt[bf]) - strcat(fmt, colname); + if ((valp = jvp ? jvp->GetValue() : NULL)) { + jcol.Type = valp->GetType(); + jcol.Len = valp->GetValLen(); + jcol.Scale = valp->GetValPrec(); + jcol.Cbn = valp->IsNull(); + } else if (!jvp || jvp->IsNull()) { + jcol.Type = TYPE_UNKNOWN; + jcol.Len = jcol.Scale = 0; + jcol.Cbn = true; + } else if (j < lvl) { + if (!fmt[bf]) + strcat(fmt, colname); - p = fmt + strlen(fmt); - jsp = jvp->GetJson(); + p = fmt + strlen(fmt); + jsp = jvp->GetJson(); - switch (jsp->GetType()) { - case TYPE_JOB: - job = (PJOB)jsp; + switch (jsp->GetType()) { + case TYPE_JOB: + job = (PJOB)jsp; - for (PJPR jrp = job->GetFirst(); jrp; jrp = jrp->GetNext()) { - PCSZ k = jrp->GetKey(); + for (PJPR jrp = job->GetFirst(); jrp; jrp = jrp->GetNext()) { + PCSZ k = jrp->GetKey(); - if (*k != '$') { - strncat(strncat(fmt, sep, 128), k, 128); - strncat(strncat(colname, "_", 64), k, 64); - } // endif Key + if (*k != '$') { + strncat(strncat(fmt, sep, 128), k, 128); + strncat(strncat(colname, "_", 64), k, 64); + } // endif Key - if (Find(g, jrp->GetVal(), k, j + 1)) - return true; + if (Find(g, jrp->GetVal(), k, j + 1)) + return true; - *p = *pc = 0; - } // endfor jrp + *p = *pc = 0; + } // endfor jrp - return false; - case TYPE_JAR: - jar = (PJAR)jsp; + return false; + case TYPE_JAR: + jar = (PJAR)jsp; - if (all || (tdp->Xcol && !stricmp(tdp->Xcol, key))) - ars = jar->GetSize(false); - else - ars = MY_MIN(jar->GetSize(false), 1); + if (all || (tdp->Xcol && !stricmp(tdp->Xcol, key))) + ars = jar->GetSize(false); + else + ars = MY_MIN(jar->GetSize(false), 1); - for (int k = 0; k < ars; k++) { - if (!tdp->Xcol || stricmp(tdp->Xcol, key)) { - sprintf(buf, "%d", k); + for (int k = 0; k < ars; k++) { + if (!tdp->Xcol || stricmp(tdp->Xcol, key)) { + sprintf(buf, "%d", k); - if (tdp->Uri) - strncat(strncat(fmt, sep, 128), buf, 128); - else - strncat(strncat(strncat(fmt, "[", 128), buf, 128), "]", 128); + if (tdp->Uri) + strncat(strncat(fmt, sep, 128), buf, 128); + else + strncat(strncat(strncat(fmt, "[", 128), buf, 128), "]", 128); - if (all) - strncat(strncat(colname, "_", 64), buf, 64); + if (all) + strncat(strncat(colname, "_", 64), buf, 64); - } else - strncat(fmt, (tdp->Uri ? sep : "[*]"), 128); + } else + strncat(fmt, (tdp->Uri ? sep : "[*]"), 128); - if (Find(g, jar->GetValue(k), "", j)) - return true; + if (Find(g, jar->GetValue(k), "", j)) + return true; - *p = *pc = 0; - } // endfor k + *p = *pc = 0; + } // endfor k - return false; - default: - sprintf(g->Message, "Logical error after %s", fmt); - return true; - } // endswitch Type + return false; + default: + sprintf(g->Message, "Logical error after %s", fmt); + return true; + } // endswitch Type - } else if (lvl >= 0) { - jcol.Type = TYPE_STRING; - jcol.Len = 256; - jcol.Scale = 0; - jcol.Cbn = true; - } else - return false; + } else if (lvl >= 0) { + jcol.Type = TYPE_STRING; + jcol.Len = 256; + jcol.Scale = 0; + jcol.Cbn = true; + } else + return false; - AddColumn(g); - return false; -} // end of Find + AddColumn(g); + return false; +} // end of Find void JSONDISC::AddColumn(PGLOBAL g) { - bool b = fmt[bf] != 0; // True if formatted + bool b = fmt[bf] != 0; // True if formatted - // Check whether this column was already found - for (jcp = fjcp; jcp; jcp = jcp->Next) - if (!strcmp(colname, jcp->Name)) - break; + // Check whether this column was already found + for (jcp = fjcp; jcp; jcp = jcp->Next) + if (!strcmp(colname, jcp->Name)) + break; - if (jcp) { - if (jcp->Type != jcol.Type) { - if (jcp->Type == TYPE_UNKNOWN) - jcp->Type = jcol.Type; - else if (jcol.Type != TYPE_UNKNOWN) - jcp->Type = TYPE_STRING; + if (jcp) { + if (jcp->Type != jcol.Type) { + if (jcp->Type == TYPE_UNKNOWN) + jcp->Type = jcol.Type; + else if (jcol.Type != TYPE_UNKNOWN) + jcp->Type = TYPE_STRING; - } // endif Type + } // endif Type - if (b && (!jcp->Fmt || strlen(jcp->Fmt) < strlen(fmt))) { - jcp->Fmt = PlugDup(g, fmt); - length[7] = MY_MAX(length[7], strlen(fmt)); - } // endif fmt + if (b && (!jcp->Fmt || strlen(jcp->Fmt) < strlen(fmt))) { + jcp->Fmt = PlugDup(g, fmt); + length[7] = MY_MAX(length[7], strlen(fmt)); + } // endif fmt - jcp->Len = MY_MAX(jcp->Len, jcol.Len); - jcp->Scale = MY_MAX(jcp->Scale, jcol.Scale); - jcp->Cbn |= jcol.Cbn; - jcp->Found = true; - } else if (jcol.Type != TYPE_UNKNOWN || tdp->Accept) { - // New column - jcp = (PJCL)PlugSubAlloc(g, NULL, sizeof(JCOL)); - *jcp = jcol; - jcp->Cbn |= (i > 1); - jcp->Name = PlugDup(g, colname); - length[0] = MY_MAX(length[0], strlen(colname)); + jcp->Len = MY_MAX(jcp->Len, jcol.Len); + jcp->Scale = MY_MAX(jcp->Scale, jcol.Scale); + jcp->Cbn |= jcol.Cbn; + jcp->Found = true; + } else if (jcol.Type != TYPE_UNKNOWN || tdp->Accept) { + // New column + jcp = (PJCL)PlugSubAlloc(g, NULL, sizeof(JCOL)); + *jcp = jcol; + jcp->Cbn |= (i > 1); + jcp->Name = PlugDup(g, colname); + length[0] = MY_MAX(length[0], strlen(colname)); - if (b) { - jcp->Fmt = PlugDup(g, fmt); - length[7] = MY_MAX(length[7], strlen(fmt)); - } else - jcp->Fmt = NULL; + if (b) { + jcp->Fmt = PlugDup(g, fmt); + length[7] = MY_MAX(length[7], strlen(fmt)); + } else + jcp->Fmt = NULL; - if (pjcp) { - jcp->Next = pjcp->Next; - pjcp->Next = jcp; - } else - fjcp = jcp; + if (pjcp) { + jcp->Next = pjcp->Next; + pjcp->Next = jcp; + } else + fjcp = jcp; - n++; - } // endif jcp + n++; + } // endif jcp - if (jcp) - pjcp = jcp; + if (jcp) + pjcp = jcp; } // end of AddColumn @@ -548,13 +548,13 @@ JSONDEF::JSONDEF(void) Limit = 1; Base = 0; Strict = false; - Sep = '.'; - Uri = NULL; - Collname = Options = Filter = NULL; - Pipe = false; - Driver = NULL; - Version = 0; - Wrapname = NULL; + Sep = '.'; + Uri = NULL; + Collname = Options = Filter = NULL; + Pipe = false; + Driver = NULL; + Version = 0; + Wrapname = NULL; } // end of JSONDEF constructor /***********************************************************************/ @@ -562,41 +562,41 @@ JSONDEF::JSONDEF(void) /***********************************************************************/ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { - Schema = GetStringCatInfo(g, "DBname", Schema); - Jmode = (JMODE)GetIntCatInfo("Jmode", MODE_OBJECT); + Schema = GetStringCatInfo(g, "DBname", Schema); + Jmode = (JMODE)GetIntCatInfo("Jmode", MODE_OBJECT); Objname = GetStringCatInfo(g, "Object", NULL); Xcol = GetStringCatInfo(g, "Expand", NULL); Pretty = GetIntCatInfo("Pretty", 2); Limit = GetIntCatInfo("Limit", 10); Base = GetIntCatInfo("Base", 0) ? 1 : 0; - Sep = *GetStringCatInfo(g, "Separator", "."); - Accept = GetBoolCatInfo("Accept", false); + Sep = *GetStringCatInfo(g, "Separator", "."); + Accept = GetBoolCatInfo("Accept", false); - // Don't use url as 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 /***********************************************************************/ @@ -604,6 +604,9 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) /***********************************************************************/ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) { + if (trace(1)) + htrc("JSON GetTable Pretty=%d Uri=%s\n", Pretty, SVP(Uri)); + if (Catfunc == FNC_COL) return new(g)TDBJCL(this); @@ -618,47 +621,47 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) !(tmp == TMP_FORCE && (m == MODE_UPDATE || m == MODE_DELETE)); - if (Uri) { - if (Driver && toupper(*Driver) == 'C') { + if (Uri) { + if (Driver && toupper(*Driver) == 'C') { #if defined(CMGO_SUPPORT) - txfp = new(g) CMGFAM(this); + txfp = new(g) CMGFAM(this); #else - sprintf(g->Message, "Mongo %s Driver not available", "C"); - return NULL; + sprintf(g->Message, "Mongo %s Driver not available", "C"); + return NULL; #endif - } else if (Driver && toupper(*Driver) == 'J') { + } else if (Driver && toupper(*Driver) == 'J') { #if defined(JAVA_SUPPORT) - txfp = new(g) JMGFAM(this); + txfp = new(g) JMGFAM(this); #else - sprintf(g->Message, "Mongo %s Driver not available", "Java"); - return NULL; + sprintf(g->Message, "Mongo %s Driver not available", "Java"); + return NULL; #endif - } else { // Driver not specified + } else { // Driver not specified #if defined(CMGO_SUPPORT) - txfp = new(g) CMGFAM(this); + txfp = new(g) CMGFAM(this); #elif defined(JAVA_SUPPORT) - txfp = new(g) JMGFAM(this); -#else // !MONGO_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); - return NULL; + txfp = new(g) JMGFAM(this); +#else // !MONGO_SUPPORT + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO"); + return NULL; #endif // !MONGO_SUPPORT - } // endif Driver + } // endif Driver - } else if (Zipped) { + } else if (Zipped) { #if defined(ZIP_SUPPORT) - if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { - txfp = new(g) UNZFAM(this); - } else if (m == MODE_INSERT) { - txfp = new(g) ZIPFAM(this); - } else { - strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); - return NULL; - } // endif's m + if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { + txfp = new(g) UNZFAM(this); + } else if (m == MODE_INSERT) { + txfp = new(g) ZIPFAM(this); + } else { + strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); + return NULL; + } // endif's m #else // !ZIP_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); - return NULL; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); + return NULL; #endif // !ZIP_SUPPORT - } else if (Compressed) { + } else if (Compressed) { #if defined(GZ_SUPPORT) if (Compressed == 1) txfp = new(g) GZFAM(this); @@ -668,7 +671,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "GZ"); return NULL; #endif // !GZ_SUPPORT - } else if (map) + } else if (map) txfp = new(g) MAPFAM(this); else txfp = new(g) DOSFAM(this); @@ -676,41 +679,41 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) // Txfp must be set for TDBDOS tdbp = new(g) TDBJSN(this, txfp); - if (Lrecl) { - // Allocate the parse work memory - PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); - memset(G, 0, sizeof(GLOBAL)); - G->Sarea_Size = Lrecl * 10; - G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size); - PlugSubSet(G->Sarea, G->Sarea_Size); - G->jump_level = 0; - ((TDBJSN*)tdbp)->G = G; - } else { - strcpy(g->Message, "LRECL is not defined"); - return NULL; - } // endif Lrecl + if (Lrecl) { + // Allocate the parse work memory + PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); + memset(G, 0, sizeof(GLOBAL)); + G->Sarea_Size = Lrecl * 10; + G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size); + PlugSubSet(G->Sarea, G->Sarea_Size); + G->jump_level = 0; + ((TDBJSN*)tdbp)->G = G; + } else { + strcpy(g->Message, "LRECL is not defined"); + return NULL; + } // endif Lrecl - } else { - if (Zipped) { + } else { + if (Zipped) { #if defined(ZIP_SUPPORT) - if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { - txfp = new(g) UNZFAM(this); - } else if (m == MODE_INSERT) { - strcpy(g->Message, "INSERT supported only for zipped JSON when pretty=0"); - return NULL; - } else { - strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); - return NULL; - } // endif's m + if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { + txfp = new(g) UNZFAM(this); + } else if (m == MODE_INSERT) { + strcpy(g->Message, "INSERT supported only for zipped JSON when pretty=0"); + return NULL; + } else { + strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); + return NULL; + } // endif's m #else // !ZIP_SUPPORT - sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); - return NULL; + sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); + return NULL; #endif // !ZIP_SUPPORT - } else - txfp = new(g) MAPFAM(this); + } else + txfp = new(g) MAPFAM(this); tdbp = new(g) TDBJSON(this, txfp); - ((TDBJSON*)tdbp)->G = g; + ((TDBJSON*)tdbp)->G = g; } // endif Pretty if (Multiple) @@ -738,16 +741,16 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp) Limit = tdp->Limit; Pretty = tdp->Pretty; B = tdp->Base ? 1 : 0; - Sep = tdp->Sep; + Sep = tdp->Sep; Strict = tdp->Strict; } else { Jmode = MODE_OBJECT; Objname = NULL; - Xcol = NULL; + Xcol = NULL; Limit = 1; Pretty = 0; B = 0; - Sep = '.'; + Sep = '.'; Strict = false; } // endif tdp @@ -761,7 +764,7 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp) TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) { - G = NULL; + G = NULL; Top = tdbp->Top; Row = tdbp->Row; Val = tdbp->Val; @@ -777,7 +780,7 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) SameRow = tdbp->SameRow; Xval = tdbp->Xval; B = tdbp->B; - Sep = tdbp->Sep; + Sep = tdbp->Sep; Pretty = tdbp->Pretty; Strict = tdbp->Strict; Comma = tdbp->Comma; @@ -786,7 +789,7 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) // Used for update PTDB TDBJSN::Clone(PTABS t) { - G = NULL; + G = NULL; PTDB tp; PJCOL cp1, cp2; PGLOBAL g = t->G; @@ -860,33 +863,33 @@ PJSON TDBJSN::FindRow(PGLOBAL g) PJSON jsp = Row; PJVAL val = NULL; - for (objpath = PlugDup(g, Objname); jsp && objpath; objpath = p) { - if ((p = strchr(objpath, Sep))) - *p++ = 0; + for (objpath = PlugDup(g, Objname); jsp && objpath; objpath = p) { + if ((p = strchr(objpath, Sep))) + *p++ = 0; - if (*objpath != '[' && !IsNum(objpath)) { // objpass is a key - val = (jsp->GetType() == TYPE_JOB) ? - jsp->GetObject()->GetValue(objpath) : NULL; - } else { - if (*objpath == '[') { - if (objpath[strlen(objpath) - 1] == ']') - objpath++; - else - return NULL; - } // endif [ + if (*objpath != '[' && !IsNum(objpath)) { // objpass is a key + val = (jsp->GetType() == TYPE_JOB) ? + jsp->GetObject()->GetValue(objpath) : NULL; + } else { + if (*objpath == '[') { + if (objpath[strlen(objpath) - 1] == ']') + objpath++; + else + return NULL; + } // endif [ - val = (jsp->GetType() == TYPE_JAR) ? - jsp->GetArray()->GetValue(atoi(objpath) - B) : NULL; - } // endif objpath + val = (jsp->GetType() == TYPE_JAR) ? + jsp->GetArray()->GetValue(atoi(objpath) - B) : NULL; + } // endif objpath - jsp = (val) ? val->GetJson() : NULL; - } // endfor objpath + jsp = (val) ? val->GetJson() : NULL; + } // endfor objpath return jsp; } // end of FindRow /***********************************************************************/ -/* OpenDB: Data Base open routine for JSN access method. */ +/* OpenDB: Data Base open routine for JSN access method. */ /***********************************************************************/ bool TDBJSN::OpenDB(PGLOBAL g) { @@ -911,15 +914,15 @@ bool TDBJSN::OpenDB(PGLOBAL g) return true; } // endswitch Jmode - } // endif Use + } // endif Use - if (TDBDOS::OpenDB(g)) - return true; + if (TDBDOS::OpenDB(g)) + return true; - if (Xcol) - To_Filter = NULL; // Imcompatible + if (Xcol) + To_Filter = NULL; // Imcompatible - return false; + return false; } // end of OpenDB /***********************************************************************/ @@ -969,27 +972,27 @@ int TDBJSN::ReadDB(PGLOBAL g) NextSame = 0; M++; return RC_OK; - } else if ((rc = TDBDOS::ReadDB(g)) == RC_OK) { - if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) - // Deferred reading failed - return rc; + } else if ((rc = TDBDOS::ReadDB(g)) == RC_OK) { + if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) + // Deferred reading failed + return rc; - // Recover the memory used for parsing - PlugSubSet(G->Sarea, G->Sarea_Size); + // Recover the memory used for parsing + PlugSubSet(G->Sarea, G->Sarea_Size); - if ((Row = ParseJson(G, To_Line, strlen(To_Line), &Pretty, &Comma))) { - Row = FindRow(g); - SameRow = 0; - Fpos++; - M = 1; - rc = RC_OK; - } else if (Pretty != 1 || strcmp(To_Line, "]")) { - strcpy(g->Message, G->Message); - rc = RC_FX; - } else - rc = RC_EF; + if ((Row = ParseJson(G, To_Line, strlen(To_Line), &Pretty, &Comma))) { + Row = FindRow(g); + SameRow = 0; + Fpos++; + M = 1; + rc = RC_OK; + } else if (Pretty != 1 || strcmp(To_Line, "]")) { + strcpy(g->Message, G->Message); + rc = RC_FX; + } else + rc = RC_EF; - } // endif ReadDB + } // endif ReadDB return rc; } // end of ReadDB @@ -999,68 +1002,68 @@ int TDBJSN::ReadDB(PGLOBAL g) /***********************************************************************/ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) { - if (Objname) { - if (!Val) { - // Parse and allocate Objname item(s) - char *p; - char *objpath = PlugDup(g, Objname); - int i; - PJOB objp; - PJAR arp; - PJVAL val = NULL; + if (Objname) { + if (!Val) { + // Parse and allocate Objname item(s) + char *p; + char *objpath = PlugDup(g, Objname); + int i; + PJOB objp; + PJAR arp; + PJVAL val = NULL; - Top = NULL; + Top = NULL; - for (; objpath; objpath = p) { - if ((p = strchr(objpath, Sep))) - *p++ = 0; + for (; objpath; objpath = p) { + if ((p = strchr(objpath, Sep))) + *p++ = 0; - if (*objpath != '[' && !IsNum(objpath)) { - objp = new(g) JOBJECT; + if (*objpath != '[' && !IsNum(objpath)) { + objp = new(g) JOBJECT; - if (!Top) - Top = objp; + if (!Top) + Top = objp; - if (val) - val->SetValue(objp); + if (val) + val->SetValue(objp); - val = new(g) JVALUE; - objp->SetValue(g, val, objpath); - } else { - if (*objpath == '[') { - // Old style - if (objpath[strlen(objpath) - 1] != ']') { - sprintf(g->Message, "Invalid Table path %s", Objname); - return RC_FX; - } else - objpath++; + val = new(g) JVALUE; + objp->SetValue(g, val, objpath); + } else { + if (*objpath == '[') { + // Old style + if (objpath[strlen(objpath) - 1] != ']') { + sprintf(g->Message, "Invalid Table path %s", Objname); + return RC_FX; + } else + objpath++; - } // endif objpath + } // endif objpath - arp = new(g) JARRAY; + arp = new(g) JARRAY; - if (!Top) - Top = arp; + if (!Top) + Top = arp; - if (val) - val->SetValue(arp); + if (val) + val->SetValue(arp); - val = new(g) JVALUE; - i = atoi(objpath) - B; - arp->SetValue(g, val, i); - arp->InitArray(g); - } // endif objpath + val = new(g) JVALUE; + i = atoi(objpath) - B; + arp->SetValue(g, val, i); + arp->InitArray(g); + } // endif objpath - } // endfor p + } // endfor p - Val = val; - } // endif Val + Val = val; + } // endif Val - Val->SetValue(jsp); - } else - Top = jsp; + Val->SetValue(jsp); + } else + Top = jsp; - return RC_OK; + return RC_OK; } // end of MakeTopTree /***********************************************************************/ @@ -1095,11 +1098,11 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) /***********************************************************************/ int TDBJSN::WriteDB(PGLOBAL g) { - int rc = TDBDOS::WriteDB(g); + int rc = TDBDOS::WriteDB(g); - PlugSubSet(G->Sarea, G->Sarea_Size); - Row->Clear(); - return rc; + PlugSubSet(G->Sarea, G->Sarea_Size); + Row->Clear(); + return rc; } // end of WriteDB /* ---------------------------- JSONCOL ------------------------------ */ @@ -1111,12 +1114,12 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) : DOSCOL(g, cdp, tdbp, cprec, i, "DOS") { Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); - G = Tjp->G; + G = Tjp->G; Jpath = cdp->GetFmt(); MulVal = NULL; Nodes = NULL; Nod = 0; - Sep = Tjp->Sep; + Sep = Tjp->Sep; Xnod = -1; Xpd = false; Parsed = false; @@ -1128,14 +1131,14 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) /***********************************************************************/ JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp) { - G = col1->G; + G = col1->G; Tjp = col1->Tjp; Jpath = col1->Jpath; MulVal = col1->MulVal; Nodes = col1->Nodes; Nod = col1->Nod; - Sep = col1->Sep; - Xnod = col1->Xnod; + Sep = col1->Sep; + Xnod = col1->Xnod; Xpd = col1->Xpd; Parsed = col1->Parsed; } // end of JSONCOL copy constructor @@ -1153,7 +1156,7 @@ bool JSONCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) return true; Tjp = (TDBJSN*)To_Tdb; - G = Tjp->G; + G = Tjp->G; return false; } // end of SetBuffer @@ -1179,130 +1182,130 @@ bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b) /***********************************************************************/ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) { - int n; - bool dg = true, b = false; - PJNODE jnp = &Nodes[i]; + int n; + bool dg = true, b = false; + PJNODE jnp = &Nodes[i]; - //if (*p == '[') p++; // Old syntax .[ or :[ - n = (int)strlen(p); + //if (*p == '[') p++; // Old syntax .[ or :[ + n = (int)strlen(p); - if (*p) { - if (p[n - 1] == ']') { - p[--n] = 0; - } else if (!IsNum(p)) { - // Wrong array specification - sprintf(g->Message, "Invalid array specification %s for %s", p, Name); - return true; - } // endif p + if (*p) { + if (p[n - 1] == ']') { + p[--n] = 0; + } else if (!IsNum(p)) { + // Wrong array specification + sprintf(g->Message, "Invalid array specification %s for %s", p, Name); + return true; + } // endif p - } else - b = true; + } else + b = true; - // To check whether a numeric Rank was specified - dg = IsNum(p); + // To check whether a numeric Rank was specified + dg = IsNum(p); - if (!n) { - // Default specifications - if (CheckExpand(g, i, nm, false)) - return true; - else if (jnp->Op != OP_EXP) { - if (b) { - // Return 1st value (B is the index base) - jnp->Rank = Tjp->B; - jnp->Op = OP_EQ; - } else if (!Value->IsTypeNum()) { - jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING); - jnp->Op = OP_CNC; - } else - jnp->Op = OP_ADD; + if (!n) { + // Default specifications + if (CheckExpand(g, i, nm, false)) + return true; + else if (jnp->Op != OP_EXP) { + if (b) { + // Return 1st value (B is the index base) + jnp->Rank = Tjp->B; + jnp->Op = OP_EQ; + } else if (!Value->IsTypeNum()) { + jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING); + jnp->Op = OP_CNC; + } else + jnp->Op = OP_ADD; - } // endif OP + } // endif OP - } else if (dg) { - // Return nth value - jnp->Rank = atoi(p) - Tjp->B; - jnp->Op = OP_EQ; - } else if (n == 1) { - // Set the Op value; - if (Sep == ':') - switch (*p) { - case '*': *p = 'x'; break; - case 'x': - case 'X': *p = '*'; break; // Expand this array - default: break; - } // endswitch p + } else if (dg) { + // Return nth value + jnp->Rank = atoi(p) - Tjp->B; + jnp->Op = OP_EQ; + } else if (n == 1) { + // Set the Op value; + if (Sep == ':') + switch (*p) { + case '*': *p = 'x'; break; + case 'x': + case 'X': *p = '*'; break; // Expand this array + default: break; + } // endswitch p - switch (*p) { - case '+': jnp->Op = OP_ADD; break; - case 'x': jnp->Op = OP_MULT; break; - case '>': jnp->Op = OP_MAX; break; - case '<': jnp->Op = OP_MIN; break; - case '!': jnp->Op = OP_SEP; break; // Average - case '#': jnp->Op = OP_NUM; break; - case '*': // Expand this array - if (!Tjp->Xcol && nm) { - Xpd = true; - jnp->Op = OP_EXP; - Tjp->Xval = i; - Tjp->Xcol = nm; - } else if (CheckExpand(g, i, nm, true)) - return true; + switch (*p) { + case '+': jnp->Op = OP_ADD; break; + case 'x': jnp->Op = OP_MULT; break; + case '>': jnp->Op = OP_MAX; break; + case '<': jnp->Op = OP_MIN; break; + case '!': jnp->Op = OP_SEP; break; // Average + case '#': jnp->Op = OP_NUM; break; + case '*': // Expand this array + if (!Tjp->Xcol && nm) { + Xpd = true; + jnp->Op = OP_EXP; + Tjp->Xval = i; + Tjp->Xcol = nm; + } else if (CheckExpand(g, i, nm, true)) + return true; - break; - default: - sprintf(g->Message, - "Invalid function specification %c for %s", *p, Name); - return true; - } // endswitch *p + break; + default: + sprintf(g->Message, + "Invalid function specification %c for %s", *p, Name); + return true; + } // endswitch *p - } else if (*p == '"' && p[n - 1] == '"') { - // This is a concat specification - jnp->Op = OP_CNC; + } else if (*p == '"' && p[n - 1] == '"') { + // This is a concat specification + jnp->Op = OP_CNC; - if (n > 2) { - // Set concat intermediate string - p[n - 1] = 0; - jnp->CncVal = AllocateValue(g, p + 1, TYPE_STRING); - } // endif n + if (n > 2) { + // Set concat intermediate string + p[n - 1] = 0; + jnp->CncVal = AllocateValue(g, p + 1, TYPE_STRING); + } // endif n - } else { - sprintf(g->Message, "Wrong array specification for %s", Name); - return true; - } // endif's + } else { + sprintf(g->Message, "Wrong array specification for %s", Name); + return true; + } // endif's - // For calculated arrays, a local Value must be used - switch (jnp->Op) { - case OP_NUM: - jnp->Valp = AllocateValue(g, TYPE_INT); - break; - case OP_ADD: - case OP_MULT: - case OP_SEP: - if (!IsTypeChar(Buf_Type)) - jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision()); - else - jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2); + // For calculated arrays, a local Value must be used + switch (jnp->Op) { + case OP_NUM: + jnp->Valp = AllocateValue(g, TYPE_INT); + break; + case OP_ADD: + case OP_MULT: + case OP_SEP: + if (!IsTypeChar(Buf_Type)) + jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision()); + else + jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2); - break; - case OP_MIN: - case OP_MAX: - jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision()); - break; - case OP_CNC: - if (IsTypeChar(Buf_Type)) - jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision()); - else - jnp->Valp = AllocateValue(g, TYPE_STRING, 512); + break; + case OP_MIN: + case OP_MAX: + jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision()); + break; + case OP_CNC: + if (IsTypeChar(Buf_Type)) + jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision()); + else + jnp->Valp = AllocateValue(g, TYPE_STRING, 512); - break; - default: - break; - } // endswitch Op + break; + default: + break; + } // endswitch Op - if (jnp->Valp) - MulVal = AllocateValue(g, jnp->Valp); + if (jnp->Valp) + MulVal = AllocateValue(g, jnp->Valp); - return false; + return false; } // end of SetArrayOptions /***********************************************************************/ @@ -1313,87 +1316,87 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) /***********************************************************************/ bool JSONCOL::ParseJpath(PGLOBAL g) { - char *p, *p1 = NULL, *p2 = NULL, *pbuf = NULL; - int i; - bool a, mul = false; + char *p, *p1 = NULL, *p2 = NULL, *pbuf = NULL; + int i; + bool a, mul = false; - if (Parsed) - return false; // Already done - else if (InitValue(g)) - return true; - else if (!Jpath) - Jpath = Name; + if (Parsed) + return false; // Already done + else if (InitValue(g)) + return true; + else if (!Jpath) + Jpath = Name; - if (To_Tdb->GetOrig()) { - // This is an updated column, get nodes from origin - for (PJCOL colp = (PJCOL)Tjp->GetColumns(); colp; - colp = (PJCOL)colp->GetNext()) - if (!stricmp(Name, colp->GetName())) { - Nod = colp->Nod; - Nodes = colp->Nodes; - Xpd = colp->Xpd; - goto fin; - } // endif Name + if (To_Tdb->GetOrig()) { + // This is an updated column, get nodes from origin + for (PJCOL colp = (PJCOL)Tjp->GetColumns(); colp; + colp = (PJCOL)colp->GetNext()) + if (!stricmp(Name, colp->GetName())) { + Nod = colp->Nod; + Nodes = colp->Nodes; + Xpd = colp->Xpd; + goto fin; + } // endif Name - sprintf(g->Message, "Cannot parse updated column %s", Name); - return true; - } // endif To_Orig + sprintf(g->Message, "Cannot parse updated column %s", Name); + return true; + } // endif To_Orig - pbuf = PlugDup(g, Jpath); - if (*pbuf == '$') pbuf++; - if (*pbuf == Sep) pbuf++; - if (*pbuf == '[') p1 = pbuf++; + pbuf = PlugDup(g, Jpath); + if (*pbuf == '$') pbuf++; + if (*pbuf == Sep) pbuf++; + if (*pbuf == '[') p1 = pbuf++; - // Estimate the required number of nodes - for (i = 0, p = pbuf; (p = NextChr(p, Sep)); i++, p++) - Nod++; // One path node found + // Estimate the required number of nodes + for (i = 0, p = pbuf; (p = NextChr(p, Sep)); i++, p++) + Nod++; // One path node found - Nodes = (PJNODE)PlugSubAlloc(g, NULL, (++Nod) * sizeof(JNODE)); - memset(Nodes, 0, (Nod) * sizeof(JNODE)); + Nodes = (PJNODE)PlugSubAlloc(g, NULL, (++Nod) * sizeof(JNODE)); + memset(Nodes, 0, (Nod) * sizeof(JNODE)); - // Analyze the Jpath for this column - for (i = 0, p = pbuf; p && i < Nod; i++, p = (p2 ? p2 : NULL)) { - a = (p1 != NULL); - p1 = strchr(p, '['); - p2 = strchr(p, Sep); + // Analyze the Jpath for this column + for (i = 0, p = pbuf; p && i < Nod; i++, p = (p2 ? p2 : NULL)) { + a = (p1 != NULL); + p1 = strchr(p, '['); + p2 = strchr(p, Sep); - if (!p2) - p2 = p1; - else if (p1) { - if (p1 < p2) - p2 = p1; - else if (p1 == p2 + 1) - *p2++ = 0; // Old syntax .[ or :[ - else - p1 = NULL; + if (!p2) + p2 = p1; + else if (p1) { + if (p1 < p2) + p2 = p1; + else if (p1 == p2 + 1) + *p2++ = 0; // Old syntax .[ or :[ + else + p1 = NULL; - } // endif p1 + } // endif p1 - if (p2) - *p2++ = 0; + if (p2) + *p2++ = 0; - // Jpath must be explicit - if (a || *p == 0 || *p == '[' || IsNum(p)) { - // Analyse intermediate array processing - if (SetArrayOptions(g, p, i, Nodes[i - 1].Key)) - return true; + // Jpath must be explicit + if (a || *p == 0 || *p == '[' || IsNum(p)) { + // Analyse intermediate array processing + if (SetArrayOptions(g, p, i, Nodes[i - 1].Key)) + return true; - } else if (*p == '*') { - // Return JSON - Nodes[i].Op = OP_XX; - } else { - Nodes[i].Key = p; - Nodes[i].Op = OP_EXIST; - } // endif's + } else if (*p == '*') { + // Return JSON + Nodes[i].Op = OP_XX; + } else { + Nodes[i].Key = p; + Nodes[i].Op = OP_EXIST; + } // endif's - } // endfor i, p + } // endfor i, p - Nod = i; + Nod = i; fin: - MulVal = AllocateValue(g, Value); - Parsed = true; - return false; + MulVal = AllocateValue(g, Value); + Parsed = true; + return false; } // end of ParseJpath /***********************************************************************/ @@ -1401,66 +1404,66 @@ fin: /***********************************************************************/ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj) { - if (Jpath) { - char *p1, *p2, *mgopath; - int i = 0; + if (Jpath) { + char *p1, *p2, *mgopath; + int i = 0; - if (strcmp(Jpath, "*")) { - p1 = Jpath; - if (*p1 == '$') p1++; - if (*p1 == '.') p1++; - mgopath = PlugDup(g, p1); - } else - return NULL; + if (strcmp(Jpath, "*")) { + p1 = Jpath; + if (*p1 == '$') p1++; + if (*p1 == '.') p1++; + mgopath = PlugDup(g, p1); + } else + return NULL; - for (p1 = p2 = mgopath; *p1; p1++) - if (i) { // Inside [] - if (isdigit(*p1)) { - if (!proj) - *p2++ = *p1; + for (p1 = p2 = mgopath; *p1; p1++) + if (i) { // Inside [] + if (isdigit(*p1)) { + if (!proj) + *p2++ = *p1; - } else if (*p1 == ']' && i == 1) { - if (proj && p1[1] == '.') - p1++; + } else if (*p1 == ']' && i == 1) { + if (proj && p1[1] == '.') + p1++; - i = 0; - } else if (*p1 == '.' && i == 2) { - if (!proj) - *p2++ = '.'; + i = 0; + } else if (*p1 == '.' && i == 2) { + if (!proj) + *p2++ = '.'; - i = 0; - } else if (!proj) - return NULL; - - } else switch (*p1) { - case ':': - case '.': - if (isdigit(p1[1])) - i = 2; + i = 0; + } else if (!proj) + return NULL; - *p2++ = '.'; - break; - case '[': - if (*(p2 - 1) != '.') - *p2++ = '.'; + } else switch (*p1) { + case ':': + case '.': + if (isdigit(p1[1])) + i = 2; - i = 1; - break; - case '*': - if (*(p2 - 1) == '.' && !*(p1 + 1)) { - p2--; // Suppress last :* - break; - } // endif p2 + *p2++ = '.'; + break; + case '[': + if (*(p2 - 1) != '.') + *p2++ = '.'; - default: - *p2++ = *p1; - break; - } // endswitch p1; + i = 1; + break; + case '*': + if (*(p2 - 1) == '.' && !*(p1 + 1)) { + p2--; // Suppress last :* + break; + } // endif p2 - *p2 = 0; - return mgopath; - } else - return NULL; + default: + *p2++ = *p1; + break; + } // endswitch p1; + + *p2 = 0; + return mgopath; + } else + return NULL; } // end of GetJpath @@ -1469,7 +1472,7 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj) /***********************************************************************/ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp) { - if (Value->IsTypeNum()) { + if (Value->IsTypeNum()) { strcpy(g->Message, "Cannot make Json for a numeric column"); Value->Reset(); } else @@ -1484,22 +1487,22 @@ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp) void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) { if (val) { - vp->SetNull(false); + vp->SetNull(false); switch (val->GetValType()) { case TYPE_STRG: case TYPE_INTG: - case TYPE_BINT: - case TYPE_DBL: - case TYPE_DTM: - vp->SetValue_pval(val->GetValue()); + case TYPE_BINT: + case TYPE_DBL: + case TYPE_DTM: + vp->SetValue_pval(val->GetValue()); break; case TYPE_BOOL: if (vp->IsTypeNum()) vp->SetValue(val->GetInteger() ? 1 : 0); else vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false")); - + break; case TYPE_JAR: SetJsonValue(g, vp, val->GetArray()->GetValue(0), n); @@ -1509,16 +1512,16 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) vp->SetValue_psz(val->GetObject()->GetText(g, NULL)); break; // } // endif Type - - default: - vp->Reset(); - vp->SetNull(true); - } // endswitch Type - } else { - vp->Reset(); - vp->SetNull(true); - } // endif val + default: + vp->Reset(); + vp->SetNull(true); + } // endswitch Type + + } else { + vp->Reset(); + vp->SetNull(true); + } // endif val } // end of SetJsonValue @@ -1530,8 +1533,8 @@ void JSONCOL::ReadColumn(PGLOBAL g) if (!Tjp->SameRow || Xnod >= Tjp->SameRow) Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0)); - if (Xpd && Value->IsNull() && !((PJDEF)Tjp->To_Def)->Accept) - throw("Null expandable JSON value"); + if (Xpd && Value->IsNull() && !((PJDEF)Tjp->To_Def)->Accept) + throw("Null expandable JSON value"); // Set null when applicable if (!Nullable) @@ -1579,11 +1582,11 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i) else return CalculateArray(g, arp, i); - } else { - // Unexpected array, unwrap it as [0] - val = arp->GetValue(0); - i--; - } // endif's + } else { + // Unexpected array, unwrap it as [0] + val = arp->GetValue(0); + i--; + } // endif's break; case TYPE_JVAL: @@ -1612,17 +1615,17 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n) PJVAL jvp; JVALUE jval; - if (!ars) { - Value->Reset(); - Value->SetNull(true); - Tjp->NextSame = 0; - return Value; - } // endif ars + if (!ars) { + Value->Reset(); + Value->SetNull(true); + Tjp->NextSame = 0; + return Value; + } // endif ars if (!(jvp = arp->GetValue((Nodes[n].Rx = Nodes[n].Nx)))) { strcpy(g->Message, "Logical error expanding array"); - throw 666; - } // endif jvp + throw 666; + } // endif jvp if (n < Nod - 1 && jvp->GetJson()) { jval.SetValue(GetColumnValue(g, jvp->GetJson(), n + 1)); @@ -1637,7 +1640,7 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n) Xnod = n; Tjp->NextSame = Xnod; - } // endif NextSame + } // endif NextSame SetJsonValue(g, Value, jvp, n); return Value; @@ -1648,58 +1651,58 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n) /***********************************************************************/ PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n) { - int i, ars, nv = 0, nextsame = Tjp->NextSame; - bool err; + int i, ars, nv = 0, nextsame = Tjp->NextSame; + bool err; OPVAL op = Nodes[n].Op; PVAL val[2], vp = Nodes[n].Valp; PJVAL jvrp, jvp; JVALUE jval; vp->Reset(); - ars = MY_MIN(Tjp->Limit, arp->size()); + ars = MY_MIN(Tjp->Limit, arp->size()); - if (trace(1)) - htrc("CalculateArray: size=%d op=%d nextsame=%d\n", - ars, op, nextsame); + if (trace(1)) + htrc("CalculateArray: size=%d op=%d nextsame=%d\n", + ars, op, nextsame); - for (i = 0; i < ars; i++) { - jvrp = arp->GetValue(i); + for (i = 0; i < ars; i++) { + jvrp = arp->GetValue(i); - if (trace(1)) - htrc("i=%d nv=%d\n", i, nv); + if (trace(1)) + htrc("i=%d nv=%d\n", i, nv); - if (!jvrp->IsNull() || (op == OP_CNC && GetJsonNull())) do { - if (jvrp->IsNull()) { - jvrp->Value = AllocateValue(g, GetJsonNull(), TYPE_STRING); - jvp = jvrp; - } else if (n < Nod - 1 && jvrp->GetJson()) { + if (!jvrp->IsNull() || (op == OP_CNC && GetJsonNull())) do { + if (jvrp->IsNull()) { + jvrp->Value = AllocateValue(g, GetJsonNull(), TYPE_STRING); + jvp = jvrp; + } else if (n < Nod - 1 && jvrp->GetJson()) { Tjp->NextSame = nextsame; jval.SetValue(GetColumnValue(g, jvrp->GetJson(), n + 1)); jvp = &jval; } else jvp = jvrp; - - if (trace(1)) - htrc("jvp=%s null=%d\n", - jvp->GetString(g), jvp->IsNull() ? 1 : 0); - if (!nv++) { + if (trace(1)) + htrc("jvp=%s null=%d\n", + jvp->GetString(g), jvp->IsNull() ? 1 : 0); + + if (!nv++) { SetJsonValue(g, vp, jvp, n); continue; } else SetJsonValue(g, MulVal, jvp, n); - if (!MulVal->IsNull()) { - switch (op) { + if (!MulVal->IsNull()) { + switch (op) { case OP_CNC: if (Nodes[n].CncVal) { val[0] = Nodes[n].CncVal; err = vp->Compute(g, val, 1, op); } // endif CncVal - + val[0] = MulVal; err = vp->Compute(g, val, 1, op); - break; + break; // case OP_NUM: case OP_SEP: val[0] = Nodes[n].Valp; @@ -1714,16 +1717,16 @@ PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n) if (err) vp->Reset(); - - if (trace(1)) { - char buf(32); - htrc("vp='%s' err=%d\n", - vp->GetCharString(&buf), err ? 1 : 0); + if (trace(1)) { + char buf(32); - } // endif trace + htrc("vp='%s' err=%d\n", + vp->GetCharString(&buf), err ? 1 : 0); - } // endif Null + } // endif trace + + } // endif Null } while (Tjp->NextSame > nextsame); @@ -1753,8 +1756,8 @@ PJSON JSONCOL::GetRow(PGLOBAL g) PJAR arp; PJSON nwr, row = Tjp->Row; - for (int i = 0; i < Nod && row; i++) { - if (Nodes[i+1].Op == OP_XX) + for (int i = 0; i < Nod && row; i++) { + if (Nodes[i+1].Op == OP_XX) break; else switch (row->GetType()) { case TYPE_JOB: @@ -1765,19 +1768,19 @@ PJSON JSONCOL::GetRow(PGLOBAL g) val = ((PJOB)row)->GetValue(Nodes[i].Key); break; case TYPE_JAR: - arp = (PJAR)row; + arp = (PJAR)row; - if (!Nodes[i].Key) { + if (!Nodes[i].Key) { if (Nodes[i].Op == OP_EQ) val = arp->GetValue(Nodes[i].Rank); else val = arp->GetValue(Nodes[i].Rx); } else { - // Unexpected array, unwrap it as [0] - val = arp->GetValue(0); - i--; - } // endif Nodes + // Unexpected array, unwrap it as [0] + val = arp->GetValue(0); + i--; + } // endif Nodes break; case TYPE_JVAL: @@ -1827,10 +1830,10 @@ PJSON JSONCOL::GetRow(PGLOBAL g) /***********************************************************************/ void JSONCOL::WriteColumn(PGLOBAL g) { - if (Xpd && Tjp->Pretty < 2) { - strcpy(g->Message, "Cannot write expanded column when Pretty is not 2"); - throw 666; - } // endif Xpd + if (Xpd && Tjp->Pretty < 2) { + strcpy(g->Message, "Cannot write expanded column when Pretty is not 2"); + throw 666; + } // endif Xpd /*********************************************************************/ /* Check whether this node must be written. */ @@ -1864,8 +1867,8 @@ void JSONCOL::WriteColumn(PGLOBAL g) if (!(jsp = ParseJson(G, s, (int)strlen(s)))) { strcpy(g->Message, s); - throw 666; - } // endif jsp + throw 666; + } // endif jsp if (arp) { if (Nod > 1 && Nodes[Nod-2].Op == OP_EQ) @@ -1887,10 +1890,10 @@ void JSONCOL::WriteColumn(PGLOBAL g) // fall through case TYPE_DATE: case TYPE_INT: - case TYPE_TINY: - case TYPE_SHORT: - case TYPE_BIGINT: - case TYPE_DOUBLE: + case TYPE_TINY: + case TYPE_SHORT: + case TYPE_BIGINT: + case TYPE_DOUBLE: if (arp) { if (Nodes[Nod-1].Op == OP_EQ) arp->SetValue(G, new(G) JVALUE(G, Value), Nodes[Nod-1].Rank); @@ -1981,7 +1984,7 @@ int TDBJSON::MakeDocument(PGLOBAL g) return RC_OK; /*********************************************************************/ - /* Create the mapping file object in mode read. */ + /* Create the mapping file object in mode read. */ /*********************************************************************/ Mode = MODE_READ; @@ -2010,70 +2013,70 @@ int TDBJSON::MakeDocument(PGLOBAL g) if (!jsp && g->Message[0]) return RC_FX; - if ((objpath = PlugDup(g, Objname))) { - if (*objpath == '$') objpath++; - if (*objpath == '.') objpath++; + if ((objpath = PlugDup(g, Objname))) { + if (*objpath == '$') objpath++; + if (*objpath == '.') objpath++; - /*********************************************************************/ - /* Find the table in the tree structure. */ - /*********************************************************************/ - for (; jsp && objpath; objpath = p) { - if ((p = strchr(objpath, Sep))) - *p++ = 0; + /*********************************************************************/ + /* Find the table in the tree structure. */ + /*********************************************************************/ + for (; jsp && objpath; objpath = p) { + if ((p = strchr(objpath, Sep))) + *p++ = 0; - if (*objpath != '[' && !IsNum(objpath)) { - // objpass is a key - if (jsp->GetType() != TYPE_JOB) { - strcpy(g->Message, "Table path does not match the json file"); - return RC_FX; - } // endif Type + if (*objpath != '[' && !IsNum(objpath)) { + // objpass is a key + if (jsp->GetType() != TYPE_JOB) { + strcpy(g->Message, "Table path does not match the json file"); + return RC_FX; + } // endif Type - key = objpath; - objp = jsp->GetObject(); - arp = NULL; - val = objp->GetValue(key); + key = objpath; + objp = jsp->GetObject(); + arp = NULL; + val = objp->GetValue(key); - if (!val || !(jsp = val->GetJson())) { - sprintf(g->Message, "Cannot find object key %s", key); - return RC_FX; - } // endif val + if (!val || !(jsp = val->GetJson())) { + sprintf(g->Message, "Cannot find object key %s", key); + return RC_FX; + } // endif val - } else { - if (*objpath == '[') { - // Old style - if (objpath[strlen(objpath) - 1] != ']') { - sprintf(g->Message, "Invalid Table path %s", Objname); - return RC_FX; - } else - objpath++; + } else { + if (*objpath == '[') { + // Old style + if (objpath[strlen(objpath) - 1] != ']') { + sprintf(g->Message, "Invalid Table path %s", Objname); + return RC_FX; + } else + objpath++; - } // endif objpath + } // endif objpath - if (jsp->GetType() != TYPE_JAR) { - strcpy(g->Message, "Table path does not match the json file"); - return RC_FX; - } // endif Type + if (jsp->GetType() != TYPE_JAR) { + strcpy(g->Message, "Table path does not match the json file"); + return RC_FX; + } // endif Type - arp = jsp->GetArray(); - objp = NULL; - i = atoi(objpath) - B; - val = arp->GetValue(i); + arp = jsp->GetArray(); + objp = NULL; + i = atoi(objpath) - B; + val = arp->GetValue(i); - if (!val) { - sprintf(g->Message, "Cannot find array value %d", i); - return RC_FX; - } // endif val + if (!val) { + sprintf(g->Message, "Cannot find array value %d", i); + return RC_FX; + } // endif val - } // endif + } // endif - jsp = val->GetJson(); - } // endfor objpath + jsp = val->GetJson(); + } // endfor objpath - } // endif objpath + } // endif objpath if (jsp && jsp->GetType() == TYPE_JAR) Doc = jsp->GetArray(); - else { + else { // The table is void or is just one object or one value Doc = new(g) JARRAY; @@ -2149,7 +2152,7 @@ int TDBJSON::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool) } else return RC_OK; - } // end of MakeIndex + } // end of MakeIndex /***********************************************************************/ /* Return the position in the table. */ @@ -2227,11 +2230,11 @@ bool TDBJSON::OpenDB(PGLOBAL g) return true; } // endswitch Jmode - if (Xcol) - To_Filter = NULL; // Imcompatible + if (Xcol) + To_Filter = NULL; // Imcompatible - Use = USE_OPEN; - return false; + Use = USE_OPEN; + return false; } // end of OpenDB /***********************************************************************/ @@ -2241,7 +2244,7 @@ int TDBJSON::ReadDB(PGLOBAL) { int rc; - N++; + N++; if (NextSame) { SameRow = NextSame; @@ -2352,8 +2355,8 @@ void TDBJSON::CloseDB(PGLOBAL g) TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp) { Topt = tdp->GetTopt(); - Db = tdp->Schema; - Dsn = tdp->Uri; + Db = tdp->Schema; + Dsn = tdp->Uri; } // end of TDBJCL constructor /***********************************************************************/ diff --git a/storage/connect/tabrest.cpp b/storage/connect/tabrest.cpp 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 // 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 e194568ccf8..1150824464f 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -232,7 +232,7 @@ bool TDBTBL::InitTableList(PGLOBAL g) { int n; uint sln; - char *scs; + const char *scs; PTABLE tp, tabp; PCOL colp; PTBLDEF tdp = (PTBLDEF)To_Def; @@ -281,7 +281,7 @@ bool TDBTBL::InitTableList(PGLOBAL g) } // endfor tp - hc->get_table()->s->connect_string.str = scs; + hc->get_table()->s->connect_string.str = (char*)scs; hc->get_table()->s->connect_string.length = sln; //NumTables = n; diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp index d808bd5ecd4..19490d350e8 100644 --- a/storage/connect/tabxml.cpp +++ b/storage/connect/tabxml.cpp @@ -1880,7 +1880,7 @@ void XMULCOL::ReadColumn(PGLOBAL g) if (N > Tdbp->Limit) { N = Tdbp->Limit; - sprintf(g->Message, "Mutiple values limited to %d", Tdbp->Limit); + sprintf(g->Message, "Multiple values limited to %d", Tdbp->Limit); PushWarning(g, Tdbp); } // endif N diff --git a/storage/connect/user_connect.cc b/storage/connect/user_connect.cc index d366e0222df..c25443ef7ef 100644 --- a/storage/connect/user_connect.cc +++ b/storage/connect/user_connect.cc @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file user_connect.cc diff --git a/storage/connect/user_connect.h b/storage/connect/user_connect.h index 983d9adc478..2670c5bcebc 100644 --- a/storage/connect/user_connect.h +++ b/storage/connect/user_connect.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ /** @file user_connect.h From 0043593b9d35ea505470cb83ffc166e2c1466e17 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 24 Aug 2019 17:32:38 +0200 Subject: [PATCH 02/15] Fix xml(2)_mult.test result mismatch --- storage/connect/mysql-test/connect/r/xml2_mult.result | 8 ++++---- storage/connect/mysql-test/connect/r/xml_mult.result | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/storage/connect/mysql-test/connect/r/xml2_mult.result b/storage/connect/mysql-test/connect/r/xml2_mult.result index a9592e986c0..87d1118edd5 100644 --- a/storage/connect/mysql-test/connect/r/xml2_mult.result +++ b/storage/connect/mysql-test/connect/r/xml2_mult.result @@ -51,14 +51,14 @@ WEB XQuery Kick Start en Per Bothner 2003 49.99 WEB XQuery Kick Start en Kurt Cagle 2003 49.99 WEB Learning XML en Erik T. Ray 2003 39.95 Warnings: -Warning 1105 Mutiple values limited to 3 +Warning 1105 Multiple values limited to 3 # One line lost because the where clause is applied only on the first 3 rows SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%'; category title author price CHILDREN Harry Potter J K. Rowling 29.99 WEB XQuery Kick Start James McGovern 49.99 Warnings: -Warning 1105 Mutiple values limited to 3 +Warning 1105 Multiple values limited to 3 # # Testing concatenated values # @@ -91,12 +91,12 @@ CHILDREN Harry Potter en J K. Rowling 2005 29.99 WEB XQuery Kick Start en James McGovern, Per Bothner, Kurt Cagle, James Linn 2003 49.99 WEB Learning XML en Erik T. Ray 2003 39.95 Warnings: -Warning 1105 Mutiple values limited to 4 +Warning 1105 Multiple values limited to 4 # The where clause is applied on the concatenated column result SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%'; category title author price CHILDREN Harry Potter J K. Rowling 29.99 WEB XQuery Kick Start James McGovern, Per Bothner, Kurt Cagle, James Linn 49.99 Warnings: -Warning 1105 Mutiple values limited to 4 +Warning 1105 Multiple values limited to 4 DROP TABLE bookstore; diff --git a/storage/connect/mysql-test/connect/r/xml_mult.result b/storage/connect/mysql-test/connect/r/xml_mult.result index d89debadfab..9922b40060c 100644 --- a/storage/connect/mysql-test/connect/r/xml_mult.result +++ b/storage/connect/mysql-test/connect/r/xml_mult.result @@ -49,14 +49,14 @@ WEB XQuery Kick Start en Per Bothner 2003 49.99 WEB XQuery Kick Start en Kurt Cagle 2003 49.99 WEB Learning XML en Erik T. Ray 2003 39.95 Warnings: -Warning 1105 Mutiple values limited to 3 +Warning 1105 Multiple values limited to 3 # One line lost because the where clause is applied only on the first 3 rows SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%'; category title author price CHILDREN Harry Potter J K. Rowling 29.99 WEB XQuery Kick Start James McGovern 49.99 Warnings: -Warning 1105 Mutiple values limited to 3 +Warning 1105 Multiple values limited to 3 # # Testing concatenated values # @@ -89,12 +89,12 @@ CHILDREN Harry Potter en J K. Rowling 2005 29.99 WEB XQuery Kick Start en James McGovern, Per Bothner, Kurt Cagle, James Linn 2003 49.99 WEB Learning XML en Erik T. Ray 2003 39.95 Warnings: -Warning 1105 Mutiple values limited to 4 +Warning 1105 Multiple values limited to 4 # The where clause is applied on the concatenated column result SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%'; category title author price CHILDREN Harry Potter J K. Rowling 29.99 WEB XQuery Kick Start James McGovern, Per Bothner, Kurt Cagle, James Linn 49.99 Warnings: -Warning 1105 Mutiple values limited to 4 +Warning 1105 Multiple values limited to 4 DROP TABLE bookstore; From 396313d301b3567aeadd04ae6a9322da2adc0a8b Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Wed, 22 May 2019 01:54:47 -0700 Subject: [PATCH 03/15] MDEV-14448: Ctrl-C should not exit the client --- client/mysql.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 50d45696a5c..86ee22e5e6a 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1368,12 +1368,21 @@ sig_handler handle_sigint(int sig) char kill_buffer[40]; MYSQL *kill_mysql= NULL; - /* terminate if no query being executed, or we already tried interrupting */ - if (!executing_query || (interrupted_query == 2)) + /* Terminate if we already tried interrupting. */ + if (interrupted_query == 2) { tee_fprintf(stdout, "Ctrl-C -- exit!\n"); goto err; } + /* If no query being executed, don't exit. */ + if (!executing_query) + { + tee_fprintf(stdout, "Ctrl-C\n"); + rl_on_new_line(); // Regenerate the prompt on a newline + rl_replace_line("", 0); // Clear the previous text + rl_redisplay(); + return; + } kill_mysql= mysql_init(kill_mysql); if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password, From 2cc360bdf2a47f968140f5b75c7668f999b36612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 28 Oct 2019 16:03:00 +0200 Subject: [PATCH 04/15] Remove bogus advice Ever since MariaDB 10.0 (and MySQL 5.6.8), the innodb_log_file_size and innodb_log_files_in_group can be changed between server restarts, and the redo log files will be resized on server startup if needed. --- debian/additions/my.cnf | 2 -- 1 file changed, 2 deletions(-) diff --git a/debian/additions/my.cnf b/debian/additions/my.cnf index d30ec182c8b..22103ec09c9 100644 --- a/debian/additions/my.cnf +++ b/debian/additions/my.cnf @@ -131,8 +131,6 @@ max_binlog_size = 100M # InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/. # Read the manual for more InnoDB related options. There are many! default_storage_engine = InnoDB -# you can't just change log file size, requires special procedure -#innodb_log_file_size = 50M innodb_buffer_pool_size = 256M innodb_log_buffer_size = 8M innodb_file_per_table = 1 From 84088d9458d2119889149c614993b18d67711a5b Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Tue, 29 Oct 2019 21:56:24 +0300 Subject: [PATCH 05/15] add .clang-format file for InnoDB --- storage/innobase/.clang-format | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 storage/innobase/.clang-format diff --git a/storage/innobase/.clang-format b/storage/innobase/.clang-format new file mode 100644 index 00000000000..54f7b47bc88 --- /dev/null +++ b/storage/innobase/.clang-format @@ -0,0 +1,11 @@ +UseTab: Always +TabWidth: 8 +IndentWidth: 8 +ContinuationIndentWidth: 8 +BreakBeforeBinaryOperators: All +PointerAlignment: Left +BreakBeforeBraces: Custom +ColumnLimit: 79 +BraceWrapping: + AfterFunction: true +AccessModifierOffset: -8 From bc8a9ab5f32a73e7e41680f98ba516611bc00ce0 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Tue, 29 Oct 2019 23:02:03 +0300 Subject: [PATCH 06/15] remove unused struct members --- dbug/dbug.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/dbug/dbug.c b/dbug/dbug.c index 3035895648e..54eebfe55a5 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -226,11 +226,8 @@ typedef struct _db_code_state_ { const char *file; /* Name of current user file */ struct _db_stack_frame_ *framep; /* Pointer to current frame */ struct settings *stack; /* debugging settings */ - const char *jmpfunc; /* Remember current function for setjmp */ - const char *jmpfile; /* Remember current file for setjmp */ int lineno; /* Current debugger output line number */ uint level; /* Current function nesting level */ - int jmplevel; /* Remember nesting level at setjmp() */ /* * The following variables are used to hold the state information From 20b72a3fad45bd8fc0bf6987fcec0c21b4f36885 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 30 Oct 2019 00:47:50 +0100 Subject: [PATCH 07/15] compilation fix for Windows --- client/mysql.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/mysql.cc b/client/mysql.cc index 86ee22e5e6a..7329f2298ab 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1378,9 +1378,11 @@ sig_handler handle_sigint(int sig) if (!executing_query) { tee_fprintf(stdout, "Ctrl-C\n"); +#ifdef HAVE_READLINE rl_on_new_line(); // Regenerate the prompt on a newline rl_replace_line("", 0); // Clear the previous text rl_redisplay(); +#endif return; } From afb4878703e71307af0fe8723f8ab10e8d4e0288 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Tue, 25 Jun 2019 15:52:05 +0400 Subject: [PATCH 08/15] MDEV-18783 - Server crash in hp_rb_make_key In debug build, whenever MEMORY table instance gets closed it performs consistency check without protection. It may cause server crash if executed concurrently with DML. Moved consistency check to ha_heap::external_lock(F_UNLCK), so that it is protected by THR_LOCK. --- storage/heap/ha_heap.cc | 4 ++++ storage/heap/hp_close.c | 6 ------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc index a1b8db34453..60a41cc52e7 100644 --- a/storage/heap/ha_heap.cc +++ b/storage/heap/ha_heap.cc @@ -453,6 +453,10 @@ int ha_heap::reset_auto_increment(ulonglong value) int ha_heap::external_lock(THD *thd, int lock_type) { +#ifndef DBUG_OFF + if (lock_type == F_UNLCK && file->s->changed && heap_check_heap(file, 0)) + return HA_ERR_CRASHED; +#endif return 0; // No external locking } diff --git a/storage/heap/hp_close.c b/storage/heap/hp_close.c index 092048a7c1c..82d6186340a 100644 --- a/storage/heap/hp_close.c +++ b/storage/heap/hp_close.c @@ -35,12 +35,6 @@ int hp_close(register HP_INFO *info) { int error=0; DBUG_ENTER("hp_close"); -#ifndef DBUG_OFF - if (info->s->changed && heap_check_heap(info,0)) - { - error=my_errno=HA_ERR_CRASHED; - } -#endif info->s->changed=0; if (info->open_list.data) heap_open_list=list_delete(heap_open_list,&info->open_list); From a7e3008ab3d368c2e2957b346647a7656d638e5c Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Wed, 30 Oct 2019 12:53:25 +0300 Subject: [PATCH 09/15] MDEV-20926 UBSAN: load of value 165, which is not a valid value for type bool Basicaly it's an uninitialized read. 165 is 0xa5 which comes from TRASH_ALLOC() Fix by calling a class ctor which initializes problematic TMP_TABLE_PARAM::force_copy_fields field --- sql/sql_show.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d8f65c74448..c63b8b0f8a8 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -7708,8 +7708,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) item->maybe_null= (fields_info->field_flags & MY_I_S_MAYBE_NULL); field_count++; } - TMP_TABLE_PARAM *tmp_table_param = - (TMP_TABLE_PARAM*) (thd->alloc(sizeof(TMP_TABLE_PARAM))); + TMP_TABLE_PARAM *tmp_table_param = new TMP_TABLE_PARAM; tmp_table_param->init(); tmp_table_param->table_charset= cs; tmp_table_param->field_count= field_count; From a3553a1387315f69551793b9baec4d8f91f51fcf Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 30 Oct 2019 11:15:05 +0100 Subject: [PATCH 10/15] 5.6.45-86.1 --- .../cmake_modules/TokuMergeLibs.cmake | 2 +- .../cmake_modules/TokuThirdParty.cmake | 34 ---- .../PerconaFT/portability/CMakeLists.txt | 1 - .../scripts/run-nightly-coverage-tests.bash | 2 +- .../scripts/run-nightly-drd-tests.bash | 2 +- .../scripts/run-nightly-release-tests.bash | 2 +- storage/tokudb/ha_tokudb.cc | 3 +- storage/tokudb/ha_tokudb.h | 3 +- storage/tokudb/hatoku_cmp.cc | 8 +- storage/tokudb/tests/math_test_int.cc | 156 +++++++++++++----- storage/tokudb/tests/math_test_uint.cc | 84 +++++++--- storage/tokudb/tests/sint_test.cc | 1 - storage/tokudb/tests/tokudb_buffer_test.cc | 11 +- storage/tokudb/tests/uint_test.cc | 1 - storage/tokudb/tests/vlq_test.cc | 9 +- storage/tokudb/tests/vlq_test_uint32.cc | 15 +- storage/tokudb/tests/vlq_test_uint64.cc | 15 +- storage/tokudb/tokudb_buffer.h | 4 +- storage/tokudb/tokudb_math.h | 6 +- 19 files changed, 228 insertions(+), 131 deletions(-) diff --git a/storage/tokudb/PerconaFT/cmake_modules/TokuMergeLibs.cmake b/storage/tokudb/PerconaFT/cmake_modules/TokuMergeLibs.cmake index e1da095fc00..f2462afdb45 100644 --- a/storage/tokudb/PerconaFT/cmake_modules/TokuMergeLibs.cmake +++ b/storage/tokudb/PerconaFT/cmake_modules/TokuMergeLibs.cmake @@ -6,7 +6,7 @@ FUNCTION(TOKU_GET_DEPENDEND_OS_LIBS target result) IF(deps) FOREACH(lib ${deps}) # Filter out keywords for used for debug vs optimized builds - IF(NOT lib MATCHES "general" AND NOT lib MATCHES "debug" AND NOT lib MATCHES "optimized") + IF(TARGET ${lib}) GET_TARGET_PROPERTY(lib_location ${lib} LOCATION) IF(NOT lib_location) SET(ret ${ret} ${lib}) diff --git a/storage/tokudb/PerconaFT/cmake_modules/TokuThirdParty.cmake b/storage/tokudb/PerconaFT/cmake_modules/TokuThirdParty.cmake index b707f368431..b312111a3a2 100644 --- a/storage/tokudb/PerconaFT/cmake_modules/TokuThirdParty.cmake +++ b/storage/tokudb/PerconaFT/cmake_modules/TokuThirdParty.cmake @@ -1,39 +1,5 @@ include(ExternalProject) -if (NOT DEFINED LIBJEMALLOC) - ## add jemalloc with an external project - set(JEMALLOC_SOURCE_DIR "${TokuDB_SOURCE_DIR}/third_party/jemalloc" CACHE FILEPATH "Where to find jemalloc sources.") - if (EXISTS "${JEMALLOC_SOURCE_DIR}/configure") - set(jemalloc_configure_opts "CC=${CMAKE_C_COMPILER}" "--with-jemalloc-prefix=" "--with-private-namespace=tokudb_jemalloc_internal_" "--enable-cc-silence") - option(JEMALLOC_DEBUG "Build jemalloc with --enable-debug." OFF) - if (JEMALLOC_DEBUG) - list(APPEND jemalloc_configure_opts --enable-debug) - endif () - ExternalProject_Add(build_jemalloc - PREFIX jemalloc - SOURCE_DIR "${JEMALLOC_SOURCE_DIR}" - CONFIGURE_COMMAND - "${JEMALLOC_SOURCE_DIR}/configure" ${jemalloc_configure_opts} - "--prefix=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/jemalloc" - ) - - add_library(jemalloc STATIC IMPORTED GLOBAL) - set_target_properties(jemalloc PROPERTIES IMPORTED_LOCATION - "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/jemalloc/lib/libjemalloc_pic.a") - add_dependencies(jemalloc build_jemalloc) - add_library(jemalloc_nopic STATIC IMPORTED GLOBAL) - set_target_properties(jemalloc_nopic PROPERTIES IMPORTED_LOCATION - "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/jemalloc/lib/libjemalloc.a") - add_dependencies(jemalloc_nopic build_jemalloc) - - # detect when we are being built as a subproject - if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING) - install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/jemalloc/lib" DESTINATION . - COMPONENT tokukv_libs_extra) - endif () - endif () -endif () - ## add lzma with an external project set(xz_configure_opts --with-pic --enable-static) if (APPLE) diff --git a/storage/tokudb/PerconaFT/portability/CMakeLists.txt b/storage/tokudb/PerconaFT/portability/CMakeLists.txt index f24cf84a829..f7a731bfb5a 100644 --- a/storage/tokudb/PerconaFT/portability/CMakeLists.txt +++ b/storage/tokudb/PerconaFT/portability/CMakeLists.txt @@ -20,7 +20,6 @@ target_link_libraries(${LIBTOKUPORTABILITY} LINK_PUBLIC ${CMAKE_THREAD_LIBS_INIT add_library(tokuportability_static_conv STATIC ${tokuportability_srcs}) set_target_properties(tokuportability_static_conv PROPERTIES POSITION_INDEPENDENT_CODE ON) -add_dependencies(tokuportability_static_conv build_jemalloc) set(tokuportability_source_libs tokuportability_static_conv ${LIBJEMALLOC} ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_SYSTEM_LIBS}) toku_merge_static_libs(${LIBTOKUPORTABILITY}_static ${LIBTOKUPORTABILITY}_static "${tokuportability_source_libs}") diff --git a/storage/tokudb/PerconaFT/scripts/run-nightly-coverage-tests.bash b/storage/tokudb/PerconaFT/scripts/run-nightly-coverage-tests.bash index cd5743cddf2..3daa87ce03c 100755 --- a/storage/tokudb/PerconaFT/scripts/run-nightly-coverage-tests.bash +++ b/storage/tokudb/PerconaFT/scripts/run-nightly-coverage-tests.bash @@ -26,7 +26,7 @@ if [ ! -d build ] ; then -D RUN_LONG_TESTS=ON \ -D TOKUDB_DATA=$tokudbdir/../tokudb.data \ .. - ninja build_jemalloc build_lzma build_snappy + ninja build_lzma build_snappy popd fi diff --git a/storage/tokudb/PerconaFT/scripts/run-nightly-drd-tests.bash b/storage/tokudb/PerconaFT/scripts/run-nightly-drd-tests.bash index 3c688581385..1ef819d8e37 100755 --- a/storage/tokudb/PerconaFT/scripts/run-nightly-drd-tests.bash +++ b/storage/tokudb/PerconaFT/scripts/run-nightly-drd-tests.bash @@ -25,7 +25,7 @@ if [ ! -d build ] ; then -D RUN_LONG_TESTS=ON \ -D TOKUDB_DATA=$tokudbdir/../tokudb.data \ .. - ninja build_jemalloc build_lzma build_snappy + ninja build_lzma build_snappy popd fi diff --git a/storage/tokudb/PerconaFT/scripts/run-nightly-release-tests.bash b/storage/tokudb/PerconaFT/scripts/run-nightly-release-tests.bash index 80938bad8a6..c1039a0b28f 100755 --- a/storage/tokudb/PerconaFT/scripts/run-nightly-release-tests.bash +++ b/storage/tokudb/PerconaFT/scripts/run-nightly-release-tests.bash @@ -25,7 +25,7 @@ if [ ! -d build ] ; then -D RUN_LONG_TESTS=ON \ -D TOKUDB_DATA=$tokudbdir/../tokudb.data \ .. - ninja build_jemalloc build_lzma build_snappy + ninja build_lzma build_snappy popd fi diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc index 251b8183ae5..32f3e77cf13 100644 --- a/storage/tokudb/ha_tokudb.cc +++ b/storage/tokudb/ha_tokudb.cc @@ -1075,7 +1075,8 @@ static inline int tokudb_generate_row(DB* dest_db, } buff = (uchar *)dest_key->data; - assert_always(buff != NULL && max_key_len > 0); + assert_always(buff != nullptr); + assert_always(max_key_len > 0); } else { assert_unreachable(); } diff --git a/storage/tokudb/ha_tokudb.h b/storage/tokudb/ha_tokudb.h index 6257583e754..1d1ea92868d 100644 --- a/storage/tokudb/ha_tokudb.h +++ b/storage/tokudb/ha_tokudb.h @@ -387,7 +387,8 @@ inline void TOKUDB_SHARE::init_cardinality_counts( assert_debug(_mutex.is_owned_by_me()); // can not change number of keys live - assert_always(_rec_per_key == NULL && _rec_per_keys == 0); + assert_always(_rec_per_key == nullptr); + assert_always(_rec_per_keys == 0); _rec_per_keys = rec_per_keys; _rec_per_key = rec_per_key; } diff --git a/storage/tokudb/hatoku_cmp.cc b/storage/tokudb/hatoku_cmp.cc index f064a125649..16393aa43b6 100644 --- a/storage/tokudb/hatoku_cmp.cc +++ b/storage/tokudb/hatoku_cmp.cc @@ -954,9 +954,8 @@ static inline int tokudb_compare_two_hidden_keys( const void* saved_key_data, const uint32_t saved_key_size ) { - assert_always( - (new_key_size >= TOKUDB_HIDDEN_PRIMARY_KEY_LENGTH) && - (saved_key_size >= TOKUDB_HIDDEN_PRIMARY_KEY_LENGTH)); + assert_always(new_key_size >= TOKUDB_HIDDEN_PRIMARY_KEY_LENGTH); + assert_always(saved_key_size >= TOKUDB_HIDDEN_PRIMARY_KEY_LENGTH); ulonglong a = hpk_char_to_num((uchar *) new_key_data); ulonglong b = hpk_char_to_num((uchar *) saved_key_data); return a < b ? -1 : (a > b ? 1 : 0); @@ -2534,7 +2533,8 @@ static uint32_t create_toku_secondary_key_pack_descriptor ( bool is_col_in_pk = false; if (bitmap_is_set(&kc_info->key_filters[pk_index],field_index)) { - assert_always(!has_hpk && prim_key != NULL); + assert_always(!has_hpk); + assert_always(prim_key != nullptr); is_col_in_pk = true; } else { diff --git a/storage/tokudb/tests/math_test_int.cc b/storage/tokudb/tests/math_test_int.cc index 10085dbd704..3313bdf5895 100644 --- a/storage/tokudb/tests/math_test_int.cc +++ b/storage/tokudb/tests/math_test_int.cc @@ -54,16 +54,20 @@ static void test_int8() { assert(over); else if (m < -max) assert(over); - else - assert(!over && n == m); + else { + assert(!over); + assert(n == m); + } n = int_sub(x, y, 8, &over); m = x - y; if (m > max-1) assert(over); else if (m < -max) assert(over); - else - assert(!over && n == m); + else { + assert(!over); + asset(n == m); + } } } } @@ -82,16 +86,20 @@ static void test_int16() { assert(over); else if (m < -max) assert(over); - else - assert(!over && n == m); + else { + assert(!over); + assert(n == m); + } n = int_sub(x, y, 16, &over); m = x - y; if (m > max-1) assert(over); else if (m < -max) assert(over); - else - assert(!over && n == m); + else { + assert(!over); + assert(n == m); + } } } } @@ -104,20 +112,42 @@ static void test_int24() { s = int_add(1, (1ULL<<23)-1, 24, &over); assert(over); s = int_add((1ULL<<23)-1, 1, 24, &over); assert(over); - s = int_sub(-1, (1ULL<<23), 24, &over); assert(!over && s == (1ULL<<23)-1); + s = int_sub(-1, (1ULL<<23), 24, &over); + assert(!over); + assert(s == (1ULL<<23)-1); s = int_sub((1ULL<<23), 1, 24, &over); assert(over); - s = int_add(0, 0, 24, &over); assert(!over && s == 0); - s = int_sub(0, 0, 24, &over); assert(!over && s == 0); - s = int_add(0, -1, 24, &over); assert(!over && s == -1); - s = int_sub(0, 1, 24, &over); assert(!over && s == -1); - s = int_add(0, (1ULL<<23), 24, &over); assert(!over && (s & ((1ULL<<24)-1)) == (1ULL<<23)); - s = int_sub(0, (1ULL<<23)-1, 24, &over); assert(!over && (s & ((1ULL<<24)-1)) == (1ULL<<23)+1); + s = int_add(0, 0, 24, &over); + assert(!over); + assert(s == 0); + s = int_sub(0, 0, 24, &over); + assert(!over); + assert(s == 0); + s = int_add(0, -1, 24, &over); + assert(!over); + assert(s == -1); + s = int_sub(0, 1, 24, &over); + assert(!over); + assert(s == -1); + s = int_add(0, (1ULL<<23), 24, &over); + assert(!over); + assert((s & ((1ULL<<24)-1)) == (1ULL<<23)); + s = int_sub(0, (1ULL<<23)-1, 24, &over); + assert(!over); + assert((s & ((1ULL<<24)-1)) == (1ULL<<23)+1); - s = int_add(-1, 0, 24, &over); assert(!over && s == -1); - s = int_add(-1, 1, 24, &over); assert(!over && s == 0); - s = int_sub(-1, -1, 24, &over); assert(!over && s == 0); - s = int_sub(-1, (1ULL<<23)-1, 24, &over); assert(!over && (s & ((1ULL<<24)-1)) == (1ULL<<23)); + s = int_add(-1, 0, 24, &over); + assert(!over); + assert(s == -1); + s = int_add(-1, 1, 24, &over); + assert(!over); + assert(s == 0); + s = int_sub(-1, -1, 24, &over); + assert(!over); + assert(s == 0); + s = int_sub(-1, (1ULL<<23)-1, 24, &over); + assert(!over); + assert((s & ((1ULL<<24)-1)) == (1ULL<<23)); } static void test_int32() { @@ -128,20 +158,42 @@ static void test_int32() { s = int_add(1, (1ULL<<31)-1, 32, &over); assert(over); s = int_add((1ULL<<31)-1, 1, 32, &over); assert(over); - s = int_sub(-1, (1ULL<<31), 32, &over); assert(s == (1ULL<<31)-1 && !over); + s = int_sub(-1, (1ULL<<31), 32, &over); + assert(s == (1ULL<<31)-1); + assert(!over); s = int_sub((1ULL<<31), 1, 32, &over); assert(over); - s = int_add(0, 0, 32, &over); assert(s == 0 && !over); - s = int_sub(0, 0, 32, &over); assert(s == 0 && !over); - s = int_add(0, -1, 32, &over); assert(s == -1 && !over); - s = int_sub(0, 1, 32, &over); assert(s == -1 && !over); - s = int_add(0, (1ULL<<31), 32, &over); assert((s & ((1ULL<<32)-1)) == (1ULL<<31) && !over); - s = int_sub(0, (1ULL<<31)-1, 32, &over); assert((s & ((1ULL<<32)-1)) == (1ULL<<31)+1 && !over); + s = int_add(0, 0, 32, &over); + assert(s == 0); + assert(!over); + s = int_sub(0, 0, 32, &over); + assert(s == 0); + assert(!over); + s = int_add(0, -1, 32, &over); + assert(s == -1); + assert(!over); + s = int_sub(0, 1, 32, &over); + assert(s == -1); + assert(!over); + s = int_add(0, (1ULL<<31), 32, &over); + assert((s & ((1ULL<<32)-1)) == (1ULL<<31)); + assert(!over); + s = int_sub(0, (1ULL<<31)-1, 32, &over); + assert((s & ((1ULL<<32)-1)) == (1ULL<<31)+1); + assert(!over); - s = int_add(-1, 0, 32, &over); assert(s == -1 && !over); - s = int_add(-1, 1, 32, &over); assert(s == 0 && !over); - s = int_sub(-1, -1, 32, &over); assert(s == 0 && !over); - s = int_sub(-1, (1ULL<<31)-1, 32, &over); assert((s & ((1ULL<<32)-1)) == (1ULL<<31) && !over); + s = int_add(-1, 0, 32, &over); + assert(s == -1); + assert(!over); + s = int_add(-1, 1, 32, &over); + assert(s == 0); + assert(!over); + s = int_sub(-1, -1, 32, &over); + assert(s == 0); + assert(!over); + s = int_sub(-1, (1ULL<<31)-1, 32, &over); + assert((s & ((1ULL<<32)-1)) == (1ULL<<31)); + assert(!over); } static void test_int64() { @@ -152,20 +204,42 @@ static void test_int64() { s = int_add(1, (1ULL<<63)-1, 64, &over); assert(over); s = int_add((1ULL<<63)-1, 1, 64, &over); assert(over); - s = int_sub(-1, (1ULL<<63), 64, &over); assert(s == (1ULL<<63)-1 && !over); + s = int_sub(-1, (1ULL<<63), 64, &over); + assert(s == (1ULL<<63)-1); + assert(!over); s = int_sub((1ULL<<63), 1, 64, &over); assert(over); - s = int_add(0, 0, 64, &over); assert(s == 0 && !over); - s = int_sub(0, 0, 64, &over); assert(s == 0 && !over); - s = int_add(0, -1, 64, &over); assert(s == -1 && !over); - s = int_sub(0, 1, 64, &over); assert(s == -1 && !over); - s = int_add(0, (1ULL<<63), 64, &over); assert(s == (int64_t)(1ULL<<63) && !over); - s = int_sub(0, (1ULL<<63)-1, 64, &over); assert(s == (int64_t)((1ULL<<63)+1) && !over); + s = int_add(0, 0, 64, &over); + assert(s == 0); + assert(!over); + s = int_sub(0, 0, 64, &over); + assert(s == 0); + assert(!over); + s = int_add(0, -1, 64, &over); + assert(s == -1); + assert(!over); + s = int_sub(0, 1, 64, &over); + assert(s == -1); + assert(!over); + s = int_add(0, (1ULL<<63), 64, &over); + assert(s == (int64_t)(1ULL<<63)); + assert(!over); + s = int_sub(0, (1ULL<<63)-1, 64, &over); + assert(s == (int64_t)((1ULL<<63)+1)); + assert(!over); - s = int_add(-1, 0, 64, &over); assert(s == -1 && !over); - s = int_add(-1, 1, 64, &over); assert(s == 0 && !over); - s = int_sub(-1, -1, 64, &over); assert(s == 0 && !over); - s = int_sub(-1, (1ULL<<63)-1, 64, &over); assert(s == (int64_t)(1ULL<<63) && !over); + s = int_add(-1, 0, 64, &over); + assert(s == -1); + assert(!over); + s = int_add(-1, 1, 64, &over); + assert(s == 0); + assert(!over); + s = int_sub(-1, -1, 64, &over); + assert(s == 0); + assert(!over); + s = int_sub(-1, (1ULL<<63)-1, 64, &over); + assert(s == (int64_t)(1ULL<<63)); + assert(!over); } static void test_int_sign(uint length_bits) { diff --git a/storage/tokudb/tests/math_test_uint.cc b/storage/tokudb/tests/math_test_uint.cc index 2fc8de8e093..2c5c9261c89 100644 --- a/storage/tokudb/tests/math_test_uint.cc +++ b/storage/tokudb/tests/math_test_uint.cc @@ -51,14 +51,18 @@ static void test_uint8() { m = x + y; if (m > (1ULL<<8)-1) assert(over); - else - assert(!over && n == (m % 256)); + else { + assert(!over); + assert(n == (m % 256)); + } n = uint_sub(x, y, 8, &over); m = x - y; if (m > x) assert(over); - else - assert(!over && n == (m % 256)); + else { + assert(!over); + assert(n == (m % 256)); + } } } } @@ -75,14 +79,18 @@ static void test_uint16() { m = x + y; if (m > (1ULL<<16)-1) assert(over); - else - assert(!over && n == (m % (1ULL<<16))); + else { + assert(!over); + assert(n == (m % (1ULL<<16))); + } n = uint_sub(x, y, 16, &over); m = x - y; if (m > x) assert(over); - else - assert(!over && n == (m % (1ULL<<16))); + else { + assert(!over); + assert(n == (m % (1ULL<<16))); + } } } } @@ -95,13 +103,23 @@ static void test_uint24() { s = uint_add((1ULL<<24)-1, (1ULL<<24)-1, 24, &over); assert(over); s = uint_add((1ULL<<24)-1, 1, 24, &over); assert(over); - s = uint_add((1ULL<<24)-1, 0, 24, &over); assert(!over && s == (1ULL<<24)-1); - s = uint_add(0, 1, 24, &over); assert(!over && s == 1); - s = uint_add(0, 0, 24, &over); assert(!over && s == 0); - s = uint_sub(0, 0, 24, &over); assert(!over && s == 0); + s = uint_add((1ULL<<24)-1, 0, 24, &over); + assert(!over); + assert(s == (1ULL<<24)-1); + s = uint_add(0, 1, 24, &over); + assert(!over); + assert(s == 1); + s = uint_add(0, 0, 24, &over); + assert(!over); + assert(s == 0); + s = uint_sub(0, 0, 24, &over); + assert(!over); + assert(s == 0); s = uint_sub(0, 1, 24, &over); assert(over); s = uint_sub(0, (1ULL<<24)-1, 24, &over); assert(over); - s = uint_sub((1ULL<<24)-1, (1ULL<<24)-1, 24, &over); assert(!over && s == 0); + s = uint_sub((1ULL<<24)-1, (1ULL<<24)-1, 24, &over); + assert(!over); + assert(s == 0); } static void test_uint32() { @@ -112,13 +130,23 @@ static void test_uint32() { s = uint_add((1ULL<<32)-1, (1ULL<<32)-1, 32, &over); assert(over); s = uint_add((1ULL<<32)-1, 1, 32, &over); assert(over); - s = uint_add((1ULL<<32)-1, 0, 32, &over); assert(!over && s == (1ULL<<32)-1); - s = uint_add(0, 1, 32, &over); assert(!over && s == 1); - s = uint_add(0, 0, 32, &over); assert(!over && s == 0); - s = uint_sub(0, 0, 32, &over); assert(!over && s == 0); + s = uint_add((1ULL<<32)-1, 0, 32, &over); + assert(!over); + assert(s == (1ULL<<32)-1); + s = uint_add(0, 1, 32, &over); + assert(!over); + assert(s == 1); + s = uint_add(0, 0, 32, &over); + assert(!over); + assert(s == 0); + s = uint_sub(0, 0, 32, &over); + assert(!over); + assert(s == 0); s = uint_sub(0, 1, 32, &over); assert(over); s = uint_sub(0, (1ULL<<32)-1, 32, &over); assert(over); - s = uint_sub((1ULL<<32)-1, (1ULL<<32)-1, 32, &over); assert(!over && s == 0); + s = uint_sub((1ULL<<32)-1, (1ULL<<32)-1, 32, &over); + assert(!over); + assert(s == 0); } static void test_uint64() { @@ -129,13 +157,23 @@ static void test_uint64() { s = uint_add(~0ULL, ~0ULL, 64, &over); assert(over); s = uint_add(~0ULL, 1, 64, &over); assert(over); - s = uint_add(~0ULL, 0, 64, &over); assert(!over && s == ~0ULL); - s = uint_add(0, 1, 64, &over); assert(!over && s == 1); - s = uint_add(0, 0, 64, &over); assert(!over && s == 0); - s = uint_sub(0, 0, 64, &over); assert(!over && s == 0); + s = uint_add(~0ULL, 0, 64, &over); + assert(!over); + assert(s == ~0ULL); + s = uint_add(0, 1, 64, &over); + assert(!over); + assert(s == 1); + s = uint_add(0, 0, 64, &over); + assert(!over); + assert(s == 0); + s = uint_sub(0, 0, 64, &over); + assert(!over); + assert(s == 0); s = uint_sub(0, 1, 64, &over); assert(over); s = uint_sub(0, ~0ULL, 64, &over); assert(over); - s = uint_sub(~0ULL, ~0ULL, 64, &over); assert(!over && s == 0); + s = uint_sub(~0ULL, ~0ULL, 64, &over); + assert(!over); + assert(s == 0); } int main() { diff --git a/storage/tokudb/tests/sint_test.cc b/storage/tokudb/tests/sint_test.cc index 9078ae87281..7823ee5a692 100644 --- a/storage/tokudb/tests/sint_test.cc +++ b/storage/tokudb/tests/sint_test.cc @@ -27,7 +27,6 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include #include #include -#include #include #include diff --git a/storage/tokudb/tests/tokudb_buffer_test.cc b/storage/tokudb/tests/tokudb_buffer_test.cc index a786cdf4592..7e296790d39 100644 --- a/storage/tokudb/tests/tokudb_buffer_test.cc +++ b/storage/tokudb/tests/tokudb_buffer_test.cc @@ -32,9 +32,13 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. static void test_null() { tokudb::buffer b; - assert(b.data() == NULL && b.size() == 0 && b.limit() == 0); + assert(b.data() == nullptr); + assert(b.size() == 0); + assert(b.limit() == 0); b.append(NULL, 0); - assert(b.data() == NULL && b.size() == 0 && b.limit() == 0); + assert(b.data() == nullptr); + assert(b.size() == 0); + assert(b.limit() == 0); } static void append_az(tokudb::buffer &b) { @@ -132,7 +136,8 @@ static void test_replace_grow() { } for (size_t i = 0; i < a.size()/2; i++) { unsigned char *cp = (unsigned char *) a.data() + 2*i; - assert(cp[0] == 'a'+i && cp[1] == 'a'+i); + assert(cp[0] == 'a'+i); + assert(cp[1] == 'a'+i); } } diff --git a/storage/tokudb/tests/uint_test.cc b/storage/tokudb/tests/uint_test.cc index b2c653b8fdd..e3aa1a6fe2f 100644 --- a/storage/tokudb/tests/uint_test.cc +++ b/storage/tokudb/tests/uint_test.cc @@ -27,7 +27,6 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include #include #include -#include #include #include diff --git a/storage/tokudb/tests/vlq_test.cc b/storage/tokudb/tests/vlq_test.cc index 80d797339b4..12b222f06c1 100644 --- a/storage/tokudb/tests/vlq_test.cc +++ b/storage/tokudb/tests/vlq_test.cc @@ -52,7 +52,8 @@ static void test_vlq_uint32_error(void) { in_s = tokudb::vlq_decode_ui(&n, b, 1); assert(in_s == 0); in_s = tokudb::vlq_decode_ui(&n, b, 2); - assert(in_s == 2 && n == 128); + assert(in_s == 2); + assert(n == 128); } static void test_80000000(void) { @@ -63,7 +64,8 @@ static void test_80000000(void) { out_s = tokudb::vlq_encode_ui(v, b, sizeof b); assert(out_s == 5); in_s = tokudb::vlq_decode_ui(&n, b, out_s); - assert(in_s == 5 && n == v); + assert(in_s == 5); + assert(n == v); } static void test_100000000(void) { @@ -74,7 +76,8 @@ static void test_100000000(void) { out_s = tokudb::vlq_encode_ui(v, b, sizeof b); assert(out_s == 5); in_s = tokudb::vlq_decode_ui(&n, b, out_s); - assert(in_s == 5 && n == v); + assert(in_s == 5); + assert(n == v); } int main(void) { diff --git a/storage/tokudb/tests/vlq_test_uint32.cc b/storage/tokudb/tests/vlq_test_uint32.cc index c5661b33ab5..3cc8af771a9 100644 --- a/storage/tokudb/tests/vlq_test_uint32.cc +++ b/storage/tokudb/tests/vlq_test_uint32.cc @@ -44,7 +44,8 @@ static void test_vlq_uint32(void) { assert(out_s == 1); uint32_t n; size_t in_s = tokudb::vlq_decode_ui(&n, b, out_s); - assert(in_s == 1 && n == v); + assert(in_s == 1); + assert(n == v); } printf("%u\n", 1<<7); @@ -54,7 +55,8 @@ static void test_vlq_uint32(void) { assert(out_s == 2); uint32_t n; size_t in_s = tokudb::vlq_decode_ui(&n, b, out_s); - assert(in_s == 2 && n == v); + assert(in_s == 2); + assert(n == v); } printf("%u\n", 1<<14); @@ -64,7 +66,8 @@ static void test_vlq_uint32(void) { assert(out_s == 3); uint32_t n; size_t in_s = tokudb::vlq_decode_ui(&n, b, out_s); - assert(in_s == 3 && n == v); + assert(in_s == 3); + assert(n == v); } printf("%u\n", 1<<21); @@ -74,7 +77,8 @@ static void test_vlq_uint32(void) { assert(out_s == 4); uint32_t n; size_t in_s = tokudb::vlq_decode_ui(&n, b, out_s); - assert(in_s == 4 && n == v); + assert(in_s == 4); + assert(n == v); } printf("%u\n", 1<<28); @@ -84,7 +88,8 @@ static void test_vlq_uint32(void) { assert(out_s == 5); uint32_t n; size_t in_s = tokudb::vlq_decode_ui(&n, b, out_s); - assert(in_s == 5 && n == v); + assert(in_s == 5); + assert(n == v); } } diff --git a/storage/tokudb/tests/vlq_test_uint64.cc b/storage/tokudb/tests/vlq_test_uint64.cc index a626db69487..697c597756c 100644 --- a/storage/tokudb/tests/vlq_test_uint64.cc +++ b/storage/tokudb/tests/vlq_test_uint64.cc @@ -46,7 +46,8 @@ static void test_vlq_uint64(uint64_t start, uint64_t stride) { assert(out_s == 1); uint64_t n; size_t in_s = tokudb::vlq_decode_ui(&n, b, out_s); - assert(in_s == 1 && n == v); + assert(in_s == 1); + assert(n == v); } printf("%u\n", 1<<7); @@ -56,7 +57,8 @@ static void test_vlq_uint64(uint64_t start, uint64_t stride) { assert(out_s == 2); uint64_t n; size_t in_s = tokudb::vlq_decode_ui(&n, b, out_s); - assert(in_s == 2 && n == v); + assert(in_s == 2); + assert(n == v); } printf("%u\n", 1<<14); @@ -66,7 +68,8 @@ static void test_vlq_uint64(uint64_t start, uint64_t stride) { assert(out_s == 3); uint64_t n; size_t in_s = tokudb::vlq_decode_ui(&n, b, out_s); - assert(in_s == 3 && n == v); + assert(in_s == 3); + assert(n == v); } printf("%u\n", 1<<21); @@ -76,7 +79,8 @@ static void test_vlq_uint64(uint64_t start, uint64_t stride) { assert(out_s == 4); uint64_t n; size_t in_s = tokudb::vlq_decode_ui(&n, b, out_s); - assert(in_s == 4 && n == v); + assert(in_s == 4); + assert(n == v); } printf("%u\n", 1<<28); @@ -90,7 +94,8 @@ static void test_vlq_uint64(uint64_t start, uint64_t stride) { assert(out_s == 5); uint64_t n; size_t in_s = tokudb::vlq_decode_ui(&n, b, out_s); - assert(in_s == 5 && n == v); + assert(in_s == 5); + assert(n == v); } } diff --git a/storage/tokudb/tokudb_buffer.h b/storage/tokudb/tokudb_buffer.h index 022f1b49643..1605543c378 100644 --- a/storage/tokudb/tokudb_buffer.h +++ b/storage/tokudb/tokudb_buffer.h @@ -134,8 +134,8 @@ public: char* data_offset = (char*)m_data + offset; if (new_s != old_s) { size_t n = m_size - (offset + old_s); - assert_always( - offset + new_s + n <= m_limit && offset + old_s + n <= m_limit); + assert_always(offset + new_s + n <= m_limit); + assert_always(offset + old_s + n <= m_limit); memmove(data_offset + new_s, data_offset + old_s, n); if (new_s > old_s) m_size += new_s - old_s; diff --git a/storage/tokudb/tokudb_math.h b/storage/tokudb/tokudb_math.h index 0338bf3871e..99cebd5b1d1 100644 --- a/storage/tokudb/tokudb_math.h +++ b/storage/tokudb/tokudb_math.h @@ -59,7 +59,8 @@ TOKUDB_UNUSED(static uint64_t uint_add( bool* over)); static uint64_t uint_add(uint64_t x, uint64_t y, uint length_bits, bool *over) { uint64_t mask = uint_mask(length_bits); - assert_always((x & ~mask) == 0 && (y & ~mask) == 0); + assert_always((x & ~mask) == 0); + assert_always((y & ~mask) == 0); uint64_t s = (x + y) & mask; *over = s < x; // check for overflow return s; @@ -75,7 +76,8 @@ TOKUDB_UNUSED(static uint64_t uint_sub( bool* over)); static uint64_t uint_sub(uint64_t x, uint64_t y, uint length_bits, bool *over) { uint64_t mask = uint_mask(length_bits); - assert_always((x & ~mask) == 0 && (y & ~mask) == 0); + assert_always((x & ~mask) == 0); + assert_always((y & ~mask) == 0); uint64_t s = (x - y) & mask; *over = s > x; // check for overflow return s; From b8eff8bce4505478dcb1981d344d917782c6e226 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Wed, 30 Oct 2019 13:23:15 +0300 Subject: [PATCH 11/15] avoid accessing TLS --- sql/sql_show.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index c63b8b0f8a8..fbdb76e9e71 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -7708,7 +7708,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) item->maybe_null= (fields_info->field_flags & MY_I_S_MAYBE_NULL); field_count++; } - TMP_TABLE_PARAM *tmp_table_param = new TMP_TABLE_PARAM; + TMP_TABLE_PARAM *tmp_table_param = new (thd->mem_root) TMP_TABLE_PARAM; tmp_table_param->init(); tmp_table_param->table_charset= cs; tmp_table_param->field_count= field_count; From d1e6b0bcff0148f474e38002d5c1198726fe7970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 30 Oct 2019 12:36:57 +0200 Subject: [PATCH 12/15] MDEV-20927 Duplicate key with auto increment Apply the changes to InnoDB and XtraDB that had been inadvertently skipped in the merge commit ae476868a5394041a00e75a29c7d45917e8dfae8 That merge failure sabotaged part of MDEV-20127: >Revert a problematic auto_increment_increment 'fix' from 2014. >This involves replacing the MDEV-8827 fix and in 10.1, >removing some WSREP instrumentation. The code changes were re-merged manually by executing the following: # Get the parent of the problematic merge. git checkout ae476868a5394041a00e75a29c7d45917e8dfae8^ # Perform the merge again. git merge ae476868a5394041a00e75a29c7d45917e8dfae8^2 # Get the conflict resolution from that merge. git checkout ae476868a5394041a00e75a29c7d45917e8dfae8 . # Note: Any changes to these files were removed (empty diff)! git diff HEAD storage/{innobase,xtradb}/handler/ha_innodb.cc # Apply the code changes: git diff cf40393471b10ca68cc1d2804c22ab9203900978^2..MERGE_HEAD \ storage/{innobase,xtradb}/handler/ha_innodb.cc| patch -p1 --- .../innodb/r/innodb-alter-autoinc.result | 6 +- .../suite/innodb/r/innodb-autoinc.result | 24 ++++---- mysql-test/suite/innodb/t/innodb-autoinc.test | 2 +- storage/innobase/handler/ha_innodb.cc | 58 +++++++++++-------- storage/xtradb/handler/ha_innodb.cc | 58 +++++++++++-------- 5 files changed, 84 insertions(+), 64 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-alter-autoinc.result b/mysql-test/suite/innodb/r/innodb-alter-autoinc.result index 82eb448fe45..c3ae453486a 100644 --- a/mysql-test/suite/innodb/r/innodb-alter-autoinc.result +++ b/mysql-test/suite/innodb/r/innodb-alter-autoinc.result @@ -148,7 +148,7 @@ t1 CREATE TABLE `t1` ( `id` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`), KEY `id` (`id`,`a`) -) ENGINE=InnoDB AUTO_INCREMENT=75 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=70 DEFAULT CHARSET=latin1 INSERT INTO t1 SET a=123; INSERT INTO t1 VALUES(-123,-45); ALTER TABLE t1 AUTO_INCREMENT = 75; @@ -161,8 +161,8 @@ a id 123 55 347 60 33101 65 +123 70 123 75 -123 80 SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -170,5 +170,5 @@ t1 CREATE TABLE `t1` ( `id` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`), KEY `id` (`id`,`a`) -) ENGINE=InnoDB AUTO_INCREMENT=85 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=80 DEFAULT CHARSET=latin1 DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb-autoinc.result b/mysql-test/suite/innodb/r/innodb-autoinc.result index 2c428b0ba1a..f2e2e087818 100644 --- a/mysql-test/suite/innodb/r/innodb-autoinc.result +++ b/mysql-test/suite/innodb/r/innodb-autoinc.result @@ -567,7 +567,7 @@ Variable_name Value auto_increment_increment 65535 auto_increment_offset 65535 INSERT INTO t1 VALUES (NULL),(NULL); -ERROR HY000: Failed to read auto-increment value from storage engine +ERROR 22003: Out of range value for column 'c1' at row 1 SELECT * FROM t1; c1 1 @@ -674,7 +674,7 @@ SELECT a,b FROM t; a b 1 S1 3 S2 -4 S2 +5 S2 # Client 1: Insert a record with auto_increment_increment=1 SET SESSION auto_increment_increment=1; SHOW CREATE TABLE t; @@ -683,14 +683,14 @@ t CREATE TABLE `t` ( `a` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `b` varchar(200) DEFAULT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 INSERT INTO t(b) VALUES('S1'); SELECT a,b FROM t; a b 1 S1 3 S2 -4 S2 -5 S1 +5 S2 +6 S1 DROP TABLE t; # Autoincrement behaviour with mixed insert. CREATE TABLE t( @@ -728,22 +728,22 @@ t CREATE TABLE `t` ( `a` tinyint(4) NOT NULL AUTO_INCREMENT, `b` varchar(200) DEFAULT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=latin1 INSERT INTO t(b) VALUES('S4'); SELECT * FROM t; a b 1 S0 11 S1 -22 S3 -23 S4 28 S2 +31 S3 +32 S4 SHOW CREATE TABLE t; Table Create Table t CREATE TABLE `t` ( `a` tinyint(4) NOT NULL AUTO_INCREMENT, `b` varchar(200) DEFAULT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=latin1 DROP TABLE t; SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=5; DROP TABLE IF EXISTS t1; @@ -784,7 +784,7 @@ t2 CREATE TABLE `t2` ( `n` int(10) unsigned NOT NULL, `o` enum('FALSE','TRUE') DEFAULT NULL, PRIMARY KEY (`m`) -) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=latin1 INSERT INTO t1 (b,c) SELECT n,o FROM t2 ; SHOW CREATE TABLE t1; Table Create Table @@ -1464,13 +1464,13 @@ SELECT * FROM t; i 1 301 -351 +601 SHOW CREATE TABLE t; Table Create Table t CREATE TABLE `t` ( `i` int(11) NOT NULL AUTO_INCREMENT, KEY `i` (`i`) -) ENGINE=InnoDB AUTO_INCREMENT=401 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=651 DEFAULT CHARSET=latin1 DROP TABLE t; # # MDEV-14008 Assertion failing: `!is_set() || (m_status == DA_OK_BULK && is_bulk_op()) diff --git a/mysql-test/suite/innodb/t/innodb-autoinc.test b/mysql-test/suite/innodb/t/innodb-autoinc.test index 8b202f5db6b..b14d6db7f5d 100644 --- a/mysql-test/suite/innodb/t/innodb-autoinc.test +++ b/mysql-test/suite/innodb/t/innodb-autoinc.test @@ -349,7 +349,7 @@ INSERT INTO t1 VALUES (18446744073709551610); #-- 2^64 - 2 SELECT * FROM t1; SET @@SESSION.AUTO_INCREMENT_INCREMENT=1152921504606846976, @@SESSION.AUTO_INCREMENT_OFFSET=1152921504606846976; SHOW VARIABLES LIKE "auto_inc%"; ---error 1467 +--error HA_ERR_AUTOINC_ERANGE INSERT INTO t1 VALUES (NULL),(NULL); SELECT * FROM t1; DROP TABLE t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index fd8f0d3787f..ed15c704373 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2019, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. @@ -2588,11 +2588,10 @@ innobase_next_autoinc( if (next_value == 0) { ulonglong next; - if (current >= offset) { + if (current > offset) { next = (current - offset) / step; } else { - next = 0; - block -= step; + next = (offset - current) / step; } ut_a(max_value > next); @@ -16035,6 +16034,37 @@ ha_innobase::get_auto_increment( ut_ad(autoinc > 0); } + /** The following logic is needed to avoid duplicate key error + for autoincrement column. + + (1) InnoDB gives the current autoincrement value with respect + to increment and offset value. + + (2) Basically it does compute_next_insert_id() logic inside InnoDB + to avoid the current auto increment value changed by handler layer. + + (3) It is restricted only for insert operations. */ + + if (increment > 1 && thd_sql_command(user_thd) != SQLCOM_ALTER_TABLE + && autoinc < col_max_value) { + + ulonglong prev_auto_inc = autoinc; + + autoinc = ((autoinc - 1) + increment - offset)/ increment; + + autoinc = autoinc * increment + offset; + + /* If autoinc exceeds the col_max_value then reset + to old autoinc value. Because in case of non-strict + sql mode, boundary value is not considered as error. */ + + if (autoinc >= col_max_value) { + autoinc = prev_auto_inc; + } + + ut_ad(autoinc > 0); + } + /* Called for the first time ? */ if (trx->n_autoinc_rows == 0) { @@ -16072,26 +16102,6 @@ ha_innobase::get_auto_increment( current = *first_value; - if (prebuilt->autoinc_increment != increment) { - - WSREP_DEBUG("autoinc decrease: %llu -> %llu\n" - "THD: %ld, current: %llu, autoinc: %llu", - prebuilt->autoinc_increment, - increment, - thd_get_thread_id(ha_thd()), - current, autoinc); - if (!wsrep_on(ha_thd())) - { - current = autoinc - prebuilt->autoinc_increment; - current = innobase_next_autoinc( - current, 1, increment, offset, col_max_value); - } - - dict_table_autoinc_initialize(prebuilt->table, current); - - *first_value = current; - } - /* Compute the last value in the interval */ next_value = innobase_next_autoinc( current, *nb_reserved_values, increment, offset, diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 55e231ef770..ccaeadce932 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2019, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2013, 2018, MariaDB Corporation. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -2899,11 +2899,10 @@ innobase_next_autoinc( if (next_value == 0) { ulonglong next; - if (current >= offset) { + if (current > offset) { next = (current - offset) / step; } else { - next = 0; - block -= step; + next = (offset - current) / step; } ut_a(max_value > next); @@ -16673,6 +16672,37 @@ ha_innobase::get_auto_increment( ut_ad(autoinc > 0); } + /** The following logic is needed to avoid duplicate key error + for autoincrement column. + + (1) InnoDB gives the current autoincrement value with respect + to increment and offset value. + + (2) Basically it does compute_next_insert_id() logic inside InnoDB + to avoid the current auto increment value changed by handler layer. + + (3) It is restricted only for insert operations. */ + + if (increment > 1 && thd_sql_command(user_thd) != SQLCOM_ALTER_TABLE + && autoinc < col_max_value) { + + ulonglong prev_auto_inc = autoinc; + + autoinc = ((autoinc - 1) + increment - offset)/ increment; + + autoinc = autoinc * increment + offset; + + /* If autoinc exceeds the col_max_value then reset + to old autoinc value. Because in case of non-strict + sql mode, boundary value is not considered as error. */ + + if (autoinc >= col_max_value) { + autoinc = prev_auto_inc; + } + + ut_ad(autoinc > 0); + } + /* Called for the first time ? */ if (trx->n_autoinc_rows == 0) { @@ -16710,26 +16740,6 @@ ha_innobase::get_auto_increment( current = *first_value; - if (prebuilt->autoinc_increment != increment) { - - WSREP_DEBUG("autoinc decrease: %llu -> %llu\n" - "THD: %ld, current: %llu, autoinc: %llu", - prebuilt->autoinc_increment, - increment, - thd_get_thread_id(ha_thd()), - current, autoinc); - if (!wsrep_on(ha_thd())) - { - current = autoinc - prebuilt->autoinc_increment; - current = innobase_next_autoinc( - current, 1, increment, offset, col_max_value); - } - - dict_table_autoinc_initialize(prebuilt->table, current); - - *first_value = current; - } - /* Compute the last value in the interval */ next_value = innobase_next_autoinc( current, *nb_reserved_values, increment, offset, From d03a59c6ff3c07deff8b3067a97e8f126e294b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 30 Oct 2019 11:56:05 +0200 Subject: [PATCH 13/15] XtraDB 5.6.45-86.1 --- .../sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff | 2 +- .../suite/sys_vars/r/sysvars_innodb,xtradb.rdiff | 2 +- storage/xtradb/buf/buf0buf.cc | 3 ++- storage/xtradb/handler/ha_innodb.cc | 11 ++++++----- storage/xtradb/include/btr0sea.ic | 4 ++-- storage/xtradb/include/ha_prototypes.h | 2 +- storage/xtradb/include/sync0rw.ic | 3 ++- storage/xtradb/include/univ.i | 4 ++-- storage/xtradb/lock/lock0wait.cc | 1 + storage/xtradb/log/log0online.cc | 7 +++---- storage/xtradb/ut/ut0ut.cc | 1 - 11 files changed, 21 insertions(+), 19 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff index 8b8c69d05bf..ff3f5ba1d2c 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff @@ -1215,7 +1215,7 @@ VARIABLE_NAME INNODB_VERSION SESSION_VALUE NULL -GLOBAL_VALUE 5.6.45 -+GLOBAL_VALUE 5.6.44-86.0 ++GLOBAL_VALUE 5.6.45-86.1 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff index d5a5a0147f5..77e8fb638a1 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff @@ -685,7 +685,7 @@ VARIABLE_NAME INNODB_VERSION SESSION_VALUE NULL -GLOBAL_VALUE 5.6.45 -+GLOBAL_VALUE 5.6.44-86.0 ++GLOBAL_VALUE 5.6.45-86.1 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc index 09db5188245..6ddcc3521da 100644 --- a/storage/xtradb/buf/buf0buf.cc +++ b/storage/xtradb/buf/buf0buf.cc @@ -124,7 +124,8 @@ _increment_page_get_statistics(buf_block_t* block, trx_t* trx) byte block_hash_offset; ut_ad(block); - ut_ad(trx && trx->take_stats); + ut_ad(trx); + ut_ad(trx->take_stats); if (!trx->distinct_page_access_hash) { trx->distinct_page_access_hash diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index ccaeadce932..788f039f1c8 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -2136,12 +2136,13 @@ UNIV_INTERN ulong thd_flush_log_at_trx_commit( /*================================*/ - void* thd) + THD* thd) { /* THDVAR cannot be used in xtrabackup, plugin variables for innodb are not loaded, this makes xtrabackup crash when trying to use them. */ - return (thd || !IS_XTRABACKUP())? THDVAR((THD*)thd, flush_log_at_trx_commit) : FALSE; + return (thd || !IS_XTRABACKUP()) + ? THDVAR(thd, flush_log_at_trx_commit) : 0; } /********************************************************************//** @@ -19003,7 +19004,7 @@ innodb_sched_priority_master_update( push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WRONG_ARGUMENTS, "Failed to set the master thread " - "priority to %lu, " + "priority to %lu, " "the nice is %lu and the current priority is %lu", priority, nice, actual_priority); } @@ -21134,14 +21135,14 @@ static MYSQL_SYSVAR_BOOL(force_primary_key, "Do not allow to create table without primary key (off by default)", NULL, NULL, FALSE); -const char *corrupt_table_action_names[]= +static const char *corrupt_table_action_names[]= { "assert", /* 0 */ "warn", /* 1 */ "salvage", /* 2 */ NullS }; -TYPELIB corrupt_table_action_typelib= +static TYPELIB corrupt_table_action_typelib= { array_elements(corrupt_table_action_names) - 1, "corrupt_table_action_typelib", corrupt_table_action_names, NULL diff --git a/storage/xtradb/include/btr0sea.ic b/storage/xtradb/include/btr0sea.ic index 4838799e906..f7cff91f9d0 100644 --- a/storage/xtradb/include/btr0sea.ic +++ b/storage/xtradb/include/btr0sea.ic @@ -104,8 +104,8 @@ btr_search_get_latch( /*=================*/ const dict_index_t* index) /*!< in: index */ { - ut_ad(index->search_latch >= btr_search_latch_arr && - index->search_latch < btr_search_latch_arr + + ut_ad(index->search_latch >= btr_search_latch_arr); + ut_ad(index->search_latch < btr_search_latch_arr + btr_search_index_num); return(index->search_latch); diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index 50b223d34f8..e5b545e0727 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -418,7 +418,7 @@ innobase_get_table_cache_size(void); ulong thd_flush_log_at_trx_commit( /*================================*/ - void* thd); + THD* thd); /**********************************************************************//** Get the current setting of the lower_case_table_names global parameter from diff --git a/storage/xtradb/include/sync0rw.ic b/storage/xtradb/include/sync0rw.ic index 075858bd3ce..125c4d90b24 100644 --- a/storage/xtradb/include/sync0rw.ic +++ b/storage/xtradb/include/sync0rw.ic @@ -453,7 +453,8 @@ rw_lock_higher_prio_waiters_exist( return(false); } - ut_ad(priority_lock && !high_priority); + ut_ad(priority_lock); + ut_ad(!high_priority); prio_rw_lock_t *prio_rw_lock = (prio_rw_lock_t *) lock; return prio_rw_lock->high_priority_wait_ex_waiter > 0 diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 69d5cbac5d1..011921d9a39 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -45,10 +45,10 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MINOR 6 -#define INNODB_VERSION_BUGFIX 44 +#define INNODB_VERSION_BUGFIX 45 #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 86.0 +#define PERCONA_INNODB_VERSION 86.1 #endif /* Enable UNIV_LOG_ARCHIVE in XtraDB */ diff --git a/storage/xtradb/lock/lock0wait.cc b/storage/xtradb/lock/lock0wait.cc index 3efc28967db..fe43ef3cc73 100644 --- a/storage/xtradb/lock/lock0wait.cc +++ b/storage/xtradb/lock/lock0wait.cc @@ -207,6 +207,7 @@ functions to get some info from THD. @param[in] trx requested trx @param[in] blocking blocking info array @param[in] blocking_count blocking info array size */ +static void print_lock_wait_timeout( const trx_t &trx, diff --git a/storage/xtradb/log/log0online.cc b/storage/xtradb/log/log0online.cc index 460fb19cf8a..601babc54a9 100644 --- a/storage/xtradb/log/log0online.cc +++ b/storage/xtradb/log/log0online.cc @@ -91,7 +91,7 @@ static const char* bmp_file_name_stem = "ib_modified_log_"; /** File name template for bitmap files. The 1st format tag is a directory name, the 2nd tag is the stem, the 3rd tag is a file sequence number, the 4th tag is the start LSN for the file. */ -static const char* bmp_file_name_template = "%s%s%lu_%llu.xdb"; +static const char* bmp_file_name_template = "%s%s%lu_" LSN_PF ".xdb"; /* On server startup with empty database srv_start_lsn == 0, in which case the first LSN of actual log records will be this. */ @@ -586,9 +586,8 @@ log_online_is_bitmap_file( return ((file_info->type == OS_FILE_TYPE_FILE || file_info->type == OS_FILE_TYPE_LINK) - && (sscanf(file_info->name, "%[a-z_]%lu_%llu.xdb", stem, - bitmap_file_seq_num, - (unsigned long long *)bitmap_file_start_lsn) == 3) + && (sscanf(file_info->name, "%[a-z_]%lu_" LSN_PF ".xdb", stem, + bitmap_file_seq_num, bitmap_file_start_lsn) == 3) && (!strcmp(stem, bmp_file_name_stem))); } diff --git a/storage/xtradb/ut/ut0ut.cc b/storage/xtradb/ut/ut0ut.cc index a9f24fcf18a..aa228a33bdc 100644 --- a/storage/xtradb/ut/ut0ut.cc +++ b/storage/xtradb/ut/ut0ut.cc @@ -40,7 +40,6 @@ Created 5/11/1994 Heikki Tuuri #include #ifndef UNIV_HOTBACKUP -# include "btr0types.h" # include "trx0trx.h" # include "ha_prototypes.h" # include "mysql_com.h" /* NAME_LEN */ From 9277b6ec1ce8bc195a10b5deb11d65843adf8972 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 30 Oct 2019 14:38:18 +0100 Subject: [PATCH 14/15] Revert "MDEV-14448: Ctrl-C should not exit the client" This reverts commit 396313d301b3567aeadd04ae6a9322da2adc0a8b. --- client/mysql.cc | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 7329f2298ab..50d45696a5c 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1368,23 +1368,12 @@ sig_handler handle_sigint(int sig) char kill_buffer[40]; MYSQL *kill_mysql= NULL; - /* Terminate if we already tried interrupting. */ - if (interrupted_query == 2) + /* terminate if no query being executed, or we already tried interrupting */ + if (!executing_query || (interrupted_query == 2)) { tee_fprintf(stdout, "Ctrl-C -- exit!\n"); goto err; } - /* If no query being executed, don't exit. */ - if (!executing_query) - { - tee_fprintf(stdout, "Ctrl-C\n"); -#ifdef HAVE_READLINE - rl_on_new_line(); // Regenerate the prompt on a newline - rl_replace_line("", 0); // Clear the previous text - rl_redisplay(); -#endif - return; - } kill_mysql= mysql_init(kill_mysql); if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password, From 8fce180765b2ede9fb9f0f7ee6ffcda3386050bf Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 30 Oct 2019 09:50:52 +0100 Subject: [PATCH 15/15] MDEV-19432 Systemd service does not get re-enabled after upgrade following Fedora recommendations (see %systemd_post macro in FC29) let's do `systemctl preset` on the first installation of the server --- support-files/rpm/server-postin.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/support-files/rpm/server-postin.sh b/support-files/rpm/server-postin.sh index deb27c98ac1..71518423687 100644 --- a/support-files/rpm/server-postin.sh +++ b/support-files/rpm/server-postin.sh @@ -16,7 +16,8 @@ fi # Make MySQL start/shutdown automatically when the machine does it. if [ $1 = 1 ] ; then if [ -x /usr/bin/systemctl ] ; then - /usr/bin/systemctl daemon-reload >/dev/null 2>&1 + /usr/bin/systemctl daemon-reload >/dev/null 2>&1 || : + /usr/bin/systemctl preset mariadb.service >/dev/null 2>&1 || : elif [ -x /sbin/chkconfig ] ; then /sbin/chkconfig --add mysql fi