diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 01fe7a6d2b334..a9a6e6732e972 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -290,10 +290,14 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, /****************************************************************************/ static char *strz(PGLOBAL g, LEX_STRING &ls) { - char *str= (char*)PlugSubAlloc(g, NULL, ls.length + 1); + char* str= NULL; + + if (ls.str) { + str= (char*)PlugSubAlloc(g, NULL, ls.length + 1); + memcpy(str, ls.str, ls.length); + str[ls.length] = 0; + } // endif str - memcpy(str, ls.str, ls.length); - str[ls.length]= 0; return str; } // end of strz @@ -5625,7 +5629,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #endif // JAVA_SUPPORT uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL); bool bif, ok= false, dbf= false; - TABTYPE ttp= TAB_UNDEF; + TABTYPE ttp= TAB_UNDEF, ttr=TAB_UNDEF; PQRYRES qrp= NULL; PCOLRES crp; PCONNECT xp= NULL; @@ -5707,7 +5711,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, 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); + push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, 0, g->Message); } else if (ttp == TAB_NIY) { sprintf(g->Message, "Unsupported table type %s", topt->type); rc= HA_ERR_INTERNAL_ERROR; @@ -5715,13 +5719,13 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #if defined(REST_SUPPORT) } else if (topt->http) { if (ttp == TAB_UNDEF) { - topt->type = "JSON"; - 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); - } // endif ttp + ttr= TAB_JSON; + strcpy(g->Message, "No table_type. Was set to JSON"); + push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, 0, g->Message); + } else + ttr= ttp; - switch (ttp) { + switch (ttr) { case TAB_JSON: #if defined(BSON_SUPPORT) case TAB_BSON: @@ -5956,7 +5960,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #if defined(REST_SUPPORT) case TAB_REST: if (!topt->http) - sprintf(g->Message, "Missing %s HTTP address", topt->type); + strcpy(g->Message, "Missing REST HTTP option"); else ok = true; @@ -6176,7 +6180,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, // Restore language type if (ttp == TAB_REST) - ttp = GetTypeID(topt->type); + ttp = ttr; for (i= 0; !rc && i < qrp->Nblin; i++) { typ= len= prec= dec= flg= 0; diff --git a/storage/connect/mongo.cpp b/storage/connect/mongo.cpp index 5f10a89ee67bc..a9c4813684b1f 100644 --- a/storage/connect/mongo.cpp +++ b/storage/connect/mongo.cpp @@ -1,6 +1,6 @@ /************** mongo C++ Program Source Code File (.CPP) **************/ -/* PROGRAM NAME: mongo Version 1.0 */ -/* (C) Copyright to the author Olivier BERTRAND 2017 */ +/* PROGRAM NAME: mongo Version 1.1 */ +/* (C) Copyright to the author Olivier BERTRAND 2021 */ /* These programs are the MGODEF class execution routines. */ /***********************************************************************/ @@ -36,6 +36,7 @@ bool MakeSelector(PGLOBAL g, PFIL fp, PSTRG s); bool IsNum(PSZ s); int GetDefaultDepth(void); +bool JsonAllPath(void); /***********************************************************************/ /* Make selector json representation for Mongo tables. */ @@ -350,7 +351,7 @@ void MGODISC::AddColumn(PGLOBAL g, PCSZ colname, PCSZ fmt, int k) bcp->Name = PlugDup(g, colname); length[0] = MY_MAX(length[0], (signed)strlen(colname)); - if (k) { + if (k || JsonAllPath()) { bcp->Fmt = PlugDup(g, fmt); length[7] = MY_MAX(length[7], (signed)strlen(fmt)); } else @@ -395,6 +396,7 @@ bool MGODEF::DefineAM(PGLOBAL g, LPCSTR, int poff) Uri = GetStringCatInfo(g, "Connect", "mongodb://localhost:27017"); Colist = GetStringCatInfo(g, "Colist", NULL); Filter = GetStringCatInfo(g, "Filter", NULL); + Strfy = GetStringCatInfo(g, "Stringify", NULL); Base = GetIntCatInfo("Base", 0) ? 1 : 0; Version = GetIntCatInfo("Version", 3); diff --git a/storage/connect/mongo.h b/storage/connect/mongo.h index dcefac372c06c..fddc491f2d020 100644 --- a/storage/connect/mongo.h +++ b/storage/connect/mongo.h @@ -1,7 +1,7 @@ /**************** mongo H Declares Source Code File (.H) ***************/ -/* Name: mongo.h Version 1.0 */ +/* Name: mongo.h Version 1.1 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2017 */ +/* (C) Copyright to the author Olivier BERTRAND 2021 */ /* */ /* This file contains the common MongoDB classes declares. */ /***********************************************************************/ @@ -82,6 +82,7 @@ class DllExport MGODEF : public EXTDEF { /* Table description */ PSZ Wrapname; /* Java wrapper name */ PCSZ Colist; /* Options list */ PCSZ Filter; /* Filtering query */ + PCSZ Strfy; /* Stringify column */ int Base; /* The array index base */ int Version; /* The Java driver version */ bool Pipe; /* True is Colist is a pipeline */ diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index c6758b217079d..abffd0b64df96 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -1,5 +1,5 @@ /************* tabbson C++ Program Source Code File (.CPP) *************/ -/* PROGRAM NAME: tabbson Version 1.1 */ +/* PROGRAM NAME: tabbson Version 1.2 */ /* (C) Copyright to the author Olivier BERTRAND 2020 - 2021 */ /* This program are the BSON class DB execution routines. */ /***********************************************************************/ @@ -193,7 +193,11 @@ int BSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) if (!(tdp->Database = SetPath(g, db))) return 0; - tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); + if ((tdp->Objname = GetStringTableOption(g, topt, "Object", NULL))) { + if (*tdp->Objname == '$') tdp->Objname++; + if (*tdp->Objname == '.') tdp->Objname++; + } // endif Objname + tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2); tdp->Xcol = GetStringTableOption(g, topt, "Expand", NULL); @@ -603,33 +607,51 @@ void BSONDISC::AddColumn(PGLOBAL g) /***********************************************************************/ PBVAL BTUTIL::FindRow(PGLOBAL g) { - char *p, *objpath; + char *p, *objpath = PlugDup(g, Tp->Objname); + char *sep = (Tp->Sep == ':') ? ":[" : ".["; + bool bp = false, b = false; PBVAL jsp = Tp->Row; PBVAL val = NULL; - for (objpath = PlugDup(g, Tp->Objname); jsp && objpath; objpath = p) { - if ((p = strchr(objpath, Tp->Sep))) + for (; jsp && objpath; objpath = p, bp = b) { + if ((p = strpbrk(objpath + 1, sep))) { + b = (*p == '['); *p++ = 0; + } // endif p - if (*objpath != '[' && !IsNum(objpath)) { // objpass is a key + if (!bp && *objpath != '[' && !IsNum(objpath)) { // objpass is a key val = (jsp->Type == TYPE_JOB) ? GetKeyValue(jsp, objpath) : NULL; } else { - if (*objpath == '[') { - if (objpath[strlen(objpath) - 1] == ']') - objpath++; - else + if (bp || *objpath == '[') { // Old style + if (objpath[strlen(objpath) - 1] != ']') { + sprintf(g->Message, "Invalid Table path %s", Tp->Objname); return NULL; - } // endif [ + } else if (!bp) + objpath++; + + } // endif bp val = (jsp->Type == TYPE_JAR) ? - GetArrayValue(GetArray(jsp), atoi(objpath) - Tp->B) : NULL; + GetArrayValue(jsp, atoi(objpath) - Tp->B) : NULL; } // endif objpath // jsp = (val) ? val->GetJson() : NULL; jsp = val; } // endfor objpath + if (jsp && jsp->Type != TYPE_JOB) { + if (jsp->Type == TYPE_JAR) { + jsp = GetArrayValue(jsp, Tp->B); + + if (jsp->Type != TYPE_JOB) + jsp = NULL; + + } else + jsp = NULL; + + } // endif Type + return jsp; } // end of FindRow @@ -653,17 +675,22 @@ PBVAL BTUTIL::MakeTopTree(PGLOBAL g, int type) if (Tp->Objname) { if (!Tp->Row) { // Parse and allocate Objpath item(s) - char* p; - char *objpath = PlugDup(g, Tp->Objname); + char *p, *objpath = PlugDup(g, Tp->Objname); + char *sep = (Tp->Sep == ':') ? ":[" : ".["; int i; + bool bp = false, b = false; PBVAL objp = NULL; PBVAL arp = NULL; - for (; objpath; objpath = p) { - if ((p = strchr(objpath, Tp->Sep))) + for (; objpath; objpath = p, bp = b) { + if ((p = strpbrk(objpath + 1, sep))) { + b = (*p == '['); *p++ = 0; + } // endif p - if (*objpath != '[' && !IsNum(objpath)) { + + if (!bp && *objpath != '[' && !IsNum(objpath)) { + // objpass is a key objp = NewVal(TYPE_JOB); if (!top) @@ -675,15 +702,15 @@ PBVAL BTUTIL::MakeTopTree(PGLOBAL g, int type) val = NewVal(); SetKeyValue(objp, MOF(val), objpath); } else { - if (*objpath == '[') { + if (bp || *objpath == '[') { // Old style if (objpath[strlen(objpath) - 1] != ']') { sprintf(g->Message, "Invalid Table path %s", Tp->Objname); return NULL; - } else + } else if (!bp) objpath++; - } // endif objpath + } // endif bp if (!top) top = NewVal(TYPE_JAR); @@ -755,10 +782,16 @@ void BCUTIL::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL jvp) break; case TYPE_DATE: if (jvp->Type == TYPE_STRG) { - if (!((DTVAL*)vp)->IsFormatted()) - ((DTVAL*)vp)->SetFormat(g, "YYYY-MM-DDThh:mm:ssZ", 20, 0); + PSZ dat = GetString(jvp); + + if (!IsNum(dat)) { + if (!((DTVAL*)vp)->IsFormatted()) + ((DTVAL*)vp)->SetFormat(g, "YYYY-MM-DDThh:mm:ssZ", 20, 0); + + vp->SetValue_psz(dat); + } else + vp->SetValue(atoi(dat)); - vp->SetValue_psz(GetString(jvp)); } else vp->SetValue(GetInteger(jvp)); @@ -1156,7 +1189,12 @@ bool BSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) G = g; Schema = GetStringCatInfo(g, "DBname", Schema); Jmode = (JMODE)GetIntCatInfo("Jmode", MODE_OBJECT); - Objname = GetStringCatInfo(g, "Object", NULL); + + if ((Objname = GetStringCatInfo(g, "Object", NULL))) { + if (*Objname == '$') Objname++; + if (*Objname == '.') Objname++; + } // endif Objname + Xcol = GetStringCatInfo(g, "Expand", NULL); Pretty = GetIntCatInfo("Pretty", 2); Limit = GetIntCatInfo("Limit", 50); @@ -1935,6 +1973,10 @@ bool BSONCOL::ParseJpath(PGLOBAL g) // Analyse intermediate array processing if (SetArrayOptions(g, p, i, Nodes[i - 1].Key)) return true; + else if (Xpd && Tbp->Mode == MODE_DELETE) { + strcpy(g->Message, "Cannot delete expanded columns"); + return true; + } // endif Xpd } else if (*p == '*') { // Return JSON @@ -2237,8 +2279,6 @@ int TDBBSON::MakeDocument(PGLOBAL g) return RC_FX; if ((objpath = PlugDup(g, Objname))) { - if (*objpath == '$') objpath++; - if (*objpath == '.') objpath++; p1 = (*objpath == '[') ? objpath++ : NULL; /*********************************************************************/ diff --git a/storage/connect/tabcmg.cpp b/storage/connect/tabcmg.cpp index 1552bdde58a7d..608445bb1ab10 100644 --- a/storage/connect/tabcmg.cpp +++ b/storage/connect/tabcmg.cpp @@ -1,5 +1,5 @@ /************** tabcmg C++ Program Source Code File (.CPP) *************/ -/* PROGRAM NAME: tabcmg Version 1.2 */ +/* PROGRAM NAME: tabcmg Version 1.3 */ /* (C) Copyright to the author Olivier BERTRAND 2017 - 2021 */ /* This program are the C MongoDB class DB execution routines. */ /***********************************************************************/ @@ -192,6 +192,7 @@ TDBCMG::TDBCMG(MGODEF *tdp) : TDBEXT(tdp) Pcg.Line = NULL; Pcg.Pipe = tdp->Pipe && tdp->Colist != NULL; B = tdp->Base ? 1 : 0; + Strfy = tdp->Strfy; } else { Pcg.Uristr = NULL; Pcg.Db_name = NULL; @@ -200,6 +201,7 @@ TDBCMG::TDBCMG(MGODEF *tdp) : TDBEXT(tdp) Pcg.Filter = NULL; Pcg.Line = NULL; Pcg.Pipe = false; + Strfy = NULL; B = 0; } // endif tdp @@ -213,6 +215,7 @@ TDBCMG::TDBCMG(TDBCMG *tdbp) : TDBEXT(tdbp) Cmgp = tdbp->Cmgp; Cnd = tdbp->Cnd; Pcg = tdbp->Pcg; + Strfy = tdbp->Strfy; B = tdbp->B; Fpos = tdbp->Fpos; N = tdbp->N; @@ -394,7 +397,7 @@ MGOCOL::MGOCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) : EXTCOL(cdp, tdbp, cprec, i, "MGO") { Tmgp = (PTDBCMG)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); - Sgfy = false; + Sgfy = (Tmgp->Strfy && !stricmp(Tmgp->Strfy, Name)); if ((Jpath = cdp->GetFmt())) { int n = strlen(Jpath) - 1; diff --git a/storage/connect/tabcmg.h b/storage/connect/tabcmg.h index 44448590da116..0a29a6ce90961 100644 --- a/storage/connect/tabcmg.h +++ b/storage/connect/tabcmg.h @@ -75,6 +75,7 @@ class DllExport TDBCMG : public TDBEXT { CMgoConn *Cmgp; // Points to a C Mongo connection class CMGOPARM Pcg; // Parms passed to Cmgp const Item *Cnd; // The first condition + PCSZ Strfy; // The stringified column int Fpos; // The current row index int N; // The current Rownum int B; // Array index base diff --git a/storage/connect/tabjmg.cpp b/storage/connect/tabjmg.cpp index b02bf6a7f36d8..9271873b8003b 100644 --- a/storage/connect/tabjmg.cpp +++ b/storage/connect/tabjmg.cpp @@ -1,6 +1,6 @@ /************** tabjmg C++ Program Source Code File (.CPP) *************/ -/* PROGRAM NAME: tabjmg Version 1.2 */ -/* (C) Copyright to the author Olivier BERTRAND 2017 */ +/* PROGRAM NAME: tabjmg Version 1.3 */ +/* (C) Copyright to the author Olivier BERTRAND 2021 */ /* This file contains the MongoDB classes using the Java Driver. */ /***********************************************************************/ @@ -166,6 +166,7 @@ TDBJMG::TDBJMG(PMGODEF tdp) : TDBEXT(tdp) Coll_name = tdp->Tabname; Options = tdp->Colist; Filter = tdp->Filter; + Strfy = tdp->Strfy; B = tdp->Base ? 1 : 0; Pipe = tdp->Pipe && Options != NULL; } else { @@ -177,6 +178,7 @@ TDBJMG::TDBJMG(PMGODEF tdp) : TDBEXT(tdp) Coll_name = NULL; Options = NULL; Filter = NULL; + Strfy = NULL; B = 0; Pipe = false; } // endif tdp @@ -197,6 +199,7 @@ TDBJMG::TDBJMG(TDBJMG *tdbp) : TDBEXT(tdbp) Coll_name = tdbp->Coll_name; Options = tdbp->Options; Filter = tdbp->Filter; + Strfy = tdbp->Strfy; B = tdbp->B; Fpos = tdbp->Fpos; N = tdbp->N; @@ -420,7 +423,7 @@ JMGCOL::JMGCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) : EXTCOL(cdp, tdbp, cprec, i, "MGO") { Tmgp = (PTDBJMG)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); - Sgfy = false; + Sgfy = (Tmgp->Strfy && !stricmp(Tmgp->Strfy, Name)); if ((Jpath = cdp->GetFmt())) { int n = strlen(Jpath) - 1; diff --git a/storage/connect/tabjmg.h b/storage/connect/tabjmg.h index e8f08730b8948..bc89319527aab 100644 --- a/storage/connect/tabjmg.h +++ b/storage/connect/tabjmg.h @@ -1,5 +1,5 @@ /**************** tabjmg H Declares Source Code File (.H) **************/ -/* Name: tabjmg.h Version 1.2 */ +/* Name: tabjmg.h Version 1.3 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2017 - 2021 */ /* */ @@ -83,6 +83,7 @@ class DllExport TDBJMG : public TDBEXT { PCSZ Coll_name; PCSZ Options; // The MongoDB options PCSZ Filter; // The filtering query + PCSZ Strfy; // The stringified column PSZ Wrapname; // Java wrapper name int Fpos; // The current row index int N; // The current Rownum diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index cad098e0f9bf8..b05e4ca2c0189 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.8 */ +/* PROGRAM NAME: tabjson Version 1.9 */ /* (C) Copyright to the author Olivier BERTRAND 2014 - 2021 */ /* This program are the JSON class DB execution routines. */ /***********************************************************************/ @@ -191,13 +191,19 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) #endif // ZIP_SUPPORT tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL); - if (!tdp->Fn && topt->http) + if (!tdp->Fn && topt->http) { tdp->Fn = GetStringTableOption(g, topt, "Subtype", NULL); + topt->subtype = NULL; + } // endif fn if (!(tdp->Database = SetPath(g, db))) return 0; - tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); + if ((tdp->Objname = GetStringTableOption(g, topt, "Object", NULL))) { + if (*tdp->Objname == '$') tdp->Objname++; + if (*tdp->Objname == '.') tdp->Objname++; + } // endif Objname + tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2); tdp->Xcol = GetStringTableOption(g, topt, "Expand", NULL); @@ -632,7 +638,12 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { Schema = GetStringCatInfo(g, "DBname", Schema); Jmode = (JMODE)GetIntCatInfo("Jmode", MODE_OBJECT); - Objname = GetStringCatInfo(g, "Object", NULL); + + if ((Objname = GetStringCatInfo(g, "Object", NULL))) { + if (*Objname == '$') Objname++; + if (*Objname == '.') Objname++; + } // endif Objname + Xcol = GetStringCatInfo(g, "Expand", NULL); Pretty = GetIntCatInfo("Pretty", 2); Limit = GetIntCatInfo("Limit", 50); @@ -950,23 +961,29 @@ int TDBJSN::EstimatedLength(void) /***********************************************************************/ PJSON TDBJSN::FindRow(PGLOBAL g) { - char *p, *objpath; + char *p, *objpath = PlugDup(g, Objname); + char *sep = (Sep == ':') ? ":[" : ".["; + bool bp = false, b = false; PJSON jsp = Row; PJVAL val = NULL; - for (objpath = PlugDup(g, Objname); jsp && objpath; objpath = p) { - if ((p = strchr(objpath, Sep))) + for (; jsp && objpath; objpath = p, bp = b) { + if ((p = strpbrk(objpath + 1, sep))) { + b = (*p == '['); *p++ = 0; + } // endif p - if (*objpath != '[' && !IsNum(objpath)) { // objpass is a key + if (!bp && *objpath != '[' && !IsNum(objpath)) { // objpass is a key val = (jsp->GetType() == TYPE_JOB) ? jsp->GetObject()->GetKeyValue(objpath) : NULL; } else { - if (*objpath == '[') { - if (objpath[strlen(objpath) - 1] == ']') - objpath++; - else + if (bp || *objpath == '[') { + if (objpath[strlen(objpath) - 1] != ']') { + sprintf(g->Message, "Invalid Table path %s", Objname); return NULL; + } else if (!bp) + objpath++; + } // endif [ val = (jsp->GetType() == TYPE_JAR) ? @@ -976,6 +993,18 @@ PJSON TDBJSN::FindRow(PGLOBAL g) jsp = (val) ? val->GetJson() : NULL; } // endfor objpath + if (jsp && jsp->GetType() != TYPE_JOB) { + if (jsp->GetType() == TYPE_JAR) { + jsp = jsp->GetArray()->GetArrayValue(B); + + if (jsp->GetType() != TYPE_JOB) + jsp = NULL; + + } else + jsp = NULL; + + } // endif Type + return jsp; } // end of FindRow @@ -1149,20 +1178,23 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) if (Objname) { if (!Val) { // Parse and allocate Objname item(s) - char *p; - char *objpath = PlugDup(g, Objname); + char *p, *objpath = PlugDup(g, Objname); + char *sep = (Sep == ':') ? ":[" : ".["; int i; + bool bp = false, b = false; PJOB objp; PJAR arp; PJVAL val = NULL; Top = NULL; - for (; objpath; objpath = p) { - if ((p = strchr(objpath, Sep))) + for (; objpath; objpath = p, bp = b) { + if ((p = strpbrk(objpath + 1, sep))) { + b = (*p == '['); *p++ = 0; + } // endif p - if (*objpath != '[' && !IsNum(objpath)) { + if (!bp && *objpath != '[' && !IsNum(objpath)) { objp = new(g) JOBJECT; if (!Top) @@ -1174,15 +1206,15 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) val = new(g) JVALUE; objp->SetKeyValue(g, val, objpath); } else { - if (*objpath == '[') { + if (bp || *objpath == '[') { // Old style if (objpath[strlen(objpath) - 1] != ']') { sprintf(g->Message, "Invalid Table path %s", Objname); - return RC_FX; - } else + return NULL; + } else if (!bp) objpath++; - } // endif objpath + } // endif bp arp = new(g) JARRAY; @@ -1537,6 +1569,10 @@ bool JSONCOL::ParseJpath(PGLOBAL g) // Analyse intermediate array processing if (SetArrayOptions(g, p, i, Nodes[i - 1].Key)) return true; + else if (Xpd && Tjp->Mode == MODE_DELETE) { + strcpy(g->Message, "Cannot delete expanded columns"); + return true; + } // endif Xpd } else if (*p == '*') { // Return JSON @@ -1752,10 +1788,16 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL jvp) break; case TYPE_DATE: if (jvp->GetValType() == TYPE_STRG) { - if (!((DTVAL*)vp)->IsFormatted()) - ((DTVAL*)vp)->SetFormat(g, "YYYY-MM-DDThh:mm:ssZ", 20, 0); + PSZ dat = jvp->GetString(g); + + if (!IsNum(dat)) { + if (!((DTVAL*)vp)->IsFormatted()) + ((DTVAL*)vp)->SetFormat(g, "YYYY-MM-DDThh:mm:ssZ", 20, 0); + + vp->SetValue_psz(dat); + } else + vp->SetValue(atoi(dat)); - vp->SetValue_psz(jvp->GetString(g)); } else vp->SetValue(jvp->GetInteger()); diff --git a/storage/connect/tabrest.cpp b/storage/connect/tabrest.cpp index 3b89d5232b759..c66d8d76f3d89 100644 --- a/storage/connect/tabrest.cpp +++ b/storage/connect/tabrest.cpp @@ -1,5 +1,5 @@ /************** tabrest C++ Program Source Code File (.CPP) ************/ -/* PROGRAM NAME: tabrest Version 2.0 */ +/* PROGRAM NAME: tabrest Version 2.1 */ /* (C) Copyright to the author Olivier BERTRAND 2018 - 2021 */ /* This program is the REST Web API support for MariaDB. */ /* The way Connect handles NOSQL data returned by REST queries is */ @@ -37,7 +37,7 @@ #include "tabrest.h" #if defined(connect_EXPORTS) -#define PUSH_WARNING(M) push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0, M) +#define PUSH_WARNING(M) push_warning(current_thd, Sql_condition::WARN_LEVEL_NOTE, 0, M) #else #define PUSH_WARNING(M) htrc(M) #endif @@ -60,12 +60,12 @@ int Xcurl(PGLOBAL g, PCSZ Http, PCSZ Uri, PCSZ filename) if (Uri) { if (*Uri == '/' || Http[strlen(Http) - 1] == '/') - sprintf(buf, "%s%s", Http, Uri); + my_snprintf(buf, sizeof(buf)-1, "%s%s", Http, Uri); else - sprintf(buf, "%s/%s", Http, Uri); + my_snprintf(buf, sizeof(buf)-1, "%s/%s", Http, Uri); } else - strcpy(buf, Http); + my_snprintf(buf, sizeof(buf)-1, "%s", Http); #if defined(_WIN32) char cmd[1024]; diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 1366362dac0f4..8f2cb631feb65 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -2643,9 +2643,9 @@ 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 = (int)(valp->GetBigintValue() / 1000); + SetValue((int)(valp->GetBigintValue() / 1000)); } else - Tval = valp->GetIntValue(); + SetValue(valp->GetIntValue()); } else Reset(); @@ -2736,21 +2736,39 @@ void DTVAL::SetValue_pvblk(PVBLK blk, int n) } // end of SetValue +/***********************************************************************/ +/* DTVAL SetValue: get date as an integer. */ +/***********************************************************************/ +void DTVAL::SetValue(int n) +{ + Tval = n; + + if (Pdtp) { + size_t n = 0, slen = (size_t)Len + 1; + struct tm tm, *ptm= GetGmTime(&tm); + + if (ptm) + n = strftime(Sdate, slen, Pdtp->OutFmt, ptm); + + } // endif Pdtp + +} // end of SetValue + /***********************************************************************/ /* DTVAL GetCharString: get string representation of a date value. */ /***********************************************************************/ char *DTVAL::GetCharString(char *p) { if (Pdtp) { - size_t n = 0; + size_t n = 0, slen = (size_t)Len + 1; struct tm tm, *ptm= GetGmTime(&tm); if (ptm) - n = strftime(Sdate, Len + 1, Pdtp->OutFmt, ptm); + n = strftime(Sdate, slen, Pdtp->OutFmt, ptm); if (!n) { *Sdate = '\0'; - strncat(Sdate, "Error", Len + 1); + strncat(Sdate, "Error", slen); } // endif n return Sdate; diff --git a/storage/connect/value.h b/storage/connect/value.h index df6a55501b6c4..f709c7dbad068 100644 --- a/storage/connect/value.h +++ b/storage/connect/value.h @@ -418,7 +418,8 @@ class DllExport DTVAL : public TYPVAL { virtual bool SetValue_char(const char *p, int n); virtual void SetValue_psz(PCSZ s); virtual void SetValue_pvblk(PVBLK blk, int n); - virtual PSZ GetCharValue(void) { return Sdate; } + virtual void SetValue(int n); + virtual PSZ GetCharValue(void) { return Sdate; } virtual char *GetCharString(char *p); virtual int ShowValue(char *buf, int len); virtual bool FormatValue(PVAL vp, PCSZ fmt);