summaryrefslogtreecommitdiff
path: root/storage/connect/tabjson.cpp
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2021-08-02 10:11:41 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2021-08-02 10:11:41 +0200
commit6efb5e9f5e3cd3ec811ae832a67e1878c14f0dea (patch)
treeb7c1a18b8bbc638ee12951d1d04db6d21bebcaed /storage/connect/tabjson.cpp
parent07674e6a741a82d2e30f9798f699209a6c34dfef (diff)
parentec8882b9ddbba2f9fc3571a1ac2ade0dabf412d9 (diff)
downloadmariadb-git-6efb5e9f5e3cd3ec811ae832a67e1878c14f0dea.tar.gz
Merge branch '10.5' into 10.6
Diffstat (limited to 'storage/connect/tabjson.cpp')
-rw-r--r--storage/connect/tabjson.cpp148
1 files changed, 102 insertions, 46 deletions
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index 6ef39391849..07a4712e8b0 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. */
/***********************************************************************/
@@ -58,6 +58,7 @@ USETEMP UseTemp(void);
bool JsonAllPath(void);
int GetDefaultDepth(void);
char *GetJsonNull(void);
+bool Stringified(PCSZ, char*);
/***********************************************************************/
/* JSONColumns: construct the result blocks containing the description */
@@ -178,8 +179,8 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
lvl = GetIntegerTableOption(g, topt, "Depth", lvl);
sep = GetStringTableOption(g, topt, "Separator", ".");
strfy = GetStringTableOption(g, topt, "Stringify", NULL);
- sz = GetIntegerTableOption(g, topt, "Jsize", 250);
- limit = GetIntegerTableOption(g, topt, "Limit", 10);
+ sz = GetIntegerTableOption(g, topt, "Jsize", 1024);
+ limit = GetIntegerTableOption(g, topt, "Limit", 50);
/*********************************************************************/
/* Open the input file. */
@@ -191,13 +192,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);
@@ -222,8 +229,7 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
if (tdp->Uri) {
#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
- tdp->Collname = GetStringTableOption(g, topt, "Name", NULL);
- tdp->Collname = GetStringTableOption(g, topt, "Tabname", tdp->Collname);
+ tdp->Collname = GetStringTableOption(g, topt, "Tabname", NULL);
tdp->Schema = GetStringTableOption(g, topt, "Dbname", "test");
tdp->Options = (PSZ)GetStringTableOption(g, topt, "Colist", "all");
tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false);
@@ -442,7 +448,7 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
jcol.Type = TYPE_UNKNOWN;
jcol.Len = jcol.Scale = 0;
jcol.Cbn = true;
- } else if (j < lvl && !(strfy && !stricmp(strfy, colname))) {
+ } else if (j < lvl && !Stringified(strfy, colname)) {
if (!fmt[bf])
strcat(fmt, colname);
@@ -512,7 +518,7 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
} // endswitch Type
} else if (lvl >= 0) {
- if (strfy && !stricmp(strfy, colname)) {
+ if (Stringified(strfy, colname)) {
if (!fmt[bf])
strcat(fmt, colname);
@@ -633,10 +639,15 @@ 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", 10);
+ Limit = GetIntCatInfo("Limit", 50);
Base = GetIntCatInfo("Base", 0) ? 1 : 0;
Sep = *GetStringCatInfo(g, "Separator", ".");
Accept = GetBoolCatInfo("Accept", false);
@@ -647,7 +658,7 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Collname = GetStringCatInfo(g, "Name",
(Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
Collname = GetStringCatInfo(g, "Tabname", Collname);
- Options = GetStringCatInfo(g, "Colist", NULL);
+ Options = GetStringCatInfo(g, "Colist", Xcol ? "all" : NULL);
Filter = GetStringCatInfo(g, "Filter", NULL);
Pipe = GetBoolCatInfo("Pipeline", false);
Driver = GetStringCatInfo(g, "Driver", NULL);
@@ -716,6 +727,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
#endif // !MONGO_SUPPORT
} // endif Driver
+ Pretty = 4; // Not a file
} else if (Zipped) {
#if defined(ZIP_SUPPORT)
if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) {
@@ -761,7 +773,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
G->jump_level = 0;
((TDBJSN*)tdbp)->G = G;
#endif // 0
- ((TDBJSN*)tdbp)->G = PlugInit(NULL, (size_t)Lrecl * (Pretty >= 0 ? 10 : 2));
+ ((TDBJSN*)tdbp)->G = PlugInit(NULL, (size_t)Lrecl * (Pretty >= 0 ? 12 : 4));
} else {
strcpy(g->Message, "LRECL is not defined");
return NULL;
@@ -950,23 +962,29 @@ int TDBJSN::EstimatedLength(void)
/***********************************************************************/
PJSON TDBJSN::FindRow(PGLOBAL g)
{
- char *p, *objpath;
+ char *p, *objpath = PlugDup(g, Objname);
+ char *sep = (char*)(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 +994,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
@@ -1143,25 +1173,28 @@ int TDBJSN::ReadDB(PGLOBAL g) {
/***********************************************************************/
/* Make the top tree from the object path. */
/***********************************************************************/
-int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
+bool 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 = (char*)(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)
@@ -1173,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 true;
+ } else if (!bp)
objpath++;
- } // endif objpath
+ } // endif bp
arp = new(g) JARRAY;
@@ -1206,7 +1239,7 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
} else
Top = jsp;
- return RC_OK;
+ return false;
} // end of MakeTopTree
/***********************************************************************/
@@ -1276,6 +1309,7 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
Xpd = false;
Parsed = false;
Warned = false;
+ Sgfy = false;
} // end of JSONCOL constructor
/***********************************************************************/
@@ -1295,6 +1329,7 @@ JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
Xpd = col1->Xpd;
Parsed = col1->Parsed;
Warned = col1->Warned;
+ Sgfy = col1->Sgfy;
} // end of JSONCOL copy constructor
/***********************************************************************/
@@ -1534,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
@@ -1567,8 +1606,10 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj)
if (*p1 == '$') p1++;
if (*p1 == '.') p1++;
mgopath = PlugDup(g, p1);
- } else
+ } else {
+ Sgfy = true;
return NULL;
+ } // endif
for (p1 = p2 = mgopath; *p1; p1++)
{
@@ -1607,6 +1648,7 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj)
case '*':
if (*(p2 - 1) == '.' && !*(p1 + 1)) {
p2--; // Suppress last :*
+ Sgfy = true;
break;
} // endif p2
/* falls through */
@@ -1615,6 +1657,10 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj)
break;
} // endswitch p1;
}
+
+ if (*(p2 - 1) == '.')
+ p2--;
+
*p2 = 0;
return mgopath;
} else
@@ -1743,10 +1789,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());
@@ -2125,10 +2177,14 @@ void JSONCOL::WriteColumn(PGLOBAL g)
if (Nodes[Nod-1].Op == OP_XX) {
s = Value->GetCharValue();
- if (!(jsp = ParseJson(G, s, strlen(s)))) {
- strcpy(g->Message, s);
- throw 666;
- } // endif jsp
+ if (s && *s) {
+ if (!(jsp = ParseJson(G, s, strlen(s)))) {
+ strcpy(g->Message, s);
+ throw 666;
+ } // endif jsp
+
+ } else
+ jsp = NULL;
if (arp) {
if (Nod > 1 && Nodes[Nod-2].Op == OP_EQ)
@@ -2557,8 +2613,8 @@ int TDBJSON::WriteDB(PGLOBAL g)
if (Mode == MODE_INSERT) {
Doc->AddArrayValue(g, vp);
Row = new(g) JOBJECT;
- } else if (Doc->SetArrayValue(g, vp, Fpos))
- return RC_FX;
+ } else
+ Doc->SetArrayValue(g, vp, Fpos);
} else if (Jmode == MODE_ARRAY) {
PJVAL vp = new(g) JVALUE(Row);
@@ -2566,15 +2622,15 @@ int TDBJSON::WriteDB(PGLOBAL g)
if (Mode == MODE_INSERT) {
Doc->AddArrayValue(g, vp);
Row = new(g) JARRAY;
- } else if (Doc->SetArrayValue(g, vp, Fpos))
- return RC_FX;
+ } else
+ Doc->SetArrayValue(g, vp, Fpos);
} else { // if (Jmode == MODE_VALUE)
if (Mode == MODE_INSERT) {
Doc->AddArrayValue(g, (PJVAL)Row);
Row = new(g) JVALUE;
- } else if (Doc->SetArrayValue(g, (PJVAL)Row, Fpos))
- return RC_FX;
+ } else
+ Doc->SetArrayValue(g, (PJVAL)Row, Fpos);
} // endif Jmode