diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 2de00db1bfd55..7ff2ca7753c09 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 883ec73e03990..d9834e56dcd16 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/ha_connect.cc b/storage/connect/ha_connect.cc index f4121ea0f18b1..84a78f7dee151 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 November 20, 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= '/'; @@ -6274,10 +6274,6 @@ bool ha_connect::FileExists(const char *fn, bool bf) int n; struct stat info; - if (check_access(ha_thd(), FILE_ACL, table->s->db.str, - NULL, NULL, 0, 0)) - return true; - #if defined(__WIN__) s= "\\"; #else // !__WIN__ diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index 19947ab18994f..fc7edb84c0f49 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 d2ebc25123d96..4ea169e1b1809 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 0b40f1d18cf7c..40685ae0f0e52 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: */ @@ -502,6 +526,166 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) return vp; } // 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: */ /*********************************************************************************/ @@ -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) { @@ -1062,6 +1254,14 @@ static int IsJson(UDF_ARGS *args, uint i) return n; } // 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. */ /*********************************************************************************/ @@ -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); 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; @@ -1883,6 +2109,55 @@ void json_object_nonull_deinit(UDF_INIT* initid) JsonFreeMem((PGLOBAL)initid->ptr); } // 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. */ /*********************************************************************************/ @@ -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(); - path = MakePSZ(g, args, 1); - jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length); + if (g->Mrr) { // First argument is a constant + g->Xchk = jsp; + JsonMemSave(g); + } // endif Mrr - if (jsx->SetJpath(g, path, true)) { - PUSH_WARNING(g->Message); - *is_null = 1; - return NULL; - } // endif SetJpath + } else + jsp = (PJSON)g->Xchk; + + 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 @@ -3593,6 +4260,61 @@ void jbin_object_nonull_deinit(UDF_INIT* initid) JsonFreeMem((PGLOBAL)initid->ptr); } // 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. */ /*********************************************************************************/ @@ -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 @@ -3905,6 +4656,147 @@ void jbin_item_merge_deinit(UDF_INIT* initid) JsonFreeMem((PGLOBAL)initid->ptr); } // 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. */ /*********************************************************************************/ @@ -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 0903b789fb623..ecbbb778214b6 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 @@ class JSNX : public BLOCK { 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 @@ class JSNX : public BLOCK { 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 @@ class JSNX : public BLOCK { 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 76a00c7e7f641..2e9085b4c87c1 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 81acbea91a694..5089022c5eada 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 0000000000000..4e59b51c52983 --- /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 0000000000000..cfe3476cd00b6 --- /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_udf.inc b/storage/connect/mysql-test/connect/t/json_udf.inc index de41169688566..f17d59832f3a7 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 d05dd28f16c01..cfd1fdae25896 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 e5609bfd1f8a0..f62b178b0037c 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 0000000000000..e4ee422c26398 --- /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/tabjson.cpp b/storage/connect/tabjson.cpp index 8f7b9508e6083..40fd946726965 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,26 @@ 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 + rc = (Pretty == 1 && !strcmp(To_Line, "]")) ? RC_EF : RC_FX; + + } // endif ReadDB return rc; } // end of ReadDB @@ -744,7 +768,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 +785,30 @@ 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 + 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 +816,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 +833,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 +848,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 +1144,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 +1169,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 +1316,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 +1360,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 +1412,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 +1425,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 +1450,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 +1878,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 +1886,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 4505d30a21ccb..f7cb74c3c4d2e 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 9c47829d5bc12..57d204a428617 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 ab4ed5f32a38a..60471c9b0d803 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, <ime); 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, <ime, &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 */