summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2015-12-21 14:36:24 +0100
committerSergei Golubchik <serg@mariadb.org>2015-12-21 14:36:24 +0100
commit1788bfe93a745582d938a608d5959b7d2e6b2f23 (patch)
tree2c51bc1cc2635335e42d5a5badc160572ab98665
parent7e8e83029f04a568bb0a85f7ffd573c178af4b81 (diff)
parente57876eacf9c74fa3452c793672f220ee8c8135d (diff)
downloadmariadb-git-1788bfe93a745582d938a608d5959b7d2e6b2f23.tar.gz
Merge branch 'connect/10.1' into 10.1
-rw-r--r--storage/connect/CMakeLists.txt4
-rw-r--r--storage/connect/filamzip.cpp7
-rw-r--r--storage/connect/fmdlex.c9
-rw-r--r--storage/connect/ha_connect.cc6
-rw-r--r--storage/connect/json.cpp48
-rw-r--r--storage/connect/json.h10
-rw-r--r--storage/connect/jsonudf.cpp1992
-rw-r--r--storage/connect/jsonudf.h49
-rw-r--r--storage/connect/mycat.cc1
-rw-r--r--storage/connect/mysql-test/connect/r/json_udf.result224
-rw-r--r--storage/connect/mysql-test/connect/r/json_udf_bin.result588
-rw-r--r--storage/connect/mysql-test/connect/std_data/gloss.json22
-rw-r--r--storage/connect/mysql-test/connect/t/json.test2
-rw-r--r--storage/connect/mysql-test/connect/t/json_udf.inc78
-rw-r--r--storage/connect/mysql-test/connect/t/json_udf.test114
-rw-r--r--storage/connect/mysql-test/connect/t/json_udf2.inc24
-rw-r--r--storage/connect/mysql-test/connect/t/json_udf_bin.test212
-rw-r--r--storage/connect/plgdbutl.cpp10
-rw-r--r--storage/connect/tabjson.cpp166
-rw-r--r--storage/connect/tabjson.h49
-rw-r--r--storage/connect/tabxml.cpp18
-rw-r--r--storage/connect/value.cpp8
22 files changed, 2790 insertions, 851 deletions
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt
index eb67215c7e6..f6b42e7f360 100644
--- a/storage/connect/CMakeLists.txt
+++ b/storage/connect/CMakeLists.txt
@@ -28,8 +28,8 @@ tabvct.cpp tabvir.cpp tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp
array.h blkfil.h block.h catalog.h checklvl.h colblk.h connect.h csort.h
engmsg.h filamap.h filamdbf.h filamfix.h filamtxt.h filamvct.h filamzip.h
-filter.h global.h ha_connect.h inihandl.h json.h maputil.h msgid.h mycat.h
-myconn.h myutil.h os.h osutil.h plgcnx.h plgdbsem.h preparse.h reldef.h
+filter.h global.h ha_connect.h inihandl.h json.h jsonudf.h maputil.h msgid.h
+mycat.h myconn.h myutil.h os.h osutil.h plgcnx.h plgdbsem.h preparse.h reldef.h
resource.h tabcol.h tabdos.h tabfix.h tabfmt.h tabjson.h tabmul.h tabmysql.h
taboccur.h tabpivot.h tabsys.h tabtbl.h tabutil.h tabvct.h tabvir.h tabxcl.h
user_connect.h valblk.h value.h xindex.h xobject.h xtable.h)
diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp
index 883ec73e039..d9834e56dcd 100644
--- a/storage/connect/filamzip.cpp
+++ b/storage/connect/filamzip.cpp
@@ -1404,8 +1404,13 @@ void ZLBFAM::Rewind(void)
// We must be positioned after the header block
if (CurBlk >= 0) { // Nothing to do if no block read yet
if (!Optimized) { // If optimized, fseek will be done in ReadBuffer
+ size_t st;
+
rewind(Stream);
- (void) fread(Zlenp, sizeof(int), 1, Stream);
+
+ if (!(st = fread(Zlenp, sizeof(int), 1, Stream)) && trace)
+ htrc("fread error %d in Rewind", errno);
+
fseek(Stream, *Zlenp + sizeof(int), SEEK_SET);
OldBlk = -1;
} // endif Optimized
diff --git a/storage/connect/fmdlex.c b/storage/connect/fmdlex.c
index 22c3a1e79ad..548a7ae5b7e 100644
--- a/storage/connect/fmdlex.c
+++ b/storage/connect/fmdlex.c
@@ -1,3 +1,5 @@
+#include <setjmp.h>
+
#define yyFlexLexer fmdfFlexLexer
#define yy_create_buffer fmdf_create_buffer
#define yy_delete_buffer fmdf_delete_buffer
@@ -506,13 +508,16 @@ YY_MALLOC_DECL
#define YY_BREAK break;
#endif
+static jmp_buf env;
+
YY_DECL
{
register yy_state_type yy_current_state;
register char *yy_cp, *yy_bp;
register int yy_act;
-
+ if (setjmp(env))
+ return -1;
/*************************************************************************/
/* Flex parser to analyze date format and produce input and/or output */
@@ -1316,7 +1321,7 @@ char msg[];
#endif
{
(void) fprintf( stderr, "%s\n", msg );
- exit( 1 );
+ longjmp(env, 1 );
}
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 0ae50e7f9bc..75dfcd22d49 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -169,9 +169,9 @@
#define JSONMAX 10 // JSON Default max grp size
extern "C" {
- char version[]= "Version 1.04.0003 October 25, 2015";
+ char version[]= "Version 1.04.0005 December 11, 2015";
#if defined(__WIN__)
- char compver[]= "Version 1.04.0003 " __DATE__ " " __TIME__;
+ char compver[]= "Version 1.04.0005 " __DATE__ " " __TIME__;
char slash= '\\';
#else // !__WIN__
char slash= '/';
@@ -6762,7 +6762,7 @@ maria_declare_plugin(connect)
0x0104, /* version number (1.04) */
NULL, /* status variables */
connect_system_variables, /* system variables */
- "1.04.0003", /* string version */
+ "1.04.0005", /* string version */
MariaDB_PLUGIN_MATURITY_BETA /* maturity */
}
maria_declare_plugin_end;
diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp
index 19947ab1899..fc7edb84c0f 100644
--- a/storage/connect/json.cpp
+++ b/storage/connect/json.cpp
@@ -534,15 +534,27 @@ 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;
FILE *fs = NULL;
g->Message[0] = 0;
- if (!jsp) {
+ // 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");
- return NULL;
+ goto fin;
} else if (!fn) {
// Serialize to a string
jp = new(g) JOUTSTR(g);
@@ -552,7 +564,7 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty)
sprintf(g->Message, MSG(OPEN_MODE_ERROR),
"w", (int)errno, fn);
strcat(strcat(g->Message, ": "), strerror(errno));
- return g->Message;
+ goto fin;;
} else if (pretty >= 2) {
// Serialize to a pretty file
jp = new(g)JOUTPRT(g, fs);
@@ -582,20 +594,20 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty)
if (fs) {
fputs(EL, fs);
fclose(fs);
- return (err) ? g->Message : NULL;
+ str = (err) ? NULL : "Ok";
} else if (!err) {
- PSZ str = ((JOUTSTR*)jp)->Strp;
-
+ str = ((JOUTSTR*)jp)->Strp;
jp->WriteChr('\0');
PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
- return str;
} else {
if (!g->Message[0])
strcpy(g->Message, "Error in Serialize");
- return NULL;
} // endif's
+fin:
+ g->jump_level--;
+ return str;
} // end of Serialize
/***********************************************************************/
@@ -1096,10 +1108,12 @@ PJVAL JARRAY::AddValue(PGLOBAL g, PJVAL jvp, int *x)
Last = jvp;
} else {
- if (Last)
- Last->Next = jvp;
- else
+ if (!First)
First = jvp;
+ else if (Last == First)
+ First->Next = Last = jvp;
+ else
+ Last->Next = jvp;
Last = jvp;
} // endif x
@@ -1282,6 +1296,18 @@ PSZ JVALUE::GetText(PGLOBAL g, PSZ text)
return text;
} // end of GetText
+void JVALUE::SetValue(PJSON jsp)
+{
+ if (jsp && jsp->GetType() == TYPE_JVAL) {
+ Jsp = jsp->GetJsp();
+ Value = jsp->GetValue();
+ } else {
+ Jsp = jsp;
+ Value = NULL;
+ } // endif Type
+
+} // end of SetValue;
+
/***********************************************************************/
/* Set the Value's value as the given integer. */
/***********************************************************************/
diff --git a/storage/connect/json.h b/storage/connect/json.h
index d2ebc25123d..4ea169e1b18 100644
--- a/storage/connect/json.h
+++ b/storage/connect/json.h
@@ -149,7 +149,7 @@ class JSON : public BLOCK {
virtual JTYP GetType(void) {return TYPE_JSON;}
virtual JTYP GetValType(void) {X return TYPE_JSON;}
virtual void InitArray(PGLOBAL g) {X}
- virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL) {X return NULL;}
+//virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL) {X return NULL;}
virtual PJPR AddPair(PGLOBAL g, PSZ key) {X return NULL;}
virtual PJAR GetKeyList(PGLOBAL g) {X return NULL;}
virtual PJVAL GetValue(const char *key) {X return NULL;}
@@ -223,7 +223,7 @@ class JARRAY : public JSON {
virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JAR;}
virtual PJAR GetArray(void) {return this;}
- virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL);
+ PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL);
virtual void InitArray(PGLOBAL g);
virtual PJVAL GetValue(int i);
virtual bool Merge(PGLOBAL g, PJSON jsp);
@@ -271,9 +271,9 @@ class JVALUE : public JSON {
virtual double GetFloat(void);
virtual PSZ GetString(void);
virtual PSZ GetText(PGLOBAL g, PSZ text);
- virtual void SetValue(PVAL valp) {Value = valp; Jsp = NULL;}
- virtual void SetValue(PJSON jsp) {Jsp = jsp; Value = NULL;}
- virtual void SetString(PGLOBAL g, PSZ s, short c = 0);
+ virtual void SetValue(PJSON jsp);
+ virtual void SetValue(PVAL valp) { Value = valp; Jsp = NULL; }
+ virtual void SetString(PGLOBAL g, PSZ s, short c = 0);
virtual void SetInteger(PGLOBAL g, int n);
virtual void SetBigint(PGLOBAL g, longlong ll);
virtual void SetFloat(PGLOBAL g, double f);
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
index 0b40f1d18cf..40685ae0f0e 100644
--- a/storage/connect/jsonudf.cpp
+++ b/storage/connect/jsonudf.cpp
@@ -36,7 +36,7 @@ static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i);
/*********************************************************************************/
/* JSNX public constructor. */
/*********************************************************************************/
-JSNX::JSNX(PGLOBAL g, PJSON row, int type, int len, int prec)
+JSNX::JSNX(PGLOBAL g, PJSON row, int type, int len, int prec, my_bool wr)
{
Row = row;
Jvalp = NULL;
@@ -58,6 +58,8 @@ JSNX::JSNX(PGLOBAL g, PJSON row, int type, int len, int prec)
Xpd = false;
Parsed = false;
Found = false;
+ Wr = wr;
+ Jb = false;
} // end of JSNX constructor
/*********************************************************************************/
@@ -71,6 +73,7 @@ my_bool JSNX::SetJpath(PGLOBAL g, char *path, my_bool jb)
Value->SetNullable(true);
+#if 0
if (jb) {
// Path must return a Json item
size_t n = strlen(path);
@@ -82,9 +85,13 @@ my_bool JSNX::SetJpath(PGLOBAL g, char *path, my_bool jb)
Jpath = path;
} else
+#endif // 0
Jpath = path;
// Parse the json path
+ Parsed = false;
+ Nod = 0;
+ Jb = jb;
return ParseJpath(g);
} // end of SetJpath
@@ -117,7 +124,14 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
if (!n) {
// Default specifications
if (jnp->Op != OP_EXP) {
- if (b) {
+ if (Wr) {
+ // Force append
+ jnp->Rank = INT_MAX32;
+ jnp->Op = OP_LE;
+ } else if (Jb) {
+ // Return a Json item
+ jnp->Op = OP_XX;
+ } else if (b) {
// Return 1st value (B is the index base)
jnp->Rank = B;
jnp->Op = OP_LE;
@@ -133,6 +147,9 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
// Return nth value
jnp->Rank = atoi(p) - B;
jnp->Op = OP_EQ;
+ } else if (Wr) {
+ sprintf(g->Message, "Invalid specification %s in a write path", p);
+ return true;
} else if (n == 1) {
// Set the Op value;
switch (*p) {
@@ -240,8 +257,12 @@ my_bool JSNX::ParseJpath(PGLOBAL g)
return true;
} else if (*p == '*') {
- // Return JSON
- Nodes[i].Op = OP_XX;
+ if (Wr) {
+ sprintf(g->Message, "Invalid specification %c in a write path", *p);
+ return true;
+ } else // Return JSON
+ Nodes[i].Op = OP_XX;
+
} else {
Nodes[i].Key = p;
Nodes[i].Op = OP_EXIST;
@@ -262,7 +283,10 @@ PVAL JSNX::MakeJson(PGLOBAL g, PJSON jsp)
if (Value->IsTypeNum()) {
strcpy(g->Message, "Cannot make Json for a numeric value");
Value->Reset();
- } else
+ } else if (jsp->GetType() != TYPE_JAR && jsp->GetType() != TYPE_JOB) {
+ strcpy(g->Message, "Target is not an array or object");
+ Value->Reset();
+ } else
Value->SetValue_psz(Serialize(g, jsp, NULL, 0));
return Value;
@@ -274,32 +298,34 @@ PVAL JSNX::MakeJson(PGLOBAL g, PJSON jsp)
void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
{
if (val) {
- switch (val->GetValType()) {
- case TYPE_STRG:
- case TYPE_INTG:
- case TYPE_BINT:
- case TYPE_DBL:
- vp->SetValue_pval(val->GetValue());
- break;
- case TYPE_BOOL:
- if (vp->IsTypeNum())
- vp->SetValue(val->GetInteger() ? 1 : 0);
- else
- vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false"));
+ if (Jb) {
+ vp->SetValue_psz(Serialize(g, val->GetJsp(), NULL, 0));
+ } else switch (val->GetValType()) {
+ case TYPE_STRG:
+ case TYPE_INTG:
+ case TYPE_BINT:
+ case TYPE_DBL:
+ vp->SetValue_pval(val->GetValue());
+ break;
+ case TYPE_BOOL:
+ if (vp->IsTypeNum())
+ vp->SetValue(val->GetInteger() ? 1 : 0);
+ else
+ vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false"));
- break;
- case TYPE_JAR:
- SetJsonValue(g, vp, val->GetArray()->GetValue(0), n);
- break;
- case TYPE_JOB:
- // if (!vp->IsTypeNum() || !Strict) {
- vp->SetValue_psz(val->GetObject()->GetText(g, NULL));
- break;
- // } // endif Type
+ break;
+ case TYPE_JAR:
+ SetJsonValue(g, vp, val->GetArray()->GetValue(0), n);
+ break;
+ case TYPE_JOB:
+ // if (!vp->IsTypeNum() || !Strict) {
+ vp->SetValue_psz(val->GetObject()->GetText(g, NULL));
+ break;
+ // } // endif Type
- default:
- vp->Reset();
- } // endswitch Type
+ default:
+ vp->Reset();
+ } // endswitch Type
} else {
vp->SetNull(true);
@@ -313,7 +339,7 @@ void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
/*********************************************************************************/
PJVAL JSNX::GetJson(PGLOBAL g)
{
- return GetValue(g, Row, 0);
+ return GetRowValue(g, Row, 0);
} // end of GetJson
/*********************************************************************************/
@@ -332,17 +358,16 @@ PVAL JSNX::GetColumnValue(PGLOBAL g, PJSON row, int i)
int n = Nod - 1;
PJVAL val = NULL;
- val = GetValue(g, row, i);
+ val = GetRowValue(g, row, i);
SetJsonValue(g, Value, val, n);
return Value;
} // end of GetColumnValue
/*********************************************************************************/
-/* GetValue: */
+/* GetRowValue: */
/*********************************************************************************/
-PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i, my_bool b)
+PJVAL JSNX::GetRowValue(PGLOBAL g, PJSON row, int i, my_bool b)
{
-//int n = Nod - 1;
my_bool expd = false;
PJAR arp;
PJVAL val = NULL;
@@ -353,11 +378,8 @@ PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i, my_bool b)
val = new(g) JVALUE(g, Value);
return val;
} else if (Nodes[i].Op == OP_XX) {
- if (b)
- return new(g)JVALUE(g, MakeJson(g, row));
- else
- return new(g)JVALUE(row);
-
+ Jb = b;
+ return new(g)JVALUE(row);
} else switch (row->GetType()) {
case TYPE_JOB:
if (!Nodes[i].Key) {
@@ -388,11 +410,11 @@ PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i, my_bool b)
else
return new(g) JVALUE(g, CalculateArray(g, arp, i));
- } else if (i < Nod-1) {
- strcpy(g->Message, "Unexpected array");
- val = NULL; // Not an expected array
- } else
+ } else {
+ // Unexpected array, unwrap it as [0]
val = arp->GetValue(0);
+ i--;
+ } // endif's
break;
case TYPE_JVAL:
@@ -404,13 +426,15 @@ PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i, my_bool b)
} // endswitch Type
if (i < Nod-1)
- row = (val) ? val->GetJson() : NULL;
+ if (!(row = (val) ? val->GetJsp() : NULL))
+ val = NULL;
+// row = (val) ? val->GetJson() : NULL;
} // endfor i
// SetJsonValue(g, Value, val, n);
return val;
-} // end of GetValue
+} // end of GetRowValue
/*********************************************************************************/
/* ExpandArray: */
@@ -503,6 +527,166 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
} // end of CalculateArray
/*********************************************************************************/
+/* CheckPath: Checks whether the path exists in the document. */
+/*********************************************************************************/
+my_bool JSNX::CheckPath(PGLOBAL g)
+{
+ PJVAL val;
+ PJSON row = Row;
+
+ for (int i = 0; i < Nod && row; i++) {
+ val = NULL;
+
+ if (Nodes[i].Op == OP_NUM || Nodes[i].Op == OP_XX) {
+ } else switch (row->GetType()) {
+ case TYPE_JOB:
+ if (Nodes[i].Key)
+ val = ((PJOB)row)->GetValue(Nodes[i].Key);
+
+ break;
+ case TYPE_JAR:
+ if (!Nodes[i].Key)
+ if (Nodes[i].Op == OP_EQ || Nodes[i].Op == OP_LE)
+ val = ((PJAR)row)->GetValue(Nodes[i].Rank);
+
+ break;
+ case TYPE_JVAL:
+ val = (PJVAL)row;
+ break;
+ default:
+ sprintf(g->Message, "Invalid row JSON type %d", row->GetType());
+ } // endswitch Type
+
+ if (i < Nod-1)
+ if (!(row = (val) ? val->GetJsp() : NULL))
+ val = NULL;
+
+ } // endfor i
+
+ return (val != NULL);
+} // end of CheckPath
+
+/***********************************************************************/
+/* GetRow: Set the complete path of the object to be set. */
+/***********************************************************************/
+PJSON JSNX::GetRow(PGLOBAL g)
+{
+ PJVAL val = NULL;
+ PJAR arp;
+ PJSON nwr, row = Row;
+
+ for (int i = 0; i < Nod - 1 && row; i++) {
+ if (Nodes[i].Op == OP_XX)
+ break;
+ else switch (row->GetType()) {
+ case TYPE_JOB:
+ if (!Nodes[i].Key)
+ // Expected Array was not there, wrap the value
+ continue;
+
+ val = ((PJOB)row)->GetValue(Nodes[i].Key);
+ break;
+ case TYPE_JAR:
+ arp = (PJAR)row;
+
+ if (!Nodes[i].Key) {
+ if (Nodes[i].Op == OP_EQ)
+ val = arp->GetValue(Nodes[i].Rank);
+ else
+ val = arp->GetValue(Nodes[i].Rx);
+
+ } else {
+ // Unexpected array, unwrap it as [0]
+ val = arp->GetValue(0);
+ i--;
+ } // endif Nodes
+
+ break;
+ case TYPE_JVAL:
+ val = (PJVAL)row;
+ break;
+ default:
+ sprintf(g->Message, "Invalid row JSON type %d", row->GetType());
+ val = NULL;
+ } // endswitch Type
+
+ if (val) {
+ row = val->GetJson();
+ } else {
+ // Construct missing objects
+ for (i++; row && i < Nod; i++) {
+ if (Nodes[i].Op == OP_XX)
+ break;
+ else if (!Nodes[i].Key)
+ // Construct intermediate array
+ nwr = new(g)JARRAY;
+ else
+ nwr = new(g)JOBJECT;
+
+ if (row->GetType() == TYPE_JOB) {
+ ((PJOB)row)->SetValue(g, new(g)JVALUE(nwr), Nodes[i-1].Key);
+ } else if (row->GetType() == TYPE_JAR) {
+ ((PJAR)row)->AddValue(g, new(g)JVALUE(nwr));
+ ((PJAR)row)->InitArray(g);
+ } else {
+ strcpy(g->Message, "Wrong type when writing new row");
+ nwr = NULL;
+ } // endif's
+
+ row = nwr;
+ } // endfor i
+
+ break;
+ } // endelse
+
+ } // endfor i
+
+ return row;
+} // end of GetRow
+
+/***********************************************************************/
+/* WriteValue: */
+/***********************************************************************/
+my_bool JSNX::WriteValue(PGLOBAL g, PJVAL jvalp)
+{
+ PJOB objp = NULL;
+ PJAR arp = NULL;
+ PJVAL jvp = NULL;
+ PJSON row = GetRow(g);
+
+ if (!row)
+ return true;
+
+ switch (row->GetType()) {
+ case TYPE_JOB: objp = (PJOB)row; break;
+ case TYPE_JAR: arp = (PJAR)row; break;
+ case TYPE_JVAL: jvp = (PJVAL)row; break;
+ default:
+ strcpy(g->Message, "Invalid target type");
+ return true;
+ } // endswitch Type
+
+ if (arp) {
+ if (!Nodes[Nod-1].Key) {
+ if (Nodes[Nod-1].Op == OP_EQ)
+ arp->SetValue(g, jvalp, Nodes[Nod-1].Rank);
+ else
+ arp->AddValue(g, jvalp);
+
+ arp->InitArray(g);
+ } // endif Key
+
+ } else if (objp) {
+ if (Nodes[Nod-1].Key)
+ objp->SetValue(g, jvalp, Nodes[Nod-1].Key);
+
+ } else if (jvp)
+ jvp->SetValue(jvalp);
+
+ return false;
+} // end of WriteValue
+
+/*********************************************************************************/
/* Locate a value in a JSON tree: */
/*********************************************************************************/
PSZ JSNX::Locate(PGLOBAL g, PJSON jsp, PJVAL jvp, int k)
@@ -802,15 +986,17 @@ my_bool JSNX::AddPath(void)
/* --------------------------------- JSON UDF ---------------------------------- */
-#define BMX (_MAX_PATH - 1)
+// BSON size should be equal on Linux and Windows
+#define BMX 255
typedef struct BSON *PBSON;
/*********************************************************************************/
/* Structure used to return binary json. */
/*********************************************************************************/
struct BSON {
- char Msg[_MAX_PATH];
+ char Msg[BMX + 1];
char *Filename;
+ PGLOBAL G;
int Pretty;
ulong Reslen;
my_bool Changed;
@@ -824,16 +1010,21 @@ struct BSON {
/*********************************************************************************/
static PBSON JbinAlloc(PGLOBAL g, UDF_ARGS *args, ulong len, PJSON jsp)
{
- PBSON bsp = (PBSON)PlugSubAlloc(g, NULL, sizeof(BSON));
+ PBSON bsp = (PBSON)PlgDBSubAlloc(g, NULL, sizeof(BSON));
+
+ if (bsp) {
+ strcpy(bsp->Msg, "Binary Json");
+ bsp->Msg[BMX] = 0;
+ bsp->Filename = NULL;
+ bsp->G = g;
+ bsp->Pretty = 2;
+ bsp->Reslen = len;
+ bsp->Changed = false;
+ bsp->Top = bsp->Jsp = jsp;
+ bsp->Bsp = (IsJson(args, 0) == 3) ? (PBSON)args->args[0] : NULL;
+ } else
+ PUSH_WARNING(g->Message);
- strcpy(bsp->Msg, "Binary Json");
- bsp->Msg[BMX] = 0;
- bsp->Filename = NULL;
- bsp->Pretty = 2;
- bsp->Reslen = len;
- bsp->Changed = false;
- bsp->Top = bsp->Jsp = jsp;
- bsp->Bsp = (IsJson(args, 0) == 3) ? (PBSON)args->args[0] : NULL;
return bsp;
} /* end of JbinAlloc */
@@ -942,8 +1133,7 @@ static char *MakeResult(PGLOBAL g, UDF_ARGS *args, PJSON top, uint n = 2)
if (IsJson(args, 0) == 2) {
// Make the change in the json file
- char *msg;
- int pretty = 2;
+ int pretty = 2;
for (uint i = n; i < args->arg_count; i++)
if (args->arg_type[i] == INT_RESULT) {
@@ -951,8 +1141,8 @@ static char *MakeResult(PGLOBAL g, UDF_ARGS *args, PJSON top, uint n = 2)
break;
} // endif type
- if ((msg = Serialize(g, top, MakePSZ(g, args, 0), pretty)))
- PUSH_WARNING(msg);
+ if (!Serialize(g, top, MakePSZ(g, args, 0), pretty))
+ PUSH_WARNING(g->Message);
str = NULL;
} else if (IsJson(args, 0) == 3) {
@@ -960,10 +1150,8 @@ static char *MakeResult(PGLOBAL g, UDF_ARGS *args, PJSON top, uint n = 2)
if (bsp->Filename) {
// Make the change in the json file
- char *msg;
-
- if ((msg = Serialize(g, top, bsp->Filename, bsp->Pretty)))
- PUSH_WARNING(msg);
+ if (!Serialize(g, top, bsp->Filename, bsp->Pretty))
+ PUSH_WARNING(g->Message);
str = bsp->Filename;
} else if (!(str = Serialize(g, top, NULL, 0)))
@@ -983,8 +1171,11 @@ static PBSON MakeBinResult(PGLOBAL g, UDF_ARGS *args, PJSON top, ulong len, int
{
PBSON bsnp = JbinAlloc(g, args, len, top);
+ if (!bsnp)
+ return NULL;
+
if (IsJson(args, 0) == 2) {
- int pretty = 2;
+ int pretty = 0;
for (uint i = n; i < args->arg_count; i++)
if (args->arg_type[i] == INT_RESULT) {
@@ -994,9 +1185,10 @@ static PBSON MakeBinResult(PGLOBAL g, UDF_ARGS *args, PJSON top, ulong len, int
bsnp->Pretty = pretty;
- if (bsnp->Filename = (char*)args->args[0])
- strncpy(bsnp->Msg, (char*)args->args[0], BMX);
- else
+ if (bsnp->Filename = (char*)args->args[0]) {
+ bsnp->Filename = MakePSZ(g, args, 0);
+ strncpy(bsnp->Msg, bsnp->Filename, BMX);
+ } else
strncpy(bsnp->Msg, "null filename", BMX);
} else if (IsJson(args, 0) == 3) {
@@ -1063,6 +1255,14 @@ static int IsJson(UDF_ARGS *args, uint i)
} // end of IsJson
/*********************************************************************************/
+/* GetMemPtr: returns the memory pointer used by this argument. */
+/*********************************************************************************/
+static PGLOBAL GetMemPtr(PGLOBAL g, UDF_ARGS *args, uint i)
+{
+ return (IsJson(args, i) == 3) ? ((PBSON)args->args[i])->G : g;
+} // end of GetMemPtr
+
+/*********************************************************************************/
/* GetFileLength: returns file size in number of bytes. */
/*********************************************************************************/
static long GetFileLength(char *fn)
@@ -1161,8 +1361,8 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
} else
memlen += sizeof(JARRAY);
- switch (args->arg_type[i]) {
- case STRING_RESULT:
+ switch (args->arg_type[i]) {
+ case STRING_RESULT:
if (n == 2 && args->args[i]) {
if ((signed)i != j) {
m = MY_MIN(args->lengths[i], sizeof(fn) - 1);
@@ -1173,11 +1373,14 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
} // endif i
memlen += fl * M;
- } else if (IsJson(args, i) == 3)
- memlen += sizeof(JVALUE);
- else if (IsJson(args, i) == 1)
+ } else if (n == 1) {
+ if (i == 0)
+ memlen += sizeof(BSON); // For Jbin functions
+
memlen += args->lengths[i] * M; // Estimate parse memory
-
+ } else if (n == 3)
+ memlen += sizeof(JVALUE);
+
memlen += sizeof(TYPVAL<PSZ>);
break;
case INT_RESULT:
@@ -1202,18 +1405,32 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
/*********************************************************************************/
/* Check if the calculated memory is enough. */
/*********************************************************************************/
-static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args,
- uint n, my_bool obj, my_bool mod = false)
+static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args, uint n,
+ my_bool m, my_bool obj = false, my_bool mod = false)
{
unsigned long rl, ml;
+ my_bool b = false;
- n = MY_MIN(n, args->arg_count);
+ n = MY_MIN(n, args->arg_count);
for (uint i = 0; i < n; i++)
- if (IsJson(args, i) == 2) {
+ if (IsJson(args, i) == 2 ||
+ (b = (m && !i && args->arg_type[0] == STRING_RESULT && !IsJson(args, 0)))) {
if (CalcLen(args, obj, rl, ml, mod))
return true;
- else if (ml > g->Sarea_Size) {
+ else if (b) {
+ ulong len;
+ char *p = args->args[0];
+
+ // Is this a file name?
+ if (!strchr("[{ \t\r\n", *p) && (len = GetFileLength(p)))
+ ml += len * (M + 1);
+ else
+ ml += args->lengths[0] * M;
+
+ } // endif b
+
+ if (ml > g->Sarea_Size) {
free(g->Sarea);
if (!(g->Sarea = PlugAllocMem(g, ml))) {
@@ -1588,7 +1805,7 @@ char *json_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result,
PGLOBAL g = (PGLOBAL)initid->ptr;
if (!g->Xchk) {
- if (!CheckMemory(g, initid, args, args->arg_count, false)) {
+ if (!CheckMemory(g, initid, args, args->arg_count, true)) {
char *p;
PJSON top;
PJAR arp;
@@ -1672,7 +1889,7 @@ char *json_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
goto fin;
} // endif Xchk
- if (!CheckMemory(g, initid, args, 2, false, true)) {
+ if (!CheckMemory(g, initid, args, 2, false, false, true)) {
int *x;
uint n = 2;
PJSON jsp, top;
@@ -1686,9 +1903,11 @@ char *json_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (CheckPath(g, args, jsp, jvp, 2))
PUSH_WARNING(g->Message);
else if (jvp && jvp->GetValType() == TYPE_JAR) {
+ PGLOBAL gb = GetMemPtr(g, args, 0);
+
arp = jvp->GetArray();
- arp->AddValue(g, MakeValue(g, args, 1), x);
- arp->InitArray(g);
+ arp->AddValue(gb, MakeValue(gb, args, 1), x);
+ arp->InitArray(gb);
str = MakeResult(g, args, top, n);
} else {
PUSH_WARNING("First argument target is not an array");
@@ -1705,10 +1924,11 @@ char *json_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = str;
-fin:
+ fin:
if (!str) {
*res_length = 0;
*is_null = 1;
+ *error = 1;
} else
*res_length = strlen(str);
@@ -1740,7 +1960,7 @@ my_bool json_array_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of json_array_delete_init
char *json_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
char *str = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -1748,11 +1968,10 @@ char *json_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (g->Xchk) {
// This constant function was recalled
str = (char*)g->Xchk;
- *res_length = strlen(str);
- return str;
+ goto fin;
} // endif Xchk
- if (!CheckMemory(g, initid, args, 1, false, true)) {
+ if (!CheckMemory(g, initid, args, 1, false, false, true)) {
int *x;
uint n = 1;
PJSON top;
@@ -1766,7 +1985,7 @@ char *json_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
else if (jvp && jvp->GetValType() == TYPE_JAR) {
arp = jvp->GetArray();
arp->DeleteValue(*x);
- arp->InitArray(g);
+ arp->InitArray(GetMemPtr(g, args, 0));
str = MakeResult(g, args, top, n);
} else {
PUSH_WARNING("First argument target is not an array");
@@ -1783,7 +2002,14 @@ char *json_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = str;
- *res_length = (str) ? strlen(str) : 0;
+ fin:
+ if (!str) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = strlen(str);
+
return str;
} // end of json_array_delete
@@ -1793,7 +2019,7 @@ void json_array_delete_deinit(UDF_INIT* initid)
} // end of json_array_delete_deinit
/*********************************************************************************/
-/* Make a Json Oject containing all the parameters. */
+/* Make a Json Object containing all the parameters. */
/*********************************************************************************/
my_bool json_object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
@@ -1810,7 +2036,7 @@ char *json_object(UDF_INIT *initid, UDF_ARGS *args, char *result,
PGLOBAL g = (PGLOBAL)initid->ptr;
if (!g->Xchk) {
- if (!CheckMemory(g, initid, args, args->arg_count, true)) {
+ if (!CheckMemory(g, initid, args, args->arg_count, false, false, true)) {
PJOB objp = new(g)JOBJECT;
for (uint i = 0; i < args->arg_count; i++)
@@ -1837,7 +2063,7 @@ void json_object_deinit(UDF_INIT* initid)
} // end of json_object_deinit
/*********************************************************************************/
-/* Make a Json Oject containing all not null parameters. */
+/* Make a Json Object containing all not null parameters. */
/*********************************************************************************/
my_bool json_object_nonull_init(UDF_INIT *initid, UDF_ARGS *args,
char *message)
@@ -1855,7 +2081,7 @@ char *json_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
PGLOBAL g = (PGLOBAL)initid->ptr;
if (!g->Xchk) {
- if (!CheckMemory(g, initid, args, args->arg_count, true)) {
+ if (!CheckMemory(g, initid, args, args->arg_count, false, true)) {
PJVAL jvp;
PJOB objp = new(g)JOBJECT;
@@ -1884,6 +2110,55 @@ void json_object_nonull_deinit(UDF_INIT* initid)
} // end of json_object_nonull_deinit
/*********************************************************************************/
+/* Make a Json Object containing all the key/value parameters. */
+/*********************************************************************************/
+my_bool json_object_key_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ if (args->arg_count % 2) {
+ strcpy(message, "This function must have an even number of arguments");
+ return true;
+ } // endif arg_count
+
+ CalcLen(args, true, reslen, memlen);
+ return JsonInit(initid, args, message, false, reslen, memlen);
+} // end of json_object_key_init
+
+char *json_object_key(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *, char *)
+{
+ char *str = NULL;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ if (!g->Xchk) {
+ if (!CheckMemory(g, initid, args, args->arg_count, false, true)) {
+ PJOB objp = new(g)JOBJECT;
+
+ for (uint i = 0; i < args->arg_count; i += 2)
+ objp->SetValue(g, MakeValue(g, args, i+1), MakePSZ(g, args, i));
+
+ str = Serialize(g, objp, NULL, 0);
+ } // endif CheckMemory
+
+ if (!str)
+ str = strcpy(result, g->Message);
+
+ // Keep result of constant function
+ g->Xchk = (initid->const_item) ? str : NULL;
+ } else
+ str = (char*)g->Xchk;
+
+ *res_length = strlen(str);
+ return str;
+} // end of json_object_key
+
+void json_object_key_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of json_object_key_deinit
+
+/*********************************************************************************/
/* Add or replace a value in a Json Object. */
/*********************************************************************************/
my_bool json_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
@@ -1897,13 +2172,13 @@ my_bool json_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
strcpy(message, "First argument must be a json item");
return true;
} else
- CalcLen(args, false, reslen, memlen, true);
+ CalcLen(args, true, reslen, memlen, true);
return JsonInit(initid, args, message, true, reslen, memlen);
} // end of json_object_add_init
char *json_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
char *key, *str = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -1911,14 +2186,14 @@ char *json_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (g->Xchk) {
// This constant function was recalled
str = (char*)g->Xchk;
- *res_length = strlen(str);
- return str;
+ goto fin;
} // endif Xchk
- if (!CheckMemory(g, initid, args, 2, false, true)) {
- PJOB jobp;
- PJVAL jvp;
- PJSON jsp, top;
+ if (!CheckMemory(g, initid, args, 2, false, true, true)) {
+ PJOB jobp;
+ PJVAL jvp;
+ PJSON jsp, top;
+ PGLOBAL gb = GetMemPtr(g, args, 0);
jvp = MakeValue(g, args, 0, &top);
jsp = jvp->GetJson();
@@ -1927,9 +2202,9 @@ char *json_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
PUSH_WARNING(g->Message);
else if (jvp && jvp->GetValType() == TYPE_JOB) {
jobp = jvp->GetObject();
- jvp = MakeValue(g, args, 1);
- key = MakeKey(g, args, 1);
- jobp->SetValue(g, jvp, key);
+ jvp = MakeValue(gb, args, 1);
+ key = MakeKey(gb, args, 1);
+ jobp->SetValue(gb, jvp, key);
str = MakeResult(g, args, top);
} else {
PUSH_WARNING("First argument target is not an object");
@@ -1946,7 +2221,14 @@ char *json_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = str;
- *res_length = strlen(str);
+ fin:
+ if (!str) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = strlen(str);
+
return str;
} // end of json_object_add
@@ -1972,13 +2254,13 @@ my_bool json_object_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
strcpy(message, "Second argument must be a key string");
return true;
} else
- CalcLen(args, false, reslen, memlen, true);
+ CalcLen(args, true, reslen, memlen, true);
return JsonInit(initid, args, message, true, reslen, memlen);
} // end of json_object_delete_init
char *json_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
char *str = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -1986,11 +2268,10 @@ char *json_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (g->Xchk) {
// This constant function was recalled
str = (char*)g->Xchk;
- *res_length = strlen(str);
- return str;
+ goto fin;
} // endif Xchk
- if (!CheckMemory(g, initid, args, 1, false, true)) {
+ if (!CheckMemory(g, initid, args, 1, false, true, true)) {
char *key;
PJOB jobp;
PJSON jsp, top;
@@ -2001,7 +2282,7 @@ char *json_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (CheckPath(g, args, jsp, jvp, 2))
PUSH_WARNING(g->Message);
else if (jvp && jvp->GetValType() == TYPE_JOB) {
- key = MakeKey(g, args, 1);
+ key = MakeKey(GetMemPtr(g, args, 0), args, 1);
jobp = jvp->GetObject();
jobp->DeleteKey(key);
str = MakeResult(g, args, top);
@@ -2020,7 +2301,14 @@ char *json_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = str;
- *res_length = strlen(str);
+ fin:
+ if (!str) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = strlen(str);
+
return str;
} // end of json_object_delete
@@ -2055,7 +2343,7 @@ char *json_object_list(UDF_INIT *initid, UDF_ARGS *args, char *result,
PGLOBAL g = (PGLOBAL)initid->ptr;
if (!g->N) {
- if (!CheckMemory(g, initid, args, 1, false)) {
+ if (!CheckMemory(g, initid, args, 1, true, true)) {
char *p;
PJSON jsp;
PJVAL jvp = MakeValue(g, args, 0);
@@ -2186,7 +2474,7 @@ my_bool json_object_grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
unsigned long reslen, memlen, n = GetJsonGrpSize();
if (args->arg_count != 2) {
- strcpy(message, "This function requires 2 arguments (value, key)");
+ strcpy(message, "This function requires 2 arguments (key, value)");
return true;
} else if (IsJson(args, 0) == 3) {
strcpy(message, "This function does not support Jbin arguments");
@@ -2214,8 +2502,7 @@ void json_object_grp_add(UDF_INIT *initid, UDF_ARGS *args, char*, char*)
PJOB objp = (PJOB)g->Activityp;
if (g->N-- > 0)
- objp->SetValue(g, MakeValue(g, args, 0),
- (args->arg_count == 1) ? MakeKey(g, args, 0) : MakePSZ(g, args, 1));
+ objp->SetValue(g, MakeValue(g, args, 1), MakePSZ(g, args, 0));
} // end of json_object_grp_add
@@ -2273,7 +2560,7 @@ my_bool json_item_merge_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of json_item_merge_init
char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
char *str = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -2281,11 +2568,10 @@ char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (g->Xchk) {
// This constant function was recalled
str = (char*)g->Xchk;
- *res_length = strlen(str);
- return str;
+ goto fin;
} // endif Xchk
- if (!CheckMemory(g, initid, args, 2, false, true)) {
+ if (!CheckMemory(g, initid, args, 2, false, false, true)) {
PJSON top;
PJVAL jvp;
PJSON jsp[2] = {NULL, NULL};
@@ -2303,8 +2589,8 @@ char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endfor i
if (jsp[0]) {
- if (jsp[0]->Merge(g, jsp[1]))
- PUSH_WARNING(g->Message);
+ if (jsp[0]->Merge(GetMemPtr(g, args, 0), jsp[1]))
+ PUSH_WARNING(GetMemPtr(g, args, 0)->Message);
else
str = MakeResult(g, args, top);
@@ -2320,7 +2606,14 @@ char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = str;
- *res_length = strlen(str);
+ fin:
+ if (!str) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = strlen(str);
+
return str;
} // end of json_item_merge
@@ -2349,7 +2642,7 @@ my_bool json_get_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} else
CalcLen(args, false, reslen, memlen);
- if (n == 2) {
+ if (n == 2 && args->args[0]) {
char fn[_MAX_PATH];
long fl;
@@ -2366,7 +2659,10 @@ my_bool json_get_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
char *json_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *)
{
- char *str = NULL;
+ char *p, *path, *str = NULL;
+ PJSON jsp;
+ PJVAL jvp;
+ PJSNX jsx;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
@@ -2375,51 +2671,47 @@ char *json_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p, *path;
- PJSON jsp;
- PJSNX jsx;
- PJVAL jvp;
-
- if (!g->Xchk) {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true, true)) {
+ PUSH_WARNING("CheckMemory error");
+ goto fin;
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- return NULL;
- } // endif jsp
-
- } else
- jsp = jvp->GetJson();
-
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ return NULL;
+ } // endif jsp
} else
- jsp = (PJSON)g->Xchk;
+ jsp = jvp->GetJson();
+
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- path = MakePSZ(g, args, 1);
- jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
+ } else
+ jsp = (PJSON)g->Xchk;
- if (jsx->SetJpath(g, path, true)) {
- PUSH_WARNING(g->Message);
- *is_null = 1;
- return NULL;
- } // endif SetJpath
+ path = MakePSZ(g, args, 1);
+ jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
- jsx->ReadValue(g);
+ if (jsx->SetJpath(g, path, true)) {
+ PUSH_WARNING(g->Message);
+ *is_null = 1;
+ return NULL;
+ } // endif SetJpath
- if (!jsx->GetValue()->IsNull())
- str = jsx->GetValue()->GetCharValue();
+ jsx->ReadValue(g);
- if (initid->const_item)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)str;
+ if (!jsx->GetValue()->IsNull())
+ str = jsx->GetValue()->GetCharValue();
- } // endif CheckMemory
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)str;
fin:
if (!str) {
@@ -2464,7 +2756,7 @@ my_bool jsonget_string_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
CalcLen(args, false, reslen, memlen);
memlen += more;
- if (n == 2) {
+ if (n == 2 && args->args[0]) {
char fn[_MAX_PATH];
long fl;
@@ -2481,8 +2773,11 @@ my_bool jsonget_string_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
char *jsonget_string(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *)
{
+ char *p, *path, *str = NULL;
int rc;
- char *str = NULL;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
@@ -2491,67 +2786,64 @@ char *jsonget_string(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p, *path;
- PJSON jsp;
- PJSNX jsx;
- PJVAL jvp;
+ // Save stack and allocation environment and prepare error return
+ if (g->jump_level == MAX_JUMP) {
+ PUSH_WARNING(MSG(TOO_MANY_JUMPS));
+ *is_null = 1;
+ return NULL;
+ } // endif jump_level
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- PUSH_WARNING(MSG(TOO_MANY_JUMPS));
- *is_null = 1;
- return NULL;
- } // endif jump_level
+ if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
+ PUSH_WARNING(g->Message);
+ str = NULL;
+ goto err;
+ } // endif rc
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- PUSH_WARNING(g->Message);
- str = NULL;
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
goto err;
- } // endif rc
-
- if (!g->Xchk) {
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- goto err;
- } // endif jsp
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif jsp
- } else
- jsp = jvp->GetJson();
+ } else
+ jsp = jvp->GetJson();
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- } else
- jsp = (PJSON)g->Xchk;
+ } else
+ jsp = (PJSON)g->Xchk;
- path = MakePSZ(g, args, 1);
- jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
+ path = MakePSZ(g, args, 1);
+ jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
- if (jsx->SetJpath(g, path)) {
- PUSH_WARNING(g->Message);
- goto err;
- } // endif SetJpath
+ if (jsx->SetJpath(g, path)) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif SetJpath
- jsx->ReadValue(g);
+ jsx->ReadValue(g);
- if (!jsx->GetValue()->IsNull())
- str = jsx->GetValue()->GetCharValue();
+ if (!jsx->GetValue()->IsNull())
+ str = jsx->GetValue()->GetCharValue();
- if (initid->const_item)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)str;
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)str;
- err:
- g->jump_level--;
- } // endif CheckMemory
+ err:
+ g->jump_level--;
-fin:
+ fin:
if (!str) {
*is_null = 1;
*res_length = 0;
@@ -2594,6 +2886,11 @@ my_bool jsonget_int_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
long long jsonget_int(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error)
{
+ char *p, *path;
+ long long n;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
@@ -2606,67 +2903,60 @@ long long jsonget_int(UDF_INIT *initid, UDF_ARGS *args,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p, *path;
- long long n;
- PJSON jsp;
- PJSNX jsx;
- PJVAL jvp;
-
- if (!g->Xchk) {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
+ if (g->Mrr) *error = 1;
+ *is_null = 1;
+ return 0LL;
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- if (g->Mrr) *error = 1;
- *is_null = 1;
- return 0;
- } // endif jsp
-
- } else
- jsp = jvp->GetJson();
-
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ if (g->Mrr) *error = 1;
+ *is_null = 1;
+ return 0;
+ } // endif jsp
} else
- jsp = (PJSON)g->Xchk;
+ jsp = jvp->GetJson();
- path = MakePSZ(g, args, 1);
- jsx = new(g) JSNX(g, jsp, TYPE_BIGINT);
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- if (jsx->SetJpath(g, path)) {
- PUSH_WARNING(g->Message);
- *is_null = 1;
- return 0;
- } // endif SetJpath
+ } else
+ jsp = (PJSON)g->Xchk;
- jsx->ReadValue(g);
+ path = MakePSZ(g, args, 1);
+ jsx = new(g) JSNX(g, jsp, TYPE_BIGINT);
- if (jsx->GetValue()->IsNull()) {
- PUSH_WARNING("Value not found");
- *is_null = 1;
- return 0;
- } // endif IsNull
+ if (jsx->SetJpath(g, path)) {
+ PUSH_WARNING(g->Message);
+ *is_null = 1;
+ return 0;
+ } // endif SetJpath
- n = jsx->GetValue()->GetBigintValue();
+ jsx->ReadValue(g);
- if (initid->const_item) {
- // 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
+ if (jsx->GetValue()->IsNull()) {
+ *is_null = 1;
+ return 0;
+ } // endif IsNull
- return n;
- } // endif CheckMemory
+ n = jsx->GetValue()->GetBigintValue();
- if (g->Mrr) *error = 1;
- *is_null = 1;
- return 0LL;
+ if (initid->const_item) {
+ // 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 jsonget_int
void jsonget_int_deinit(UDF_INIT* initid)
@@ -2711,6 +3001,11 @@ my_bool jsonget_real_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
double jsonget_real(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error)
{
+ char *p, *path;
+ double d;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
@@ -2723,66 +3018,59 @@ double jsonget_real(UDF_INIT *initid, UDF_ARGS *args,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p, *path;
- double d;
- PJSON jsp;
- PJSNX jsx;
- PJVAL jvp;
-
- if (!g->Xchk) {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
+ if (g->Mrr) *error = 1;
+ *is_null = 1;
+ return 0.0;
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- *is_null = 1;
- return 0.0;
- } // endif jsp
-
- } else
- jsp = jvp->GetJson();
-
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ *is_null = 1;
+ return 0.0;
+ } // endif jsp
} else
- jsp = (PJSON)g->Xchk;
+ jsp = jvp->GetJson();
- path = MakePSZ(g, args, 1);
- jsx = new(g) JSNX(g, jsp, TYPE_DOUBLE);
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- if (jsx->SetJpath(g, path)) {
- PUSH_WARNING(g->Message);
- *is_null = 1;
- return 0.0;
- } // endif SetJpath
+ } else
+ jsp = (PJSON)g->Xchk;
- jsx->ReadValue(g);
+ path = MakePSZ(g, args, 1);
+ jsx = new(g) JSNX(g, jsp, TYPE_DOUBLE);
- if (jsx->GetValue()->IsNull()) {
- PUSH_WARNING("Value not found");
- *is_null = 1;
- return 0.0;
- } // endif IsNull
+ if (jsx->SetJpath(g, path)) {
+ PUSH_WARNING(g->Message);
+ *is_null = 1;
+ return 0.0;
+ } // endif SetJpath
- d = jsx->GetValue()->GetFloatValue();
+ jsx->ReadValue(g);
- if (initid->const_item) {
- // Keep result of constant function
- double *dp = (double*)PlugSubAlloc(g, NULL, sizeof(double));
- *dp = d;
- g->Activityp = (PACTIVITY)dp;
- } // endif const_item
+ if (jsx->GetValue()->IsNull()) {
+ *is_null = 1;
+ return 0.0;
+ } // endif IsNull
- return d;
- } // endif CheckMemory
+ d = jsx->GetValue()->GetFloatValue();
- if (g->Mrr) *error = 1;
- *is_null = 1;
- return 0.0;
+ if (initid->const_item) {
+ // Keep result of constant function
+ double *dp = (double*)PlugSubAlloc(g, NULL, sizeof(double));
+ *dp = d;
+ g->Activityp = (PACTIVITY)dp;
+ } // endif const_item
+
+ return d;
} // end of jsonget_real
void jsonget_real_deinit(UDF_INIT* initid)
@@ -2824,7 +3112,11 @@ my_bool jsonlocate_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
char *jsonlocate(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *error)
{
- char *path = NULL;
+ char *p, *path = NULL;
+ int k, rc;
+ PJVAL jvp, jvp2;
+ PJSON jsp;
+ PJSNX jsx;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
@@ -2841,75 +3133,68 @@ char *jsonlocate(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p;
- int k, rc;
- PJVAL jvp, jvp2;
- PJSON jsp;
- PJSNX jsx;
+ // Save stack and allocation environment and prepare error return
+ if (g->jump_level == MAX_JUMP) {
+ PUSH_WARNING(MSG(TOO_MANY_JUMPS));
+ *error = 1;
+ *is_null = 1;
+ return NULL;
+ } // endif jump_level
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- PUSH_WARNING(MSG(TOO_MANY_JUMPS));
- *error = 1;
- *is_null = 1;
- return NULL;
- } // endif jump_level
+ if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
+ PUSH_WARNING(g->Message);
+ *error = 1;
+ path = NULL;
+ goto err;
+ } // endif rc
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- PUSH_WARNING(g->Message);
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, !g->Xchk)) {
+ PUSH_WARNING("CheckMemory error");
*error = 1;
- path = NULL;
goto err;
- } // endif rc
-
- if (!g->Xchk) {
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- goto err;
- } // endif jsp
-
- } else
- jsp = jvp->GetJson();
-
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif jsp
} else
- jsp = (PJSON)g->Xchk;
+ jsp = jvp->GetJson();
- // The item to locate
- jvp2 = MakeValue(g, args, 1);
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- k = (args->arg_count > 2) ? (int)*(long long*)args->args[2] : 1;
+ } else
+ jsp = (PJSON)g->Xchk;
- jsx = new(g) JSNX(g, jsp, TYPE_STRING);
- path = jsx->Locate(g, jsp, jvp2, k);
+ // The item to locate
+ jvp2 = MakeValue(g, args, 1);
- if (initid->const_item)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)path;
+ k = (args->arg_count > 2) ? (int)*(long long*)args->args[2] : 1;
- err:
- g->jump_level--;
+ jsx = new(g) JSNX(g, jsp, TYPE_STRING);
+ path = jsx->Locate(g, jsp, jvp2, k);
- if (!path) {
- *res_length = 0;
- *is_null = 1;
- } else
- *res_length = strlen(path);
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)path;
- return path;
- } // endif CheckMemory
+ err:
+ g->jump_level--;
- *error = 1;
- *is_null = 1;
- return NULL;
+ if (!path) {
+ *res_length = 0;
+ *is_null = 1;
+ } else
+ *res_length = strlen(path);
+
+ return path;
} // end of jsonlocate
void jsonlocate_deinit(UDF_INIT* initid)
@@ -2951,7 +3236,11 @@ my_bool json_locate_all_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
char *json_locate_all(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *error)
{
- char *path = NULL;
+ char *p, *path = NULL;
+ int rc, mx = 10;
+ PJVAL jvp, jvp2;
+ PJSON jsp;
+ PJSNX jsx;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
@@ -2969,82 +3258,416 @@ char *json_locate_all(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p;
- int rc, mx = 10;
- PJVAL jvp, jvp2;
- PJSON jsp;
- PJSNX jsx;
+ // Save stack and allocation environment and prepare error return
+ if (g->jump_level == MAX_JUMP) {
+ PUSH_WARNING(MSG(TOO_MANY_JUMPS));
+ *error = 1;
+ *is_null = 1;
+ return NULL;
+ } // endif jump_level
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- PUSH_WARNING(MSG(TOO_MANY_JUMPS));
- *error = 1;
- *is_null = 1;
- return NULL;
- } // endif jump_level
+ if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
+ PUSH_WARNING(g->Message);
+ *error = 1;
+ path = NULL;
+ goto err;
+ } // endif rc
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- PUSH_WARNING(g->Message);
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
*error = 1;
- path = NULL;
goto err;
- } // endif rc
-
- if (!g->Xchk) {
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- goto err;
- } // endif jsp
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif jsp
- } else
- jsp = jvp->GetJson();
+ } else
+ jsp = jvp->GetJson();
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- } else
- jsp = (PJSON)g->Xchk;
+ } else
+ jsp = (PJSON)g->Xchk;
- // The item to locate
- jvp2 = MakeValue(g, args, 1);
+ // The item to locate
+ jvp2 = MakeValue(g, args, 1);
- if (args->arg_count > 2)
- mx = (int)*(long long*)args->args[2];
+ if (args->arg_count > 2)
+ mx = (int)*(long long*)args->args[2];
- jsx = new(g) JSNX(g, jsp, TYPE_STRING);
- path = jsx->LocateAll(g, jsp, jvp2, mx);
+ jsx = new(g) JSNX(g, jsp, TYPE_STRING);
+ path = jsx->LocateAll(g, jsp, jvp2, mx);
- if (initid->const_item)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)path;
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)path;
- err:
- g->jump_level--;
+ err:
+ g->jump_level--;
- if (!path) {
- *res_length = 0;
+ if (!path) {
+ *res_length = 0;
+ *is_null = 1;
+ } else
+ *res_length = strlen(path);
+
+ return path;
+} // end of json_locate_all
+
+void json_locate_all_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of json_locate_all_deinit
+
+/*********************************************************************************/
+/* Check whether the document contains a value or item. */
+/*********************************************************************************/
+my_bool jsoncontains_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen, more = 1024;
+ int n = IsJson(args, 0);
+
+ if (args->arg_count < 2) {
+ strcpy(message, "At least 2 arguments required");
+ return true;
+ } else if (!n && args->arg_type[0] != STRING_RESULT) {
+ strcpy(message, "First argument must be a json item");
+ return true;
+ } else if (args->arg_count > 2 && args->arg_type[2] != INT_RESULT) {
+ strcpy(message, "Third argument is not an integer (index)");
+ return true;
+ } else if (args->arg_count > 3) {
+ if (args->arg_type[3] == INT_RESULT && args->args[3])
+ more += (unsigned long)*(long long*)args->args[3];
+ else
+ strcpy(message, "Fourth argument is not an integer (memory)");
+
+ } // endif's
+
+ CalcLen(args, false, reslen, memlen);
+ memlen += more;
+
+ if (IsJson(args, 0) != 3)
+ memlen += 1000; // TODO: calculate this
+
+ return JsonInit(initid, args, message, false, reslen, memlen);
+} // end of jsoncontains_init
+
+long long jsoncontains(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *p, res[256];
+ long long n;
+ unsigned long reslen;
+
+ *is_null = 0;
+ p = jsonlocate(initid, args, res, &reslen, is_null, error);
+ n = (*is_null) ? 0LL : 1LL;
+ return n;
+} // end of jsoncontains
+
+void jsoncontains_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of jsoncontains_deinit
+
+/*********************************************************************************/
+/* Check whether the document contains a path. */
+/*********************************************************************************/
+my_bool jsoncontains_path_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen, more = 1024;
+ int n = IsJson(args, 0);
+
+ if (args->arg_count < 2) {
+ strcpy(message, "At least 2 arguments required");
+ return true;
+ } else if (!n && args->arg_type[0] != STRING_RESULT) {
+ strcpy(message, "First argument must be a json item");
+ return true;
+ } else if (args->arg_type[1] != STRING_RESULT) {
+ strcpy(message, "Second argument is not a string (path)");
+ return true;
+ } else if (args->arg_count > 2) {
+ if (args->arg_type[2] == INT_RESULT && args->args[2])
+ more += (unsigned long)*(long long*)args->args[2];
+ else
+ strcpy(message, "Third argument is not an integer (memory)");
+
+ } // endif's
+
+ CalcLen(args, false, reslen, memlen);
+ memlen += more;
+
+ if (IsJson(args, 0) != 3)
+ memlen += 1000; // TODO: calculate this
+
+ return JsonInit(initid, args, message, true, reslen, memlen);
+} // end of jsoncontains_path_init
+
+long long jsoncontains_path(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *p, *path;
+ long long n;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ if (g->N) {
+ if (!g->Activityp) {
*is_null = 1;
+ return 0LL;
} else
- *res_length = strlen(path);
+ return *(long long*)g->Activityp;
- return path;
- } // endif CheckMemory
+ } else if (initid->const_item)
+ g->N = 1;
+
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
+ goto err;
+ } else
+ jvp = MakeValue(g, args, 0);
- *error = 1;
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif jsp
+
+ } else
+ jsp = jvp->GetJson();
+
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
+
+ } else
+ jsp = (PJSON)g->Xchk;
+
+ path = MakePSZ(g, args, 1);
+ jsx = new(g)JSNX(g, jsp, TYPE_BIGINT);
+
+ if (jsx->SetJpath(g, path)) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif SetJpath
+
+ n = (jsx->CheckPath(g)) ? 1LL : 0LL;
+
+ if (initid->const_item) {
+ // 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;
+
+ err:
+ if (g->Mrr) *error = 1;
*is_null = 1;
- return NULL;
-} // end of json_locate_all
+ return 0LL;
+} // end of jsoncontains_path
-void json_locate_all_deinit(UDF_INIT* initid)
+void jsoncontains_path_deinit(UDF_INIT* initid)
{
JsonFreeMem((PGLOBAL)initid->ptr);
-} // end of json_locate_all_deinit
+} // end of jsoncontains_path_deinit
+
+/*********************************************************************************/
+/* Set Json items of a Json document according to path. */
+/*********************************************************************************/
+my_bool json_set_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+ int n = IsJson(args, 0);
+
+ if (!(args->arg_count % 2)) {
+ strcpy(message, "This function must have an odd number of arguments");
+ return true;
+ } else if (!n && args->arg_type[0] != STRING_RESULT) {
+ strcpy(message, "First argument must be a json item");
+ return true;
+ } else
+ CalcLen(args, false, reslen, memlen);
+
+ if (n == 2 && args->args[0]) {
+ char fn[_MAX_PATH];
+ long fl;
+
+ memcpy(fn, args->args[0], args->lengths[0]);
+ fn[args->lengths[0]] = 0;
+ fl = GetFileLength(fn);
+ memlen += fl * 3;
+ } else if (n != 3)
+ memlen += args->lengths[0] * 3;
+
+ return JsonInit(initid, args, message, true, reslen, memlen);
+} // end of json_set_item_init
+
+char *json_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *p, *path, *str = NULL;
+ int w, rc;
+ my_bool b = true;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PGLOBAL gb = GetMemPtr(g, args, 0);
+
+ if (g->N) {
+ str = (char*)g->Activityp;
+ goto fin;
+ } else if (initid->const_item)
+ g->N = 1;
+
+ if (!strcmp(result, "$insert"))
+ w = 1;
+ else if (!strcmp(result, "$update"))
+ w = 2;
+ else
+ w = 0;
+
+ // Save stack and allocation environment and prepare error return
+ if (g->jump_level == MAX_JUMP) {
+ PUSH_WARNING(MSG(TOO_MANY_JUMPS));
+ *error = 1;
+ goto fin;
+ } // endif jump_level
+
+ if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
+ PUSH_WARNING(g->Message);
+ str = NULL;
+ goto err;
+ } // endif rc
+
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true, false, true)) {
+ PUSH_WARNING("CheckMemory error");
+ goto err;
+ } else
+ jvp = MakeValue(g, args, 0);
+
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif jsp
+
+ } else
+ jsp = jvp->GetJson();
+
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
+
+ } else
+ jsp = (PJSON)g->Xchk;
+
+ jsx = new(g)JSNX(g, jsp, TYPE_STRING, initid->max_length, 0, true);
+
+ for (uint i = 1; i+1 < args->arg_count; i += 2) {
+ jvp = MakeValue(gb, args, i);
+ path = MakePSZ(g, args, i+1);
+
+ if (jsx->SetJpath(g, path, false)) {
+ PUSH_WARNING(g->Message);
+ continue;
+ } // endif SetJpath
+
+ if (w) {
+ jsx->ReadValue(g);
+ b = jsx->GetValue()->IsNull();
+ b = (w == 1) ? b : !b;
+ } // endif w
+
+ if (b && jsx->WriteValue(gb, jvp))
+ PUSH_WARNING(g->Message);
+
+ } // endfor i
+
+ // In case of error or file, return unchanged argument
+ if (!(str = MakeResult(g, args, jsp, INT_MAX32)))
+ str = MakePSZ(g, args, 0);
+
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)str;
+
+ err:
+ g->jump_level--;
+
+ fin:
+ if (!str) {
+ *is_null = 1;
+ *res_length = 0;
+ } else
+ *res_length = strlen(str);
+
+ return str;
+} // end of json_set_item
+
+void json_set_item_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of json_set_item_deinit
+
+/*********************************************************************************/
+/* Insert Json items of a Json document according to path. */
+/*********************************************************************************/
+my_bool json_insert_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ return json_set_item_init(initid, args, message);
+} // end of json_insert_item_init
+
+char *json_insert_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *p)
+{
+ strcpy(result, "$insert");
+ return json_set_item(initid, args, result, res_length, is_null, p);
+} // end of json_insert_item
+
+void json_insert_item_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of json_insert_item_deinit
+
+/*********************************************************************************/
+/* Update Json items of a Json document according to path. */
+/*********************************************************************************/
+my_bool json_update_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ return json_set_item_init(initid, args, message);
+} // end of json_update_item_init
+
+char *json_update_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *p)
+{
+ strcpy(result, "$update");
+ return json_set_item(initid, args, result, res_length, is_null, p);
+} // end of json_update_item
+
+void json_update_item_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of json_update_item_deinit
/*********************************************************************************/
/* Returns a json file as a json string. */
@@ -3085,7 +3708,7 @@ my_bool json_file_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
more += fl * M;
memlen += more;
- return JsonInit(initid, args, message, false, reslen, memlen);
+ return JsonInit(initid, args, message, true, reslen, memlen);
} // end of json_file_init
char *json_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
@@ -3140,13 +3763,14 @@ char *json_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
PUSH_WARNING(g->Message);
} else
- str = GetJsonFile(g, fn);
+ if (!(str = GetJsonFile(g, fn)))
+ PUSH_WARNING(g->Message);
if (initid->const_item)
// Keep result of constant function
g->Xchk = str;
-fin:
+ fin:
if (!str) {
*res_length = 0;
*is_null = 1;
@@ -3183,7 +3807,7 @@ my_bool jfile_make_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
char *jfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *)
{
- char *p, *str, *msg, *fn = NULL;
+ char *p, *str = NULL, *fn = NULL;
int n, pretty = 2;
PJSON jsp;
PJVAL jvp;
@@ -3195,8 +3819,6 @@ char *jfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- PlugSubSet(g, g->Sarea, g->Sarea_Size);
-
if ((n = IsJson(args, 0)) == 3) {
// Get default file name and pretty
PBSON bsp = (PBSON)args->args[0];
@@ -3207,14 +3829,18 @@ char *jfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result,
fn = args->args[0];
if (!g->Xchk) {
- jvp = MakeValue(g, args, 0);
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
+ goto fin;
+ } else
+ jvp = MakeValue(g, args, 0);
if ((p = jvp->GetString())) {
if (!strchr("[{ \t\r\n", *p)) {
// Is this a file name?
if (!(p = GetJsonFile(g, p))) {
PUSH_WARNING(g->Message);
- return NULL;
+ goto fin;
} else
fn = jvp->GetString();
@@ -3222,7 +3848,7 @@ char *jfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!(jsp = ParseJson(g, p, strlen(p)))) {
PUSH_WARNING(g->Message);
- return NULL;
+ goto fin;
} // endif jsp
jvp->SetValue(jsp);
@@ -3249,9 +3875,9 @@ char *jfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endswitch arg_type
if (fn) {
- if ((msg = Serialize(g, jvp->GetJson(), fn, pretty)))
- PUSH_WARNING(msg);
- } else
+ if (!Serialize(g, jvp->GetJson(), fn, pretty))
+ PUSH_WARNING(g->Message);
+ } else
PUSH_WARNING("Missing file name");
str= fn;
@@ -3283,35 +3909,41 @@ my_bool jbin_array_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
unsigned long reslen, memlen;
CalcLen(args, false, reslen, memlen);
- return JsonInit(initid, args, message, false, reslen, memlen);
+ return JsonInit(initid, args, message, true, reslen, memlen);
} // end of jbin_array_init
char *jbin_array(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *)
+ unsigned long *res_length, char *is_null, char *error)
{
PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = (PBSON)g->Xchk;
if (!bsp || bsp->Changed) {
if (!CheckMemory(g, initid, args, args->arg_count, false)) {
- PJAR arp = new(g)JARRAY;
+ PJAR arp = new(g) JARRAY;
+
+ bsp = JbinAlloc(g, args, initid->max_length, arp);
+ strcat(bsp->Msg, " array");
for (uint i = 0; i < args->arg_count; i++)
arp->AddValue(g, MakeValue(g, args, i));
arp->InitArray(g);
- bsp = JbinAlloc(g, args, initid->max_length, arp);
- strcat(bsp->Msg, " array");
- } else {
- bsp = JbinAlloc(g, args, initid->max_length, NULL);
- strncpy(bsp->Msg, g->Message, 139);
- } // endif CheckMemory
+ } else
+ if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
+ strncpy(bsp->Msg, g->Message, 139);
// Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_array
@@ -3329,17 +3961,18 @@ my_bool jbin_array_add_values_init(UDF_INIT *initid, UDF_ARGS *args, char *messa
} // end of jbin_array_add_values_init
char *jbin_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *is_null, char *)
+ unsigned long *res_length, char *is_null, char *error)
{
PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = (PBSON)g->Xchk;
if (!bsp || bsp->Changed) {
- if (!CheckMemory(g, initid, args, args->arg_count, false)) {
- char *p;
- PJSON top;
- PJAR arp;
- PJVAL jvp = MakeValue(g, args, 0, &top);
+ if (!CheckMemory(g, initid, args, args->arg_count, true)) {
+ char *p;
+ PJSON top;
+ PJAR arp;
+ PJVAL jvp = MakeValue(g, args, 0, &top);
+ PGLOBAL gb = GetMemPtr(g, args, 0);
if ((p = jvp->GetString())) {
if (!(top = ParseJson(g, p, strlen(p)))) {
@@ -3351,28 +3984,36 @@ char *jbin_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif p
if (jvp->GetValType() != TYPE_JAR) {
- arp = new(g)JARRAY;
- arp->AddValue(g, jvp);
+ arp = new(gb)JARRAY;
+ arp->AddValue(gb, jvp);
} else
arp = jvp->GetArray();
for (uint i = 1; i < args->arg_count; i++)
- arp->AddValue(g, MakeValue(g, args, i));
+ arp->AddValue(gb, MakeValue(gb, args, i));
- arp->InitArray(g);
- bsp = JbinAlloc(g, args, initid->max_length, top);
- strcat(bsp->Msg, " array");
- bsp->Jsp = arp;
- } else {
- bsp = JbinAlloc(g, args, initid->max_length, NULL);
- strncpy(bsp->Msg, g->Message, BMX);
- } // endif CheckMemory
+ arp->InitArray(gb);
+
+ if ((bsp = JbinAlloc(g, args, initid->max_length, top))) {
+ strcat(bsp->Msg, " array");
+ bsp->Jsp = arp;
+ } // endif bsp
+
+ } else
+ if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
+ strncpy(bsp->Msg, g->Message, BMX);
// Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_array_add_values
@@ -3390,7 +4031,7 @@ my_bool jbin_array_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_array_add_init
char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
int n = 2;
PJSON top = NULL;
@@ -3403,7 +4044,7 @@ char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
return (char*)bsp;
} // endif bsp
- if (!CheckMemory(g, initid, args, 2, false, true)) {
+ if (!CheckMemory(g, initid, args, 2, false, false, true)) {
int *x = NULL;
uint n = 2;
// PJSON jsp;
@@ -3417,9 +4058,11 @@ char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (CheckPath(g, args, top, jvp, n))
PUSH_WARNING(g->Message);
else if (jvp && jvp->GetValType() == TYPE_JAR) {
+ PGLOBAL gb = GetMemPtr(g, args, 0);
+
arp = jvp->GetArray();
- arp->AddValue(g, MakeValue(g, args, 1), x);
- arp->InitArray(g);
+ arp->AddValue(gb, MakeValue(gb, args, 1), x);
+ arp->InitArray(gb);
} else {
PUSH_WARNING("First argument is not an array");
// if (g->Mrr) *error = 1; (only if no path)
@@ -3434,7 +4077,13 @@ char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_array_add
@@ -3452,7 +4101,7 @@ my_bool jbin_array_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_array_delete_init
char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
PJSON top = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -3464,7 +4113,7 @@ char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
return (char*)bsp;
} // endif bsp
- if (!CheckMemory(g, initid, args, 1, false, true)) {
+ if (!CheckMemory(g, initid, args, 1, false, false, true)) {
int *x;
uint n = 1;
PJAR arp;
@@ -3476,7 +4125,7 @@ char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
if ((x = GetIntArgPtr(g, args, n))) {
arp = jvp->GetArray();
arp->DeleteValue(*x);
- arp->InitArray(g);
+ arp->InitArray(GetMemPtr(g, args, 0));
} else
PUSH_WARNING("Missing or null array index");
@@ -3494,7 +4143,13 @@ char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_array_delete
@@ -3504,7 +4159,7 @@ void jbin_array_delete_deinit(UDF_INIT* initid)
} // end of jbin_array_delete_deinit
/*********************************************************************************/
-/* Make a Json Oject containing all the parameters. */
+/* Make a Json Object containing all the parameters. */
/*********************************************************************************/
my_bool jbin_object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
@@ -3515,7 +4170,7 @@ my_bool jbin_object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_object_init
char *jbin_object(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *)
+ unsigned long *res_length, char *is_null, char *error)
{
PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = (PBSON)g->Xchk;
@@ -3527,18 +4182,24 @@ char *jbin_object(UDF_INIT *initid, UDF_ARGS *args, char *result,
for (uint i = 0; i < args->arg_count; i++)
objp->SetValue(g, MakeValue(g, args, i), MakeKey(g, args, i));
- bsp = JbinAlloc(g, args, initid->max_length, objp);
- strcat(bsp->Msg, " object");
- } else {
- bsp = JbinAlloc(g, args, initid->max_length, NULL);
- strncpy(bsp->Msg, g->Message, BMX);
- } // endif CheckMemory
+ if ((bsp = JbinAlloc(g, args, initid->max_length, objp)))
+ strcat(bsp->Msg, " object");
+
+ } else
+ if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
+ strncpy(bsp->Msg, g->Message, BMX);
// Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_object
@@ -3548,24 +4209,24 @@ void jbin_object_deinit(UDF_INIT* initid)
} // end of jbin_object_deinit
/*********************************************************************************/
-/* Make a Json Oject containing all not null parameters. */
+/* Make a Json Object containing all not null parameters. */
/*********************************************************************************/
my_bool jbin_object_nonull_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
unsigned long reslen, memlen;
CalcLen(args, true, reslen, memlen);
- return JsonInit(initid, args, message, false, reslen, memlen);
+ return JsonInit(initid, args, message, true, reslen, memlen);
} // end of jbin_object_nonull_init
char *jbin_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *)
+ unsigned long *res_length, char *is_null, char *error)
{
PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = (PBSON)g->Xchk;
if (!bsp || bsp->Changed) {
- if (!CheckMemory(g, initid, args, args->arg_count, true)) {
+ if (!CheckMemory(g, initid, args, args->arg_count, false, true)) {
PJVAL jvp;
PJOB objp = new(g)JOBJECT;
@@ -3573,18 +4234,24 @@ char *jbin_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!(jvp = MakeValue(g, args, i))->IsNull())
objp->SetValue(g, jvp, MakeKey(g, args, i));
- bsp = JbinAlloc(g, args, initid->max_length, objp);
- strcat(bsp->Msg, " object");
- } else {
- bsp = JbinAlloc(g, args, initid->max_length, NULL);
- strncpy(bsp->Msg, g->Message, BMX);
- } // endif CheckMemory
+ if ((bsp = JbinAlloc(g, args, initid->max_length, objp)))
+ strcat(bsp->Msg, " object");
+
+ } else
+ if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
+ strncpy(bsp->Msg, g->Message, BMX);
// Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_object_nonull
@@ -3594,6 +4261,61 @@ void jbin_object_nonull_deinit(UDF_INIT* initid)
} // end of jbin_object_nonull_deinit
/*********************************************************************************/
+/* Make a Json Object containing all the key/value parameters. */
+/*********************************************************************************/
+my_bool jbin_object_key_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ if (args->arg_count % 2) {
+ strcpy(message, "This function must have an even number of arguments");
+ return true;
+ } // endif arg_count
+
+ CalcLen(args, true, reslen, memlen);
+ return JsonInit(initid, args, message, true, reslen, memlen);
+} // end of jbin_object_key_init
+
+char *jbin_object_key(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PBSON bsp = (PBSON)g->Xchk;
+
+ if (!bsp || bsp->Changed) {
+ if (!CheckMemory(g, initid, args, args->arg_count, false, true)) {
+ PJOB objp = new(g)JOBJECT;
+
+ for (uint i = 0; i < args->arg_count; i += 2)
+ objp->SetValue(g, MakeValue(g, args, i+1), MakePSZ(g, args, i));
+
+ if ((bsp = JbinAlloc(g, args, initid->max_length, objp)))
+ strcat(bsp->Msg, " object");
+
+ } else
+ if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
+ strncpy(bsp->Msg, g->Message, BMX);
+
+ // Keep result of constant function
+ g->Xchk = (initid->const_item) ? bsp : NULL;
+ } // endif bsp
+
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
+ return (char*)bsp;
+} // end of jbin_object_key
+
+void jbin_object_key_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of jbin_object_key_deinit
+
+/*********************************************************************************/
/* Add or replace a value in a Json Object. */
/*********************************************************************************/
my_bool jbin_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
@@ -3602,7 +4324,7 @@ my_bool jbin_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_object_add_init
char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
PJSON top = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -3615,7 +4337,7 @@ char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
return (char*)bsp;
} // endif bsp
- if (!CheckMemory(g, initid, args, 2, false, true)) {
+ if (!CheckMemory(g, initid, args, 2, false, true, true)) {
char *key;
PJOB jobp;
PJVAL jvp = MakeValue(g, args, 0, &top);
@@ -3624,10 +4346,12 @@ char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (CheckPath(g, args, jsp, jvp, 2))
PUSH_WARNING(g->Message);
else if (jvp && jvp->GetValType() == TYPE_JOB) {
+ PGLOBAL gb = GetMemPtr(g, args, 0);
+
jobp = jvp->GetObject();
- jvp = MakeValue(g, args, 1);
- key = MakeKey(g, args, 1);
- jobp->SetValue(g, jvp, key);
+ jvp = MakeValue(gb, args, 1);
+ key = MakeKey(gb, args, 1);
+ jobp->SetValue(gb, jvp, key);
} else {
PUSH_WARNING("First argument target is not an object");
// if (g->Mrr) *error = 1; (only if no path)
@@ -3642,7 +4366,13 @@ char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_object_add
@@ -3660,7 +4390,7 @@ my_bool jbin_object_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_object_delete_init
char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
PJSON top = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -3673,7 +4403,7 @@ char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
return (char*)bsp;
} // endif bsp
- if (!CheckMemory(g, initid, args, 1, false, true)) {
+ if (!CheckMemory(g, initid, args, 1, false, true, true)) {
char *key;
PJOB jobp;
PJVAL jvp = MakeValue(g, args, 0, &top);
@@ -3699,7 +4429,13 @@ char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_object_delete
@@ -3724,7 +4460,7 @@ char *jbin_object_list(UDF_INIT *initid, UDF_ARGS *args, char *result,
PBSON bsp = (PBSON)g->Xchk;
if (!bsp || bsp->Changed) {
- if (!CheckMemory(g, initid, args, 1, false)) {
+ if (!CheckMemory(g, initid, args, 1, true, true)) {
char *p;
PJSON jsp;
PJVAL jvp = MakeValue(g, args, 0);
@@ -3747,14 +4483,20 @@ char *jbin_object_list(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif CheckMemory
- bsp = JbinAlloc(g, args, initid->max_length, jarp);
- strcat(bsp->Msg, " array");
+ if ((bsp = JbinAlloc(g, args, initid->max_length, jarp)))
+ strcat(bsp->Msg, " array");
// Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_object_list
@@ -3772,10 +4514,14 @@ my_bool jbin_get_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_get_item_init
char *jbin_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *is_null, char *)
+ unsigned long *res_length, char *is_null, char *error)
{
- PGLOBAL g = (PGLOBAL)initid->ptr;
+ char *p, *path;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
PBSON bsp = NULL;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
bsp = (PBSON)g->Activityp;
@@ -3783,56 +4529,54 @@ char *jbin_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p, *path;
- PJSON jsp;
- PJSNX jsx;
- PJVAL jvp;
-
- if (!g->Xchk) {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true, true)) {
+ PUSH_WARNING("CheckMemory error");
+ goto fin;
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- return NULL;
- } // endif jsp
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto fin;
+ } // endif jsp
- } else
- jsp = jvp->GetJson();
+ } else
+ jsp = jvp->GetJson();
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- } else
- jsp = (PJSON)g->Xchk;
+ } else
+ jsp = (PJSON)g->Xchk;
- path = MakePSZ(g, args, 1);
- jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
+ path = MakePSZ(g, args, 1);
+ jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
- if (jsx->SetJpath(g, path, true)) {
- PUSH_WARNING(g->Message);
- *is_null = 1;
- return NULL;
- } // endif SetJpath
+ if (jsx->SetJpath(g, path, false)) {
+ PUSH_WARNING(g->Message);
+ goto fin;
+ } // endif SetJpath
- // Get the json tree
- jvp = jsx->GetValue(g, jsp, 0, false);
+ // Get the json tree
+ if ((jvp = jsx->GetRowValue(g, jsp, 0, false))) {
+ jsp = (jvp->GetJsp()) ? jvp->GetJsp() : new(g) JVALUE(g, jvp->GetValue());
- if (jvp->GetJsp()) {
- bsp = JbinAlloc(g, args, initid->max_length, jvp->GetJsp());
+ if ((bsp = JbinAlloc(g, args, initid->max_length, jsp)))
strcat(bsp->Msg, " item");
- } // end of Jsp
+ else
+ *error = 1;
- if (initid->const_item)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)bsp;
+ } // endif jvp
- } // endif CheckMemory
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)bsp;
-fin:
+ fin:
if (!bsp) {
*is_null = 1;
*res_length = 0;
@@ -3856,7 +4600,7 @@ my_bool jbin_item_merge_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_item_merge_init
char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
PJSON top = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -3868,9 +4612,10 @@ char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
return (char*)bsp;
} // endif bsp
- if (!CheckMemory(g, initid, args, 2, false, true)) {
- PJVAL jvp;
- PJSON jsp[2] = {NULL, NULL};
+ if (!CheckMemory(g, initid, args, 2, false, false, true)) {
+ PJVAL jvp;
+ PJSON jsp[2] = {NULL, NULL};
+ PGLOBAL gb = GetMemPtr(g, args, 0);
for (int i = 0; i < 2; i++) {
jvp = MakeValue(g, args, i);
@@ -3884,8 +4629,8 @@ char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endfor i
- if (jsp[0] && jsp[0]->Merge(g, jsp[1]))
- PUSH_WARNING(g->Message);
+ if (jsp[0] && jsp[0]->Merge(gb, jsp[1]))
+ PUSH_WARNING(gb->Message);
} // endif CheckMemory
@@ -3896,7 +4641,13 @@ char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_item_merge
@@ -3906,6 +4657,147 @@ void jbin_item_merge_deinit(UDF_INIT* initid)
} // end of jbin_item_merge_deinit
/*********************************************************************************/
+/* Set Json items of a Json document according to path. */
+/*********************************************************************************/
+my_bool jbin_set_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ return json_set_item_init(initid, args, message);
+} // end of jbin_set_item_init
+
+char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *p, *path;
+ int w;
+ my_bool b = true;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
+ PBSON bsp = NULL;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PGLOBAL gb = GetMemPtr(g, args, 0);
+
+ if (g->N) {
+ bsp = (PBSON)g->Activityp;
+ goto fin;
+ } else if (initid->const_item)
+ g->N = 1;
+
+ if (!strcmp(result, "$insert"))
+ w = 1;
+ else if (!strcmp(result, "$update"))
+ w = 2;
+ else
+ w = 0;
+
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true, false, true)) {
+ PUSH_WARNING("CheckMemory error");
+ } else
+ jvp = MakeValue(g, args, 0);
+
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto fin;
+ } // endif jsp
+
+ } else
+ jsp = jvp->GetJson();
+
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
+
+ } else
+ jsp = (PJSON)g->Xchk;
+
+ jsx = new(g)JSNX(g, jsp, TYPE_STRING, initid->max_length, 0, true);
+
+ for (uint i = 1; i+1 < args->arg_count; i += 2) {
+ jvp = MakeValue(gb, args, i);
+ path = MakePSZ(g, args, i+1);
+
+ if (jsx->SetJpath(g, path, false)) {
+ PUSH_WARNING(g->Message);
+ continue;
+ } // endif SetJpath
+
+ if (w) {
+ jsx->ReadValue(g);
+ b = jsx->GetValue()->IsNull();
+ b = (w == 1) ? b : !b;
+ } // endif w
+
+ if (b && jsx->WriteValue(gb, jvp))
+ PUSH_WARNING(g->Message);
+
+ } // endfor i
+
+ if (!(bsp = MakeBinResult(g, args, jsp, initid->max_length, INT_MAX32)))
+ *error = 1;
+
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)bsp;
+
+ fin:
+ if (!bsp) {
+ *is_null = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
+ return (char*)bsp;
+} // end of jbin_set_item
+
+void jbin_set_item_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of jbin_set_item_deinit
+
+/*********************************************************************************/
+/* Insert Json items of a Json document according to path. */
+/*********************************************************************************/
+my_bool jbin_insert_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ return json_set_item_init(initid, args, message);
+} // end of jbin_insert_item_init
+
+char *jbin_insert_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *p)
+{
+ strcpy(result, "$insert");
+ return jbin_set_item(initid, args, result, res_length, is_null, p);
+} // end of jbin_insert_item
+
+void jbin_insert_item_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of jbin_insert_item_deinit
+
+/*********************************************************************************/
+/* Update Json items of a Json document according to path. */
+/*********************************************************************************/
+my_bool jbin_update_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ return json_set_item_init(initid, args, message);
+} // end of jbin_update_item_init
+
+char *jbin_update_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *p)
+{
+ strcpy(result, "$update");
+ return jbin_set_item(initid, args, result, res_length, is_null, p);
+} // end of jbin_update_item
+
+void jbin_update_item_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of jbin_update_item_deinit
+
+/*********************************************************************************/
/* Returns a json file as a json item. */
/*********************************************************************************/
my_bool jbin_file_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
@@ -3939,7 +4831,7 @@ my_bool jbin_file_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
reslen += fl;
more += fl * M;
memlen += more;
- return JsonInit(initid, args, message, false, reslen, memlen);
+ return JsonInit(initid, args, message, true, reslen, memlen);
} // end of jbin_file_init
char *jbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
@@ -3976,10 +4868,14 @@ char *jbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
else if (pretty == 3)
pretty = pty;
- bsp = JbinAlloc(g, args, len, jsp);
- strcat(bsp->Msg, " file");
- bsp->Filename = fn;
- bsp->Pretty = pretty;
+ if ((bsp = JbinAlloc(g, args, len, jsp))) {
+ strcat(bsp->Msg, " file");
+ bsp->Filename = fn;
+ bsp->Pretty = pretty;
+ } else {
+ *error = 1;
+ goto fin;
+ } // endif bsp
// Check whether a path was specified
if (CheckPath(g, args, jsp, jvp, 1)) {
@@ -3993,7 +4889,7 @@ char *jbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
-fin:
+ fin:
if (!bsp) {
*res_length = 0;
*is_null = 1;
diff --git a/storage/connect/jsonudf.h b/storage/connect/jsonudf.h
index 0903b789fb6..ecbbb778214 100644
--- a/storage/connect/jsonudf.h
+++ b/storage/connect/jsonudf.h
@@ -61,6 +61,10 @@ extern "C" {
DllExport char *json_object_nonull(UDF_EXEC_ARGS);
DllExport void json_object_nonull_deinit(UDF_INIT*);
+ DllExport my_bool json_object_key_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char *json_object_key(UDF_EXEC_ARGS);
+ DllExport void json_object_key_deinit(UDF_INIT*);
+
DllExport my_bool json_object_add_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_object_add(UDF_EXEC_ARGS);
DllExport void json_object_add_deinit(UDF_INIT*);
@@ -105,6 +109,10 @@ extern "C" {
DllExport double jsonget_real(UDF_INIT*, UDF_ARGS*, char*, char*);
DllExport void jsonget_real_deinit(UDF_INIT*);
+ DllExport my_bool jsoncontains_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport long long jsoncontains(UDF_EXEC_ARGS);
+ DllExport void jsoncontains_deinit(UDF_INIT*);
+
DllExport my_bool jsonlocate_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jsonlocate(UDF_EXEC_ARGS);
DllExport void jsonlocate_deinit(UDF_INIT*);
@@ -113,6 +121,22 @@ extern "C" {
DllExport char *json_locate_all(UDF_EXEC_ARGS);
DllExport void json_locate_all_deinit(UDF_INIT*);
+ DllExport my_bool jsoncontains_path_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport long long jsoncontains_path(UDF_EXEC_ARGS);
+ DllExport void jsoncontains_path_deinit(UDF_INIT*);
+
+ DllExport my_bool json_set_item_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char *json_set_item(UDF_EXEC_ARGS);
+ DllExport void json_set_item_deinit(UDF_INIT*);
+
+ DllExport my_bool json_insert_item_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char *json_insert_item(UDF_EXEC_ARGS);
+ DllExport void json_insert_item_deinit(UDF_INIT*);
+
+ DllExport my_bool json_update_item_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char *json_update_item(UDF_EXEC_ARGS);
+ DllExport void json_update_item_deinit(UDF_INIT*);
+
DllExport my_bool json_file_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_file(UDF_EXEC_ARGS);
DllExport void json_file_deinit(UDF_INIT*);
@@ -145,6 +169,10 @@ extern "C" {
DllExport char *jbin_object_nonull(UDF_EXEC_ARGS);
DllExport void jbin_object_nonull_deinit(UDF_INIT*);
+ DllExport my_bool jbin_object_key_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char *jbin_object_key(UDF_EXEC_ARGS);
+ DllExport void jbin_object_key_deinit(UDF_INIT*);
+
DllExport my_bool jbin_object_add_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_object_add(UDF_EXEC_ARGS);
DllExport void jbin_object_add_deinit(UDF_INIT*);
@@ -165,6 +193,18 @@ extern "C" {
DllExport char *jbin_item_merge(UDF_EXEC_ARGS);
DllExport void jbin_item_merge_deinit(UDF_INIT*);
+ DllExport my_bool jbin_set_item_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char *jbin_set_item(UDF_EXEC_ARGS);
+ DllExport void jbin_set_item_deinit(UDF_INIT*);
+
+ DllExport my_bool jbin_insert_item_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char *jbin_insert_item(UDF_EXEC_ARGS);
+ DllExport void jbin_insert_item_deinit(UDF_INIT*);
+
+ DllExport my_bool jbin_update_item_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char *jbin_update_item(UDF_EXEC_ARGS);
+ DllExport void jbin_update_item_deinit(UDF_INIT*);
+
DllExport my_bool jbin_file_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_file(UDF_EXEC_ARGS);
DllExport void jbin_file_deinit(UDF_INIT*);
@@ -189,7 +229,7 @@ typedef struct _jpn {
class JSNX : public BLOCK {
public:
// Constructors
- JSNX(PGLOBAL g, PJSON row, int type, int len = 64, int prec = 0);
+ JSNX(PGLOBAL g, PJSON row, int type, int len = 64, int prec = 0, my_bool wr = false);
// Implementation
int GetPrecision(void) {return Prec;}
@@ -199,8 +239,10 @@ public:
my_bool SetJpath(PGLOBAL g, char *path, my_bool jb = false);
my_bool ParseJpath(PGLOBAL g);
void ReadValue(PGLOBAL g);
- PJVAL GetValue(PGLOBAL g, PJSON row, int i, my_bool b = true);
+ PJVAL GetRowValue(PGLOBAL g, PJSON row, int i, my_bool b = true);
PJVAL GetJson(PGLOBAL g);
+ my_bool CheckPath(PGLOBAL g);
+ my_bool WriteValue(PGLOBAL g, PJVAL jvalp);
char *Locate(PGLOBAL g, PJSON jsp, PJVAL jvp, int k = 1);
char *LocateAll(PGLOBAL g, PJSON jsp, PJVAL jvp, int mx = 10);
@@ -211,6 +253,7 @@ protected:
PVAL CalculateArray(PGLOBAL g, PJAR arp, int n);
PVAL MakeJson(PGLOBAL g, PJSON jsp);
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n);
+ PJSON GetRow(PGLOBAL g);
my_bool LocateArray(PJAR jarp);
my_bool LocateObject(PJOB jobp);
my_bool LocateValue(PJVAL jvp);
@@ -244,4 +287,6 @@ protected:
my_bool Xpd; // True for expandable column
my_bool Parsed; // True when parsed
my_bool Found; // Item found by locate
+ my_bool Wr; // Write mode
+ my_bool Jb; // Must return json item
}; // end of class JSNX
diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc
index 76a00c7e7f6..2e9085b4c87 100644
--- a/storage/connect/mycat.cc
+++ b/storage/connect/mycat.cc
@@ -89,6 +89,7 @@
#if defined(XML_SUPPORT)
#include "tabxml.h"
#endif // XML_SUPPORT
+#include "mycat.h"
/***********************************************************************/
/* Extern static variables. */
diff --git a/storage/connect/mysql-test/connect/r/json_udf.result b/storage/connect/mysql-test/connect/r/json_udf.result
index 81acbea91a6..5089022c5ea 100644
--- a/storage/connect/mysql-test/connect/r/json_udf.result
+++ b/storage/connect/mysql-test/connect/r/json_udf.result
@@ -2,11 +2,14 @@ CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=VIR BLOCK_SIZE=5;
#
# Test UDF's with constant arguments
#
-SELECT JsonValue(56,3.1416,'foo',NULL);
+SELECT JsonValue(56, 3.1416, 'foo', NULL);
ERROR HY000: Can't initialize function 'jsonvalue'; Cannot accept more than 1 argument
SELECT JsonValue(3.1416);
JsonValue(3.1416)
3.141600
+SELECT JsonValue(-80);
+JsonValue(-80)
+-80
SELECT JsonValue('foo');
JsonValue('foo')
"foo"
@@ -25,8 +28,8 @@ false
SELECT JsonValue();
JsonValue()
null
-SELECT JsonValue('[11,22,33]' json_) FROM t1;
-JsonValue('[11,22,33]' json_)
+SELECT JsonValue('[11, 22, 33]' json_) FROM t1;
+JsonValue('[11, 22, 33]' json_)
[11,22,33]
[11,22,33]
[11,22,33]
@@ -35,27 +38,29 @@ JsonValue('[11,22,33]' json_)
SELECT Json_Array();
Json_Array()
[]
-SELECT Json_Array(56,3.1416,'My name is "Foo"',NULL);
-Json_Array(56,3.1416,'My name is "Foo"',NULL)
+SELECT Json_Array(56, 3.1416, 'My name is "Foo"', NULL);
+Json_Array(56, 3.1416, 'My name is "Foo"', NULL)
[56,3.141600,"My name is \"Foo\"",null]
-SELECT Json_Array(Json_Array(56,3.1416,'foo'),NULL);
-Json_Array(Json_Array(56,3.1416,'foo'),NULL)
-[[56,3.141600,"foo"],null]
-SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL)) Array;
+SELECT Json_Array(Json_Array(56, 3.1416, 'foo'), TRUE);
+Json_Array(Json_Array(56, 3.1416, 'foo'), TRUE)
+[[56,3.141600,"foo"],true]
+SELECT Json_Array_Add(Json_Array(56, 3.1416, 'foo', NULL)) Array;
ERROR HY000: Can't initialize function 'json_array_add'; This function must have at least 2 arguments
-SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL),'One more') Array;
+SELECT Json_Array_Add(Json_Array(56, 3.1416, 'foo', NULL), 'One more') Array;
Array
[56,3.141600,"foo",null,"One more"]
-SELECT Json_Array_Add(JsonValue('one value'),'One more');
+SELECT Json_Array_Add(JsonValue('one value'), 'One more');
ERROR HY000: Can't initialize function 'json_array_add'; First argument must be a json item
-SELECT Json_Array_Add('one value','One more');
+SELECT Json_Array_Add('one value', 'One more');
ERROR HY000: Can't initialize function 'json_array_add'; First argument must be a json item
-SELECT Json_Array_Add('one value' json_,'One more');
-Json_Array_Add('one value' json_,'One more')
+SELECT Json_Array_Add('one value' json_, 'One more');
+Json_Array_Add('one value' json_, 'One more')
one value
Warnings:
Warning 1105 Error 2 opening one value
Warning 1105 First argument target is not an array
+SELECT Json_Array_Add(5 json_, 'One more');
+ERROR HY000: Can't initialize function 'json_array_add'; First argument must be a json item
SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 0);
Json_Array_Add('[5,3,8,7,9]' json_, 4, 0)
[4,5,3,8,7,9]
@@ -65,6 +70,15 @@ Array
SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 9);
Json_Array_Add('[5,3,8,7,9]' json_, 4, 9)
[5,3,8,7,9,4]
+SELECT Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), '[2]', 33, 1);
+Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), '[2]', 33, 1)
+[1,2,[11,22],"[2]"]
+SELECT Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), 33, '[2]', 1);
+Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), 33, '[2]', 1)
+[1,2,[11,33,22]]
+SELECT Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), 33, 1, '[2]');
+Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), 33, 1, '[2]')
+[1,2,[11,33,22]]
SELECT Json_Array_Add_Values(Json_Array(56, 3.1416, 'machin', NULL), 'One more', 'Two more') Array;
Array
[56,3.141600,"machin",null,"One more","Two more"]
@@ -92,19 +106,24 @@ Array
SELECT Json_Array_Add_Values('[56]', 3.1416, 'machin') Array;
Array
[56,3.141600,"machin"]
-SELECT Json_Array_Delete(Json_Array(56,3.1416,'My name is "Foo"',NULL),0);
-Json_Array_Delete(Json_Array(56,3.1416,'My name is "Foo"',NULL),0)
+SELECT Json_Array_Delete(Json_Array(56, 3.1416, 'My name is "Foo"', NULL), 0);
+Json_Array_Delete(Json_Array(56, 3.1416, 'My name is "Foo"', NULL), 0)
[3.141600,"My name is \"Foo\"",null]
-SELECT Json_Array_Delete(Json_Object(56,3.1416,'My name is Foo',NULL),2);
-Json_Array_Delete(Json_Object(56,3.1416,'My name is Foo',NULL),2)
+SELECT Json_Array_Delete(Json_Object(56, 3.1416, 'My name is Foo', NULL), 2);
+Json_Array_Delete(Json_Object(56, 3.1416, 'My name is Foo', NULL), 2)
{"56":56,"3.1416":3.141600,"My name is Foo":"My name is Foo","NULL":null}
Warnings:
Warning 1105 First argument target is not an array
-SELECT Json_Array_Delete(Json_Array(56,3.1416,'My name is "Foo"',NULL),'2');
-Json_Array_Delete(Json_Array(56,3.1416,'My name is "Foo"',NULL),'2')
+SELECT Json_Array_Delete(Json_Array(56, 3.1416, 'My name is "Foo"', NULL), '2');
+Json_Array_Delete(Json_Array(56, 3.1416, 'My name is "Foo"', NULL), '2')
[56,3.141600,"My name is \"Foo\"",null]
Warnings:
Warning 1105 Missing or null array index
+SELECT Json_Array_Delete(json_array(56, 3.1416, 'My name is "Foo"', NULL), '2', 2);
+Json_Array_Delete(json_array(56, 3.1416, 'My name is "Foo"', NULL), '2', 2)
+[56,3.141600,"My name is \"Foo\"",null]
+Warnings:
+Warning 1105 No sub-item at '2'
SELECT Json_Object(56, 3.1416, 'foo', NULL);
Json_Object(56, 3.1416, 'foo', NULL)
{"56":56,"3.1416":3.141600,"foo":"foo","NULL":null}
@@ -120,19 +139,30 @@ Json_Object(Json_Array(56, 3.1416, 'foo'), NULL)
SELECT Json_Array(Json_Object(56 "qty", 3.1416 "price", 'foo') ,NULL);
Json_Array(Json_Object(56 "qty", 3.1416 "price", 'foo') ,NULL)
[{"qty":56,"price":3.141600,"foo":"foo"},null]
-SELECT Json_Object_Add(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty), 'blue' color);
-Json_Object_Add(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty), 'blue' color)
+SELECT Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL);
+Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL)
+{"qty":56,"price":3.141600,"truc":"machin","garanty":null}
+SELECT Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty');
+ERROR HY000: Can't initialize function 'json_object_key'; This function must have an even number of arguments
+SELECT Json_Object_Add(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color);
+Json_Object_Add(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color)
{"qty":56,"price":3.141600,"truc":"machin","garanty":null,"color":"blue"}
-SELECT Json_Object_Add(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty), 45.99 price);
-Json_Object_Add(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty), 45.99 price)
+SELECT Json_Object_Add(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price);
+Json_Object_Add(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price)
{"qty":56,"price":45.990000,"truc":"machin","garanty":null}
-SELECT Json_Object_Delete(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty), 'truc');
-Json_Object_Delete(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty), 'truc')
+SELECT Json_Object_Add(Json_File('notexist.json'), 'cheese' item, '[1]', 1);
+Json_Object_Add(Json_File('notexist.json'), 'cheese' item, '[1]', 1)
+NULL
+Warnings:
+Warning 1105 Error 2 opening notexist.json
+Warning 1105 First argument target is not an object
+SELECT Json_Object_Delete(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'truc');
+Json_Object_Delete(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'truc')
{"qty":56,"price":3.141600,"garanty":null}
-SELECT Json_Object_Delete(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty), 'chose');
-Json_Object_Delete(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty), 'chose')
+SELECT Json_Object_Delete(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'chose');
+Json_Object_Delete(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'chose')
{"qty":56,"price":3.141600,"truc":"machin","garanty":null}
-SELECT Json_Object_List(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty)) "Key List";
+SELECT Json_Object_List(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty)) "Key List";
Key List
["qty","price","truc","garanty"]
SELECT Json_Object_List('{"qty":56, "price":3.1416, "truc":"machin", "garanty":null}') "Key List";
@@ -188,6 +218,16 @@ DEPARTMENT Json_Array_Grp(NAME)
Warnings:
Warning 1105 Result truncated to json_grp_size values
SET connect_json_grp_size=30;
+SELECT Json_Object(title, Json_Array_Grp(name) `json_names`) from t3 GROUP BY title;
+Json_Object(title, Json_Array_Grp(name) `json_names`)
+{"title":"ADMINISTRATOR","names":["GOOSEPEN","FUNNIGUY","SHRINKY"]}
+{"title":"DIRECTOR","names":["QUINN","WERTHER","STRONG"]}
+{"title":"ENGINEER","names":["BROWNY","ORELLY","MARTIN","TONGHO","WALTER","SMITH"]}
+{"title":"PROGRAMMER","names":["BUGHAPPY"]}
+{"title":"SALESMAN","names":["WHEELFOR","MERCHANT","BULLOZER","BANCROFT","FODDERMAN"]}
+{"title":"SCIENTIST","names":["BIGHEAD","BIGHORN"]}
+{"title":"SECRETARY","names":["MESSIFUL","HONEY","SHORTSIGHT","CHERRY","MONAPENNY"]}
+{"title":"TYPIST","names":["KITTY","PLUMHEAD"]}
SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t3 GROUP BY DEPARTMENT;
Json_Array(DEPARTMENT, Json_Array_Grp(NAME))
["0021",["STRONG","SHORTSIGHT"]]
@@ -227,12 +267,12 @@ Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY
{"DEPARTMENT":"2452","TITLE":"SCIENTIST","EMPLOYES":[{"SERIALNO":"34567","NAME":"BIGHEAD","SALARY":8000.000000},{"SERIALNO":"36666","NAME":"BIGHORN","SALARY":11000.000000}]}
{"DEPARTMENT":"2452","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"11111","NAME":"CHERRY","SALARY":4500.000000}]}
SELECT Json_Object_Grp(SALARY) FROM t3;
-ERROR HY000: Can't initialize function 'json_object_grp'; This function requires 2 arguments (value, key)
-SELECT Json_Object_Grp(SALARY, NAME) FROM t3;
-Json_Object_Grp(SALARY, NAME)
+ERROR HY000: Can't initialize function 'json_object_grp'; This function requires 2 arguments (key, value)
+SELECT Json_Object_Grp(NAME, SALARY) FROM t3;
+Json_Object_Grp(NAME, SALARY)
{"BANCROFT":9600.000000,"SMITH":9000.000000,"MERCHANT":8700.000000,"FUNNIGUY":8500.000000,"BUGHAPPY":8500.000000,"BIGHEAD":8000.000000,"SHRINKY":7500.000000,"WALTER":7400.000000,"FODDERMAN":7000.000000,"TONGHO":6800.000000,"SHORTSIGHT":5500.000000,"MESSIFUL":5000.500000,"HONEY":4900.000000,"GOOSEPEN":4700.000000,"CHERRY":4500.000000,"MONAPENNY":3800.000000,"KITTY":3000.450000,"PLUMHEAD":2800.000000,"STRONG":23000.000000,"BULLOZER":14800.000000,"WERTHER":14500.000000,"QUINN":14000.000000,"ORELLY":13400.000000,"BIGHORN":11000.000000,"BROWNY":10500.000000,"WHEELFOR":10030.000000,"MARTIN":10000.000000}
-SELECT Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES") FROM t3 GROUP BY DEPARTMENT;
-Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES")
+SELECT Json_Object(DEPARTMENT, Json_Object_Grp(NAME, SALARY) "Json_SALARIES") FROM t3 GROUP BY DEPARTMENT;
+Json_Object(DEPARTMENT, Json_Object_Grp(NAME, SALARY) "Json_SALARIES")
{"DEPARTMENT":"0021","SALARIES":{"STRONG":23000.000000,"SHORTSIGHT":5500.000000}}
{"DEPARTMENT":"0318","SALARIES":{"BANCROFT":9600.000000,"PLUMHEAD":2800.000000,"HONEY":4900.000000,"TONGHO":6800.000000,"WALTER":7400.000000,"SHRINKY":7500.000000,"WERTHER":14500.000000,"MERCHANT":8700.000000,"WHEELFOR":10030.000000}}
{"DEPARTMENT":"0319","SALARIES":{"BULLOZER":14800.000000,"QUINN":14000.000000,"BROWNY":10500.000000,"KITTY":3000.450000,"MONAPENNY":3800.000000,"MARTIN":10000.000000,"FUNNIGUY":8500.000000,"BUGHAPPY":8500.000000,"FODDERMAN":7000.000000,"MESSIFUL":5000.500000,"GOOSEPEN":4700.000000}}
@@ -240,6 +280,20 @@ Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES")
SELECT Json_Array_Grp(NAME) FROM t3;
Json_Array_Grp(NAME)
["BANCROFT","SMITH","MERCHANT","FUNNIGUY","BUGHAPPY","BIGHEAD","SHRINKY","WALTER","FODDERMAN","TONGHO","SHORTSIGHT","MESSIFUL","HONEY","GOOSEPEN","CHERRY","MONAPENNY","KITTY","PLUMHEAD","STRONG","BULLOZER","WERTHER","QUINN","ORELLY","BIGHORN","BROWNY","WHEELFOR","MARTIN"]
+SELECT Json_Object_Key(name, title) FROM t3 WHERE DEPARTMENT = 318;
+Json_Object_Key(name, title)
+{"BANCROFT":"SALESMAN"}
+{"MERCHANT":"SALESMAN"}
+{"SHRINKY":"ADMINISTRATOR"}
+{"WALTER":"ENGINEER"}
+{"TONGHO":"ENGINEER"}
+{"HONEY":"SECRETARY"}
+{"PLUMHEAD":"TYPIST"}
+{"WERTHER":"DIRECTOR"}
+{"WHEELFOR":"SALESMAN"}
+SELECT Json_Object_Grp(name, title) FROM t3 WHERE DEPARTMENT = 318;
+Json_Object_Grp(name, title)
+{"BANCROFT":"SALESMAN","MERCHANT":"SALESMAN","SHRINKY":"ADMINISTRATOR","WALTER":"ENGINEER","TONGHO":"ENGINEER","HONEY":"SECRETARY","PLUMHEAD":"TYPIST","WERTHER":"DIRECTOR","WHEELFOR":"SALESMAN"}
#
# Test value getting UDF's
#
@@ -304,42 +358,40 @@ JsonGet_Int(@j1, '[#]')
SELECT JsonGet_Int(@j1, '[+]');
JsonGet_Int(@j1, '[+]')
243
-SELECT JsonGet_Int(@j1 json_,'[3]');
-JsonGet_Int(@j1 json_,'[3]')
+SELECT JsonGet_Int(@j1 json_, '[3]');
+JsonGet_Int(@j1 json_, '[3]')
45
-SELECT JsonGet_Int(Json_Array(45,28,36,45,89),'[3]');
-JsonGet_Int(Json_Array(45,28,36,45,89),'[3]')
+SELECT JsonGet_Int(Json_Array(45,28,36,45,89), '[3]');
+JsonGet_Int(Json_Array(45,28,36,45,89), '[3]')
45
-SELECT JsonGet_Int(Json_Array(45,28,36,45,89),'["+"]');
-JsonGet_Int(Json_Array(45,28,36,45,89),'["+"]')
+SELECT JsonGet_Int(Json_Array(45,28,36,45,89), '["+"]');
+JsonGet_Int(Json_Array(45,28,36,45,89), '["+"]')
45
-SELECT JsonGet_Int(Json_Array(45,28,36,45,89),'[+]');
-JsonGet_Int(Json_Array(45,28,36,45,89),'[+]')
+SELECT JsonGet_Int(Json_Array(45,28,36,45,89), '[+]');
+JsonGet_Int(Json_Array(45,28,36,45,89), '[+]')
243
-SELECT JsonGet_Int(Json_Array(json_array(45,28),json_array(36,45,89)),'[1]:[0]');
-JsonGet_Int(Json_Array(json_array(45,28),json_array(36,45,89)),'[1]:[0]')
+SELECT JsonGet_Int(Json_Array(json_array(45,28), json_array(36,45,89)), '[1]:[0]');
+JsonGet_Int(Json_Array(json_array(45,28), json_array(36,45,89)), '[1]:[0]')
36
-SELECT JsonGet_Int(Json_Array(json_array(45,28),json_array(36,45,89)),'[0]:[1]');
-JsonGet_Int(Json_Array(json_array(45,28),json_array(36,45,89)),'[0]:[1]')
+SELECT JsonGet_Int(Json_Array(json_array(45,28), json_array(36,45,89)), '[0]:[1]');
+JsonGet_Int(Json_Array(json_array(45,28), json_array(36,45,89)), '[0]:[1]')
28
-SELECT JsonGet_Int(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'qty');
-JsonGet_Int(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'qty')
+SELECT JsonGet_Int(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'qty');
+JsonGet_Int(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'qty')
56
-SELECT JsonGet_Int(@j2 json_,'price');
-JsonGet_Int(@j2 json_,'price')
+SELECT JsonGet_Int(@j2 json_, 'price');
+JsonGet_Int(@j2 json_, 'price')
3
-SELECT JsonGet_Int(@j2,'qty');
-JsonGet_Int(@j2,'qty')
+SELECT JsonGet_Int(@j2, 'qty');
+JsonGet_Int(@j2, 'qty')
56
-SELECT JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose');
-JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose')
+SELECT JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'chose');
+JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'chose')
NULL
-Warnings:
-Warning 1105 Value not found
-SELECT JsonGet_Int(JsonGet_String(Json_Array(Json_Array(45,28),Json_Array(36,45,89)),'[1]:*'),'[+]') sum;
+SELECT JsonGet_Int(JsonGet_String(Json_Array(Json_Array(45,28),Json_Array(36,45,89)), '[1]:*'), '[+]') sum;
sum
170
-SELECT department, JsonGet_Int(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"),'salaries:[+]') Sumsal FROM t3 GROUP BY department;
+SELECT department, JsonGet_Int(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"), 'salaries:[+]') Sumsal FROM t3 GROUP BY department;
department Sumsal
0021 28500
0318 72230
@@ -348,41 +400,39 @@ department Sumsal
SELECT JsonGet_Real(@j1, '[2]');
JsonGet_Real(@j1, '[2]')
36.000000000000000
-SELECT JsonGet_Real(@j1 json_,'[3]',2);
-JsonGet_Real(@j1 json_,'[3]',2)
+SELECT JsonGet_Real(@j1 json_, '[3]', 2);
+JsonGet_Real(@j1 json_, '[3]', 2)
45.00
-SELECT JsonGet_Real(Json_Array(45,28,36,45,89),'[3]');
-JsonGet_Real(Json_Array(45,28,36,45,89),'[3]')
+SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '[3]');
+JsonGet_Real(Json_Array(45,28,36,45,89), '[3]')
45.000000000000000
-SELECT JsonGet_Real(Json_Array(45,28,36,45,89),'["+"]');
-JsonGet_Real(Json_Array(45,28,36,45,89),'["+"]')
+SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '["+"]');
+JsonGet_Real(Json_Array(45,28,36,45,89), '["+"]')
45.000000000000000
-SELECT JsonGet_Real(Json_Array(45,28,36,45,89),'[+]');
-JsonGet_Real(Json_Array(45,28,36,45,89),'[+]')
+SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '[+]');
+JsonGet_Real(Json_Array(45,28,36,45,89), '[+]')
243.000000000000000
-SELECT JsonGet_Real(Json_Array(45,28,36,45,89),'[!]');
-JsonGet_Real(Json_Array(45,28,36,45,89),'[!]')
+SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '[!]');
+JsonGet_Real(Json_Array(45,28,36,45,89), '[!]')
48.600000000000000
-SELECT JsonGet_Real(Json_Array(json_array(45,28),json_array(36,45,89)),'[1]:[0]');
-JsonGet_Real(Json_Array(json_array(45,28),json_array(36,45,89)),'[1]:[0]')
+SELECT JsonGet_Real(Json_Array(json_array(45,28), json_array(36,45,89)), '[1]:[0]');
+JsonGet_Real(Json_Array(json_array(45,28), json_array(36,45,89)), '[1]:[0]')
36.000000000000000
-SELECT JsonGet_Real(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'price');
-JsonGet_Real(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'price')
+SELECT JsonGet_Real(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'price');
+JsonGet_Real(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'price')
3.141600000000000
-SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}' json_,'qty');
-JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}' json_,'qty')
+SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}' json_, 'qty');
+JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}' json_, 'qty')
56.000000000000000
-SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','price');
-JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','price')
+SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'price');
+JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'price')
3.141600000000000
-SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','price', 4);
-JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','price', 4)
+SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'price', 4);
+JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'price', 4)
3.1416
-SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose');
-JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose')
+SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'chose');
+JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'chose')
NULL
-Warnings:
-Warning 1105 Value not found
SELECT department, JsonGet_Real(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"),'salaries:[+]') Sumsal FROM t3 GROUP BY department;
department Sumsal
0021 28500.000000000000000
@@ -401,12 +451,12 @@ JsonGet_Real(Json_Array(45,28,36,45,89), '[!]', 2) "Avg";
Rank Number Concat Sum Avg
89 5 45,28,36,45,89 243 48.60
SELECT
-JsonGet_String('{"qty":7,"price":29.50,"garanty":null}','price') "String",
-JsonGet_Int('{"qty":7,"price":29.50,"garanty":null}','price') "Int",
-JsonGet_Real('{"qty":7,"price":29.50,"garanty":null}','price') "Real";
+JsonGet_String('{"qty":7,"price":29.50,"garanty":null}', 'price') "String",
+JsonGet_Int('{"qty":7,"price":29.50,"garanty":null}', 'price') "Int",
+JsonGet_Real('{"qty":7,"price":29.50,"garanty":null}', 'price') "Real";
String Int Real
29.50 29 29.500000000000000
-SELECT JsonGet_Real('{"qty":7,"price":29.50,"garanty":null}','price',3) "Real";
+SELECT JsonGet_Real('{"qty":7,"price":29.50,"garanty":null}', 'price', 3) "Real";
Real
29.500
#
@@ -515,7 +565,7 @@ Json_Locate_All('test/biblio.json' jfile_, 'Knab')
#
# Testing json files
#
-select Jfile_Make('[{"_id":5,"type":"food","item":"beer","taste":"light","price":5.65,"ratings":[5,8,9]},
+SELECT Jfile_Make('[{"_id":5,"type":"food","item":"beer","taste":"light","price":5.65,"ratings":[5,8,9]},
{"_id":6,"type":"car","item":"roadster","mileage":56000,"ratings":[6,9]},
{"_id":7,"type":"food","item":"meat","origin":"argentina","ratings":[2,4]},
{"_id":8,"type":"furniture","item":"table","size":{"W":60,"L":80,"H":40},"ratings":[5,8,7]}]', 'test/fx.json', 0) AS NewFile;
diff --git a/storage/connect/mysql-test/connect/r/json_udf_bin.result b/storage/connect/mysql-test/connect/r/json_udf_bin.result
new file mode 100644
index 00000000000..4e59b51c529
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/json_udf_bin.result
@@ -0,0 +1,588 @@
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=VIR BLOCK_SIZE=3;
+#
+# Test Jbin UDF's
+#
+SELECT Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), n) from t1;
+Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), n)
+[56,3.141600,"My name is \"Foo\"",null,1]
+[56,3.141600,"My name is \"Foo\"",null,2]
+[56,3.141600,"My name is \"Foo\"",null,3]
+SELECT Json_Array_Add(Jbin_Array(n, 3.1416, 'My name is "Foo"', NULL), n) from t1;
+Json_Array_Add(Jbin_Array(n, 3.1416, 'My name is "Foo"', NULL), n)
+[1,3.141600,"My name is \"Foo\"",null,1]
+[2,3.141600,"My name is \"Foo\"",null,2]
+[3,3.141600,"My name is \"Foo\"",null,3]
+SELECT Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), Jbin_Array('a','b',n)) from t1;
+Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), Jbin_Array('a','b',n))
+[56,3.141600,"My name is \"Foo\"",null,["a","b",1]]
+[56,3.141600,"My name is \"Foo\"",null,["a","b",2]]
+[56,3.141600,"My name is \"Foo\"",null,["a","b",3]]
+SELECT Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), JsonGet_String(Jbin_Array('a','b','c'), '[1]'));
+Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), JsonGet_String(Jbin_Array('a','b','c'), '[1]'))
+[56,3.141600,"My name is \"Foo\"",null,"b"]
+SELECT Json_Array_Delete(Jbin_Array_Add_Values(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), "One more", 2), 4);
+Json_Array_Delete(Jbin_Array_Add_Values(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), "One more", 2), 4)
+[56,3.141600,"My name is \"Foo\"",null,2]
+SELECT Json_Array_Delete(Jbin_Array(56, Jbin_Array(3.1416, 'My name is "Foo"'), NULL), '[1]', 1);
+Json_Array_Delete(Jbin_Array(56, Jbin_Array(3.1416, 'My name is "Foo"'), NULL), '[1]', 1)
+[56,[3.141600],null]
+SELECT Json_Array_Delete(Jbin_Array(56, Jbin_Array(3.1416, 'My name is "Foo"'), TRUE), 1, '[1]');
+Json_Array_Delete(Jbin_Array(56, Jbin_Array(3.1416, 'My name is "Foo"'), TRUE), 1, '[1]')
+[56,[3.141600],true]
+SELECT Json_Array(1, TRUE, 0, FALSE);
+Json_Array(1, TRUE, 0, FALSE)
+[1,true,0,false]
+SELECT Json_Serialize(Jbin_Array(TRUE, FALSE));
+Json_Serialize(Jbin_Array(TRUE, FALSE))
+[true,false]
+SELECT Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL);
+Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL)
+{"qty":56,"price":3.141600,"truc":"machin","garanty":null}
+SELECT Json_Serialize(Jbin_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL));
+Json_Serialize(Jbin_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL))
+{"qty":56,"price":3.141600,"truc":"machin","garanty":null}
+SELECT Jbin_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty');
+ERROR HY000: Can't initialize function 'jbin_object_key'; This function must have an even number of arguments
+SELECT Json_Object_Add(Jbin_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color);
+Json_Object_Add(Jbin_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color)
+{"qty":56,"price":3.141600,"truc":"machin","garanty":null,"color":"blue"}
+SELECT Json_Object_Add(Jbin_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price);
+Json_Object_Add(Jbin_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price)
+{"qty":56,"price":45.990000,"truc":"machin","garanty":null}
+SELECT Json_Object_Add(Jbin_Object_Nonull(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color);
+Json_Object_Add(Jbin_Object_Nonull(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color)
+{"qty":56,"price":3.141600,"truc":"machin","color":"blue"}
+SELECT Json_Object_Add(Jbin_Object_Nonull(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price);
+Json_Object_Add(Jbin_Object_Nonull(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price)
+{"qty":56,"price":45.990000,"truc":"machin"}
+#
+# Test Jbin file UDF's
+#
+SELECT Json_Serialize(Jbin_File('gloss.json'));
+Json_Serialize(Jbin_File('gloss.json'))
+{"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}}}
+SELECT JsonLocate(Jbin_File('gloss.json'),'XML');
+JsonLocate(Jbin_File('gloss.json'),'XML')
+glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso:[1]
+SELECT Json_Object_Key('first', 'foo', 'second', Jbin_Array('a', 33));
+Json_Object_Key('first', 'foo', 'second', Jbin_Array('a', 33))
+{"first":"foo","second":["a",33]}
+SELECT Json_Get_Item(Json_Array('a','b','c'), '[1]');
+Json_Get_Item(Json_Array('a','b','c'), '[1]')
+NULL
+SELECT Json_Get_Item(Json_Object('foo' AS "first", Json_Array('a', 33) AS "json_second"), 'second') AS "item";
+item
+["a",33]
+SELECT Json_Get_Item(Jbin_Object('foo' first, Jbin_Array('a', 33) jbin_second), 'second:*') item;
+item
+["a",33]
+SELECT Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv');
+Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv')
+{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}
+SELECT Json_Serialize(Jbin_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv'));
+Json_Serialize(Jbin_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv'))
+{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}
+SELECT Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:*');
+Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:*')
+{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}
+SELECT JsonGet_String(Json_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso') lang;
+lang
+GML
+SELECT Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso') "See also";
+See also
+["GML","XML"]
+SELECT Json_Serialize(Jbin_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso')) "See also";
+See also
+["GML","XML"]
+SELECT JsonGet_String(Json_Get_Item(Json_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso'),'[0]') lang;
+lang
+GML
+#
+# Test Item Get/Set/Insert/Update UDF's
+#
+SELECT Json_Get_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), '[]');
+Json_Get_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), '[]')
+[1,2,{"trois":3,"quatre":4}]
+SELECT Json_Get_Item(Jbin_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), '[1]');
+Json_Get_Item(Jbin_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), '[1]')
+NULL
+SELECT Json_Get_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), '[1]');
+Json_Get_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), '[1]')
+NULL
+SELECT Json_Set_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)));
+Json_Set_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)))
+[1,2,{"trois":3,"quatre":4}]
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 'foo');
+ERROR HY000: Can't initialize function 'json_set_item'; This function must have an odd number of arguments
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq');
+Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq')
+[1,2,{"trois":3,"quatre":4,"cinq":5}]
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 7, '[1]');
+Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 7, '[1]')
+[1,7,{"trois":3,"quatre":4}]
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 7, '[1]');
+Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 7, '[1]')
+[1,7,{"trois":3,"quatre":4,"cinq":5}]
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Json_Array(7, 8, 9), '[1]');
+Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Json_Array(7, 8, 9), '[1]')
+[1,[7,8,9],{"trois":3,"quatre":4}]
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[2]');
+Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[2]')
+[1,2,[7,8,9]]
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[2]:*');
+Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[2]:*')
+[1,2,{"trois":3,"quatre":4}]
+Warnings:
+Warning 1105 Invalid specification * in a write path
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 3.1416, 'foo');
+Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 3.1416, 'foo')
+[1,2,{"trois":3,"quatre":4}]
+SELECT Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 'toto', '[1]:[2]');
+Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 'toto', '[1]:[2]')
+[1,[7,8,"toto"],{"trois":3,"quatre":4}]
+SELECT Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 300, '[2]:nxt:total:[]');
+Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 300, '[2]:nxt:total:[]')
+[1,[7,8,9],{"trois":3,"quatre":4,"nxt":{"total":[300]}}]
+SELECT Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 300, '[2]:nxt:total:[]');
+Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 300, '[2]:nxt:total:[]')
+[1,[7,8,9,10],{"trois":3,"quatre":4,"cinq":5,"nxt":{"total":[300]}}]
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[1]', 5, '[2]:cinq', 10, '[1]:[]');
+Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[1]', 5, '[2]:cinq', 10, '[1]:[]')
+[1,[7,8,9,10],{"trois":3,"quatre":4,"cinq":5}]
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 44, '[2]:quatre');
+Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 44, '[2]:quatre')
+[1,2,{"trois":3,"quatre":44}]
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, 'truc');
+Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, 'truc')
+[1,2,{"trois":3,"quatre":4}]
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '');
+Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '')
+[1,2,{"trois":3,"quatre":4},5]
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '*');
+Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '*')
+[1,2,{"trois":3,"quatre":4}]
+Warnings:
+Warning 1105 Invalid specification * in a write path
+SELECT Json_Serialize(Jbin_Set_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq'));
+Json_Serialize(Jbin_Set_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq'))
+[1,2,{"trois":3,"quatre":4,"cinq":5}]
+SELECT Json_Insert_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq');
+Json_Insert_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq')
+[1,2,{"trois":3,"quatre":4,"cinq":5}]
+SELECT Json_Update_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq');
+Json_Update_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq')
+[1,2,{"trois":3,"quatre":4}]
+SELECT Json_Insert_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 44, '[2]:quatre');
+Json_Insert_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 44, '[2]:quatre')
+[1,[7,8,9,10],{"trois":3,"quatre":4,"cinq":5}]
+SELECT Json_Update_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 44, '[2]:quatre');
+Json_Update_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 44, '[2]:quatre')
+[1,[7,8,9],{"trois":3,"quatre":44}]
+SELECT Json_Insert_Item(Json_Array(1, Json_Array(7, 8, 9), Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[1]', 300, '[2]:nxt:total:[]');
+Json_Insert_Item(Json_Array(1, Json_Array(7, 8, 9), Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[1]', 300, '[2]:nxt:total:[]')
+[1,[7,8,9],{"trois":3,"quatre":4,"cinq":5,"nxt":{"total":[300]}}]
+SELECT Json_Update_Item(Json_Array(1, Json_Array(7, 8, 9), Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[1]', 300, '[2]:nxt:total:[]');
+Json_Update_Item(Json_Array(1, Json_Array(7, 8, 9), Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[1]', 300, '[2]:nxt:total:[]')
+[1,[7,10,9],{"trois":3,"quatre":4}]
+SELECT Json_Insert_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[]');
+Json_Insert_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[]')
+[1,2,{"trois":3,"quatre":4},5]
+SELECT Json_Update_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[]');
+Json_Update_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[]')
+[1,2,{"trois":3,"quatre":4}]
+#
+# Test merging items UDF's
+#
+SELECT Json_Item_Merge(Jbin_Array('a','b','c'), Jbin_Array('d','e','f'));
+Json_Item_Merge(Jbin_Array('a','b','c'), Jbin_Array('d','e','f'))
+["a","b","c","d","e","f"]
+SELECT Json_Item_Merge(Json_Array('a','b','c'), Json_Array('d','e','f')) AS "Result";
+Result
+["a","b","c","d","e","f"]
+SELECT Json_Array_Add(Jbin_Item_Merge(Jbin_Array('a','b','c'), Jbin_Array('d','e','f')), 'and', 3);
+Json_Array_Add(Jbin_Item_Merge(Jbin_Array('a','b','c'), Jbin_Array('d','e','f')), 'and', 3)
+["a","b","c","and","d","e","f"]
+SELECT Json_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "d",5 "e",6 "f"));
+Json_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "d",5 "e",6 "f"))
+{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6}
+SELECT Json_Item_Merge(Jbin_Object(1 "a",2 "b",2 "c"), Jbin_Array('d','e','f'));
+Json_Item_Merge(Jbin_Object(1 "a",2 "b",2 "c"), Jbin_Array('d','e','f'))
+Binary Json object
+Warnings:
+Warning 1105 Second argument is not an object
+SELECT Json_Object_Add(Jbin_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "d",5 "e",6 "f")), 'x' AS "and");
+Json_Object_Add(Jbin_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "d",5 "e",6 "f")), 'x' AS "and")
+{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6,"and":"x"}
+SELECT Json_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "a",5 "e",6 "f"));
+Json_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "a",5 "e",6 "f"))
+{"a":4,"b":2,"c":3,"e":5,"f":6}
+SELECT Json_Item_Merge('foo', Json_Array('d','e','f'));
+ERROR HY000: Can't initialize function 'json_item_merge'; First argument must be a json item
+#
+# Test making file UDF's
+#
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
+bt1.json
+SELECT Json_File('bt1.json');
+Json_File('bt1.json')
+[
+ "a",
+ "b",
+ "c"
+]
+
+SELECT Json_File(Jfile_Make(Jbin_File('bt1.json'), 0));
+Json_File(Jfile_Make(Jbin_File('bt1.json'), 0))
+"a"
+"b"
+"c"
+
+SELECT Json_File(Jfile_Make(Jbin_File('bt1.json'), 1));
+Json_File(Jfile_Make(Jbin_File('bt1.json'), 1))
+[
+ "a",
+ "b",
+ "c"
+]
+
+SELECT Json_File(Jfile_Make(Jbin_File('bt1.json'), 2));
+Json_File(Jfile_Make(Jbin_File('bt1.json'), 2))
+[
+ "a",
+ "b",
+ "c"
+]
+
+SELECT Json_File('bt1.json', 0);
+Json_File('bt1.json', 0)
+["a","b","c"]
+Warnings:
+Warning 1105 File pretty format doesn't match the specified pretty value
+SELECT Json_File('bt1.json', 1);
+Json_File('bt1.json', 1)
+["a","b","c"]
+Warnings:
+Warning 1105 File pretty format doesn't match the specified pretty value
+SELECT Json_File('bt1.json', 2);
+Json_File('bt1.json', 2)
+["a","b","c"]
+SELECT Json_Serialize(Jbin_Array('a','b','c'));
+Json_Serialize(Jbin_Array('a','b','c'))
+["a","b","c"]
+SELECT Json_Serialize(Jbin_Array_Add(Jbin_File('not_exist.json'), 'd'));
+Json_Serialize(Jbin_Array_Add(Jbin_File('not_exist.json'), 'd'))
+Null json tree
+Warnings:
+Warning 1105 Open(map) error 2 on not_exist.json
+Warning 1105 First argument is not an array
+# This does not modify the file
+SELECT Json_Serialize(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'));
+Json_Serialize(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'))
+["a","b","c","d"]
+SELECT Json_File('bt1.json', 2);
+Json_File('bt1.json', 2)
+["a","b","c"]
+# This does modify the file
+SELECT Json_Array_Add(Jbin_File('bt1.json'), 'd');
+Json_Array_Add(Jbin_File('bt1.json'), 'd')
+bt1.json
+SELECT Json_File('bt1.json', 2);
+Json_File('bt1.json', 2)
+["a","b","c","d"]
+# Back to the original file
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
+bt1.json
+SELECT Json_Object(Jbin_Array_Add(Jbin_Array('a','b','c'), 'd') "Jbin_foo") AS "Result";
+Result
+{"foo":["a","b","c","d"]}
+SELECT Json_Object(Jbin_Array_Add(Jbin_File('bt1.json'), 'd')) AS "Result";
+Result
+{"Array_Add(Jbin_File('bt1.json'), 'd')":["a","b","c","d"]}
+SELECT Json_Object(Jbin_Array_Add(Jbin_File('bt1.json'), 'd') "Jbin_bt1") AS "Result";
+Result
+{"bt1":["a","b","c","d"]}
+# This does modify the file
+SELECT Json_Object(Json_Array_Add(Jbin_File('bt1.json'), 'd') "Jfile_bt1") AS "Result";
+Result
+{"bt1":["a","b","c","d"]}
+SELECT Json_File('bt1.json');
+Json_File('bt1.json')
+[
+ "a",
+ "b",
+ "c",
+ "d"
+]
+
+SELECT Json_File(Json_Array_Delete(Jbin_File('bt1.json'), 3), 2);
+Json_File(Json_Array_Delete(Jbin_File('bt1.json'), 3), 2)
+["a","b","c"]
+SELECT Json_Object(Jbin_Array_Add(Jbin_File('bt1.json'), 'd') "Jbin_bt1", n "t1") AS "Result" from t1;
+Result
+{"bt1":["a","b","c","d"],"t1":1}
+{"bt1":["a","b","c","d"],"t1":2}
+{"bt1":["a","b","c","d"],"t1":3}
+SELECT Json_File(Json_Array_Add(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'), 'e')) AS "Result";
+Result
+[
+ "a",
+ "b",
+ "c",
+ "d",
+ "e"
+]
+
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
+bt1.json
+SELECT Json_File(Json_Array_Add(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'), 'e')) AS "Result" from t1;
+Result
+[
+ "a",
+ "b",
+ "c",
+ "d",
+ "e"
+]
+
+[
+ "a",
+ "b",
+ "c",
+ "d",
+ "e"
+]
+
+[
+ "a",
+ "b",
+ "c",
+ "d",
+ "e"
+]
+
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
+bt1.json
+SELECT Json_Array_Add(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'), n) AS "Result" from t1;
+Result
+bt1.json
+bt1.json
+bt1.json
+# Show modified file
+SELECT Json_File('bt1.json');
+Json_File('bt1.json')
+[
+ "a",
+ "b",
+ "c",
+ "d",
+ 1,
+ "d",
+ 2,
+ "d",
+ 3
+]
+
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
+bt1.json
+SELECT Json_Array_Add(Jbin_File('bt1.json'), n) AS "Result" from t1;
+Result
+bt1.json
+bt1.json
+bt1.json
+# Show modified file
+SELECT Json_File('bt1.json');
+Json_File('bt1.json')
+[
+ "a",
+ "b",
+ "c",
+ 1,
+ 2,
+ 3
+]
+
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
+bt1.json
+SELECT Json_File(Jbin_Item_Merge(Jbin_File('bt1.json'), Jbin_Array('d','e','f')));
+Json_File(Jbin_Item_Merge(Jbin_File('bt1.json'), Jbin_Array('d','e','f')))
+[
+ "a",
+ "b",
+ "c"
+]
+
+SELECT Json_File(Json_Item_Merge(Jbin_File('bt1.json'), Jbin_Array('d','e','f')));
+Json_File(Json_Item_Merge(Jbin_File('bt1.json'), Jbin_Array('d','e','f')))
+[
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f"
+]
+
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json')
+bt1.json
+# Test DELETE from file
+SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 1)) AS "Result";
+Result
+{"Array_Delete(Jbin_File('bt1.json'), 1)":["a","c"]}
+SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 2) "Jbin_bt1") AS "Result";
+Result
+{"bt1":["a","b"]}
+SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 0) "Jbin_bt1", n "t1") AS "Result" from t1;
+Result
+{"bt1":["b","c"],"t1":1}
+{"bt1":["b","c"],"t1":2}
+{"bt1":["b","c"],"t1":3}
+SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 3 - n) "Jbin_bt1") AS "Result" from t1;
+Result
+{"bt1":["a","b"]}
+{"bt1":["a"]}
+{"bt1":[]}
+SELECT Json_Object(Json_Array_Delete(Jbin_File('bt1.json'), 3 - n) "Jbin_bt1") AS "Result" from t1;
+Result
+{"bt1":["a","b"]}
+{"bt1":["a"]}
+{"bt1":[]}
+# Show modified file
+SELECT Json_File('bt1.json');
+Json_File('bt1.json')
+[
+
+]
+
+# Object file
+SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
+Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0)
+bt2.json
+SELECT Json_File('bt2.json', 0);
+Json_File('bt2.json', 0)
+{"a":1,"b":2,"c":3}
+SELECT Json_File('bt2.json');
+Json_File('bt2.json')
+{"a":1,"b":2,"c":3}
+
+SELECT Json_Serialize(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"));
+Json_Serialize(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"))
+{"a":1,"b":2,"c":3,"d":4}
+# First query (file not modified)
+SELECT Json_Object(Jbin_Object_Add(Jbin_File('bt2.json'), 4 AS "d") AS "Jbin_new") AS "Result";
+Result
+{"new":{"a":1,"b":2,"c":3,"d":4}}
+# First query (file modified)
+SELECT Json_Object(Json_Object_Add(Jbin_File('bt2.json'), 4 AS "d") AS "Jfile_new") AS "Result";
+Result
+{"new":{"a":1,"b":2,"c":3,"d":4}}
+SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
+Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0)
+bt2.json
+SELECT Json_Object(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d") "Jbin_new", n "t1") AS "Result" from t1;
+Result
+{"new":{"a":1,"b":2,"c":3,"d":4},"t1":1}
+{"new":{"a":1,"b":2,"c":3,"d":4},"t1":2}
+{"new":{"a":1,"b":2,"c":3,"d":4},"t1":3}
+SELECT Json_File(Json_Object_Add(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"), 5 "e")) AS "Result";
+Result
+{"a":1,"b":2,"c":3,"d":4,"e":5}
+
+SELECT Json_Object_Add(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"), 5 "e") AS "Result" from t1;
+Result
+bt2.json
+bt2.json
+bt2.json
+SELECT Json_Object_Add(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"), n "n") AS "Result" from t1;
+Result
+bt2.json
+bt2.json
+bt2.json
+SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
+Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0)
+bt2.json
+SELECT Json_Object_Add(Jbin_File('bt2.json'), n) AS "Result" from t1;
+Result
+bt2.json
+bt2.json
+bt2.json
+SELECT Json_File('bt2.json');
+Json_File('bt2.json')
+{"a":1,"b":2,"c":3,"n":3}
+
+SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
+Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0)
+bt2.json
+SELECT Json_Serialize(Jbin_Item_Merge(Jbin_File('bt2.json'), Jbin_Object(4 "d",5 "e",6 "f"))) AS "Result";
+Result
+{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6}
+SELECT Json_File(Json_Item_Merge(Jbin_File('bt2.json'), Jbin_Object(4 "d",5 "e",6 "f"))) AS "Result";
+Result
+{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6}
+
+SELECT Json_Item_Merge(Json_Object(1 "a", 2 "b", 3 "c"), Json_Object(4 "d",5 "b",6 "f")) AS "Result";
+Result
+{"a":1,"b":5,"c":3,"d":4,"f":6}
+SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'b')) AS "Result";
+Result
+{"Object_Delete(Jbin_File('bt2.json'), 'b')":{"a":1,"c":3,"d":4,"e":5,"f":6}}
+SELECT Json_Object(Jbin_Object_Delete(Jbin_File('bt2.json'), 'c') "Jbin_bt1") AS "Result";
+Result
+{"bt1":{"a":1,"d":4,"e":5,"f":6}}
+SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'c') "Jbin_bt1") AS "Result";
+Result
+{"bt1":{"a":1,"d":4,"e":5,"f":6}}
+SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'c') "Jfile_bt1") AS "Result";
+Result
+{"bt1":{"a":1,"d":4,"e":5,"f":6}}
+SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'a') "Jbin_bt1", n "t1") AS "Result" from t1;
+Result
+{"bt1":{"d":4,"e":5,"f":6},"t1":1}
+{"bt1":{"d":4,"e":5,"f":6},"t1":2}
+{"bt1":{"d":4,"e":5,"f":6},"t1":3}
+SELECT Json_Serialize(Jbin_Object_List(Jbin_File('bt2.json'))) "Key list";
+Key list
+["d","e","f"]
+SELECT Jfile_Make('{"a":1, "b":[44, 55]}' json_, 'bt3.json', 0);
+Jfile_Make('{"a":1, "b":[44, 55]}' json_, 'bt3.json', 0)
+bt3.json
+SELECT Json_Array_Add(Json_File('bt3.json', 'b'), 66);
+Json_Array_Add(Json_File('bt3.json', 'b'), 66)
+[44,55,66]
+SELECT Json_Array_Add(Json_File('bt3.json'), 66, 'b');
+Json_Array_Add(Json_File('bt3.json'), 66, 'b')
+{"a":1,"b":[44,55,66]}
+SELECT Json_Array_Add(Jbin_File('bt3.json', 'b'), 66);
+Json_Array_Add(Jbin_File('bt3.json', 'b'), 66)
+bt3.json
+SELECT Json_File('bt3.json', 3);
+Json_File('bt3.json', 3)
+{"a":1,"b":[44,55,66]}
+SELECT Jfile_Make('{"a":1, "b":[44, 55]}' json_, 'bt3.json', 0);
+Jfile_Make('{"a":1, "b":[44, 55]}' json_, 'bt3.json', 0)
+bt3.json
+CREATE TABLE t2 (
+n INT KEY,
+jfile_cols CHAR(12) NOT NULL)
+ENGINE= MYISAM;
+INSERT INTO t2 VALUES(1,'bt3.json');
+# In this table, the jfile_cols column just contains a file name
+UPDATE t2 SET jfile_cols = Json_Array_Add(Jbin_File('bt3.json', 'b'), 66) WHERE n = 1;
+SELECT JsonGet_String(jfile_cols, '*') FROM t2;
+JsonGet_String(jfile_cols, '*')
+{"a":1,"b":[44,55,66]}
+UPDATE t2 SET jfile_cols = Json_Insert_Item(jfile_cols, 77, 'b:[]') WHERE n = 1;
+SELECT JsonGet_String(jfile_cols, 'b:*') FROM t2;
+JsonGet_String(jfile_cols, 'b:*')
+[44,55,66,77]
+UPDATE t2 SET jfile_cols = Json_Insert_Item(Jbin_Insert_Item(jfile_cols, 88, 'b:') , 99, 'b:') WHERE n = 1;
+SELECT JsonGet_String(jfile_cols, '*') FROM t2;
+JsonGet_String(jfile_cols, '*')
+{"a":1,"b":[44,55,66,77,88,99]}
+DROP TABLE t1, t2;
diff --git a/storage/connect/mysql-test/connect/std_data/gloss.json b/storage/connect/mysql-test/connect/std_data/gloss.json
new file mode 100644
index 00000000000..cfe3476cd00
--- /dev/null
+++ b/storage/connect/mysql-test/connect/std_data/gloss.json
@@ -0,0 +1,22 @@
+{
+ "glossary": {
+ "title": "example glossary",
+ "GlossDiv": {
+ "title": "S",
+ "GlossList": {
+ "GlossEntry": {
+ "ID": "SGML",
+ "SortAs": "SGML",
+ "GlossTerm": "Standard Generalized Markup Language",
+ "Acronym": "SGML",
+ "Abbrev": "ISO 8879:1986",
+ "GlossDef": {
+ "para": "A meta-markup language, used to create markup languages such as DocBook.",
+ "GlossSeeAlso": ["GML", "XML"]
+ },
+ "GlossSee": "markup"
+ }
+ }
+ }
+ }
+}
diff --git a/storage/connect/mysql-test/connect/t/json.test b/storage/connect/mysql-test/connect/t/json.test
index b743071b1be..fa962d3b302 100644
--- a/storage/connect/mysql-test/connect/t/json.test
+++ b/storage/connect/mysql-test/connect/t/json.test
@@ -135,7 +135,7 @@ CREATE TABLE t1
Year int(4) FIELD_FORMAT='DATEPUB',
INDEX IX(ISBN)
)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='bib0.json' LRECL=350 OPTION_LIST='Pretty=0';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='bib0.json' LRECL=320 OPTION_LIST='Pretty=0';
SHOW INDEX FROM t1;
SELECT * FROM t1;
DESCRIBE SELECT * FROM t1 WHERE ISBN = '9782212090819';
diff --git a/storage/connect/mysql-test/connect/t/json_udf.inc b/storage/connect/mysql-test/connect/t/json_udf.inc
index de411696885..f17d59832f3 100644
--- a/storage/connect/mysql-test/connect/t/json_udf.inc
+++ b/storage/connect/mysql-test/connect/t/json_udf.inc
@@ -9,40 +9,50 @@ if (!$HA_CONNECT_SO) {
--skip Needs a dynamically built ha_connect.so
}
-CREATE FUNCTION json_array RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_array_add RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_array_add_values RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_array_delete RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_object RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_object_nonull RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_object_add RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_object_delete RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_object_list RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jsonvalue RETURNS STRING SONAME 'ha_connect';
-CREATE AGGREGATE FUNCTION json_array_grp RETURNS STRING SONAME 'ha_connect';
-CREATE AGGREGATE FUNCTION json_object_grp RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_item_merge RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_get_item RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jsonget_string RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jsonget_int RETURNS INTEGER SONAME 'ha_connect';
-CREATE FUNCTION jsonget_real RETURNS REAL SONAME 'ha_connect';
-CREATE FUNCTION jsonlocate RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_locate_all RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_file RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jfile_make RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION json_serialize RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jbin_array RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jbin_array_add_values RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jbin_array_add RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jbin_array_delete RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jbin_object RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jbin_object_nonull RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jbin_object_add RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jbin_object_delete RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jbin_object_list RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jbin_get_item RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jbin_item_merge RETURNS STRING SONAME 'ha_connect';
-CREATE FUNCTION jbin_file RETURNS STRING SONAME 'ha_connect';
+--eval CREATE FUNCTION json_array RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_array_add RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_array_add_values RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_array_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_object RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_object_nonull RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_object_key RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_object_add RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_object_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_object_list RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jsonvalue RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE AGGREGATE FUNCTION json_array_grp RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE AGGREGATE FUNCTION json_object_grp RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jsonget_string RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jsonget_int RETURNS INTEGER SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jsonget_real RETURNS REAL SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jsonlocate RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_locate_all RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_file RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jfile_make RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jsoncontains RETURNS INTEGER SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jsoncontains_path RETURNS INTEGER SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_get_item RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_set_item RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_insert_item RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_update_item RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_item_merge RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION json_serialize RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_array RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_array_add_values RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_array_add RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_array_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_object RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_object_nonull RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_object_key RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_object_add RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_object_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_object_list RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_get_item RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_item_merge RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_set_item RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_insert_item RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_update_item RETURNS STRING SONAME '$HA_CONNECT_SO';
+--eval CREATE FUNCTION jbin_file RETURNS STRING SONAME '$HA_CONNECT_SO';
--enable_query_log
diff --git a/storage/connect/mysql-test/connect/t/json_udf.test b/storage/connect/mysql-test/connect/t/json_udf.test
index d05dd28f16c..cfd1fdae258 100644
--- a/storage/connect/mysql-test/connect/t/json_udf.test
+++ b/storage/connect/mysql-test/connect/t/json_udf.test
@@ -11,50 +11,66 @@ CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=VIR BLOCK_SIZE=5;
--echo # Test UDF's with constant arguments
--echo #
--error ER_CANT_INITIALIZE_UDF
-SELECT JsonValue(56,3.1416,'foo',NULL);
+SELECT JsonValue(56, 3.1416, 'foo', NULL);
SELECT JsonValue(3.1416);
+SELECT JsonValue(-80);
SELECT JsonValue('foo');
SELECT JsonValue(9223372036854775807);
SELECT JsonValue(NULL);
SELECT JsonValue(TRUE);
SELECT JsonValue(FALSE);
SELECT JsonValue();
-SELECT JsonValue('[11,22,33]' json_) FROM t1;
+SELECT JsonValue('[11, 22, 33]' json_) FROM t1;
#
SELECT Json_Array();
-SELECT Json_Array(56,3.1416,'My name is "Foo"',NULL);
-SELECT Json_Array(Json_Array(56,3.1416,'foo'),NULL);
+SELECT Json_Array(56, 3.1416, 'My name is "Foo"', NULL);
+SELECT Json_Array(Json_Array(56, 3.1416, 'foo'), TRUE);
+#
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Array_Add(Json_Array(56, 3.1416, 'foo', NULL)) Array;
+SELECT Json_Array_Add(Json_Array(56, 3.1416, 'foo', NULL), 'One more') Array;
--error ER_CANT_INITIALIZE_UDF
-SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL)) Array;
-SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL),'One more') Array;
+SELECT Json_Array_Add(JsonValue('one value'), 'One more');
--error ER_CANT_INITIALIZE_UDF
-SELECT Json_Array_Add(JsonValue('one value'),'One more');
+SELECT Json_Array_Add('one value', 'One more');
+SELECT Json_Array_Add('one value' json_, 'One more');
--error ER_CANT_INITIALIZE_UDF
-SELECT Json_Array_Add('one value','One more');
-SELECT Json_Array_Add('one value' json_,'One more');
+SELECT Json_Array_Add(5 json_, 'One more');
SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 0);
SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 2) Array;
SELECT Json_Array_Add('[5,3,8,7,9]' json_, 4, 9);
+SELECT Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), '[2]', 33, 1);
+SELECT Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), 33, '[2]', 1);
+SELECT Json_Array_Add(Json_Array(1, 2, Json_Array(11, 22)), 33, 1, '[2]');
+#
SELECT Json_Array_Add_Values(Json_Array(56, 3.1416, 'machin', NULL), 'One more', 'Two more') Array;
SELECT Json_Array_Add_Values(Json_Array(56, 3.1416, 'machin'), 'One more', 'Two more') Array FROM t1;
SELECT Json_Array_Add_Values(Json_Array(56, 3.1416, 'machin'), n) Array FROM t1;
SELECT Json_Array_Add_Values(Json_Array(n, 3.1416, 'machin'), n) Array FROM t1;
SELECT Json_Array_Add_Values('[56]', 3.1416, 'machin') Array;
#
-SELECT Json_Array_Delete(Json_Array(56,3.1416,'My name is "Foo"',NULL),0);
-SELECT Json_Array_Delete(Json_Object(56,3.1416,'My name is Foo',NULL),2);
-SELECT Json_Array_Delete(Json_Array(56,3.1416,'My name is "Foo"',NULL),'2');
+SELECT Json_Array_Delete(Json_Array(56, 3.1416, 'My name is "Foo"', NULL), 0);
+SELECT Json_Array_Delete(Json_Object(56, 3.1416, 'My name is Foo', NULL), 2);
+SELECT Json_Array_Delete(Json_Array(56, 3.1416, 'My name is "Foo"', NULL), '2');
+SELECT Json_Array_Delete(json_array(56, 3.1416, 'My name is "Foo"', NULL), '2', 2);
#
SELECT Json_Object(56, 3.1416, 'foo', NULL);
SELECT Json_Object(56 qty, 3.1416 price, 'foo' truc, NULL garanty);
SELECT Json_Object();
SELECT Json_Object(Json_Array(56, 3.1416, 'foo'), NULL);
SELECT Json_Array(Json_Object(56 "qty", 3.1416 "price", 'foo') ,NULL);
-SELECT Json_Object_Add(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty), 'blue' color);
-SELECT Json_Object_Add(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty), 45.99 price);
-SELECT Json_Object_Delete(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty), 'truc');
-SELECT Json_Object_Delete(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty), 'chose');
-SELECT Json_Object_List(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty)) "Key List";
+SELECT Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL);
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty');
+#
+SELECT Json_Object_Add(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color);
+SELECT Json_Object_Add(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price);
+SELECT Json_Object_Add(Json_File('notexist.json'), 'cheese' item, '[1]', 1);
+#
+SELECT Json_Object_Delete(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'truc');
+SELECT Json_Object_Delete(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'chose');
+#
+SELECT Json_Object_List(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty)) "Key List";
SELECT Json_Object_List('{"qty":56, "price":3.1416, "truc":"machin", "garanty":null}') "Key List";
--echo #
@@ -93,15 +109,19 @@ CREATE TABLE t3 (
SELECT Json_Object(SERIALNO, NAME, TITLE, SALARY) FROM t3 WHERE NAME = 'MERCHANT';
SELECT DEPARTMENT, Json_Array_Grp(NAME) FROM t3 GROUP BY DEPARTMENT;
SET connect_json_grp_size=30;
+SELECT Json_Object(title, Json_Array_Grp(name) `json_names`) from t3 GROUP BY title;
SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t3 GROUP BY DEPARTMENT;
SELECT Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) FROM t3 GROUP BY DEPARTMENT;
SELECT Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES) FROM t3 GROUP BY DEPARTMENT;
SELECT Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES) FROM t3 GROUP BY DEPARTMENT, TITLE;
--error ER_CANT_INITIALIZE_UDF
SELECT Json_Object_Grp(SALARY) FROM t3;
-SELECT Json_Object_Grp(SALARY, NAME) FROM t3;
-SELECT Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES") FROM t3 GROUP BY DEPARTMENT;
+SELECT Json_Object_Grp(NAME, SALARY) FROM t3;
+SELECT Json_Object(DEPARTMENT, Json_Object_Grp(NAME, SALARY) "Json_SALARIES") FROM t3 GROUP BY DEPARTMENT;
SELECT Json_Array_Grp(NAME) FROM t3;
+#
+SELECT Json_Object_Key(name, title) FROM t3 WHERE DEPARTMENT = 318;
+SELECT Json_Object_Grp(name, title) FROM t3 WHERE DEPARTMENT = 318;
--echo #
--echo # Test value getting UDF's
@@ -127,31 +147,31 @@ SELECT department, JsonGet_String(Json_Object(department, Json_Array_Grp(salary)
SELECT JsonGet_Int(@j1, '[4]');
SELECT JsonGet_Int(@j1, '[#]');
SELECT JsonGet_Int(@j1, '[+]');
-SELECT JsonGet_Int(@j1 json_,'[3]');
-SELECT JsonGet_Int(Json_Array(45,28,36,45,89),'[3]');
-SELECT JsonGet_Int(Json_Array(45,28,36,45,89),'["+"]');
-SELECT JsonGet_Int(Json_Array(45,28,36,45,89),'[+]');
-SELECT JsonGet_Int(Json_Array(json_array(45,28),json_array(36,45,89)),'[1]:[0]');
-SELECT JsonGet_Int(Json_Array(json_array(45,28),json_array(36,45,89)),'[0]:[1]');
-SELECT JsonGet_Int(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'qty');
-SELECT JsonGet_Int(@j2 json_,'price');
-SELECT JsonGet_Int(@j2,'qty');
-SELECT JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose');
-SELECT JsonGet_Int(JsonGet_String(Json_Array(Json_Array(45,28),Json_Array(36,45,89)),'[1]:*'),'[+]') sum;
-SELECT department, JsonGet_Int(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"),'salaries:[+]') Sumsal FROM t3 GROUP BY department;
+SELECT JsonGet_Int(@j1 json_, '[3]');
+SELECT JsonGet_Int(Json_Array(45,28,36,45,89), '[3]');
+SELECT JsonGet_Int(Json_Array(45,28,36,45,89), '["+"]');
+SELECT JsonGet_Int(Json_Array(45,28,36,45,89), '[+]');
+SELECT JsonGet_Int(Json_Array(json_array(45,28), json_array(36,45,89)), '[1]:[0]');
+SELECT JsonGet_Int(Json_Array(json_array(45,28), json_array(36,45,89)), '[0]:[1]');
+SELECT JsonGet_Int(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'qty');
+SELECT JsonGet_Int(@j2 json_, 'price');
+SELECT JsonGet_Int(@j2, 'qty');
+SELECT JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'chose');
+SELECT JsonGet_Int(JsonGet_String(Json_Array(Json_Array(45,28),Json_Array(36,45,89)), '[1]:*'), '[+]') sum;
+SELECT department, JsonGet_Int(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"), 'salaries:[+]') Sumsal FROM t3 GROUP BY department;
#
SELECT JsonGet_Real(@j1, '[2]');
-SELECT JsonGet_Real(@j1 json_,'[3]',2);
-SELECT JsonGet_Real(Json_Array(45,28,36,45,89),'[3]');
-SELECT JsonGet_Real(Json_Array(45,28,36,45,89),'["+"]');
-SELECT JsonGet_Real(Json_Array(45,28,36,45,89),'[+]');
-SELECT JsonGet_Real(Json_Array(45,28,36,45,89),'[!]');
-SELECT JsonGet_Real(Json_Array(json_array(45,28),json_array(36,45,89)),'[1]:[0]');
-SELECT JsonGet_Real(Json_Object(56 qty,3.1416 price,'machin' truc, NULL garanty),'price');
-SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}' json_,'qty');
-SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','price');
-SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','price', 4);
-SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose');
+SELECT JsonGet_Real(@j1 json_, '[3]', 2);
+SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '[3]');
+SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '["+"]');
+SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '[+]');
+SELECT JsonGet_Real(Json_Array(45,28,36,45,89), '[!]');
+SELECT JsonGet_Real(Json_Array(json_array(45,28), json_array(36,45,89)), '[1]:[0]');
+SELECT JsonGet_Real(Json_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'price');
+SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}' json_, 'qty');
+SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'price');
+SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'price', 4);
+SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}', 'chose');
SELECT department, JsonGet_Real(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"),'salaries:[+]') Sumsal FROM t3 GROUP BY department;
--echo #
@@ -164,10 +184,10 @@ SELECT
JsonGet_Int(Json_Array(45,28,36,45,89), '[+]') "Sum",
JsonGet_Real(Json_Array(45,28,36,45,89), '[!]', 2) "Avg";
SELECT
- JsonGet_String('{"qty":7,"price":29.50,"garanty":null}','price') "String",
- JsonGet_Int('{"qty":7,"price":29.50,"garanty":null}','price') "Int",
- JsonGet_Real('{"qty":7,"price":29.50,"garanty":null}','price') "Real";
-SELECT JsonGet_Real('{"qty":7,"price":29.50,"garanty":null}','price',3) "Real";
+ JsonGet_String('{"qty":7,"price":29.50,"garanty":null}', 'price') "String",
+ JsonGet_Int('{"qty":7,"price":29.50,"garanty":null}', 'price') "Int",
+ JsonGet_Real('{"qty":7,"price":29.50,"garanty":null}', 'price') "Real";
+SELECT JsonGet_Real('{"qty":7,"price":29.50,"garanty":null}', 'price', 3) "Real";
--echo #
--echo # Testing Locate
@@ -206,7 +226,7 @@ SELECT Json_Locate_All('test/biblio.json' jfile_, 'Knab');
--echo #
--echo # Testing json files
--echo #
-select Jfile_Make('[{"_id":5,"type":"food","item":"beer","taste":"light","price":5.65,"ratings":[5,8,9]},
+SELECT Jfile_Make('[{"_id":5,"type":"food","item":"beer","taste":"light","price":5.65,"ratings":[5,8,9]},
{"_id":6,"type":"car","item":"roadster","mileage":56000,"ratings":[6,9]},
{"_id":7,"type":"food","item":"meat","origin":"argentina","ratings":[2,4]},
{"_id":8,"type":"furniture","item":"table","size":{"W":60,"L":80,"H":40},"ratings":[5,8,7]}]', 'test/fx.json', 0) AS NewFile;
diff --git a/storage/connect/mysql-test/connect/t/json_udf2.inc b/storage/connect/mysql-test/connect/t/json_udf2.inc
index e5609bfd1f8..f62b178b003 100644
--- a/storage/connect/mysql-test/connect/t/json_udf2.inc
+++ b/storage/connect/mysql-test/connect/t/json_udf2.inc
@@ -1,38 +1,48 @@
--disable_query_log
-DROP FUNCTION jsonvalue;
DROP FUNCTION json_array;
DROP FUNCTION json_array_add;
DROP FUNCTION json_array_add_values;
DROP FUNCTION json_array_delete;
DROP FUNCTION json_object;
DROP FUNCTION json_object_nonull;
+DROP FUNCTION json_object_key;
DROP FUNCTION json_object_add;
DROP FUNCTION json_object_delete;
DROP FUNCTION json_object_list;
+DROP FUNCTION jsonvalue;
DROP FUNCTION json_array_grp;
DROP FUNCTION json_object_grp;
-DROP FUNCTION json_item_merge;
-DROP FUNCTION json_get_item;
-DROP FUNCTION JsonGet_string;
-DROP FUNCTION JsonGet_int;
-DROP FUNCTION JsonGet_real;
+DROP FUNCTION jsonget_string;
+DROP FUNCTION jsonget_int;
+DROP FUNCTION jsonget_real;
DROP FUNCTION jsonlocate;
DROP FUNCTION json_locate_all;
DROP FUNCTION json_file;
-DROP FUNCTION json_serialize;
DROP FUNCTION jfile_make;
+DROP FUNCTION json_get_item;
+DROP FUNCTION json_item_merge;
+DROP FUNCTION jsoncontains;
+DROP FUNCTION jsoncontains_path;
+DROP FUNCTION json_set_item;
+DROP FUNCTION json_insert_item;
+DROP FUNCTION json_update_item;
+DROP FUNCTION json_serialize;
DROP FUNCTION jbin_array;
DROP FUNCTION jbin_array_add_values;
DROP FUNCTION jbin_array_add;
DROP FUNCTION jbin_array_delete;
DROP FUNCTION jbin_object;
DROP FUNCTION jbin_object_nonull;
+DROP FUNCTION jbin_object_key;
DROP FUNCTION jbin_object_add;
DROP FUNCTION jbin_object_delete;
DROP FUNCTION jbin_object_list;
DROP FUNCTION jbin_get_item;
DROP FUNCTION jbin_item_merge;
+DROP FUNCTION jbin_set_item;
+DROP FUNCTION jbin_insert_item;
+DROP FUNCTION jbin_update_item;
DROP FUNCTION jbin_file;
--enable_query_log
diff --git a/storage/connect/mysql-test/connect/t/json_udf_bin.test b/storage/connect/mysql-test/connect/t/json_udf_bin.test
new file mode 100644
index 00000000000..e4ee422c263
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/json_udf_bin.test
@@ -0,0 +1,212 @@
+--source json_udf.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--copy_file $MTR_SUITE_DIR/std_data/gloss.json $MYSQLD_DATADIR/gloss.json
+
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=VIR BLOCK_SIZE=3;
+
+--echo #
+--echo # Test Jbin UDF's
+--echo #
+SELECT Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), n) from t1;
+SELECT Json_Array_Add(Jbin_Array(n, 3.1416, 'My name is "Foo"', NULL), n) from t1;
+SELECT Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), Jbin_Array('a','b',n)) from t1;
+SELECT Json_Array_Add(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), JsonGet_String(Jbin_Array('a','b','c'), '[1]'));
+SELECT Json_Array_Delete(Jbin_Array_Add_Values(Jbin_Array(56, 3.1416, 'My name is "Foo"', NULL), "One more", 2), 4);
+SELECT Json_Array_Delete(Jbin_Array(56, Jbin_Array(3.1416, 'My name is "Foo"'), NULL), '[1]', 1);
+SELECT Json_Array_Delete(Jbin_Array(56, Jbin_Array(3.1416, 'My name is "Foo"'), TRUE), 1, '[1]');
+SELECT Json_Array(1, TRUE, 0, FALSE);
+SELECT Json_Serialize(Jbin_Array(TRUE, FALSE));
+#
+SELECT Json_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL);
+SELECT Json_Serialize(Jbin_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty', NULL));
+--error ER_CANT_INITIALIZE_UDF
+SELECT Jbin_Object_Key('qty', 56, 'price', 3.1416, 'truc', 'machin', 'garanty');
+SELECT Json_Object_Add(Jbin_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color);
+SELECT Json_Object_Add(Jbin_Object(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price);
+SELECT Json_Object_Add(Jbin_Object_Nonull(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 'blue' color);
+SELECT Json_Object_Add(Jbin_Object_Nonull(56 qty, 3.1416 price, 'machin' truc, NULL garanty), 45.99 price);
+
+--echo #
+--echo # Test Jbin file UDF's
+--echo #
+SELECT Json_Serialize(Jbin_File('gloss.json'));
+SELECT JsonLocate(Jbin_File('gloss.json'),'XML');
+#
+SELECT Json_Object_Key('first', 'foo', 'second', Jbin_Array('a', 33));
+SELECT Json_Get_Item(Json_Array('a','b','c'), '[1]');
+SELECT Json_Get_Item(Json_Object('foo' AS "first", Json_Array('a', 33) AS "json_second"), 'second') AS "item";
+SELECT Json_Get_Item(Jbin_Object('foo' first, Jbin_Array('a', 33) jbin_second), 'second:*') item;
+SELECT Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv');
+SELECT Json_Serialize(Jbin_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv'));
+SELECT Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:*');
+SELECT JsonGet_String(Json_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso') lang;
+SELECT Json_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso') "See also";
+SELECT Json_Serialize(Jbin_Get_Item(Jbin_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso')) "See also";
+SELECT JsonGet_String(Json_Get_Item(Json_File('gloss.json'),'glossary:GlossDiv:GlossList:GlossEntry:GlossDef:GlossSeeAlso'),'[0]') lang;
+
+--echo #
+--echo # Test Item Get/Set/Insert/Update UDF's
+--echo #
+SELECT Json_Get_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), '[]');
+SELECT Json_Get_Item(Jbin_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), '[1]');
+SELECT Json_Get_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), '[1]');
+#
+SELECT Json_Set_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)));
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 'foo');
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq');
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 7, '[1]');
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 7, '[1]');
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Json_Array(7, 8, 9), '[1]');
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[2]');
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[2]:*');
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 3.1416, 'foo');
+SELECT Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 'toto', '[1]:[2]');
+SELECT Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 300, '[2]:nxt:total:[]');
+SELECT Json_Set_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 300, '[2]:nxt:total:[]');
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), Jbin_Array(7, 8, 9), '[1]', 5, '[2]:cinq', 10, '[1]:[]');
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 44, '[2]:quatre');
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, 'truc');
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '');
+SELECT Json_Set_Item(Jbin_Array(1, 2, Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '*');
+SELECT Json_Serialize(Jbin_Set_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq'));
+#
+SELECT Json_Insert_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq');
+SELECT Json_Update_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq');
+SELECT Json_Insert_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 44, '[2]:quatre');
+SELECT Json_Update_Item(Jbin_Array(1, Jbin_Array(7, 8, 9), Jbin_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[]', 44, '[2]:quatre');
+SELECT Json_Insert_Item(Json_Array(1, Json_Array(7, 8, 9), Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[1]', 300, '[2]:nxt:total:[]');
+SELECT Json_Update_Item(Json_Array(1, Json_Array(7, 8, 9), Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[2]:cinq', 10, '[1]:[1]', 300, '[2]:nxt:total:[]');
+SELECT Json_Insert_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[]');
+SELECT Json_Update_Item(Json_Array(1, 2, Json_Object_Key('trois', 3, 'quatre', 4)), 5, '[]');
+
+--echo #
+--echo # Test merging items UDF's
+--echo #
+SELECT Json_Item_Merge(Jbin_Array('a','b','c'), Jbin_Array('d','e','f'));
+SELECT Json_Item_Merge(Json_Array('a','b','c'), Json_Array('d','e','f')) AS "Result";
+SELECT Json_Array_Add(Jbin_Item_Merge(Jbin_Array('a','b','c'), Jbin_Array('d','e','f')), 'and', 3);
+SELECT Json_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "d",5 "e",6 "f"));
+SELECT Json_Item_Merge(Jbin_Object(1 "a",2 "b",2 "c"), Jbin_Array('d','e','f'));
+SELECT Json_Object_Add(Jbin_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "d",5 "e",6 "f")), 'x' AS "and");
+SELECT Json_Item_Merge(Jbin_Object(1 "a",2 "b",3 "c"), Jbin_Object(4 "a",5 "e",6 "f"));
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Item_Merge('foo', Json_Array('d','e','f'));
+
+--echo #
+--echo # Test making file UDF's
+--echo #
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+SELECT Json_File('bt1.json');
+SELECT Json_File(Jfile_Make(Jbin_File('bt1.json'), 0));
+SELECT Json_File(Jfile_Make(Jbin_File('bt1.json'), 1));
+SELECT Json_File(Jfile_Make(Jbin_File('bt1.json'), 2));
+SELECT Json_File('bt1.json', 0);
+SELECT Json_File('bt1.json', 1);
+SELECT Json_File('bt1.json', 2);
+SELECT Json_Serialize(Jbin_Array('a','b','c'));
+SELECT Json_Serialize(Jbin_Array_Add(Jbin_File('not_exist.json'), 'd'));
+--echo # This does not modify the file
+SELECT Json_Serialize(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'));
+SELECT Json_File('bt1.json', 2);
+--echo # This does modify the file
+SELECT Json_Array_Add(Jbin_File('bt1.json'), 'd');
+SELECT Json_File('bt1.json', 2);
+--echo # Back to the original file
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+SELECT Json_Object(Jbin_Array_Add(Jbin_Array('a','b','c'), 'd') "Jbin_foo") AS "Result";
+SELECT Json_Object(Jbin_Array_Add(Jbin_File('bt1.json'), 'd')) AS "Result";
+SELECT Json_Object(Jbin_Array_Add(Jbin_File('bt1.json'), 'd') "Jbin_bt1") AS "Result";
+--echo # This does modify the file
+SELECT Json_Object(Json_Array_Add(Jbin_File('bt1.json'), 'd') "Jfile_bt1") AS "Result";
+SELECT Json_File('bt1.json');
+SELECT Json_File(Json_Array_Delete(Jbin_File('bt1.json'), 3), 2);
+SELECT Json_Object(Jbin_Array_Add(Jbin_File('bt1.json'), 'd') "Jbin_bt1", n "t1") AS "Result" from t1;
+SELECT Json_File(Json_Array_Add(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'), 'e')) AS "Result";
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+SELECT Json_File(Json_Array_Add(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'), 'e')) AS "Result" from t1;
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+SELECT Json_Array_Add(Jbin_Array_Add(Jbin_File('bt1.json'), 'd'), n) AS "Result" from t1;
+--echo # Show modified file
+SELECT Json_File('bt1.json');
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+SELECT Json_Array_Add(Jbin_File('bt1.json'), n) AS "Result" from t1;
+--echo # Show modified file
+SELECT Json_File('bt1.json');
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+SELECT Json_File(Jbin_Item_Merge(Jbin_File('bt1.json'), Jbin_Array('d','e','f')));
+SELECT Json_File(Json_Item_Merge(Jbin_File('bt1.json'), Jbin_Array('d','e','f')));
+SELECT Jfile_Make(Jbin_Array('a','b','c'), 'bt1.json');
+--echo # Test DELETE from file
+SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 1)) AS "Result";
+SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 2) "Jbin_bt1") AS "Result";
+SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 0) "Jbin_bt1", n "t1") AS "Result" from t1;
+SELECT Json_Object(Jbin_Array_Delete(Jbin_File('bt1.json'), 3 - n) "Jbin_bt1") AS "Result" from t1;
+SELECT Json_Object(Json_Array_Delete(Jbin_File('bt1.json'), 3 - n) "Jbin_bt1") AS "Result" from t1;
+--echo # Show modified file
+SELECT Json_File('bt1.json');
+--echo # Object file
+SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
+SELECT Json_File('bt2.json', 0);
+SELECT Json_File('bt2.json');
+SELECT Json_Serialize(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"));
+--echo # First query (file not modified)
+SELECT Json_Object(Jbin_Object_Add(Jbin_File('bt2.json'), 4 AS "d") AS "Jbin_new") AS "Result";
+--echo # First query (file modified)
+SELECT Json_Object(Json_Object_Add(Jbin_File('bt2.json'), 4 AS "d") AS "Jfile_new") AS "Result";
+SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
+SELECT Json_Object(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d") "Jbin_new", n "t1") AS "Result" from t1;
+SELECT Json_File(Json_Object_Add(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"), 5 "e")) AS "Result";
+SELECT Json_Object_Add(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"), 5 "e") AS "Result" from t1;
+SELECT Json_Object_Add(Jbin_Object_Add(Jbin_File('bt2.json'), 4 "d"), n "n") AS "Result" from t1;
+SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
+SELECT Json_Object_Add(Jbin_File('bt2.json'), n) AS "Result" from t1;
+SELECT Json_File('bt2.json');
+SELECT Jfile_Make(Jbin_Object(1 "a", 2 "b", 3 "c"), 'bt2.json', 0);
+SELECT Json_Serialize(Jbin_Item_Merge(Jbin_File('bt2.json'), Jbin_Object(4 "d",5 "e",6 "f"))) AS "Result";
+SELECT Json_File(Json_Item_Merge(Jbin_File('bt2.json'), Jbin_Object(4 "d",5 "e",6 "f"))) AS "Result";
+SELECT Json_Item_Merge(Json_Object(1 "a", 2 "b", 3 "c"), Json_Object(4 "d",5 "b",6 "f")) AS "Result";
+#
+SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'b')) AS "Result";
+SELECT Json_Object(Jbin_Object_Delete(Jbin_File('bt2.json'), 'c') "Jbin_bt1") AS "Result";
+SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'c') "Jbin_bt1") AS "Result";
+SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'c') "Jfile_bt1") AS "Result";
+SELECT Json_Object(Json_Object_Delete(Jbin_File('bt2.json'), 'a') "Jbin_bt1", n "t1") AS "Result" from t1;
+#
+SELECT Json_Serialize(Jbin_Object_List(Jbin_File('bt2.json'))) "Key list";
+
+#
+# Test documentation examples
+#
+SELECT Jfile_Make('{"a":1, "b":[44, 55]}' json_, 'bt3.json', 0);
+SELECT Json_Array_Add(Json_File('bt3.json', 'b'), 66);
+SELECT Json_Array_Add(Json_File('bt3.json'), 66, 'b');
+SELECT Json_Array_Add(Jbin_File('bt3.json', 'b'), 66);
+SELECT Json_File('bt3.json', 3);
+SELECT Jfile_Make('{"a":1, "b":[44, 55]}' json_, 'bt3.json', 0);
+#
+CREATE TABLE t2 (
+ n INT KEY,
+ jfile_cols CHAR(12) NOT NULL)
+ENGINE= MYISAM;
+INSERT INTO t2 VALUES(1,'bt3.json');
+--echo # In this table, the jfile_cols column just contains a file name
+UPDATE t2 SET jfile_cols = Json_Array_Add(Jbin_File('bt3.json', 'b'), 66) WHERE n = 1;
+SELECT JsonGet_String(jfile_cols, '*') FROM t2;
+UPDATE t2 SET jfile_cols = Json_Insert_Item(jfile_cols, 77, 'b:[]') WHERE n = 1;
+SELECT JsonGet_String(jfile_cols, 'b:*') FROM t2;
+UPDATE t2 SET jfile_cols = Json_Insert_Item(Jbin_Insert_Item(jfile_cols, 88, 'b:') , 99, 'b:') WHERE n = 1;
+SELECT JsonGet_String(jfile_cols, '*') FROM t2;
+
+DROP TABLE t1, t2;
+
+#
+# Clean up
+#
+--source json_udf2.inc
+--remove_file $MYSQLD_DATADIR/gloss.json
+--remove_file $MYSQLD_DATADIR/bt1.json
+--remove_file $MYSQLD_DATADIR/bt2.json
+--remove_file $MYSQLD_DATADIR/bt3.json
diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp
index 9e236da2d93..1ec1108c639 100644
--- a/storage/connect/plgdbutl.cpp
+++ b/storage/connect/plgdbutl.cpp
@@ -679,7 +679,8 @@ void PlugConvertConstant(PGLOBAL g, void* & value, short& type)
/* non quoted blanks are not included in the output format. */
/***********************************************************************/
PDTP MakeDateFormat(PGLOBAL g, PSZ dfmt, bool in, bool out, int flag)
- {
+{
+ int rc;
PDTP pdp = (PDTP)PlugSubAlloc(g, NULL, sizeof(DATPAR));
if (trace)
@@ -708,7 +709,7 @@ PDTP MakeDateFormat(PGLOBAL g, PSZ dfmt, bool in, bool out, int flag)
pthread_mutex_lock(&parmut);
#endif // !__WIN__
#endif // THREAD
- /*int rc =*/ fmdflex(pdp);
+ rc = fmdflex(pdp);
#if defined(THREAD)
#if defined(__WIN__)
LeaveCriticalSection((LPCRITICAL_SECTION)&parsec);
@@ -718,9 +719,10 @@ PDTP MakeDateFormat(PGLOBAL g, PSZ dfmt, bool in, bool out, int flag)
#endif // THREAD
if (trace)
- htrc("Done: in=%s out=%s\n", SVP(pdp->InFmt), SVP(pdp->OutFmt));
+ htrc("Done: in=%s out=%s rc=%d\n", SVP(pdp->InFmt), SVP(pdp->OutFmt), rc);
+
return pdp;
- } // end of MakeDateFormat
+} // end of MakeDateFormat
/***********************************************************************/
/* Extract the date from a formatted string according to format. */
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index 8f7b9508e60..17260836371 100644
--- a/storage/connect/tabjson.cpp
+++ b/storage/connect/tabjson.cpp
@@ -38,6 +38,7 @@
/***********************************************************************/
#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 function. */
@@ -411,9 +412,23 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
// Txfp must be set for TDBDOS
tdbp = new(g) TDBJSN(this, txfp);
- } else {
+
+#if USE_G
+ // Allocate the parse work memory
+ PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
+ memset(G, 0, sizeof(GLOBAL));
+ G->Sarea_Size = Lrecl * 10;
+ G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size);
+ PlugSubSet(G, G->Sarea, G->Sarea_Size);
+ G->jump_level = -1;
+ ((TDBJSN*)tdbp)->G = G;
+#else
+ ((TDBJSN*)tdbp)->G = g;
+#endif
+ } else {
txfp = new(g) MAPFAM(this);
tdbp = new(g) TDBJSON(this, txfp);
+ ((TDBJSON*)tdbp)->G = g;
} // endif Pretty
if (Multiple)
@@ -462,6 +477,7 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
{
+ G = NULL;
Top = tdbp->Top;
Row = tdbp->Row;
Val = tdbp->Val;
@@ -485,6 +501,7 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
// Used for update
PTDB TDBJSN::CopyOne(PTABS t)
{
+ G = NULL;
PTDB tp;
PJCOL cp1, cp2;
PGLOBAL g = t->G;
@@ -578,7 +595,7 @@ PJSON TDBJSN::FindRow(PGLOBAL g)
} // end of FindRow
/***********************************************************************/
-/* OpenDB: Data Base open routine for JSN access method. */
+/* OpenDB: Data Base open routine for JSN access method. */
/***********************************************************************/
bool TDBJSN::OpenDB(PGLOBAL g)
{
@@ -603,7 +620,7 @@ bool TDBJSN::OpenDB(PGLOBAL g)
return true;
} // endswitch Jmode
- } // endif Use
+ } // endif Use
return TDBDOS::OpenDB(g);
} // end of OpenDB
@@ -655,19 +672,31 @@ int TDBJSN::ReadDB(PGLOBAL g)
NextSame = 0;
M++;
return RC_OK;
- } else if ((rc = TDBDOS::ReadDB(g)) == RC_OK)
- if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) {
- // Deferred reading failed
- } else if (!(Row = ParseJson(g, To_Line,
- strlen(To_Line), &Pretty, &Comma))) {
- rc = (Pretty == 1 && !strcmp(To_Line, "]")) ? RC_EF : RC_FX;
- } else {
- Row = FindRow(g);
- SameRow = 0;
- Fpos++;
- M = 1;
- rc = RC_OK;
- } // endif's
+ } else if ((rc = TDBDOS::ReadDB(g)) == RC_OK) {
+ if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK))
+ // 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);
+ SameRow = 0;
+ Fpos++;
+ 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;
+
+ } // endif ReadDB
return rc;
} // end of ReadDB
@@ -744,7 +773,7 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
if (MakeTopTree(g, Row))
return true;
- if ((s = Serialize(g, Top, NULL, Pretty))) {
+ if ((s = Serialize(G, Top, NULL, Pretty))) {
if (Comma)
strcat(s, ",");
@@ -761,15 +790,33 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
} // end of PrepareWriting
-/* ---------------------------- JSONCOL ------------------------------ */
+ /***********************************************************************/
+ /* WriteDB: Data Base write routine for DOS access method. */
+ /***********************************************************************/
+ int TDBJSN::WriteDB(PGLOBAL g)
+{
+ int rc = TDBDOS::WriteDB(g);
+
+#if USE_G
+ if (rc == RC_FX)
+ strcpy(g->Message, G->Message);
+
+ PlugSubSet(G, G->Sarea, G->Sarea_Size);
+#endif
+ Row->Clear();
+ return rc;
+} // end of WriteDB
+
+ /* ---------------------------- JSONCOL ------------------------------ */
/***********************************************************************/
/* JSONCOL public constructor. */
/***********************************************************************/
JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
: DOSCOL(g, cdp, tdbp, cprec, i, "DOS")
- {
+{
Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp);
+ G = Tjp->G;
Jpath = cdp->GetFmt();
MulVal = NULL;
Nodes = NULL;
@@ -777,14 +824,15 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
Xnod = -1;
Xpd = false;
Parsed = false;
- } // end of JSONCOL constructor
+} // end of JSONCOL constructor
/***********************************************************************/
/* JSONCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
- {
+{
+ G = col1->G;
Tjp = col1->Tjp;
Jpath = col1->Jpath;
MulVal = col1->MulVal;
@@ -793,7 +841,7 @@ JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
Xnod = col1->Xnod;
Xpd = col1->Xpd;
Parsed = col1->Parsed;
- } // end of JSONCOL copy constructor
+} // end of JSONCOL copy constructor
/***********************************************************************/
/* SetBuffer: prepare a column block for write operation. */
@@ -808,6 +856,7 @@ bool JSONCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
return true;
Tjp = (TDBJSN*)To_Tdb;
+ G = Tjp->G;
return false;
} // end of SetBuffer
@@ -1103,15 +1152,15 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
Value->SetValue(row->GetType() == TYPE_JAR ? row->size() : 1);
return(Value);
} else if (Nodes[i].Op == OP_XX) {
- return MakeJson(g, row);
+ return MakeJson(G, row);
} else switch (row->GetType()) {
case TYPE_JOB:
if (!Nodes[i].Key) {
- // Expected Array was not there
+ // Expected Array was not there, wrap the value
if (i < Nod-1)
continue;
else
- val = new(g) JVALUE(row);
+ val = new(G) JVALUE(row);
} else
val = ((PJOB)row)->GetValue(Nodes[i].Key);
@@ -1128,11 +1177,11 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
else
return CalculateArray(g, arp, i);
- } else if (i < Nod-1) {
- strcpy(g->Message, "Unexpected array");
- val = NULL; // Not an expected array
- } else
- val = arp->GetValue(0);
+ } else {
+ // Unexpected array, unwrap it as [0]
+ val = arp->GetValue(0);
+ i--;
+ } // endif's
break;
case TYPE_JVAL:
@@ -1275,30 +1324,31 @@ PJSON JSONCOL::GetRow(PGLOBAL g)
PJAR arp;
PJSON nwr, row = Tjp->Row;
- for (int i = 0; i < Nod-1 && row; i++) {
- if (Nodes[i+1].Op == OP_XX)
+ for (int i = 0; i < Nod && row; i++) {
+ if (Nodes[i+1].Op == OP_XX)
break;
else switch (row->GetType()) {
case TYPE_JOB:
if (!Nodes[i].Key)
- // Expected Array was not there
+ // Expected Array was not there, wrap the value
continue;
val = ((PJOB)row)->GetValue(Nodes[i].Key);
break;
case TYPE_JAR:
- if (!Nodes[i].Key) {
- arp = (PJAR)row;
+ arp = (PJAR)row;
+ if (!Nodes[i].Key) {
if (Nodes[i].Op == OP_EQ)
val = arp->GetValue(Nodes[i].Rank);
else
val = arp->GetValue(Nodes[i].Rx);
} else {
- strcpy(g->Message, "Unexpected array");
- val = NULL; // Not an expected array
- } // endif Nodes
+ // Unexpected array, unwrap it as [0]
+ val = arp->GetValue(0);
+ i--;
+ } // endif Nodes
break;
case TYPE_JVAL:
@@ -1318,15 +1368,15 @@ PJSON JSONCOL::GetRow(PGLOBAL g)
break;
else if (!Nodes[i].Key)
// Construct intermediate array
- nwr = new(g) JARRAY;
+ nwr = new(G) JARRAY;
else
- nwr = new(g) JOBJECT;
+ nwr = new(G) JOBJECT;
if (row->GetType() == TYPE_JOB) {
- ((PJOB)row)->SetValue(g, new(g) JVALUE(nwr), Nodes[i-1].Key);
+ ((PJOB)row)->SetValue(G, new(G) JVALUE(nwr), Nodes[i-1].Key);
} else if (row->GetType() == TYPE_JAR) {
- ((PJAR)row)->AddValue(g, new(g) JVALUE(nwr));
- ((PJAR)row)->InitArray(g);
+ ((PJAR)row)->AddValue(G, new(G) JVALUE(nwr));
+ ((PJAR)row)->InitArray(G);
} else {
strcpy(g->Message, "Wrong type when writing new row");
nwr = NULL;
@@ -1370,7 +1420,6 @@ void JSONCOL::WriteColumn(PGLOBAL g)
PJAR arp = NULL;
PJVAL jvp = NULL;
PJSON jsp, row = GetRow(g);
- JTYP type = row->GetType();
switch (row->GetType()) {
case TYPE_JOB: objp = (PJOB)row; break;
@@ -1384,21 +1433,21 @@ void JSONCOL::WriteColumn(PGLOBAL g)
if (Nodes[Nod-1].Op == OP_XX) {
s = Value->GetCharValue();
- if (!(jsp = ParseJson(g, s, (int)strlen(s)))) {
+ if (!(jsp = ParseJson(G, s, (int)strlen(s)))) {
strcpy(g->Message, s);
longjmp(g->jumper[g->jump_level], 666);
} // endif jsp
if (arp) {
if (Nod > 1 && Nodes[Nod-2].Op == OP_EQ)
- arp->SetValue(g, new(g) JVALUE(jsp), Nodes[Nod-2].Rank);
+ arp->SetValue(G, new(G) JVALUE(jsp), Nodes[Nod-2].Rank);
else
- arp->AddValue(g, new(g) JVALUE(jsp));
+ arp->AddValue(G, new(G) JVALUE(jsp));
- arp->InitArray(g);
+ arp->InitArray(G);
} else if (objp) {
if (Nod > 1 && Nodes[Nod-2].Key)
- objp->SetValue(g, new(g) JVALUE(jsp), Nodes[Nod-2].Key);
+ objp->SetValue(G, new(G) JVALUE(jsp), Nodes[Nod-2].Key);
} else if (jvp)
jvp->SetValue(jsp);
@@ -1409,17 +1458,19 @@ void JSONCOL::WriteColumn(PGLOBAL g)
// Passthru
case TYPE_DATE:
case TYPE_INT:
- case TYPE_DOUBLE:
+ case TYPE_SHORT:
+ case TYPE_BIGINT:
+ case TYPE_DOUBLE:
if (arp) {
if (Nodes[Nod-1].Op == OP_EQ)
- arp->SetValue(g, new(g) JVALUE(g, Value), Nodes[Nod-1].Rank);
+ arp->SetValue(G, new(G) JVALUE(G, Value), Nodes[Nod-1].Rank);
else
- arp->AddValue(g, new(g) JVALUE(g, Value));
+ arp->AddValue(G, new(G) JVALUE(G, Value));
- arp->InitArray(g);
+ arp->InitArray(G);
} else if (objp) {
if (Nodes[Nod-1].Key)
- objp->SetValue(g, new(g) JVALUE(g, Value), Nodes[Nod-1].Key);
+ objp->SetValue(G, new(G) JVALUE(G, Value), Nodes[Nod-1].Key);
} else if (jvp)
jvp->SetValue(Value);
@@ -1835,8 +1886,7 @@ void TDBJSON::CloseDB(PGLOBAL g)
return;
// Save the modified document
- char filename[_MAX_PATH];
- PSZ msg;
+ char filename[_MAX_PATH];
Doc->InitArray(g);
@@ -1844,8 +1894,8 @@ void TDBJSON::CloseDB(PGLOBAL g)
PlugSetPath(filename, ((PJDEF)To_Def)->Fn, GetPath());
// Serialize the modified table
- if ((msg = Serialize(g, Top, filename, Pretty)))
- puts(msg);
+ if (!Serialize(g, Top, filename, Pretty))
+ puts(g->Message);
} // end of CloseDB
diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h
index 4505d30a21c..f7cb74c3c4d 100644
--- a/storage/connect/tabjson.h
+++ b/storage/connect/tabjson.h
@@ -68,7 +68,8 @@ class JSONDEF : public DOSDEF { /* Table description */
/***********************************************************************/
class TDBJSN : public TDBDOS {
friend class JSONCOL;
- public:
+ friend class JSONDEF;
+public:
// Constructor
TDBJSN(PJDEF tdp, PTXF txfp);
TDBJSN(TDBJSN *tdbp);
@@ -90,32 +91,34 @@ class TDBJSN : public TDBDOS {
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
- virtual bool PrepareWriting(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
+ virtual bool PrepareWriting(PGLOBAL g);
+ virtual int WriteDB(PGLOBAL g);
protected:
PJSON FindRow(PGLOBAL g);
int MakeTopTree(PGLOBAL g, PJSON jsp);
// Members
- PJSON Top; // The top JSON tree
- PJSON Row; // The current row
- PJSON Val; // The value of the current row
- PJCOL Colp; // The multiple column
- JMODE Jmode; // MODE_OBJECT by default
- char *Objname; // The table object name
- char *Xcol; // Name of expandable column
- int Fpos; // The current row index
- int N; // The current Rownum
- int M; // Index of multiple value
- int Limit; // Limit of multiple values
- int Pretty; // Depends on file structure
- int NextSame; // Same next row
- int SameRow; // Same row nb
- int Xval; // Index of expandable array
- int B; // Array index base
- bool Strict; // Strict syntax checking
- bool Comma; // Row has final comma
+ PGLOBAL G; // Support of parse memory
+ PJSON Top; // The top JSON tree
+ PJSON Row; // The current row
+ PJSON Val; // The value of the current row
+ PJCOL Colp; // The multiple column
+ JMODE Jmode; // MODE_OBJECT by default
+ char *Objname; // The table object name
+ char *Xcol; // Name of expandable column
+ int Fpos; // The current row index
+ int N; // The current Rownum
+ int M; // Index of multiple value
+ int Limit; // Limit of multiple values
+ int Pretty; // Depends on file structure
+ int NextSame; // Same next row
+ int SameRow; // Same row nb
+ int Xval; // Index of expandable array
+ int B; // Array index base
+ bool Strict; // Strict syntax checking
+ bool Comma; // Row has final comma
}; // end of class TDBJSN
/* -------------------------- JSONCOL class -------------------------- */
@@ -154,7 +157,8 @@ class JSONCOL : public DOSCOL {
JSONCOL(void) {}
// Members
- TDBJSN *Tjp; // To the JSN table block
+ PGLOBAL G; // Support of parse memory
+ TDBJSN *Tjp; // To the JSN table block
PVAL MulVal; // To value used by multiple column
char *Jpath; // The json path
JNODE *Nodes; // The intermediate objects
@@ -170,7 +174,8 @@ class JSONCOL : public DOSCOL {
/* This is the JSON Access Method class declaration. */
/***********************************************************************/
class TDBJSON : public TDBJSN {
- friend class JSONCOL;
+ friend class JSONDEF;
+ friend class JSONCOL;
public:
// Constructor
TDBJSON(PJDEF tdp, PTXF txfp);
diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp
index 9c47829d5bc..57d204a4286 100644
--- a/storage/connect/tabxml.cpp
+++ b/storage/connect/tabxml.cpp
@@ -60,7 +60,7 @@ extern "C" char version[];
#endif // !__WIN__
#define TYPE_UNKNOWN 12 /* Must be greater than other types */
-#define XSTR(M) sizeof(M) - strlen(M) - 1 /* To avoid overflow*/
+#define XLEN(M) sizeof(M) - strlen(M) - 1 /* To avoid overflow*/
/***********************************************************************/
/* Class and structure used by XMLColumns. */
@@ -226,30 +226,30 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
more:
if (vp->atp) {
strncpy(colname, vp->atp->GetName(g), sizeof(colname));
- strncat(xcol->Name, colname, XSTR(xcol->Name));
+ strncat(xcol->Name, colname, XLEN(xcol->Name));
switch (vp->atp->GetText(g, buf, sizeof(buf))) {
case RC_INFO:
PushWarning(g, txmp);
case RC_OK:
- strncat(fmt, "@", XSTR(fmt));
+ strncat(fmt, "@", XLEN(fmt));
break;
default:
goto err;
} // enswitch rc
if (j)
- strncat(fmt, colname, XSTR(fmt));
+ strncat(fmt, colname, XLEN(fmt));
} else {
if (tdp->Usedom && node->GetType() != 1)
continue;
strncpy(colname, node->GetName(g), sizeof(colname));
- strncat(xcol->Name, colname, XSTR(xcol->Name));
+ strncat(xcol->Name, colname, XLEN(xcol->Name));
if (j)
- strncat(fmt, colname, XSTR(fmt));
+ strncat(fmt, colname, XLEN(fmt));
if (j < lvl && ok) {
vp = lvlp[j+1];
@@ -267,9 +267,9 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
if (!vp->atp)
node = vp->nl->GetItem(g, vp->k++, node);
- strncat(fmt, colname, XSTR(fmt));
- strncat(fmt, "/", XSTR(fmt));
- strncat(xcol->Name, "_", XSTR(xcol->Name));
+ strncat(fmt, colname, XLEN(fmt));
+ strncat(fmt, "/", XLEN(fmt));
+ strncat(xcol->Name, "_", XLEN(xcol->Name));
j++;
vp->n = (int)strlen(xcol->Name);
vp->m = (int)strlen(fmt);
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index ab4ed5f32a3..60471c9b0d8 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -2440,7 +2440,6 @@ void DTVAL::SetTimeShift(void)
} // end of SetTimeShift
-#if defined(connect_EXPORTS)
// Added by Alexander Barkov
static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime)
{
@@ -2462,9 +2461,6 @@ static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm)
TIME_to_localtime(tm, &ltime);
return tm;
} // end of gmtime_mysql
-#else
-#define gmtime_mysql(T,B) gmtime((const time_t *)T)
-#endif
/***********************************************************************/
/* GetGmTime: returns a pointer to a static tm structure obtained */
@@ -2493,7 +2489,6 @@ struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
return datm;
} // end of GetGmTime
-#if defined(connect_EXPORTS)
// Added by Alexander Barkov
static time_t mktime_mysql(struct tm *ptm)
{
@@ -2504,9 +2499,6 @@ static time_t mktime_mysql(struct tm *ptm)
time_t t= TIME_to_timestamp(current_thd, &ltime, &error_code);
return error_code ? (time_t) -1 : t;
}
-#else
-#define mktime_mysql mktime
-#endif
/***********************************************************************/
/* MakeTime: calculates a date value from a tm structures using the */