summaryrefslogtreecommitdiff
path: root/storage/connect
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2020-11-27 10:25:47 +0100
committerOlivier Bertrand <bertrandop@gmail.com>2020-11-27 10:25:47 +0100
commit950bf6ab53d7b6d5db0e7d986b81fbd5709e98f6 (patch)
tree1cbf8bd65fcb1f593b9aecc2fee046ccaf190ae6 /storage/connect
parentb656d3d333f6d8a28407e5e4b636cd142d757595 (diff)
downloadmariadb-git-950bf6ab53d7b6d5db0e7d986b81fbd5709e98f6.tar.gz
- Begin implementation of BSON
modified: storage/connect/bson.cpp modified: storage/connect/bson.h modified: storage/connect/bsonudf.cpp modified: storage/connect/bsonudf.h modified: storage/connect/jsonudf.cpp
Diffstat (limited to 'storage/connect')
-rw-r--r--storage/connect/bson.cpp17
-rw-r--r--storage/connect/bson.h8
-rw-r--r--storage/connect/bsonudf.cpp429
-rw-r--r--storage/connect/bsonudf.h30
-rw-r--r--storage/connect/jsonudf.cpp2
5 files changed, 361 insertions, 125 deletions
diff --git a/storage/connect/bson.cpp b/storage/connect/bson.cpp
index 61e5eb9fe16..4725b67c06b 100644
--- a/storage/connect/bson.cpp
+++ b/storage/connect/bson.cpp
@@ -653,7 +653,7 @@ PSZ BDOC::Serialize(PGLOBAL g, PBVAL bvp, char* fn, int pretty) {
err = SerializeValue(MVP(bvp->To_Val));
break;
default:
- strcpy(g->Message, "Invalid json tree");
+ err = SerializeValue(bvp);
} // endswitch Type
if (fs) {
@@ -760,7 +760,7 @@ bool BDOC::SerializeObject(OFFSET obp) {
bool BDOC::SerializeValue(PBVAL jvp) {
char buf[64];
- switch (jvp->Type) {
+ if (jvp) switch (jvp->Type) {
case TYPE_JAR:
return SerializeArray(jvp->To_Val, false);
case TYPE_JOB:
@@ -788,8 +788,7 @@ bool BDOC::SerializeValue(PBVAL jvp) {
return jp->WriteStr("???"); // TODO
} // endswitch Type
- strcpy(jp->g->Message, "Unrecognized value");
- return true;
+ return jp->WriteStr("null");
} // end of SerializeValue
/* --------------------------- Class BJSON --------------------------- */
@@ -860,7 +859,7 @@ int BJSON::GetObjectSize(PBPR bop, bool b)
/***********************************************************************/
PBPR BJSON::AddPair(PGLOBAL g, PBPR bop, PSZ key, OFFSET val)
{
- PBPR brp, nrp = SubAllocPair(g, MOF(key), val);
+ PBPR brp, nrp = SubAllocPair(g, key, val);
if (bop) {
for (brp = bop; brp->Next; brp = MPP(brp->Next));
@@ -995,10 +994,10 @@ PBPR BJSON::SetKeyValue(PGLOBAL g, PBPR bop, OFFSET bvp, PSZ key)
prp = brp;
if (!brp)
- prp->Vlp = MOF(SubAllocPair(g, MOF(key), bvp));
+ prp->Vlp = MOF(SubAllocPair(g, key, bvp));
} else
- bop = SubAllocPair(g, MOF(key), bvp);
+ bop = SubAllocPair(g, key, bvp);
// Return the first pair of this object
return bop;
@@ -1094,7 +1093,7 @@ PBVAL BJSON::AddArrayValue(PGLOBAL g, PBVAL bap, PBVAL nvp, int* x)
nvp = SubAllocVal(g);
if (bap) {
- int i = 0, n = *x;
+ int i = 0, n = (x) ? *x : INT_MAX32;
PBVAL bvp;
for (bvp = bap; bvp; bvp = MVP(bvp->Next), i++)
@@ -1240,7 +1239,7 @@ PBVAL BJSON::SubAllocVal(PGLOBAL g)
bvp->To_Val = 0;
bvp->Nd = 0;
- bvp->Type = TYPE_UNKNOWN;
+ bvp->Type = TYPE_NULL;
bvp->Next = 0;
return bvp;
} // end of SubAllocVal
diff --git a/storage/connect/bson.h b/storage/connect/bson.h
index bffda8ea316..284bee1da48 100644
--- a/storage/connect/bson.h
+++ b/storage/connect/bson.h
@@ -76,8 +76,14 @@ public:
// SubAlloc functions
void* BsonSubAlloc(PGLOBAL g, size_t size);
PBPR SubAllocPair(PGLOBAL g, OFFSET key, OFFSET val = 0);
+ PBPR SubAllocPair(PGLOBAL g, PSZ key, OFFSET val = 0)
+ {return SubAllocPair(g, MOF(key), val);}
PBVAL SubAllocVal(PGLOBAL g);
- PBVAL SubAllocVal(PGLOBAL g, OFFSET toval, int type = TYPE_UNKNOWN, short nd = 0);
+ PBVAL SubAllocVal(PGLOBAL g, OFFSET toval, int type = TYPE_NULL, short nd = 0);
+ PBVAL SubAllocVal(PGLOBAL g, PBVAL toval, int type = TYPE_NULL, short nd = 0)
+ {return SubAllocVal(g, MOF(toval), type, nd);}
+ PBVAL SubAllocVal(PGLOBAL g, PSZ str, int type = TYPE_STRG, short nd = 0)
+ {return SubAllocVal(g, MOF(str), type, nd);}
PBVAL SubAllocVal(PGLOBAL g, PVAL valp);
PBVAL DupVal(PGLOBAL g, PBVAL bvp);
diff --git a/storage/connect/bsonudf.cpp b/storage/connect/bsonudf.cpp
index bbb279ce6ce..95cc8aa7da8 100644
--- a/storage/connect/bsonudf.cpp
+++ b/storage/connect/bsonudf.cpp
@@ -1,7 +1,7 @@
/****************** bsonudf C++ Program Source Code File (.CPP) ******************/
/* PROGRAM NAME: bsonudf Version 1.0 */
/* (C) Copyright to the author Olivier BERTRAND 2020 */
-/* This program are the BSON User Defined Functions . */
+/* This program are the BSON User Defined Functions. */
/*********************************************************************************/
/*********************************************************************************/
@@ -25,7 +25,7 @@
#else
#define PUSH_WARNING(M) htrc(M)
#endif
-#define M 9
+#define M 6
/* --------------------------------- JSON UDF ---------------------------------- */
@@ -49,7 +49,8 @@ inline void JsonFreeMem(PGLOBAL g) {
/*********************************************************************************/
/* SubAlloc a new BJNX class with protection against memory exhaustion. */
/*********************************************************************************/
-static PBJNX BjnxNew(PGLOBAL g, PBVAL vlp, int type, int len) {
+static PBJNX BjnxNew(PGLOBAL g, PBVAL vlp, int type, int len)
+{
PBJNX bjnx;
try {
@@ -71,7 +72,8 @@ static PBJNX BjnxNew(PGLOBAL g, PBVAL vlp, int type, int len) {
/* BSNX public constructor. */
/*********************************************************************************/
BJNX::BJNX(PGLOBAL g, PBVAL row, int type, int len, int prec, my_bool wr)
- : BDOC(g->Sarea) {
+ : BDOC(g->Sarea)
+{
Row = row;
Bvalp = NULL;
Jpnp = NULL;
@@ -99,7 +101,8 @@ BJNX::BJNX(PGLOBAL g, PBVAL row, int type, int len, int prec, my_bool wr)
/*********************************************************************************/
/* SetJpath: set and parse the json path. */
/*********************************************************************************/
-my_bool BJNX::SetJpath(PGLOBAL g, char* path, my_bool jb) {
+my_bool BJNX::SetJpath(PGLOBAL g, char* path, my_bool jb)
+{
// Check Value was allocated
if (!Value)
return true;
@@ -117,7 +120,8 @@ my_bool BJNX::SetJpath(PGLOBAL g, char* path, my_bool jb) {
/*********************************************************************************/
/* Analyse array processing options. */
/*********************************************************************************/
-my_bool BJNX::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm) {
+my_bool BJNX::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm)
+{
int n = (int)strlen(p);
my_bool dg = true, b = false;
PJNODE jnp = &Nodes[i];
@@ -243,7 +247,8 @@ my_bool BJNX::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm) {
/* creating the table. It permits to indicate the position of the node */
/* corresponding to that column. */
/*********************************************************************************/
-my_bool BJNX::ParseJpath(PGLOBAL g) {
+my_bool BJNX::ParseJpath(PGLOBAL g)
+{
char* p, * p1 = NULL, * p2 = NULL, * pbuf = NULL;
int i;
my_bool a, mul = false;
@@ -329,7 +334,8 @@ my_bool BJNX::ParseJpath(PGLOBAL g) {
/*********************************************************************************/
/* MakeJson: Serialize the json item and set value to it. */
/*********************************************************************************/
-PVAL BJNX::MakeJson(PGLOBAL g, PBVAL bvp) {
+PVAL BJNX::MakeJson(PGLOBAL g, PBVAL bvp)
+{
if (Value->IsTypeNum()) {
strcpy(g->Message, "Cannot make Json for a numeric value");
Value->Reset();
@@ -345,7 +351,8 @@ PVAL BJNX::MakeJson(PGLOBAL g, PBVAL bvp) {
/*********************************************************************************/
/* SetValue: Set a value from a JVALUE contains. */
/*********************************************************************************/
-void BJNX::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL vlp) {
+void BJNX::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL vlp)
+{
if (vlp) {
vp->SetNull(false);
@@ -396,21 +403,24 @@ void BJNX::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL vlp) {
/*********************************************************************************/
/* GetJson: */
/*********************************************************************************/
-PBVAL BJNX::GetJson(PGLOBAL g) {
+PBVAL BJNX::GetJson(PGLOBAL g)
+{
return GetRowValue(g, Row, 0);
} // end of GetJson
/*********************************************************************************/
/* ReadValue: */
/*********************************************************************************/
-void BJNX::ReadValue(PGLOBAL g) {
+void BJNX::ReadValue(PGLOBAL g)
+{
Value->SetValue_pval(GetColumnValue(g, Row, 0));
} // end of ReadValue
/*********************************************************************************/
/* GetColumnValue: */
/*********************************************************************************/
-PVAL BJNX::GetColumnValue(PGLOBAL g, PBVAL row, int i) {
+PVAL BJNX::GetColumnValue(PGLOBAL g, PBVAL row, int i)
+{
PBVAL vlp = GetRowValue(g, row, i);
SetJsonValue(g, Value, vlp);
@@ -420,7 +430,8 @@ PVAL BJNX::GetColumnValue(PGLOBAL g, PBVAL row, int i) {
/*********************************************************************************/
/* GetRowValue: */
/*********************************************************************************/
-PBVAL BJNX::GetRowValue(PGLOBAL g, PBVAL row, int i, my_bool b) {
+PBVAL BJNX::GetRowValue(PGLOBAL g, PBVAL row, int i, my_bool b)
+{
my_bool expd = false;
PBVAL bap;
PBVAL vlp = NULL;
@@ -488,7 +499,8 @@ PBVAL BJNX::GetRowValue(PGLOBAL g, PBVAL row, int i, my_bool b) {
/*********************************************************************************/
/* ExpandArray: */
/*********************************************************************************/
-PVAL BJNX::ExpandArray(PGLOBAL g, PBVAL arp, int n) {
+PVAL BJNX::ExpandArray(PGLOBAL g, PBVAL arp, int n)
+{
strcpy(g->Message, "Expand cannot be done by this function");
return NULL;
} // end of ExpandArray
@@ -496,7 +508,8 @@ PVAL BJNX::ExpandArray(PGLOBAL g, PBVAL arp, int n) {
/*********************************************************************************/
/* CalculateArray: NIY */
/*********************************************************************************/
-PVAL BJNX::CalculateArray(PGLOBAL g, PBVAL bap, int n) {
+PVAL BJNX::CalculateArray(PGLOBAL g, PBVAL bap, int n)
+{
#if 0
int i, ars = GetArraySize(bap), nv = 0;
bool err;
@@ -592,7 +605,8 @@ PVAL BJNX::CalculateArray(PGLOBAL g, PBVAL bap, int n) {
/*********************************************************************************/
/* CheckPath: Checks whether the path exists in the document. */
/*********************************************************************************/
-my_bool BJNX::CheckPath(PGLOBAL g) {
+my_bool BJNX::CheckPath(PGLOBAL g)
+{
PBVAL val = NULL;
PBVAL row = Row;
@@ -632,7 +646,8 @@ my_bool BJNX::CheckPath(PGLOBAL g) {
/***********************************************************************/
/* GetRow: Set the complete path of the object to be set. */
/***********************************************************************/
-PBVAL BJNX::GetRow(PGLOBAL g) {
+PBVAL BJNX::GetRow(PGLOBAL g)
+{
PBVAL val = NULL;
PBVAL arp;
PBVAL nwr, row = Row;
@@ -711,7 +726,8 @@ PBVAL BJNX::GetRow(PGLOBAL g) {
/***********************************************************************/
/* WriteValue: */
/***********************************************************************/
-my_bool BJNX::WriteValue(PGLOBAL g, PBVAL jvalp) {
+my_bool BJNX::WriteValue(PGLOBAL g, PBVAL jvalp)
+{
PBPR objp = NULL;
PBVAL arp = NULL;
PBVAL jvp = NULL;
@@ -751,7 +767,8 @@ my_bool BJNX::WriteValue(PGLOBAL g, PBVAL jvalp) {
/*********************************************************************************/
/* Locate a value in a JSON tree: */
/*********************************************************************************/
-PSZ BJNX::Locate(PGLOBAL g, PBVAL jsp, PBVAL jvp, int k) {
+PSZ BJNX::Locate(PGLOBAL g, PBVAL jsp, PBVAL jvp, int k)
+{
PSZ str = NULL;
my_bool b = false, err = true;
@@ -808,7 +825,8 @@ PSZ BJNX::Locate(PGLOBAL g, PBVAL jsp, PBVAL jvp, int k) {
/*********************************************************************************/
/* Locate in a JSON Array. */
/*********************************************************************************/
-my_bool BJNX::LocateArray(PGLOBAL g, PBVAL jarp) {
+my_bool BJNX::LocateArray(PGLOBAL g, PBVAL jarp)
+{
char s[16];
int n = GetArraySize(jarp);
size_t m = Jp->N;
@@ -831,7 +849,8 @@ my_bool BJNX::LocateArray(PGLOBAL g, PBVAL jarp) {
/*********************************************************************************/
/* Locate in a JSON Object. */
/*********************************************************************************/
-my_bool BJNX::LocateObject(PGLOBAL g, PBPR jobp) {
+my_bool BJNX::LocateObject(PGLOBAL g, PBPR jobp)
+{
size_t m;
if (Jp->WriteChr('.'))
@@ -856,7 +875,8 @@ my_bool BJNX::LocateObject(PGLOBAL g, PBPR jobp) {
/*********************************************************************************/
/* Locate a JSON Value. */
/*********************************************************************************/
-my_bool BJNX::LocateValue(PGLOBAL g, PBVAL jvp) {
+my_bool BJNX::LocateValue(PGLOBAL g, PBVAL jvp)
+{
if (CompareTree(g, Bvalp, jvp))
Found = (--K == 0);
else if (jvp->Type == TYPE_JAR)
@@ -870,7 +890,8 @@ my_bool BJNX::LocateValue(PGLOBAL g, PBVAL jvp) {
/*********************************************************************************/
/* Locate all occurrences of a value in a JSON tree: */
/*********************************************************************************/
-PSZ BJNX::LocateAll(PGLOBAL g, PBVAL jsp, PBVAL bvp, int mx) {
+PSZ BJNX::LocateAll(PGLOBAL g, PBVAL jsp, PBVAL bvp, int mx)
+{
PSZ str = NULL;
my_bool b = false, err = true;
PJPN jnp;
@@ -930,7 +951,8 @@ PSZ BJNX::LocateAll(PGLOBAL g, PBVAL jsp, PBVAL bvp, int mx) {
/*********************************************************************************/
/* Locate in a JSON Array. */
/*********************************************************************************/
-my_bool BJNX::LocateArrayAll(PGLOBAL g, PBVAL jarp) {
+my_bool BJNX::LocateArrayAll(PGLOBAL g, PBVAL jarp)
+{
int i = 0;
if (I < Imax) {
@@ -954,7 +976,8 @@ my_bool BJNX::LocateArrayAll(PGLOBAL g, PBVAL jarp) {
/*********************************************************************************/
/* Locate in a JSON Object. */
/*********************************************************************************/
-my_bool BJNX::LocateObjectAll(PGLOBAL g, PBPR jobp) {
+my_bool BJNX::LocateObjectAll(PGLOBAL g, PBPR jobp)
+{
if (I < Imax) {
Jpnp[++I].Type = TYPE_JOB;
@@ -975,7 +998,8 @@ my_bool BJNX::LocateObjectAll(PGLOBAL g, PBPR jobp) {
/*********************************************************************************/
/* Locate a JSON Value. */
/*********************************************************************************/
-my_bool BJNX::LocateValueAll(PGLOBAL g, PBVAL jvp) {
+my_bool BJNX::LocateValueAll(PGLOBAL g, PBVAL jvp)
+{
if (CompareTree(g, Bvalp, jvp))
return AddPath();
else if (jvp->Type == TYPE_JAR)
@@ -989,7 +1013,8 @@ my_bool BJNX::LocateValueAll(PGLOBAL g, PBVAL jvp) {
/*********************************************************************************/
/* Compare two JSON trees. */
/*********************************************************************************/
-my_bool BJNX::CompareTree(PGLOBAL g, PBVAL jp1, PBVAL jp2) {
+my_bool BJNX::CompareTree(PGLOBAL g, PBVAL jp1, PBVAL jp2)
+{
if (!jp1 || !jp2 || jp1->Type != jp2->Type || GetSize(jp1) != GetSize(jp2))
return false;
@@ -1017,7 +1042,8 @@ my_bool BJNX::CompareTree(PGLOBAL g, PBVAL jp1, PBVAL jp2) {
/*********************************************************************************/
/* Compare two VAL values and return true if they are equal. */
/*********************************************************************************/
-my_bool BJNX::CompareValues(PGLOBAL g, PBVAL v1, PBVAL v2) {
+my_bool BJNX::CompareValues(PGLOBAL g, PBVAL v1, PBVAL v2)
+{
my_bool b = false;
if (v1 && v2)
@@ -1091,7 +1117,8 @@ my_bool BJNX::CompareValues(PGLOBAL g, PBVAL v1, PBVAL v2) {
/*********************************************************************************/
/* Add the found path to the list. */
/*********************************************************************************/
-my_bool BJNX::AddPath(void) {
+my_bool BJNX::AddPath(void)
+{
char s[16];
if (Jp->WriteStr("\"$"))
@@ -1121,86 +1148,270 @@ my_bool BJNX::AddPath(void) {
return false;
} // end of AddPath
+/* -----------------------------Utility functions ------------------------------ */
+
/*********************************************************************************/
/* Make a BVAL value from the passed argument. */
/*********************************************************************************/
-static PBVAL MakeBinValue(PGLOBAL g, UDF_ARGS* args, uint i) {
+static PBVAL MakeBinValue(PGLOBAL g, UDF_ARGS* args, uint i)
+{
char* sap = (args->arg_count > i) ? args->args[i] : NULL;
int n, len;
int ci;
longlong bigint;
- void* Base = g->Sarea; // Required by MOF
- BDOC doc(Base);
- PBVAL bp;
- PBVAL bvp = doc.SubAllocVal(g);
-
- if (sap) switch (args->arg_type[i]) {
- case STRING_RESULT:
- if ((len = args->lengths[i])) {
- if ((n = IsJson(args, i)) < 3)
- sap = MakePSZ(g, args, i);
-
- if (n) {
- if (n == 2) {
- if (!(sap = GetJsonFile(g, sap))) {
+ BDOC doc(g->Sarea);
+ PBVAL bp, bvp = doc.SubAllocVal(g);
+
+ if (sap) {
+ if (args->arg_type[i] == STRING_RESULT) {
+ if ((len = args->lengths[i])) {
+ if ((n = IsJson(args, i)) < 3)
+ sap = MakePSZ(g, args, i);
+
+ if (n) {
+ if (n == 2) {
+ if (!(sap = GetJsonFile(g, sap))) {
+ PUSH_WARNING(g->Message);
+ return NULL;
+ } // endif sap
+
+ len = strlen(sap);
+ } // endif 2
+
+ if (!(bp = doc.ParseJson(g, sap, strlen(sap)))) {
PUSH_WARNING(g->Message);
return NULL;
- } // endif sap
-
- len = strlen(sap);
- } // endif 2
+ } else
+ bvp = bp;
- if (!(bp = doc.ParseJson(g, sap, strlen(sap))))
- PUSH_WARNING(g->Message);
+ } else {
+ // Check whether this string is a valid json string
+ JsonMemSave(g);
- bvp = bp;
- } else {
- // Check whether this string is a valid json string
- JsonMemSave(g);
+ if (!(bp = doc.ParseJson(g, sap, strlen(sap)))) {
+ // Recover suballocated memory
+ JsonSubSet(g);
+ ci = (strnicmp(args->attributes[i], "ci", 2)) ? 0 : 1;
+ doc.SetString(bvp, sap, ci);
+ } else
+ bvp = bp;
- if (!(bvp = doc.ParseJson(g, sap, strlen(sap)))) {
- // Recover suballocated memory
- JsonSubSet(g);
- ci = (strnicmp(args->attributes[i], "ci", 2)) ? 0 : 1;
- bvp = doc.SubAllocVal(g, MOF(sap), TYPE_STRG, ci);
- } else
g->Saved_Size = 0;
+ } // endif n
- } // endif n
-
- } // endif len
+ } // endif len
- break;
- case INT_RESULT:
- bigint = *(longlong*)sap;
-
- if ((bigint == 0LL && !strcmp(args->attributes[i], "FALSE")) ||
- (bigint == 1LL && !strcmp(args->attributes[i], "TRUE")))
- doc.SetBool(bvp, (bool)bigint);
- else
- doc.SetBigint(g, bvp, bigint);
+ } else switch (args->arg_type[i]) {
+ case INT_RESULT:
+ bigint = *(longlong*)sap;
- break;
- case REAL_RESULT:
- doc.SetFloat(bvp, *(double*)sap);
- break;
- case DECIMAL_RESULT:
- doc.SetFloat(bvp, atof(MakePSZ(g, args, i)));
- break;
- case TIME_RESULT:
- case ROW_RESULT:
- default:
- bvp = NULL;
- break;
- } // endswitch arg_type
+ if ((bigint == 0LL && !strcmp(args->attributes[i], "FALSE")) ||
+ (bigint == 1LL && !strcmp(args->attributes[i], "TRUE")))
+ doc.SetBool(bvp, (bool)bigint);
+ else
+ doc.SetBigint(g, bvp, bigint);
+
+ break;
+ case REAL_RESULT:
+ doc.SetFloat(bvp, *(double*)sap);
+ break;
+ case DECIMAL_RESULT:
+ doc.SetFloat(bvp, atof(MakePSZ(g, args, i)));
+ break;
+ case TIME_RESULT:
+ case ROW_RESULT:
+ default:
+ bvp->Type = TYPE_UNKNOWN;
+ break;
+ } // endswitch arg_type
+
+ } // endif sap
return bvp;
} // end of MakeBinValue
+/* ------------------------- Now the new Bin UDF's ----------------------------- */
+
+/*********************************************************************************/
+/* Make a Json value containing the parameter. */
+/*********************************************************************************/
+my_bool bsonvalue_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
+{
+ unsigned long reslen, memlen;
+
+ if (args->arg_count > 1) {
+ strcpy(message, "Cannot accept more than 1 argument");
+ return true;
+ } else
+ CalcLen(args, false, reslen, memlen);
+
+ return JsonInit(initid, args, message, false, reslen, memlen);
+} // end of bsonvalue_init
+
+char* bsonvalue(UDF_INIT* initid, UDF_ARGS* args, char* result,
+ unsigned long* res_length, char*, char*)
+{
+ char *str;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ if (!g->Xchk) {
+ if (!CheckMemory(g, initid, args, 1, false)) {
+ BDOC doc(g->Sarea);
+ PBVAL bvp = MakeBinValue(g, args, 0);
+
+ if (!(str = doc.Serialize(g, bvp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ } else
+ 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 bsonValue
+
+void bsonvalue_deinit(UDF_INIT* initid) {
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of bsonvalue_deinit
+
+/*********************************************************************************/
+/* Make a Bson array containing all the parameters. */
+/*********************************************************************************/
+my_bool bson_make_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);
+} // end of bson_make_array_init
+
+char* bson_make_array(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)) {
+ BDOC doc(g->Sarea);
+ PBVAL bvp = NULL, arp = NULL;
+
+ for (uint i = 0; i < args->arg_count; i++)
+ bvp = doc.AddArrayValue(g, bvp, MakeBinValue(g, args, i));
+
+ arp = doc.SubAllocVal(g, bvp, TYPE_JAR);
+
+ if (!(str = doc.Serialize(g, arp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ } else
+ 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 bson_make_array
+
+void bson_make_array_deinit(UDF_INIT* initid) {
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of bson_make_array_deinit
+
+/*********************************************************************************/
+/* Add one or several values to a Bson array. */
+/*********************************************************************************/
+my_bool bson_array_add_values_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
+ unsigned long reslen, memlen;
+
+ if (args->arg_count < 2) {
+ strcpy(message, "This function must have at least 2 arguments");
+ return true;
+ //} else if (!IsJson(args, 0, true)) {
+ // strcpy(message, "First argument must be a valid json string or item");
+ // return true;
+ } else
+ CalcLen(args, false, reslen, memlen);
+
+ if (!JsonInit(initid, args, message, true, reslen, memlen)) {
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ // This is a constant function
+ g->N = (initid->const_item) ? 1 : 0;
+
+ // This is to avoid double execution when using prepared statements
+ if (IsJson(args, 0) > 1)
+ initid->const_item = 0;
+
+ return false;
+ } else
+ return true;
+
+} // end of bson_array_add_values_init
+
+char* bson_array_add_values(UDF_INIT* initid, UDF_ARGS* args, char* result,
+ unsigned long* res_length, char* is_null, char*) {
+ char* str = NULL;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ if (!g->Xchk) {
+ if (!CheckMemory(g, initid, args, args->arg_count, true)) {
+ uint n = 1;
+ bool b = false;
+ BDOC doc(g->Sarea);
+ PBVAL bvp = NULL, arp = MakeBinValue(g, args, 0);
+
+ if (arp->Type == TYPE_JAR) {
+ bvp = doc.GetArray(arp);
+ b = !bvp;
+ } else
+ n = 0;
+
+ for (uint i = n; i < args->arg_count; i++)
+ bvp = doc.AddArrayValue(g, bvp, MakeBinValue(g, args, i));
+
+ if (!n)
+ arp = doc.SubAllocVal(g, bvp, TYPE_JAR);
+ else if (b)
+ doc.SetValueArr(arp, bvp);
+
+// str = MakeResult(g, args, top, args->arg_count);
+ str = doc.Serialize(g, arp, NULL, 0);
+ } // endif CheckMemory
+
+ if (!str) {
+ PUSH_WARNING(g->Message);
+ str = args->args[0];
+ } // endif str
+
+ // Keep result of constant function
+ g->Xchk = (g->N) ? str : NULL;
+ } else
+ str = (char*)g->Xchk;
+
+ if (!str) {
+ *res_length = 0;
+ *is_null = 1;
+ } else
+ *res_length = strlen(str);
+
+ return str;
+} // end of bson_array_add_values
+
+void bson_array_add_values_deinit(UDF_INIT* initid) {
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of bson_array_add_values_deinit
+
/*********************************************************************************/
/* Test BJSON parse and serialize. */
/*********************************************************************************/
-my_bool json_test_bson_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
+my_bool bson_test_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
unsigned long reslen, memlen, more = 1000;
if (args->arg_count == 0) {
@@ -1213,9 +1424,9 @@ my_bool json_test_bson_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
CalcLen(args, false, reslen, memlen);
return JsonInit(initid, args, message, true, reslen, memlen, more);
-} // end of json_test_bson_init
+} // end of bson_test_init
-char* json_test_bson(UDF_INIT* initid, UDF_ARGS* args, char* result,
+char* bson_test(UDF_INIT* initid, UDF_ARGS* args, char* result,
unsigned long* res_length, char* is_null, char* error) {
char* str = NULL, * sap = NULL, * fn = NULL;
int pretty = 1;
@@ -1281,16 +1492,16 @@ err:
*res_length = strlen(str);
return str;
-} // end of json_test_bson
+} // end of bson_test
-void json_test_bson_deinit(UDF_INIT* initid) {
+void bson_test_deinit(UDF_INIT* initid) {
JsonFreeMem((PGLOBAL)initid->ptr);
-} // end of json_test_bson_deinit
+} // end of bson_test_deinit
/*********************************************************************************/
/* Locate a value in a Json tree. */
/*********************************************************************************/
-my_bool jsonlocate_bson_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
+my_bool bsonlocate_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
unsigned long reslen, memlen, more = 1000;
if (args->arg_count < 2) {
@@ -1311,11 +1522,11 @@ my_bool jsonlocate_bson_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
more = 0;
return JsonInit(initid, args, message, true, reslen, memlen, more);
-} // end of jsonlocate_bson_init
+} // end of bsonlocate_init
-char* jsonlocate_bson(UDF_INIT* initid, UDF_ARGS* args, char* result,
+char* bsonlocate(UDF_INIT* initid, UDF_ARGS* args, char* result,
unsigned long* res_length, char* is_null, char* error) {
- char* path = NULL;
+ char *path = NULL;
int k;
PBVAL bvp, bvp2;
PBJNX bnxp;
@@ -1358,7 +1569,10 @@ char* jsonlocate_bson(UDF_INIT* initid, UDF_ARGS* args, char* result,
bvp = (PBVAL)g->Xchk;
// The item to locate
- bvp2 = MakeBinValue(g, args, 1);
+ if (!(bvp2 = MakeBinValue(g, args, 1))) {
+ PUSH_WARNING("Invalid second argument");
+ goto err;
+ } // endif bvp
k = (args->arg_count > 2) ? (int)*(long long*)args->args[2] : 1;
@@ -1389,16 +1603,16 @@ err:
*res_length = strlen(path);
return path;
-} // end of jsonlocate_bson
+} // end of bsonlocate
-void jsonlocate_bson_deinit(UDF_INIT* initid) {
+void bsonlocate_deinit(UDF_INIT* initid) {
JsonFreeMem((PGLOBAL)initid->ptr);
-} // end of jsonlocate_bson_deinit
+} // end of bsonlocate_deinit
/*********************************************************************************/
/* Locate all occurences of a value in a Json tree. */
/*********************************************************************************/
-my_bool json_locate_all_bson_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
+my_bool bson_locate_all_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
unsigned long reslen, memlen, more = 1000;
if (args->arg_count < 2) {
@@ -1419,9 +1633,9 @@ my_bool json_locate_all_bson_init(UDF_INIT* initid, UDF_ARGS* args, char* messag
more = 0;
return JsonInit(initid, args, message, true, reslen, memlen, more);
-} // end of json_locate_all_bson_init
+} // end of bson_locate_all_init
-char* json_locate_all_bson(UDF_INIT* initid, UDF_ARGS* args, char* result,
+char* bson_locate_all(UDF_INIT* initid, UDF_ARGS* args, char* result,
unsigned long* res_length, char* is_null, char* error) {
char* path = NULL;
int mx = 10;
@@ -1467,7 +1681,10 @@ char* json_locate_all_bson(UDF_INIT* initid, UDF_ARGS* args, char* result,
bvp = (PBVAL)g->Xchk;
// The item to locate
- bvp2 = MakeBinValue(g, args, 1);
+ if (!(bvp2 = MakeBinValue(g, args, 1))) {
+ PUSH_WARNING("Invalid second argument");
+ goto err;
+ } // endif bvp
if (args->arg_count > 2)
mx = (int)*(long long*)args->args[2];
@@ -1499,9 +1716,9 @@ err:
*res_length = strlen(path);
return path;
-} // end of json_locate_all_bson
+} // end of bson_locate_all
-void json_locate_all_bson_deinit(UDF_INIT* initid) {
+void bson_locate_all_deinit(UDF_INIT* initid) {
JsonFreeMem((PGLOBAL)initid->ptr);
-} // end of json_locate_all_bson_deinit
+} // end of bson_locate_all_deinit
diff --git a/storage/connect/bsonudf.h b/storage/connect/bsonudf.h
index 6687d4c1640..b310aa1827b 100644
--- a/storage/connect/bsonudf.h
+++ b/storage/connect/bsonudf.h
@@ -83,16 +83,28 @@ protected:
}; // end of class BJNX
extern "C" {
- DllExport my_bool json_test_bson_init(UDF_INIT*, UDF_ARGS*, char*);
- DllExport char* json_test_bson(UDF_EXEC_ARGS);
- DllExport void json_test_bson_deinit(UDF_INIT*);
+ DllExport my_bool bson_test_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char* bson_test(UDF_EXEC_ARGS);
+ DllExport void bson_test_deinit(UDF_INIT*);
- DllExport my_bool jsonlocate_bson_init(UDF_INIT*, UDF_ARGS*, char*);
- DllExport char* jsonlocate_bson(UDF_EXEC_ARGS);
- DllExport void jsonlocate_bson_deinit(UDF_INIT*);
+ DllExport my_bool bsonvalue_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char* bsonvalue(UDF_EXEC_ARGS);
+ DllExport void bsonvalue_deinit(UDF_INIT*);
- DllExport my_bool json_locate_all_bson_init(UDF_INIT*, UDF_ARGS*, char*);
- DllExport char* json_locate_all_bson(UDF_EXEC_ARGS);
- DllExport void json_locate_all_bson_deinit(UDF_INIT*);
+ DllExport my_bool bson_make_array_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char* bson_make_array(UDF_EXEC_ARGS);
+ DllExport void bson_make_array_deinit(UDF_INIT*);
+
+ DllExport my_bool bson_array_add_values_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char* bson_array_add_values(UDF_EXEC_ARGS);
+ DllExport void bson_array_add_values_deinit(UDF_INIT*);
+
+ DllExport my_bool bsonlocate_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char* bsonlocate(UDF_EXEC_ARGS);
+ DllExport void bsonlocate_deinit(UDF_INIT*);
+
+ DllExport my_bool bson_locate_all_init(UDF_INIT*, UDF_ARGS*, char*);
+ DllExport char* bson_locate_all(UDF_EXEC_ARGS);
+ DllExport void bson_locate_all_deinit(UDF_INIT*);
} // extern "C"
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
index cb29b9f5d6c..d993947589f 100644
--- a/storage/connect/jsonudf.cpp
+++ b/storage/connect/jsonudf.cpp
@@ -1950,6 +1950,8 @@ static PJVAL MakeTypedValue(PGLOBAL g, UDF_ARGS *args, uint i,
return jvp;
} // end of MakeTypedValue
+/* ------------------------------ The JSON UDF's ------------------------------- */
+
/*********************************************************************************/
/* Make a Json value containing the parameter. */
/*********************************************************************************/