summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2020-11-25 12:56:45 +0100
committerOlivier Bertrand <bertrandop@gmail.com>2020-11-25 12:56:45 +0100
commitdc8f914c383366d11b6a995ba184b99d5ec663cf (patch)
tree8af9316330bfe009952248317a6f68addcaced84
parentdae4bd0b36b83cc50d827c62f02ed1b8b1aa2045 (diff)
downloadmariadb-git-dc8f914c383366d11b6a995ba184b99d5ec663cf.tar.gz
Remove based enum not accepted by most gcc compilers
-rw-r--r--storage/connect/bson.cpp1016
-rw-r--r--storage/connect/bson.h187
-rw-r--r--storage/connect/json.h41
-rw-r--r--storage/connect/jsonudf.cpp1476
-rw-r--r--storage/connect/jsonudf.h114
-rw-r--r--storage/connect/tabjson.cpp2
-rw-r--r--storage/connect/value.cpp2
7 files changed, 2270 insertions, 568 deletions
diff --git a/storage/connect/bson.cpp b/storage/connect/bson.cpp
index 86825f5808e..2f380752c0d 100644
--- a/storage/connect/bson.cpp
+++ b/storage/connect/bson.cpp
@@ -21,8 +21,6 @@
#include "plgdbsem.h"
#include "bson.h"
-#define ARGS MY_MIN(24,(int)len-i),s+MY_MAX(i-3,0)
-
#if defined(__WIN__)
#define EL "\r\n"
#else
@@ -89,53 +87,25 @@ char* NextChr(PSZ s, char sep) {
/***********************************************************************/
/* BDOC constructor. */
/***********************************************************************/
-BDOC::BDOC(void) : jp(NULL), base(NULL), s(NULL), len(0)
+BDOC::BDOC(void *base) : BJSON(base, NULL)
{
+ jp = NULL;
+ s = NULL;
+ len = 0;
pty[0] = pty[1] = pty[2] = true;
} // end of BDOC constructor
/***********************************************************************/
-/* Program for sub-allocating Bson structures. */
-/***********************************************************************/
-void* BDOC::BsonSubAlloc(PGLOBAL g, size_t size) {
- PPOOLHEADER pph; /* Points on area header. */
- void* memp = g->Sarea;
-
- size = ((size + 3) / 4) * 4; /* Round up size to multiple of 4 */
- pph = (PPOOLHEADER)memp;
-
- xtrc(16, "SubAlloc in %p size=%zd used=%zd free=%zd\n",
- memp, size, pph->To_Free, pph->FreeBlk);
-
- if (size > pph->FreeBlk) { /* Not enough memory left in pool */
- sprintf(g->Message,
- "Not enough memory for request of %zd (used=%zd free=%zd)",
- size, pph->To_Free, pph->FreeBlk);
- xtrc(1, "BsonSubAlloc: %s\n", g->Message);
- throw(1234);
- } /* endif size OS32 code */
-
- // Do the suballocation the simplest way
- memp = MakePtr(memp, pph->To_Free); /* Points to suballocated block */
- pph->To_Free += size; /* New offset of pool free block */
- pph->FreeBlk -= size; /* New size of pool free block */
- xtrc(16, "Done memp=%p used=%zd free=%zd\n",
- memp, pph->To_Free, pph->FreeBlk);
- return memp;
-} /* end of BsonSubAlloc */
-
-
-
-/***********************************************************************/
/* Parse a json string. */
/* Note: when pretty is not known, the caller set pretty to 3. */
/***********************************************************************/
PBVAL BDOC::ParseJson(PGLOBAL g, char* js, size_t lng, int* ptyp, bool* comma) {
int i, pretty = (ptyp) ? *ptyp : 3;
bool b = false;
- PBVAL bvp = NULL;
- xtrc(1, "ParseJson: s=%.10s len=%zd\n", s, len);
+ s = js;
+ len = lng;
+ xtrc(1, "BDOC::ParseJson: s=%.10s len=%zd\n", s, len);
if (!s || !len) {
strcpy(g->Message, "Void JSON object");
@@ -147,30 +117,26 @@ PBVAL BDOC::ParseJson(PGLOBAL g, char* js, size_t lng, int* ptyp, bool* comma) {
if (s[0] == '[' && (s[1] == '\n' || (s[1] == '\r' && s[2] == '\n')))
pty[0] = false;
- s = js;
- len = lng;
-
try {
- bvp = (PBVAL)PlugSubAlloc(g, NULL, sizeof(BVAL));
- bvp->Type = TYPE_UNKNOWN;
- base = bvp;
+ Bvp = SubAllocVal(g);
+ Bvp->Type = TYPE_UNKNOWN;
for (i = 0; i < len; i++)
switch (s[i]) {
case '[':
- if (bvp->Type != TYPE_UNKNOWN)
- bvp->To_Val = ParseAsArray(g, i, pretty, ptyp);
+ if (Bvp->Type != TYPE_UNKNOWN)
+ Bvp->To_Val = ParseAsArray(g, i, pretty, ptyp);
else
- bvp->To_Val = ParseArray(g, ++i);
+ Bvp->To_Val = ParseArray(g, ++i);
- bvp->Type = TYPE_JAR;
+ Bvp->Type = TYPE_JAR;
break;
case '{':
- if (bvp->Type != TYPE_UNKNOWN) {
- bvp->To_Val = ParseAsArray(g, i, pretty, ptyp);
- bvp->Type = TYPE_JAR;
- } else if ((bvp->To_Val = ParseObject(g, ++i)))
- bvp->Type = TYPE_JOB;
+ if (Bvp->Type != TYPE_UNKNOWN) {
+ Bvp->To_Val = ParseAsArray(g, i, pretty, ptyp);
+ Bvp->Type = TYPE_JAR;
+ } else if ((Bvp->To_Val = ParseObject(g, ++i)))
+ Bvp->Type = TYPE_JOB;
else
throw 2;
@@ -181,7 +147,7 @@ PBVAL BDOC::ParseJson(PGLOBAL g, char* js, size_t lng, int* ptyp, bool* comma) {
case '\r':
break;
case ',':
- if (bvp->Type != TYPE_UNKNOWN && (pretty == 1 || pretty == 3)) {
+ if (Bvp->Type != TYPE_UNKNOWN && (pretty == 1 || pretty == 3)) {
if (comma)
*comma = true;
@@ -201,18 +167,18 @@ PBVAL BDOC::ParseJson(PGLOBAL g, char* js, size_t lng, int* ptyp, bool* comma) {
} // endif b
default:
- if (bvp->Type != TYPE_UNKNOWN) {
- bvp->To_Val = ParseAsArray(g, i, pretty, ptyp);
- bvp->Type = TYPE_JAR;
- } else if ((bvp->To_Val = MakeOff(base, ParseValue(g, i))))
- bvp->Type = TYPE_JVAL;
+ if (Bvp->Type != TYPE_UNKNOWN) {
+ Bvp->To_Val = ParseAsArray(g, i, pretty, ptyp);
+ Bvp->Type = TYPE_JAR;
+ } else if ((Bvp->To_Val = MOF(ParseValue(g, i))))
+ Bvp->Type = TYPE_JVAL;
else
throw 4;
break;
}; // endswitch s[i]
- if (bvp->Type == TYPE_UNKNOWN)
+ if (Bvp->Type == TYPE_UNKNOWN)
sprintf(g->Message, "Invalid Json string '%.*s'", MY_MIN((int)len, 50), s);
else if (ptyp && pretty == 3) {
*ptyp = 3; // Not recognized pretty
@@ -228,13 +194,13 @@ PBVAL BDOC::ParseJson(PGLOBAL g, char* js, size_t lng, int* ptyp, bool* comma) {
} catch (int n) {
if (trace(1))
htrc("Exception %d: %s\n", n, g->Message);
- bvp = NULL;
+ Bvp = NULL;
} catch (const char* msg) {
strcpy(g->Message, msg);
- bvp = NULL;
+ Bvp = NULL;
} // end catch
- return bvp;
+ return Bvp;
} // end of ParseJson
/***********************************************************************/
@@ -280,7 +246,7 @@ OFFSET BDOC::ParseArray(PGLOBAL g, int& i) {
throw 1;
} // endif level
- return MakeOff(base, vlp);
+ return MOF(firstvlp);
case '\n':
if (!b)
pty[0] = pty[1] = false;
@@ -294,7 +260,7 @@ OFFSET BDOC::ParseArray(PGLOBAL g, int& i) {
throw 1;
} else if (lastvlp) {
vlp = ParseValue(g, i);
- lastvlp->Next = MakeOff(base, vlp);
+ lastvlp->Next = MOF(vlp);
lastvlp = vlp;
} else
firstvlp = lastvlp = ParseValue(g, i);
@@ -305,26 +271,13 @@ OFFSET BDOC::ParseArray(PGLOBAL g, int& i) {
if (b) {
// Case of Pretty == 0
- return MakeOff(base, vlp);
+ return MOF(firstvlp);
} // endif b
throw ("Unexpected EOF in array");
} // end of ParseArray
/***********************************************************************/
-/* Sub-allocate and initialize a BPAIR. */
-/***********************************************************************/
-PBPR BDOC::SubAllocPair(PGLOBAL g, OFFSET key)
-{
- PBPR bpp = (PBPR)BsonSubAlloc(g, sizeof(BPAIR));
-
- bpp->Key = key;
- bpp->Vlp = 0;
- bpp->Next = 0;
- return bpp;
-} // end of SubAllocPair
-
-/***********************************************************************/
/* Parse a JSON Object. */
/***********************************************************************/
OFFSET BDOC::ParseObject(PGLOBAL g, int& i) {
@@ -342,7 +295,7 @@ OFFSET BDOC::ParseObject(PGLOBAL g, int& i) {
bpp = SubAllocPair(g, key);
if (lastbpp) {
- lastbpp->Next = MakeOff(base, bpp);
+ lastbpp->Next = MOF(bpp);
lastbpp = bpp;
} else
firstbpp = lastbpp = bpp;
@@ -356,7 +309,7 @@ OFFSET BDOC::ParseObject(PGLOBAL g, int& i) {
break;
case ':':
if (level == 1) {
- lastbpp->Vlp = MakeOff(base, ParseValue(g, ++i));
+ lastbpp->Vlp = MOF(ParseValue(g, ++i));
level = 2;
} else {
sprintf(g->Message, "Unexpected ':' near %.*s", ARGS);
@@ -378,7 +331,7 @@ OFFSET BDOC::ParseObject(PGLOBAL g, int& i) {
throw 2;
} // endif level
- return MakeOff(base, firstbpp);
+ return MOF(firstbpp);
case '\n':
pty[0] = pty[1] = false;
case '\r':
@@ -396,20 +349,6 @@ OFFSET BDOC::ParseObject(PGLOBAL g, int& i) {
} // end of ParseObject
/***********************************************************************/
-/* Sub-allocate and initialize a BVAL. */
-/***********************************************************************/
-PBVAL BDOC::SubAllocVal(PGLOBAL g)
-{
- PBVAL bvp = (PBVAL)BsonSubAlloc(g, sizeof(BVAL));
-
- bvp->To_Val = 0;
- bvp->Nd = 0;
- bvp->Type = TYPE_UNKNOWN;
- bvp->Next = 0;
- return bvp;
-} // end of SubAllocVal
-
-/***********************************************************************/
/* Parse a JSON Value. */
/***********************************************************************/
PBVAL BDOC::ParseValue(PGLOBAL g, int& i) {
@@ -505,7 +444,7 @@ OFFSET BDOC::ParseString(PGLOBAL g, int& i) {
case '"':
p[n++] = 0;
PlugSubAlloc(g, NULL, n);
- return MakeOff(base, p);
+ return MOF(p);
case '\\':
if (++i < len) {
if (s[i] == 'u') {
@@ -634,7 +573,7 @@ fin:
double* dvp = (double*)PlugSubAlloc(g, NULL, sizeof(double));
*dvp = dv;
- vlp->To_Val = MakeOff(base, dvp);
+ vlp->To_Val = MOF(dvp);
vlp->Type = TYPE_DBL;
} else {
vlp->F = (float)dv;
@@ -643,13 +582,13 @@ fin:
vlp->Nd = nd;
} else {
- long long iv = strtoll(buf, NULL, 10);
+ longlong iv = strtoll(buf, NULL, 10);
if (iv > INT_MAX32 || iv < INT_MIN32) {
- long long *llp = (long long*)PlugSubAlloc(g, NULL, sizeof(long long));
+ longlong *llp = (longlong*)PlugSubAlloc(g, NULL, sizeof(longlong));
*llp = iv;
- vlp->To_Val = MakeOff(base, llp);
+ vlp->To_Val = MOF(llp);
vlp->Type = TYPE_BINT;
} else {
vlp->N = (int)iv;
@@ -668,12 +607,11 @@ err:
} // end of ParseNumeric
/***********************************************************************/
-/* Serialize a JSON document tree: */
+/* Serialize a BJSON document tree: */
/***********************************************************************/
PSZ BDOC::Serialize(PGLOBAL g, PBVAL bvp, char* fn, int pretty) {
PSZ str = NULL;
bool b = false, err = true;
- JOUT* jp;
FILE* fs = NULL;
g->Message[0] = 0;
@@ -712,7 +650,7 @@ PSZ BDOC::Serialize(PGLOBAL g, PBVAL bvp, char* fn, int pretty) {
err |= SerializeObject(bvp->To_Val);
break;
case TYPE_JVAL:
- err = SerializeValue((PBVAL)MakePtr(base, bvp->To_Val));
+ err = SerializeValue(MVP(bvp->To_Val));
break;
default:
strcpy(g->Message, "Invalid json tree");
@@ -750,7 +688,7 @@ PSZ BDOC::Serialize(PGLOBAL g, PBVAL bvp, char* fn, int pretty) {
/***********************************************************************/
bool BDOC::SerializeArray(OFFSET arp, bool b) {
bool first = true;
- PBVAL vp = (PBVAL)MakePtr(base, arp);
+ PBVAL vp = MVP(arp);
if (b) {
if (jp->Prty()) {
@@ -764,7 +702,7 @@ bool BDOC::SerializeArray(OFFSET arp, bool b) {
} else if (jp->WriteChr('['))
return true;
- for (vp; vp; vp = (PBVAL)MakePtr(base, vp->Next)) {
+ for (vp; vp; vp = MVP(vp->Next)) {
if (first)
first = false;
else if ((!b || jp->Prty()) && jp->WriteChr(','))
@@ -780,7 +718,7 @@ bool BDOC::SerializeArray(OFFSET arp, bool b) {
if (SerializeValue(vp))
return true;
- } // endfor i
+ } // endfor vp
if (b && jp->Prty() == 1 && jp->WriteStr(EL))
return true;
@@ -793,22 +731,22 @@ bool BDOC::SerializeArray(OFFSET arp, bool b) {
/***********************************************************************/
bool BDOC::SerializeObject(OFFSET obp) {
bool first = true;
- PBPR prp = (PBPR)MakePtr(base, obp);
+ PBPR prp = MPP(obp);
if (jp->WriteChr('{'))
return true;
- for (prp; prp; prp = (PBPR)MakePtr(base, prp->Next)) {
+ for (prp; prp; prp = MPP(prp->Next)) {
if (first)
first = false;
else if (jp->WriteChr(','))
return true;
if (jp->WriteChr('"') ||
- jp->WriteStr((const char*)MakePtr(base, prp->Key)) ||
+ jp->WriteStr(MZP(prp->Key)) ||
jp->WriteChr('"') ||
jp->WriteChr(':') ||
- SerializeValue((PBVAL)MakePtr(base, prp->Vlp)))
+ SerializeValue(MVP(prp->Vlp)))
return true;
} // endfor i
@@ -831,18 +769,18 @@ bool BDOC::SerializeValue(PBVAL jvp) {
return jp->WriteStr(jvp->B ? "true" : "false");
case TYPE_STRG:
case TYPE_DTM:
- return jp->Escape((const char*)MakePtr(base, jvp->To_Val));
+ return jp->Escape(MZP(jvp->To_Val));
case TYPE_INTG:
sprintf(buf, "%d", jvp->N);
return jp->WriteStr(buf);
case TYPE_BINT:
- sprintf(buf, "%lld", *(long long*)MakePtr(base, jvp->To_Val));
+ sprintf(buf, "%lld", *(longlong*)MakePtr(Base, jvp->To_Val));
return jp->WriteStr(buf);
case TYPE_FLOAT:
sprintf(buf, "%.*f", jvp->Nd, jvp->F);
return jp->WriteStr(buf);
case TYPE_DBL:
- sprintf(buf, "%.*lf", jvp->Nd, *(double*)MakePtr(base, jvp->To_Val));
+ sprintf(buf, "%.*lf", jvp->Nd, *(double*)MakePtr(Base, jvp->To_Val));
return jp->WriteStr(buf);
case TYPE_NULL:
return jp->WriteStr("null");
@@ -854,84 +792,139 @@ bool BDOC::SerializeValue(PBVAL jvp) {
return true;
} // end of SerializeValue
-#if 0
-/* -------------------------- Class JOBJECT -------------------------- */
+/* --------------------------- Class BJSON --------------------------- */
+
+/***********************************************************************/
+/* Program for sub-allocating Bjson structures. */
+/***********************************************************************/
+void* BJSON::BsonSubAlloc(PGLOBAL g, size_t size)
+{
+ PPOOLHEADER pph; /* Points on area header. */
+ void* memp = g->Sarea;
+
+ size = ((size + 3) / 4) * 4; /* Round up size to multiple of 4 */
+ pph = (PPOOLHEADER)memp;
+
+ xtrc(16, "SubAlloc in %p size=%zd used=%zd free=%zd\n",
+ memp, size, pph->To_Free, pph->FreeBlk);
+
+ if (size > pph->FreeBlk) { /* Not enough memory left in pool */
+ sprintf(g->Message,
+ "Not enough memory for request of %zd (used=%zd free=%zd)",
+ size, pph->To_Free, pph->FreeBlk);
+ xtrc(1, "BsonSubAlloc: %s\n", g->Message);
+ throw(1234);
+ } /* endif size OS32 code */
+
+ // Do the suballocation the simplest way
+ memp = MakePtr(memp, pph->To_Free); /* Points to suballocated block */
+ pph->To_Free += size; /* New offset of pool free block */
+ pph->FreeBlk -= size; /* New size of pool free block */
+ xtrc(16, "Done memp=%p used=%zd free=%zd\n",
+ memp, pph->To_Free, pph->FreeBlk);
+ return memp;
+} /* end of BsonSubAlloc */
+
+/* ------------------------ Bobject functions ------------------------ */
+
+/***********************************************************************/
+/* Sub-allocate and initialize a BPAIR. */
+/***********************************************************************/
+PBPR BJSON::SubAllocPair(PGLOBAL g, OFFSET key, OFFSET val)
+{
+ PBPR bpp = (PBPR)BsonSubAlloc(g, sizeof(BPAIR));
+
+ bpp->Key = key;
+ bpp->Vlp = val;
+ bpp->Next = 0;
+ return bpp;
+} // end of SubAllocPair
/***********************************************************************/
/* Return the number of pairs in this object. */
/***********************************************************************/
-int JOBJECT::GetSize(bool b) {
+int BJSON::GetObjectSize(PBPR bop, bool b)
+{
int n = 0;
- for (PJPR jpp = First; jpp; jpp = jpp->Next)
+ for (PBPR brp = bop; brp; brp = MPP(brp->Next))
// If b return only non null pairs
- if (!b || jpp->Val && !jpp->Val->IsNull())
+ if (!b || (brp->Vlp && (MVP(brp->Vlp))->Type != TYPE_NULL))
n++;
return n;
-} // end of GetSize
+} // end of GetObjectSize
/***********************************************************************/
-/* Add a new pair to an Object. */
+/* Add a new pair to an Object and return it. */
/***********************************************************************/
-PJPR JOBJECT::AddPair(PGLOBAL g, PCSZ key) {
- PJPR jpp = (PJPR)PlugSubAlloc(g, NULL, sizeof(JPAIR));
+PBPR BJSON::AddPair(PGLOBAL g, PBPR bop, PSZ key, OFFSET val)
+{
+ PBPR brp, nrp = SubAllocPair(g, MOF(key), val);
- jpp->Key = key;
- jpp->Next = NULL;
- jpp->Val = NULL;
+ if (bop) {
+ for (brp = bop; brp->Next; brp = MPP(brp->Next));
- if (Last)
- Last->Next = jpp;
- else
- First = jpp;
+ brp->Next = MOF(nrp);
+ } else
+ bop = nrp;
- Last = jpp;
- return jpp;
+ return bop;
} // end of AddPair
/***********************************************************************/
-/* Return all keys as an array. */
+/* Return all object keys as an array. */
/***********************************************************************/
-PJAR JOBJECT::GetKeyList(PGLOBAL g) {
- PJAR jarp = new(g) JARRAY();
+PBVAL BJSON::GetKeyList(PGLOBAL g, PBPR bop)
+{
+ PBVAL bvp, lvp, fvp = NULL;
- for (PJPR jpp = First; jpp; jpp = jpp->Next)
- jarp->AddArrayValue(g, new(g) JVALUE(g, jpp->Key));
+ for (PBPR brp = bop; brp; brp = MPP(brp->Next))
+ if (fvp) {
+ bvp = SubAllocVal(g, brp->Key, TYPE_STRG);
+ lvp->Next = MOF(bvp);
+ lvp = bvp;
+ } else
+ lvp = fvp = SubAllocVal(g, brp->Key, TYPE_STRG);
- jarp->InitArray(g);
- return jarp;
+ return fvp;
} // end of GetKeyList
/***********************************************************************/
-/* Return all values as an array. */
+/* Return all object values as an array. */
/***********************************************************************/
-PJAR JOBJECT::GetValList(PGLOBAL g) {
- PJAR jarp = new(g) JARRAY();
+PBVAL BJSON::GetObjectValList(PGLOBAL g, PBPR bop)
+{
+ PBVAL bvp, lvp, fvp = NULL;
- for (PJPR jpp = First; jpp; jpp = jpp->Next)
- jarp->AddArrayValue(g, jpp->Val);
+ for (PBPR brp = bop; brp; brp = MPP(brp->Next))
+ if (fvp) {
+ bvp = DupVal(g, MVP(brp->Vlp));
+ lvp->Next = MOF(bvp);
+ lvp = bvp;
+ } else
+ lvp = fvp = DupVal(g, MVP(brp->Vlp));
- jarp->InitArray(g);
- return jarp;
-} // end of GetValList
+ return fvp;
+} // end of GetObjectValList
/***********************************************************************/
/* Get the value corresponding to the given key. */
/***********************************************************************/
-PJVAL JOBJECT::GetKeyValue(const char* key) {
- for (PJPR jp = First; jp; jp = jp->Next)
- if (!strcmp(jp->Key, key))
- return jp->Val;
+PBVAL BJSON::GetKeyValue(PBPR bop, PSZ key)
+{
+ for (PBPR brp = bop; brp; brp = MPP(brp->Next))
+ if (!strcmp(MZP(brp->Key), key))
+ return MVP(brp->Vlp);
return NULL;
-} // end of GetValue;
+} // end of GetKeyValue;
/***********************************************************************/
/* Return the text corresponding to all keys (XML like). */
/***********************************************************************/
-PSZ JOBJECT::GetText(PGLOBAL g, PSTRG text) {
- if (First) {
+PSZ BJSON::GetObjectText(PGLOBAL g, PBPR bop, PSTRG text) {
+ if (bop) {
bool b;
if (!text) {
@@ -944,7 +937,8 @@ PSZ JOBJECT::GetText(PGLOBAL g, PSTRG text) {
b = false;
} // endif text
- if (b && !First->Next && !strcmp(First->Key, "$date")) {
+#if 0
+ if (b && !bop->Next && !strcmp(MZP(bop->Key), "$date")) {
int i;
PSZ s;
@@ -964,228 +958,211 @@ PSZ JOBJECT::GetText(PGLOBAL g, PSTRG text) {
} // endif text
- } else for (PJPR jp = First; jp; jp = jp->Next) {
- jp->Val->GetText(g, text);
+ } else
+#endif // 0
- if (jp->Next)
+ for (PBPR brp = bop; brp; brp = MPP(brp->Next)) {
+ GetValueText(g, MVP(brp->Vlp), text);
+
+ if (brp->Next)
text->Append(' ');
- } // endfor jp
+ } // endfor brp
if (b) {
text->Trim();
return text->GetStr();
} // endif b
- } // endif First
+ } // endif bop
return NULL;
-} // end of GetText;
+} // end of GetObjectText;
/***********************************************************************/
-/* Merge two objects. */
+/* Set or add a value corresponding to the given key. */
/***********************************************************************/
-bool JOBJECT::Merge(PGLOBAL g, PJSON jsp) {
- if (jsp->GetType() != TYPE_JOB) {
- strcpy(g->Message, "Second argument is not an object");
- return true;
- } // endif Type
+PBPR BJSON::SetKeyValue(PGLOBAL g, PBPR bop, OFFSET bvp, PSZ key)
+{
+ PBPR brp = bop, prp = NULL;
+
+ if (brp) {
+ for (brp = bop; brp; brp = MPP(brp->Next))
+ if (!strcmp(MZP(brp->Key), key)) {
+ brp->Vlp = bvp;
+ break;
+ } else
+ prp = brp;
- PJOB jobp = (PJOB)jsp;
+ if (!brp)
+ prp->Vlp = MOF(SubAllocPair(g, MOF(key), bvp));
- for (PJPR jpp = jobp->First; jpp; jpp = jpp->Next)
- SetKeyValue(g, jpp->Val, jpp->Key);
+ } else
+ bop = SubAllocPair(g, MOF(key), bvp);
- return false;
-} // end of Marge;
+ // Return the first pair of this object
+ return bop;
+} // end of SetKeyValue
/***********************************************************************/
-/* Set or add a value corresponding to the given key. */
+/* Merge two objects. */
/***********************************************************************/
-void JOBJECT::SetKeyValue(PGLOBAL g, PJVAL jvp, PCSZ key) {
- PJPR jp;
-
- for (jp = First; jp; jp = jp->Next)
- if (!strcmp(jp->Key, key)) {
- jp->Val = jvp;
- break;
- } // endif key
+PBPR BJSON::MergeObject(PGLOBAL g, PBPR bop1, PBPR bop2)
+{
+ if (bop1)
+ for (PBPR brp = bop2; brp; brp = MPP(brp->Next))
+ SetKeyValue(g, bop1, brp->Vlp, MZP(brp->Key));
- if (!jp) {
- jp = AddPair(g, key);
- jp->Val = jvp;
- } // endif jp
+ else
+ bop1 = bop2;
-} // end of SetValue
+ return bop1;
+} // end of MergeObject;
/***********************************************************************/
/* Delete a value corresponding to the given key. */
/***********************************************************************/
-void JOBJECT::DeleteKey(PCSZ key) {
- PJPR jp, * pjp = &First;
+PBPR BJSON::DeleteKey(PBPR bop, PCSZ key)
+{
+ PBPR brp, pbrp = NULL;
+
+ for (brp = bop; brp; brp = MPP(brp->Next))
+ if (!strcmp(MZP(brp->Key), key)) {
+ if (pbrp) {
+ pbrp->Next = brp->Next;
+ return bop;
+ } else
+ return MPP(brp->Next);
- for (jp = First; jp; jp = jp->Next)
- if (!strcmp(jp->Key, key)) {
- *pjp = jp->Next;
- break;
} else
- pjp = &jp->Next;
+ pbrp = brp;
+ return bop;
} // end of DeleteKey
/***********************************************************************/
/* True if void or if all members are nulls. */
/***********************************************************************/
-bool JOBJECT::IsNull(void) {
- for (PJPR jp = First; jp; jp = jp->Next)
- if (!jp->Val->IsNull())
+bool BJSON::IsObjectNull(PBPR bop)
+{
+ for (PBPR brp = bop; brp; brp = MPP(brp->Next))
+ if (brp->Vlp && (MVP(brp->Vlp))->Type != TYPE_NULL)
return false;
return true;
-} // end of IsNull
+} // end of IsObjectNull
-/* -------------------------- Class JARRAY --------------------------- */
-
-/***********************************************************************/
-/* JARRAY constructor. */
-/***********************************************************************/
-JARRAY::JARRAY(void) : JSON() {
- Type = TYPE_JAR;
- Size = 0;
- Alloc = 0;
- First = Last = NULL;
- Mvals = NULL;
-} // end of JARRAY constructor
+/* ------------------------- Barray functions ------------------------ */
/***********************************************************************/
/* Return the number of values in this object. */
/***********************************************************************/
-int JARRAY::GetSize(bool b) {
- if (b) {
- // Return only non null values
- int n = 0;
-
- for (PJVAL jvp = First; jvp; jvp = jvp->Next)
- if (!jvp->IsNull())
- n++;
+int BJSON::GetArraySize(PBVAL bap, bool b)
+{
+ int n = 0;
- return n;
- } else
- return Size;
+ for (PBVAL bvp = bap; bvp; bvp = MVP(bvp->Next))
+ // If b, return only non null values
+ if (!b || bvp->Type != TYPE_NULL)
+ n++;
-} // end of GetSize
+ return n;
+} // end of GetArraySize
/***********************************************************************/
-/* Make the array of values from the values list. */
+/* Get the Nth value of an Array. */
/***********************************************************************/
-void JARRAY::InitArray(PGLOBAL g) {
- int i;
- PJVAL jvp, * pjvp = &First;
-
- for (Size = 0, jvp = First; jvp; jvp = jvp->Next)
- if (!jvp->Del)
- Size++;
-
- if (Size > Alloc) {
- // No need to realloc after deleting values
- Mvals = (PJVAL*)PlugSubAlloc(g, NULL, Size * sizeof(PJVAL));
- Alloc = Size;
- } // endif Size
-
- for (i = 0, jvp = First; jvp; jvp = jvp->Next)
- if (!jvp->Del) {
- Mvals[i++] = jvp;
- pjvp = &jvp->Next;
- Last = jvp;
- } else
- *pjvp = jvp->Next;
+PBVAL BJSON::GetArrayValue(PBVAL bap, int n)
+{
+ int i = 0;
-} // end of InitArray
+ for (PBVAL bvp = bap; bvp; bvp = MVP(bvp->Next))
+ if (i == n)
+ return bvp;
+ else
+ i++;
-/***********************************************************************/
-/* Get the Nth value of an Array. */
-/***********************************************************************/
-PJVAL JARRAY::GetArrayValue(int i) {
- if (Mvals && i >= 0 && i < Size)
- return Mvals[i];
- else
- return NULL;
-} // end of GetValue
+ return NULL;
+} // end of GetArrayValue
/***********************************************************************/
/* Add a Value to the Array Value list. */
/***********************************************************************/
-PJVAL JARRAY::AddArrayValue(PGLOBAL g, PJVAL jvp, int* x) {
- if (!jvp)
- jvp = new(g) JVALUE;
+PBVAL BJSON::AddArrayValue(PGLOBAL g, PBVAL bap, PBVAL nvp, int* x)
+{
+ if (!nvp)
+ nvp = SubAllocVal(g);
- if (x) {
+ if (bap) {
int i = 0, n = *x;
- PJVAL jp, * jpp = &First;
+ PBVAL bvp;
- for (jp = First; jp && i < n; i++, jp = *(jpp = &jp->Next));
-
- (*jpp) = jvp;
-
- if (!(jvp->Next = jp))
- Last = jvp;
-
- } else {
- if (!First)
- First = jvp;
- else if (Last == First)
- First->Next = Last = jvp;
- else
- Last->Next = jvp;
+ for (bvp = bap; bvp; bvp = MVP(bvp->Next), i++)
+ if (!bvp->Next || (x && i == n)) {
+ nvp->Next = bvp->Next;
+ bvp->Next = MOF(nvp);
+ break;
+ } // endif Next
- Last = jvp;
- Last->Next = NULL;
- } // endif x
+ } else
+ bap = nvp;
- return jvp;
-} // end of AddValue
+ return bap;
+} // end of AddArrayValue
/***********************************************************************/
/* Merge two arrays. */
/***********************************************************************/
-bool JARRAY::Merge(PGLOBAL g, PJSON jsp) {
- if (jsp->GetType() != TYPE_JAR) {
- strcpy(g->Message, "Second argument is not an array");
- return true;
- } // endif Type
-
- PJAR arp = (PJAR)jsp;
+PBVAL BJSON::MergeArray(PGLOBAL g, PBVAL bap1, PBVAL bap2)
+{
+ if (bap1) {
+ for (PBVAL bvp = bap2; bvp; bvp = MVP(bvp->Next))
+ AddArrayValue(g, bap1, bvp);
- for (int i = 0; i < arp->size(); i++)
- AddArrayValue(g, arp->GetArrayValue(i));
+ return bap1;
+ } else
+ return bap2;
- InitArray(g);
- return false;
-} // end of Merge
+} // end of MergeArray
/***********************************************************************/
-/* Set the nth Value of the Array Value list. */
+/* Set the nth Value of the Array Value list or add it. */
/***********************************************************************/
-bool JARRAY::SetArrayValue(PGLOBAL g, PJVAL jvp, int n) {
- int i = 0;
- PJVAL jp, * jpp = &First;
+PBVAL BJSON::SetArrayValue(PGLOBAL g, PBVAL bap, PBVAL nvp, int n)
+{
+ PBVAL bvp = bap, pvp = NULL;
+
+ if (bvp) {
+ for (int i = 0; bvp; i++, bvp = MVP(bvp->Next))
+ if (i == n) {
+ bvp->To_Val = nvp->To_Val;
+ bvp->Nd = nvp->Nd;
+ bvp->Type = nvp->Type;
+ return bap;
+ } else
+ pvp = bvp;
+
+ } // endif bap
+
+ if (!bvp) {
+ bvp = DupVal(g, nvp);
- for (jp = First; i < n; i++, jp = *(jpp = &jp->Next))
- if (!jp)
- *jpp = jp = new(g) JVALUE;
+ if (pvp)
+ pvp->Next = MOF(bvp);
+ else
+ bap = bvp;
+
+ } // endif bvp
- *jpp = jvp;
- jvp->Next = (jp ? jp->Next : NULL);
- return false;
+ return bap;
} // end of SetValue
/***********************************************************************/
/* Return the text corresponding to all values. */
/***********************************************************************/
-PSZ JARRAY::GetText(PGLOBAL g, PSTRG text) {
- if (First) {
+PSZ BJSON::GetArrayText(PGLOBAL g, PBVAL bap, PSTRG text) {
+ if (bap) {
bool b;
- PJVAL jp;
if (!text) {
text = new(g) STRING(g, 256);
@@ -1197,12 +1174,12 @@ PSZ JARRAY::GetText(PGLOBAL g, PSTRG text) {
text->Append('(');
b = false;
- }
+ } // endif text
- for (jp = First; jp; jp = jp->Next) {
- jp->GetText(g, text);
+ for (PBVAL bvp = bap; bvp; bvp = MVP(bvp->Next)) {
+ GetValueText(g, bvp, text);
- if (jp->Next)
+ if (bvp->Next)
text->Append(", ");
else if (!b)
text->Append(')');
@@ -1222,31 +1199,90 @@ PSZ JARRAY::GetText(PGLOBAL g, PSTRG text) {
/***********************************************************************/
/* Delete a Value from the Arrays Value list. */
/***********************************************************************/
-bool JARRAY::DeleteValue(int n) {
- PJVAL jvp = GetArrayValue(n);
+PBVAL BJSON::DeleteValue(PBVAL bap, int n)
+{
+ PBVAL bvp = bap, pvp = NULL;
- if (jvp) {
- jvp->Del = true;
- return false;
- } else
- return true;
+ if (bvp)
+ for (int i = 0; bvp; i++, bvp = MVP(bvp->Next))
+ if (i == n) {
+ if (pvp)
+ pvp->Next = bvp->Next;
+ else
+ bap = bvp;
+
+ break;
+ } // endif i
+ return bap;
} // end of DeleteValue
/***********************************************************************/
/* True if void or if all members are nulls. */
/***********************************************************************/
-bool JARRAY::IsNull(void) {
- for (int i = 0; i < Size; i++)
- if (!Mvals[i]->IsNull())
+bool BJSON::IsArrayNull(PBVAL bap)
+{
+ for (PBVAL bvp = bap; bvp; bvp = MVP(bvp->Next))
+ if (bvp->Type != TYPE_NULL)
return false;
return true;
} // end of IsNull
-/* -------------------------- Class JVALUE- -------------------------- */
+/* ------------------------- Bvalue functions ------------------------ */
+
+/***********************************************************************/
+/* Sub-allocate and clear a BVAL. */
+/***********************************************************************/
+PBVAL BJSON::SubAllocVal(PGLOBAL g)
+{
+ PBVAL bvp = (PBVAL)BsonSubAlloc(g, sizeof(BVAL));
+
+ bvp->To_Val = 0;
+ bvp->Nd = 0;
+ bvp->Type = TYPE_UNKNOWN;
+ bvp->Next = 0;
+ return bvp;
+} // end of SubAllocVal
+
+/***********************************************************************/
+/* Sub-allocate and initialize a BVAL as string. */
+/***********************************************************************/
+PBVAL BJSON::SubAllocVal(PGLOBAL g, OFFSET toval, JTYP type, short nd)
+{
+ PBVAL bvp = (PBVAL)BsonSubAlloc(g, sizeof(BVAL));
+
+ bvp->To_Val = toval;
+ bvp->Nd = nd;
+ bvp->Type = type;
+ bvp->Next = 0;
+ return bvp;
+} // end of SubAllocVal
/***********************************************************************/
+/* Allocate a BVALUE with a given string or numeric value. */
+/***********************************************************************/
+PBVAL BJSON::SubAllocVal(PGLOBAL g, PVAL valp)
+{
+ PBVAL vlp = SubAllocVal(g);
+ SetValue(g, vlp, valp);
+ vlp->Next = NULL;
+ return vlp;
+} // end of SubAllocVal
+
+/***********************************************************************/
+/* Sub-allocate and initialize a BVAL from another BVAL. */
+/***********************************************************************/
+PBVAL BJSON::DupVal(PGLOBAL g, PBVAL bvlp) {
+ PBVAL bvp = (PBVAL)BsonSubAlloc(g, sizeof(BVAL));
+
+ *bvp = *bvlp;
+ bvp->Next = 0;
+ return bvp;
+} // end of DupVal
+
+#if 0
+/***********************************************************************/
/* Constructor for a JVALUE. */
/***********************************************************************/
JVALUE::JVALUE(PJSON jsp) : JSON() {
@@ -1276,7 +1312,6 @@ JVALUE::JVALUE(PJSON jsp) : JSON() {
Type = TYPE_JVAL;
} // end of JVALUE constructor
-#if 0
/***********************************************************************/
/* Constructor for a JVALUE with a given string or numeric value. */
/***********************************************************************/
@@ -1289,18 +1324,7 @@ JVALUE::JVALUE(PGLOBAL g, PVL vlp) : JSON() {
} // end of JVALUE constructor
#endif // 0
-/***********************************************************************/
-/* Constructor for a JVALUE with a given string or numeric value. */
-/***********************************************************************/
-JVALUE::JVALUE(PGLOBAL g, PVAL valp) : JSON() {
- Jsp = NULL;
- //Val = NULL;
- SetValue(g, valp);
- Next = NULL;
- Del = false;
- Type = TYPE_JVAL;
-} // end of JVALUE constructor
-
+#if 0
/***********************************************************************/
/* Constructor for a given string. */
/***********************************************************************/
@@ -1339,13 +1363,31 @@ JTYP JVALUE::GetValType(void) {
return DataType;
} // end of GetValType
+#endif // 0
+
+/***********************************************************************/
+/* Return the size of value's value. */
+/***********************************************************************/
+int BJSON::GetSize(PBVAL vlp, bool b)
+{
+ switch (vlp->Type) {
+ case TYPE_JAR:
+ return GetArraySize(MVP(vlp->To_Val));
+ case TYPE_JOB:
+ return GetObjectSize(MPP(vlp->To_Val));
+ default:
+ return 1;
+ } // enswitch Type
+
+} // end of GetSize
/***********************************************************************/
/* Return the Value's Object value. */
/***********************************************************************/
-PJOB JVALUE::GetObject(void) {
- if (DataType == TYPE_JSON && Jsp->GetType() == TYPE_JOB)
- return (PJOB)Jsp;
+PBPR BJSON::GetObject(PBVAL vlp)
+{
+ if (vlp->Type == TYPE_JOB)
+ return MPP(vlp->To_Val);
return NULL;
} // end of GetObject
@@ -1353,24 +1395,41 @@ PJOB JVALUE::GetObject(void) {
/***********************************************************************/
/* Return the Value's Array value. */
/***********************************************************************/
-PJAR JVALUE::GetArray(void) {
- if (DataType == TYPE_JSON && Jsp->GetType() == TYPE_JAR)
- return (PJAR)Jsp;
+PBVAL BJSON::GetArray(PBVAL vlp)
+{
+ if (vlp->Type == TYPE_JAR)
+ return MVP(vlp->To_Val);
return NULL;
} // end of GetArray
/***********************************************************************/
-/* Return the Value's as a Value class. */
+/* Return the Value's as a Value struct. */
/***********************************************************************/
-PVAL JVALUE::GetValue(PGLOBAL g) {
- PVAL valp = NULL;
+PVAL BJSON::GetValue(PGLOBAL g, PBVAL vp)
+{
+ double d;
+ PVAL valp;
+ PBVAL vlp = vp->Type == TYPE_JVAL ? MVP(vp->To_Val) : vp;
- if (DataType != TYPE_JSON)
- if (DataType == TYPE_STRG)
- valp = AllocateValue(g, Strp, DataType, Nd);
- else
- valp = AllocateValue(g, &LLn, DataType, Nd);
+ switch (vlp->Type) {
+ case TYPE_STRG:
+ case TYPE_DBL:
+ case TYPE_BINT:
+ valp = AllocateValue(g, MP(vlp->To_Val), vlp->Type, vlp->Nd);
+ break;
+ case TYPE_INTG:
+ case TYPE_BOOL:
+ valp = AllocateValue(g, vlp, vlp->Type);
+ break;
+ case TYPE_FLOAT:
+ d = (double)vlp->F;
+ valp = AllocateValue(g, &d, TYPE_DOUBLE, vlp->Nd);
+ break;
+ default:
+ valp = NULL;
+ break;
+ } // endswitch Type
return valp;
} // end of GetValue
@@ -1378,16 +1437,30 @@ PVAL JVALUE::GetValue(PGLOBAL g) {
/***********************************************************************/
/* Return the Value's Integer value. */
/***********************************************************************/
-int JVALUE::GetInteger(void) {
- int n;
+int BJSON::GetInteger(PBVAL vp) {
+ int n;
+ PBVAL vlp = (vp->Type == TYPE_JVAL) ? MVP(vp->To_Val) : vp;
- switch (DataType) {
- case TYPE_INTG: n = N; break;
- case TYPE_DBL: n = (int)F; break;
+ switch (vlp->Type) {
+ case TYPE_INTG:
+ n = vlp->N;
+ break;
+ case TYPE_FLOAT:
+ n = (int)vlp->F;
+ break;
case TYPE_DTM:
- case TYPE_STRG: n = atoi(Strp); break;
- case TYPE_BOOL: n = (B) ? 1 : 0; break;
- case TYPE_BINT: n = (int)LLn; break;
+ case TYPE_STRG:
+ n = atoi(MZP(vlp->To_Val));
+ break;
+ case TYPE_BOOL:
+ n = (vlp->B) ? 1 : 0;
+ break;
+ case TYPE_BINT:
+ n = (int)*(longlong*)MP(vlp->To_Val);
+ break;
+ case TYPE_DBL:
+ n = (int)*(double*)MP(vlp->To_Val);
+ break;
default:
n = 0;
} // endswitch Type
@@ -1398,16 +1471,30 @@ int JVALUE::GetInteger(void) {
/***********************************************************************/
/* Return the Value's Big integer value. */
/***********************************************************************/
-long long JVALUE::GetBigint(void) {
- long long lln;
+longlong BJSON::GetBigint(PBVAL vp) {
+ longlong lln;
+ PBVAL vlp = (vp->Type == TYPE_JVAL) ? MVP(vp->To_Val) : vp;
- switch (DataType) {
- case TYPE_BINT: lln = LLn; break;
- case TYPE_INTG: lln = (long long)N; break;
- case TYPE_DBL: lln = (long long)F; break;
+ switch (vlp->Type) {
+ case TYPE_BINT:
+ lln = *(longlong*)MP(vlp->To_Val);
+ break;
+ case TYPE_INTG:
+ lln = (longlong)vlp->N;
+ break;
+ case TYPE_FLOAT:
+ lln = (longlong)vlp->F;
+ break;
+ case TYPE_DBL:
+ lln = (longlong)*(double*)MP(vlp->To_Val);
+ break;
case TYPE_DTM:
- case TYPE_STRG: lln = atoll(Strp); break;
- case TYPE_BOOL: lln = (B) ? 1 : 0; break;
+ case TYPE_STRG:
+ lln = atoll(MZP(vlp->To_Val));
+ break;
+ case TYPE_BOOL:
+ lln = (vlp->B) ? 1 : 0;
+ break;
default:
lln = 0;
} // endswitch Type
@@ -1418,16 +1505,31 @@ long long JVALUE::GetBigint(void) {
/***********************************************************************/
/* Return the Value's Double value. */
/***********************************************************************/
-double JVALUE::GetFloat(void) {
+double BJSON::GetDouble(PBVAL vp)
+{
double d;
+ PBVAL vlp = (vp->Type == TYPE_JVAL) ? MVP(vp->To_Val) : vp;
- switch (DataType) {
- case TYPE_DBL: d = F; break;
- case TYPE_BINT: d = (double)LLn; break;
- case TYPE_INTG: d = (double)N; break;
+ switch (vlp->Type) {
+ case TYPE_DBL:
+ d = *(double*)MP(vlp->To_Val);
+ break;
+ case TYPE_BINT:
+ d = (double)*(longlong*)MP(vlp->To_Val);
+ break;
+ case TYPE_INTG:
+ d = (double)vlp->N;
+ break;
+ case TYPE_FLOAT:
+ d = (double)vlp->F;
+ break;
case TYPE_DTM:
- case TYPE_STRG: d = atof(Strp); break;
- case TYPE_BOOL: d = (B) ? 1.0 : 0.0; break;
+ case TYPE_STRG:
+ d = atof(MZP(vlp->To_Val));
+ break;
+ case TYPE_BOOL:
+ d = (vlp->B) ? 1.0 : 0.0;
+ break;
default:
d = 0.0;
} // endswitch Type
@@ -1438,47 +1540,53 @@ double JVALUE::GetFloat(void) {
/***********************************************************************/
/* Return the Value's String value. */
/***********************************************************************/
-PSZ JVALUE::GetString(PGLOBAL g, char* buff) {
+PSZ BJSON::GetString(PGLOBAL g, PBVAL vp, char* buff)
+{
char buf[32];
char* p = (buff) ? buff : buf;
+ PBVAL vlp = (vp->Type == TYPE_JVAL) ? MVP(vp->To_Val) : vp;
- switch (DataType) {
+ switch (vlp->Type) {
case TYPE_DTM:
case TYPE_STRG:
- p = Strp;
+ p = MZP(vlp->To_Val);
break;
case TYPE_INTG:
- sprintf(p, "%d", N);
+ sprintf(p, "%d", vlp->N);
+ break;
+ case TYPE_FLOAT:
+ sprintf(p, "%.*f", vlp->Nd, vlp->F);
break;
case TYPE_BINT:
- sprintf(p, "%lld", LLn);
+ sprintf(p, "%lld", *(longlong*)MP(vlp->To_Val));
break;
case TYPE_DBL:
- sprintf(p, "%.*lf", Nd, F);
+ sprintf(p, "%.*lf", vlp->Nd, *(double*)MP(vlp->To_Val));
break;
case TYPE_BOOL:
- p = (char*)((B) ? "true" : "false");
+ p = (PSZ)((vlp->B) ? "true" : "false");
break;
case TYPE_NULL:
- p = (char*)"null";
+ p = (PSZ)"null";
break;
default:
p = NULL;
} // endswitch Type
-
- return (p == buf) ? (char*)PlugDup(g, buf) : p;
+ return (p == buf) ? (PSZ)PlugDup(g, buf) : p;
} // end of GetString
/***********************************************************************/
/* Return the Value's String value. */
/***********************************************************************/
-PSZ JVALUE::GetText(PGLOBAL g, PSTRG text) {
- if (DataType == TYPE_JSON)
- return Jsp->GetText(g, text);
+PSZ BJSON::GetValueText(PGLOBAL g, PBVAL vlp, PSTRG text) {
+ if (vlp->Type == TYPE_JOB)
+ return GetObjectText(g, MPP(vlp->To_Val), text);
+ else if (vlp->Type == TYPE_JAR)
+ return GetArrayText(g, MVP(vlp->To_Val), text);
char buff[32];
- PSZ s = (DataType == TYPE_NULL) ? NULL : GetString(g, buff);
+ PSZ s = (vlp->Type == TYPE_NULL) ? NULL : GetString(g, vlp, buff);
if (s)
text->Append(s);
@@ -1488,60 +1596,81 @@ PSZ JVALUE::GetText(PGLOBAL g, PSTRG text) {
return NULL;
} // end of GetText
-void JVALUE::SetValue(PJSON jsp) {
- if (DataType == TYPE_JSON && jsp->GetType() == TYPE_JVAL) {
- Jsp = jsp->GetJsp();
- Nd = ((PJVAL)jsp)->Nd;
- DataType = ((PJVAL)jsp)->DataType;
- // Val = ((PJVAL)jsp)->GetVal();
- } else {
- Jsp = jsp;
- DataType = TYPE_JSON;
- } // endif Type
+void BJSON::SetValueObj(PBVAL vlp, PBPR bop)
+{
+ vlp->To_Val = MOF(bop);
+ vlp->Type = TYPE_JOB;
+} // end of SetValueObj;
+void BJSON::SetValueArr(PBVAL vlp, PBVAL bap)
+{
+ vlp->To_Val = MOF(bap);
+ vlp->Type = TYPE_JAR;
} // end of SetValue;
-void JVALUE::SetValue(PGLOBAL g, PVAL valp) {
- //if (!Val)
- // Val = AllocVal(g, TYPE_VAL);
+void BJSON::SetValueVal(PBVAL vlp, PBVAL vp)
+{
+ vlp->To_Val = vp->To_Val;
+ vlp->Nd = vp->Nd;
+ vlp->Type = vp->Type;
+} // end of SetValue;
+void BJSON::SetValue(PGLOBAL g, PBVAL vlp, PVAL valp)
+{
if (!valp || valp->IsNull()) {
- DataType = TYPE_NULL;
+ vlp->Type = TYPE_NULL;
} else switch (valp->GetType()) {
case TYPE_DATE:
if (((DTVAL*)valp)->IsFormatted())
- Strp = valp->GetCharValue();
+ vlp->To_Val = MOF(valp->GetCharValue());
else {
char buf[32];
- Strp = PlugDup(g, valp->GetCharString(buf));
+ vlp->To_Val = MOF(PlugDup(g, valp->GetCharString(buf)));
} // endif Formatted
- DataType = TYPE_DTM;
+ vlp->Type = TYPE_DTM;
break;
case TYPE_STRING:
- Strp = valp->GetCharValue();
- DataType = TYPE_STRG;
+ vlp->To_Val = MOF(valp->GetCharValue());
+ vlp->Type = TYPE_STRG;
break;
case TYPE_DOUBLE:
case TYPE_DECIM:
- F = valp->GetFloatValue();
+ vlp->Nd = (IsTypeNum(valp->GetType())) ? valp->GetValPrec() : 0;
- if (IsTypeNum(valp->GetType()))
- Nd = valp->GetValPrec();
+ if (vlp->Nd <= 6) {
+ vlp->F = (float)valp->GetFloatValue();
+ vlp->Type = TYPE_FLOAT;
+ } else {
+ double *dp = (double*)PlugSubAlloc(g, NULL, sizeof(double));
+
+ *dp = valp->GetFloatValue();
+ vlp->To_Val = MOF(dp);
+ vlp->Type = TYPE_DBL;
+ } // endif Nd
- DataType = TYPE_DBL;
break;
case TYPE_TINY:
- B = valp->GetTinyValue() != 0;
- DataType = TYPE_BOOL;
+ vlp->B = valp->GetTinyValue() != 0;
+ vlp->Type = TYPE_BOOL;
case TYPE_INT:
- N = valp->GetIntValue();
- DataType = TYPE_INTG;
+ vlp->N = valp->GetIntValue();
+ vlp->Type = TYPE_INTG;
break;
case TYPE_BIGINT:
- LLn = valp->GetBigintValue();
- DataType = TYPE_BINT;
+ if (valp->GetBigintValue() >= INT_MIN32 &&
+ valp->GetBigintValue() <= INT_MAX32) {
+ vlp->N = valp->GetIntValue();
+ vlp->Type = TYPE_INTG;
+ } else {
+ longlong* llp = (longlong*)PlugSubAlloc(g, NULL, sizeof(longlong));
+
+ *llp = valp->GetBigintValue();
+ vlp->To_Val = MOF(llp);
+ vlp->Type = TYPE_BINT;
+ } // endif BigintValue
+
break;
default:
sprintf(g->Message, "Unsupported typ %d\n", valp->GetType());
@@ -1553,49 +1682,76 @@ void JVALUE::SetValue(PGLOBAL g, PVAL valp) {
/***********************************************************************/
/* Set the Value's value as the given integer. */
/***********************************************************************/
-void JVALUE::SetInteger(PGLOBAL g, int n) {
- N = n;
- DataType = TYPE_INTG;
+void BJSON::SetInteger(PBVAL vlp, int n)
+{
+ vlp->N = n;
+ vlp->Type = TYPE_INTG;
} // end of SetInteger
/***********************************************************************/
/* Set the Value's Boolean value as a tiny integer. */
/***********************************************************************/
-void JVALUE::SetBool(PGLOBAL g, bool b) {
- B = b;
- DataType = TYPE_BOOL;
+void BJSON::SetBool(PBVAL vlp, bool b)
+{
+ vlp->B = b;
+ vlp->Type = TYPE_BOOL;
} // end of SetTiny
/***********************************************************************/
/* Set the Value's value as the given big integer. */
/***********************************************************************/
-void JVALUE::SetBigint(PGLOBAL g, long long ll) {
- LLn = ll;
- DataType = TYPE_BINT;
+void BJSON::SetBigint(PGLOBAL g, PBVAL vlp, longlong ll)
+{
+ if (ll >= INT_MIN32 && ll <= INT_MAX32) {
+ vlp->N = (int)ll;
+ vlp->Type = TYPE_INTG;
+ } else {
+ longlong* llp = (longlong*)PlugSubAlloc(g, NULL, sizeof(longlong));
+
+ *llp = ll;
+ vlp->To_Val = MOF(llp);
+ vlp->Type = TYPE_BINT;
+ } // endif ll
+
} // end of SetBigint
/***********************************************************************/
/* Set the Value's value as the given DOUBLE. */
/***********************************************************************/
-void JVALUE::SetFloat(PGLOBAL g, double f) {
- F = f;
- Nd = 6;
- DataType = TYPE_DBL;
+void BJSON::SetFloat(PBVAL vlp, double f) {
+ vlp->F = (float)f;
+ vlp->Nd = 6;
+ vlp->Type = TYPE_FLOAT;
} // end of SetFloat
/***********************************************************************/
/* Set the Value's value as the given string. */
/***********************************************************************/
-void JVALUE::SetString(PGLOBAL g, PSZ s, int ci) {
- Strp = s;
- Nd = ci;
- DataType = TYPE_STRG;
+void BJSON::SetString(PBVAL vlp, PSZ s, int ci) {
+ vlp->To_Val = MOF(s);
+ vlp->Nd = ci;
+ vlp->Type = TYPE_STRG;
} // end of SetString
/***********************************************************************/
/* True when its JSON or normal value is null. */
/***********************************************************************/
-bool JVALUE::IsNull(void) {
- return (DataType == TYPE_JSON) ? Jsp->IsNull() : DataType == TYPE_NULL;
-} // end of IsNull
-#endif // 0
+bool BJSON::IsValueNull(PBVAL vlp) {
+ bool b;
+
+ switch (vlp->Type) {
+ case TYPE_NULL:
+ b = true;
+ break;
+ case TYPE_JOB:
+ b = IsObjectNull(MPP(vlp->To_Val));
+ break;
+ case TYPE_JAR:
+ b = IsArrayNull(MVP(vlp->To_Val));
+ break;
+ default:
+ b = false;
+ } // endswitch Type
+
+ return b;
+ } // end of IsNull
diff --git a/storage/connect/bson.h b/storage/connect/bson.h
index 7cf0820dc7a..9f5f44d073c 100644
--- a/storage/connect/bson.h
+++ b/storage/connect/bson.h
@@ -16,20 +16,25 @@
#define X
#endif
+#define ARGS MY_MIN(24,(int)len-i),s+MY_MAX(i-3,0)
+#define MOF(X) MakeOff(Base, X)
+#define MP(X) MakePtr(Base, X)
+#define MPP(X) (PBPR)MakePtr(Base, X)
+#define MVP(X) (PBVAL)MakePtr(Base, X)
+#define MZP(X) (PSZ)MakePtr(Base, X)
+#define LLN(X) *(longlong*)MakePtr(Base, X)
+#define DBL(X) *(double*)MakePtr(Base, X)
+
class BDOC;
class BOUT;
-//class JSON;
+class BJSON;
typedef class BDOC* PBDOC;
-//typedef class BJSON* PBSON;
-
-// BSON size should be equal on Linux and Windows
-#define BMX 255
-
-typedef uint OFFSET;
+typedef class BJSON* PBJSON;
+typedef uint OFFSET;
/***********************************************************************/
-/* Structure JVALUE. */
+/* Structure BVAL. Binary representation of a JVALUE. */
/***********************************************************************/
typedef struct _jvalue {
union {
@@ -39,12 +44,12 @@ typedef struct _jvalue {
bool B; // A boolean value True or false (0)
};
short Nd; // Number of decimals
- JTYP Type; // The value type
+ short Type; // The value type
OFFSET Next; // Offset to the next value in array
} BVAL, *PBVAL; // end of struct BVALUE
/***********************************************************************/
-/* Structure JPAIR. The pairs of a json Object. */
+/* Structure BPAIR. The pairs of a json Object. */
/***********************************************************************/
typedef struct _jpair {
OFFSET Key; // Offset to this pair key name
@@ -52,26 +57,6 @@ typedef struct _jpair {
OFFSET Next; // Offset to the next pair in object
} BPAIR, *PBPR; // end of struct BPAIR
-#if 0
-/***********************************************************************/
-/* Structure used to return binary json to Json UDF functions. */
-/* (should be moved to jsonudf.h). */
-/***********************************************************************/
-typedef struct _JsonBin {
- char Msg[BMX + 1];
- char *Filename;
- PGLOBAL G;
- int Pretty;
- ulong Reslen;
- my_bool Changed;
- PBSON Top;
- PBSON Jsp;
- PBJN Bsp;
-} BJSON, *PBJN ; // end of struct BJSON
-
-PBJN JbinAlloc(PGLOBAL g, UDF_ARGS* args, ulong len, PJSON jsp);
-#endif // 0
-
char* NextChr(PSZ s, char sep);
char* GetJsonNull(void);
const char* GetFmt(int type, bool un);
@@ -79,15 +64,84 @@ const char* GetFmt(int type, bool un);
DllExport bool IsNum(PSZ s);
/***********************************************************************/
-/* Class JDOC. The class for parsing and serializing json documents. */
+/* Class BJSON. The class handling all BJSON operations. */
/***********************************************************************/
-class BDOC : public BLOCK {
+class BJSON : public BLOCK {
public:
- BDOC(void);
+ // Constructor
+ BJSON(void* base, PBVAL vp = NULL) { Base = base; Bvp = vp; }
- void *BsonSubAlloc(PGLOBAL g, size_t size);
- PBPR SubAllocPair(PGLOBAL g, OFFSET key);
+ void* GetBase(void) { return Base; }
+
+ // SubAlloc functions
+ void* BsonSubAlloc(PGLOBAL g, size_t size);
+ PBPR SubAllocPair(PGLOBAL g, OFFSET key, OFFSET val = 0);
PBVAL SubAllocVal(PGLOBAL g);
+ PBVAL SubAllocVal(PGLOBAL g, OFFSET toval, JTYP type = TYPE_UNKNOWN, short nd = 0);
+ PBVAL SubAllocVal(PGLOBAL g, PVAL valp);
+ PBVAL DupVal(PGLOBAL g, PBVAL bvp);
+
+ // Array functions
+ int GetArraySize(PBVAL bap, bool b = false);
+ PBVAL GetArrayValue(PBVAL bap, int i);
+ PSZ GetArrayText(PGLOBAL g, PBVAL bap, PSTRG text);
+ PBVAL MergeArray(PGLOBAL g, PBVAL bap1,PBVAL bap2);
+ PBVAL DeleteValue(PBVAL bap, int n);
+ PBVAL AddArrayValue(PGLOBAL g, PBVAL bap, PBVAL nvp = NULL, int* x = NULL);
+ PBVAL SetArrayValue(PGLOBAL g, PBVAL bap, PBVAL nvp, int n);
+ bool IsArrayNull(PBVAL bap);
+
+ // Object functions
+ int GetObjectSize(PBPR bop, bool b = false);
+ PSZ GetObjectText(PGLOBAL g, PBPR bop, PSTRG text);
+ PBPR MergeObject(PGLOBAL g, PBPR bop1, PBPR bop2);
+ PBPR AddPair(PGLOBAL g, PBPR bop, PSZ key, OFFSET val = 0);
+ PBVAL GetKeyValue(PBPR bop, PSZ key);
+ PBVAL GetKeyList(PGLOBAL g, PBPR bop);
+ PBVAL GetObjectValList(PGLOBAL g, PBPR bop);
+ PBPR SetKeyValue(PGLOBAL g, PBPR bop, OFFSET bvp, PSZ key);
+ PBPR DeleteKey(PBPR bop, PCSZ k);
+ bool IsObjectNull(PBPR bop);
+
+ // Value functions
+ int GetSize(PBVAL vlp, bool b = false);
+ PBPR GetObject(PBVAL vlp);
+ PBVAL GetArray(PBVAL vlp);
+ //PJSON GetJsp(void) { return (DataType == TYPE_JSON ? Jsp : NULL); }
+ PSZ GetValueText(PGLOBAL g, PBVAL vlp, PSTRG text);
+ //inline PJSON GetJson(void) { return (DataType == TYPE_JSON ? Jsp : this); }
+ PSZ GetString(PGLOBAL g, PBVAL vp, char* buff = NULL);
+ int GetInteger(PBVAL vp);
+ long long GetBigint(PBVAL vp);
+ double GetDouble(PBVAL vp);
+ PVAL GetValue(PGLOBAL g, PBVAL vp);
+ void SetValueObj(PBVAL vlp, PBPR bop);
+ void SetValueArr(PBVAL vlp, PBVAL bap);
+ void SetValueVal(PBVAL vlp, PBVAL vp);
+ void SetValue(PGLOBAL g, PBVAL vlp, PVAL valp);
+ void SetString(PBVAL vlp, PSZ s, int ci = 0);
+ void SetInteger(PBVAL vlp, int n);
+ void SetBigint(PGLOBAL g, PBVAL vlp, longlong ll);
+ void SetFloat(PBVAL vlp, double f);
+ void SetBool(PBVAL vlp, bool b);
+ bool IsValueNull(PBVAL vlp);
+
+ // Members
+ PBVAL Bvp;
+ void* Base;
+
+protected:
+ // Default constructor not to be used
+ BJSON(void) {}
+}; // end of class BJSON
+
+/***********************************************************************/
+/* Class JDOC. The class for parsing and serializing json documents. */
+/***********************************************************************/
+class BDOC : public BJSON {
+public:
+ BDOC(void *);
+
PBVAL ParseJson(PGLOBAL g, char* s, size_t n, int* prty = NULL, bool* b = NULL);
PSZ Serialize(PGLOBAL g, PBVAL bvp, char* fn, int pretty);
@@ -98,73 +152,22 @@ protected:
OFFSET ParseString(PGLOBAL g, int& i);
void ParseNumeric(PGLOBAL g, int& i, PBVAL bvp);
OFFSET ParseAsArray(PGLOBAL g, int& i, int pretty, int* ptyp);
- bool SerializeArray(OFFSET arp, bool b);
- bool SerializeObject(OFFSET obp);
- bool SerializeValue(PBVAL vp);
+ bool SerializeArray(OFFSET arp, bool b);
+ bool SerializeObject(OFFSET obp);
+ bool SerializeValue(PBVAL vp);
// Members used when parsing and serializing
-private:
JOUT* jp; // Used with serialize
- void* base; // The base for making offsets or pointers
char* s; // The Json string to parse
int len; // The Json string length
bool pty[3]; // Used to guess what pretty is
+
+ // Default constructor not to be used
+ BDOC(void) {}
}; // end of class BDOC
#if 0
/***********************************************************************/
-/* Class BJSON. The class handling all BSON operations. */
-/***********************************************************************/
-class BJSON : public BLOCK {
-public:
- // Constructor
- BJSON(PBVAL vp, void* base) { Vlp = vp; Base = base; }
-
- // Array functions
- int GetSize(bool b);
- PBVAL GetArrayValue(int i);
- PSZ GetText(PGLOBAL g, PSTRG text);
- bool Merge(PGLOBAL g, PBVAL jsp);
- bool DeleteValue(int n);
- PBVAL AddArrayValue(PGLOBAL g, PBVAL jvp = NULL, int* x = NULL);
- bool SetArrayValue(PGLOBAL g, PBVAL jvp, int i);
-
- // Object functions
- int GetObjectSize(PBPR prp, bool b);
- PSZ GetObjectText(PGLOBAL g, PBPR prp, PSTRG text);
- bool MergeObject(PGLOBAL g, PBPR prp);
- PJPR AddPair(PGLOBAL g, PCSZ key);
- PJVAL GetKeyValue(const char* key);
- PJAR GetKeyList(PGLOBAL g);
- PJAR GetValList(PGLOBAL g);
- void SetKeyValue(PGLOBAL g, PBVAL jvp, PCSZ key);
- void DeleteKey(PCSZ k);
-
- // Value functions
- PBPR GetObject(void);
- PBVAL GetArray(void);
- PJSON GetJsp(void) { return (DataType == TYPE_JSON ? Jsp : NULL); }
- PSZ GetValueText(PGLOBAL g, PSTRG text);
- inline PJSON GetJson(void) { return (DataType == TYPE_JSON ? Jsp : this); }
- PSZ GetString(PGLOBAL g, char* buff = NULL);
- int GetInteger(void);
- long long GetBigint(void);
- double GetFloat(void);
- PVAL GetValue(PGLOBAL g);
- void SetValue(PJSON jsp);
- void SetValue(PGLOBAL g, PVAL valp);
- void SetString(PGLOBAL g, PSZ s, int ci = 0);
- void SetInteger(PGLOBAL g, int n);
- void SetBigint(PGLOBAL g, longlong ll);
- void SetFloat(PGLOBAL g, double f);
- void SetBool(PGLOBAL g, bool b);
-
- // Members
- PBVAL Vlp;
- void* Base;
-}; // end of class BJSON
-
-/***********************************************************************/
/* Class JOBJECT: contains a list of value pairs. */
/***********************************************************************/
class JOBJECT : public JSON {
diff --git a/storage/connect/json.h b/storage/connect/json.h
index c5251af01a9..5ba4d7b3dbd 100644
--- a/storage/connect/json.h
+++ b/storage/connect/json.h
@@ -15,10 +15,7 @@
#define X
#endif
-// Required by some compilers
-enum JTYP : short;
-
-enum JTYP : short {
+enum JTYP {
TYPE_NULL = TYPE_VOID,
TYPE_STRG = TYPE_STRING,
TYPE_DBL = TYPE_DOUBLE,
@@ -48,9 +45,6 @@ typedef class JVALUE *PJVAL;
typedef class JOBJECT *PJOB;
typedef class JARRAY *PJAR;
-// BSON size should be equal on Linux and Windows
-#define BMX 255
-typedef struct BSON *PBSON;
typedef struct JPAIR *PJPR;
//typedef struct VAL *PVL;
@@ -63,39 +57,6 @@ struct JPAIR {
PJPR Next; // To the next pair
}; // end of struct JPAIR
-#if 0
-/***********************************************************************/
-/* Structure VAL (string, int, float, bool or null) */
-/***********************************************************************/
-struct VAL {
- union {
- char *Strp; // Ptr to a string
- int N; // An integer value
- long long LLn; // A big integer value
- double F; // A float value
- bool B; // True or false
- };
- int Nd; // Decimal number
- JTYP Type; // The value type
-}; // end of struct VAL
-#endif // 0
-
-/***********************************************************************/
-/* Structure used to return binary json to Json UDF functions. */
-/***********************************************************************/
-struct BSON {
- char Msg[BMX + 1];
- char *Filename;
- PGLOBAL G;
- int Pretty;
- ulong Reslen;
- my_bool Changed;
- PJSON Top;
- PJSON Jsp;
- PBSON Bsp;
-}; // end of struct BSON
-
-PBSON JbinAlloc(PGLOBAL g, UDF_ARGS* args, ulong len, PJSON jsp);
//PVL AllocVal(PGLOBAL g, JTYP type);
char *NextChr(PSZ s, char sep);
char *GetJsonNull(void);
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
index c9f0ea9239a..0012b3d6bdd 100644
--- a/storage/connect/jsonudf.cpp
+++ b/storage/connect/jsonudf.cpp
@@ -63,7 +63,7 @@ static PJSNX JsnxNew(PGLOBAL g, PJSON jsp, int type, int len)
return jsx;
} /* end of JsnxNew */
- /* ----------------------------------- JSNX ------------------------------------ */
+/* ----------------------------------- JSNX ------------------------------------ */
/*********************************************************************************/
/* JSNX public constructor. */
@@ -1186,6 +1186,7 @@ static my_bool JsonSubSet(PGLOBAL g)
pph->To_Free = (g->Saved_Size) ? g->Saved_Size : (size_t)sizeof(POOLHEADER);
pph->FreeBlk = g->Sarea_Size - pph->To_Free;
+ g->Saved_Size = 0;
return FALSE;
} /* end of JsonSubSet */
@@ -6558,3 +6559,1476 @@ long long countin(UDF_INIT *initid, UDF_ARGS *args, char *result,
free(str2);
return n;
} // end of countin
+
+/* --------------------------- New Testing BJSON Stuff --------------------------*/
+
+/*********************************************************************************/
+/* SubAlloc a new BJNX class with protection against memory exhaustion. */
+/*********************************************************************************/
+static PBJNX BjnxNew(PGLOBAL g, PBVAL vlp, int type, int len) {
+ PBJNX bjnx;
+
+ try {
+ bjnx = new(g) BJNX(g, vlp, type, len);
+ } catch (...) {
+ if (trace(1023))
+ htrc("%s\n", g->Message);
+
+ PUSH_WARNING(g->Message);
+ bjnx = NULL;
+ } // end try/catch
+
+ return bjnx;
+} /* end of BjnxNew */
+
+/* ----------------------------------- BSNX ------------------------------------ */
+
+/*********************************************************************************/
+/* BSNX public constructor. */
+/*********************************************************************************/
+BJNX::BJNX(PGLOBAL g, PBVAL row, int type, int len, int prec, my_bool wr)
+ : BDOC(g->Sarea)
+{
+ Row = row;
+ Bvalp = NULL;
+ Jpnp = NULL;
+ Jp = NULL;
+ Nodes = NULL;
+ Value = AllocateValue(g, type, len, prec);
+ MulVal = NULL;
+ Jpath = NULL;
+ Buf_Type = type;
+ Long = len;
+ Prec = prec;
+ Nod = 0;
+ Xnod = -1;
+ K = 0;
+ I = -1;
+ Imax = 9;
+ B = 0;
+ Xpd = false;
+ Parsed = false;
+ Found = false;
+ Wr = wr;
+ Jb = false;
+} // end of BJNX constructor
+
+/*********************************************************************************/
+/* SetJpath: set and parse the json path. */
+/*********************************************************************************/
+my_bool BJNX::SetJpath(PGLOBAL g, char* path, my_bool jb) {
+ // Check Value was allocated
+ if (!Value)
+ return true;
+
+ Value->SetNullable(true);
+ Jpath = path;
+
+ // Parse the json path
+ Parsed = false;
+ Nod = 0;
+ Jb = jb;
+ return ParseJpath(g);
+} // end of SetJpath
+
+/*********************************************************************************/
+/* Analyse array processing options. */
+/*********************************************************************************/
+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];
+
+ if (*p) {
+ if (p[n - 1] == ']') {
+ p[--n] = 0;
+ } else if (!IsNum(p)) {
+ // Wrong array specification
+ sprintf(g->Message, "Invalid array specification %s", p);
+ return true;
+ } // endif p
+
+ } else
+ b = true;
+
+ // To check whether a numeric Rank was specified
+ dg = IsNum(p);
+
+ if (!n) {
+ // Default specifications
+ if (jnp->Op != OP_EXP) {
+ 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;
+ } else if (!Value->IsTypeNum()) {
+ jnp->CncVal = AllocateValue(g, PlugDup(g, ", "), TYPE_STRING);
+ jnp->Op = OP_CNC;
+ } else
+ jnp->Op = OP_ADD;
+
+ } // endif OP
+
+ } else if (dg) {
+ // 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) {
+ case '+': jnp->Op = OP_ADD; break;
+ case 'x': jnp->Op = OP_MULT; break;
+ case '>': jnp->Op = OP_MAX; break;
+ case '<': jnp->Op = OP_MIN; break;
+ case '!': jnp->Op = OP_SEP; break; // Average
+ case '#': jnp->Op = OP_NUM; break;
+ case '*': // Expand this array
+ strcpy(g->Message, "Expand not supported by this function");
+ return true;
+ default:
+ sprintf(g->Message, "Invalid function specification %c", *p);
+ return true;
+ } // endswitch *p
+
+ } else if (*p == '"' && p[n - 1] == '"') {
+ // This is a concat specification
+ jnp->Op = OP_CNC;
+
+ if (n > 2) {
+ // Set concat intermediate string
+ p[n - 1] = 0;
+
+ if (trace(1))
+ htrc("Concat string=%s\n", p + 1);
+
+ jnp->CncVal = AllocateValue(g, p + 1, TYPE_STRING);
+ } // endif n
+
+ } else {
+ strcpy(g->Message, "Wrong array specification");
+ return true;
+ } // endif's
+
+ // For calculated arrays, a local Value must be used
+ switch (jnp->Op) {
+ case OP_NUM:
+ jnp->Valp = AllocateValue(g, TYPE_INT);
+ break;
+ case OP_ADD:
+ case OP_MULT:
+ case OP_SEP:
+ if (!IsTypeChar(Buf_Type))
+ jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision());
+ else
+ jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2);
+
+ break;
+ case OP_MIN:
+ case OP_MAX:
+ jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision());
+ break;
+ case OP_CNC:
+ if (IsTypeChar(Buf_Type))
+ jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision());
+ else
+ jnp->Valp = AllocateValue(g, TYPE_STRING, 512);
+
+ break;
+ default:
+ break;
+ } // endswitch Op
+
+ if (jnp->Valp)
+ MulVal = AllocateValue(g, jnp->Valp);
+
+ return false;
+} // end of SetArrayOptions
+
+/*********************************************************************************/
+/* Parse the eventual passed Jpath information. */
+/* This information can be specified in the Fieldfmt column option when */
+/* creating the table. It permits to indicate the position of the node */
+/* corresponding to that column. */
+/*********************************************************************************/
+my_bool BJNX::ParseJpath(PGLOBAL g) {
+ char* p, * p1 = NULL, * p2 = NULL, * pbuf = NULL;
+ int i;
+ my_bool a, mul = false;
+
+ if (Parsed)
+ return false; // Already done
+ else if (!Jpath)
+ // Jpath = Name;
+ return true;
+
+ if (trace(1))
+ htrc("ParseJpath %s\n", SVP(Jpath));
+
+ if (!(pbuf = PlgDBDup(g, Jpath)))
+ return true;
+
+ if (*pbuf == '$') pbuf++;
+ if (*pbuf == '.') pbuf++;
+ if (*pbuf == '[') p1 = pbuf++;
+
+ // Estimate the required number of nodes
+ for (i = 0, p = pbuf; (p = NextChr(p, '.')); i++, p++)
+ Nod++; // One path node found
+
+ if (!(Nodes = (PJNODE)PlgDBSubAlloc(g, NULL, (++Nod) * sizeof(JNODE))))
+ return true;
+
+ memset(Nodes, 0, (Nod) * sizeof(JNODE));
+
+ // Analyze the Jpath for this column
+ for (i = 0, p = pbuf; p && i < Nod; i++, p = (p2 ? p2 : NULL)) {
+ a = (p1 != NULL);
+ p1 = strchr(p, '[');
+ p2 = strchr(p, '.');
+
+ if (!p2)
+ p2 = p1;
+ else if (p1) {
+ if (p1 < p2)
+ p2 = p1;
+ else if (p1 == p2 + 1)
+ *p2++ = 0; // Old syntax .[
+ else
+ p1 = NULL;
+
+ } // endif p1
+
+ if (p2)
+ *p2++ = 0;
+
+ // Jpath must be explicit
+ if (a || *p == 0 || *p == '[' || IsNum(p)) {
+ // Analyse intermediate array processing
+ if (SetArrayOptions(g, p, i, Nodes[i - 1].Key))
+ return true;
+
+ } else if (*p == '*') {
+ 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;
+ } // endif's
+
+ } // endfor i, p
+
+ Nod = i;
+ MulVal = AllocateValue(g, Value);
+
+ if (trace(1))
+ for (i = 0; i < Nod; i++)
+ htrc("Node(%d) Key=%s Op=%d Rank=%d\n",
+ i, SVP(Nodes[i].Key), Nodes[i].Op, Nodes[i].Rank);
+
+ Parsed = true;
+ return false;
+} // end of ParseJpath
+
+/*********************************************************************************/
+/* MakeJson: Serialize the json item and set value to it. */
+/*********************************************************************************/
+PVAL BJNX::MakeJson(PGLOBAL g, PBVAL bvp) {
+ if (Value->IsTypeNum()) {
+ strcpy(g->Message, "Cannot make Json for a numeric value");
+ Value->Reset();
+ } else if (bvp->Type != TYPE_JAR && bvp->Type != TYPE_JOB) {
+ strcpy(g->Message, "Target is not an array or object");
+ Value->Reset();
+ } else
+ Value->SetValue_psz(Serialize(g, bvp, NULL, 0));
+
+ return Value;
+} // end of MakeJson
+
+/*********************************************************************************/
+/* SetValue: Set a value from a JVALUE contains. */
+/*********************************************************************************/
+void BJNX::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL vlp) {
+ if (vlp) {
+ vp->SetNull(false);
+
+ if (Jb) {
+ vp->SetValue_psz(Serialize(g, vlp, NULL, 0));
+ } else switch (vlp->Type) {
+ case TYPE_DTM:
+ case TYPE_STRG:
+ vp->SetValue_psz(GetString(g, vlp));
+ break;
+ case TYPE_INTG:
+ case TYPE_BINT:
+ vp->SetValue(GetInteger(vlp));
+ break;
+ case TYPE_DBL:
+ if (vp->IsTypeNum())
+ vp->SetValue(GetDouble(vlp));
+ else // Get the proper number of decimals
+ vp->SetValue_psz(GetString(g, vlp));
+
+ break;
+ case TYPE_BOOL:
+ if (vp->IsTypeNum())
+ vp->SetValue(GetInteger(vlp) ? 1 : 0);
+ else
+ vp->SetValue_psz(GetString(g, vlp));
+
+ break;
+ case TYPE_JAR:
+ vp->SetValue_psz(GetArrayText(g, MVP(vlp->To_Val), NULL));
+ break;
+ case TYPE_JOB:
+ vp->SetValue_psz(GetObjectText(g, MPP(vlp->To_Val), NULL));
+ break;
+ case TYPE_NULL:
+ vp->SetNull(true);
+ default:
+ vp->Reset();
+ } // endswitch Type
+
+ } else {
+ vp->SetNull(true);
+ vp->Reset();
+ } // endif val
+
+} // end of SetJsonValue
+
+/*********************************************************************************/
+/* GetJson: */
+/*********************************************************************************/
+PBVAL BJNX::GetJson(PGLOBAL g) {
+ return GetRowValue(g, Row, 0);
+} // end of GetJson
+
+/*********************************************************************************/
+/* ReadValue: */
+/*********************************************************************************/
+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) {
+ PBVAL vlp = GetRowValue(g, row, i);
+
+ SetJsonValue(g, Value, vlp);
+ return Value;
+} // end of GetColumnValue
+
+/*********************************************************************************/
+/* GetRowValue: */
+/*********************************************************************************/
+PBVAL BJNX::GetRowValue(PGLOBAL g, PBVAL row, int i, my_bool b) {
+ my_bool expd = false;
+ PBVAL bap;
+ PBVAL vlp = NULL;
+
+ for (; i < Nod && row; i++) {
+ if (Nodes[i].Op == OP_NUM) {
+ Value->SetValue(row->Type == TYPE_JAR ? GetArraySize(MVP(row->To_Val)) : 1);
+ vlp = SubAllocVal(g, Value);
+ return vlp;
+ } else if (Nodes[i].Op == OP_XX) {
+ Jb = b;
+// return DupVal(g, row);
+ return row; // or last line ???
+ } else switch (row->Type) {
+ case TYPE_JOB:
+ if (!Nodes[i].Key) {
+ // Expected Array was not there
+ if (Nodes[i].Op == OP_LE) {
+ if (i < Nod - 1)
+ continue;
+ else
+ vlp = row; // DupVal(g, row) ???
+
+ } else {
+ strcpy(g->Message, "Unexpected object");
+ vlp = NULL;
+ } //endif Op
+
+ } else
+ vlp = GetKeyValue(MPP(row->To_Val), Nodes[i].Key);
+
+ break;
+ case TYPE_JAR:
+ bap = MVP(row->To_Val);
+
+ if (!Nodes[i].Key) {
+ if (Nodes[i].Op == OP_EQ || Nodes[i].Op == OP_LE)
+ vlp = GetArrayValue(bap, Nodes[i].Rank);
+ else if (Nodes[i].Op == OP_EXP)
+ return (PBVAL)ExpandArray(g, bap, i);
+ else
+ return SubAllocVal(g, CalculateArray(g, bap, i));
+
+ } else {
+ // Unexpected array, unwrap it as [0]
+ vlp = GetArrayValue(bap, 0);
+ i--;
+ } // endif's
+
+ break;
+ case TYPE_JVAL:
+ vlp = row;
+ break;
+ default:
+ sprintf(g->Message, "Invalid row JSON type %d", row->Type);
+ vlp = NULL;
+ } // endswitch Type
+
+ row = vlp;
+ } // endfor i
+
+ return vlp;
+} // end of GetRowValue
+
+/*********************************************************************************/
+/* ExpandArray: */
+/*********************************************************************************/
+PVAL BJNX::ExpandArray(PGLOBAL g, PBVAL arp, int n)
+{
+ strcpy(g->Message, "Expand cannot be done by this function");
+ return NULL;
+} // end of ExpandArray
+
+/*********************************************************************************/
+/* CalculateArray: NIY */
+/*********************************************************************************/
+PVAL BJNX::CalculateArray(PGLOBAL g, PBVAL bap, int n)
+{
+#if 0
+ int i, ars = GetArraySize(bap), nv = 0;
+ bool err;
+ OPVAL op = Nodes[n].Op;
+ PVAL val[2], vp = Nodes[n].Valp;
+ PBVAL bvrp, bvp;
+ BVAL bval;
+
+ vp->Reset();
+ xtrc(1,"CalculateArray size=%d op=%d\n", ars, op);
+
+ for (i = 0; i < ars; i++) {
+ bvrp = GetArrayValue(bap, i);
+ xtrc(1, "i=%d nv=%d\n", i, nv);
+
+ if (!IsValueNull(bvrp) || (op == OP_CNC && GetJsonNull())) {
+ if (IsValueNull(bvrp)) {
+ SetString(bvrp, GetJsonNull(), 0);
+ bvp = bvrp;
+ } else if (n < Nod - 1 && bvrp->GetJson()) {
+ bval.SetValue(g, GetColumnValue(g, jvrp->GetJson(), n + 1));
+ bvp = &bval;
+ } else
+ jvp = jvrp;
+
+ if (trace(1))
+ htrc("jvp=%s null=%d\n",
+ jvp->GetString(g), jvp->IsNull() ? 1 : 0);
+
+ if (!nv++) {
+ SetJsonValue(g, vp, jvp);
+ continue;
+ } else
+ SetJsonValue(g, MulVal, jvp);
+
+ if (!MulVal->IsNull()) {
+ switch (op) {
+ case OP_CNC:
+ if (Nodes[n].CncVal) {
+ val[0] = Nodes[n].CncVal;
+ err = vp->Compute(g, val, 1, op);
+ } // endif CncVal
+
+ val[0] = MulVal;
+ err = vp->Compute(g, val, 1, op);
+ break;
+ // case OP_NUM:
+ case OP_SEP:
+ val[0] = Nodes[n].Valp;
+ val[1] = MulVal;
+ err = vp->Compute(g, val, 2, OP_ADD);
+ break;
+ default:
+ val[0] = Nodes[n].Valp;
+ val[1] = MulVal;
+ err = vp->Compute(g, val, 2, op);
+ } // endswitch Op
+
+ if (err)
+ vp->Reset();
+
+ if (trace(1)) {
+ char buf(32);
+
+ htrc("vp='%s' err=%d\n",
+ vp->GetCharString(&buf), err ? 1 : 0);
+ } // endif trace
+
+ } // endif Zero
+
+ } // endif jvrp
+
+ } // endfor i
+
+ if (op == OP_SEP) {
+ // Calculate average
+ MulVal->SetValue(nv);
+ val[0] = vp;
+ val[1] = MulVal;
+
+ if (vp->Compute(g, val, 2, OP_DIV))
+ vp->Reset();
+
+ } // endif Op
+
+ return vp;
+#else
+ strcpy(g->Message, "Calculate array NIY");
+ return NULL;
+#endif
+} // end of CalculateArray
+
+/*********************************************************************************/
+/* CheckPath: Checks whether the path exists in the document. */
+/*********************************************************************************/
+my_bool BJNX::CheckPath(PGLOBAL g) {
+ PBVAL val = NULL;
+ PBVAL 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->Type) {
+ case TYPE_JOB:
+ if (Nodes[i].Key)
+ val = GetKeyValue(MPP(row->To_Val), Nodes[i].Key);
+
+ break;
+ case TYPE_JAR:
+ if (!Nodes[i].Key)
+ if (Nodes[i].Op == OP_EQ || Nodes[i].Op == OP_LE)
+ val = GetArrayValue(MVP(row->To_Val), Nodes[i].Rank);
+
+ break;
+ case TYPE_JVAL:
+ val = MVP(row->To_Val);
+ break;
+ default:
+ sprintf(g->Message, "Invalid row JSON type %d", row->Type);
+ } // endswitch Type
+
+// if (i < Nod - 1)
+// if (!(row = (val) ? val->GetJsp() : NULL))
+// val = NULL;
+
+ row = val;
+ } // endfor i
+
+ return (val != NULL);
+} // end of CheckPath
+
+/***********************************************************************/
+/* GetRow: Set the complete path of the object to be set. */
+/***********************************************************************/
+PBVAL BJNX::GetRow(PGLOBAL g) {
+ PBVAL val = NULL;
+ PBVAL arp;
+ PBVAL nwr, row = Row;
+
+ for (int i = 0; i < Nod - 1 && row; i++) {
+ if (Nodes[i].Op == OP_XX)
+ break;
+ else switch (row->Type) {
+ case TYPE_JOB:
+ if (!Nodes[i].Key)
+ // Expected Array was not there, wrap the value
+ continue;
+
+ val = GetKeyValue(MPP(row->To_Val), Nodes[i].Key);
+ break;
+ case TYPE_JAR:
+ arp = MVP(row->To_Val);
+
+ if (!Nodes[i].Key) {
+ if (Nodes[i].Op == OP_EQ)
+ val = GetArrayValue(arp, Nodes[i].Rank);
+ else
+ val = GetArrayValue(arp, Nodes[i].Rx);
+
+ } else {
+ // Unexpected array, unwrap it as [0]
+ val = GetArrayValue(arp, 0);
+ i--;
+ } // endif Nodes
+
+ break;
+ case TYPE_JVAL:
+ val = MVP(row->To_Val);
+ break;
+ default:
+ sprintf(g->Message, "Invalid row JSON type %d", row->Type);
+ val = NULL;
+ } // endswitch Type
+
+ if (val) {
+ row = val;
+ } 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 = SubAllocVal(g);
+// else
+// nwr = SubAllocPair(g);
+
+ // Construct new row
+ nwr = SubAllocVal(g);
+
+ if (row->Type == TYPE_JOB) {
+ SetKeyValue(g, MPP(row->To_Val), MOF(nwr), Nodes[i - 1].Key);
+ } else if (row->Type == TYPE_JAR) {
+ AddArrayValue(g, MVP(row->To_Val), nwr);
+ } 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 BJNX::WriteValue(PGLOBAL g, PBVAL jvalp) {
+ PBPR objp = NULL;
+ PBVAL arp = NULL;
+ PBVAL jvp = NULL;
+ PBVAL row = GetRow(g);
+
+ if (!row)
+ return true;
+
+ switch (row->Type) {
+ case TYPE_JOB: objp = MPP(row->To_Val); break;
+ case TYPE_JAR: arp = MVP(row->To_Val); break;
+ case TYPE_JVAL: jvp = MVP(row->To_Val); 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)
+ SetArrayValue(g, arp, jvalp, Nodes[Nod - 1].Rank);
+ else
+ AddArrayValue(g, arp, jvalp);
+
+ } // endif Key
+
+ } else if (objp) {
+ if (Nodes[Nod - 1].Key)
+ SetKeyValue(g, objp, MOF(jvalp), Nodes[Nod - 1].Key);
+
+ } else if (jvp)
+ SetValueVal(jvp, jvalp);
+
+ return false;
+} // end of WriteValue
+
+/*********************************************************************************/
+/* Locate a value in a JSON tree: */
+/*********************************************************************************/
+PSZ BJNX::Locate(PGLOBAL g, PBVAL jsp, PBVAL jvp, int k) {
+ PSZ str = NULL;
+ my_bool b = false, err = true;
+
+ g->Message[0] = 0;
+
+ if (!jsp) {
+ strcpy(g->Message, "Null json tree");
+ return NULL;
+ } // endif jsp
+
+ try {
+ // Write to the path string
+ Jp = new(g) JOUTSTR(g);
+ Jp->WriteChr('$');
+ Bvalp = jvp;
+ K = k;
+
+ switch (jsp->Type) {
+ case TYPE_JAR:
+ err = LocateArray(g, MVP(jsp->To_Val));
+ break;
+ case TYPE_JOB:
+ err = LocateObject(g, MPP(jsp->To_Val));
+ break;
+ case TYPE_JVAL:
+ err = LocateValue(g, MVP(jsp->To_Val));
+ break;
+ default:
+ err = true;
+ } // endswitch Type
+
+ if (err) {
+ if (!g->Message[0])
+ strcpy(g->Message, "Invalid json tree");
+
+ } else if (Found) {
+ Jp->WriteChr('\0');
+ PlugSubAlloc(g, NULL, Jp->N);
+ str = Jp->Strp;
+ } // endif's
+
+ } catch (int n) {
+ if (trace(1))
+ htrc("Exception %d: %s\n", n, g->Message);
+
+ PUSH_WARNING(g->Message);
+ } catch (const char* msg) {
+ strcpy(g->Message, msg);
+ } // end catch
+
+ return str;
+} // end of Locate
+
+/*********************************************************************************/
+/* Locate in a JSON Array. */
+/*********************************************************************************/
+my_bool BJNX::LocateArray(PGLOBAL g, PBVAL jarp) {
+ char s[16];
+ int n = GetArraySize(jarp);
+ size_t m = Jp->N;
+
+ for (int i = 0; i < n && !Found; i++) {
+ Jp->N = m;
+ sprintf(s, "[%d]", i + B);
+
+ if (Jp->WriteStr(s))
+ return true;
+
+ if (LocateValue(g, GetArrayValue(jarp, i)))
+ return true;
+
+ } // endfor i
+
+ return false;
+} // end of LocateArray
+
+/*********************************************************************************/
+/* Locate in a JSON Object. */
+/*********************************************************************************/
+my_bool BJNX::LocateObject(PGLOBAL g, PBPR jobp) {
+ size_t m;
+
+ if (Jp->WriteChr('.'))
+ return true;
+
+ m = Jp->N;
+
+ for (PBPR pair = jobp; pair && !Found; pair = MPP(pair->Next)) {
+ Jp->N = m;
+
+ if (Jp->WriteStr(MZP(pair->Key)))
+ return true;
+
+ if (LocateValue(g, MVP(pair->Vlp)))
+ return true;
+
+ } // endfor i
+
+ return false;
+} // end of LocateObject
+
+/*********************************************************************************/
+/* Locate a JSON Value. */
+/*********************************************************************************/
+my_bool BJNX::LocateValue(PGLOBAL g, PBVAL jvp)
+{
+ if (CompareTree(g, Bvalp, jvp))
+ Found = (--K == 0);
+ else if (jvp->Type == TYPE_JAR)
+ return LocateArray(g, GetArray(jvp));
+ else if (jvp->Type == TYPE_JOB)
+ return LocateObject(g, GetObject(jvp));
+
+ return false;
+} // end of LocateValue
+
+/*********************************************************************************/
+/* Locate all occurrences of a value in a JSON tree: */
+/*********************************************************************************/
+PSZ BJNX::LocateAll(PGLOBAL g, PBVAL jsp, PBVAL bvp, int mx)
+{
+ PSZ str = NULL;
+ my_bool b = false, err = true;
+ PJPN jnp;
+
+ if (!jsp) {
+ strcpy(g->Message, "Null json tree");
+ return NULL;
+ } // endif jsp
+
+ try {
+ jnp = (PJPN)PlugSubAlloc(g, NULL, sizeof(JPN) * mx);
+ memset(jnp, 0, sizeof(JPN) * mx);
+ g->Message[0] = 0;
+
+ // Write to the path string
+ Jp = new(g)JOUTSTR(g);
+ Bvalp = bvp;
+ Imax = mx - 1;
+ Jpnp = jnp;
+ Jp->WriteChr('[');
+
+ switch (jsp->Type) {
+ case TYPE_JAR:
+ err = LocateArrayAll(g, MVP(jsp->To_Val));
+ break;
+ case TYPE_JOB:
+ err = LocateObjectAll(g, MPP(jsp->To_Val));
+ break;
+ case TYPE_JVAL:
+ err = LocateValueAll(g, MVP(jsp->To_Val));
+ break;
+ default:
+ err = LocateValueAll(g, jsp);
+ } // endswitch Type
+
+ if (!err) {
+ if (Jp->N > 1)
+ Jp->N--;
+
+ Jp->WriteChr(']');
+ Jp->WriteChr('\0');
+ PlugSubAlloc(g, NULL, Jp->N);
+ str = Jp->Strp;
+ } else if (!g->Message[0])
+ strcpy(g->Message, "Invalid json tree");
+
+ } catch (int n) {
+ xtrc(1, "Exception %d: %s\n", n, g->Message);
+ PUSH_WARNING(g->Message);
+ } catch (const char* msg) {
+ strcpy(g->Message, msg);
+ } // end catch
+
+ return str;
+} // end of LocateAll
+
+/*********************************************************************************/
+/* Locate in a JSON Array. */
+/*********************************************************************************/
+my_bool BJNX::LocateArrayAll(PGLOBAL g, PBVAL jarp)
+{
+ int i = 0;
+
+ if (I < Imax) {
+ Jpnp[++I].Type = TYPE_JAR;
+
+ for (PBVAL vp = jarp; vp; vp = MVP(vp->Next)) {
+ Jpnp[I].N = i;
+
+ if (LocateValueAll(g, GetArrayValue(jarp, i)))
+ return true;
+
+ i++;
+ } // endfor i
+
+ I--;
+ } // endif I
+
+ return false;
+} // end of LocateArrayAll
+
+/*********************************************************************************/
+/* Locate in a JSON Object. */
+/*********************************************************************************/
+my_bool BJNX::LocateObjectAll(PGLOBAL g, PBPR jobp)
+{
+ if (I < Imax) {
+ Jpnp[++I].Type = TYPE_JOB;
+
+ for (PBPR pair = jobp; pair; pair = MPP(pair->Next)) {
+ Jpnp[I].Key = MZP(pair->Key);
+
+ if (LocateValueAll(g, MVP(pair->Vlp)))
+ return true;
+
+ } // endfor i
+
+ I--;
+ } // endif I
+
+ return false;
+} // end of LocateObjectAll
+
+/*********************************************************************************/
+/* Locate a JSON Value. */
+/*********************************************************************************/
+my_bool BJNX::LocateValueAll(PGLOBAL g, PBVAL jvp) {
+ if (CompareTree(g, Bvalp, jvp))
+ return AddPath();
+ else if (jvp->Type == TYPE_JAR)
+ return LocateArrayAll(g, GetArray(jvp));
+ else if (jvp->Type == TYPE_JOB)
+ return LocateObjectAll(g, GetObject(jvp));
+
+ return false;
+} // end of LocateValueAll
+
+/*********************************************************************************/
+/* Compare two JSON trees. */
+/*********************************************************************************/
+my_bool BJNX::CompareTree(PGLOBAL g, PBVAL jp1, PBVAL jp2)
+{
+ if (!jp1 || !jp2 || jp1->Type != jp2->Type || GetSize(jp1) != GetSize(jp2))
+ return false;
+
+ my_bool found = true;
+
+ if (jp1->Type == TYPE_JAR) {
+ for (int i = 0; found && i < GetArraySize(jp1); i++)
+ found = (CompareValues(g, GetArrayValue(jp1, i), GetArrayValue(jp2, i)));
+
+ } else if (jp1->Type == TYPE_JOB) {
+ PBPR p1 = MPP(jp1->To_Val), p2 = MPP(jp2->To_Val);
+
+ // Keys can be differently ordered
+ for (; found && p1 && p2; p1 = MPP(p1->Next))
+ found = CompareValues(g, MVP(p1->Vlp), GetKeyValue(p2, MZP(p1->Key)));
+
+ } else if (jp1->Type == TYPE_JVAL) {
+ found = CompareTree(g, MVP(jp1->To_Val), (MVP(jp2->To_Val)));
+ } else
+ found = CompareValues(g, jp1, jp2);
+
+ return found;
+} // end of CompareTree
+
+/*********************************************************************************/
+/* Compare two VAL values and return true if they are equal. */
+/*********************************************************************************/
+my_bool BJNX::CompareValues(PGLOBAL g, PBVAL v1, PBVAL v2)
+{
+ my_bool b = false;
+
+ if (v1 && v2)
+ switch (v1->Type) {
+ case TYPE_JAR:
+ if (v2->Type == TYPE_JAR)
+ b = CompareTree(g, MVP(v1->To_Val), MVP(v2->To_Val));
+
+ break;
+ case TYPE_STRG:
+ if (v2->Type == TYPE_STRG) {
+ if (v1->Nd || v2->Nd) // Case insensitive
+ b = (!stricmp(MZP(v1->To_Val), MZP(v2->To_Val)));
+ else
+ b = (!strcmp(MZP(v1->To_Val), MZP(v2->To_Val)));
+
+ } // endif Type
+
+ break;
+ case TYPE_DTM:
+ if (v2->Type == TYPE_DTM)
+ b = (!strcmp(MZP(v1->To_Val), MZP(v2->To_Val)));
+
+ break;
+ case TYPE_INTG:
+ if (v2->Type == TYPE_INTG)
+ b = (v1->N == v2->N);
+ else if (v2->Type == TYPE_BINT)
+ b = ((longlong)v1->N == LLN(v2->To_Val));
+
+ break;
+ case TYPE_BINT:
+ if (v2->Type == TYPE_INTG)
+ b = (LLN(v1->To_Val) == (longlong)v2->N);
+ else if (v2->Type == TYPE_BINT)
+ b = (LLN(v1->To_Val) == LLN(v2->To_Val));
+
+ break;
+ case TYPE_FLOAT:
+ if (v2->Type == TYPE_FLOAT)
+ b = (v1->F == v2->F);
+ else if (v2->Type == TYPE_DBL)
+ b = ((double)v1->F == DBL(v2->To_Val));
+
+ break;
+ case TYPE_DBL:
+ if (v2->Type == TYPE_DBL)
+ b = (DBL(v1->To_Val) == DBL(v2->To_Val));
+ else if (v2->Type == TYPE_FLOAT)
+ b = (DBL(v1->To_Val) == (double)v2->F);
+
+ break;
+ case TYPE_BOOL:
+ if (v2->Type == TYPE_BOOL)
+ b = (v1->B == v2->B);
+
+ break;
+ case TYPE_NULL:
+ b = (v2->Type == TYPE_NULL);
+ break;
+ default:
+ break;
+ } // endswitch Type
+
+ else
+ b = (!v1 && !v2);
+
+ return b;
+} // end of CompareValues
+
+/*********************************************************************************/
+/* Add the found path to the list. */
+/*********************************************************************************/
+my_bool BJNX::AddPath(void) {
+ char s[16];
+
+ if (Jp->WriteStr("\"$"))
+ return true;
+
+ for (int i = 0; i <= I; i++) {
+ if (Jpnp[i].Type == TYPE_JAR) {
+ sprintf(s, "[%d]", Jpnp[i].N + B);
+
+ if (Jp->WriteStr(s))
+ return true;
+
+ } else {
+ if (Jp->WriteChr('.'))
+ return true;
+
+ if (Jp->WriteStr(Jpnp[i].Key))
+ return true;
+
+ } // endif's
+
+ } // endfor i
+
+ if (Jp->WriteStr("\","))
+ return true;
+
+ return false;
+} // end of AddPath
+
+/*********************************************************************************/
+/* Make a BVAL value from the passed argument. */
+/*********************************************************************************/
+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))) {
+ 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);
+
+ bvp = bp;
+ } else {
+ // Check whether this string is a valid json string
+ JsonMemSave(g);
+
+ 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 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);
+
+ 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
+
+ return bvp;
+} // end of MakeBinValue
+
+/*********************************************************************************/
+/* Test BJSON parse and serialize. */
+/*********************************************************************************/
+my_bool json_test_bson_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
+ unsigned long reslen, memlen, more = 1000;
+
+ if (args->arg_count == 0) {
+ strcpy(message, "At least 1 argument required (json)");
+ return true;
+ } else if (!IsJson(args, 0) && args->arg_type[0] != STRING_RESULT) {
+ strcpy(message, "First argument must be a json item");
+ return true;
+ } else
+ CalcLen(args, false, reslen, memlen);
+
+ return JsonInit(initid, args, message, true, reslen, memlen, more);
+} // end of json_test_bson_init
+
+char* json_test_bson(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;
+ PBVAL bvp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ BDOC doc(g);
+
+ if (g->N) {
+ str = (char*)g->Activityp;
+ goto err;
+ } else if (initid->const_item)
+ g->N = 1;
+
+ try {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, !g->Xchk)) {
+ PUSH_WARNING("CheckMemory error");
+ *error = 1;
+ goto err;
+ } else if (!(bvp = MakeBinValue(g, args, 0))) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif bvp
+
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = bvp;
+ JsonMemSave(g);
+ } // endif Mrr
+
+ } else
+ bvp = (PBVAL)g->Xchk;
+
+ for (uint i = 1; i < args->arg_count; i++)
+ if (args->arg_type[i] == STRING_RESULT)
+ fn = args->args[i];
+ else if (args->arg_type[i] == INT_RESULT)
+ pretty = (int)*(longlong*)args->args[i];
+
+ // Serialize the parse tree
+ str = doc.Serialize(g, bvp, fn, pretty);
+
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)str;
+
+ } catch (int n) {
+ xtrc(1, "json_test_bson: error %d: %s\n", n, g->Message);
+ PUSH_WARNING(g->Message);
+ *error = 1;
+ str = NULL;
+ } catch (const char* msg) {
+ strcpy(g->Message, msg);
+ PUSH_WARNING(g->Message);
+ *error = 1;
+ str = NULL;
+ } // end catch
+
+err:
+ if (!str) {
+ *res_length = 0;
+ *is_null = 1;
+ } else
+ *res_length = strlen(str);
+
+ return str;
+} // end of json_test_bson
+
+void json_test_bson_deinit(UDF_INIT* initid) {
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of json_test_bson_deinit
+
+/*********************************************************************************/
+/* Locate a value in a Json tree. */
+/*********************************************************************************/
+my_bool jsonlocate_bson_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
+ unsigned long reslen, memlen, more = 1000;
+
+ if (args->arg_count < 2) {
+ strcpy(message, "At least 2 arguments required");
+ return true;
+ } else if (!IsJson(args, 0) && 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 (rank)");
+ return true;
+ } // endifs args
+
+ CalcLen(args, false, reslen, memlen);
+
+ // TODO: calculate this
+ if (IsJson(args, 0) == 3)
+ more = 0;
+
+ return JsonInit(initid, args, message, true, reslen, memlen, more);
+} // end of jsonlocate_bson_init
+
+char* jsonlocate_bson(UDF_INIT* initid, UDF_ARGS* args, char* result,
+ unsigned long* res_length, char* is_null, char* error) {
+ char* path = NULL;
+ int k;
+ PBVAL bvp, bvp2;
+ PBJNX bnxp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ if (g->N) {
+ if (g->Activityp) {
+ path = (char*)g->Activityp;
+ *res_length = strlen(path);
+ return path;
+ } else {
+ *res_length = 0;
+ *is_null = 1;
+ return NULL;
+ } // endif Activityp
+
+ } else if (initid->const_item)
+ g->N = 1;
+
+ try {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, !g->Xchk)) {
+ PUSH_WARNING("CheckMemory error");
+ *error = 1;
+ goto err;
+ } else
+ bvp = MakeBinValue(g, args, 0);
+
+ if (!bvp) {
+ PUSH_WARNING("First argument is not a valid JSON item");
+ goto err;
+ } // endif bvp
+
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = bvp;
+ JsonMemSave(g);
+ } // endif Mrr
+
+ } else
+ bvp = (PBVAL)g->Xchk;
+
+ // The item to locate
+ bvp2 = MakeBinValue(g, args, 1);
+
+ k = (args->arg_count > 2) ? (int)*(long long*)args->args[2] : 1;
+
+ bnxp = new(g) BJNX(g, bvp, TYPE_STRING);
+ path = bnxp->Locate(g, bvp, bvp2, k);
+
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)path;
+
+ } catch (int n) {
+ xtrc(1, "Exception %d: %s\n", n, g->Message);
+ PUSH_WARNING(g->Message);
+ *error = 1;
+ path = NULL;
+ } catch (const char* msg) {
+ strcpy(g->Message, msg);
+ PUSH_WARNING(g->Message);
+ *error = 1;
+ path = NULL;
+ } // end catch
+
+err:
+ if (!path) {
+ *res_length = 0;
+ *is_null = 1;
+ } else
+ *res_length = strlen(path);
+
+ return path;
+} // end of jsonlocate_bson
+
+void jsonlocate_bson_deinit(UDF_INIT* initid) {
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of jsonlocate_bson_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)
+{
+ unsigned long reslen, memlen, more = 1000;
+
+ if (args->arg_count < 2) {
+ strcpy(message, "At least 2 arguments required");
+ return true;
+ } else if (!IsJson(args, 0) && 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 (Depth)");
+ return true;
+ } // endifs
+
+ CalcLen(args, false, reslen, memlen);
+
+ // TODO: calculate this
+ if (IsJson(args, 0) == 3)
+ more = 0;
+
+ return JsonInit(initid, args, message, true, reslen, memlen, more);
+} // end of json_locate_all_bson_init
+
+char* json_locate_all_bson(UDF_INIT* initid, UDF_ARGS* args, char* result,
+ unsigned long* res_length, char* is_null, char* error)
+{
+ char *path = NULL;
+ int mx = 10;
+ PBVAL bvp, bvp2;
+ PBJNX bnxp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ if (g->N) {
+ if (g->Activityp) {
+ path = (char*)g->Activityp;
+ *res_length = strlen(path);
+ return path;
+ } else {
+ *error = 1;
+ *res_length = 0;
+ *is_null = 1;
+ return NULL;
+ } // endif Activityp
+
+ } else if (initid->const_item)
+ g->N = 1;
+
+ try {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
+ *error = 1;
+ goto err;
+ } else
+ bvp = MakeBinValue(g, args, 0);
+
+ if (!bvp) {
+ PUSH_WARNING("First argument is not a valid JSON item");
+ goto err;
+ } // endif bvp
+
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = bvp;
+ JsonMemSave(g);
+ } // endif Mrr
+
+ } else
+ bvp = (PBVAL)g->Xchk;
+
+ // The item to locate
+ bvp2 = MakeBinValue(g, args, 1);
+
+ if (args->arg_count > 2)
+ mx = (int)*(long long*)args->args[2];
+
+ bnxp = new(g) BJNX(g, bvp, TYPE_STRING);
+ path = bnxp->LocateAll(g, bvp, bvp2, mx);
+
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)path;
+
+ } catch (int n) {
+ xtrc(1, "Exception %d: %s\n", n, g->Message);
+ PUSH_WARNING(g->Message);
+ *error = 1;
+ path = NULL;
+ } catch (const char* msg) {
+ strcpy(g->Message, msg);
+ PUSH_WARNING(g->Message);
+ *error = 1;
+ path = NULL;
+ } // end catch
+
+err:
+ if (!path) {
+ *res_length = 0;
+ *is_null = 1;
+ } else
+ *res_length = strlen(path);
+
+ return path;
+} // end of json_locate_all_bson
+
+void json_locate_all_bson_deinit(UDF_INIT* initid) {
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of json_locate_all_bson_deinit
+
diff --git a/storage/connect/jsonudf.h b/storage/connect/jsonudf.h
index 46bac66b607..886f380d426 100644
--- a/storage/connect/jsonudf.h
+++ b/storage/connect/jsonudf.h
@@ -1,7 +1,7 @@
/******************** tabjson H Declares Source Code File (.H) *******************/
-/* Name: jsonudf.h Version 1.3 */
+/* Name: jsonudf.h Version 1.4 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2015-2017 */
+/* (C) Copyright to the author Olivier BERTRAND 2015-2020 */
/* */
/* This file contains the JSON UDF function and class declares. */
/*********************************************************************************/
@@ -15,6 +15,27 @@
#define UDF_EXEC_ARGS \
UDF_INIT*, UDF_ARGS*, char*, unsigned long*, char*, char*
+// BSON size should be equal on Linux and Windows
+#define BMX 255
+typedef struct BSON* PBSON;
+
+/***********************************************************************/
+/* Structure used to return binary json to Json UDF functions. */
+/***********************************************************************/
+struct BSON {
+ char Msg[BMX + 1];
+ char *Filename;
+ PGLOBAL G;
+ int Pretty;
+ ulong Reslen;
+ my_bool Changed;
+ PJSON Top;
+ PJSON Jsp;
+ PBSON Bsp;
+}; // end of struct BSON
+
+PBSON JbinAlloc(PGLOBAL g, UDF_ARGS* args, ulong len, PJSON jsp);
+
/*********************************************************************************/
/* The JSON tree node. Can be an Object or an Array. */
/*********************************************************************************/
@@ -29,8 +50,6 @@ typedef struct _jnode {
} JNODE, *PJNODE;
typedef class JSNX *PJSNX;
-typedef class JOUTPATH *PJTP;
-typedef class JOUTALL *PJTA;
extern "C" {
DllExport my_bool jsonvalue_init(UDF_INIT*, UDF_ARGS*, char*);
@@ -368,3 +387,90 @@ public:
int k, recl;
}; // end of class JUP
+
+/* --------------------------- New Testing BJSON Stuff --------------------------*/
+
+typedef class BJNX* PBJNX;
+
+/*********************************************************************************/
+/* Class BJNX: BJSON access methods. */
+/*********************************************************************************/
+class BJNX : public BDOC {
+public:
+ // Constructors
+ BJNX(PGLOBAL g, PBVAL row, int type, int len = 64, int prec = 0, my_bool wr = false);
+
+ // Implementation
+ int GetPrecision(void) { return Prec; }
+ PVAL GetValue(void) { return Value; }
+
+ // Methods
+ my_bool SetJpath(PGLOBAL g, char* path, my_bool jb = false);
+ my_bool ParseJpath(PGLOBAL g);
+ void ReadValue(PGLOBAL g);
+ PBVAL GetRowValue(PGLOBAL g, PBVAL row, int i, my_bool b = true);
+ PBVAL GetJson(PGLOBAL g);
+ my_bool CheckPath(PGLOBAL g);
+ my_bool WriteValue(PGLOBAL g, PBVAL jvalp);
+ char* Locate(PGLOBAL g, PBVAL jsp, PBVAL jvp, int k = 1);
+ char* LocateAll(PGLOBAL g, PBVAL jsp, PBVAL jvp, int mx = 10);
+
+protected:
+ my_bool SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm);
+ PVAL GetColumnValue(PGLOBAL g, PBVAL row, int i);
+ PVAL ExpandArray(PGLOBAL g, PBVAL arp, int n);
+ PVAL CalculateArray(PGLOBAL g, PBVAL arp, int n);
+ PVAL MakeJson(PGLOBAL g, PBVAL bvp);
+ void SetJsonValue(PGLOBAL g, PVAL vp, PBVAL vlp);
+ PBVAL GetRow(PGLOBAL g);
+ my_bool CompareValues(PGLOBAL g, PBVAL v1, PBVAL v2);
+ my_bool LocateArray(PGLOBAL g, PBVAL jarp);
+ my_bool LocateObject(PGLOBAL g, PBPR jobp);
+ my_bool LocateValue(PGLOBAL g, PBVAL jvp);
+ my_bool LocateArrayAll(PGLOBAL g, PBVAL jarp);
+ my_bool LocateObjectAll(PGLOBAL g, PBPR jobp);
+ my_bool LocateValueAll(PGLOBAL g, PBVAL jvp);
+ my_bool CompareTree(PGLOBAL g, PBVAL jp1, PBVAL jp2);
+ my_bool AddPath(void);
+
+ // Default constructor not to be used
+ BJNX(void) {}
+
+ // Members
+ PBVAL Row;
+ PBVAL Bvalp;
+ PJPN Jpnp;
+ JOUTSTR* Jp;
+ JNODE* Nodes; // The intermediate objects
+ PVAL Value;
+ PVAL MulVal; // To value used by multiple column
+ char* Jpath; // The json path
+ int Buf_Type;
+ int Long;
+ int Prec;
+ int Nod; // The number of intermediate objects
+ int Xnod; // Index of multiple values
+ int K; // Kth item to locate
+ int I; // Index of JPN
+ int Imax; // Max number of JPN's
+ int B; // Index base
+ 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 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 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 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*);
+} // extern "C"
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index a9aeadd7bf4..336b0f371ca 100644
--- a/storage/connect/tabjson.cpp
+++ b/storage/connect/tabjson.cpp
@@ -1596,6 +1596,7 @@ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp)
if (Value->IsTypeNum()) {
strcpy(g->Message, "Cannot make Json for a numeric column");
Value->Reset();
+#if 0
} else if (Value->GetType() == TYPE_BIN) {
if ((unsigned)Value->GetClen() >= sizeof(BSON)) {
ulong len = Tjp->Lrecl ? Tjp->Lrecl : 500;
@@ -1607,6 +1608,7 @@ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp)
strcpy(g->Message, "Column size too small");
Value->SetValue_char(NULL, 0);
} // endif Clen
+#endif 0
} else
Value->SetValue_psz(Serialize(g, jsp, NULL, 0));
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index bca6d26d1e9..e710fefc624 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -197,7 +197,7 @@ const char *GetFormatType(int type)
case TYPE_DOUBLE: c = "F"; break;
case TYPE_DATE: c = "D"; break;
case TYPE_TINY: c = "T"; break;
- case TYPE_DECIM: c = "M"; break;
+ case TYPE_DECIM: c = "F"; break;
case TYPE_BIN: c = "B"; break;
case TYPE_PCHAR: c = "P"; break;
} // endswitch type