diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2017-07-18 13:16:55 +0200 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2017-07-18 13:16:55 +0200 |
commit | f590296c28ec54007692181e010d7064c1071ff2 (patch) | |
tree | 8ca5932a93f59bb60abfb0928ef483e96ed999d6 | |
parent | a9d32010d0ba36cc9b9d7fb58eeace687bb13f7a (diff) | |
download | mariadb-git-f590296c28ec54007692181e010d7064c1071ff2.tar.gz |
-- Finalize work on MongoDB access
Implement discovery for the MongoDB Java Driver
Create classes to minimize code and avoid dupicates
Rearrange and rename implied files
modified: storage/connect/CMakeLists.txt
renamed: storage/connect/mongofam.cpp -> storage/connect/cmgfam.cpp
renamed: storage/connect/mongofam.h -> storage/connect/cmgfam.h
modified: storage/connect/cmgoconn.h
modified: storage/connect/javaconn.h
modified: storage/connect/jdbconn.cpp
modified: storage/connect/jmgoconn.cpp
modified: storage/connect/jmgoconn.h
modified: storage/connect/mongo.cpp
modified: storage/connect/mongo.h
renamed: storage/connect/tabmgo.cpp -> storage/connect/tabcmg.cpp
renamed: storage/connect/tabmgo.h -> storage/connect/tabcmg.h
modified: storage/connect/tabjmg.cpp
modified: storage/connect/tabjmg.h
modified: storage/connect/tabjson.cpp
modified: storage/connect/tabjson.h
-- Trace Sarea allocation and freeing
modified: storage/connect/connect.cc
modified: storage/connect/plugutil.cpp
modified: storage/connect/user_connect.cc
-- Null Json values where not mark as null in JSNX::SetJsonValue
This was added in TYPE_NULL (declared as TYPE_VOID)
modified: storage/connect/json.cpp
modified: storage/connect/json.h
modified: storage/connect/jsonudf.cpp
-- Null JValues are ignored in JSNX::CalculateArray
Also done in tabjson.cpp for JSONCOL::CalculateArray
modified: storage/connect/json.h
modified: storage/connect/jsonudf.cpp
modified: storage/connect/tabjson.cpp
-- Null JSON values now represented by connect_json_null session variable
modified: storage/connect/json.cpp
modified: storage/connect/json.h
modified: storage/connect/jsonudf.cpp
modified: storage/connect/tabjson.cpp
-- JVALUE has size = 1
modified: storage/connect/json.h
-- Fix by vuvova because Debian compilation failure.
modified: storage/connect/value.cpp
26 files changed, 994 insertions, 587 deletions
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 248764879ed..9b0f555ad48 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -316,8 +316,8 @@ ENDIF(CONNECT_WITH_ZIP) # INCLUDE_DIRECTORIES(${MONGO_INCLUDE_DIR}) # SET(MONGO_LIBRARY ${MONGO_LIBRARIES}) # SET(CONNECT_SOURCES ${CONNECT_SOURCES} -# cmgoconn.cpp mongofam.cpp tabmgo.cpp -# cmgoconn.h mongofam.h tabmgo.h) +# cmgoconn.cpp cmgfam.cpp tabcmg.cpp +# cmgoconn.h cmgfam.h tabcmg.h) # IF (NOT JAVA_FOUND AND JNI_FOUND) # SET(CONNECT_SOURCES ${CONNECT_SOURCES} mongo.cpp mongo.h) # ENDIF (NOT JAVA_FOUND AND JNI_FOUND) diff --git a/storage/connect/mongofam.cpp b/storage/connect/cmgfam.cpp index e40ed422d06..579b5b919a7 100644 --- a/storage/connect/mongofam.cpp +++ b/storage/connect/cmgfam.cpp @@ -1,7 +1,7 @@ -/************ MONGO FAM C++ Program Source Code File (.CPP) ************/ -/* PROGRAM NAME: mongofam.cpp */ +/************** CMGFAM C++ Program Source Code File (.CPP) *************/ +/* PROGRAM NAME: cmgfam.cpp */ /* ------------- */ -/* Version 1.3 */ +/* Version 1.4 */ /* */ /* COPYRIGHT: */ /* ---------- */ @@ -30,18 +30,18 @@ #include "filamtxt.h" #include "tabdos.h" #include "tabjson.h" -#include "mongofam.h" +#include "cmgfam.h" #if defined(UNIX) || defined(UNIV_LINUX) #include "osutil.h" #endif -/* --------------------------- Class MGOFAM -------------------------- */ +/* --------------------------- Class CMGFAM -------------------------- */ /***********************************************************************/ /* Constructors. */ /***********************************************************************/ -MGOFAM::MGOFAM(PJDEF tdp) : DOSFAM((PDOSDEF)NULL) +CMGFAM::CMGFAM(PJDEF tdp) : DOSFAM((PDOSDEF)NULL) { Cmgp = NULL; Pcg.Tdbp = NULL; @@ -66,20 +66,20 @@ MGOFAM::MGOFAM(PJDEF tdp) : DOSFAM((PDOSDEF)NULL) Mode = MODE_ANY; Done = false; Lrecl = tdp->Lrecl + tdp->Ending; -} // end of MGOFAM standard constructor +} // end of CMGFAM standard constructor - MGOFAM::MGOFAM(PMGOFAM tdfp) : DOSFAM(tdfp) + CMGFAM::CMGFAM(PCMGFAM tdfp) : DOSFAM(tdfp) { Pcg = tdfp->Pcg; To_Fbt = tdfp->To_Fbt; Mode = tdfp->Mode; Done = tdfp->Done; - } // end of MGOFAM copy constructor + } // end of CMGFAM copy constructor /***********************************************************************/ /* Reset: reset position values at the beginning of file. */ /***********************************************************************/ -void MGOFAM::Reset(void) +void CMGFAM::Reset(void) { TXTFAM::Reset(); Fpos = Tpos = Spos = 0; @@ -88,7 +88,7 @@ void MGOFAM::Reset(void) /***********************************************************************/ /* MGO GetFileLength: returns file size in number of bytes. */ /***********************************************************************/ -int MGOFAM::GetFileLength(PGLOBAL g) +int CMGFAM::GetFileLength(PGLOBAL g) { return 0; } // end of GetFileLength @@ -98,7 +98,7 @@ int MGOFAM::GetFileLength(PGLOBAL g) /* This function can be called with a null argument to test the */ /* availability of Cardinality implementation (1 yes, 0 no). */ /***********************************************************************/ -int MGOFAM::Cardinality(PGLOBAL g) +int CMGFAM::Cardinality(PGLOBAL g) { if (!g) return 1; @@ -109,7 +109,7 @@ int MGOFAM::Cardinality(PGLOBAL g) /***********************************************************************/ /* Note: This function is not really implemented yet. */ /***********************************************************************/ -int MGOFAM::MaxBlkSize(PGLOBAL, int s) +int CMGFAM::MaxBlkSize(PGLOBAL, int s) { return s; } // end of MaxBlkSize @@ -117,7 +117,7 @@ int MGOFAM::MaxBlkSize(PGLOBAL, int s) /***********************************************************************/ /* Init: initialize MongoDB processing. */ /***********************************************************************/ -bool MGOFAM::Init(PGLOBAL g) +bool CMGFAM::Init(PGLOBAL g) { if (Done) return false; @@ -141,7 +141,7 @@ bool MGOFAM::Init(PGLOBAL g) /***********************************************************************/ /* OpenTableFile: Open a MongoDB table. */ /***********************************************************************/ -bool MGOFAM::OpenTableFile(PGLOBAL g) +bool CMGFAM::OpenTableFile(PGLOBAL g) { Mode = Tdbp->GetMode(); @@ -165,7 +165,7 @@ bool MGOFAM::OpenTableFile(PGLOBAL g) /***********************************************************************/ /* GetRowID: return the RowID of last read record. */ /***********************************************************************/ -int MGOFAM::GetRowID(void) +int CMGFAM::GetRowID(void) { return Rows; } // end of GetRowID @@ -173,7 +173,7 @@ int MGOFAM::GetRowID(void) /***********************************************************************/ /* GetPos: return the position of last read record. */ /***********************************************************************/ -int MGOFAM::GetPos(void) +int CMGFAM::GetPos(void) { return Fpos; } // end of GetPos @@ -181,7 +181,7 @@ int MGOFAM::GetPos(void) /***********************************************************************/ /* GetNextPos: return the position of next record. */ /***********************************************************************/ -int MGOFAM::GetNextPos(void) +int CMGFAM::GetNextPos(void) { return Fpos; // TODO } // end of GetNextPos @@ -189,7 +189,7 @@ int MGOFAM::GetNextPos(void) /***********************************************************************/ /* SetPos: Replace the table at the specified position. */ /***********************************************************************/ -bool MGOFAM::SetPos(PGLOBAL g, int pos) +bool CMGFAM::SetPos(PGLOBAL g, int pos) { Fpos = pos; Placed = true; @@ -199,25 +199,25 @@ bool MGOFAM::SetPos(PGLOBAL g, int pos) /***********************************************************************/ /* Record file position in case of UPDATE or DELETE. */ /***********************************************************************/ -bool MGOFAM::RecordPos(PGLOBAL g) +bool CMGFAM::RecordPos(PGLOBAL g) { - strcpy(g->Message, "MGOFAM::RecordPos NIY"); + strcpy(g->Message, "CMGFAM::RecordPos NIY"); return true; } // end of RecordPos /***********************************************************************/ /* Initialize Fpos and the current position for indexed DELETE. */ /***********************************************************************/ -int MGOFAM::InitDelete(PGLOBAL g, int fpos, int spos) +int CMGFAM::InitDelete(PGLOBAL g, int fpos, int spos) { - strcpy(g->Message, "MGOFAM::InitDelete NIY"); + strcpy(g->Message, "CMGFAM::InitDelete NIY"); return RC_FX; } // end of InitDelete /***********************************************************************/ /* Skip one record in file. */ /***********************************************************************/ -int MGOFAM::SkipRecord(PGLOBAL g, bool header) +int CMGFAM::SkipRecord(PGLOBAL g, bool header) { return RC_OK; // Dummy } // end of SkipRecord @@ -225,7 +225,7 @@ int MGOFAM::SkipRecord(PGLOBAL g, bool header) /***********************************************************************/ /* ReadBuffer: Get next document from a collection. */ /***********************************************************************/ -int MGOFAM::ReadBuffer(PGLOBAL g) +int CMGFAM::ReadBuffer(PGLOBAL g) { int rc = Cmgp->ReadNext(g); @@ -239,7 +239,7 @@ int MGOFAM::ReadBuffer(PGLOBAL g) /***********************************************************************/ /* WriteBuffer: File write routine for MGO access method. */ /***********************************************************************/ -int MGOFAM::WriteBuffer(PGLOBAL g) +int CMGFAM::WriteBuffer(PGLOBAL g) { return Cmgp->Write(g); } // end of WriteBuffer @@ -247,7 +247,7 @@ int MGOFAM::WriteBuffer(PGLOBAL g) /***********************************************************************/ /* Data Base delete line routine for MGO and BLK access methods. */ /***********************************************************************/ -int MGOFAM::DeleteRecords(PGLOBAL g, int irc) +int CMGFAM::DeleteRecords(PGLOBAL g, int irc) { return (irc == RC_OK) ? WriteBuffer(g) : RC_OK; } // end of DeleteRecords @@ -255,7 +255,7 @@ int MGOFAM::DeleteRecords(PGLOBAL g, int irc) /***********************************************************************/ /* Table file close routine for MGO access method. */ /***********************************************************************/ -void MGOFAM::CloseTableFile(PGLOBAL g, bool) +void CMGFAM::CloseTableFile(PGLOBAL g, bool) { Cmgp->Close(); Done = false; @@ -264,7 +264,7 @@ void MGOFAM::CloseTableFile(PGLOBAL g, bool) /***********************************************************************/ /* Rewind routine for MGO access method. */ /***********************************************************************/ -void MGOFAM::Rewind(void) +void CMGFAM::Rewind(void) { Cmgp->Rewind(); } // end of Rewind diff --git a/storage/connect/mongofam.h b/storage/connect/cmgfam.h index 99cc6128ffd..7571f5c5309 100644 --- a/storage/connect/mongofam.h +++ b/storage/connect/cmgfam.h @@ -1,5 +1,5 @@ -/************** MongoFam H Declares Source Code File (.H) **************/ -/* Name: mongofam.h Version 1.4 */ +/*************** CMGFam H Declares Source Code File (.H) ***************/ +/* Name: cmgfam.h Version 1.5 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2017 */ /* */ @@ -8,19 +8,19 @@ #include "cmgoconn.h" typedef class TXTFAM *PTXF; -typedef class MGOFAM *PMGOFAM; +typedef class CMGFAM *PCMGFAM; typedef class MGODEF *PMGODEF; -typedef class TDBMGO *PTDBMGO; +typedef class TDBCMG *PTDBCMG; /***********************************************************************/ /* This is the MongoDB Access Method class declaration. */ /***********************************************************************/ -class DllExport MGOFAM : public DOSFAM { +class DllExport CMGFAM : public DOSFAM { friend void mongo_init(bool); public: // Constructor - MGOFAM(PJDEF tdp); - MGOFAM(PMGOFAM txfp); + CMGFAM(PJDEF tdp); + CMGFAM(PCMGFAM txfp); // Implementation virtual AMT GetAmType(void) { return TYPE_AM_MGO; } @@ -28,7 +28,7 @@ public: virtual int GetPos(void); virtual int GetNextPos(void); void SetTdbp(PTDBDOS tdbp) { Tdbp = tdbp; } - virtual PTXF Duplicate(PGLOBAL g) { return (PTXF)new(g) MGOFAM(this); } + virtual PTXF Duplicate(PGLOBAL g) { return (PTXF)new(g) CMGFAM(this); } void SetLrecl(int lrecl) { Lrecl = lrecl; } // Methods @@ -61,5 +61,5 @@ protected: PFBLOCK To_Fbt; // Pointer to temp file block MODE Mode; bool Done; // Init done -}; // end of class MGOFAM +}; // end of class CMGFAM diff --git a/storage/connect/cmgoconn.h b/storage/connect/cmgoconn.h index 9e1361039ab..47275f54381 100644 --- a/storage/connect/cmgoconn.h +++ b/storage/connect/cmgoconn.h @@ -10,7 +10,7 @@ #include <mongoc.h> // C connection to a MongoDB data source -class TDBMGO; +class TDBCMG; class MGOCOL; /***********************************************************************/ @@ -18,7 +18,7 @@ class MGOCOL; /***********************************************************************/ typedef class INCOL *PINCOL; typedef class MGODEF *PMGODEF; -typedef class TDBMGO *PTDBMGO; +typedef class TDBCMG *PTDBCMG; typedef class MGOCOL *PMGOCOL; typedef struct mongo_parms { @@ -63,8 +63,8 @@ public: /* CMgoConn class. */ /***********************************************************************/ class CMgoConn : public BLOCK { - friend class TDBMGO; - friend class MGODISC; + friend class TDBCMG; + friend class CMGDISC; public: // Constructor CMgoConn(PGLOBAL g, PCPARM pcg); diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index 08d35b05932..8f06a710ef2 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -80,7 +80,7 @@ PGLOBAL CntExit(PGLOBAL g) /* CntEndDB: DB termination semantic routine. */ /***********************************************************************/ void CntEndDB(PGLOBAL g) - { +{ PDBUSER dbuserp= PlgGetUser(g); if (dbuserp) { @@ -88,9 +88,14 @@ void CntEndDB(PGLOBAL g) delete dbuserp->Catalog; free(dbuserp); - } // endif dbuserp - } // end of CntEndDB + if (trace) + htrc("CntEndDB: Freeing Dup\n"); + + g->Activityp->Aptr = NULL; + } // endif dbuserp + +} // end of CntEndDB /***********************************************************************/ /* CntCheckDB: Initialize a DB application session. */ diff --git a/storage/connect/global.h b/storage/connect/global.h index cb756494efc..de7a9fb3c03 100644 --- a/storage/connect/global.h +++ b/storage/connect/global.h @@ -58,31 +58,10 @@ /* Miscellaneous Constants */ /***********************************************************************/ #define NO_IVAL -95684275 /* Used by GetIntegerOption */ -#define VMLANG 370 /* Size of olf VM lang blocks */ #define MAX_JUMP 24 /* Maximum jump level number */ #define MAX_STR 4160 /* Maximum message length */ -#define STR_SIZE 501 /* Length of char strings. */ -#define STD_INPUT 0 /* Standard language input */ -#define STD_OUTPUT 1 /* Standard language output */ -#define ERROR_OUTPUT 2 /* Error message output */ -#define DEBUG_OUTPUT 3 /* Debug info output */ -#define PROMPT_OUTPUT 4 /* Prompt message output */ -#define COPY_OUTPUT 5 /* Copy of language input */ -#define STD_MSG 6 /* System message file */ -#define DEBUG_MSG 7 /* Debug message file */ -#define DUMMY 0 /* Dummy file index in Ldm block */ -#define STDIN 1 /* stdin file index in Ldm block */ -#define STDOUT 2 /* stdout file index in Ldm block */ -#define STDERR 3 /* stderr file index in Ldm block */ -#define STDEBUG 4 /* debug file index in Ldm block */ -#define STDPRN 5 /* stdprn file index in Ldm block */ -#define STDFREE 6 /* Free file index in Ldm block */ -#define TYPE_SEM -2 /* Returned semantic function */ -#define TYPE_DFONC -2 /* Indirect sem ref in FPARM */ #define TYPE_VOID -1 -#define TYPE_SBPAR -1 /* Phrase reference in FPARM */ -#define TYPE_SEMX 0 /* Initial semantic function type? */ #define TYPE_ERROR 0 #define TYPE_STRING 1 #define TYPE_DOUBLE 2 @@ -96,22 +75,6 @@ #define TYPE_BIN 10 #define TYPE_PCHAR 11 -#if defined(OS32) - #define SYS_STAMP "OS32" -#elif defined(UNIX) || defined(LINUX) || defined(UNIV_LINUX) - #define SYS_STAMP "UNIX" -#elif defined(OS16) - #define SYS_STAMP "OS16" -#elif defined(DOSR) - #define SYS_STAMP "DOSR" -#elif defined(WIN) - #define SYS_STAMP "WIN1" -#elif defined(__WIN__) - #define SYS_STAMP "WIN2" -#else - #define SYS_STAMP "XXXX" -#endif - #if defined(__cplusplus) extern "C" { #endif @@ -119,11 +82,6 @@ extern "C" { /***********************************************************************/ /* Static variables */ /***********************************************************************/ -#if defined(STORAGE) - char sys_stamp[5] = SYS_STAMP; -#else - extern char sys_stamp[]; -#endif /***********************************************************************/ /* File-Selection Indicators */ diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index b0a37ea445a..fc23d320c83 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -210,9 +210,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(MONGO_SUPPORT) +#if defined(JDBC_SUPPORT) || defined(MONGO_SUPPORT) PQRYRES MGOColumns(PGLOBAL g, PCSZ db, PCSZ url, PTOS topt, bool info); -#endif // MONGO_SUPPORT +#endif // JDBC_SUPPORT || MONGO_SUPPORT 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, @@ -223,6 +223,7 @@ void mongo_init(bool); USETEMP UseTemp(void); int GetConvSize(void); TYPCONV GetTypeConv(void); +char *GetJsonNull(void); uint GetJsonGrpSize(void); char *GetJavaWrapper(void); uint GetWorkSize(void); @@ -332,6 +333,13 @@ static MYSQL_THDVAR_ENUM( 0, // def (no) &xconv_typelib); // typelib +// Null representation for JSON values +static MYSQL_THDVAR_STR(json_null, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, + "Representation of Json null values", + // check_json_null, update_json_null, + NULL, NULL, "<null>"); + // Estimate max number of rows for JSON aggregate functions static MYSQL_THDVAR_UINT(json_grp_size, PLUGIN_VAR_RQCMDARG, // opt @@ -343,7 +351,7 @@ static MYSQL_THDVAR_UINT(json_grp_size, static MYSQL_THDVAR_STR(java_wrapper, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, "Java wrapper class name", - // check_class_path, update_class_path, + // check_java_wrapper, update_java_wrapper, NULL, NULL, "wrappers/JdbcInterface"); #endif // JDBC_SUPPORT @@ -383,6 +391,8 @@ bool ExactInfo(void) {return THDVAR(current_thd, exact_info);} USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);} int GetConvSize(void) {return THDVAR(current_thd, conv_size);} TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);} +char *GetJsonNull(void) + {return connect_hton ? THDVAR(current_thd, json_null) : NULL;} uint GetJsonGrpSize(void) {return connect_hton ? THDVAR(current_thd, json_grp_size) : 10;} uint GetWorkSize(void) {return THDVAR(current_thd, work_size);} @@ -5761,25 +5771,13 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #if !defined(MONGO_SUPPORT) driver = "JAVA"; - // strcpy(g->Message, "No column discovery for Java MONGO tables yet"); - // Temporarily use the JSONColumns function - qrp = JSONColumns(g, db, url, topt, fnc == FNC_COL); #elif !defined(JDBC_SUPPORT) driver = "C"; - qrp = MGOColumns(g, db, url, topt, fnc == FNC_COL); #else // MONGO_SUPPORT && JDBC_SUPPORT if (!driver) driver = "C"; - - if (toupper(*driver) == 'C') { - qrp = MGOColumns(g, db, url, topt, fnc == FNC_COL); - } else { - // strcpy(g->Message, "No column discovery for Java MONGO tables yet"); - // Temporarily use the JSONColumns function - qrp = JSONColumns(g, db, url, topt, fnc == FNC_COL); - } // endif driver - #endif // MONGO_SUPPORT && JDBC_SUPPORT + qrp = MGOColumns(g, db, url, topt, fnc == FNC_COL); break; #endif // MONGO_SUPPORT || JDBC_SUPPORT #if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT) @@ -7137,6 +7135,7 @@ static struct st_mysql_sys_var* connect_system_variables[]= { #if defined(XMSG) MYSQL_SYSVAR(errmsg_dir_path), #endif // XMSG + MYSQL_SYSVAR(json_null), MYSQL_SYSVAR(json_grp_size), #if defined(JDBC_SUPPORT) MYSQL_SYSVAR(jvm_path), diff --git a/storage/connect/javaconn.h b/storage/connect/javaconn.h index fba633945f0..565c4ac2607 100644 --- a/storage/connect/javaconn.h +++ b/storage/connect/javaconn.h @@ -63,6 +63,7 @@ class JAVAConn; /***********************************************************************/ class JAVAConn : public BLOCK { friend class TDBJMG; + friend class JMGDISC; private: JAVAConn(); // Standard (unused) constructor diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index dbfd1b0e24d..e0524392082 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -1226,7 +1226,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) case 5: crp->Name = "Nullable"; break; } // endswitch i - // Build the java string array + // Build the java int array jintArray val = env->NewIntArray(4); if (val == nullptr) { diff --git a/storage/connect/jmgoconn.cpp b/storage/connect/jmgoconn.cpp index cb0729ed1f7..a51127c80a0 100644 --- a/storage/connect/jmgoconn.cpp +++ b/storage/connect/jmgoconn.cpp @@ -110,8 +110,8 @@ JMgoConn::JMgoConn(PGLOBAL g, PCSZ collname, PCSZ wrapper) deleteid = gcollid = countid = rewindid = nullptr; DiscFunc = "MongoDisconnect"; Fpc = NULL; - m_Version = 0; m_Fetch = 0; + m_Ncol = 0; m_Version = 0; } // end of JMgoConn @@ -122,13 +122,13 @@ void JMgoConn::AddJars(PSTRG jpop, char sep) { #if defined(DEVELOPMENT) if (m_Version == 2) { - //jpop->Append(sep); - //jpop->Append("C:/Eclipse/workspace/MongoWrap2/bin"); + jpop->Append(sep); + jpop->Append("C:/Eclipse/workspace/MongoWrap2/bin"); jpop->Append(sep); jpop->Append("C:/mongo-java-driver/mongo-java-driver-2.13.3.jar"); } else { - //jpop->Append(sep); - //jpop->Append("C:/Eclipse/workspace/MongoWrap3/bin"); + jpop->Append(sep); + jpop->Append("C:/Eclipse/workspace/MongoWrap3/bin"); jpop->Append(sep); jpop->Append("C:/mongo-java-driver/mongo-java-driver-3.4.2.jar"); } // endif m_Version @@ -495,13 +495,15 @@ int JMgoConn::Fetch(int pos) //else // m_Fetch++; - m_Rows += (int)rc; + m_Ncol = (int)rc; + rc = MY_MIN(rc, 1); + m_Rows += rc; } else sprintf(g->Message, "Fetch: %s", Msg); //} // endif pos - return (int)rc; + return rc; } // end of Fetch /***********************************************************************/ diff --git a/storage/connect/jmgoconn.h b/storage/connect/jmgoconn.h index 8e8577efe97..8ee7985d760 100644 --- a/storage/connect/jmgoconn.h +++ b/storage/connect/jmgoconn.h @@ -19,31 +19,6 @@ typedef class MGODEF *PMGODEF; typedef class TDBJMG *PTDBJMG; typedef class JMGCOL *PJMGCOL; -#if 0 -/***********************************************************************/ -/* Class used to get the columns of a mongo collection. */ -/***********************************************************************/ -class MGODISC : public BLOCK { -public: - // Constructor - MGODISC(PGLOBAL g, int *lg); - - // Functions - int GetColumns(PGLOBAL g, char *db, PTOS topt); - bool FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc, - char *pcn, char *pfmt, int i, int k, bool b); - - // Members - BCOL bcol; - PBCOL bcp, fbcp, pbcp; - PMGODEF tdp; - TDBJMG *tmgp; - int *length; - int n, k, lvl; - bool all; -}; // end of MGODISC -#endif // 0 - typedef struct JKCOL { JKCOL *Next; PJNCOL Jncolp; @@ -73,6 +48,7 @@ public: /***********************************************************************/ class JMgoConn : public JAVAConn { friend class TDBJMG; + friend class JMGDISC; //friend class TDBXJDC; //friend PQRYRES GetColumnInfo(PGLOBAL, char*&, char *, int, PVBLK&); private: @@ -132,5 +108,6 @@ protected: jmethodID deleteid; // The CollDelete method ID PJNCOL Fpc; // To JNCOL classes int m_Fetch; + int m_Ncol; int m_Version; // Java driver version (2 or 3) }; // end of JMgoConn class definition diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index 44758e7b0ad..da94d4e227c 100644 --- a/storage/connect/json.cpp +++ b/storage/connect/json.cpp @@ -1,5 +1,5 @@ /*************** json CPP Declares Source Code File (.H) ***************/ -/* Name: json.cpp Version 1.3 */ +/* Name: json.cpp Version 1.4 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2014 - 2017 */ /* */ @@ -53,6 +53,8 @@ void trans_func(unsigned int u, _EXCEPTION_POINTERS* pExp) char *GetExceptionDesc(PGLOBAL g, unsigned int e); #endif // SE_CATCH +char *GetJsonNull(void); + /***********************************************************************/ /* IsNum: check whether this string is all digits. */ /***********************************************************************/ @@ -537,7 +539,7 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src) if (!has_e) goto err; - // passthru + // fall through case '-': if (found_digit) goto err; @@ -827,7 +829,7 @@ bool JOUTSTR::Escape(const char *s) case '\r': case '\b': case '\f': WriteChr('\\'); - // passthru + // fall through default: WriteChr(s[i]); break; @@ -964,6 +966,25 @@ return false; /* -------------------------- Class JOBJECT -------------------------- */ /***********************************************************************/ +/* Return the number of pairs in this object. */ +/***********************************************************************/ +int JOBJECT::GetSize(bool b) +{ + if (b) { + // Return only non null pairs + int n = 0; + + for (PJPR jpp = First; jpp; jpp = jpp->Next) + if (jpp->Val && !jpp->Val->IsNull()) + n++; + + return n; + } else + return Size; + +} // end of GetSize + +/***********************************************************************/ /* Add a new pair to an Object. */ /***********************************************************************/ PJPR JOBJECT::AddPair(PGLOBAL g, PCSZ key) @@ -1046,7 +1067,7 @@ PSZ JOBJECT::GetText(PGLOBAL g, PSZ text) PlugSubAlloc(g, NULL, strlen(text) + 1); return text + n; -} // end of GetValue; +} // end of GetText; /***********************************************************************/ /* Merge two objects. */ @@ -1087,7 +1108,7 @@ void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PCSZ key) } // end of SetValue /***********************************************************************/ -/* Delete a value corresponding to the given key. */ +/* Delete a value corresponding to the given key. */ /***********************************************************************/ void JOBJECT::DeleteKey(PCSZ key) { @@ -1118,6 +1139,25 @@ bool JOBJECT::IsNull(void) /* -------------------------- Class JARRAY --------------------------- */ /***********************************************************************/ +/* Return the number of values in this object. */ +/***********************************************************************/ +int JARRAY::GetSize(bool b) +{ + if (b) { + // Return only non null values + int n = 0; + + for (PJVAL jvp = First; jvp; jvp = jvp->Next) + if (!jvp->IsNull()) + n++; + + return n; + } else + return Size; + +} // end of GetSize + +/***********************************************************************/ /* Make the array of values from the values list. */ /***********************************************************************/ void JARRAY::InitArray(PGLOBAL g) @@ -1226,17 +1266,41 @@ bool JARRAY::SetValue(PGLOBAL g, PJVAL jvp, int n) } // end of SetValue /***********************************************************************/ +/* Return the text corresponding to all values. */ +/***********************************************************************/ +PSZ JARRAY::GetText(PGLOBAL g, PSZ text) +{ + int n; + PJVAL jp; + + if (!text) { + text = (char*)PlugSubAlloc(g, NULL, 0); + text[0] = 0; + n = 1; + } else + n = 0; + + for (jp = First; jp; jp = jp->Next) + jp->GetText(g, text); + + if (n) + PlugSubAlloc(g, NULL, strlen(text) + 1); + + return text + n; +} // end of GetText; + +/***********************************************************************/ /* Delete a Value from the Arrays Value list. */ /***********************************************************************/ bool JARRAY::DeleteValue(int n) { - PJVAL jvp = GetValue(n); + PJVAL jvp = GetValue(n); - if (jvp) { - jvp->Del = true; - return false; - } else - return true; + if (jvp) { + jvp->Del = true; + return false; + } else + return true; } // end of DeleteValue @@ -1286,7 +1350,7 @@ JTYP JVALUE::GetValType(void) else if (Value) return (JTYP)Value->GetType(); else - return (JTYP)TYPE_VOID; + return TYPE_NULL; } // end of GetValType @@ -1350,7 +1414,7 @@ PSZ JVALUE::GetString(void) /***********************************************************************/ PSZ JVALUE::GetText(PGLOBAL g, PSZ text) { - if (Jsp && Jsp->GetType() == TYPE_JOB) + if (Jsp) return Jsp->GetText(g, text); char buf[32]; @@ -1358,8 +1422,8 @@ PSZ JVALUE::GetText(PGLOBAL g, PSZ text) if (s) strcat(strcat(text, " "), s); - else - strcat(text, " <null>"); + else if (GetJsonNull()) + strcat(strcat(text, " "), GetJsonNull()); return text; } // end of GetText diff --git a/storage/connect/json.h b/storage/connect/json.h index 685c1dddcf2..daed055435b 100644 --- a/storage/connect/json.h +++ b/storage/connect/json.h @@ -13,7 +13,8 @@ #define X #endif -enum JTYP {TYPE_STRG = TYPE_STRING, +enum JTYP {TYPE_NULL = TYPE_VOID, + TYPE_STRG = TYPE_STRING, TYPE_DBL = TYPE_DOUBLE, TYPE_BOOL = TYPE_TINY, TYPE_BINT = TYPE_BIGINT, @@ -146,6 +147,7 @@ class JSON : public BLOCK { JSON(void) {Size = 0;} int size(void) {return Size;} + virtual int GetSize(bool b) {return Size;} virtual void Clear(void) {Size = 0;} virtual JTYP GetType(void) {return TYPE_JSON;} virtual JTYP GetValType(void) {X return TYPE_JSON;} @@ -193,10 +195,11 @@ class JOBJECT : public JSON { using JSON::GetValue; using JSON::SetValue; - virtual void Clear(void) {First = Last = NULL; Size = 0;} + virtual void Clear(void) {First = Last = NULL; Size = 0;} virtual JTYP GetType(void) {return TYPE_JOB;} virtual PJPR GetFirst(void) {return First;} - virtual PJPR AddPair(PGLOBAL g, PCSZ key); + virtual int GetSize(bool b); + virtual PJPR AddPair(PGLOBAL g, PCSZ key); virtual PJOB GetObject(void) {return this;} virtual PJVAL GetValue(const char* key); virtual PJAR GetKeyList(PGLOBAL g); @@ -222,11 +225,13 @@ class JARRAY : public JSON { using JSON::GetValue; using JSON::SetValue; virtual void Clear(void) {First = Last = NULL; Size = 0;} - virtual JTYP GetType(void) {return TYPE_JAR;} + virtual JTYP GetType(void) {return TYPE_JAR;} virtual PJAR GetArray(void) {return this;} - PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL); + virtual int GetSize(bool b); + PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL); virtual void InitArray(PGLOBAL g); virtual PJVAL GetValue(int i); + virtual PSZ GetText(PGLOBAL g, PSZ text); virtual bool Merge(PGLOBAL g, PJSON jsp); virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i); virtual bool DeleteValue(int n); @@ -246,20 +251,20 @@ class JARRAY : public JSON { class JVALUE : public JSON { friend class JARRAY; friend class JSNX; + friend class JSONCOL; friend PJVAL ParseValue(PGLOBAL, int&, STRG&, bool*); friend bool SerializeValue(JOUT *, PJVAL); public: - JVALUE(void) : JSON() - {Jsp = NULL; Value = NULL; Next = NULL; Del = false;} + JVALUE(void) : JSON() {Clear();} JVALUE(PJSON jsp) : JSON() - {Jsp = jsp; Value = NULL; Next = NULL; Del = false;} - JVALUE(PGLOBAL g, PVAL valp); + {Jsp = jsp; Value = NULL; Next = NULL; Del = false; Size = 1;} + JVALUE(PGLOBAL g, PVAL valp); JVALUE(PGLOBAL g, PCSZ strp); using JSON::GetValue; using JSON::SetValue; virtual void Clear(void) - {Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;} + {Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 1;} virtual JTYP GetType(void) {return TYPE_JVAL;} virtual JTYP GetValType(void); virtual PJOB GetObject(void); diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 124e5bdc6ad..eb98510c702 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -1,5 +1,5 @@ /****************** jsonudf C++ Program Source Code File (.CPP) ******************/ -/* PROGRAM NAME: jsonudf Version 1.5 */ +/* PROGRAM NAME: jsonudf Version 1.6 */ /* (C) Copyright to the author Olivier BERTRAND 2015-2017 */ /* This program are the JSON User Defined Functions . */ /*********************************************************************************/ @@ -29,6 +29,7 @@ bool IsNum(PSZ s); char *NextChr(PSZ s, char sep); +char *GetJsonNull(void); uint GetJsonGrpSize(void); static int IsJson(UDF_ARGS *args, uint i); static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i); @@ -347,11 +348,13 @@ void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) SetJsonValue(g, vp, val->GetArray()->GetValue(0), n); break; case TYPE_JOB: - // if (!vp->IsTypeNum() || !Strict) { +// if (!vp->IsTypeNum() || !Strict) { vp->SetValue_psz(val->GetObject()->GetText(g, NULL)); break; - // } // endif Type +// } // endif Type + case TYPE_NULL: + vp->SetNull(true); default: vp->Reset(); } // endswitch Type @@ -488,15 +491,16 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) JVALUE jval; vp->Reset(); -//ars = MY_MIN(Tjp->Limit, arp->size()); ars = arp->size(); for (i = 0; i < ars; i++) { jvrp = arp->GetValue(i); -// do { - if (n < Nod - 1 && jvrp->GetJson()) { -// Tjp->NextSame = nextsame; + if (!jvrp->IsNull() || (op == OP_CNC && GetJsonNull())) { + if (jvrp->IsNull()) { + jvrp->Value = AllocateValue(g, GetJsonNull(), TYPE_STRING); + jvp = jvrp; + } else if (n < Nod - 1 && jvrp->GetJson()) { jval.SetValue(GetColumnValue(g, jvrp->GetJson(), n + 1)); jvp = &jval; } else @@ -510,25 +514,25 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) if (!MulVal->IsZero()) { switch (op) { - case OP_CNC: - if (Nodes[n].CncVal) { - val[0] = Nodes[n].CncVal; - err = vp->Compute(g, val, 1, op); - } // endif CncVal + 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; - // case OP_NUM: - case OP_SEP: - val[0] = Nodes[n].Valp; - val[1] = MulVal; - err = vp->Compute(g, val, 2, OP_ADD); - break; - default: - val[0] = Nodes[n].Valp; - val[1] = MulVal; - err = vp->Compute(g, val, 2, op); + val[0] = MulVal; + err = vp->Compute(g, val, 1, op); + break; +// case OP_NUM: + case OP_SEP: + val[0] = Nodes[n].Valp; + val[1] = MulVal; + err = vp->Compute(g, val, 2, OP_ADD); + break; + default: + val[0] = Nodes[n].Valp; + val[1] = MulVal; + err = vp->Compute(g, val, 2, op); } // endswitch Op if (err) @@ -536,7 +540,7 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) } // endif Zero -// } while (Tjp->NextSame > nextsame); + } // endif jvrp } // endfor i @@ -1100,6 +1104,7 @@ inline void JsonMemSave(PGLOBAL g) /*********************************************************************************/ inline void JsonFreeMem(PGLOBAL g) { + g->Activityp = NULL; PlugExit(g); } /* end of JsonFreeMem */ @@ -1111,7 +1116,7 @@ static my_bool JsonInit(UDF_INIT *initid, UDF_ARGS *args, unsigned long reslen, unsigned long memlen, unsigned long more = 0) { - PGLOBAL g = PlugInit(NULL, memlen + more); + PGLOBAL g = PlugInit(NULL, memlen + more + 500); // +500 to avoid CheckMem if (!g) { strcpy(message, "Allocation error"); @@ -1471,6 +1476,9 @@ static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args, uint n, ml += g->More; if (ml > g->Sarea_Size) { + if (trace) + htrc("Freeing Sarea size=%d\n", g->Sarea_Size); + free(g->Sarea); if (!(g->Sarea = PlugAllocMem(g, ml))) { @@ -1814,7 +1822,7 @@ char *json_make_array(UDF_INIT *initid, UDF_ARGS *args, char *result, return str; } // end of json_make_array -void json_array_deinit(UDF_INIT* initid) +void json_make_array_deinit(UDF_INIT* initid) { JsonFreeMem((PGLOBAL)initid->ptr); } // end of json_make_array_deinit @@ -2098,6 +2106,206 @@ void json_array_delete_deinit(UDF_INIT* initid) } // end of json_array_delete_deinit /*********************************************************************************/ +/* Sum big integer values from a Json array. */ +/*********************************************************************************/ +my_bool jsonsum_int_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + unsigned long reslen, memlen, more; + + if (args->arg_count != 1) { + strcpy(message, "This function must have 1 argument"); + return true; + } else if (!IsJson(args, 0) && args->arg_type[0] != STRING_RESULT) { + strcpy(message, "First argument must be a json item"); + return true; + } else + CalcLen(args, false, reslen, memlen); + + // TODO: calculate this + more = (IsJson(args, 0) != 3) ? 1000 : 0; + + return JsonInit(initid, args, message, true, reslen, memlen, more); +} // end of jsonsum_int_init + +long long jsonsum_int(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) +{ + long long n = 0LL; + PGLOBAL g = (PGLOBAL)initid->ptr; + + if (g->N) { + if (!g->Activityp) { + *is_null = 1; + return 0LL; + } else + return *(long long*)g->Activityp; + + } else if (initid->const_item) + g->N = 1; + + if (!CheckMemory(g, initid, args, 1, false, false, true)) { + PJVAL jvp = MakeValue(g, args, 0); + + if (jvp && jvp->GetValType() == TYPE_JAR) { + PJAR arp = jvp->GetArray(); + + for (int i = 0; i < arp->size(); i++) + n += arp->GetValue(i)->GetBigint(); + + } else { + PUSH_WARNING("First argument target is not an array"); + } // endif jvp + + } else { + *error = 1; + n = -1LL; + } // end of CheckMemory + + if (g->N) { + // Keep result of constant function + long long *np = (long long*)PlugSubAlloc(g, NULL, sizeof(long long)); + *np = n; + g->Activityp = (PACTIVITY)np; + } // endif const_item + + return n; +} // end of jsonsum_int + +void jsonsum_int_deinit(UDF_INIT* initid) +{ + JsonFreeMem((PGLOBAL)initid->ptr); +} // end of jsonsum_int_deinit + +/*********************************************************************************/ +/* Sum big integer values from a Json array. */ +/*********************************************************************************/ +my_bool jsonsum_real_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + unsigned long reslen, memlen, more; + + if (args->arg_count != 1) { + strcpy(message, "This function must have 1 argument"); + return true; + } else if (!IsJson(args, 0) && args->arg_type[0] != STRING_RESULT) { + strcpy(message, "First argument must be a json item"); + return true; + } else + CalcLen(args, false, reslen, memlen); + + // TODO: calculate this + more = (IsJson(args, 0) != 3) ? 1000 : 0; + + return JsonInit(initid, args, message, true, reslen, memlen, more); +} // end of jsonsum_real_init + +double jsonsum_real(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) +{ + double n = 0.0; + PGLOBAL g = (PGLOBAL)initid->ptr; + + if (g->N) { + if (!g->Activityp) { + *is_null = 1; + return 0.0; + } else + return *(double*)g->Activityp; + + } else if (initid->const_item) + g->N = 1; + + if (!CheckMemory(g, initid, args, 1, false, false, true)) { + PJVAL jvp = MakeValue(g, args, 0); + + if (jvp && jvp->GetValType() == TYPE_JAR) { + PJAR arp = jvp->GetArray(); + + for (int i = 0; i < arp->size(); i++) + n += arp->GetValue(i)->GetFloat(); + + } else { + PUSH_WARNING("First argument target is not an array"); + } // endif jvp + + } else { + *error = 1; + n = -1.0; + } // end of CheckMemory + + if (g->N) { + // Keep result of constant function + double *np = (double*)PlugSubAlloc(g, NULL, sizeof(double)); + *np = n; + g->Activityp = (PACTIVITY)np; + } // endif const_item + + return n; +} // end of jsonsum_real + +void jsonsum_real_deinit(UDF_INIT* initid) +{ + JsonFreeMem((PGLOBAL)initid->ptr); +} // end of jsonsum_real_deinit + +/*********************************************************************************/ +/* Returns the average of big integer values from a Json array. */ +/*********************************************************************************/ +my_bool jsonavg_real_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + return jsonsum_real_init(initid, args, message); +} // end of jsonavg_real_init + +double jsonavg_real(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) +{ + double n = 0.0; + PGLOBAL g = (PGLOBAL)initid->ptr; + + if (g->N) { + if (!g->Activityp) { + *is_null = 1; + return 0.0; + } else + return *(double*)g->Activityp; + + } else if (initid->const_item) + g->N = 1; + + if (!CheckMemory(g, initid, args, 1, false, false, true)) { + PJVAL jvp = MakeValue(g, args, 0); + + if (jvp && jvp->GetValType() == TYPE_JAR) { + PJAR arp = jvp->GetArray(); + + if (arp->size()) { + for (int i = 0; i < arp->size(); i++) + n += arp->GetValue(i)->GetFloat(); + + n /= arp->size(); + } // endif size + + } else { + PUSH_WARNING("First argument target is not an array"); + } // endif jvp + + } else { + *error = 1; + n = -1.0; + } // end of CheckMemory + + if (g->N) { + // Keep result of constant function + double *np = (double*)PlugSubAlloc(g, NULL, sizeof(double)); + *np = n; + g->Activityp = (PACTIVITY)np; + } // endif const_item + + return n; +} // end of jsonavg_real + +void jsonavg_real_deinit(UDF_INIT* initid) +{ + JsonFreeMem((PGLOBAL)initid->ptr); +} // end of jsonavg_real_deinit + +/*********************************************************************************/ /* Make a Json Object containing all the parameters. */ /*********************************************************************************/ my_bool json_make_object_init(UDF_INIT *initid, UDF_ARGS *args, char *message) @@ -2990,6 +3198,7 @@ char *jsonget_string(UDF_INIT *initid, UDF_ARGS *args, char *result, } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); + PUSH_WARNING(g->Message); str = NULL; } catch (const char *msg) { @@ -3039,7 +3248,7 @@ my_bool jsonget_int_init(UDF_INIT *initid, UDF_ARGS *args, char *message) } // end of jsonget_int_init long long jsonget_int(UDF_INIT *initid, UDF_ARGS *args, - char *is_null, char *error) + char *is_null, char *error) { char *p, *path; long long n; @@ -3330,6 +3539,7 @@ char *jsonlocate(UDF_INIT *initid, UDF_ARGS *args, char *result, } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); + PUSH_WARNING(g->Message); *error = 1; path = NULL; @@ -3454,6 +3664,7 @@ char *json_locate_all(UDF_INIT *initid, UDF_ARGS *args, char *result, } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); + PUSH_WARNING(g->Message); *error = 1; path = NULL; @@ -3728,6 +3939,7 @@ char *handle_item(UDF_INIT *initid, UDF_ARGS *args, char *result, } catch (int n) { if (trace) htrc("Exception %d: %s\n", n, g->Message); + PUSH_WARNING(g->Message); str = NULL; } catch (const char *msg) { diff --git a/storage/connect/jsonudf.h b/storage/connect/jsonudf.h index 53fa555ee08..cd3b9768f7a 100644 --- a/storage/connect/jsonudf.h +++ b/storage/connect/jsonudf.h @@ -53,6 +53,18 @@ extern "C" { DllExport char *json_array_delete(UDF_EXEC_ARGS); DllExport void json_array_delete_deinit(UDF_INIT*); + DllExport my_bool jsonsum_int_init(UDF_INIT*, UDF_ARGS*, char*); + DllExport long long jsonsum_int(UDF_INIT*, UDF_ARGS*, char*, char*); + DllExport void jsonsum_int_deinit(UDF_INIT*); + + DllExport my_bool jsonsum_real_init(UDF_INIT*, UDF_ARGS*, char*); + DllExport double jsonsum_real(UDF_INIT*, UDF_ARGS*, char*, char*); + DllExport void jsonsum_real_deinit(UDF_INIT*); + + DllExport my_bool jsonavg_real_init(UDF_INIT*, UDF_ARGS*, char*); + DllExport double jsonavg_real(UDF_INIT*, UDF_ARGS*, char*, char*); + DllExport void jsonavg_real_deinit(UDF_INIT*); + DllExport my_bool json_make_object_init(UDF_INIT*, UDF_ARGS*, char*); DllExport char *json_make_object(UDF_EXEC_ARGS); DllExport void json_make_object_deinit(UDF_INIT*); diff --git a/storage/connect/mongo.cpp b/storage/connect/mongo.cpp index 07b8beb8ce7..55c26dae9f3 100644 --- a/storage/connect/mongo.cpp +++ b/storage/connect/mongo.cpp @@ -19,11 +19,265 @@ #include "xtable.h" #include "tabext.h" #if defined(MONGO_SUPPORT) -#include "tabmgo.h" +#include "tabcmg.h" #endif // MONGO_SUPPORT #if defined(JDBC_SUPPORT) #include "tabjmg.h" #endif // JDBC_SUPPORT +#include "resource.h" + +/***********************************************************************/ +/* This should be an option. */ +/***********************************************************************/ +#define MAXCOL 200 /* Default max column nb in result */ +#define TYPE_UNKNOWN 12 /* Must be greater than other types */ + +bool IsNum(PSZ s); + +/***********************************************************************/ +/* MGOColumns: construct the result blocks containing the description */ +/* of all the columns of a document contained inside MongoDB. */ +/***********************************************************************/ +PQRYRES MGOColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt, bool info) +{ + 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, + FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT}; + unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0}; + int ncol = sizeof(buftyp) / sizeof(int); + int i, n = 0; +//PCSZ drv; + PBCOL bcp; + MGODISC *cmgd; + PQRYRES qrp; + PCOLRES crp; + + if (info) { + length[0] = 128; + length[7] = 256; + goto skipit; + } // endif info + + /*********************************************************************/ + /* Open MongoDB. */ + /*********************************************************************/ +# if !defined(JDBC_SUPPORT) + cmgd = new(g) CMGDISC(g, (int*)length); +#elif !defined(MONGO_SUPPORT) + cmgd = new(g) JMGDISC(g, (int*)length); +#else + drv = GetStringTableOption(g, topt, "Driver", "C"); + + if (toupper(*drv) == 'C') + cmgd = new(g) CMGDISC(g, (int*)length); + else + cmgd = new(g) JMGDISC(g, (int*)length); +#endif + + if ((n = cmgd->GetColumns(g, db, uri, topt)) < 0) + goto err; + +skipit: + if (trace) + htrc("MGOColumns: n=%d len=%d\n", n, length[0]); + + /*********************************************************************/ + /* Allocate the structures used to refer to the result set. */ + /*********************************************************************/ + qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, + buftyp, fldtyp, length, false, false); + + crp = qrp->Colresp->Next->Next->Next->Next->Next->Next; + crp->Name = "Nullable"; + crp->Next->Name = "Bpath"; + + if (info || !qrp) + return qrp; + + qrp->Nblin = n; + + /*********************************************************************/ + /* Now get the results into blocks. */ + /*********************************************************************/ + for (i = 0, bcp = cmgd->fbcp; bcp; i++, bcp = bcp->Next) { + if (bcp->Type == TYPE_UNKNOWN) // Void column + bcp->Type = TYPE_STRING; + + crp = qrp->Colresp; // Column Name + crp->Kdata->SetValue(bcp->Name, i); + crp = crp->Next; // Data Type + crp->Kdata->SetValue(bcp->Type, i); + crp = crp->Next; // Type Name + crp->Kdata->SetValue(GetTypeName(bcp->Type), i); + crp = crp->Next; // Precision + crp->Kdata->SetValue(bcp->Len, i); + crp = crp->Next; // Length + crp->Kdata->SetValue(bcp->Len, i); + crp = crp->Next; // Scale (precision) + crp->Kdata->SetValue(bcp->Scale, i); + crp = crp->Next; // Nullable + crp->Kdata->SetValue(bcp->Cbn ? 1 : 0, i); + crp = crp->Next; // Field format + + if (crp->Kdata) + crp->Kdata->SetValue(bcp->Fmt, i); + + } // endfor i + + /*********************************************************************/ + /* Return the result pointer. */ + /*********************************************************************/ + return qrp; + +err: + if (cmgd->tmgp) + cmgd->tmgp->CloseDB(g); + + return NULL; +} // end of MGOColumns + +/***********************************************************************/ +/* Class used to get the columns of a mongo collection. */ +/***********************************************************************/ +MGODISC::MGODISC(PGLOBAL g, int *lg) { + length = lg; + fbcp = NULL; + pbcp = NULL; + tmgp = NULL; + drv = NULL; + i = ncol = lvl = 0; + all = false; +} // end of MGODISC constructor + +/***********************************************************************/ +/* Class used to get the columns of a mongo collection. */ +/***********************************************************************/ +int MGODISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt) +{ + PCSZ level = GetStringTableOption(g, topt, "Level", NULL); + PMGODEF tdp; + + if (level) { + lvl = atoi(level); + lvl = (lvl > 16) ? 16 : lvl; + } else + lvl = 0; + + all = GetBooleanTableOption(g, topt, "Fullarray", false); + + /*********************************************************************/ + /* Open the MongoDB collection. */ + /*********************************************************************/ + tdp = new(g) MGODEF; + tdp->Uri = uri; + tdp->Driver = drv; + tdp->Tabname = GetStringTableOption(g, topt, "Name", NULL); + tdp->Tabname = GetStringTableOption(g, topt, "Tabname", tdp->Tabname); + tdp->Tabschema = GetStringTableOption(g, topt, "Dbname", db); + tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; + tdp->Colist = GetStringTableOption(g, topt, "Colist", "all"); + tdp->Filter = GetStringTableOption(g, topt, "Filter", NULL); + tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false); + tdp->Version = GetIntegerTableOption(g, topt, "Version", 3); + tdp->Wrapname = (PSZ)GetStringTableOption(g, topt, "Wrapper", + (tdp->Version == 2) ? "Mongo2Interface" : "Mongo3Interface"); + + if (trace) + htrc("Uri %s coll=%s db=%s colist=%s filter=%s lvl=%d\n", + tdp->Uri, tdp->Tabname, tdp->Tabschema, tdp->Colist, tdp->Filter, lvl); + + tmgp = tdp->GetTable(g, MODE_READ); + tmgp->SetMode(MODE_READ); + + if (tmgp->OpenDB(g)) + return -1; + + bcol.Next = NULL; + bcol.Name = bcol.Fmt = NULL; + bcol.Type = TYPE_UNKNOWN; + bcol.Len = bcol.Scale = 0; + bcol.Found = true; + bcol.Cbn = false; + + if (Init(g)) + return -1; + + /*********************************************************************/ + /* Analyse the BSON tree and define columns. */ + /*********************************************************************/ + for (i = 1; ; i++) { + switch (tmgp->ReadDB(g)) { + case RC_EF: + return ncol; + case RC_FX: + return -1; + default: + GetDoc(); + } // endswitch ReadDB + + if (Find(g)) + return -1; + + // Missing columns can be null + for (bcp = fbcp; bcp; bcp = bcp->Next) { + bcp->Cbn |= !bcp->Found; + bcp->Found = false; + } // endfor bcp + + } // endfor i + + return ncol; +} // end of GetColumns + +/***********************************************************************/ +/* Add a new column in the column list. */ +/***********************************************************************/ +void MGODISC::AddColumn(PGLOBAL g, PCSZ colname, PCSZ fmt, int k) +{ + // Check whether this column was already found + for (bcp = fbcp; bcp; bcp = bcp->Next) + if (!strcmp(colname, bcp->Name)) + break; + + if (bcp) { + if (bcp->Type != bcol.Type) + bcp->Type = TYPE_STRING; + + if (k && *fmt && (!bcp->Fmt || strlen(bcp->Fmt) < strlen(fmt))) { + bcp->Fmt = PlugDup(g, fmt); + length[7] = MY_MAX(length[7], strlen(fmt)); + } // endif *fmt + + bcp->Len = MY_MAX(bcp->Len, bcol.Len); + bcp->Scale = MY_MAX(bcp->Scale, bcol.Scale); + bcp->Cbn |= bcol.Cbn; + bcp->Found = true; + } else { + // New column + bcp = (PBCOL)PlugSubAlloc(g, NULL, sizeof(BCOL)); + *bcp = bcol; + bcp->Cbn |= (i > 1); + bcp->Name = PlugDup(g, colname); + length[0] = MY_MAX(length[0], strlen(colname)); + + if (k) { + bcp->Fmt = PlugDup(g, fmt); + length[7] = MY_MAX(length[7], strlen(fmt)); + } else + bcp->Fmt = NULL; + + if (pbcp) { + bcp->Next = pbcp->Next; + pbcp->Next = bcp; + } else + fbcp = bcp; + + ncol++; + } // endif jcp + + pbcp = bcp; +} // end of AddColumn /* -------------------------- Class MGODEF --------------------------- */ @@ -91,7 +345,7 @@ PTDB MGODEF::GetTable(PGLOBAL g, MODE m) #if defined(MONGO_SUPPORT) if (Driver && toupper(*Driver) == 'C') - return new(g) TDBMGO(this); + return new(g) TDBCMG(this); #endif // MONGO_SUPPORT #if defined(JDBC_SUPPORT) return new(g) TDBJMG(this); @@ -100,4 +354,3 @@ PTDB MGODEF::GetTable(PGLOBAL g, MODE m) return NULL; #endif // !JDBC_SUPPORT } // end of GetTable - diff --git a/storage/connect/mongo.h b/storage/connect/mongo.h index 26d83b38bbc..af69226ea8b 100644 --- a/storage/connect/mongo.h +++ b/storage/connect/mongo.h @@ -26,14 +26,42 @@ typedef struct _bncol { } BCOL, *PBCOL; /***********************************************************************/ +/* Class used to get the columns of a mongo collection. */ +/***********************************************************************/ +class MGODISC : public BLOCK { +public: + // Constructor + MGODISC(PGLOBAL g, int *lg); + + // Methods + virtual bool Init(PGLOBAL g) { return false; } + virtual void GetDoc(void) {} + virtual bool Find(PGLOBAL g) = 0; + + // Functions + int GetColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt); + void AddColumn(PGLOBAL g, PCSZ colname, PCSZ fmt, int k); + + // Members + BCOL bcol; + PBCOL bcp, fbcp, pbcp; + PMGODEF tdp; + PTDB tmgp; + PCSZ drv; + int *length; + int i, ncol, lvl; + bool all; +}; // end of MGODISC + +/***********************************************************************/ /* MongoDB table. */ /***********************************************************************/ class DllExport MGODEF : public EXTDEF { /* Table description */ - friend class TDBMGO; + friend class TDBCMG; friend class TDBJMG; friend class TDBGOL; friend class TDBJGL; - friend class MGOFAM; + friend class CMGFAM; friend class MGODISC; friend PQRYRES MGOColumns(PGLOBAL, PCSZ, PCSZ, PTOS, bool); public: diff --git a/storage/connect/plugutil.cpp b/storage/connect/plugutil.cpp index f0822526b98..e4bfd825932 100644 --- a/storage/connect/plugutil.cpp +++ b/storage/connect/plugutil.cpp @@ -2,11 +2,11 @@ /* */ /* PROGRAM NAME: PLUGUTIL */ /* ------------- */ -/* Version 2.9 */ +/* Version 3.0 */ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 1993-2015 */ +/* (C) Copyright to the author Olivier BERTRAND 1993-2017 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -76,6 +76,7 @@ #include "osutil.h" #include "global.h" +#include "plgdbsem.h" #if defined(NEWMSG) #include "rcmsg.h" #endif // NEWMSG @@ -132,12 +133,12 @@ void htrc(char const *fmt, ...) /* Return value is the pointer to the Global structure. */ /***********************************************************************/ PGLOBAL PlugInit(LPCSTR Language, uint worksize) - { - PGLOBAL g; +{ + PGLOBAL g; - if (trace > 1) - htrc("PlugInit: Language='%s'\n", - ((!Language) ? "Null" : (char*)Language)); + if (trace > 1) + htrc("PlugInit: Language='%s'\n", + ((!Language) ? "Null" : (char*)Language)); try { g = new GLOBAL; @@ -146,53 +147,54 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize) return NULL; } // end try/catch - //if (!(g = (PGLOBAL)malloc(sizeof(GLOBAL)))) { - // fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL)); - // return NULL; - // } else { - g->Sarea = NULL; - g->Createas = 0; - g->Alchecked = 0; - g->Mrr = 0; - g->Activityp = NULL; - g->Xchk = NULL; - g->N = 0; - g->More = 0; - strcpy(g->Message, ""); - - /*******************************************************************/ - /* Allocate the main work segment. */ - /*******************************************************************/ - if (worksize && !(g->Sarea = PlugAllocMem(g, worksize))) { - char errmsg[MAX_STR]; - sprintf(errmsg, MSG(WORK_AREA), g->Message); - strcpy(g->Message, errmsg); - g->Sarea_Size = 0; - } else - g->Sarea_Size = worksize; - - //} /* endif g */ - - g->jump_level = -1; /* New setting to allow recursive call of Plug */ - return(g); - } /* end of PlugInit */ + g->Sarea = NULL; + g->Createas = 0; + g->Alchecked = 0; + g->Mrr = 0; + g->Activityp = NULL; + g->Xchk = NULL; + g->N = 0; + g->More = 0; + strcpy(g->Message, ""); + + /*******************************************************************/ + /* Allocate the main work segment. */ + /*******************************************************************/ + if (worksize && !(g->Sarea = PlugAllocMem(g, worksize))) { + char errmsg[MAX_STR]; + sprintf(errmsg, MSG(WORK_AREA), g->Message); + strcpy(g->Message, errmsg); + g->Sarea_Size = 0; + } else + g->Sarea_Size = worksize; + + g->jump_level = -1; /* New setting to allow recursive call of Plug */ + return(g); +} /* end of PlugInit */ /***********************************************************************/ /* PlugExit: Terminate Plug operations. */ /***********************************************************************/ int PlugExit(PGLOBAL g) - { - int rc = 0; +{ + if (g) { + PDBUSER dup = PlgGetUser(g); + + if (dup) + free(dup); + + if (g->Sarea) { + if (trace) + htrc("Freeing Sarea size=%d\n", g->Sarea_Size); - if (!g) - return rc; + free(g->Sarea); + } // endif Sarea - if (g->Sarea) - free(g->Sarea); + delete g; + } // endif g - delete g; - return rc; - } /* end of PlugExit */ + return 0; +} // end of PlugExit /***********************************************************************/ /* Remove the file type from a file name. */ @@ -456,7 +458,7 @@ short GetLineLength(PGLOBAL g) /* Program for memory allocation of work and language areas. */ /***********************************************************************/ void *PlugAllocMem(PGLOBAL g, uint size) - { +{ void *areap; /* Pointer to allocated area */ /*********************************************************************/ @@ -465,16 +467,16 @@ void *PlugAllocMem(PGLOBAL g, uint size) if (!(areap = malloc(size))) sprintf(g->Message, MSG(MALLOC_ERROR), "malloc"); - if (trace > 1) { + if (trace) { if (areap) htrc("Memory of %u allocated at %p\n", size, areap); else htrc("PlugAllocMem: %s\n", g->Message); - } // endif trace + } // endif trace return (areap); - } /* end of PlugAllocMem */ +} // end of PlugAllocMem /***********************************************************************/ /* Program for SubSet initialization of memory pools. */ diff --git a/storage/connect/tabmgo.cpp b/storage/connect/tabcmg.cpp index 810785ede80..23ae5219719 100644 --- a/storage/connect/tabmgo.cpp +++ b/storage/connect/tabcmg.cpp @@ -1,7 +1,7 @@ -/************** tabmgo C++ Program Source Code File (.CPP) *************/ -/* PROGRAM NAME: tabmgo Version 1.0 */ +/************** tabcmg C++ Program Source Code File (.CPP) *************/ +/* PROGRAM NAME: tabcmg Version 1.1 */ /* (C) Copyright to the author Olivier BERTRAND 2017 */ -/* This program are the MongoDB class DB execution routines. */ +/* This program are the C MongoDB class DB execution routines. */ /***********************************************************************/ /***********************************************************************/ @@ -22,214 +22,40 @@ #include "maputil.h" #include "filamtxt.h" #include "tabext.h" -#include "tabmgo.h" +#include "tabcmg.h" #include "tabmul.h" -#include "checklvl.h" -#include "resource.h" -#include "mycat.h" // for FNC_COL #include "filter.h" -/***********************************************************************/ -/* This should be an option. */ -/***********************************************************************/ -#define MAXCOL 200 /* Default max column nb in result */ -#define TYPE_UNKNOWN 12 /* Must be greater than other types */ - -bool IsNum(PSZ s); +/* -------------------------- Class CMGDISC -------------------------- */ /***********************************************************************/ -/* MGOColumns: construct the result blocks containing the description */ -/* of all the columns of a document contained inside MongoDB. */ +/* Get document. */ /***********************************************************************/ -PQRYRES MGOColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt, bool info) +void CMGDISC::GetDoc(void) { - 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, - FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT}; - unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0}; - int ncol = sizeof(buftyp) / sizeof(int); - int i, n = 0; - PBCOL bcp; - MGODISC *mgd; - PQRYRES qrp; - PCOLRES crp; - - if (info) { - length[0] = 128; - length[7] = 256; - goto skipit; - } // endif info - - /*********************************************************************/ - /* Open MongoDB. */ - /*********************************************************************/ - mgd = new(g) MGODISC(g, (int*)length); - - if ((n = mgd->GetColumns(g, db, uri, topt)) < 0) - goto err; - -skipit: - if (trace) - htrc("MGOColumns: n=%d len=%d\n", n, length[0]); - - /*********************************************************************/ - /* Allocate the structures used to refer to the result set. */ - /*********************************************************************/ - qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, - buftyp, fldtyp, length, false, false); - - crp = qrp->Colresp->Next->Next->Next->Next->Next->Next; - crp->Name = "Nullable"; - crp->Next->Name = "Bpath"; - - if (info || !qrp) - return qrp; - - qrp->Nblin = n; - - /*********************************************************************/ - /* Now get the results into blocks. */ - /*********************************************************************/ - for (i = 0, bcp = mgd->fbcp; bcp; i++, bcp = bcp->Next) { - if (bcp->Type == TYPE_UNKNOWN) // Void column - bcp->Type = TYPE_STRING; - - crp = qrp->Colresp; // Column Name - crp->Kdata->SetValue(bcp->Name, i); - crp = crp->Next; // Data Type - crp->Kdata->SetValue(bcp->Type, i); - crp = crp->Next; // Type Name - crp->Kdata->SetValue(GetTypeName(bcp->Type), i); - crp = crp->Next; // Precision - crp->Kdata->SetValue(bcp->Len, i); - crp = crp->Next; // Length - crp->Kdata->SetValue(bcp->Len, i); - crp = crp->Next; // Scale (precision) - crp->Kdata->SetValue(bcp->Scale, i); - crp = crp->Next; // Nullable - crp->Kdata->SetValue(bcp->Cbn ? 1 : 0, i); - crp = crp->Next; // Field format - - if (crp->Kdata) - crp->Kdata->SetValue(bcp->Fmt, i); - - } // endfor i - - /*********************************************************************/ - /* Return the result pointer. */ - /*********************************************************************/ - return qrp; - -err: - if (mgd->tmgp) - mgd->tmgp->CloseDB(g); - - return NULL; -} // end of MGOColumns + doc = ((TDBCMG*)tmgp)->Cmgp->Document; +} // end of GetDoc /***********************************************************************/ -/* Class used to get the columns of a mongo collection. */ +/* Analyse passed document. */ /***********************************************************************/ -// Constructor -MGODISC::MGODISC(PGLOBAL g, int *lg) { - length = lg; - fbcp = NULL; - pbcp = NULL; - tmgp = NULL; - n = k = lvl = 0; - all = false; -} // end of MGODISC constructor +//bool CMGDISC::Find(PGLOBAL g, int i, int k, bool b) +bool CMGDISC::Find(PGLOBAL g) +{ + return FindInDoc(g, &iter, doc, NULL, NULL, 0, false); +} // end of Find /***********************************************************************/ -/* Class used to get the columns of a mongo collection. */ +/* Analyse passed document. */ /***********************************************************************/ -int MGODISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt) -{ - PCSZ level; - bson_iter_t iter; - const bson_t *doc; - PMGODEF tdp; - TDBMGO *tmgp = NULL; - - level = GetStringTableOption(g, topt, "Level", NULL); - - if (level) { - lvl = atoi(level); - lvl = (lvl > 16) ? 16 : lvl; - } else - lvl = 0; - - all = GetBooleanTableOption(g, topt, "Fullarray", false); - - /*********************************************************************/ - /* Open the MongoDB collection. */ - /*********************************************************************/ - tdp = new(g) MGODEF; - tdp->Uri = uri; - tdp->Tabname = GetStringTableOption(g, topt, "Name", NULL); - tdp->Tabname = GetStringTableOption(g, topt, "Tabname", tdp->Tabname); - tdp->Tabschema = GetStringTableOption(g, topt, "Dbname", db); - tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; - tdp->Colist = GetStringTableOption(g, topt, "Colist", "all"); - tdp->Filter = GetStringTableOption(g, topt, "Filter", NULL); - tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false); - - if (trace) - htrc("Uri %s coll=%s db=%s colist=%s filter=%s lvl=%d\n", - tdp->Uri, tdp->Tabname, tdp->Tabschema, tdp->Colist, tdp->Filter, lvl); - - tmgp = new(g) TDBMGO(tdp); - tmgp->SetMode(MODE_READ); - - if (tmgp->OpenDB(g)) - return -1; - - bcol.Next = NULL; - bcol.Name = bcol.Fmt = NULL; - bcol.Type = TYPE_UNKNOWN; - bcol.Len = bcol.Scale = 0; - bcol.Found = true; - bcol.Cbn = false; - - /*********************************************************************/ - /* Analyse the BSON tree and define columns. */ - /*********************************************************************/ - for (int i = 1; ; i++) { - switch (tmgp->ReadDB(g)) { - case RC_EF: - return n; - case RC_FX: - return -1; - default: - doc = tmgp->Cmgp->Document; - } // endswitch ReadDB - - if (FindInDoc(g, &iter, doc, NULL, NULL, i, k, false)) - return -1; - - // Missing columns can be null - for (bcp = fbcp; bcp; bcp = bcp->Next) { - bcp->Cbn |= !bcp->Found; - bcp->Found = false; - } // endfor bcp - - } // endfor i - - return n; -} // end of GetColumns - -/*********************************************************************/ -/* Analyse passed document. */ -/*********************************************************************/ -bool MGODISC::FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc, - char *pcn, char *pfmt, int i, int k, bool b) +bool CMGDISC::FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc, + char *pcn, char *pfmt, int k, bool b) { if (!doc || bson_iter_init(iter, doc)) { const char *key; char colname[65]; char fmt[129]; - bool newcol; + bool newcol; while (bson_iter_next(iter)) { key = bson_iter_key(iter); @@ -286,7 +112,7 @@ bool MGODISC::FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc, bson_iter_t child; if (bson_iter_recurse(iter, &child)) - if (FindInDoc(g, &child, NULL, colname, fmt, i, k + 1, false)) + if (FindInDoc(g, &child, NULL, colname, fmt, k + 1, false)) return true; newcol = false; @@ -307,7 +133,7 @@ bool MGODISC::FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc, bson_iter_array(iter, &len, &data); arr = bson_new_from_data(data, len); - if (FindInDoc(g, &itar, arr, colname, fmt, i, k + 1, !all)) + if (FindInDoc(g, &itar, arr, colname, fmt, k + 1, !all)) return true; newcol = false; @@ -315,50 +141,8 @@ bool MGODISC::FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc, } // endif's - if (newcol) { - // Check whether this column was already found - for (bcp = fbcp; bcp; bcp = bcp->Next) - if (!strcmp(colname, bcp->Name)) - break; - - if (bcp) { - if (bcp->Type != bcol.Type) - bcp->Type = TYPE_STRING; - - if (k && *fmt && (!bcp->Fmt || strlen(bcp->Fmt) < strlen(fmt))) { - bcp->Fmt = PlugDup(g, fmt); - length[7] = MY_MAX(length[7], strlen(fmt)); - } // endif *fmt - - bcp->Len = MY_MAX(bcp->Len, bcol.Len); - bcp->Scale = MY_MAX(bcp->Scale, bcol.Scale); - bcp->Cbn |= bcol.Cbn; - bcp->Found = true; - } else { - // New column - bcp = (PBCOL)PlugSubAlloc(g, NULL, sizeof(BCOL)); - *bcp = bcol; - bcp->Cbn |= (i > 1); - bcp->Name = PlugDup(g, colname); - length[0] = MY_MAX(length[0], strlen(colname)); - - if (k) { - bcp->Fmt = PlugDup(g, fmt); - length[7] = MY_MAX(length[7], strlen(fmt)); - } else - bcp->Fmt = NULL; - - if (pbcp) { - bcp->Next = pbcp->Next; - pbcp->Next = bcp; - } else - fbcp = bcp; - - n++; - } // endif jcp - - pbcp = bcp; - } // endif newcol + if (newcol) + AddColumn(g, colname, fmt, k); if (b) break; // Test only first element of arrays @@ -370,12 +154,12 @@ bool MGODISC::FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc, return false; } // end of FindInDoc -/* --------------------------- Class TDBMGO -------------------------- */ +/* --------------------------- Class TDBCMG -------------------------- */ /***********************************************************************/ -/* Implementation of the TDBMGO class. */ +/* Implementation of the TDBCMG class. */ /***********************************************************************/ -TDBMGO::TDBMGO(MGODEF *tdp) : TDBEXT(tdp) +TDBCMG::TDBCMG(MGODEF *tdp) : TDBEXT(tdp) { Cmgp = NULL; Cnd = NULL; @@ -402,9 +186,9 @@ TDBMGO::TDBMGO(MGODEF *tdp) : TDBEXT(tdp) Fpos = -1; N = 0; Done = false; -} // end of TDBMGO standard constructor +} // end of TDBCMG standard constructor -TDBMGO::TDBMGO(TDBMGO *tdbp) : TDBEXT(tdbp) +TDBCMG::TDBCMG(TDBCMG *tdbp) : TDBEXT(tdbp) { Cmgp = tdbp->Cmgp; Cnd = tdbp->Cnd; @@ -413,16 +197,16 @@ TDBMGO::TDBMGO(TDBMGO *tdbp) : TDBEXT(tdbp) Fpos = tdbp->Fpos; N = tdbp->N; Done = tdbp->Done; -} // end of TDBMGO copy constructor +} // end of TDBCMG copy constructor // Used for update -PTDB TDBMGO::Clone(PTABS t) +PTDB TDBCMG::Clone(PTABS t) { PTDB tp; PMGOCOL cp1, cp2; PGLOBAL g = t->G; - tp = new(g) TDBMGO(this); + tp = new(g) TDBCMG(this); for (cp1 = (PMGOCOL)Columns; cp1; cp1 = (PMGOCOL)cp1->GetNext()) if (!cp1->IsSpecial()) { @@ -436,7 +220,7 @@ PTDB TDBMGO::Clone(PTABS t) /***********************************************************************/ /* Allocate JSN column description block. */ /***********************************************************************/ -PCOL TDBMGO::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) +PCOL TDBCMG::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) { PMGOCOL colp = new(g) MGOCOL(g, cdp, this, cprec, n); @@ -446,7 +230,7 @@ PCOL TDBMGO::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) /***********************************************************************/ /* InsertSpecialColumn: Put a special column ahead of the column list.*/ /***********************************************************************/ -PCOL TDBMGO::InsertSpecialColumn(PCOL colp) +PCOL TDBCMG::InsertSpecialColumn(PCOL colp) { if (!colp->IsSpecial()) return NULL; @@ -459,7 +243,7 @@ PCOL TDBMGO::InsertSpecialColumn(PCOL colp) /***********************************************************************/ /* Init: initialize MongoDB processing. */ /***********************************************************************/ -bool TDBMGO::Init(PGLOBAL g) +bool TDBCMG::Init(PGLOBAL g) { if (Done) return false; @@ -482,7 +266,7 @@ bool TDBMGO::Init(PGLOBAL g) /***********************************************************************/ /* MONGO Cardinality: returns table size in number of rows. */ /***********************************************************************/ -int TDBMGO::Cardinality(PGLOBAL g) +int TDBCMG::Cardinality(PGLOBAL g) { if (!g) return 1; @@ -495,7 +279,7 @@ int TDBMGO::Cardinality(PGLOBAL g) /***********************************************************************/ /* MONGO GetMaxSize: returns collection size estimate. */ /***********************************************************************/ -int TDBMGO::GetMaxSize(PGLOBAL g) +int TDBCMG::GetMaxSize(PGLOBAL g) { if (MaxSize < 0) MaxSize = Cardinality(g); @@ -506,7 +290,7 @@ int TDBMGO::GetMaxSize(PGLOBAL g) /***********************************************************************/ /* OpenDB: Data Base open routine for MONGO access method. */ /***********************************************************************/ -bool TDBMGO::OpenDB(PGLOBAL g) +bool TDBCMG::OpenDB(PGLOBAL g) { if (Use == USE_OPEN) { /*******************************************************************/ @@ -540,7 +324,7 @@ bool TDBMGO::OpenDB(PGLOBAL g) /***********************************************************************/ /* Data Base indexed read routine for ODBC access method. */ /***********************************************************************/ -bool TDBMGO::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr) +bool TDBCMG::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr) { strcpy(g->Message, "MONGO tables are not indexable"); return true; @@ -549,7 +333,7 @@ bool TDBMGO::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr) /***********************************************************************/ /* ReadDB: Get next document from a collection. */ /***********************************************************************/ -int TDBMGO::ReadDB(PGLOBAL g) +int TDBCMG::ReadDB(PGLOBAL g) { return Cmgp->ReadNext(g); } // end of ReadDB @@ -557,7 +341,7 @@ int TDBMGO::ReadDB(PGLOBAL g) /***********************************************************************/ /* WriteDB: Data Base write routine for MGO access method. */ /***********************************************************************/ -int TDBMGO::WriteDB(PGLOBAL g) +int TDBCMG::WriteDB(PGLOBAL g) { return Cmgp->Write(g); } // end of WriteDB @@ -565,7 +349,7 @@ int TDBMGO::WriteDB(PGLOBAL g) /***********************************************************************/ /* Data Base delete line routine for MGO access method. */ /***********************************************************************/ -int TDBMGO::DeleteDB(PGLOBAL g, int irc) +int TDBCMG::DeleteDB(PGLOBAL g, int irc) { return (irc == RC_OK) ? WriteDB(g) : RC_OK; } // end of DeleteDB @@ -573,7 +357,7 @@ int TDBMGO::DeleteDB(PGLOBAL g, int irc) /***********************************************************************/ /* Table close routine for MONGO tables. */ /***********************************************************************/ -void TDBMGO::CloseDB(PGLOBAL g) +void TDBCMG::CloseDB(PGLOBAL g) { Cmgp->Close(); Done = false; @@ -587,7 +371,7 @@ void TDBMGO::CloseDB(PGLOBAL g) MGOCOL::MGOCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) : EXTCOL(cdp, tdbp, cprec, i, "MGO") { - Tmgp = (PTDBMGO)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); + Tmgp = (PTDBCMG)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); Jpath = cdp->GetFmt() ? cdp->GetFmt() : cdp->GetName(); } // end of MGOCOL constructor diff --git a/storage/connect/tabmgo.h b/storage/connect/tabcmg.h index 9a4e537eadf..260f2def8a2 100644 --- a/storage/connect/tabmgo.h +++ b/storage/connect/tabcmg.h @@ -1,5 +1,5 @@ -/**************** tabmgo H Declares Source Code File (.H) **************/ -/* Name: tabmgo.h Version 1.1 */ +/**************** tabcmg H Declares Source Code File (.H) **************/ +/* Name: tabcmg.h Version 1.2 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2017 */ /* */ @@ -11,45 +11,46 @@ /***********************************************************************/ /* Class used to get the columns of a mongo collection. */ /***********************************************************************/ -class MGODISC : public BLOCK { +class CMGDISC : public MGODISC { public: // Constructor - MGODISC(PGLOBAL g, int *lg); + CMGDISC(PGLOBAL g, int *lg) : MGODISC(g, lg) { drv = "C"; } - // Functions - int GetColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt); + // Methods + virtual void GetDoc(void); +//virtual bool Find(PGLOBAL g, int i, int k, bool b); + virtual bool Find(PGLOBAL g); + + // BSON Function +//bool FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc, +// char *pcn, char *pfmt, int i, int k, bool b); bool FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc, - char *pcn, char *pfmt, int i, int k, bool b); + char *pcn, char *pfmt, int k, bool b); // Members - BCOL bcol; - PBCOL bcp, fbcp, pbcp; - PMGODEF tdp; - TDBMGO *tmgp; - int *length; - int n, k, lvl; - bool all; -}; // end of MGODISC + bson_iter_t iter; + const bson_t *doc; +}; // end of CMGDISC -/* -------------------------- TDBMGO class --------------------------- */ +/* -------------------------- TDBCMG class --------------------------- */ /***********************************************************************/ /* This is the MongoDB Table Type class declaration. */ /* The table is a collection, each record being a document. */ /***********************************************************************/ -class DllExport TDBMGO : public TDBEXT { +class DllExport TDBCMG : public TDBEXT { friend class MGOCOL; friend class MGODEF; - friend class MGODISC; + friend class CMGDISC; friend PQRYRES MGOColumns(PGLOBAL, PCSZ, PCSZ, PTOS, bool); public: // Constructor - TDBMGO(MGODEF *tdp); - TDBMGO(TDBMGO *tdbp); + TDBCMG(MGODEF *tdp); + TDBCMG(TDBCMG *tdbp); // Implementation virtual AMT GetAmType(void) {return TYPE_AM_MGO;} - virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBMGO(this);} + virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBCMG(this);} // Methods virtual PTDB Clone(PTABS t); @@ -78,7 +79,7 @@ protected: int N; // The current Rownum int B; // Array index base bool Done; // Init done -}; // end of class TDBMGO +}; // end of class TDBCMG /* --------------------------- MGOCOL class -------------------------- */ @@ -86,7 +87,7 @@ protected: /* Class MGOCOL: MongoDB access method column descriptor. */ /***********************************************************************/ class DllExport MGOCOL : public EXTCOL { - friend class TDBMGO; + friend class TDBCMG; friend class FILTER; public: // Constructors @@ -106,7 +107,7 @@ protected: MGOCOL(void) {} // Members - TDBMGO *Tmgp; // To the MGO table block + TDBCMG *Tmgp; // To the MGO table block char *Jpath; // The json path }; // end of class MGOCOL diff --git a/storage/connect/tabjmg.cpp b/storage/connect/tabjmg.cpp index bf147e76cc0..76a6c3aff6c 100644 --- a/storage/connect/tabjmg.cpp +++ b/storage/connect/tabjmg.cpp @@ -27,13 +27,108 @@ #include "mycat.h" // for FNC_COL #include "filter.h" +PQRYRES MGOColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt, bool info); + +/* -------------------------- Class JMGDISC -------------------------- */ + /***********************************************************************/ -/* This should be an option. */ +/* Initialyze. */ /***********************************************************************/ -#define MAXCOL 200 /* Default max column nb in result */ -#define TYPE_UNKNOWN 12 /* Must be greater than other types */ +bool JMGDISC::Init(PGLOBAL g) +{ + if (!(Jcp = ((TDBJMG*)tmgp)->Jcp)) { + strcpy(g->Message, "Init: Jcp is NULL"); + return true; + } else if (Jcp->gmID(g, columnid, "ColumnDesc", + "(Ljava/lang/Object;I[II)Ljava/lang/Object;")) + return true; + else if (Jcp->gmID(g, bvnameid, "ColDescName", "()Ljava/lang/String;")) + return true; + + return false; +} // end of Init + +/***********************************************************************/ +/* Analyse passed document. */ +/***********************************************************************/ +bool JMGDISC::Find(PGLOBAL g) +{ + return ColDesc(g, nullptr, NULL, NULL, Jcp->m_Ncol, 0); +} // end of Find + +/***********************************************************************/ +/* Analyse passed document. */ +/***********************************************************************/ +bool JMGDISC::ColDesc(PGLOBAL g, jobject obj, char *pcn, char *pfmt, + int ncol, int k) +{ + const char *key; + char colname[65]; + char fmt[129]; + bool rc = true; + jint *n = nullptr; + jstring jkey; + jobject jres; + + // Build the java int array + jintArray val = Jcp->env->NewIntArray(5); + + if (val == nullptr) { + strcpy(g->Message, "Cannot allocate jint array"); + return true; + } else if (!ncol) + n = Jcp->env->GetIntArrayElements(val, 0); + + for (int i = 0; i < ncol; i++) { + jres = Jcp->env->CallObjectMethod(Jcp->job, columnid, obj, i, val, lvl - k); + n = Jcp->env->GetIntArrayElements(val, 0); + + if (Jcp->Check(n[0])) { + sprintf(g->Message, "ColDesc: %s", Jcp->Msg); + goto err; + } else if (!n[0]) + continue; + + jkey = (jstring)Jcp->env->CallObjectMethod(Jcp->job, bvnameid); + key = Jcp->env->GetStringUTFChars(jkey, (jboolean)false); + + if (pcn) { + strncpy(colname, pcn, 64); + colname[64] = 0; + strncat(strncat(colname, "_", 65), key, 65); + } else + strcpy(colname, key); + + if (pfmt) { + strncpy(fmt, pfmt, 128); + fmt[128] = 0; + strncat(strncat(fmt, ".", 129), key, 129); + } else + strcpy(fmt, key); -PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info); + if (!jres) { + bcol.Type = n[0]; + bcol.Len = n[1]; + bcol.Scale = n[2]; + bcol.Cbn = n[3]; + AddColumn(g, colname, fmt, k); + } else { + if (n[0] == 2 && !all) + n[4] = MY_MIN(n[4], 1); + + if (ColDesc(g, jres, colname, fmt, n[4], k + 1)) + goto err; + + } // endif jres + + } // endfor i + + rc = false; + + err: + Jcp->env->ReleaseIntArrayElements(val, n, 0); + return rc; +} // end of ColDesc /* --------------------------- Class TDBJMG -------------------------- */ @@ -82,16 +177,6 @@ TDBJMG::TDBJMG(PMGODEF tdp) : TDBEXT(tdp) TDBJMG::TDBJMG(TDBJMG *tdbp) : TDBEXT(tdbp) { Uri = tdbp->Uri; -//Pool = tdbp->Pool; -//Client = tdbp->Client; -//Database = NULL; -//Collection = tdbp->Collection; -//Cursor = tdbp->Cursor; -//Query = tdbp->Query; -//Opts = tdbp->Opts; -//Fpc = tdbp->Fpc; -//Cnd = tdbp->Cnd; -//Uristr = tdbp->Uristr; Db_name = tdbp->Db_name;; Coll_name = tdbp->Coll_name; Options = tdbp->Options; @@ -126,11 +211,7 @@ PTDB TDBJMG::Clone(PTABS t) /***********************************************************************/ PCOL TDBJMG::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) { - PJMGCOL colp = new(g) JMGCOL(g, cdp, this, cprec, n); - -//colp->Mbuf = (char*)PlugSubAlloc(g, NULL, colp->Long + 1); - return colp; - //return (colp->ParseJpath(g)) ? NULL : colp; + return new(g) JMGCOL(g, cdp, this, cprec, n); } // end of MakeCol /***********************************************************************/ @@ -497,12 +578,12 @@ TDBJGL::TDBJGL(PMGODEF tdp) : TDBCAT(tdp) Db = tdp->GetTabschema(); } // end of TDBJCL constructor - /***********************************************************************/ - /* GetResult: Get the list the JSON file columns. */ - /***********************************************************************/ +/***********************************************************************/ +/* GetResult: Get the list the MongoDB collection columns. */ +/***********************************************************************/ PQRYRES TDBJGL::GetResult(PGLOBAL g) { - return JSONColumns(g, Db, Uri, Topt, false); + return MGOColumns(g, Db, Uri, Topt, false); } // end of GetResult - /* -------------------------- End of mongo --------------------------- */ +/* -------------------------- End of mongo --------------------------- */ diff --git a/storage/connect/tabjmg.h b/storage/connect/tabjmg.h index 323fc0bba48..bf16060a92d 100644 --- a/storage/connect/tabjmg.h +++ b/storage/connect/tabjmg.h @@ -9,6 +9,31 @@ #include "jmgoconn.h" #include "jdbccat.h" +/***********************************************************************/ +/* Class used to get the columns of a mongo collection. */ +/***********************************************************************/ +class JMGDISC : public MGODISC { +public: + // Constructor + JMGDISC(PGLOBAL g, int *lg) : MGODISC(g, lg) + { drv = "Java"; Jcp = NULL; columnid = nullptr; } + + // Methods + virtual bool Init(PGLOBAL g); + virtual void GetDoc(void) {} + virtual bool Find(PGLOBAL g); + +protected: + // Function + bool ColDesc(PGLOBAL g, jobject obj, char *pcn, char *pfmt, + int ncol, int k); + + // Members + JMgoConn *Jcp; // Points to a Mongo connection class + jmethodID columnid; // The ColumnDesc method ID + jmethodID bvnameid; // The ColDescName method ID +}; // end of JMGDISC + /* -------------------------- TDBJMG class --------------------------- */ /***********************************************************************/ @@ -18,7 +43,7 @@ class DllExport TDBJMG : public TDBEXT { friend class JMGCOL; friend class MGODEF; - friend class MGODISC; + friend class JMGDISC; friend class JAVAConn; friend PQRYRES MGOColumns(PGLOBAL, PCSZ, PCSZ, PTOS, bool); public: diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index 2deb3e845c3..b22c69b6948 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -1,5 +1,5 @@ /************* tabjson C++ Program Source Code File (.CPP) *************/ -/* PROGRAM NAME: tabjson Version 1.4 */ +/* PROGRAM NAME: tabjson Version 1.5 */ /* (C) Copyright to the author Olivier BERTRAND 2014 - 2017 */ /* This program are the JSON class DB execution routines. */ /***********************************************************************/ @@ -35,7 +35,7 @@ #include "jmgfam.h" #endif // JDBC_SUPPORT #if defined(MONGO_SUPPORT) -#include "mongofam.h" +#include "cmgfam.h" #endif // MONGO_SUPPORT #include "tabmul.h" #include "checklvl.h" @@ -47,7 +47,6 @@ /***********************************************************************/ #define MAXCOL 200 /* Default max column nb in result */ #define TYPE_UNKNOWN 12 /* Must be greater than other types */ -#define USE_G 1 /* Use recoverable memory if 1 */ /***********************************************************************/ /* External functions. */ @@ -55,6 +54,7 @@ USETEMP UseTemp(void); bool IsNum(PSZ s); char *NextChr(PSZ s, char sep); +char *GetJsonNull(void); typedef struct _jncol { struct _jncol *Next; @@ -199,12 +199,12 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) } else if (tdp->Uri) { #if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT) #if !defined(JDBC_SUPPORT) - tjnp = new(g) TDBJSN(tdp, new(g) MGOFAM(tdp)); + tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp)); #elif !defined(MONGO_SUPPORT) tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp)); #else if (tdp->Driver && toupper(*tdp->Driver) == 'C') - tjnp = new(g) TDBJSN(tdp, new(g) MGOFAM(tdp)); + tjnp = new(g) TDBJSN(tdp, new(g) CMGFAM(tdp)); else tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp)); #endif @@ -217,7 +217,6 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) tjnp->SetMode(MODE_READ); -#if USE_G // Allocate the parse work memory PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); memset(G, 0, sizeof(GLOBAL)); @@ -226,9 +225,6 @@ PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info) PlugSubSet(G, G->Sarea, G->Sarea_Size); G->jump_level = 0; tjnp->SetG(G); -#else - tjnp->SetG(g); -#endif if (tjnp->OpenDB(g)) return NULL; @@ -560,12 +556,12 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) if (Uri) { #if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT) #if !defined(JDBC_SUPPORT) - txfp = new(g) MGOFAM(this); + txfp = new(g) CMGFAM(this); #elif !defined(MONGO_SUPPORT) txfp = new(g) JMGFAM(this); #else if (Driver && toupper(*Driver) == 'C') - txfp = new(g) MGOFAM(this); + txfp = new(g) CMGFAM(this); else txfp = new(g) JMGFAM(this); #endif @@ -602,7 +598,6 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) // Txfp must be set for TDBDOS tdbp = new(g) TDBJSN(this, txfp); -#if USE_G if (Lrecl) { // Allocate the parse work memory PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL)); @@ -616,9 +611,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) strcpy(g->Message, "LRECL is not defined"); return NULL; } // endif Lrecl -#else - ((TDBJSN*)tdbp)->G = g; -#endif + } else { if (Zipped) { #if defined(ZIP_SUPPORT) @@ -903,10 +896,8 @@ int TDBJSN::ReadDB(PGLOBAL g) // Deferred reading failed return rc; -#if USE_G // Recover the memory used for parsing PlugSubSet(G, G->Sarea, G->Sarea_Size); -#endif if ((Row = ParseJson(G, To_Line, strlen(To_Line), &Pretty, &Comma))) { Row = FindRow(g); @@ -915,9 +906,7 @@ int TDBJSN::ReadDB(PGLOBAL g) M = 1; rc = RC_OK; } else if (Pretty != 1 || strcmp(To_Line, "]")) { -#if USE_G strcpy(g->Message, G->Message); -#endif rc = RC_FX; } else rc = RC_EF; @@ -1030,9 +1019,7 @@ int TDBJSN::WriteDB(PGLOBAL g) { int rc = TDBDOS::WriteDB(g); -#if USE_G PlugSubSet(G, G->Sarea, G->Sarea_Size); -#endif Row->Clear(); return rc; } // end of WriteDB @@ -1586,8 +1573,11 @@ PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n) for (i = 0; i < ars; i++) { jvrp = arp->GetValue(i); - do { - 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; diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h index 6cdd2993e1f..3ccc43f198d 100644 --- a/storage/connect/tabjson.h +++ b/storage/connect/tabjson.h @@ -40,7 +40,7 @@ class DllExport JSONDEF : public DOSDEF { /* Table description */ friend class JMGFAM; #endif // JDBC_SUPPORT #if defined(MONGO_SUPPORT) - friend class MGOFAM; + friend class CMGFAM; #endif // MONGO_SUPPORT friend PQRYRES JSONColumns(PGLOBAL, PCSZ, PCSZ, PTOS, bool); public: @@ -93,7 +93,7 @@ class DllExport TDBJSN : public TDBDOS { friend class JMGFAM; #endif // JDBC_SUPPORT #if defined(MONGO_SUPPORT) - friend class MGOFAM; + friend class CMGFAM; #endif // MONGO_SUPPORT public: // Constructor @@ -163,7 +163,7 @@ class DllExport JSONCOL : public DOSCOL { friend class JMGFAM; #endif // JDBC_SUPPORT #if defined(MONGO_SUPPORT) - friend class MGOFAM; + friend class CMGFAM; #endif // MONGO_SUPPORT public: // Constructors diff --git a/storage/connect/user_connect.cc b/storage/connect/user_connect.cc index 32119c34900..623c5c466c4 100644 --- a/storage/connect/user_connect.cc +++ b/storage/connect/user_connect.cc @@ -111,7 +111,10 @@ bool user_connect::user_init() int rc= PlugExit(g); g= NULL; - free(dup); + + if (dup) + free(dup); + return true; } // endif g-> @@ -152,10 +155,14 @@ bool user_connect::CheckCleanup(bool force) PlugCleanup(g, true); if (g->Sarea_Size != worksize) { - if (g->Sarea) - free(g->Sarea); + if (g->Sarea) { + if (trace) + htrc("CheckCleanup: Free Sarea %d\n", g->Sarea_Size); + + free(g->Sarea); + } // endif Size - // Check whether the work area size was changed + // Check whether the work area could be allocated if (!(g->Sarea = PlugAllocMem(g, worksize))) { g->Sarea = PlugAllocMem(g, g->Sarea_Size); SetWorkSize(g->Sarea_Size); // Was too big diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 236c8eaba1b..4ea838b0940 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -119,6 +119,7 @@ ulonglong CharToNumber(const char *p, int n, ulonglong maxval, if (minus) *minus = true; } // endif Unsigned + // Fall through case '+': p++; break; @@ -571,7 +572,7 @@ void VALUE::Printf(PGLOBAL g, FILE *f, uint n) if (Null) fprintf(f, "%s<null>\n", m); else - fprintf(f, strcat(strcat(GetCharString(buf), "\n"), m)); + fprintf(f, "%s%s\n", m, GetCharString(buf)); } /* end of Printf */ @@ -2566,7 +2567,7 @@ bool DTVAL::SetValue_pval(PVAL valp, bool chktype) } else if (valp->GetType() == TYPE_BIGINT && !(valp->GetBigintValue() % 1000)) { // Assuming that this timestamp is in milliseconds - Tval = valp->GetBigintValue() / 1000; + Tval = (int)(valp->GetBigintValue() / 1000); } else Tval = valp->GetIntValue(); |