summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2021-06-24 00:46:12 +0200
committerOlivier Bertrand <bertrandop@gmail.com>2021-06-24 00:46:12 +0200
commited70f76cf7cbe2195909c5e495a4b18347a7c58c (patch)
tree1343c27f76c886d84e14b8d9254780f6428afb2a /storage
parent5f64276fb2bd4a400927105cf5d536b82e01fbd2 (diff)
downloadmariadb-git-ed70f76cf7cbe2195909c5e495a4b18347a7c58c.tar.gz
- Make function strz return null when LEX_STRING is null
modified: storage/connect/ha_connect.cc - Use NOTE instead of WARNING in connect_assisted_discovery This because MariaDB raise an error when doing so modified: storage/connect/ha_connect.cc modified: storage/connect/tabrest.cpp - Make MONGO tables recognize STRINGIFY and JsonAllPath modified: storage/connect/mongo.cpp modified: storage/connect/mongo.h modified: storage/connect/tabcmg.h modified: storage/connect/tabjmg.cpp modified: storage/connect/tabcmg.cpp modified: storage/connect/tabjmg.h - Fix OBJECT option for Pretty != 2 JSN and BSON tables Accept all syntaxes for the OBJECT option modified: storage/connect/tabbson.cpp modified: storage/connect/tabjson.cpp - Use my_snprintf in function xcurl (by vuvova) modified: storage/connect/tabrest.cpp - Format dates entered as integer when formatted modified: storage/connect/value.cpp modified: storage/connect/value.h
Diffstat (limited to 'storage')
-rw-r--r--storage/connect/ha_connect.cc30
-rw-r--r--storage/connect/mongo.cpp8
-rw-r--r--storage/connect/mongo.h5
-rw-r--r--storage/connect/tabbson.cpp92
-rw-r--r--storage/connect/tabcmg.cpp7
-rw-r--r--storage/connect/tabcmg.h1
-rw-r--r--storage/connect/tabjmg.cpp9
-rw-r--r--storage/connect/tabjmg.h3
-rw-r--r--storage/connect/tabjson.cpp90
-rw-r--r--storage/connect/tabrest.cpp10
-rw-r--r--storage/connect/value.cpp28
-rw-r--r--storage/connect/value.h3
12 files changed, 201 insertions, 85 deletions
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 01fe7a6d2b3..a9a6e6732e9 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 5f10a89ee67..a9c4813684b 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 dcefac372c0..fddc491f2d0 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 @@ protected:
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 c6758b21707..abffd0b64df 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 1552bdde58a..608445bb1ab 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 44448590da1..0a29a6ce909 100644
--- a/storage/connect/tabcmg.h
+++ b/storage/connect/tabcmg.h
@@ -75,6 +75,7 @@ protected:
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 b02bf6a7f36..9271873b800 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 e8f08730b89..bc89319527a 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 @@ protected:
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 cad098e0f9b..b05e4ca2c01 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 3b89d5232b7..c66d8d76f3d 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 1366362dac0..8f2cb631feb 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();
@@ -2737,20 +2737,38 @@ 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 df6a55501b6..f709c7dbad0 100644
--- a/storage/connect/value.h
+++ b/storage/connect/value.h
@@ -418,7 +418,8 @@ class DllExport DTVAL : public TYPVAL<int> {
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);