1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

- Fix memory leak for the JSON table type

(and continue BSON implementatio)
  modified:   storage/connect/bson.cpp
  modified:   storage/connect/bson.h
  modified:   storage/connect/bsonudf.cpp
  modified:   storage/connect/connect.cc
  modified:   storage/connect/global.h
  modified:   storage/connect/ha_connect.cc
  modified:   storage/connect/jsonudf.cpp
  modified:   storage/connect/mycat.cc
  modified:   storage/connect/plgdbsem.h
  modified:   storage/connect/plugutil.cpp
  modified:   storage/connect/tabjson.cpp
  modified:   storage/connect/tabjson.h
  modified:   storage/connect/user_connect.cc

- Desesperatly trying to fix xml.test failure
  modified:   storage/connect/mysql-test/connect/r/xml.result
This commit is contained in:
Olivier Bertrand
2020-12-01 19:30:56 +01:00
parent 950bf6ab53
commit 4e8af8a664
16 changed files with 3223 additions and 190 deletions

View File

@@ -87,7 +87,7 @@ char* NextChr(PSZ s, char sep) {
/***********************************************************************/
/* BDOC constructor. */
/***********************************************************************/
BDOC::BDOC(void *base) : BJSON(base, NULL)
BDOC::BDOC(PGLOBAL G) : BJSON(G, NULL)
{
jp = NULL;
s = NULL;
@@ -118,25 +118,25 @@ PBVAL BDOC::ParseJson(PGLOBAL g, char* js, size_t lng, int* ptyp, bool* comma) {
pty[0] = false;
try {
Bvp = SubAllocVal(g);
Bvp = NewVal();
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);
Bvp->To_Val = ParseAsArray(i, pretty, ptyp);
else
Bvp->To_Val = ParseArray(g, ++i);
Bvp->To_Val = ParseArray(++i);
Bvp->Type = TYPE_JAR;
break;
case '{':
if (Bvp->Type != TYPE_UNKNOWN) {
Bvp->To_Val = ParseAsArray(g, i, pretty, ptyp);
Bvp->To_Val = ParseAsArray(i, pretty, ptyp);
Bvp->Type = TYPE_JAR;
} else {
Bvp->To_Val = ParseObject(g, ++i);
Bvp->To_Val = ParseObject(++i);
Bvp->Type = TYPE_JOB;
} // endif Type
@@ -168,9 +168,9 @@ PBVAL BDOC::ParseJson(PGLOBAL g, char* js, size_t lng, int* ptyp, bool* comma) {
default:
if (Bvp->Type != TYPE_UNKNOWN) {
Bvp->To_Val = ParseAsArray(g, i, pretty, ptyp);
Bvp->To_Val = ParseAsArray(i, pretty, ptyp);
Bvp->Type = TYPE_JAR;
} else if ((Bvp->To_Val = MOF(ParseValue(g, i))))
} else if ((Bvp->To_Val = MOF(ParseValue(i))))
Bvp->Type = TYPE_JVAL;
else
throw 4;
@@ -193,7 +193,8 @@ 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);
htrc("Exception %d: %s\n", n, G->Message);
GetMsg(g);
Bvp = NULL;
} catch (const char* msg) {
strcpy(g->Message, msg);
@@ -206,16 +207,16 @@ PBVAL BDOC::ParseJson(PGLOBAL g, char* js, size_t lng, int* ptyp, bool* comma) {
/***********************************************************************/
/* Parse several items as being in an array. */
/***********************************************************************/
OFFSET BDOC::ParseAsArray(PGLOBAL g, int& i, int pretty, int* ptyp) {
OFFSET BDOC::ParseAsArray(int& i, int pretty, int* ptyp) {
if (pty[0] && (!pretty || pretty > 2)) {
OFFSET jsp;
if ((jsp = ParseArray(g, (i = 0))) && ptyp && pretty == 3)
if ((jsp = ParseArray((i = 0))) && ptyp && pretty == 3)
*ptyp = (pty[0]) ? 0 : 3;
return jsp;
} else
strcpy(g->Message, "More than one item in file");
strcpy(G->Message, "More than one item in file");
return 0;
} // end of ParseAsArray
@@ -223,7 +224,7 @@ OFFSET BDOC::ParseAsArray(PGLOBAL g, int& i, int pretty, int* ptyp) {
/***********************************************************************/
/* Parse a JSON Array. */
/***********************************************************************/
OFFSET BDOC::ParseArray(PGLOBAL g, int& i) {
OFFSET BDOC::ParseArray(int& i) {
int level = 0;
bool b = (!i);
PBVAL vlp, firstvlp, lastvlp;
@@ -234,7 +235,7 @@ OFFSET BDOC::ParseArray(PGLOBAL g, int& i) {
switch (s[i]) {
case ',':
if (level < 2) {
sprintf(g->Message, "Unexpected ',' near %.*s", ARGS);
sprintf(G->Message, "Unexpected ',' near %.*s", ARGS);
throw 1;
} else
level = 1;
@@ -242,7 +243,7 @@ OFFSET BDOC::ParseArray(PGLOBAL g, int& i) {
break;
case ']':
if (level == 1) {
sprintf(g->Message, "Unexpected ',]' near %.*s", ARGS);
sprintf(G->Message, "Unexpected ',]' near %.*s", ARGS);
throw 1;
} // endif level
@@ -256,14 +257,14 @@ OFFSET BDOC::ParseArray(PGLOBAL g, int& i) {
break;
default:
if (level == 2) {
sprintf(g->Message, "Unexpected value near %.*s", ARGS);
sprintf(G->Message, "Unexpected value near %.*s", ARGS);
throw 1;
} else if (lastvlp) {
vlp = ParseValue(g, i);
vlp = ParseValue(i);
lastvlp->Next = MOF(vlp);
lastvlp = vlp;
} else
firstvlp = lastvlp = ParseValue(g, i);
firstvlp = lastvlp = ParseValue(i);
level = (b) ? 1 : 2;
break;
@@ -280,7 +281,7 @@ OFFSET BDOC::ParseArray(PGLOBAL g, int& i) {
/***********************************************************************/
/* Parse a JSON Object. */
/***********************************************************************/
OFFSET BDOC::ParseObject(PGLOBAL g, int& i) {
OFFSET BDOC::ParseObject(int& i) {
OFFSET key;
int level = 0;
PBPR bpp, firstbpp, lastbpp;
@@ -291,8 +292,8 @@ OFFSET BDOC::ParseObject(PGLOBAL g, int& i) {
switch (s[i]) {
case '"':
if (level < 2) {
key = ParseString(g, ++i);
bpp = SubAllocPair(g, key);
key = ParseString(++i);
bpp = SubAllocPair(key);
if (lastbpp) {
lastbpp->Next = MOF(bpp);
@@ -302,24 +303,24 @@ OFFSET BDOC::ParseObject(PGLOBAL g, int& i) {
level = 2;
} else {
sprintf(g->Message, "misplaced string near %.*s", ARGS);
sprintf(G->Message, "misplaced string near %.*s", ARGS);
throw 2;
} // endif level
break;
case ':':
if (level == 2) {
lastbpp->Vlp = MOF(ParseValue(g, ++i));
lastbpp->Vlp = MOF(ParseValue(++i));
level = 3;
} else {
sprintf(g->Message, "Unexpected ':' near %.*s", ARGS);
sprintf(G->Message, "Unexpected ':' near %.*s", ARGS);
throw 2;
} // endif level
break;
case ',':
if (level < 3) {
sprintf(g->Message, "Unexpected ',' near %.*s", ARGS);
sprintf(G->Message, "Unexpected ',' near %.*s", ARGS);
throw 2;
} else
level = 1;
@@ -327,7 +328,7 @@ OFFSET BDOC::ParseObject(PGLOBAL g, int& i) {
break;
case '}':
if (!(level == 0 || level == 3)) {
sprintf(g->Message, "Unexpected '}' near %.*s", ARGS);
sprintf(G->Message, "Unexpected '}' near %.*s", ARGS);
throw 2;
} // endif level
@@ -339,20 +340,21 @@ OFFSET BDOC::ParseObject(PGLOBAL g, int& i) {
case '\t':
break;
default:
sprintf(g->Message, "Unexpected character '%c' near %.*s",
sprintf(G->Message, "Unexpected character '%c' near %.*s",
s[i], ARGS);
throw 2;
}; // endswitch s[i]
strcpy(g->Message, "Unexpected EOF in Object");
strcpy(G->Message, "Unexpected EOF in Object");
throw 2;
} // end of ParseObject
/***********************************************************************/
/* Parse a JSON Value. */
/***********************************************************************/
PBVAL BDOC::ParseValue(PGLOBAL g, int& i) {
PBVAL bvp = SubAllocVal(g);
PBVAL BDOC::ParseValue(int& i)
{
PBVAL bvp = NewVal();
for (; i < len; i++)
switch (s[i]) {
@@ -369,16 +371,16 @@ PBVAL BDOC::ParseValue(PGLOBAL g, int& i) {
suite:
switch (s[i]) {
case '[':
bvp->To_Val = ParseArray(g, ++i);
bvp->To_Val = ParseArray(++i);
bvp->Type = TYPE_JAR;
break;
case '{':
bvp->To_Val = ParseObject(g, ++i);
bvp->To_Val = ParseObject(++i);
bvp->Type = TYPE_JOB;
break;
case '"':
// jvp->Val = AllocVal(g, TYPE_STRG);
bvp->To_Val = ParseString(g, ++i);
bvp->To_Val = ParseString(++i);
bvp->Type = TYPE_STRG;
break;
case 't':
@@ -412,7 +414,7 @@ suite:
case '-':
default:
if (s[i] == '-' || isdigit(s[i]))
ParseNumeric(g, i, bvp);
ParseNumeric(i, bvp);
else
goto err;
@@ -421,29 +423,29 @@ suite:
return bvp;
err:
sprintf(g->Message, "Unexpected character '%c' near %.*s", s[i], ARGS);
sprintf(G->Message, "Unexpected character '%c' near %.*s", s[i], ARGS);
throw 3;
} // end of ParseValue
/***********************************************************************/
/* Unescape and parse a JSON string. */
/***********************************************************************/
OFFSET BDOC::ParseString(PGLOBAL g, int& i) {
OFFSET BDOC::ParseString(int& i) {
uchar* p;
int n = 0;
// Be sure of memory availability
if (((size_t)len + 1 - i) > ((PPOOLHEADER)g->Sarea)->FreeBlk)
if (((size_t)len + 1 - i) > ((PPOOLHEADER)G->Sarea)->FreeBlk)
throw("ParseString: Out of memory");
// The size to allocate is not known yet
p = (uchar*)PlugSubAlloc(g, NULL, 0);
p = (uchar*)PlugSubAlloc(G, NULL, 0);
for (; i < len; i++)
switch (s[i]) {
case '"':
p[n++] = 0;
PlugSubAlloc(g, NULL, n);
PlugSubAlloc(G, NULL, n);
return MOF(p);
case '\\':
if (++i < len) {
@@ -514,7 +516,7 @@ throw("Unexpected EOF in String");
/***********************************************************************/
/* Parse a JSON numeric value. */
/***********************************************************************/
void BDOC::ParseNumeric(PGLOBAL g, int& i, PBVAL vlp) {
void BDOC::ParseNumeric(int& i, PBVAL vlp) {
char buf[50];
int n = 0;
short nd = 0;
@@ -570,7 +572,7 @@ fin:
double dv = strtod(buf, NULL);
if (nd > 6) {
double* dvp = (double*)PlugSubAlloc(g, NULL, sizeof(double));
double* dvp = (double*)PlugSubAlloc(G, NULL, sizeof(double));
*dvp = dv;
vlp->To_Val = MOF(dvp);
@@ -585,7 +587,7 @@ fin:
longlong iv = strtoll(buf, NULL, 10);
if (iv > INT_MAX32 || iv < INT_MIN32) {
longlong *llp = (longlong*)PlugSubAlloc(g, NULL, sizeof(longlong));
longlong *llp = (longlong*)PlugSubAlloc(G, NULL, sizeof(longlong));
*llp = iv;
vlp->To_Val = MOF(llp);
@@ -614,7 +616,7 @@ PSZ BDOC::Serialize(PGLOBAL g, PBVAL bvp, char* fn, int pretty) {
bool b = false, err = true;
FILE* fs = NULL;
g->Message[0] = 0;
G->Message[0] = 0;
try {
if (!bvp) {
@@ -664,15 +666,15 @@ PSZ BDOC::Serialize(PGLOBAL g, PBVAL bvp, char* fn, int pretty) {
str = ((JOUTSTR*)jp)->Strp;
jp->WriteChr('\0');
PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
} else {
if (!g->Message[0])
} else if (G->Message[0])
strcpy(g->Message, "Error in Serialize");
} // endif's
else
GetMsg(g);
} catch (int n) {
if (trace(1))
htrc("Exception %d: %s\n", n, g->Message);
htrc("Exception %d: %s\n", n, G->Message);
GetMsg(g);
str = NULL;
} catch (const char* msg) {
strcpy(g->Message, msg);
@@ -796,10 +798,10 @@ bool BDOC::SerializeValue(PBVAL jvp) {
/***********************************************************************/
/* Program for sub-allocating Bjson structures. */
/***********************************************************************/
void* BJSON::BsonSubAlloc(PGLOBAL g, size_t size)
void* BJSON::BsonSubAlloc(size_t size)
{
PPOOLHEADER pph; /* Points on area header. */
void* memp = g->Sarea;
void* memp = G->Sarea;
size = ((size + 3) / 4) * 4; /* Round up size to multiple of 4 */
pph = (PPOOLHEADER)memp;
@@ -808,10 +810,10 @@ void* BJSON::BsonSubAlloc(PGLOBAL g, size_t size)
memp, size, pph->To_Free, pph->FreeBlk);
if (size > pph->FreeBlk) { /* Not enough memory left in pool */
sprintf(g->Message,
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);
xtrc(1, "BsonSubAlloc: %s\n", G->Message);
throw(1234);
} /* endif size OS32 code */
@@ -824,14 +826,29 @@ void* BJSON::BsonSubAlloc(PGLOBAL g, size_t size)
return memp;
} /* end of BsonSubAlloc */
/*********************************************************************************/
/* Program for SubSet re-initialization of the memory pool. */
/*********************************************************************************/
void BJSON::SubSet(bool b)
{
PPOOLHEADER pph = (PPOOLHEADER)G->Sarea;
pph->To_Free = (G->Saved_Size) ? G->Saved_Size : sizeof(POOLHEADER);
pph->FreeBlk = G->Sarea_Size - pph->To_Free;
if (b)
G->Saved_Size = 0;
} /* end of JsonSubSet */
/* ------------------------ Bobject functions ------------------------ */
/***********************************************************************/
/* Sub-allocate and initialize a BPAIR. */
/***********************************************************************/
PBPR BJSON::SubAllocPair(PGLOBAL g, OFFSET key, OFFSET val)
PBPR BJSON::SubAllocPair(OFFSET key, OFFSET val)
{
PBPR bpp = (PBPR)BsonSubAlloc(g, sizeof(BPAIR));
PBPR bpp = (PBPR)BsonSubAlloc(sizeof(BPAIR));
bpp->Key = key;
bpp->Vlp = val;
@@ -857,9 +874,9 @@ int BJSON::GetObjectSize(PBPR bop, bool b)
/***********************************************************************/
/* Add a new pair to an Object and return it. */
/***********************************************************************/
PBPR BJSON::AddPair(PGLOBAL g, PBPR bop, PSZ key, OFFSET val)
PBPR BJSON::AddPair(PBPR bop, PSZ key, OFFSET val)
{
PBPR brp, nrp = SubAllocPair(g, key, val);
PBPR brp, nrp = SubAllocPair(key, val);
if (bop) {
for (brp = bop; brp->Next; brp = MPP(brp->Next));
@@ -874,17 +891,17 @@ PBPR BJSON::AddPair(PGLOBAL g, PBPR bop, PSZ key, OFFSET val)
/***********************************************************************/
/* Return all object keys as an array. */
/***********************************************************************/
PBVAL BJSON::GetKeyList(PGLOBAL g, PBPR bop)
PBVAL BJSON::GetKeyList(PBPR bop)
{
PBVAL bvp, lvp, fvp = NULL;
for (PBPR brp = bop; brp; brp = MPP(brp->Next))
if (fvp) {
bvp = SubAllocVal(g, brp->Key, TYPE_STRG);
bvp = SubAllocVal(brp->Key, TYPE_STRG);
lvp->Next = MOF(bvp);
lvp = bvp;
} else
lvp = fvp = SubAllocVal(g, brp->Key, TYPE_STRG);
lvp = fvp = SubAllocVal(brp->Key, TYPE_STRG);
return fvp;
} // end of GetKeyList
@@ -892,17 +909,17 @@ PBVAL BJSON::GetKeyList(PGLOBAL g, PBPR bop)
/***********************************************************************/
/* Return all object values as an array. */
/***********************************************************************/
PBVAL BJSON::GetObjectValList(PGLOBAL g, PBPR bop)
PBVAL BJSON::GetObjectValList(PBPR bop)
{
PBVAL bvp, lvp, fvp = NULL;
for (PBPR brp = bop; brp; brp = MPP(brp->Next))
if (fvp) {
bvp = DupVal(g, MVP(brp->Vlp));
bvp = DupVal(MVP(brp->Vlp));
lvp->Next = MOF(bvp);
lvp = bvp;
} else
lvp = fvp = DupVal(g, MVP(brp->Vlp));
lvp = fvp = DupVal(MVP(brp->Vlp));
return fvp;
} // end of GetObjectValList
@@ -981,7 +998,7 @@ PSZ BJSON::GetObjectText(PGLOBAL g, PBPR bop, PSTRG text) {
/***********************************************************************/
/* Set or add a value corresponding to the given key. */
/***********************************************************************/
PBPR BJSON::SetKeyValue(PGLOBAL g, PBPR bop, OFFSET bvp, PSZ key)
PBPR BJSON::SetKeyValue(PBPR bop, OFFSET bvp, PSZ key)
{
PBPR brp = bop, prp = NULL;
@@ -994,10 +1011,10 @@ PBPR BJSON::SetKeyValue(PGLOBAL g, PBPR bop, OFFSET bvp, PSZ key)
prp = brp;
if (!brp)
prp->Vlp = MOF(SubAllocPair(g, key, bvp));
prp->Vlp = MOF(SubAllocPair(key, bvp));
} else
bop = SubAllocPair(g, key, bvp);
bop = SubAllocPair(key, bvp);
// Return the first pair of this object
return bop;
@@ -1006,11 +1023,11 @@ PBPR BJSON::SetKeyValue(PGLOBAL g, PBPR bop, OFFSET bvp, PSZ key)
/***********************************************************************/
/* Merge two objects. */
/***********************************************************************/
PBPR BJSON::MergeObject(PGLOBAL g, PBPR bop1, PBPR bop2)
PBPR BJSON::MergeObject(PBPR bop1, PBPR bop2)
{
if (bop1)
for (PBPR brp = bop2; brp; brp = MPP(brp->Next))
SetKeyValue(g, bop1, brp->Vlp, MZP(brp->Key));
SetKeyValue(bop1, brp->Vlp, MZP(brp->Key));
else
bop1 = bop2;
@@ -1087,10 +1104,10 @@ PBVAL BJSON::GetArrayValue(PBVAL bap, int n)
/***********************************************************************/
/* Add a Value to the Array Value list. */
/***********************************************************************/
PBVAL BJSON::AddArrayValue(PGLOBAL g, PBVAL bap, PBVAL nvp, int* x)
PBVAL BJSON::AddArrayValue(PBVAL bap, PBVAL nvp, int* x)
{
if (!nvp)
nvp = SubAllocVal(g);
nvp = NewVal();
if (bap) {
int i = 0, n = (x) ? *x : INT_MAX32;
@@ -1112,11 +1129,11 @@ PBVAL BJSON::AddArrayValue(PGLOBAL g, PBVAL bap, PBVAL nvp, int* x)
/***********************************************************************/
/* Merge two arrays. */
/***********************************************************************/
PBVAL BJSON::MergeArray(PGLOBAL g, PBVAL bap1, PBVAL bap2)
PBVAL BJSON::MergeArray(PBVAL bap1, PBVAL bap2)
{
if (bap1) {
for (PBVAL bvp = bap2; bvp; bvp = MVP(bvp->Next))
AddArrayValue(g, bap1, bvp);
AddArrayValue(bap1, bvp);
return bap1;
} else
@@ -1127,7 +1144,7 @@ PBVAL BJSON::MergeArray(PGLOBAL g, PBVAL bap1, PBVAL bap2)
/***********************************************************************/
/* Set the nth Value of the Array Value list or add it. */
/***********************************************************************/
PBVAL BJSON::SetArrayValue(PGLOBAL g, PBVAL bap, PBVAL nvp, int n)
PBVAL BJSON::SetArrayValue(PBVAL bap, PBVAL nvp, int n)
{
PBVAL bvp = bap, pvp = NULL;
@@ -1144,7 +1161,7 @@ PBVAL BJSON::SetArrayValue(PGLOBAL g, PBVAL bap, PBVAL nvp, int n)
} // endif bap
if (!bvp) {
bvp = DupVal(g, nvp);
bvp = DupVal(nvp);
if (pvp)
pvp->Next = MOF(bvp);
@@ -1233,47 +1250,56 @@ bool BJSON::IsArrayNull(PBVAL bap)
/***********************************************************************/
/* Sub-allocate and clear a BVAL. */
/***********************************************************************/
PBVAL BJSON::SubAllocVal(PGLOBAL g)
PBVAL BJSON::NewVal(int type)
{
PBVAL bvp = (PBVAL)BsonSubAlloc(g, sizeof(BVAL));
PBVAL bvp = (PBVAL)BsonSubAlloc(sizeof(BVAL));
bvp->To_Val = 0;
bvp->Nd = 0;
bvp->Type = TYPE_NULL;
bvp->Next = 0;
return bvp;
} // end of SubAllocVal
/***********************************************************************/
/* Sub-allocate and initialize a BVAL as string. */
/***********************************************************************/
PBVAL BJSON::SubAllocVal(PGLOBAL g, OFFSET toval, int 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
/***********************************************************************/
/* Sub-allocate and initialize a BVAL as type. */
/***********************************************************************/
PBVAL BJSON::SubAllocVal(OFFSET toval, int type, short nd)
{
PBVAL bvp = NewVal(type);
bvp->To_Val = toval;
bvp->Nd = nd;
return bvp;
} // end of SubAllocVal
/***********************************************************************/
/* Sub-allocate and initialize a BVAL as string. */
/***********************************************************************/
PBVAL BJSON::SubAllocStr(OFFSET toval, short nd)
{
PBVAL bvp = NewVal(TYPE_STRG);
bvp->To_Val = toval;
bvp->Nd = nd;
return bvp;
} // end of SubAllocVal
/***********************************************************************/
/* Allocate a BVALUE with a given string or numeric value. */
/***********************************************************************/
PBVAL BJSON::SubAllocVal(PGLOBAL g, PVAL valp)
PBVAL BJSON::SubAllocVal(PVAL valp)
{
PBVAL vlp = SubAllocVal(g);
SetValue(g, vlp, valp);
vlp->Next = NULL;
PBVAL vlp = NewVal();
SetValue(vlp, valp);
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));
PBVAL BJSON::DupVal(PBVAL bvlp) {
PBVAL bvp = NewVal();
*bvp = *bvlp;
bvp->Next = 0;
@@ -1539,7 +1565,7 @@ double BJSON::GetDouble(PBVAL vp)
/***********************************************************************/
/* Return the Value's String value. */
/***********************************************************************/
PSZ BJSON::GetString(PGLOBAL g, PBVAL vp, char* buff)
PSZ BJSON::GetString(PBVAL vp, char* buff)
{
char buf[32];
char* p = (buff) ? buff : buf;
@@ -1572,7 +1598,7 @@ PSZ BJSON::GetString(PGLOBAL g, PBVAL vp, char* buff)
p = NULL;
} // endswitch Type
return (p == buf) ? (PSZ)PlugDup(g, buf) : p;
return (p == buf) ? (PSZ)PlugDup(G, buf) : p;
} // end of GetString
/***********************************************************************/
@@ -1585,7 +1611,7 @@ PSZ BJSON::GetValueText(PGLOBAL g, PBVAL vlp, PSTRG text) {
return GetArrayText(g, MVP(vlp->To_Val), text);
char buff[32];
PSZ s = (vlp->Type == TYPE_NULL) ? NULL : GetString(g, vlp, buff);
PSZ s = (vlp->Type == TYPE_NULL) ? NULL : GetString(vlp, buff);
if (s)
text->Append(s);
@@ -1614,7 +1640,7 @@ void BJSON::SetValueVal(PBVAL vlp, PBVAL vp)
vlp->Type = vp->Type;
} // end of SetValue;
void BJSON::SetValue(PGLOBAL g, PBVAL vlp, PVAL valp)
void BJSON::SetValue(PBVAL vlp, PVAL valp)
{
if (!valp || valp->IsNull()) {
vlp->Type = TYPE_NULL;
@@ -1625,7 +1651,7 @@ void BJSON::SetValue(PGLOBAL g, PBVAL vlp, PVAL valp)
else {
char buf[32];
vlp->To_Val = MOF(PlugDup(g, valp->GetCharString(buf)));
vlp->To_Val = MOF(PlugDup(G, valp->GetCharString(buf)));
} // endif Formatted
vlp->Type = TYPE_DTM;
@@ -1642,7 +1668,7 @@ void BJSON::SetValue(PGLOBAL g, PBVAL vlp, PVAL valp)
vlp->F = (float)valp->GetFloatValue();
vlp->Type = TYPE_FLOAT;
} else {
double *dp = (double*)PlugSubAlloc(g, NULL, sizeof(double));
double *dp = (double*)PlugSubAlloc(G, NULL, sizeof(double));
*dp = valp->GetFloatValue();
vlp->To_Val = MOF(dp);
@@ -1663,7 +1689,7 @@ void BJSON::SetValue(PGLOBAL g, PBVAL vlp, PVAL valp)
vlp->N = valp->GetIntValue();
vlp->Type = TYPE_INTG;
} else {
longlong* llp = (longlong*)PlugSubAlloc(g, NULL, sizeof(longlong));
longlong* llp = (longlong*)PlugSubAlloc(G, NULL, sizeof(longlong));
*llp = valp->GetBigintValue();
vlp->To_Val = MOF(llp);
@@ -1672,7 +1698,7 @@ void BJSON::SetValue(PGLOBAL g, PBVAL vlp, PVAL valp)
break;
default:
sprintf(g->Message, "Unsupported typ %d\n", valp->GetType());
sprintf(G->Message, "Unsupported typ %d\n", valp->GetType());
throw(777);
} // endswitch Type
@@ -1699,13 +1725,13 @@ void BJSON::SetBool(PBVAL vlp, bool b)
/***********************************************************************/
/* Set the Value's value as the given big integer. */
/***********************************************************************/
void BJSON::SetBigint(PGLOBAL g, PBVAL vlp, longlong ll)
void BJSON::SetBigint(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));
longlong* llp = (longlong*)PlugSubAlloc(G, NULL, sizeof(longlong));
*llp = ll;
vlp->To_Val = MOF(llp);

View File

@@ -69,54 +69,64 @@ DllExport bool IsNum(PSZ s);
class BJSON : public BLOCK {
public:
// Constructor
BJSON(void* base, PBVAL vp = NULL) { Base = base; Bvp = vp; }
BJSON(PGLOBAL g, PBVAL vp = NULL) { G = g, Base = G->Sarea; Bvp = vp; }
void* GetBase(void) { return Base; }
void SubSet(bool b = false);
void MemSave(void) {G->Saved_Size = ((PPOOLHEADER)G->Sarea)->To_Free;}
void GetMsg(PGLOBAL g) { if (g != G) strcpy(g->Message, G->Message); }
// SubAlloc functions
void* BsonSubAlloc(PGLOBAL g, size_t size);
PBPR SubAllocPair(PGLOBAL g, OFFSET key, OFFSET val = 0);
PBPR SubAllocPair(PGLOBAL g, PSZ key, OFFSET val = 0)
{return SubAllocPair(g, MOF(key), val);}
PBVAL SubAllocVal(PGLOBAL g);
PBVAL SubAllocVal(PGLOBAL g, OFFSET toval, int type = TYPE_NULL, short nd = 0);
PBVAL SubAllocVal(PGLOBAL g, PBVAL toval, int type = TYPE_NULL, short nd = 0)
{return SubAllocVal(g, MOF(toval), type, nd);}
PBVAL SubAllocVal(PGLOBAL g, PSZ str, int type = TYPE_STRG, short nd = 0)
{return SubAllocVal(g, MOF(str), type, nd);}
PBVAL SubAllocVal(PGLOBAL g, PVAL valp);
PBVAL DupVal(PGLOBAL g, PBVAL bvp);
void* BsonSubAlloc(size_t size);
PBPR SubAllocPair(OFFSET key, OFFSET val = 0);
PBPR SubAllocPair(PSZ key, OFFSET val = 0)
{return SubAllocPair(MOF(key), val);}
PBVAL NewVal(int type = TYPE_NULL);
PBVAL SubAllocVal(OFFSET toval, int type = TYPE_NULL, short nd = 0);
PBVAL SubAllocVal(PBVAL toval, int type = TYPE_NULL, short nd = 0)
{return SubAllocVal(MOF(toval), type, nd);}
PBVAL SubAllocStr(OFFSET str, short nd = 0);
PBVAL SubAllocStr(PSZ str, short nd = 0)
{return SubAllocStr(MOF(str), nd);}
PBVAL SubAllocVal(PVAL valp);
PBVAL DupVal(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 MergeArray(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);
PBVAL AddArrayValue(PBVAL bap, PBVAL nvp = NULL, int* x = NULL);
PBVAL SetArrayValue(PBVAL bap, PBVAL nvp, int n);
bool IsArrayNull(PBVAL bap);
// Object functions
int GetObjectSize(PBPR bop, bool b = false);
PBPR GetNext(PBPR prp) {return MPP(prp->Next);}
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);
PBPR MergeObject(PBPR bop1, PBPR bop2);
PBPR AddPair(PBPR bop, PSZ key, OFFSET val = 0);
PSZ GetKey(PBPR prp) {return MZP(prp->Key);}
PBVAL GetVal(PBPR prp) {return MVP(prp->Vlp);}
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);
PBVAL GetKeyList(PBPR bop);
PBVAL GetObjectValList(PBPR bop);
PBPR SetKeyValue(PBPR bop, OFFSET bvp, PSZ key);
inline PBPR SetKeyValue(PBPR bop, PBVAL vlp, PSZ key)
{return SetKeyValue(bop, MOF(vlp), key);}
PBPR DeleteKey(PBPR bop, PCSZ k);
bool IsObjectNull(PBPR bop);
// Value functions
int GetSize(PBVAL vlp, bool b = false);
PBVAL GetNext(PBVAL vlp) {return MVP(vlp->Next);}
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);
inline PBVAL GetBson(PBVAL bvp) { return IsJson(bvp) ? MVP(bvp->To_Val) : bvp; }
PSZ GetString(PBVAL vp, char* buff = NULL);
int GetInteger(PBVAL vp);
long long GetBigint(PBVAL vp);
double GetDouble(PBVAL vp);
@@ -124,17 +134,20 @@ public:
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 SetValue(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 SetBigint(PBVAL vlp, longlong ll);
void SetFloat(PBVAL vlp, double f);
void SetBool(PBVAL vlp, bool b);
void Clear(PBVAL vlp) { vlp->N = 0; vlp->Nd = 0; vlp->Next = 0; vlp->Type = TYPE_NULL; }
bool IsValueNull(PBVAL vlp);
bool IsJson(PBVAL vlp) {return (vlp->Type == TYPE_JAR || vlp->Type == TYPE_JOB);}
// Members
PGLOBAL G;
PBVAL Bvp;
void* Base;
void *Base;
protected:
// Default constructor not to be used
@@ -146,18 +159,18 @@ protected:
/***********************************************************************/
class BDOC : public BJSON {
public:
BDOC(void *);
BDOC(PGLOBAL G);
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);
protected:
OFFSET ParseArray(PGLOBAL g, int& i);
OFFSET ParseObject(PGLOBAL g, int& i);
PBVAL ParseValue(PGLOBAL g, int& i);
OFFSET ParseString(PGLOBAL g, int& i);
void ParseNumeric(PGLOBAL g, int& i, PBVAL bvp);
OFFSET ParseAsArray(PGLOBAL g, int& i, int pretty, int* ptyp);
OFFSET ParseArray(int& i);
OFFSET ParseObject(int& i);
PBVAL ParseValue(int& i);
OFFSET ParseString(int& i);
void ParseNumeric(int& i, PBVAL bvp);
OFFSET ParseAsArray(int& i, int pretty, int* ptyp);
bool SerializeArray(OFFSET arp, bool b);
bool SerializeObject(OFFSET obp);
bool SerializeValue(PBVAL vp);

View File

@@ -41,7 +41,7 @@ inline void JsonMemSave(PGLOBAL g) {
/*********************************************************************************/
inline void JsonFreeMem(PGLOBAL g) {
g->Activityp = NULL;
PlugExit(g);
g = PlugExit(g);
} /* end of JsonFreeMem */
/* --------------------------- New Testing BJSON Stuff --------------------------*/
@@ -71,8 +71,7 @@ static PBJNX BjnxNew(PGLOBAL g, PBVAL vlp, int type, int len)
/*********************************************************************************/
/* BSNX public constructor. */
/*********************************************************************************/
BJNX::BJNX(PGLOBAL g, PBVAL row, int type, int len, int prec, my_bool wr)
: BDOC(g->Sarea)
BJNX::BJNX(PGLOBAL g, PBVAL row, int type, int len, int prec, my_bool wr) : BDOC(g)
{
Row = row;
Bvalp = NULL;
@@ -361,7 +360,7 @@ void BJNX::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL vlp)
} else switch (vlp->Type) {
case TYPE_DTM:
case TYPE_STRG:
vp->SetValue_psz(GetString(g, vlp));
vp->SetValue_psz(GetString(vlp));
break;
case TYPE_INTG:
case TYPE_BINT:
@@ -371,14 +370,14 @@ void BJNX::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL vlp)
if (vp->IsTypeNum())
vp->SetValue(GetDouble(vlp));
else // Get the proper number of decimals
vp->SetValue_psz(GetString(g, vlp));
vp->SetValue_psz(GetString(vlp));
break;
case TYPE_BOOL:
if (vp->IsTypeNum())
vp->SetValue(GetInteger(vlp) ? 1 : 0);
else
vp->SetValue_psz(GetString(g, vlp));
vp->SetValue_psz(GetString(vlp));
break;
case TYPE_JAR:
@@ -439,7 +438,7 @@ PBVAL BJNX::GetRowValue(PGLOBAL g, PBVAL row, int i, my_bool b)
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);
vlp = SubAllocVal(Value);
return vlp;
} else if (Nodes[i].Op == OP_XX) {
Jb = b;
@@ -473,7 +472,7 @@ PBVAL BJNX::GetRowValue(PGLOBAL g, PBVAL row, int i, my_bool b)
else if (Nodes[i].Op == OP_EXP)
return (PBVAL)ExpandArray(g, bap, i);
else
return SubAllocVal(g, CalculateArray(g, bap, i));
return SubAllocVal(CalculateArray(g, bap, i));
} else {
// Unexpected array, unwrap it as [0]
@@ -701,12 +700,12 @@ PBVAL BJNX::GetRow(PGLOBAL g)
// nwr = SubAllocPair(g);
// Construct new row
nwr = SubAllocVal(g);
nwr = NewVal();
if (row->Type == TYPE_JOB) {
SetKeyValue(g, MPP(row->To_Val), MOF(nwr), Nodes[i - 1].Key);
SetKeyValue(MPP(row->To_Val), MOF(nwr), Nodes[i - 1].Key);
} else if (row->Type == TYPE_JAR) {
AddArrayValue(g, MVP(row->To_Val), nwr);
AddArrayValue(MVP(row->To_Val), nwr);
} else {
strcpy(g->Message, "Wrong type when writing new row");
nwr = NULL;
@@ -748,15 +747,15 @@ my_bool BJNX::WriteValue(PGLOBAL g, PBVAL jvalp)
if (arp) {
if (!Nodes[Nod - 1].Key) {
if (Nodes[Nod - 1].Op == OP_EQ)
SetArrayValue(g, arp, jvalp, Nodes[Nod - 1].Rank);
SetArrayValue(arp, jvalp, Nodes[Nod - 1].Rank);
else
AddArrayValue(g, arp, jvalp);
AddArrayValue(arp, jvalp);
} // endif Key
} else if (objp) {
if (Nodes[Nod - 1].Key)
SetKeyValue(g, objp, MOF(jvalp), Nodes[Nod - 1].Key);
SetKeyValue(objp, MOF(jvalp), Nodes[Nod - 1].Key);
} else if (jvp)
SetValueVal(jvp, jvalp);
@@ -1159,8 +1158,8 @@ static PBVAL MakeBinValue(PGLOBAL g, UDF_ARGS* args, uint i)
int n, len;
int ci;
longlong bigint;
BDOC doc(g->Sarea);
PBVAL bp, bvp = doc.SubAllocVal(g);
BDOC doc(g);
PBVAL bp, bvp = doc.NewVal();
if (sap) {
if (args->arg_type[i] == STRING_RESULT) {
@@ -1209,7 +1208,7 @@ static PBVAL MakeBinValue(PGLOBAL g, UDF_ARGS* args, uint i)
(bigint == 1LL && !strcmp(args->attributes[i], "TRUE")))
doc.SetBool(bvp, (bool)bigint);
else
doc.SetBigint(g, bvp, bigint);
doc.SetBigint(bvp, bigint);
break;
case REAL_RESULT:
@@ -1256,7 +1255,7 @@ char* bsonvalue(UDF_INIT* initid, UDF_ARGS* args, char* result,
if (!g->Xchk) {
if (!CheckMemory(g, initid, args, 1, false)) {
BDOC doc(g->Sarea);
BDOC doc(g);
PBVAL bvp = MakeBinValue(g, args, 0);
if (!(str = doc.Serialize(g, bvp, NULL, 0)))
@@ -1297,13 +1296,13 @@ char* bson_make_array(UDF_INIT* initid, UDF_ARGS* args, char* result,
if (!g->Xchk) {
if (!CheckMemory(g, initid, args, args->arg_count, false)) {
BDOC doc(g->Sarea);
BDOC doc(g);
PBVAL bvp = NULL, arp = NULL;
for (uint i = 0; i < args->arg_count; i++)
bvp = doc.AddArrayValue(g, bvp, MakeBinValue(g, args, i));
bvp = doc.AddArrayValue(bvp, MakeBinValue(g, args, i));
arp = doc.SubAllocVal(g, bvp, TYPE_JAR);
arp = doc.SubAllocVal(bvp, TYPE_JAR);
if (!(str = doc.Serialize(g, arp, NULL, 0)))
str = strcpy(result, g->Message);
@@ -1364,7 +1363,7 @@ char* bson_array_add_values(UDF_INIT* initid, UDF_ARGS* args, char* result,
if (!CheckMemory(g, initid, args, args->arg_count, true)) {
uint n = 1;
bool b = false;
BDOC doc(g->Sarea);
BDOC doc(g);
PBVAL bvp = NULL, arp = MakeBinValue(g, args, 0);
if (arp->Type == TYPE_JAR) {
@@ -1374,10 +1373,10 @@ char* bson_array_add_values(UDF_INIT* initid, UDF_ARGS* args, char* result,
n = 0;
for (uint i = n; i < args->arg_count; i++)
bvp = doc.AddArrayValue(g, bvp, MakeBinValue(g, args, i));
bvp = doc.AddArrayValue(bvp, MakeBinValue(g, args, i));
if (!n)
arp = doc.SubAllocVal(g, bvp, TYPE_JAR);
arp = doc.SubAllocVal(bvp, TYPE_JAR);
else if (b)
doc.SetValueArr(arp, bvp);

View File

@@ -73,8 +73,7 @@ PGLOBAL CntExit(PGLOBAL g)
g->Activityp = NULL;
} // endif Activityp
PlugExit(g);
g= NULL;
g= PlugExit(g);
} // endif g
return g;

View File

@@ -208,7 +208,7 @@ DllExport char *PlugGetMessage(PGLOBAL, int);
DllExport short GetLineLength(PGLOBAL); // Console line length
#endif // __WIN__
DllExport PGLOBAL PlugInit(LPCSTR, size_t); // Plug global initialization
DllExport int PlugExit(PGLOBAL); // Plug global termination
DllExport PGLOBAL PlugExit(PGLOBAL); // Plug global termination
DllExport LPSTR PlugRemoveType(LPSTR, LPCSTR);
DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR prefix, LPCSTR name, LPCSTR dir);
DllExport BOOL PlugIsAbsolutePath(LPCSTR path);

View File

@@ -170,7 +170,7 @@
#define JSONMAX 10 // JSON Default max grp size
extern "C" {
char version[]= "Version 1.07.0002 November 13, 2020";
char version[]= "Version 1.07.0002 November 30, 2020";
#if defined(__WIN__)
char compver[]= "Version 1.07.0002 " __DATE__ " " __TIME__;
char slash= '\\';
@@ -230,6 +230,9 @@ char *GetUserVariable(PGLOBAL g, const uchar *varname)
PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
PQRYRES VirColumns(PGLOBAL g, bool info);
PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info);
#ifdef DEVELOPMENT
PQRYRES BSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info);
#endif // DEVEOPMENT
PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info);
#if defined(REST_SUPPORT)
PQRYRES RESTColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
@@ -4513,6 +4516,9 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
case TAB_VEC:
case TAB_REST:
case TAB_JSON:
#if defined DEVELOPMENT
case TAB_BSON:
#endif // DEVELOPMENT
if (options->filename && *options->filename) {
if (!quick) {
char path[FN_REFLEN], dbpath[FN_REFLEN];
@@ -5679,6 +5685,9 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
} else if (topt->http) {
switch (ttp) {
case TAB_JSON:
#ifdef DEVELOPMENT
case TAB_BSON:
#endif // DEVELOPMENT
case TAB_XML:
case TAB_CSV:
ttp = TAB_REST;
@@ -5863,6 +5872,9 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
case TAB_XML:
#endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT
case TAB_JSON:
#ifdef DEVELOPMENT
case TAB_BSON:
#endif // DEVELOPMENT
dsn= strz(g, create_info->connect_string);
if (!fn && !zfn && !mul && !dsn)
@@ -6029,6 +6041,11 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
case TAB_JSON:
qrp= JSONColumns(g, db, dsn, topt, fnc == FNC_COL);
break;
#ifdef DEVELOPMENT
case TAB_BSON:
qrp= BSONColumns(g, db, dsn, topt, fnc == FNC_COL);
break;
#endif // DEVELOPMENT
#if defined(JAVA_SUPPORT)
case TAB_MONGO:
url= strz(g, create_info->connect_string);

View File

@@ -1178,7 +1178,7 @@ my_bool JsonSubSet(PGLOBAL g)
{
PPOOLHEADER pph = (PPOOLHEADER)g->Sarea;
pph->To_Free = (g->Saved_Size) ? g->Saved_Size : (size_t)sizeof(POOLHEADER);
pph->To_Free = (g->Saved_Size) ? g->Saved_Size : sizeof(POOLHEADER);
pph->FreeBlk = g->Sarea_Size - pph->To_Free;
g->Saved_Size = 0;
return FALSE;
@@ -1198,7 +1198,7 @@ inline void JsonMemSave(PGLOBAL g)
inline void JsonFreeMem(PGLOBAL g)
{
g->Activityp = NULL;
PlugExit(g);
g = PlugExit(g);
} /* end of JsonFreeMem */
/*********************************************************************************/
@@ -1281,7 +1281,7 @@ my_bool JsonInit(UDF_INIT *initid, UDF_ARGS *args, char *message, my_bool mbn,
return true;
} else if (g->Sarea_Size == 0) {
strcpy(message, g->Message);
PlugExit(g);
g = PlugExit(g);
return true;
} // endif g

View File

@@ -16,9 +16,9 @@
/*************** Mycat CC Program Source Code File (.CC) ***************/
/* PROGRAM NAME: MYCAT */
/* ------------- */
/* Version 1.7 */
/* Version 1.8 */
/* */
/* Author: Olivier Bertrand 2012 - 2019 */
/* Author: Olivier Bertrand 2012 - 2020 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -82,7 +82,11 @@
#endif // JAVA_SUPPORT
#include "tabpivot.h"
#include "tabvir.h"
#if defined(DEVELOPMENT)
#include "tabbson.h"
#else
#include "tabjson.h"
#endif // DEVELOPMENT
#include "ha_connect.h"
#if defined(XML_SUPPORT)
#include "tabxml.h"
@@ -157,6 +161,9 @@ TABTYPE GetTypeID(const char *type)
: (!stricmp(type, "PIVOT")) ? TAB_PIVOT
: (!stricmp(type, "VIR")) ? TAB_VIR
: (!stricmp(type, "JSON")) ? TAB_JSON
#if defined(DEVELOPMENT)
: (!stricmp(type, "BSON")) ? TAB_BSON
#endif
#if defined(ZIP_SUPPORT)
: (!stricmp(type, "ZIP")) ? TAB_ZIP
#endif
@@ -181,6 +188,9 @@ bool IsFileType(TABTYPE type)
case TAB_INI:
case TAB_VEC:
case TAB_JSON:
#if defined(DEVELOPMENT)
case TAB_BSON:
#endif
case TAB_REST:
// case TAB_ZIP:
isfile= true;
@@ -276,6 +286,9 @@ bool IsTypeIndexable(TABTYPE type)
case TAB_VEC:
case TAB_DBF:
case TAB_JSON:
#if defined(DEVELOPMENT)
case TAB_BSON:
#endif
idx= true;
break;
default:
@@ -302,6 +315,9 @@ int GetIndexType(TABTYPE type)
case TAB_VEC:
case TAB_DBF:
case TAB_JSON:
#if defined(DEVELOPMENT)
case TAB_BSON:
#endif
xtyp= 1;
break;
case TAB_MYSQL:
@@ -445,7 +461,7 @@ PTABDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
case TAB_XML: tdp= new(g) XMLDEF; break;
#endif // XML_SUPPORT
#if defined(VCT_SUPPORT)
case TAB_VEC: tdp = new(g) VCTDEF; break;
case TAB_VEC: tdp= new(g) VCTDEF; break;
#endif // VCT_SUPPORT
#if defined(ODBC_SUPPORT)
case TAB_ODBC: tdp= new(g) ODBCDEF; break;
@@ -466,8 +482,11 @@ PTABDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
case TAB_PIVOT: tdp= new(g) PIVOTDEF; break;
case TAB_VIR: tdp= new(g) VIRDEF; break;
case TAB_JSON: tdp= new(g) JSONDEF; break;
#if defined(DEVELOPMENT)
case TAB_BSON: tdp= new(g) BSONDEF; break;
#endif
#if defined(ZIP_SUPPORT)
case TAB_ZIP: tdp = new(g) ZIPDEF; break;
case TAB_ZIP: tdp= new(g) ZIPDEF; break;
#endif // ZIP_SUPPORT
#if defined(REST_SUPPORT)
case TAB_REST: tdp= new (g) RESTDEF; break;

View File

@@ -323,7 +323,7 @@ HEX(c) 3F3F3F3F3F3F3F
Warnings:
Level Warning
Code 1366
Message Incorrect string value: '\xC3\x81\xC3\x82\xC3\x83...' for column 'c' at row 1
Message Incorrect string value: '\xC3\x81\xC3\x82\xC3\x83...' for column `test`.`t1`.`c` at row 1
Level Warning
Code 1105
Message Out of range value ÁÂÃÄÅÆÇ for column 'c' at row 1
@@ -374,7 +374,7 @@ INSERT INTO t1 VALUES (_cp1251 0xC0C1C2C3);
Warnings:
Level Warning
Code 1105
Message Com error: Unable to save character to 'iso-8859-1' encoding.
Message Com error: Impossible d'enregistrer le caract<EFBFBD>re dans le codage iso-8859-1.
INSERT INTO t1 VALUES ('&<>"\'');
SELECT node, hex(node) FROM t1;

View File

@@ -83,7 +83,8 @@ enum TABTYPE {TAB_UNDEF = 0, /* Table of undefined type */
TAB_ZIP = 27, /* ZIP file info table */
TAB_MONGO = 28, /* Table retrieved from MongoDB */
TAB_REST = 29, /* Table retrieved from Rest */
TAB_NIY = 30}; /* Table not implemented yet */
TAB_BSON = 30, /* BSON Table (development) */
TAB_NIY = 31}; /* Table not implemented yet */
enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_ROWID = 1, /* ROWID type (special column) */

View File

@@ -184,7 +184,7 @@ PGLOBAL PlugInit(LPCSTR Language, size_t worksize)
/***********************************************************************/
/* PlugExit: Terminate Plug operations. */
/***********************************************************************/
int PlugExit(PGLOBAL g)
PGLOBAL PlugExit(PGLOBAL g)
{
if (g) {
PDBUSER dup = PlgGetUser(g);
@@ -196,7 +196,7 @@ int PlugExit(PGLOBAL g)
delete g;
} // endif g
return 0;
return NULL;
} // end of PlugExit
/***********************************************************************/
@@ -483,9 +483,10 @@ bool AllocSarea(PGLOBAL g, size_t size)
#else
if (trace(8)) {
#endif
if (g->Sarea)
if (g->Sarea) {
htrc("Work area of %zd allocated at %p\n", size, g->Sarea);
else
PlugSubSet(g->Sarea, size);
} else
htrc("SareaAlloc: %s\n", g->Message);
} // endif trace

2599
storage/connect/tabbson.cpp Normal file

File diff suppressed because it is too large Load Diff

342
storage/connect/tabbson.h Normal file
View File

@@ -0,0 +1,342 @@
/*************** tabbson H Declares Source Code File (.H) **************/
/* Name: tabbson.h Version 1.0 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2020 */
/* */
/* This file contains the BSON classes declares. */
/***********************************************************************/
#pragma once
#include "block.h"
#include "colblk.h"
#include "bson.h"
#include "tabjson.h"
typedef class BTUTIL* PBTUT;
typedef class BCUTIL* PBCUT;
typedef class BSONDEF* PBDEF;
typedef class TDBBSON* PBTDB;
typedef class BSONCOL* PBSCOL;
class TDBBSN;
DllExport PQRYRES BSONColumns(PGLOBAL, PCSZ, PCSZ, PTOS, bool);
/***********************************************************************/
/* Class used to get the columns of a mongo collection. */
/***********************************************************************/
class BSONDISC : public BLOCK {
public:
// Constructor
BSONDISC(PGLOBAL g, uint* lg);
// Functions
int GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt);
bool Find(PGLOBAL g, PBVAL jvp, PCSZ key, int j);
void AddColumn(PGLOBAL g);
// Members
JCOL jcol;
PJCL jcp, fjcp, pjcp;
//PVL vlp;
PBDEF tdp;
TDBBSN *tjnp;
PBTDB tjsp;
PBPR jpp;
PBVAL jsp;
PBPR row;
PBTUT bp;
PCSZ sep;
char colname[65], fmt[129], buf[16];
uint *length;
int i, n, bf, ncol, lvl, sz, limit;
bool all, strfy;
}; // end of BSONDISC
/***********************************************************************/
/* JSON table. */
/***********************************************************************/
class DllExport BSONDEF : public DOSDEF { /* Table description */
friend class TDBBSON;
friend class TDBBSN;
friend class TDBBCL;
friend class BSONDISC;
friend class BSONCOL;
#if defined(CMGO_SUPPORT)
friend class CMGFAM;
#endif // CMGO_SUPPORT
#if defined(JAVA_SUPPORT)
friend class JMGFAM;
#endif // JAVA_SUPPORT
public:
// Constructor
BSONDEF(void);
// Implementation
virtual const char* GetType(void) { return "BSON"; }
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
protected:
// Members
PGLOBAL G; /* Bson utility memory */
JMODE Jmode; /* MODE_OBJECT by default */
PCSZ Objname; /* Name of first level object */
PCSZ Xcol; /* Name of expandable column */
int Limit; /* Limit of multiple values */
int Pretty; /* Depends on file structure */
int Base; /* The array index base */
bool Strict; /* Strict syntax checking */
char Sep; /* The Jpath separator */
const char* Uri; /* MongoDB connection URI */
PCSZ Collname; /* External collection name */
PSZ Options; /* Colist ; Pipe */
PSZ Filter; /* Filter */
PSZ Driver; /* MongoDB Driver (C or JAVA) */
bool Pipe; /* True if Colist is a pipeline */
int Version; /* Driver version */
PSZ Wrapname; /* MongoDB java wrapper name */
}; // end of BSONDEF
/* -------------------------- BTUTIL class --------------------------- */
/***********************************************************************/
/* Handles all BJSON actions for a BSON table. */
/***********************************************************************/
class BTUTIL : public BDOC {
public:
// Constructor
BTUTIL(PGLOBAL G, TDBBSN* tp) : BDOC(G) { Tp = tp; }
// Utility functions
PBVAL FindRow(PGLOBAL g);
PBVAL ParseLine(PGLOBAL g, int *pretty, bool *comma);
PBVAL MakeTopTree(PGLOBAL g, PBVAL jsp);
PSZ SerialVal(PGLOBAL g, PBVAL top, int pretty);
protected:
// Members
TDBBSN* Tp;
}; // end of class BTUTIL
/* -------------------------- BCUTIL class --------------------------- */
/***********************************************************************/
/* Handles all BJSON actions for a BSON columns. */
/***********************************************************************/
class BCUTIL : public BTUTIL {
public:
// Constructor
BCUTIL(PGLOBAL G, PBSCOL cp, TDBBSN* tp) : BTUTIL(G, tp) { Cp = cp; }
// Utility functions
void SetJsonValue(PGLOBAL g, PVAL vp, PBVAL jvp);
PVAL MakeBson(PGLOBAL g, PBVAL jsp);
PVAL GetColumnValue(PGLOBAL g, PBVAL row, int i);
PVAL ExpandArray(PGLOBAL g, PBVAL arp, int n);
PVAL CalculateArray(PBVAL arp, int n);
PBVAL GetRow(PGLOBAL g);
protected:
// Member
PBSCOL Cp;
}; // end of class BCUTIL
/* -------------------------- TDBBSN class --------------------------- */
/***********************************************************************/
/* This is the BSN Access Method class declaration. */
/* The table is a DOS file, each record being a JSON object. */
/***********************************************************************/
class DllExport TDBBSN : public TDBDOS {
friend class BSONCOL;
friend class BSONDEF;
friend class BTUTIL;
friend class BCUTIL;
friend class BSONDISC;
#if defined(CMGO_SUPPORT)
friend class CMGFAM;
#endif // CMGO_SUPPORT
#if defined(JAVA_SUPPORT)
friend class JMGFAM;
#endif // JAVA_SUPPORT
public:
// Constructor
TDBBSN(PGLOBAL g, PBDEF tdp, PTXF txfp);
TDBBSN(TDBBSN* tdbp);
// Implementation
virtual AMT GetAmType(void) { return TYPE_AM_JSN; }
virtual bool SkipHeader(PGLOBAL g);
virtual PTDB Duplicate(PGLOBAL g) { return (PTDB)new(g) TDBBSN(this); }
PBVAL GetRow(void) { return Row; }
// Methods
virtual PTDB Clone(PTABS t);
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual PCOL InsertSpecialColumn(PCOL colp);
virtual int RowNumber(PGLOBAL g, bool b = FALSE) {return (b) ? M : N;}
virtual bool CanBeFiltered(void)
{return Txfp->GetAmType() == TYPE_AM_MGO || !Xcol;}
// Database routines
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual bool PrepareWriting(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual void CloseDB(PGLOBAL g);
// Specific routine
virtual int EstimatedLength(void);
protected:
PBVAL FindRow(PGLOBAL g);
//int MakeTopTree(PGLOBAL g, PBVAL jsp);
// Members
PBTUT Bp; // The BSUTIL handling class
PBVAL Top; // The top JSON tree
PBVAL Row; // The current row
PBVAL Val; // The value of the current row
PBSCOL Colp; // The multiple column
JMODE Jmode; // MODE_OBJECT by default
PCSZ Objname; // The table object name
PCSZ Xcol; // Name of expandable column
int Fpos; // The current row index
int N; // The current Rownum
int M; // Index of multiple value
int Limit; // Limit of multiple values
int Pretty; // Depends on file structure
int NextSame; // Same next row
int SameRow; // Same row nb
int Xval; // Index of expandable array
int B; // Array index base
char Sep; // The Jpath separator
bool Strict; // Strict syntax checking
bool Comma; // Row has final comma
}; // end of class TDBBSN
/* -------------------------- BSONCOL class -------------------------- */
/***********************************************************************/
/* Class BSONCOL: JSON access method column descriptor. */
/***********************************************************************/
class DllExport BSONCOL : public DOSCOL {
friend class TDBBSN;
friend class TDBBSON;
friend class BCUTIL;
#if defined(CMGO_SUPPORT)
friend class CMGFAM;
#endif // CMGO_SUPPORT
#if defined(JAVA_SUPPORT)
friend class JMGFAM;
#endif // JAVA_SUPPORT
public:
// Constructors
BSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
BSONCOL(BSONCOL* colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) { return Tbp->GetAmType(); }
// Methods
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
bool ParseJpath(PGLOBAL g);
virtual PSZ GetJpath(PGLOBAL g, bool proj);
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
protected:
bool CheckExpand(PGLOBAL g, int i, PSZ nm, bool b);
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 MakeBson(PGLOBAL g, PBVAL jsp);
//void SetJsonValue(PGLOBAL g, PVAL vp, PBVAL val);
//PBVAL GetRow(PGLOBAL g);
// Default constructor not to be used
BSONCOL(void) {}
// Members
TDBBSN *Tbp; // To the JSN table block
PBCUT Cp; // To the BCUTIL handling class
PVAL MulVal; // To value used by multiple column
char *Jpath; // The json path
JNODE *Nodes; // The intermediate objects
int Nod; // The number of intermediate objects
int Xnod; // Index of multiple values
char Sep; // The Jpath separator
bool Xpd; // True for expandable column
bool Parsed; // True when parsed
}; // end of class BSONCOL
/* -------------------------- TDBBSON class -------------------------- */
/***********************************************************************/
/* This is the JSON Access Method class declaration. */
/***********************************************************************/
class DllExport TDBBSON : public TDBBSN {
friend class BSONDEF;
friend class BSONCOL;
public:
// Constructor
TDBBSON(PGLOBAL g, PBDEF tdp, PTXF txfp);
TDBBSON(PBTDB tdbp);
// Implementation
virtual AMT GetAmType(void) { return TYPE_AM_JSON; }
virtual PTDB Duplicate(PGLOBAL g) { return (PTDB)new(g) TDBBSON(this); }
PBVAL GetDoc(void) { return Docp; }
// Methods
virtual PTDB Clone(PTABS t);
// Database routines
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual void ResetSize(void);
virtual int GetProgCur(void) { return N; }
virtual int GetRecpos(void);
virtual bool SetRecpos(PGLOBAL g, int recpos);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual bool PrepareWriting(PGLOBAL g) { return false; }
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
int MakeDocument(PGLOBAL g);
// Optimization routines
virtual int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add);
protected:
int MakeNewDoc(PGLOBAL g);
// Members
PBVAL Docp; // The document array
int Multiple; // 0: No 1: DIR 2: Section 3: filelist
bool Done; // True when document parsing is done
bool Changed; // After Update, Insert or Delete
}; // end of class TDBBSON
/***********************************************************************/
/* This is the class declaration for the JSON catalog table. */
/***********************************************************************/
class DllExport TDBBCL : public TDBCAT {
public:
// Constructor
TDBBCL(PBDEF tdp);
protected:
// Specific routines
virtual PQRYRES GetResult(PGLOBAL g);
// Members
PTOS Topt;
PCSZ Db;
PCSZ Dsn;
}; // end of class TDBBCL

View File

@@ -167,6 +167,7 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
{
char filename[_MAX_PATH];
bool mgo = (GetTypeID(topt->type) == TAB_MONGO);
PGLOBAL G = NULL;
lvl = GetIntegerTableOption(g, topt, "Level", GetDefaultDepth());
lvl = GetIntegerTableOption(g, topt, "Depth", lvl);
@@ -296,12 +297,15 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
tjnp->SetMode(MODE_READ);
// Allocate the parse work memory
#if 0
PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
memset(G, 0, sizeof(GLOBAL));
G->Sarea_Size = (size_t)tdp->Lrecl * (tdp->Pretty >= 0 ? 10 : 2);
G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size);
PlugSubSet(G->Sarea, G->Sarea_Size);
G->jump_level = 0;
#endif // 0
G = PlugInit(NULL, (size_t)tdp->Lrecl * (tdp->Pretty >= 0 ? 10 : 2));
tjnp->SetG(G);
if (tjnp->OpenDB(g))
@@ -738,6 +742,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
if (Lrecl) {
// Allocate the parse work memory
#if 0
PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
memset(G, 0, sizeof(GLOBAL));
G->Sarea_Size = (size_t)Lrecl * 10;
@@ -745,6 +750,8 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
PlugSubSet(G->Sarea, G->Sarea_Size);
G->jump_level = 0;
((TDBJSN*)tdbp)->G = G;
#endif // 0
((TDBJSN*)tdbp)->G = PlugInit(NULL, (size_t)Lrecl * (Pretty >= 0 ? 10 : 2));
} else {
strcpy(g->Message, "LRECL is not defined");
return NULL;
@@ -1226,7 +1233,16 @@ int TDBJSN::WriteDB(PGLOBAL g)
return rc;
} // end of WriteDB
/* ---------------------------- JSONCOL ------------------------------ */
/***********************************************************************/
/* Data Base close routine for JSON access method. */
/***********************************************************************/
void TDBJSN::CloseDB(PGLOBAL g)
{
TDBDOS::CloseDB(g);
G = PlugExit(G);
} // end of CloseDB
/* ---------------------------- JSONCOL ------------------------------ */
/***********************************************************************/
/* JSONCOL public constructor. */
@@ -1608,7 +1624,7 @@ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp)
strcpy(g->Message, "Column size too small");
Value->SetValue_char(NULL, 0);
} // endif Clen
#endif 0
#endif // 0
} else
Value->SetValue_psz(Serialize(g, jsp, NULL, 0));

View File

@@ -5,6 +5,7 @@
/* */
/* This file contains the JSON classes declares. */
/***********************************************************************/
#pragma once
//#include "osutil.h" // Unuseful and bad for OEM
#include "block.h"
#include "colblk.h"
@@ -161,6 +162,7 @@ public:
virtual int ReadDB(PGLOBAL g);
virtual bool PrepareWriting(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual void CloseDB(PGLOBAL g);
// Specific routine
virtual int EstimatedLength(void);

View File

@@ -112,8 +112,7 @@ bool user_connect::user_init()
if (g)
printf("%s\n", g->Message);
int rc= PlugExit(g);
g= NULL;
g= PlugExit(g);
if (dup)
free(dup);