diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2020-11-27 10:25:47 +0100 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2020-11-27 10:25:47 +0100 |
commit | 950bf6ab53d7b6d5db0e7d986b81fbd5709e98f6 (patch) | |
tree | 1cbf8bd65fcb1f593b9aecc2fee046ccaf190ae6 /storage/connect | |
parent | b656d3d333f6d8a28407e5e4b636cd142d757595 (diff) | |
download | mariadb-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.cpp | 17 | ||||
-rw-r--r-- | storage/connect/bson.h | 8 | ||||
-rw-r--r-- | storage/connect/bsonudf.cpp | 429 | ||||
-rw-r--r-- | storage/connect/bsonudf.h | 30 | ||||
-rw-r--r-- | storage/connect/jsonudf.cpp | 2 |
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. */ /*********************************************************************************/ |