summaryrefslogtreecommitdiff
path: root/storage/connect/json.cpp
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2017-05-23 19:35:50 +0200
committerOlivier Bertrand <bertrandop@gmail.com>2017-05-23 19:35:50 +0200
commit3e36eb230b65d53acc8e02b00a024e72ed249425 (patch)
treebe89d99353fc70488a5b43707fac12b960f2f29b /storage/connect/json.cpp
parente8333389c89c946d3794ec9ea708d308318301a3 (diff)
downloadmariadb-git-3e36eb230b65d53acc8e02b00a024e72ed249425.tar.gz
Fix gcc compiler warnings reported by Sergei
modified: storage/connect/array.cpp modified: storage/connect/array.h modified: storage/connect/blkfil.cpp modified: storage/connect/blkfil.h modified: storage/connect/block.h modified: storage/connect/colblk.cpp modified: storage/connect/colblk.h modified: storage/connect/csort.h modified: storage/connect/filamvct.cpp modified: storage/connect/filter.cpp modified: storage/connect/filter.h modified: storage/connect/global.h modified: storage/connect/json.h modified: storage/connect/plgdbsem.h modified: storage/connect/plgdbutl.cpp modified: storage/connect/tabcol.cpp modified: storage/connect/tabcol.h modified: storage/connect/tabdos.cpp modified: storage/connect/tabdos.h modified: storage/connect/tabjson.cpp modified: storage/connect/table.cpp modified: storage/connect/tabodbc.cpp modified: storage/connect/tabodbc.h modified: storage/connect/tabsys.h modified: storage/connect/tabxml.h modified: storage/connect/value.cpp modified: storage/connect/value.h modified: storage/connect/xindex.cpp modified: storage/connect/xindex.h modified: storage/connect/xobject.cpp modified: storage/connect/xobject.h modified: storage/connect/xtable.h Set values as nullable when retrieving catalog info modified: storage/connect/jdbconn.cpp modified: storage/connect/mysql-test/connect/r/odbc_oracle.result modified: storage/connect/odbconn.cpp Change format of Jpath modified: storage/connect/json.cpp modified: storage/connect/jsonudf.cpp modified: storage/connect/mysql-test/connect/r/json.result modified: storage/connect/mysql-test/connect/r/json_udf.result modified: storage/connect/mysql-test/connect/r/json_udf_bin.result modified: storage/connect/mysql-test/connect/r/zip.result modified: storage/connect/mysql-test/connect/t/json.test modified: storage/connect/mysql-test/connect/t/json_udf.test modified: storage/connect/mysql-test/connect/t/json_udf_bin.test modified: storage/connect/mysql-test/connect/t/zip.test modified: storage/connect/tabjson.cpp modified: storage/connect/tabjson.h modified: storage/connect/tabmgo.cpp Change null representation from ??? to <null> modified: storage/connect/json.cpp Change the name of UDF that are equal to a native JSON function name modified: storage/connect/jsonudf.cpp modified: storage/connect/jsonudf.h modified: storage/connect/mysql-test/connect/t/json_udf.inc modified: storage/connect/mysql-test/connect/t/json_udf2.inc Fix bug in making JSON project info modified: storage/connect/mongofam.cpp Fix COMPUTE when one argument is null modified: storage/connect/value.cpp Value is null only when nullable modified: storage/connect/value.h
Diffstat (limited to 'storage/connect/json.cpp')
-rw-r--r--storage/connect/json.cpp386
1 files changed, 202 insertions, 184 deletions
diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp
index b473871e9f7..44758e7b0ad 100644
--- a/storage/connect/json.cpp
+++ b/storage/connect/json.cpp
@@ -53,6 +53,36 @@ void trans_func(unsigned int u, _EXCEPTION_POINTERS* pExp)
char *GetExceptionDesc(PGLOBAL g, unsigned int e);
#endif // SE_CATCH
+/***********************************************************************/
+/* IsNum: check whether this string is all digits. */
+/***********************************************************************/
+bool IsNum(PSZ s)
+{
+ for (char *p = s; *p; p++)
+ if (*p == ']')
+ break;
+ else if (!isdigit(*p) || *p == '-')
+ return false;
+
+ return true;
+} // end of IsNum
+
+/***********************************************************************/
+/* NextChr: return the first found '[' or Sep pointer. */
+/***********************************************************************/
+char *NextChr(PSZ s, char sep)
+{
+ char *p1 = strchr(s, '[');
+ char *p2 = strchr(s, sep);
+
+ if (!p2)
+ return p1;
+ else if (p1)
+ return MY_MIN(p1, p2);
+
+ return p2;
+} // end of NextChr
+
/***********************************************************************/
/* Parse a json string. */
@@ -60,7 +90,7 @@ char *GetExceptionDesc(PGLOBAL g, unsigned int e);
/***********************************************************************/
PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma)
{
- int i, rc, pretty = (ptyp) ? *ptyp : 3;
+ int i, pretty = (ptyp) ? *ptyp : 3;
bool b = false, pty[3] = {true, true, true};
PJSON jsp = NULL;
STRG src;
@@ -81,117 +111,91 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma)
if (s[0] == '[' && (s[1] == '\n' || (s[1] == '\r' && s[2] == '\n')))
pty[0] = false;
-
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return NULL;
- } // endif jump_level
-
-#if defined(SE_CATCH)
- // Let's try to recover from any kind of interrupt
- _se_translator_function f = _set_se_translator(trans_func);
-
try {
-#endif // SE_CATCH --------------------- try section --------------------
- if ((rc = setjmp(g->jumper[++g->jump_level])) != 0) {
- goto err;
- } // endif rc
-
-#if defined(SE_CATCH) // ------------- end of try section -----------------
- } catch (SE_Exception e) {
- sprintf(g->Message, "ParseJson: exception doing setjmp: %s (rc=%hd)",
- GetExceptionDesc(g, e.nSE), e.nSE);
- _set_se_translator(f);
- goto err;
- } catch (...) {
- strcpy(g->Message, "Exception doing setjmp");
- _set_se_translator(f);
- goto err;
- } // end of try-catches
-
- _set_se_translator(f);
-#endif // SE_CATCH
-
- for (i = 0; i < len; i++)
- switch (s[i]) {
- case '[':
- if (jsp)
- goto tryit;
- else if (!(jsp = ParseArray(g, ++i, src, pty)))
- goto err;
-
- break;
- case '{':
- if (jsp)
- goto tryit;
- else if (!(jsp = ParseObject(g, ++i, src, pty)))
- goto err;
-
- break;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- break;
- case ',':
- if (jsp && (pretty == 1 || pretty == 3)) {
- if (comma)
- *comma = true;
-
- pty[0] = pty[2] = false;
- break;
- } // endif pretty
-
- sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
- goto err;
- case '(':
- b = true;
- break;
- case ')':
- if (b) {
- b = false;
- break;
- } // endif b
-
- default:
- if (jsp)
- goto tryit;
- else if (!(jsp = ParseValue(g, i, src, pty)))
- goto err;
-
- break;
- }; // endswitch s[i]
-
- if (!jsp)
- sprintf(g->Message, "Invalid Json string '%.*s'", 50, s);
- else if (ptyp && pretty == 3) {
- *ptyp = 3; // Not recognized pretty
-
- for (i = 0; i < 3; i++)
- if (pty[i]) {
- *ptyp = i;
- break;
- } // endif pty
-
- } // endif ptyp
-
- g->jump_level--;
- return jsp;
+ for (i = 0; i < len; i++)
+ switch (s[i]) {
+ case '[':
+ if (jsp)
+ goto tryit;
+ else if (!(jsp = ParseArray(g, ++i, src, pty)))
+ throw 1;
+
+ break;
+ case '{':
+ if (jsp)
+ goto tryit;
+ else if (!(jsp = ParseObject(g, ++i, src, pty)))
+ throw 2;
+
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ case ',':
+ if (jsp && (pretty == 1 || pretty == 3)) {
+ if (comma)
+ *comma = true;
+
+ pty[0] = pty[2] = false;
+ break;
+ } // endif pretty
+
+ sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
+ throw 3;
+ case '(':
+ b = true;
+ break;
+ case ')':
+ if (b) {
+ b = false;
+ break;
+ } // endif b
+
+ default:
+ if (jsp)
+ goto tryit;
+ else if (!(jsp = ParseValue(g, i, src, pty)))
+ throw 4;
+
+ break;
+ }; // endswitch s[i]
+
+ if (!jsp)
+ sprintf(g->Message, "Invalid Json string '%.*s'", 50, s);
+ else if (ptyp && pretty == 3) {
+ *ptyp = 3; // Not recognized pretty
+
+ for (i = 0; i < 3; i++)
+ if (pty[i]) {
+ *ptyp = i;
+ break;
+ } // endif pty
+
+ } // endif ptyp
+
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ jsp = NULL;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ jsp = NULL;
+ } // end catch
+
+ return jsp;
tryit:
if (pty[0] && (!pretty || pretty > 2)) {
if ((jsp = ParseArray(g, (i = 0), src, pty)) && ptyp && pretty == 3)
*ptyp = (pty[0]) ? 0 : 3;
- g->jump_level--;
return jsp;
} else
strcpy(g->Message, "More than one item in file");
-err:
- g->jump_level--;
- return NULL;
+ return NULL;
} // end of ParseJson
/***********************************************************************/
@@ -335,16 +339,16 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty)
PJVAL jvp = new(g) JVALUE;
for (; i < len; i++)
- switch (s[i]) {
- case '\n':
- pty[0] = pty[1] = false;
- case '\r':
- case ' ':
- case '\t':
- break;
- default:
- goto suite;
- } // endswitch
+ switch (s[i]) {
+ case '\n':
+ pty[0] = pty[1] = false;
+ case '\r':
+ case ' ':
+ case '\t':
+ break;
+ default:
+ goto suite;
+ } // endswitch
suite:
switch (s[i]) {
@@ -585,78 +589,75 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src)
PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty)
{
PSZ str = NULL;
- bool b = false, err = true;
- JOUT *jp;
+ bool b = false, err = true;
+ JOUT *jp;
FILE *fs = NULL;
g->Message[0] = 0;
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return NULL;
- } // endif jump_level
-
- if (setjmp(g->jumper[++g->jump_level])) {
- str = NULL;
- goto fin;
- } // endif jmp
-
- if (!jsp) {
- strcpy(g->Message, "Null json tree");
- goto fin;
- } else if (!fn) {
- // Serialize to a string
- jp = new(g) JOUTSTR(g);
- b = pretty == 1;
- } else {
- if (!(fs = fopen(fn, "wb"))) {
- sprintf(g->Message, MSG(OPEN_MODE_ERROR),
- "w", (int)errno, fn);
- strcat(strcat(g->Message, ": "), strerror(errno));
- goto fin;;
- } else if (pretty >= 2) {
- // Serialize to a pretty file
- jp = new(g)JOUTPRT(g, fs);
+ try {
+ if (!jsp) {
+ strcpy(g->Message, "Null json tree");
+ throw 1;
+ } else if (!fn) {
+ // Serialize to a string
+ jp = new(g) JOUTSTR(g);
+ b = pretty == 1;
} else {
- // Serialize to a flat file
- b = true;
- jp = new(g)JOUTFILE(g, fs, pretty);
- } // endif's
-
- } // endif's
-
- switch (jsp->GetType()) {
- case TYPE_JAR:
- err = SerializeArray(jp, (PJAR)jsp, b);
- break;
- case TYPE_JOB:
- err = ((b && jp->Prty()) && jp->WriteChr('\t'));
- err |= SerializeObject(jp, (PJOB)jsp);
- break;
- case TYPE_JVAL:
- err = SerializeValue(jp, (PJVAL)jsp);
- break;
- default:
- strcpy(g->Message, "Invalid json tree");
- } // endswitch Type
+ if (!(fs = fopen(fn, "wb"))) {
+ sprintf(g->Message, MSG(OPEN_MODE_ERROR),
+ "w", (int)errno, fn);
+ strcat(strcat(g->Message, ": "), strerror(errno));
+ throw 2;
+ } else if (pretty >= 2) {
+ // Serialize to a pretty file
+ jp = new(g)JOUTPRT(g, fs);
+ } else {
+ // Serialize to a flat file
+ b = true;
+ jp = new(g)JOUTFILE(g, fs, pretty);
+ } // endif's
+
+ } // endif's
+
+ switch (jsp->GetType()) {
+ case TYPE_JAR:
+ err = SerializeArray(jp, (PJAR)jsp, b);
+ break;
+ case TYPE_JOB:
+ err = ((b && jp->Prty()) && jp->WriteChr('\t'));
+ err |= SerializeObject(jp, (PJOB)jsp);
+ break;
+ case TYPE_JVAL:
+ err = SerializeValue(jp, (PJVAL)jsp);
+ break;
+ default:
+ strcpy(g->Message, "Invalid json tree");
+ } // endswitch Type
+
+ if (fs) {
+ fputs(EL, fs);
+ fclose(fs);
+ str = (err) ? NULL : strcpy(g->Message, "Ok");
+ } else if (!err) {
+ str = ((JOUTSTR*)jp)->Strp;
+ jp->WriteChr('\0');
+ PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
+ } else {
+ if (!g->Message[0])
+ strcpy(g->Message, "Error in Serialize");
- if (fs) {
- fputs(EL, fs);
- fclose(fs);
- str = (err) ? NULL : strcpy(g->Message, "Ok");
- } else if (!err) {
- str = ((JOUTSTR*)jp)->Strp;
- jp->WriteChr('\0');
- PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
- } else {
- if (!g->Message[0])
- strcpy(g->Message, "Error in Serialize");
+ } // endif's
- } // endif's
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ str = NULL;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ str = NULL;
+ } // end catch
-fin:
- g->jump_level--;
return str;
} // end of Serialize
@@ -965,7 +966,7 @@ return false;
/***********************************************************************/
/* Add a new pair to an Object. */
/***********************************************************************/
-PJPR JOBJECT::AddPair(PGLOBAL g, PSZ key)
+PJPR JOBJECT::AddPair(PGLOBAL g, PCSZ key)
{
PJPR jpp = new(g) JPAIR(key);
@@ -1021,7 +1022,24 @@ PSZ JOBJECT::GetText(PGLOBAL g, PSZ text)
if (!First && n)
return NULL;
- else for (PJPR jp = First; jp; jp = jp->Next)
+ else if (n == 1 && Size == 1 && !strcmp(First->GetKey(), "$date")) {
+ int i;
+
+ First->Val->GetText(g, text);
+ i = (text[1] == '-' ? 2 : 1);
+
+ if (IsNum(text + i)) {
+ // Date is in milliseconds
+ int j = (int)strlen(text);
+
+ if (j >= 4 + i)
+ text[j - 3] = 0; // Change it to seconds
+ else
+ strcpy(text, " 0");
+
+ } // endif text
+
+ } else for (PJPR jp = First; jp; jp = jp->Next)
jp->Val->GetText(g, text);
if (n)
@@ -1051,7 +1069,7 @@ bool JOBJECT::Merge(PGLOBAL g, PJSON jsp)
/***********************************************************************/
/* Set or add a value corresponding to the given key. */
/***********************************************************************/
-void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key)
+void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PCSZ key)
{
PJPR jp;
@@ -1071,7 +1089,7 @@ void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key)
/***********************************************************************/
/* Delete a value corresponding to the given key. */
/***********************************************************************/
-void JOBJECT::DeleteKey(PSZ key)
+void JOBJECT::DeleteKey(PCSZ key)
{
PJPR jp, *pjp = &First;
@@ -1250,10 +1268,10 @@ JVALUE::JVALUE(PGLOBAL g, PVAL valp) : JSON()
/***********************************************************************/
/* Constructor for a given string. */
/***********************************************************************/
-JVALUE::JVALUE(PGLOBAL g, PSZ strp) : JSON()
+JVALUE::JVALUE(PGLOBAL g, PCSZ strp) : JSON()
{
Jsp = NULL;
- Value = AllocateValue(g, strp, TYPE_STRING);
+ Value = AllocateValue(g, (void*)strp, TYPE_STRING);
Next = NULL;
Del = false;
} // end of JVALUE constructor
@@ -1341,7 +1359,7 @@ PSZ JVALUE::GetText(PGLOBAL g, PSZ text)
if (s)
strcat(strcat(text, " "), s);
else
- strcat(text, " ???");
+ strcat(text, " <null>");
return text;
} // end of GetText
@@ -1374,7 +1392,7 @@ void JVALUE::SetTiny(PGLOBAL g, char n)
{
Value = AllocateValue(g, &n, TYPE_TINY);
Jsp = NULL;
-} // end of SetInteger
+} // end of SetTiny
/***********************************************************************/
/* Set the Value's value as the given big integer. */
@@ -1408,6 +1426,6 @@ void JVALUE::SetString(PGLOBAL g, PSZ s, short c)
/***********************************************************************/
bool JVALUE::IsNull(void)
{
- return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsZero() : true;
+ return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsNull() : true;
} // end of IsNull