Commit 7915abff authored by Olivier Bertrand's avatar Olivier Bertrand

Add experimental Bson_Array function (not documented)

Change names of functions not returning Json.
  modified:   storage/connect/json.cpp
  modified:   storage/connect/json.h
  modified:   storage/connect/jsonudf.cpp
  modified:   storage/connect/jsonudf.h
  modified:   storage/connect/mysql-test/connect/r/json_udf.result
  modified:   storage/connect/plugutil.c
  modified:   storage/connect/value.cpp
  modified:   storage/connect/value.h
parent 175ef097
...@@ -63,7 +63,7 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma) ...@@ -63,7 +63,7 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
switch (s[i]) { switch (s[i]) {
case '[': case '[':
if (jsp) { if (jsp) {
if (pretty < 3) { if (pretty && pretty < 3) {
strcpy(g->Message, "More than one item in file"); strcpy(g->Message, "More than one item in file");
goto err; goto err;
} else } else
...@@ -75,7 +75,7 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma) ...@@ -75,7 +75,7 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
break; break;
case '{': case '{':
if (jsp) { if (jsp) {
if (pretty < 3) { if (pretty && pretty < 3) {
strcpy(g->Message, "More than one item in file"); strcpy(g->Message, "More than one item in file");
goto err; goto err;
} else } else
...@@ -336,7 +336,6 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src) ...@@ -336,7 +336,6 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src)
}; // endswitch s[i] }; // endswitch s[i]
jvp->Size = 1;
return jvp; return jvp;
err: err:
...@@ -973,6 +972,7 @@ void JOBJECT::DeleteKey(PSZ key) ...@@ -973,6 +972,7 @@ void JOBJECT::DeleteKey(PSZ key)
for (jp = First; jp; jp = jp->Next) for (jp = First; jp; jp = jp->Next)
if (!strcmp(jp->Key, key)) { if (!strcmp(jp->Key, key)) {
*pjp = jp->Next; *pjp = jp->Next;
Size--;
break; break;
} else } else
pjp = &jp->Next; pjp = &jp->Next;
...@@ -1246,9 +1246,9 @@ void JVALUE::SetFloat(PGLOBAL g, double f) ...@@ -1246,9 +1246,9 @@ void JVALUE::SetFloat(PGLOBAL g, double f)
/***********************************************************************/ /***********************************************************************/
/* Set the Value's value as the given string. */ /* Set the Value's value as the given string. */
/***********************************************************************/ /***********************************************************************/
void JVALUE::SetString(PGLOBAL g, PSZ s) void JVALUE::SetString(PGLOBAL g, PSZ s, short c)
{ {
Value = AllocateValue(g, s, TYPE_STRING); Value = AllocateValue(g, s, TYPE_STRING, c);
} // end of SetString } // end of SetString
/***********************************************************************/ /***********************************************************************/
......
...@@ -155,7 +155,8 @@ class JSON : public BLOCK { ...@@ -155,7 +155,8 @@ class JSON : public BLOCK {
virtual PJAR GetArray(void) {return NULL;} virtual PJAR GetArray(void) {return NULL;}
virtual PJVAL GetValue(int i) {X return NULL;} virtual PJVAL GetValue(int i) {X return NULL;}
virtual PVAL GetValue(void) {X return NULL;} virtual PVAL GetValue(void) {X return NULL;}
virtual PJSON GetJson(void) {X return NULL;} virtual PJSON GetJsp(void) { X return NULL; }
virtual PJSON GetJson(void) { X return NULL; }
virtual PJPR GetFirst(void) {X return NULL;} virtual PJPR GetFirst(void) {X return NULL;}
virtual int GetInteger(void) {X return 0;} virtual int GetInteger(void) {X return 0;}
virtual double GetFloat() {X return 0.0;} virtual double GetFloat() {X return 0.0;}
...@@ -165,7 +166,7 @@ class JSON : public BLOCK { ...@@ -165,7 +166,7 @@ class JSON : public BLOCK {
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X} virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X}
virtual void SetValue(PVAL valp) {X} virtual void SetValue(PVAL valp) {X}
virtual void SetValue(PJSON jsp) {X} virtual void SetValue(PJSON jsp) {X}
virtual void SetString(PGLOBAL g, PSZ s) {X} virtual void SetString(PGLOBAL g, PSZ s, short c) {X}
virtual void SetInteger(PGLOBAL g, int n) {X} virtual void SetInteger(PGLOBAL g, int n) {X}
virtual void SetFloat(PGLOBAL g, double f) {X} virtual void SetFloat(PGLOBAL g, double f) {X}
virtual void DeleteKey(char *k) {X} virtual void DeleteKey(char *k) {X}
...@@ -258,7 +259,8 @@ class JVALUE : public JSON { ...@@ -258,7 +259,8 @@ class JVALUE : public JSON {
virtual PJOB GetObject(void); virtual PJOB GetObject(void);
virtual PJAR GetArray(void); virtual PJAR GetArray(void);
virtual PVAL GetValue(void) {return Value;} virtual PVAL GetValue(void) {return Value;}
virtual PJSON GetJson(void) {return (Jsp ? Jsp : this);} virtual PJSON GetJsp(void) {return Jsp;}
virtual PJSON GetJson(void) { return (Jsp ? Jsp : this); }
virtual int GetInteger(void); virtual int GetInteger(void);
virtual long long GetBigint(void); virtual long long GetBigint(void);
virtual double GetFloat(void); virtual double GetFloat(void);
...@@ -266,7 +268,7 @@ class JVALUE : public JSON { ...@@ -266,7 +268,7 @@ class JVALUE : public JSON {
virtual PSZ GetText(PGLOBAL g, PSZ text); virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual void SetValue(PVAL valp) {Value = valp;} virtual void SetValue(PVAL valp) {Value = valp;}
virtual void SetValue(PJSON jsp) {Jsp = jsp;} virtual void SetValue(PJSON jsp) {Jsp = jsp;}
virtual void SetString(PGLOBAL g, PSZ s); virtual void SetString(PGLOBAL g, PSZ s, short c = 0);
virtual void SetInteger(PGLOBAL g, int n); virtual void SetInteger(PGLOBAL g, int n);
virtual void SetBigint(PGLOBAL g, longlong ll); virtual void SetBigint(PGLOBAL g, longlong ll);
virtual void SetFloat(PGLOBAL g, double f); virtual void SetFloat(PGLOBAL g, double f);
......
/************* jsonudf C++ Program Source Code File (.CPP) *************/ /****************** jsonudf C++ Program Source Code File (.CPP) ******************/
/* PROGRAM NAME: jsonudf Version 1.1 */ /* PROGRAM NAME: jsonudf Version 1.1 */
/* (C) Copyright to the author Olivier BERTRAND 2015 */ /* (C) Copyright to the author Olivier BERTRAND 2015 */
/* This program are the JSON User Defined Functions . */ /* This program are the JSON User Defined Functions . */
/***********************************************************************/ /*********************************************************************************/
/***********************************************************************/ /*********************************************************************************/
/* Include relevant sections of the MariaDB header file. */ /* Include relevant sections of the MariaDB header file. */
/***********************************************************************/ /*********************************************************************************/
#include <my_global.h> #include <my_global.h>
#include <mysqld.h> #include <mysqld.h>
#include <mysql.h> #include <mysql.h>
...@@ -24,32 +24,38 @@ uint GetJsonGrpSize(void); ...@@ -24,32 +24,38 @@ uint GetJsonGrpSize(void);
static int IsJson(UDF_ARGS *args, uint i); static int IsJson(UDF_ARGS *args, uint i);
static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i); static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i);
/* ------------------------------ JSNX ------------------------------- */ /* ----------------------------------- JSNX ------------------------------------ */
/***********************************************************************/ /*********************************************************************************/
/* JSNX public constructor. */ /* JSNX public constructor. */
/***********************************************************************/ /*********************************************************************************/
JSNX::JSNX(PGLOBAL g, PJSON row, int type, int len, int prec) JSNX::JSNX(PGLOBAL g, PJSON row, int type, int len, int prec)
{ {
Row = row; Row = row;
Jvalp = NULL;
Jpnp = NULL;
Jp = NULL;
Nodes = NULL;
Value = AllocateValue(g, type, len, prec); Value = AllocateValue(g, type, len, prec);
MulVal = NULL; MulVal = NULL;
Nodes = NULL;
Jp = NULL;
Jpath = NULL; Jpath = NULL;
Buf_Type = type; Buf_Type = type;
Long = len; Long = len;
Prec = prec; Prec = prec;
Nod = 0; Nod = 0;
Xnod = -1; Xnod = -1;
K = 0;
I = -1;
Imax = 9;
B = 0; B = 0;
Xpd = false; Xpd = false;
Parsed = false; Parsed = false;
Found = false;
} // end of JSNX constructor } // end of JSNX constructor
/***********************************************************************/ /*********************************************************************************/
/* SetJpath: set and parse the json path. */ /* SetJpath: set and parse the json path. */
/***********************************************************************/ /*********************************************************************************/
my_bool JSNX::SetJpath(PGLOBAL g, char *path) my_bool JSNX::SetJpath(PGLOBAL g, char *path)
{ {
// Check Value was allocated // Check Value was allocated
...@@ -63,28 +69,9 @@ my_bool JSNX::SetJpath(PGLOBAL g, char *path) ...@@ -63,28 +69,9 @@ my_bool JSNX::SetJpath(PGLOBAL g, char *path)
return ParseJpath(g); return ParseJpath(g);
} // end of SetJpath } // end of SetJpath
/***********************************************************************/ /*********************************************************************************/
/* Check whether this object is expanded. */
/***********************************************************************/
my_bool JSNX::CheckExpand(PGLOBAL g, int i, PSZ nm, my_bool b)
{
#if 0
if ((Tjp->Xcol && nm && !strcmp(nm, Tjp->Xcol) &&
(Tjp->Xval < 0 || Tjp->Xval == i)) || Xpd) {
Xpd = true; // Expandable object
Nodes[i].Op = OP_EXP;
} else if (b) {
strcpy(g->Message, "Cannot expand more than one branch");
return true;
} // endif Xcol
#endif // 0
return false;
} // end of CheckExpand
/***********************************************************************/
/* Analyse array processing options. */ /* Analyse array processing options. */
/***********************************************************************/ /*********************************************************************************/
my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
{ {
int n = (int)strlen(p); int n = (int)strlen(p);
...@@ -97,9 +84,7 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) ...@@ -97,9 +84,7 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
p++; p++;
} else { } else {
// Wrong array specification // Wrong array specification
sprintf(g->Message, sprintf(g->Message, "Invalid array specification %s", p);
// "Invalid array specification %s for %s", p, Name);
"Invalid array specification %s", p);
return true; return true;
} // endif p } // endif p
...@@ -112,9 +97,7 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) ...@@ -112,9 +97,7 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
if (!n) { if (!n) {
// Default specifications // Default specifications
if (CheckExpand(g, i, nm, false)) if (jnp->Op != OP_EXP) {
return true;
else if (jnp->Op != OP_EXP) {
if (b) { if (b) {
// Return 1st value (B is the index base) // Return 1st value (B is the index base)
jnp->Rank = B; jnp->Rank = B;
...@@ -144,21 +127,8 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) ...@@ -144,21 +127,8 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
case 'X': // Expand this array case 'X': // Expand this array
strcpy(g->Message, "Expand not supported by this function"); strcpy(g->Message, "Expand not supported by this function");
return true; return true;
#if 0
if (!Tjp->Xcol && nm) {
Xpd = true;
jnp->Op = OP_EXP;
Tjp->Xval = i;
Tjp->Xcol = nm;
} else if (CheckExpand(g, i, nm, true))
return true;
break;
#endif // 0
default: default:
sprintf(g->Message, sprintf(g->Message, "Invalid function specification %c", *p);
// "Invalid function specification %c for %s", *p, Name);
"Invalid function specification %c", *p);
return true; return true;
} // endswitch *p } // endswitch *p
...@@ -173,7 +143,6 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) ...@@ -173,7 +143,6 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
} // endif n } // endif n
} else { } else {
// sprintf(g->Message, "Wrong array specification for %s", Name);
strcpy(g->Message, "Wrong array specification"); strcpy(g->Message, "Wrong array specification");
return true; return true;
} // endif's } // endif's
...@@ -213,12 +182,12 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) ...@@ -213,12 +182,12 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
return false; return false;
} // end of SetArrayOptions } // end of SetArrayOptions
/***********************************************************************/ /*********************************************************************************/
/* Parse the eventual passed Jpath information. */ /* Parse the eventual passed Jpath information. */
/* This information can be specified in the Fieldfmt column option */ /* This information can be specified in the Fieldfmt column option when */
/* when creating the table. It permits to indicate the position of */ /* creating the table. It permits to indicate the position of the node */
/* the node corresponding to that column. */ /* corresponding to that column. */
/***********************************************************************/ /*********************************************************************************/
my_bool JSNX::ParseJpath(PGLOBAL g) my_bool JSNX::ParseJpath(PGLOBAL g)
{ {
char *p, *p2 = NULL, *pbuf = NULL; char *p, *p2 = NULL, *pbuf = NULL;
...@@ -227,28 +196,10 @@ my_bool JSNX::ParseJpath(PGLOBAL g) ...@@ -227,28 +196,10 @@ my_bool JSNX::ParseJpath(PGLOBAL g)
if (Parsed) if (Parsed)
return false; // Already done return false; // Already done
//else if (InitValue(g))
// return true;
else if (!Jpath) else if (!Jpath)
// Jpath = Name; // Jpath = Name;
return true; return true;
#if 0
if (To_Tdb->GetOrig()) {
// This is an updated column, get nodes from origin
for (PJCOL colp = (PJCOL)Tjp->GetColumns(); colp;
colp = (PJCOL)colp->GetNext())
if (!stricmp(Name, colp->GetName())) {
Nod = colp->Nod;
Nodes = colp->Nodes;
goto fin;
} // endif Name
sprintf(g->Message, "Cannot parse updated column %s", Name);
return true;
} // endif To_Orig
#endif // 0
pbuf = PlugDup(g, Jpath); pbuf = PlugDup(g, Jpath);
// The Jpath must be analyzed // The Jpath must be analyzed
...@@ -279,15 +230,14 @@ my_bool JSNX::ParseJpath(PGLOBAL g) ...@@ -279,15 +230,14 @@ my_bool JSNX::ParseJpath(PGLOBAL g)
} // endfor i, p } // endfor i, p
//fin:
MulVal = AllocateValue(g, Value); MulVal = AllocateValue(g, Value);
Parsed = true; Parsed = true;
return false; return false;
} // end of ParseJpath } // end of ParseJpath
/***********************************************************************/ /*********************************************************************************/
/* MakeJson: Serialize the json item and set value to it. */ /* MakeJson: Serialize the json item and set value to it. */
/***********************************************************************/ /*********************************************************************************/
PVAL JSNX::MakeJson(PGLOBAL g, PJSON jsp) PVAL JSNX::MakeJson(PGLOBAL g, PJSON jsp)
{ {
if (Value->IsTypeNum()) { if (Value->IsTypeNum()) {
...@@ -299,9 +249,9 @@ PVAL JSNX::MakeJson(PGLOBAL g, PJSON jsp) ...@@ -299,9 +249,9 @@ PVAL JSNX::MakeJson(PGLOBAL g, PJSON jsp)
return Value; return Value;
} // end of MakeJson } // end of MakeJson
/***********************************************************************/ /*********************************************************************************/
/* SetValue: Set a value from a JVALUE contains. */ /* SetValue: Set a value from a JVALUE contains. */
/***********************************************************************/ /*********************************************************************************/
void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
{ {
if (val) { if (val) {
...@@ -339,99 +289,38 @@ void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) ...@@ -339,99 +289,38 @@ void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
} // end of SetJsonValue } // end of SetJsonValue
/***********************************************************************/ /*********************************************************************************/
/* GetJson: */ /* GetJson: */
/***********************************************************************/ /*********************************************************************************/
PJVAL JSNX::GetJson(PGLOBAL g) PJVAL JSNX::GetJson(PGLOBAL g)
{ {
return GetValue(g, Row, 0); return GetValue(g, Row, 0);
} // end of GetJson } // end of GetJson
/***********************************************************************/ /*********************************************************************************/
/* ReadValue: */ /* ReadValue: */
/***********************************************************************/ /*********************************************************************************/
void JSNX::ReadValue(PGLOBAL g) void JSNX::ReadValue(PGLOBAL g)
{ {
//if (!Tjp->SameRow || Xnod >= Tjp->SameRow)
// Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0));
Value->SetValue_pval(GetColumnValue(g, Row, 0)); Value->SetValue_pval(GetColumnValue(g, Row, 0));
// Set null when applicable
//if (Nullable)
// Value->SetNull(Value->IsZero());
} // end of ReadValue } // end of ReadValue
/***********************************************************************/ /*********************************************************************************/
/* GetColumnValue: */ /* GetColumnValue: */
/***********************************************************************/ /*********************************************************************************/
PVAL JSNX::GetColumnValue(PGLOBAL g, PJSON row, int i) PVAL JSNX::GetColumnValue(PGLOBAL g, PJSON row, int i)
{ {
int n = Nod - 1; int n = Nod - 1;
//my_bool expd = false;
//PJAR arp;
PJVAL val = NULL; PJVAL val = NULL;
#if 0
for (; i < Nod && row; i++) {
if (Nodes[i].Op == OP_NUM) {
Value->SetValue(row->GetType() == TYPE_JAR ? row->size() : 1);
return(Value);
} else if (Nodes[i].Op == OP_XX) {
return MakeJson(g, row);
} else switch (row->GetType()) {
case TYPE_JOB:
if (!Nodes[i].Key) {
// Expected Array was not there
if (i < Nod-1)
continue;
else
val = new(g)JVALUE(row);
} else
val = ((PJOB)row)->GetValue(Nodes[i].Key);
break;
case TYPE_JAR:
arp = (PJAR)row;
if (!Nodes[i].Key) {
if (Nodes[i].Op == OP_EQ)
val = arp->GetValue(Nodes[i].Rank);
else if (Nodes[i].Op == OP_EXP)
return ExpandArray(g, arp, i);
else
return CalculateArray(g, arp, i);
} else if (i < Nod-1) {
strcpy(g->Message, "Unexpected array");
val = NULL; // Not an expected array
} else
val = arp->GetValue(0);
break;
case TYPE_JVAL:
val = (PJVAL)row;
break;
default:
sprintf(g->Message, "Invalid row JSON type %d", row->GetType());
val = NULL;
} // endswitch Type
if (i < Nod-1)
row = (val) ? val->GetJson() : NULL;
} // endfor i
#endif // 0
val = GetValue(g, row, i); val = GetValue(g, row, i);
SetJsonValue(g, Value, val, n); SetJsonValue(g, Value, val, n);
return Value; return Value;
} // end of GetColumnValue } // end of GetColumnValue
/***********************************************************************/ /*********************************************************************************/
/* GetValue: */ /* GetValue: */
/***********************************************************************/ /*********************************************************************************/
PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i) PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i)
{ {
//int n = Nod - 1; //int n = Nod - 1;
...@@ -494,48 +383,18 @@ PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i) ...@@ -494,48 +383,18 @@ PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i)
return val; return val;
} // end of GetValue } // end of GetValue
/***********************************************************************/ /*********************************************************************************/
/* ExpandArray: */ /* ExpandArray: */
/***********************************************************************/ /*********************************************************************************/
PVAL JSNX::ExpandArray(PGLOBAL g, PJAR arp, int n) PVAL JSNX::ExpandArray(PGLOBAL g, PJAR arp, int n)
{ {
#if 0
int ars;
PJVAL jvp;
JVALUE jval;
ars = MY_MIN(Tjp->Limit, arp->size());
if (!(jvp = arp->GetValue((Nodes[n].Rx = Nodes[n].Nx)))) {
strcpy(g->Message, "Logical error expanding array");
longjmp(g->jumper[g->jump_level], 666);
} // endif jvp
if (n < Nod - 1 && jvp->GetJson()) {
jval.SetValue(GetColumnValue(g, jvp->GetJson(), n + 1));
jvp = &jval;
} // endif n
if (n >= Tjp->NextSame) {
if (++Nodes[n].Nx == ars) {
Nodes[n].Nx = 0;
Xnod = 0;
} else
Xnod = n;
Tjp->NextSame = Xnod;
} // endif NextSame
SetJsonValue(g, Value, jvp, n);
return Value;
#endif // 0
strcpy(g->Message, "Expand cannot be done by this function"); strcpy(g->Message, "Expand cannot be done by this function");
return NULL; return NULL;
} // end of ExpandArray } // end of ExpandArray
/***********************************************************************/ /*********************************************************************************/
/* CalculateArray: */ /* CalculateArray: */
/***********************************************************************/ /*********************************************************************************/
PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
{ {
//int i, ars, nv = 0, nextsame = Tjp->NextSame; //int i, ars, nv = 0, nextsame = Tjp->NextSame;
...@@ -614,174 +473,10 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) ...@@ -614,174 +473,10 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
return vp; return vp;
} // end of CalculateArray } // end of CalculateArray
#if 0 /*********************************************************************************/
/***********************************************************************/
/* GetRow: Get the object containing this column. */
/***********************************************************************/
PJSON JSNX::GetRow(PGLOBAL g)
{
PJVAL val = NULL;
PJAR arp;
//PJSON nwr, row = Tjp->Row;
PJSON nwr, row = Row;
for (int i = 0; i < Nod-1 && row; i++) {
if (Nodes[i+1].Op == OP_XX)
break;
else switch (row->GetType()) {
case TYPE_JOB:
if (!Nodes[i].Key)
// Expected Array was not there
continue;
val = ((PJOB)row)->GetValue(Nodes[i].Key);
break;
case TYPE_JAR:
if (!Nodes[i].Key) {
arp = (PJAR)row;
if (Nodes[i].Op == OP_EQ)
val = arp->GetValue(Nodes[i].Rank);
else
val = arp->GetValue(Nodes[i].Rx);
} else {
strcpy(g->Message, "Unexpected array");
val = NULL; // Not an expected array
} // endif Nodes
break;
case TYPE_JVAL:
val = (PJVAL)row;
break;
default:
sprintf(g->Message, "Invalid row JSON type %d", row->GetType());
val = NULL;
} // endswitch Type
if (val) {
row = val->GetJson();
} else {
// Construct missing objects
for (i++; row && i < Nod; i++) {
if (Nodes[i].Op == OP_XX)
break;
else if (!Nodes[i].Key)
// Construct intermediate array
nwr = new(g)JARRAY;
else
nwr = new(g)JOBJECT;
if (row->GetType() == TYPE_JOB) {
((PJOB)row)->SetValue(g, new(g)JVALUE(nwr), Nodes[i-1].Key);
} else if (row->GetType() == TYPE_JAR) {
((PJAR)row)->AddValue(g, new(g)JVALUE(nwr));
((PJAR)row)->InitArray(g);
} else {
strcpy(g->Message, "Wrong type when writing new row");
nwr = NULL;
} // endif's
row = nwr;
} // endfor i
break;
} // endelse
} // endfor i
return row;
} // end of GetRow
/***********************************************************************/
/* WriteColumn: */
/***********************************************************************/
void JSNX::WriteColumn(PGLOBAL g)
{
/*********************************************************************/
/* Check whether this node must be written. */
/*********************************************************************/
if (Value != To_Val)
Value->SetValue_pval(To_Val, FALSE); // Convert the updated value
/*********************************************************************/
/* On INSERT Null values are represented by no node. */
/*********************************************************************/
if (Value->IsNull() && Tjp->Mode == MODE_INSERT)
return;
char *s;
PJOB objp = NULL;
PJAR arp = NULL;
PJVAL jvp = NULL;
PJSON jsp, row = GetRow(g);
JTYP type = row->GetType();
switch (row->GetType()) {
case TYPE_JOB: objp = (PJOB)row; break;
case TYPE_JAR: arp = (PJAR)row; break;
case TYPE_JVAL: jvp = (PJVAL)row; break;
default: row = NULL; // ???????????????????????????
} // endswitch Type
if (row) switch (Buf_Type) {
case TYPE_STRING:
if (Nodes[Nod-1].Op == OP_XX) {
s = Value->GetCharValue();
if (!(jsp = ParseJson(g, s, (int)strlen(s)))) {
strcpy(g->Message, s);
longjmp(g->jumper[g->jump_level], 666);
} // endif jsp
if (arp) {
if (Nod > 1 && Nodes[Nod-2].Op == OP_EQ)
arp->SetValue(g, new(g)JVALUE(jsp), Nodes[Nod-2].Rank);
else
arp->AddValue(g, new(g)JVALUE(jsp));
arp->InitArray(g);
} else if (objp) {
if (Nod > 1 && Nodes[Nod-2].Key)
objp->SetValue(g, new(g)JVALUE(jsp), Nodes[Nod-2].Key);
} else if (jvp)
jvp->SetValue(jsp);
break;
} // endif Op
// Passthru
case TYPE_DATE:
case TYPE_INT:
case TYPE_DOUBLE:
if (arp) {
if (Nodes[Nod-1].Op == OP_EQ)
arp->SetValue(g, new(g)JVALUE(g, Value), Nodes[Nod-1].Rank);
else
arp->AddValue(g, new(g)JVALUE(g, Value));
arp->InitArray(g);
} else if (objp) {
if (Nodes[Nod-1].Key)
objp->SetValue(g, new(g)JVALUE(g, Value), Nodes[Nod-1].Key);
} else if (jvp)
jvp->SetValue(Value);
break;
default: // ??????????
sprintf(g->Message, "Invalid column type %d", Buf_Type);
} // endswitch Type
} // end of WriteColumn
#endif // 0
/***********************************************************************/
/* Locate a value in a JSON tree: */ /* Locate a value in a JSON tree: */
/***********************************************************************/ /*********************************************************************************/
PSZ JSNX::Locate(PGLOBAL g, PJSON jsp, char *what, PSZ JSNX::Locate(PGLOBAL g, PJSON jsp, PJVAL jvp, int k)
enum Item_result type, unsigned long len)
{ {
my_bool b = false, err = true; my_bool b = false, err = true;
...@@ -790,8 +485,12 @@ enum Item_result type, unsigned long len) ...@@ -790,8 +485,12 @@ enum Item_result type, unsigned long len)
if (!jsp) { if (!jsp) {
strcpy(g->Message, "Null json tree"); strcpy(g->Message, "Null json tree");
return NULL; return NULL;
} else // Write to the path string } // endif jsp
Jp = new(g)JOUTPATH(g, what, type, len);
// Write to the path string
Jp = new(g) JOUTSTR(g);
Jvalp = jvp;
K = k;
switch (jsp->GetType()) { switch (jsp->GetType()) {
case TYPE_JAR: case TYPE_JAR:
...@@ -811,7 +510,7 @@ enum Item_result type, unsigned long len) ...@@ -811,7 +510,7 @@ enum Item_result type, unsigned long len)
if (!g->Message[0]) if (!g->Message[0])
strcpy(g->Message, "Invalid json tree"); strcpy(g->Message, "Invalid json tree");
} else if (Jp->Found) { } else if (Found) {
Jp->WriteChr('\0'); Jp->WriteChr('\0');
PlugSubAlloc(g, NULL, Jp->N); PlugSubAlloc(g, NULL, Jp->N);
return Jp->Strp; return Jp->Strp;
...@@ -820,15 +519,15 @@ enum Item_result type, unsigned long len) ...@@ -820,15 +519,15 @@ enum Item_result type, unsigned long len)
return NULL; return NULL;
} // end of Locate } // end of Locate
/***********************************************************************/ /*********************************************************************************/
/* Locate in a JSON Array. */ /* Locate in a JSON Array. */
/***********************************************************************/ /*********************************************************************************/
my_bool JSNX::LocateArray(PJAR jarp) my_bool JSNX::LocateArray(PJAR jarp)
{ {
char s[16]; char s[16];
size_t m = Jp->N; size_t m = Jp->N;
for (int i = 0; i < jarp->size() && !Jp->Found; i++) { for (int i = 0; i < jarp->size() && !Found; i++) {
Jp->N = m; Jp->N = m;
sprintf(s, "[%d]", i + B); sprintf(s, "[%d]", i + B);
...@@ -843,14 +542,14 @@ my_bool JSNX::LocateArray(PJAR jarp) ...@@ -843,14 +542,14 @@ my_bool JSNX::LocateArray(PJAR jarp)
return false; return false;
} // end of LocateArray } // end of LocateArray
/***********************************************************************/ /*********************************************************************************/
/* Locate in a JSON Object. */ /* Locate in a JSON Object. */
/***********************************************************************/ /*********************************************************************************/
my_bool JSNX::LocateObject(PJOB jobp) my_bool JSNX::LocateObject(PJOB jobp)
{ {
size_t m = Jp->N; size_t m = Jp->N;
for (PJPR pair = jobp->First; pair && !Jp->Found; pair = pair->Next) { for (PJPR pair = jobp->First; pair && !Found; pair = pair->Next) {
Jp->N = m; Jp->N = m;
if (Jp->WriteStr(pair->Key)) if (Jp->WriteStr(pair->Key))
...@@ -864,56 +563,248 @@ my_bool JSNX::LocateObject(PJOB jobp) ...@@ -864,56 +563,248 @@ my_bool JSNX::LocateObject(PJOB jobp)
return false; return false;
} // end of LocateObject } // end of LocateObject
/***********************************************************************/ /*********************************************************************************/
/* Locate a JSON Value. */ /* Locate a JSON Value. */
/***********************************************************************/ /*********************************************************************************/
my_bool JSNX::LocateValue(PJVAL jvp) my_bool JSNX::LocateValue(PJVAL jvp)
{ {
char *p, buf[32]; if (CompareTree(Jvalp, jvp)) {
PJAR jap; Found = (--K == 0);
PJOB jop; } else if (jvp->GetArray()) {
PVAL valp;
if ((jap = jvp->GetArray())) {
if (Jp->WriteChr(':')) if (Jp->WriteChr(':'))
return true; return true;
return LocateArray(jap); return LocateArray(jvp->GetArray());
} else if ((jop = jvp->GetObject())) { } else if (jvp->GetObject()) {
if (Jp->WriteChr(':')) if (Jp->WriteChr(':'))
return true; return true;
return LocateObject(jop); return LocateObject(jvp->GetObject());
} else if (!(valp = jvp->Value) || valp->IsNull()) } // endif's
return false; return false;
else switch (Jp->Type) { } // end of LocateValue
case STRING_RESULT:
p = valp->GetCharString(buf); /*********************************************************************************/
Jp->Found = (strlen(p) == Jp->Len && /* Locate all occurrences of a value in a JSON tree: */
!strncmp(Jp->What, valp->GetCharString(buf), Jp->Len)); /*********************************************************************************/
break; PSZ JSNX::LocateAll(PGLOBAL g, PJSON jsp, PJVAL jvp, int mx)
case INT_RESULT: {
Jp->Found = *(longlong*)Jp->What == valp->GetBigintValue(); my_bool b = false, err = true;
PJPN jnp = (PJPN)PlugSubAlloc(g, NULL, sizeof(JPN) * mx);
memset(jnp, 0, sizeof(JPN) * mx);
g->Message[0] = 0;
if (!jsp) {
strcpy(g->Message, "Null json tree");
return NULL;
} // endif jsp
// Write to the path string
Jp = new(g)JOUTSTR(g);
Jvalp = jvp;
Imax = mx - 1;
Jpnp = jnp;
Jp->WriteChr('[');
switch (jsp->GetType()) {
case TYPE_JAR:
err = LocateArrayAll((PJAR)jsp);
break; break;
case DECIMAL_RESULT: case TYPE_JOB:
Jp->Found = atof(Jp->What) == valp->GetFloatValue(); err = LocateObjectAll((PJOB)jsp);
break; break;
case REAL_RESULT: case TYPE_JVAL:
Jp->Found = *(double*)Jp->What == valp->GetFloatValue(); err = LocateValueAll((PJVAL)jsp);
break; break;
default: default:
sprintf(Jp->g->Message, "Invalid type %d", Buf_Type); err = true;
return true;
} // endswitch Type } // endswitch Type
if (err) {
if (!g->Message[0])
strcpy(g->Message, "Invalid json tree");
} else {
if (Jp->N > 1)
Jp->N--;
Jp->WriteChr(']');
Jp->WriteChr('\0');
PlugSubAlloc(g, NULL, Jp->N);
return Jp->Strp;
} // endif's
return NULL;
} // end of LocateAll
/*********************************************************************************/
/* Locate in a JSON Array. */
/*********************************************************************************/
my_bool JSNX::LocateArrayAll(PJAR jarp)
{
if (I < Imax) {
Jpnp[++I].Type = TYPE_JAR;
for (int i = 0; i < jarp->size(); i++) {
Jpnp[I].N = i;
if (LocateValueAll(jarp->GetValue(i)))
return true;
} // endfor i
I--;
} // endif I
return false; return false;
} // end of LocateValue } // end of LocateArrayAll
/*********************************************************************************/
/* Locate in a JSON Object. */
/*********************************************************************************/
my_bool JSNX::LocateObjectAll(PJOB jobp)
{
if (I < Imax) {
Jpnp[++I].Type = TYPE_JOB;
for (PJPR pair = jobp->First; pair; pair = pair->Next) {
Jpnp[I].Key = pair->Key;
if (LocateValueAll(pair->Val))
return true;
} // endfor i
I--;
} // endif I
return false;
} // end of LocateObjectAll
/*********************************************************************************/
/* Locate a JSON Value. */
/*********************************************************************************/
my_bool JSNX::LocateValueAll(PJVAL jvp)
{
if (CompareTree(Jvalp, jvp))
return AddPath();
else if (jvp->GetArray())
return LocateArrayAll(jvp->GetArray());
else if (jvp->GetObject())
return LocateObjectAll(jvp->GetObject());
return false;
} // end of LocateValueAll
/*********************************************************************************/
/* Compare two JSON trees. */
/*********************************************************************************/
my_bool JSNX::CompareTree(PJSON jp1, PJSON jp2)
{
if (!jp1 || !jp2 || jp1->GetType() != jp2->GetType()
|| jp1->size() != jp2->size())
return false;
my_bool found = true;
if (jp1->GetType() == TYPE_JVAL) {
PVAL v1 = jp1->GetValue(), v2 = jp2->GetValue();
if (v1 && v2) {
if (v1->GetType() == v2->GetType())
found = !v1->CompareValue(v2);
else
found = false;
/* ---------------------------- JSON UDF ----------------------------- */ } else
found = CompareTree(jp1->GetJsp(), jp2->GetJsp());
} else if (jp1->GetType() == TYPE_JAR) {
for (int i = 0; found && i < jp1->size(); i++)
found = (CompareTree(jp1->GetValue(i), jp2->GetValue(i)));
} else if (jp1->GetType() == TYPE_JOB) {
PJPR p1 = jp1->GetFirst(), p2 = jp2->GetFirst();
for (; found && p1 && p2; p1 = p1->Next, p2 = p2->Next)
found = CompareTree(p1->Val, p2->Val);
} else
found = false;
return found;
} // end of CompareTree
/*********************************************************************************/
/* Add the found path to the list. */
/*********************************************************************************/
my_bool JSNX::AddPath(void)
{
char s[16];
my_bool b = false;
if (Jp->WriteChr('"'))
return true;
for (int i = 0; i <= I; i++) {
if (b) {
if (Jp->WriteChr(':')) return true;
} else
b = true;
if (Jpnp[i].Type == TYPE_JAR) {
sprintf(s, "[%d]", Jpnp[i].N + B);
if (Jp->WriteStr(s))
return true;
} else if (Jp->WriteStr(Jpnp[i].Key))
return true;
} // endfor i
/***********************************************************************/ if (Jp->WriteStr("\","))
return true;
return false;
} // end of AddPath
/* --------------------------------- JSON UDF ---------------------------------- */
typedef struct BSON *PBSON;
/*********************************************************************************/
/* Structure used to return binary json. */
/*********************************************************************************/
struct BSON {
char Msg[140];
void *Memp;
ulong Reslen;
my_bool Changed;
PJSON Jsp;
}; // end of struct BSON
/*********************************************************************************/
/* Allocate and initialize a BSON structure. */
/*********************************************************************************/
static PBSON BsonAlloc(PGLOBAL g, ulong len, PJSON jsp)
{
PBSON bsp = (PBSON)PlugSubAlloc(g, NULL, sizeof(BSON));
strcpy(bsp->Msg, "Binary Json");
bsp->Msg[139] = 0;
bsp->Memp = g->Sarea;
bsp->Reslen = len;
bsp->Changed = false;
bsp->Jsp = jsp;
return bsp;
} /* end of BsonAlloc */
/*********************************************************************************/
/* Program for SubSet re-initialization of the memory pool. */ /* Program for SubSet re-initialization of the memory pool. */
/***********************************************************************/ /*********************************************************************************/
static my_bool JsonSubSet(PGLOBAL g) static my_bool JsonSubSet(PGLOBAL g)
{ {
PPOOLHEADER pph = (PPOOLHEADER)g->Sarea; PPOOLHEADER pph = (PPOOLHEADER)g->Sarea;
...@@ -923,17 +814,28 @@ static my_bool JsonSubSet(PGLOBAL g) ...@@ -923,17 +814,28 @@ static my_bool JsonSubSet(PGLOBAL g)
return FALSE; return FALSE;
} /* end of JsonSubSet */ } /* end of JsonSubSet */
/***********************************************************************/ /*********************************************************************************/
/* Program for saving the status of the memory pools. */ /* Program for saving the status of the memory pools. */
/***********************************************************************/ /*********************************************************************************/
inline void JsonMemSave(PGLOBAL g) inline void JsonMemSave(PGLOBAL g)
{ {
g->Createas = (int)((PPOOLHEADER)g->Sarea)->To_Free; g->Createas = (int)((PPOOLHEADER)g->Sarea)->To_Free;
} /* end of JsonMemSave */ } /* end of JsonMemSave */
/***********************************************************************/ /*********************************************************************************/
/* Program for freeing the memory pools. */
/*********************************************************************************/
inline void JsonMemFree(PGLOBAL g)
{
if (g->Alchecked)
g->Sarea = NULL;
PlugExit(g);
} /* end of JsonMemFree */
/*********************************************************************************/
/* Allocate and initialise the memory area. */ /* Allocate and initialise the memory area. */
/***********************************************************************/ /*********************************************************************************/
static my_bool JsonInit(UDF_INIT *initid, UDF_ARGS *args, static my_bool JsonInit(UDF_INIT *initid, UDF_ARGS *args,
char *message, my_bool mbn, char *message, my_bool mbn,
unsigned long reslen, unsigned long memlen) unsigned long reslen, unsigned long memlen)
...@@ -944,22 +846,25 @@ static my_bool JsonInit(UDF_INIT *initid, UDF_ARGS *args, ...@@ -944,22 +846,25 @@ static my_bool JsonInit(UDF_INIT *initid, UDF_ARGS *args,
strcpy(message, "Allocation error"); strcpy(message, "Allocation error");
return true; return true;
} else if (g->Sarea_Size == 0) { } else if (g->Sarea_Size == 0) {
if (memlen) {
strcpy(message, g->Message); strcpy(message, g->Message);
PlugExit(g); PlugExit(g);
return true; return true;
} else } else
initid->ptr = (char*)g; assert(IsJson(args, 0) == 3);
} // endif g
g->Mrr = (args->arg_count && args->args[0]) ? 1 : 0; g->Mrr = (args->arg_count && args->args[0]) ? 1 : 0;
g->Alchecked = (initid->const_item) ? 1 : 0;
initid->maybe_null = mbn; initid->maybe_null = mbn;
initid->max_length = reslen; initid->max_length = reslen;
initid->ptr = (char*)g;
return false; return false;
} // end of JsonInit } // end of JsonInit
/***********************************************************************/ /*********************************************************************************/
/* Check if a path was specified and set jvp according to it. */ /* Check if a path was specified and set jvp according to it. */
/***********************************************************************/ /*********************************************************************************/
static my_bool CheckPath(PGLOBAL g, UDF_ARGS *args, PJSON top, PJVAL& jvp, int n) static my_bool CheckPath(PGLOBAL g, UDF_ARGS *args, PJSON top, PJVAL& jvp, int n)
{ {
for (uint i = n; i < args->arg_count; i++) for (uint i = n; i < args->arg_count; i++)
...@@ -982,9 +887,9 @@ static my_bool CheckPath(PGLOBAL g, UDF_ARGS *args, PJSON top, PJVAL& jvp, int n ...@@ -982,9 +887,9 @@ static my_bool CheckPath(PGLOBAL g, UDF_ARGS *args, PJSON top, PJVAL& jvp, int n
return false; return false;
} // end of CheckPath } // end of CheckPath
/***********************************************************************/ /*********************************************************************************/
/* Make the result according to the first argument type. */ /* Make the result according to the first argument type. */
/***********************************************************************/ /*********************************************************************************/
static char *MakeResult(PGLOBAL g, UDF_ARGS *args, PJSON top, int n = 2) static char *MakeResult(PGLOBAL g, UDF_ARGS *args, PJSON top, int n = 2)
{ {
char *str; char *str;
...@@ -1004,33 +909,40 @@ static char *MakeResult(PGLOBAL g, UDF_ARGS *args, PJSON top, int n = 2) ...@@ -1004,33 +909,40 @@ static char *MakeResult(PGLOBAL g, UDF_ARGS *args, PJSON top, int n = 2)
PUSH_WARNING(msg); PUSH_WARNING(msg);
str = NULL; str = NULL;
} else if (!(str = Serialize(g, top, NULL, 0))) } else {
if (!(str = Serialize(g, top, NULL, 0)))
PUSH_WARNING(g->Message); PUSH_WARNING(g->Message);
if (IsJson(args, 0) == 3)
((PBSON)args->args[0])->Changed = 1;
} // endif IsJson
return str; return str;
} // end of MakeResult } // end of MakeResult
/***********************************************************************/ /*********************************************************************************/
/* Returns not 0 if the argument is a JSON item or file name. */ /* Returns not 0 if the argument is a JSON item or file name. */
/***********************************************************************/ /*********************************************************************************/
static int IsJson(UDF_ARGS *args, uint i) static int IsJson(UDF_ARGS *args, uint i)
{ {
int n = 0; int n = 0;
if (i >= args->arg_count) if (i >= args->arg_count || args->arg_type[i] != STRING_RESULT)
n = 0; n = 0;
else if (!strnicmp(args->attributes[i], "Json_", 5)) else if (!strnicmp(args->attributes[i], "Json_", 5))
n = 1; // arg is a json item n = 1; // arg is a json item
else if (args->arg_type[i] == STRING_RESULT && else if (!strnicmp(args->attributes[i], "Jfile_", 6))
!strnicmp(args->attributes[i], "Jfile_", 6))
n = 2; // arg is a json file name n = 2; // arg is a json file name
else if (!strnicmp(args->attributes[i], "Bson_", 5))
n = 3; // arg is a binary json item
return n; return n;
} // end of IsJson } // end of IsJson
/***********************************************************************/ /*********************************************************************************/
/* GetFileLength: returns file size in number of bytes. */ /* GetFileLength: returns file size in number of bytes. */
/***********************************************************************/ /*********************************************************************************/
static long GetFileLength(char *fn) static long GetFileLength(char *fn)
{ {
int h; int h;
...@@ -1049,21 +961,23 @@ static long GetFileLength(char *fn) ...@@ -1049,21 +961,23 @@ static long GetFileLength(char *fn)
return len; return len;
} // end of GetFileLength } // end of GetFileLength
/***********************************************************************/ /*********************************************************************************/
/* Calculate the reslen and memlen needed by a function. */ /* Calculate the reslen and memlen needed by a function. */
/***********************************************************************/ /*********************************************************************************/
static my_bool CalcLen(UDF_ARGS *args, my_bool obj, static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
unsigned long& reslen, unsigned long& memlen, unsigned long& reslen, unsigned long& memlen,
my_bool mod = false) my_bool mod = false)
{ {
char fn[_MAX_PATH]; char fn[_MAX_PATH];
unsigned long i, k, n; unsigned long i, k, m, n;
long fl, j = -1; long fl, j = -1;
reslen = args->arg_count + 2; reslen = args->arg_count + 2;
// Calculate the result max length // Calculate the result max length
for (i = 0; i < args->arg_count; i++) { for (i = 0; i < args->arg_count; i++) {
n = IsJson(args, i);
if (obj) { if (obj) {
if (!(k = args->attribute_lengths[i])) if (!(k = args->attribute_lengths[i]))
k = strlen(args->attributes[i]); k = strlen(args->attributes[i]);
...@@ -1073,18 +987,20 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj, ...@@ -1073,18 +987,20 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
switch (args->arg_type[i]) { switch (args->arg_type[i]) {
case STRING_RESULT: case STRING_RESULT:
if (IsJson(args, i) == 2 && args->args[i]) { if (n == 2 && args->args[i]) {
if (!mod) { if (!mod) {
n = MY_MIN(args->lengths[i], sizeof(fn) - 1); m = MY_MIN(args->lengths[i], sizeof(fn) - 1);
memcpy(fn, args->args[i], n); memcpy(fn, args->args[i], m);
fn[n] = 0; fn[m] = 0;
j = i; j = i;
fl = GetFileLength(fn); fl = GetFileLength(fn);
reslen += fl; reslen += fl;
} else } else
reslen += args->lengths[i]; reslen += args->lengths[i];
} else if (IsJson(args, i) == 1) } else if (n == 3 && args->args[i])
reslen += ((PBSON)args->args[i])->Reslen;
else if (n == 1)
reslen += args->lengths[i]; reslen += args->lengths[i];
else else
reslen += (args->lengths[i] + 1) * 2; // Pessimistic ! reslen += (args->lengths[i] + 1) * 2; // Pessimistic !
...@@ -1109,10 +1025,14 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj, ...@@ -1109,10 +1025,14 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
} // endfor i } // endfor i
// Calculate the amount of memory needed if (IsJson(args, 0) == 3) {
memlen = 0L; // We'll use arg memory
return false;
} else // Calculate the amount of memory needed
memlen = MEMFIX + sizeof(JOUTSTR) + reslen; memlen = MEMFIX + sizeof(JOUTSTR) + reslen;
for (i = 0; i < args->arg_count; i++) { for (i = 0; i < args->arg_count; i++) {
n = IsJson(args, i);
memlen += (args->lengths[i] + sizeof(JVALUE)); memlen += (args->lengths[i] + sizeof(JVALUE));
if (obj) { if (obj) {
...@@ -1125,17 +1045,19 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj, ...@@ -1125,17 +1045,19 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
switch (args->arg_type[i]) { switch (args->arg_type[i]) {
case STRING_RESULT: case STRING_RESULT:
if (IsJson(args, i) == 2 && args->args[i]) { if (n == 2 && args->args[i]) {
if ((signed)i != j) { if ((signed)i != j) {
n = MY_MIN(args->lengths[i], sizeof(fn) - 1); m = MY_MIN(args->lengths[i], sizeof(fn) - 1);
memcpy(fn, args->args[i], n); memcpy(fn, args->args[i], m);
fn[n] = 0; fn[m] = 0;
j = -1; j = -1;
fl = GetFileLength(fn); fl = GetFileLength(fn);
} // endif i } // endif i
memlen += fl * M; memlen += fl * M;
} else if (IsJson(args, i) == 1) } else if (IsJson(args, i) == 3)
memlen += sizeof(JVALUE);
else if (IsJson(args, i) == 1)
memlen += args->lengths[i] * M; // Estimate parse memory memlen += args->lengths[i] * M; // Estimate parse memory
memlen += sizeof(TYPVAL<PSZ>); memlen += sizeof(TYPVAL<PSZ>);
...@@ -1160,14 +1082,26 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj, ...@@ -1160,14 +1082,26 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
return false; return false;
} // end of CalcLen } // end of CalcLen
/***********************************************************************/ /*********************************************************************************/
/* Check if the calculated memory is enough. */ /* Check if the calculated memory is enough. */
/***********************************************************************/ /*********************************************************************************/
static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args, static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args,
uint n, my_bool obj, my_bool mod = false) uint n, my_bool obj, my_bool mod = false)
{ {
unsigned long rl, ml; unsigned long rl, ml;
if (IsJson(args, 0) == 3) {
if (!g->Sarea) {
PPOOLHEADER p = (PPOOLHEADER)((PBSON)args->args[0])->Memp;
g->Sarea = p;
g->Sarea_Size = p->To_Free + p->FreeBlk;
g->Alchecked = 1;
} // endif Sarea
return false;
} // endif IsJson
n = MY_MIN(n, args->arg_count); n = MY_MIN(n, args->arg_count);
for (uint i = 0; i < n; i++) for (uint i = 0; i < n; i++)
...@@ -1199,9 +1133,9 @@ static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args, ...@@ -1199,9 +1133,9 @@ static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args,
return false; return false;
} // end of CheckMemory } // end of CheckMemory
/***********************************************************************/ /*********************************************************************************/
/* Make a zero terminated string from the passed argument. */ /* Make a zero terminated string from the passed argument. */
/***********************************************************************/ /*********************************************************************************/
static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i) static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i)
{ {
if (args->arg_count > (unsigned)i && args->args[i]) { if (args->arg_count > (unsigned)i && args->args[i]) {
...@@ -1216,9 +1150,9 @@ static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i) ...@@ -1216,9 +1150,9 @@ static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i)
} // end of MakePSZ } // end of MakePSZ
/***********************************************************************/ /*********************************************************************************/
/* Make a valid key from the passed argument. */ /* Make a valid key from the passed argument. */
/***********************************************************************/ /*********************************************************************************/
static PSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i) static PSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
{ {
if (args->arg_count > (unsigned)i) { if (args->arg_count > (unsigned)i) {
...@@ -1257,9 +1191,9 @@ static PSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i) ...@@ -1257,9 +1191,9 @@ static PSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
return "Key"; return "Key";
} // end of MakeKey } // end of MakeKey
/***********************************************************************/ /*********************************************************************************/
/* Return a json file contains. */ /* Return a json file contains. */
/***********************************************************************/ /*********************************************************************************/
static char *GetJsonFile(PGLOBAL g, char *fn) static char *GetJsonFile(PGLOBAL g, char *fn)
{ {
char *str; char *str;
...@@ -1290,13 +1224,14 @@ static char *GetJsonFile(PGLOBAL g, char *fn) ...@@ -1290,13 +1224,14 @@ static char *GetJsonFile(PGLOBAL g, char *fn)
return str; return str;
} // end of GetJsonFile } // end of GetJsonFile
/***********************************************************************/ /*********************************************************************************/
/* Make a JSON value from the passed argument. */ /* Make a JSON value from the passed argument. */
/***********************************************************************/ /*********************************************************************************/
static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, uint i) static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, uint i)
{ {
char *sap = (args->arg_count > i) ? args->args[i] : NULL; char *sap = (args->arg_count > i) ? args->args[i] : NULL;
int n, len; int n, len;
short c;
long long bigint; long long bigint;
PJSON jsp; PJSON jsp;
PJVAL jvp = new(g) JVALUE; PJVAL jvp = new(g) JVALUE;
...@@ -1304,9 +1239,13 @@ static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, uint i) ...@@ -1304,9 +1239,13 @@ static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, uint i)
if (sap) switch (args->arg_type[i]) { if (sap) switch (args->arg_type[i]) {
case STRING_RESULT: case STRING_RESULT:
if ((len = args->lengths[i])) { if ((len = args->lengths[i])) {
if ((n = IsJson(args, i)) < 3)
sap = MakePSZ(g, args, i); sap = MakePSZ(g, args, i);
if ((n = IsJson(args, i))) { if (n) {
if (n == 3) {
jsp = ((PBSON)sap)->Jsp;
} else {
if (n == 2) { if (n == 2) {
if (!(sap = GetJsonFile(g, sap))) if (!(sap = GetJsonFile(g, sap)))
PUSH_WARNING(g->Message); PUSH_WARNING(g->Message);
...@@ -1316,14 +1255,17 @@ static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, uint i) ...@@ -1316,14 +1255,17 @@ static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, uint i)
if (!(jsp = ParseJson(g, sap, len, 3))) if (!(jsp = ParseJson(g, sap, len, 3)))
PUSH_WARNING(g->Message); PUSH_WARNING(g->Message);
} // endif's n
if (jsp && jsp->GetType() == TYPE_JVAL) if (jsp && jsp->GetType() == TYPE_JVAL)
jvp = (PJVAL)jsp; jvp = (PJVAL)jsp;
else else
jvp->SetValue(jsp); jvp->SetValue(jsp);
} else } else {
jvp->SetString(g, sap); c = (strnicmp(args->attributes[i], "ci", 2)) ? 0 : 1;
jvp->SetString(g, sap, c);
} // endif n
} // endif len } // endif len
...@@ -1353,9 +1295,9 @@ static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, uint i) ...@@ -1353,9 +1295,9 @@ static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, uint i)
return jvp; return jvp;
} // end of MakeValue } // end of MakeValue
/***********************************************************************/ /*********************************************************************************/
/* Make a Json value containing the parameter. */ /* Make a Json value containing the parameter. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Value_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool Json_Value_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
...@@ -1386,7 +1328,7 @@ char *Json_Value(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1386,7 +1328,7 @@ char *Json_Value(UDF_INIT *initid, UDF_ARGS *args, char *result,
str = strcpy(result, g->Message); str = strcpy(result, g->Message);
// Keep result of constant function // Keep result of constant function
g->Xchk = (g->Alchecked) ? str : NULL; g->Xchk = (initid->const_item) ? str : NULL;
} else } else
str = (char*)g->Xchk; str = (char*)g->Xchk;
...@@ -1396,12 +1338,12 @@ char *Json_Value(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1396,12 +1338,12 @@ char *Json_Value(UDF_INIT *initid, UDF_ARGS *args, char *result,
void Json_Value_deinit(UDF_INIT* initid) void Json_Value_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Value_deinit } // end of Json_Value_deinit
/***********************************************************************/ /*********************************************************************************/
/* Make a Json array containing all the parameters. */ /* Make a Json array containing all the parameters. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Array_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool Json_Array_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
...@@ -1432,7 +1374,7 @@ char *Json_Array(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1432,7 +1374,7 @@ char *Json_Array(UDF_INIT *initid, UDF_ARGS *args, char *result,
str = strcpy(result, g->Message); str = strcpy(result, g->Message);
// Keep result of constant function // Keep result of constant function
g->Xchk = (g->Alchecked) ? str : NULL; g->Xchk = (initid->const_item) ? str : NULL;
} else } else
str = (char*)g->Xchk; str = (char*)g->Xchk;
...@@ -1442,12 +1384,12 @@ char *Json_Array(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1442,12 +1384,12 @@ char *Json_Array(UDF_INIT *initid, UDF_ARGS *args, char *result,
void Json_Array_deinit(UDF_INIT* initid) void Json_Array_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Array_deinit } // end of Json_Array_deinit
/***********************************************************************/ /*********************************************************************************/
/* Add one or several values to a Json array. */ /* Add one or several values to a Json array. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Array_Add_Values_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool Json_Array_Add_Values_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
...@@ -1494,7 +1436,7 @@ char *Json_Array_Add_Values(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1494,7 +1436,7 @@ char *Json_Array_Add_Values(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif str } // endif str
// Keep result of constant function // Keep result of constant function
g->Xchk = (g->Alchecked) ? str : NULL; g->Xchk = (initid->const_item) ? str : NULL;
} else } else
str = (char*)g->Xchk; str = (char*)g->Xchk;
...@@ -1509,12 +1451,12 @@ char *Json_Array_Add_Values(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1509,12 +1451,12 @@ char *Json_Array_Add_Values(UDF_INIT *initid, UDF_ARGS *args, char *result,
void Json_Array_Add_Values_deinit(UDF_INIT* initid) void Json_Array_Add_Values_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Array_Add_Values_deinit } // end of Json_Array_Add_Values_deinit
/***********************************************************************/ /*********************************************************************************/
/* Add one value to a Json array. */ /* Add one value to a Json array. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Array_Add_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool Json_Array_Add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
...@@ -1581,7 +1523,7 @@ char *Json_Array_Add(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1581,7 +1523,7 @@ char *Json_Array_Add(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!str) if (!str)
str = MakePSZ(g, args, 0); str = MakePSZ(g, args, 0);
if (g->Alchecked) if (initid->const_item)
// Keep result of constant function // Keep result of constant function
g->Xchk = str; g->Xchk = str;
...@@ -1591,12 +1533,12 @@ char *Json_Array_Add(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1591,12 +1533,12 @@ char *Json_Array_Add(UDF_INIT *initid, UDF_ARGS *args, char *result,
void Json_Array_Add_deinit(UDF_INIT* initid) void Json_Array_Add_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Array_Add_deinit } // end of Json_Array_Add_deinit
/***********************************************************************/ /*********************************************************************************/
/* Delete a value from a Json array. */ /* Delete a value from a Json array. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Array_Delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool Json_Array_Delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
...@@ -1654,7 +1596,7 @@ char *Json_Array_Delete(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1654,7 +1596,7 @@ char *Json_Array_Delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!str) if (!str)
str = MakePSZ(g, args, 0); str = MakePSZ(g, args, 0);
if (g->Alchecked) if (initid->const_item)
// Keep result of constant function // Keep result of constant function
g->Xchk = str; g->Xchk = str;
...@@ -1664,12 +1606,12 @@ char *Json_Array_Delete(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1664,12 +1606,12 @@ char *Json_Array_Delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
void Json_Array_Delete_deinit(UDF_INIT* initid) void Json_Array_Delete_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Array_Delete_deinit } // end of Json_Array_Delete_deinit
/***********************************************************************/ /*********************************************************************************/
/* Make a Json Oject containing all the parameters. */ /* Make a Json Oject containing all the parameters. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Object_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool Json_Object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
...@@ -1698,7 +1640,7 @@ char *Json_Object(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1698,7 +1640,7 @@ char *Json_Object(UDF_INIT *initid, UDF_ARGS *args, char *result,
str = strcpy(result, g->Message); str = strcpy(result, g->Message);
// Keep result of constant function // Keep result of constant function
g->Xchk = (g->Alchecked) ? str : NULL; g->Xchk = (initid->const_item) ? str : NULL;
} else } else
str = (char*)g->Xchk; str = (char*)g->Xchk;
...@@ -1708,12 +1650,12 @@ char *Json_Object(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1708,12 +1650,12 @@ char *Json_Object(UDF_INIT *initid, UDF_ARGS *args, char *result,
void Json_Object_deinit(UDF_INIT* initid) void Json_Object_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Object_deinit } // end of Json_Object_deinit
/***********************************************************************/ /*********************************************************************************/
/* Make a Json Oject containing all not null parameters. */ /* Make a Json Oject containing all not null parameters. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Object_Nonull_init(UDF_INIT *initid, UDF_ARGS *args, my_bool Json_Object_Nonull_init(UDF_INIT *initid, UDF_ARGS *args,
char *message) char *message)
{ {
...@@ -1745,7 +1687,7 @@ char *Json_Object_Nonull(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1745,7 +1687,7 @@ char *Json_Object_Nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
str = strcpy(result, g->Message); str = strcpy(result, g->Message);
// Keep result of constant function // Keep result of constant function
g->Xchk = (g->Alchecked) ? str : NULL; g->Xchk = (initid->const_item) ? str : NULL;
} else } else
str = (char*)g->Xchk; str = (char*)g->Xchk;
...@@ -1755,12 +1697,12 @@ char *Json_Object_Nonull(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1755,12 +1697,12 @@ char *Json_Object_Nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
void Json_Object_Nonull_deinit(UDF_INIT* initid) void Json_Object_Nonull_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Object_nonull_deinit } // end of Json_Object_nonull_deinit
/***********************************************************************/ /*********************************************************************************/
/* Add or replace a value in a Json Object. */ /* Add or replace a value in a Json Object. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Object_Add_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool Json_Object_Add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
...@@ -1814,7 +1756,7 @@ char *Json_Object_Add(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1814,7 +1756,7 @@ char *Json_Object_Add(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!str) if (!str)
str = MakePSZ(g, args, 0); str = MakePSZ(g, args, 0);
if (g->Alchecked) if (initid->const_item)
// Keep result of constant function // Keep result of constant function
g->Xchk = str; g->Xchk = str;
...@@ -1824,12 +1766,12 @@ char *Json_Object_Add(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1824,12 +1766,12 @@ char *Json_Object_Add(UDF_INIT *initid, UDF_ARGS *args, char *result,
void Json_Object_Add_deinit(UDF_INIT* initid) void Json_Object_Add_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Object_Add_deinit } // end of Json_Object_Add_deinit
/***********************************************************************/ /*********************************************************************************/
/* Delete a value from a Json object. */ /* Delete a value from a Json object. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Object_Delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool Json_Object_Delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
...@@ -1886,7 +1828,7 @@ char *Json_Object_Delete(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1886,7 +1828,7 @@ char *Json_Object_Delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!str) if (!str)
str = MakePSZ(g, args, 0); str = MakePSZ(g, args, 0);
if (g->Alchecked) if (initid->const_item)
// Keep result of constant function // Keep result of constant function
g->Xchk = str; g->Xchk = str;
...@@ -1896,12 +1838,12 @@ char *Json_Object_Delete(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1896,12 +1838,12 @@ char *Json_Object_Delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
void Json_Object_Delete_deinit(UDF_INIT* initid) void Json_Object_Delete_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Object_Delete_deinit } // end of Json_Object_Delete_deinit
/***********************************************************************/ /*********************************************************************************/
/* Returns an array of the Json object keys. */ /* Returns an array of the Json object keys. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Object_List_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool Json_Object_List_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
...@@ -1942,11 +1884,11 @@ char *Json_Object_List(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1942,11 +1884,11 @@ char *Json_Object_List(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif CheckMemory } // endif CheckMemory
if (g->Alchecked) { if (initid->const_item) {
// Keep result of constant function // Keep result of constant function
g->Xchk = str; g->Xchk = str;
g->N = 1; // str can be NULL g->N = 1; // str can be NULL
} // endif Alchecked } // endif const_item
} else } else
str = (char*)g->Xchk; str = (char*)g->Xchk;
...@@ -1962,12 +1904,12 @@ char *Json_Object_List(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -1962,12 +1904,12 @@ char *Json_Object_List(UDF_INIT *initid, UDF_ARGS *args, char *result,
void Json_Object_List_deinit(UDF_INIT* initid) void Json_Object_List_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Object_List_deinit } // end of Json_Object_List_deinit
/***********************************************************************/ /*********************************************************************************/
/* Make a Json array from values coming from rows. */ /* Make a Json array from values coming from rows. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Array_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool Json_Array_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen, n = GetJsonGrpSize(); unsigned long reslen, memlen, n = GetJsonGrpSize();
...@@ -1975,6 +1917,9 @@ my_bool Json_Array_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -1975,6 +1917,9 @@ my_bool Json_Array_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
if (args->arg_count != 1) { if (args->arg_count != 1) {
strcpy(message, "Json_Array_Grp can only accept 1 argument"); strcpy(message, "Json_Array_Grp can only accept 1 argument");
return true; return true;
} else if (IsJson(args, 0) == 3) {
strcpy(message, "Json_Array_Grp does not support Bson argument");
return true;
} else } else
CalcLen(args, false, reslen, memlen); CalcLen(args, false, reslen, memlen);
...@@ -2032,18 +1977,21 @@ void Json_Array_Grp_clear(UDF_INIT *initid, char*, char*) ...@@ -2032,18 +1977,21 @@ void Json_Array_Grp_clear(UDF_INIT *initid, char*, char*)
void Json_Array_Grp_deinit(UDF_INIT* initid) void Json_Array_Grp_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Array_Grp_deinit } // end of Json_Array_Grp_deinit
/***********************************************************************/ /*********************************************************************************/
/* Make a Json object from values coming from rows. */ /* Make a Json object from values coming from rows. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Object_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool Json_Object_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen, n = GetJsonGrpSize(); unsigned long reslen, memlen, n = GetJsonGrpSize();
if (args->arg_count != 2) { if (args->arg_count != 2) {
strcpy(message, "Json_Array_Grp can only accept 2 arguments"); strcpy(message, "Json_Object_Grp can only accept 2 arguments");
return true;
} else if (IsJson(args, 0) == 3) {
strcpy(message, "Json_Object_Grp does not support Bson arguments");
return true; return true;
} else } else
CalcLen(args, true, reslen, memlen); CalcLen(args, true, reslen, memlen);
...@@ -2100,21 +2048,22 @@ void Json_Object_Grp_clear(UDF_INIT *initid, char*, char*) ...@@ -2100,21 +2048,22 @@ void Json_Object_Grp_clear(UDF_INIT *initid, char*, char*)
void Json_Object_Grp_deinit(UDF_INIT* initid) void Json_Object_Grp_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Object_Grp_deinit } // end of Json_Object_Grp_deinit
/***********************************************************************/ /*********************************************************************************/
/* Get a string value from a Json item. */ /* Get a string value from a Json item. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Get_String_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool JsonGetString_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
int n = IsJson(args, 0);
if (args->arg_count < 2) { if (args->arg_count < 2) {
strcpy(message, "Json_Get_String must have at least 2 arguments"); strcpy(message, "JsonGetString must have at least 2 arguments");
return true; return true;
} else if (!IsJson(args, 0) && args->arg_type[1] != STRING_RESULT) { } else if (!n && args->arg_type[0] != STRING_RESULT) {
strcpy(message, "Json_Get_String first argument must be a json item"); strcpy(message, "JsonGetString first argument must be a json item");
return true; return true;
} else if (args->arg_type[1] != STRING_RESULT) { } else if (args->arg_type[1] != STRING_RESULT) {
strcpy(message, "Second argument is not a (jpath) string"); strcpy(message, "Second argument is not a (jpath) string");
...@@ -2122,7 +2071,7 @@ my_bool Json_Get_String_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -2122,7 +2071,7 @@ my_bool Json_Get_String_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} else } else
CalcLen(args, false, reslen, memlen); CalcLen(args, false, reslen, memlen);
if (IsJson(args, 0) == 2) { if (n == 2) {
char fn[_MAX_PATH]; char fn[_MAX_PATH];
long fl; long fl;
...@@ -2130,13 +2079,13 @@ my_bool Json_Get_String_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -2130,13 +2079,13 @@ my_bool Json_Get_String_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
fn[args->lengths[0]] = 0; fn[args->lengths[0]] = 0;
fl = GetFileLength(fn); fl = GetFileLength(fn);
memlen += fl * 3; memlen += fl * 3;
} else } else if (n != 3)
memlen += args->lengths[0] * 3; memlen += args->lengths[0] * 3;
return JsonInit(initid, args, message, true, reslen, memlen); return JsonInit(initid, args, message, true, reslen, memlen);
} // end of Json_Get_String_init } // end of JsonGetString_init
char *Json_Get_String(UDF_INIT *initid, UDF_ARGS *args, char *result, char *JsonGetString(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *) unsigned long *res_length, char *is_null, char *)
{ {
char *str = NULL; char *str = NULL;
...@@ -2145,7 +2094,7 @@ char *Json_Get_String(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2145,7 +2094,7 @@ char *Json_Get_String(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (g->N) { if (g->N) {
str = (char*)g->Xchk; str = (char*)g->Xchk;
goto fin; goto fin;
} else if (g->Alchecked) } else if (initid->const_item)
g->N = 1; g->N = 1;
if (!CheckMemory(g, initid, args, 1, false)) { if (!CheckMemory(g, initid, args, 1, false)) {
...@@ -2189,7 +2138,7 @@ char *Json_Get_String(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2189,7 +2138,7 @@ char *Json_Get_String(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!jsx->GetValue()->IsNull()) if (!jsx->GetValue()->IsNull())
str = jsx->GetValue()->GetCharValue(); str = jsx->GetValue()->GetCharValue();
if (g->Alchecked) if (initid->const_item)
// Keep result of constant function // Keep result of constant function
g->Xchk = str; g->Xchk = str;
...@@ -2203,25 +2152,25 @@ char *Json_Get_String(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2203,25 +2152,25 @@ char *Json_Get_String(UDF_INIT *initid, UDF_ARGS *args, char *result,
*res_length = strlen(str); *res_length = strlen(str);
return str; return str;
} // end of Json_Get_String } // end of JsonGetString
void Json_Get_String_deinit(UDF_INIT* initid) void JsonGetString_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Get_String_deinit } // end of JsonGetString_deinit
/***********************************************************************/ /*********************************************************************************/
/* Get an integer value from a Json item. */ /* Get an integer value from a Json item. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Get_Int_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool JsonGetInt_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
if (args->arg_count != 2) { if (args->arg_count != 2) {
strcpy(message, "Json_Get_Int must have 2 arguments"); strcpy(message, "JsonGetInt must have 2 arguments");
return true; return true;
} else if (!IsJson(args, 0) && args->arg_type[1] != STRING_RESULT) { } else if (!IsJson(args, 0) && args->arg_type[0] != STRING_RESULT) {
strcpy(message, "Json_Get_Int first argument must be a json item"); strcpy(message, "JsonGetInt first argument must be a json item");
return true; return true;
} else if (args->arg_type[1] != STRING_RESULT) { } else if (args->arg_type[1] != STRING_RESULT) {
strcpy(message, "Second argument is not a (jpath) string"); strcpy(message, "Second argument is not a (jpath) string");
...@@ -2229,11 +2178,13 @@ my_bool Json_Get_Int_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -2229,11 +2178,13 @@ my_bool Json_Get_Int_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} else } else
CalcLen(args, false, reslen, memlen); CalcLen(args, false, reslen, memlen);
if (IsJson(args, 0) != 3)
memlen += 1000; // TODO: calculate this memlen += 1000; // TODO: calculate this
return JsonInit(initid, args, message, true, reslen, memlen); return JsonInit(initid, args, message, true, reslen, memlen);
} // end of Json_Get_Int_init } // end of JsonGetInt_init
long long Json_Get_Int(UDF_INIT *initid, UDF_ARGS *args, long long JsonGetInt(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error) char *is_null, char *error)
{ {
PGLOBAL g = (PGLOBAL)initid->ptr; PGLOBAL g = (PGLOBAL)initid->ptr;
...@@ -2245,7 +2196,7 @@ long long Json_Get_Int(UDF_INIT *initid, UDF_ARGS *args, ...@@ -2245,7 +2196,7 @@ long long Json_Get_Int(UDF_INIT *initid, UDF_ARGS *args,
} else } else
return *(long long*)g->Xchk; return *(long long*)g->Xchk;
} else if (g->Alchecked) } else if (initid->const_item)
g->N = 1; g->N = 1;
if (!CheckMemory(g, initid, args, 1, false)) { if (!CheckMemory(g, initid, args, 1, false)) {
...@@ -2296,12 +2247,12 @@ long long Json_Get_Int(UDF_INIT *initid, UDF_ARGS *args, ...@@ -2296,12 +2247,12 @@ long long Json_Get_Int(UDF_INIT *initid, UDF_ARGS *args,
n = jsx->GetValue()->GetBigintValue(); n = jsx->GetValue()->GetBigintValue();
if (g->Alchecked) { if (initid->const_item) {
// Keep result of constant function // Keep result of constant function
long long *np = (long long*)PlugSubAlloc(g, NULL, sizeof(long long)); long long *np = (long long*)PlugSubAlloc(g, NULL, sizeof(long long));
*np = n; *np = n;
g->Xchk = np; g->Xchk = np;
} // endif Alchecked } // endif const_item
return n; return n;
} // endif CheckMemory } // endif CheckMemory
...@@ -2309,25 +2260,25 @@ long long Json_Get_Int(UDF_INIT *initid, UDF_ARGS *args, ...@@ -2309,25 +2260,25 @@ long long Json_Get_Int(UDF_INIT *initid, UDF_ARGS *args,
if (g->Mrr) *error = 1; if (g->Mrr) *error = 1;
*is_null = 1; *is_null = 1;
return 0LL; return 0LL;
} // end of Json_Get_Int } // end of JsonGetInt
void Json_Get_Int_deinit(UDF_INIT* initid) void JsonGetInt_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Get_Int_deinit } // end of JsonGetInt_deinit
/***********************************************************************/ /*********************************************************************************/
/* Get a double value from a Json item. */ /* Get a double value from a Json item. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Get_Real_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool JsonGetReal_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
if (args->arg_count < 2) { if (args->arg_count < 2) {
strcpy(message, "Json_Get_Real must have at least 2 arguments"); strcpy(message, "JsonGetReal must have at least 2 arguments");
return true; return true;
} else if (!IsJson(args, 0) && args->arg_type[1] != STRING_RESULT) { } else if (!IsJson(args, 0) && args->arg_type[0] != STRING_RESULT) {
strcpy(message, "Json_Get_Real first argument must be a json item"); strcpy(message, "JsonGetReal first argument must be a json item");
return true; return true;
} else if (args->arg_type[1] != STRING_RESULT) { } else if (args->arg_type[1] != STRING_RESULT) {
strcpy(message, "Second argument is not a (jpath) string"); strcpy(message, "Second argument is not a (jpath) string");
...@@ -2343,11 +2294,14 @@ my_bool Json_Get_Real_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -2343,11 +2294,14 @@ my_bool Json_Get_Real_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
initid->decimals = 15; initid->decimals = 15;
CalcLen(args, false, reslen, memlen); CalcLen(args, false, reslen, memlen);
if (IsJson(args, 0) != 3)
memlen += 1000; // TODO: calculate this memlen += 1000; // TODO: calculate this
return JsonInit(initid, args, message, true, reslen, memlen); return JsonInit(initid, args, message, true, reslen, memlen);
} // end of Json_Get_Real_init } // end of JsonGetReal_init
double Json_Get_Real(UDF_INIT *initid, UDF_ARGS *args, double JsonGetReal(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error) char *is_null, char *error)
{ {
PGLOBAL g = (PGLOBAL)initid->ptr; PGLOBAL g = (PGLOBAL)initid->ptr;
...@@ -2359,7 +2313,7 @@ double Json_Get_Real(UDF_INIT *initid, UDF_ARGS *args, ...@@ -2359,7 +2313,7 @@ double Json_Get_Real(UDF_INIT *initid, UDF_ARGS *args,
} else } else
return *(double*)g->Xchk; return *(double*)g->Xchk;
} else if (g->Alchecked) } else if (initid->const_item)
g->N = 1; g->N = 1;
if (!CheckMemory(g, initid, args, 1, false)) { if (!CheckMemory(g, initid, args, 1, false)) {
...@@ -2409,12 +2363,12 @@ double Json_Get_Real(UDF_INIT *initid, UDF_ARGS *args, ...@@ -2409,12 +2363,12 @@ double Json_Get_Real(UDF_INIT *initid, UDF_ARGS *args,
d = jsx->GetValue()->GetFloatValue(); d = jsx->GetValue()->GetFloatValue();
if (g->Alchecked) { if (initid->const_item) {
// Keep result of constant function // Keep result of constant function
double *dp = (double*)PlugSubAlloc(g, NULL, sizeof(double)); double *dp = (double*)PlugSubAlloc(g, NULL, sizeof(double));
*dp = d; *dp = d;
g->Xchk = dp; g->Xchk = dp;
} // endif Alchecked } // endif const_item
return d; return d;
} // endif CheckMemory } // endif CheckMemory
...@@ -2422,17 +2376,17 @@ double Json_Get_Real(UDF_INIT *initid, UDF_ARGS *args, ...@@ -2422,17 +2376,17 @@ double Json_Get_Real(UDF_INIT *initid, UDF_ARGS *args,
if (g->Mrr) *error = 1; if (g->Mrr) *error = 1;
*is_null = 1; *is_null = 1;
return 0.0; return 0.0;
} // end of Json_Get_Real } // end of JsonGetReal
void Json_Get_Real_deinit(UDF_INIT* initid) void JsonGetReal_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Get_Real_deinit } // end of JsonGetReal_deinit
/***********************************************************************/ /*********************************************************************************/
/* Locate a value in a Json tree. */ /* Locate a value in a Json tree. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Locate_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool JsonLocate_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen, more = 1000; unsigned long reslen, memlen, more = 1000;
...@@ -2442,19 +2396,25 @@ my_bool Json_Locate_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -2442,19 +2396,25 @@ my_bool Json_Locate_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} else if (!IsJson(args, 0) && args->arg_type[0] != STRING_RESULT) { } else if (!IsJson(args, 0) && args->arg_type[0] != STRING_RESULT) {
strcpy(message, "Json_Locate first argument must be a json item"); strcpy(message, "Json_Locate first argument must be a json item");
return true; return true;
} else if (args->arg_count > 2) } else if (args->arg_count > 2 && args->arg_type[2] != INT_RESULT) {
if (args->arg_type[2] != INT_RESULT) { strcpy(message, "Third argument is not an integer (rank)");
strcpy(message, "Third argument is not an integer (memory)"); return true;
} else if (args->arg_count > 3)
if (args->arg_type[3] != INT_RESULT) {
strcpy(message, "Fourth argument is not an integer (memory)");
return true; return true;
} else } else
more = (ulong)*(longlong*)args->args[2]; more = (ulong)*(longlong*)args->args[2];
CalcLen(args, false, reslen, memlen); CalcLen(args, false, reslen, memlen);
memlen += more; // TODO: calculate this
if (IsJson(args, 0) != 3)
memlen += 1000; // TODO: calculate this
return JsonInit(initid, args, message, true, reslen, memlen); return JsonInit(initid, args, message, true, reslen, memlen);
} // end of Json_Locate_init } // end of JsonLocate_init
char *Json_Locate(UDF_INIT *initid, UDF_ARGS *args, char *result, char *JsonLocate(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *error) unsigned long *res_length, char *is_null, char *error)
{ {
char *path = NULL; char *path = NULL;
...@@ -2471,13 +2431,13 @@ char *Json_Locate(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2471,13 +2431,13 @@ char *Json_Locate(UDF_INIT *initid, UDF_ARGS *args, char *result,
return NULL; return NULL;
} // endif Xchk } // endif Xchk
} else if (g->Alchecked) } else if (initid->const_item)
g->N = 1; g->N = 1;
if (!CheckMemory(g, initid, args, 1, false)) { if (!CheckMemory(g, initid, args, 1, false)) {
char *p; char *p;
int rc; int k, rc;
PJVAL jvp; PJVAL jvp, jvp2;
PJSON jsp; PJSON jsp;
PJSNX jsx; PJSNX jsx;
...@@ -2516,10 +2476,15 @@ char *Json_Locate(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2516,10 +2476,15 @@ char *Json_Locate(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else } else
jsp = (PJSON)g->Xchk; jsp = (PJSON)g->Xchk;
// The item to locate
jvp2 = MakeValue(g, args, 1);
k = (args->arg_count > 2) ? (int)*(long long*)args->args[2] : 1;
jsx = new(g)JSNX(g, jsp, TYPE_STRING); jsx = new(g)JSNX(g, jsp, TYPE_STRING);
path = jsx->Locate(g, jsp, args->args[1], args->arg_type[1], args->lengths[1]); path = jsx->Locate(g, jsp, jvp2, k);
if (g->Alchecked) if (initid->const_item)
// Keep result of constant function // Keep result of constant function
g->Xchk = path; g->Xchk = path;
...@@ -2538,16 +2503,145 @@ char *Json_Locate(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2538,16 +2503,145 @@ char *Json_Locate(UDF_INIT *initid, UDF_ARGS *args, char *result,
*error = 1; *error = 1;
*is_null = 1; *is_null = 1;
return NULL; return NULL;
} // end of Json_Locate } // end of JsonLocate
void Json_Locate_deinit(UDF_INIT* initid) void Json_Locate_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Locate_deinit } // end of JsonLocate_deinit
/*********************************************************************************/
/* Locate all occurences of a value in a Json tree. */
/*********************************************************************************/
my_bool Json_Locate_All_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
unsigned long reslen, memlen, more = 1000;
if (args->arg_count < 2) {
strcpy(message, "Json_Locate must have at least 2 arguments");
return true;
} else if (!IsJson(args, 0) && args->arg_type[0] != STRING_RESULT) {
strcpy(message, "Json_Locate 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;
} else if (args->arg_count > 3)
if (args->arg_type[3] != INT_RESULT) {
strcpy(message, "Fourth argument is not an integer (memory)");
return true;
} else
more = (ulong)*(longlong*)args->args[2];
CalcLen(args, false, reslen, memlen);
if (IsJson(args, 0) != 3)
memlen += 1000; // TODO: calculate this
return JsonInit(initid, args, message, false, reslen, memlen);
} // end of Json_Locate_All_init
char *Json_Locate_All(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *error)
{
char *path = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
/***********************************************************************/ if (g->N) {
/* Returns a json file as a string. */ if (g->Xchk) {
/***********************************************************************/ path = (char*)g->Xchk;
*res_length = strlen(path);
return path;
} else {
*error = 1;
*res_length = 0;
*is_null = 1;
return NULL;
} // endif Xchk
} else if (initid->const_item)
g->N = 1;
if (!CheckMemory(g, initid, args, 1, false)) {
char *p;
int rc, mx = 10;
PJVAL jvp, jvp2;
PJSON jsp;
PJSNX jsx;
// Save stack and allocation environment and prepare error return
if (g->jump_level == MAX_JUMP) {
PUSH_WARNING(MSG(TOO_MANY_JUMPS));
*error = 1;
*is_null = 1;
return NULL;
} // endif jump_level
if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
PUSH_WARNING(g->Message);
*error = 1;
path = NULL;
goto err;
} // endif rc
if (!g->Xchk) {
jvp = MakeValue(g, args, 0);
if ((p = jvp->GetString())) {
if (!(jsp = ParseJson(g, p, strlen(p)))) {
PUSH_WARNING(g->Message);
goto err;
} // endif jsp
} else
jsp = jvp->GetJson();
if (g->Mrr) { // First argument is a constant
g->Xchk = jsp;
JsonMemSave(g);
} // endif Mrr
} else
jsp = (PJSON)g->Xchk;
// The item to locate
jvp2 = MakeValue(g, args, 1);
if (args->arg_count > 2)
mx = (int)*(long long*)args->args[2];
jsx = new(g)JSNX(g, jsp, TYPE_STRING);
path = jsx->LocateAll(g, jsp, jvp2, mx);
if (initid->const_item)
// Keep result of constant function
g->Xchk = path;
err:
g->jump_level--;
if (!path) {
*res_length = 0;
*is_null = 1;
} else
*res_length = strlen(path);
return path;
} // endif CheckMemory
*error = 1;
*is_null = 1;
return NULL;
} // end of Json_Locate_All
void Json_Locate_All_deinit(UDF_INIT* initid)
{
JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Locate_All_deinit
/*********************************************************************************/
/* Returns a json file as a json string. */
/*********************************************************************************/
my_bool Json_File_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool Json_File_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen, fl, more = 1024; unsigned long reslen, memlen, fl, more = 1024;
...@@ -2596,7 +2690,7 @@ char *Json_File(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2596,7 +2690,7 @@ char *Json_File(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (g->N) { if (g->N) {
str = (char*)g->Xchk; str = (char*)g->Xchk;
goto fin; goto fin;
} else if (g->Alchecked) } else if (initid->const_item)
g->N = 1; g->N = 1;
PlugSubSet(g, g->Sarea, g->Sarea_Size); PlugSubSet(g, g->Sarea, g->Sarea_Size);
...@@ -2611,9 +2705,9 @@ char *Json_File(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2611,9 +2705,9 @@ char *Json_File(UDF_INIT *initid, UDF_ARGS *args, char *result,
pretty = (args->arg_count > 2) ? (int)*(longlong*)args->args[2] : 3; pretty = (args->arg_count > 2) ? (int)*(longlong*)args->args[2] : 3;
/*******************************************************************/ /*****************************************************************************/
/* Create the mapping file object. */ /* Create the mapping file object. */
/*******************************************************************/ /*****************************************************************************/
hFile = CreateFileMap(g, fn, &mm, MODE_READ, false); hFile = CreateFileMap(g, fn, &mm, MODE_READ, false);
if (hFile == INVALID_HANDLE_VALUE) { if (hFile == INVALID_HANDLE_VALUE) {
...@@ -2628,9 +2722,9 @@ char *Json_File(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2628,9 +2722,9 @@ char *Json_File(UDF_INIT *initid, UDF_ARGS *args, char *result,
return NULL; return NULL;
} // endif hFile } // endif hFile
/*******************************************************************/ /*****************************************************************************/
/* Get the file size (assuming file is smaller than 4 GB) */ /* Get the file size (assuming file is smaller than 4 GB) */
/*******************************************************************/ /*****************************************************************************/
len = mm.lenL; len = mm.lenL;
memory = (char *)mm.memory; memory = (char *)mm.memory;
...@@ -2651,9 +2745,9 @@ char *Json_File(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2651,9 +2745,9 @@ char *Json_File(UDF_INIT *initid, UDF_ARGS *args, char *result,
CloseFileHandle(hFile); // Not used anymore CloseFileHandle(hFile); // Not used anymore
hFile = INVALID_HANDLE_VALUE; // For Fblock hFile = INVALID_HANDLE_VALUE; // For Fblock
/*********************************************************************/ /*******************************************************************************/
/* Parse the json file and allocate its tree structure. */ /* Parse the json file and allocate its tree structure. */
/*********************************************************************/ /*******************************************************************************/
g->Message[0] = 0; g->Message[0] = 0;
if (!(jsp = ParseJson(g, memory, len, pretty))) { if (!(jsp = ParseJson(g, memory, len, pretty))) {
...@@ -2669,7 +2763,7 @@ char *Json_File(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2669,7 +2763,7 @@ char *Json_File(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else } else
str = GetJsonFile(g, fn); str = GetJsonFile(g, fn);
if (g->Alchecked) if (initid->const_item)
// Keep result of constant function // Keep result of constant function
g->Xchk = str; g->Xchk = str;
...@@ -2685,21 +2779,21 @@ char *Json_File(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2685,21 +2779,21 @@ char *Json_File(UDF_INIT *initid, UDF_ARGS *args, char *result,
void Json_File_deinit(UDF_INIT* initid) void Json_File_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_File_deinit } // end of Json_File_deinit
/***********************************************************************/ /*********************************************************************************/
/* Make a json file from a json item. */ /* Make a json file from a json item. */
/***********************************************************************/ /*********************************************************************************/
my_bool Json_Make_File_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool JsonMakeFile_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen, more = 1024; unsigned long reslen, memlen, more = 1024;
if (args->arg_count < 2 || args->arg_count > 3) { if (args->arg_count < 2 || args->arg_count > 3) {
strcpy(message, "Json_Make_File only accepts 2 or 3 arguments"); strcpy(message, "JsonMakeFile only accepts 2 or 3 arguments");
return true; return true;
} else if (IsJson(args, 0) != 1) { } else if (!IsJson(args, 0) || IsJson(args, 0) > 2) {
strcpy(message, "Json_Make_File first argument must be a json item"); strcpy(message, "JsonMakeFile first argument must be a json item");
return true; return true;
} else if (args->arg_type[1] != STRING_RESULT) { } else if (args->arg_type[1] != STRING_RESULT) {
strcpy(message, "Second argument must be a (string) file name"); strcpy(message, "Second argument must be a (string) file name");
...@@ -2711,9 +2805,9 @@ my_bool Json_Make_File_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -2711,9 +2805,9 @@ my_bool Json_Make_File_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
CalcLen(args, false, reslen, memlen); CalcLen(args, false, reslen, memlen);
return JsonInit(initid, args, message, true, reslen, memlen); return JsonInit(initid, args, message, true, reslen, memlen);
} // end of Json_Make_File_init } // end of JsonMakeFile_init
char *Json_Make_File(UDF_INIT *initid, UDF_ARGS *args, char *result, char *JsonMakeFile(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *) unsigned long *res_length, char *is_null, char *)
{ {
char *str, *fn, *msg; char *str, *fn, *msg;
...@@ -2724,7 +2818,7 @@ char *Json_Make_File(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2724,7 +2818,7 @@ char *Json_Make_File(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (g->N) { if (g->N) {
str = (char*)g->Xchk; str = (char*)g->Xchk;
goto fin; goto fin;
} else if (g->Alchecked) } else if (initid->const_item)
g->N = 1; g->N = 1;
PlugSubSet(g, g->Sarea, g->Sarea_Size); PlugSubSet(g, g->Sarea, g->Sarea_Size);
...@@ -2748,7 +2842,7 @@ char *Json_Make_File(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2748,7 +2842,7 @@ char *Json_Make_File(UDF_INIT *initid, UDF_ARGS *args, char *result,
str= fn; str= fn;
if (g->Alchecked) if (initid->const_item)
// Keep result of constant function // Keep result of constant function
g->Xchk = str; g->Xchk = str;
...@@ -2760,9 +2854,55 @@ char *Json_Make_File(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2760,9 +2854,55 @@ char *Json_Make_File(UDF_INIT *initid, UDF_ARGS *args, char *result,
*res_length = strlen(str); *res_length = strlen(str);
return str; return str;
} // end of Json_Make_File } // end of JsonMakeFile
void JsonMakeFile_deinit(UDF_INIT* initid)
{
JsonMemFree((PGLOBAL)initid->ptr);
} // end of JsonMakeFile_deinit
/*********************************************************************************/
/* Make and return a binary Json array containing all the parameters. */
/*********************************************************************************/
my_bool Bson_Array_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
unsigned long reslen, memlen;
CalcLen(args, false, reslen, memlen);
memlen *= 2; // TODO: Make this adjustable
return JsonInit(initid, args, message, false, reslen, memlen);
} // end of Bson_Array_init
char *Bson_Array(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *, char *)
{
PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = (PBSON)g->Xchk;
if (!bsp || bsp->Changed) {
if (!CheckMemory(g, initid, args, args->arg_count, false)) {
PJAR arp = new(g)JARRAY;
for (uint i = 0; i < args->arg_count; i++)
arp->AddValue(g, MakeValue(g, args, i));
arp->InitArray(g);
bsp = BsonAlloc(g, initid->max_length, arp);
strcat(bsp->Msg, " array");
} else {
bsp = BsonAlloc(g, initid->max_length, NULL);
strncpy(bsp->Msg, g->Message, 139);
} // endif CheckMemory
// Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp
*res_length = sizeof(BSON);
return (char*)bsp;
} // end of Bson_Array
void Json_Make_File_deinit(UDF_INIT* initid) void Bson_Array_deinit(UDF_INIT* initid)
{ {
PlugExit((PGLOBAL)initid->ptr); JsonMemFree((PGLOBAL)initid->ptr);
} // end of Json_Make_File_deinit } // end of Bson_Array_deinit
/*************** tabjson H Declares Source Code File (.H) **************/ /******************** tabjson H Declares Source Code File (.H) *******************/
/* Name: jsonudf.h Version 1.1 */ /* Name: jsonudf.h Version 1.1 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2015 */ /* (C) Copyright to the author Olivier BERTRAND 2015 */
/* */ /* */
/* This file contains the JSON UDF function and classe declares. */ /* This file contains the JSON UDF function and class declares. */
/***********************************************************************/ /*********************************************************************************/
#include "global.h" #include "global.h"
#include "plgdbsem.h" #include "plgdbsem.h"
#include "block.h" #include "block.h"
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
#define UDF_EXEC_ARGS \ #define UDF_EXEC_ARGS \
UDF_INIT*, UDF_ARGS*, char*, unsigned long*, char*, char* UDF_INIT*, UDF_ARGS*, char*, unsigned long*, char*, char*
/***********************************************************************/ /*********************************************************************************/
/* The JSON tree node. Can be an Object or an Array. */ /* The JSON tree node. Can be an Object or an Array. */
/***********************************************************************/ /*********************************************************************************/
typedef struct _jnode { typedef struct _jnode {
PSZ Key; // The key used for object PSZ Key; // The key used for object
OPVAL Op; // Operator used for this node OPVAL Op; // Operator used for this node
...@@ -30,6 +30,7 @@ typedef struct _jnode { ...@@ -30,6 +30,7 @@ typedef struct _jnode {
typedef class JSNX *PJSNX; typedef class JSNX *PJSNX;
typedef class JOUTPATH *PJTP; typedef class JOUTPATH *PJTP;
typedef class JOUTALL *PJTA;
extern "C" { extern "C" {
DllExport my_bool Json_Value_init(UDF_INIT*, UDF_ARGS*, char*); DllExport my_bool Json_Value_init(UDF_INIT*, UDF_ARGS*, char*);
...@@ -84,34 +85,51 @@ extern "C" { ...@@ -84,34 +85,51 @@ extern "C" {
DllExport void Json_Object_Grp_clear(UDF_INIT *, char *, char *); DllExport void Json_Object_Grp_clear(UDF_INIT *, char *, char *);
DllExport void Json_Object_Grp_deinit(UDF_INIT*); DllExport void Json_Object_Grp_deinit(UDF_INIT*);
DllExport my_bool Json_Get_String_init(UDF_INIT*, UDF_ARGS*, char*); DllExport my_bool JsonGetString_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *Json_Get_String(UDF_EXEC_ARGS); DllExport char *JsonGetString(UDF_EXEC_ARGS);
DllExport void Json_Get_String_deinit(UDF_INIT*); DllExport void JsonGetString_deinit(UDF_INIT*);
DllExport my_bool Json_Get_Int_init(UDF_INIT*, UDF_ARGS*, char*); DllExport my_bool JsonGetInt_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport long long Json_Get_Int(UDF_INIT*, UDF_ARGS*, char*, char*); DllExport long long JsonGetInt(UDF_INIT*, UDF_ARGS*, char*, char*);
DllExport void Json_Get_Int_deinit(UDF_INIT*); DllExport void JsonGetInt_deinit(UDF_INIT*);
DllExport my_bool Json_Get_Real_init(UDF_INIT*, UDF_ARGS*, char*); DllExport my_bool JsonGetReal_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport double Json_Get_Real(UDF_INIT*, UDF_ARGS*, char*, char*); DllExport double JsonGetReal(UDF_INIT*, UDF_ARGS*, char*, char*);
DllExport void Json_Get_Real_deinit(UDF_INIT*); DllExport void JsonGetReal_deinit(UDF_INIT*);
DllExport my_bool Json_Locate_init(UDF_INIT*, UDF_ARGS*, char*); DllExport my_bool JsonLocate_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *Json_Locate(UDF_EXEC_ARGS); DllExport char *JsonLocate(UDF_EXEC_ARGS);
DllExport void Json_Locate_deinit(UDF_INIT*); DllExport void JsonLocate_deinit(UDF_INIT*);
DllExport my_bool Json_Locate_All_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *Json_Locate_All(UDF_EXEC_ARGS);
DllExport void Json_Locate_All_deinit(UDF_INIT*);
DllExport my_bool Json_File_init(UDF_INIT*, UDF_ARGS*, char*); DllExport my_bool Json_File_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *Json_File(UDF_EXEC_ARGS); DllExport char *Json_File(UDF_EXEC_ARGS);
DllExport void Json_File_deinit(UDF_INIT*); DllExport void Json_File_deinit(UDF_INIT*);
DllExport my_bool Json_Make_File_init(UDF_INIT*, UDF_ARGS*, char*); DllExport my_bool JsonMakeFile_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *Json_Make_File(UDF_EXEC_ARGS); DllExport char *JsonMakeFile(UDF_EXEC_ARGS);
DllExport void Json_Make_File_deinit(UDF_INIT*); DllExport void JsonMakeFile_deinit(UDF_INIT*);
DllExport my_bool Bson_Array_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *Bson_Array(UDF_EXEC_ARGS);
DllExport void Bson_Array_deinit(UDF_INIT*);
} // extern "C" } // extern "C"
/***********************************************************************/ /*********************************************************************************/
/* Structure JPN. Used to make the locate path. */
/*********************************************************************************/
typedef struct _jpn {
enum JTYP Type;
PSZ Key;
int N;
} JPN, *PJPN;
/*********************************************************************************/
/* Class JSNX: JSON access method. */ /* Class JSNX: JSON access method. */
/***********************************************************************/ /*********************************************************************************/
class JSNX : public BLOCK { class JSNX : public BLOCK {
public: public:
// Constructors // Constructors
...@@ -126,11 +144,10 @@ class JSNX : public BLOCK { ...@@ -126,11 +144,10 @@ class JSNX : public BLOCK {
my_bool ParseJpath(PGLOBAL g); my_bool ParseJpath(PGLOBAL g);
void ReadValue(PGLOBAL g); void ReadValue(PGLOBAL g);
PJVAL GetJson(PGLOBAL g); PJVAL GetJson(PGLOBAL g);
char *Locate(PGLOBAL g, PJSON jsp, char *what, char *Locate(PGLOBAL g, PJSON jsp, PJVAL jvp, int k = 1);
enum Item_result type, unsigned long len); char *LocateAll(PGLOBAL g, PJSON jsp, PJVAL jvp, int mx = 10);
protected: protected:
my_bool CheckExpand(PGLOBAL g, int i, PSZ nm, my_bool b);
my_bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm); my_bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm);
PVAL GetColumnValue(PGLOBAL g, PJSON row, int i); PVAL GetColumnValue(PGLOBAL g, PJSON row, int i);
PJVAL GetValue(PGLOBAL g, PJSON row, int i); PJVAL GetValue(PGLOBAL g, PJSON row, int i);
...@@ -138,42 +155,37 @@ class JSNX : public BLOCK { ...@@ -138,42 +155,37 @@ class JSNX : public BLOCK {
PVAL CalculateArray(PGLOBAL g, PJAR arp, int n); PVAL CalculateArray(PGLOBAL g, PJAR arp, int n);
PVAL MakeJson(PGLOBAL g, PJSON jsp); PVAL MakeJson(PGLOBAL g, PJSON jsp);
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n); void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n);
//PJSON GetRow(PGLOBAL g);
my_bool LocateArray(PJAR jarp); my_bool LocateArray(PJAR jarp);
my_bool LocateObject(PJOB jobp); my_bool LocateObject(PJOB jobp);
my_bool LocateValue(PJVAL jvp); my_bool LocateValue(PJVAL jvp);
my_bool LocateArrayAll(PJAR jarp);
my_bool LocateObjectAll(PJOB jobp);
my_bool LocateValueAll(PJVAL jvp);
my_bool CompareTree(PJSON jp1, PJSON jp2);
my_bool AddPath(void);
// Default constructor not to be used // Default constructor not to be used
JSNX(void) {} JSNX(void) {}
// Members // Members
PJSON Row; PJSON Row;
PJVAL Jvalp;
PJPN Jpnp;
JOUTSTR *Jp;
JNODE *Nodes; // The intermediate objects
PVAL Value; PVAL Value;
PVAL MulVal; // To value used by multiple column PVAL MulVal; // To value used by multiple column
PJTP Jp;
JNODE *Nodes; // The intermediate objects
char *Jpath; // The json path char *Jpath; // The json path
int Buf_Type; int Buf_Type;
int Long; int Long;
int Prec; int Prec;
int Nod; // The number of intermediate objects int Nod; // The number of intermediate objects
int Xnod; // Index of multiple values 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 int B; // Index base
my_bool Xpd; // True for expandable column my_bool Xpd; // True for expandable column
my_bool Parsed; // True when parsed my_bool Parsed; // True when parsed
my_bool Found; // Item found by locate
}; // end of class JSNX }; // end of class JSNX
/***********************************************************************/
/* Class JOUTPATH. Used to make the locate path. */
/***********************************************************************/
class JOUTPATH : public JOUTSTR {
public:
JOUTPATH(PGLOBAL g, char *w, enum Item_result type, unsigned long len)
: JOUTSTR(g) {What = w; Type = type; Len = len; Found = false;}
// Members
enum Item_result Type;
unsigned long Len;
char *What;
my_bool Found;
}; // end of class JOUTPATH
...@@ -20,14 +20,14 @@ Array ...@@ -20,14 +20,14 @@ Array
[56,3.141600,"foo",null,"One more"] [56,3.141600,"foo",null,"One more"]
SELECT Json_Array_Add(Json_Value('one value'),'One more'); SELECT Json_Array_Add(Json_Value('one value'),'One more');
Json_Array_Add(Json_Value('one value'),'One more') Json_Array_Add(Json_Value('one value'),'One more')
"one value" NULL
Warnings: Warnings:
Warning 1105 First argument is not an array Warning 1105 First argument is not an array
SELECT Json_Array_Add('one value','One more'); SELECT Json_Array_Add('one value','One more');
ERROR HY000: Can't initialize function 'Json_Array_Add'; Json_Array_Add first argument must be a json item ERROR HY000: Can't initialize function 'Json_Array_Add'; Json_Array_Add first argument must be a json item
SELECT Json_Array_Add('one value' json_,'One more'); SELECT Json_Array_Add('one value' json_,'One more');
Json_Array_Add('one value' json_,'One more') Json_Array_Add('one value' json_,'One more')
one value NULL
Warnings: Warnings:
Warning 1105 Unexpected character 'o' near one value Warning 1105 Unexpected character 'o' near one value
Warning 1105 First argument is not an array Warning 1105 First argument is not an array
...@@ -147,7 +147,7 @@ Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY ...@@ -147,7 +147,7 @@ Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY
{"DEPARTMENT":"2452","TITLE":"SCIENTIST","EMPLOYES":[{"SERIALNO":"34567","NAME":"BIGHEAD","SALARY":8000.000000},{"SERIALNO":"36666","NAME":"BIGHORN","SALARY":11000.000000}]} {"DEPARTMENT":"2452","TITLE":"SCIENTIST","EMPLOYES":[{"SERIALNO":"34567","NAME":"BIGHEAD","SALARY":8000.000000},{"SERIALNO":"36666","NAME":"BIGHORN","SALARY":11000.000000}]}
{"DEPARTMENT":"2452","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"11111","NAME":"CHERRY","SALARY":4500.000000}]} {"DEPARTMENT":"2452","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"11111","NAME":"CHERRY","SALARY":4500.000000}]}
SELECT Json_Object_Grp(SALARY) FROM t1; SELECT Json_Object_Grp(SALARY) FROM t1;
ERROR HY000: Can't initialize function 'Json_Object_Grp'; Json_Array_Grp can only accept 2 arguments ERROR HY000: Can't initialize function 'Json_Object_Grp'; Json_Object_Grp can only accept 2 arguments
SELECT Json_Object_Grp(SALARY, NAME) FROM t1; SELECT Json_Object_Grp(SALARY, NAME) FROM t1;
Json_Object_Grp(SALARY, NAME) Json_Object_Grp(SALARY, NAME)
{"BANCROFT":9600.000000,"SMITH":9000.000000,"MERCHANT":8700.000000,"FUNNIGUY":8500.000000,"BUGHAPPY":8500.000000,"BIGHEAD":8000.000000,"SHRINKY":7500.000000,"WALTER":7400.000000,"FODDERMAN":7000.000000,"TONGHO":6800.000000,"SHORTSIGHT":5500.000000,"MESSIFUL":5000.500000,"HONEY":4900.000000,"GOOSEPEN":4700.000000,"CHERRY":4500.000000,"MONAPENNY":3800.000000,"KITTY":3000.450000,"PLUMHEAD":2800.000000,"STRONG":23000.000000,"BULLOZER":14800.000000,"WERTHER":14500.000000,"QUINN":14000.000000,"ORELLY":13400.000000,"BIGHORN":11000.000000,"BROWNY":10500.000000,"WHEELFOR":10030.000000,"MARTIN":10000.000000} {"BANCROFT":9600.000000,"SMITH":9000.000000,"MERCHANT":8700.000000,"FUNNIGUY":8500.000000,"BUGHAPPY":8500.000000,"BIGHEAD":8000.000000,"SHRINKY":7500.000000,"WALTER":7400.000000,"FODDERMAN":7000.000000,"TONGHO":6800.000000,"SHORTSIGHT":5500.000000,"MESSIFUL":5000.500000,"HONEY":4900.000000,"GOOSEPEN":4700.000000,"CHERRY":4500.000000,"MONAPENNY":3800.000000,"KITTY":3000.450000,"PLUMHEAD":2800.000000,"STRONG":23000.000000,"BULLOZER":14800.000000,"WERTHER":14500.000000,"QUINN":14000.000000,"ORELLY":13400.000000,"BIGHORN":11000.000000,"BROWNY":10500.000000,"WHEELFOR":10030.000000,"MARTIN":10000.000000}
......
...@@ -143,7 +143,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize) ...@@ -143,7 +143,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL)); fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL));
return NULL; return NULL;
} else { } else {
g->Sarea_Size = worksize; g->Sarea = NULL;
g->Createas = 0; g->Createas = 0;
g->Alchecked = 0; g->Alchecked = 0;
g->Mrr = 0; g->Mrr = 0;
...@@ -155,7 +155,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize) ...@@ -155,7 +155,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
/*******************************************************************/ /*******************************************************************/
/* Allocate the main work segment. */ /* Allocate the main work segment. */
/*******************************************************************/ /*******************************************************************/
if (!(g->Sarea = PlugAllocMem(g, worksize))) { if (worksize && !(g->Sarea = PlugAllocMem(g, worksize))) {
char errmsg[256]; char errmsg[256];
sprintf(errmsg, MSG(WORK_AREA), g->Message); sprintf(errmsg, MSG(WORK_AREA), g->Message);
strcpy(g->Message, errmsg); strcpy(g->Message, errmsg);
......
...@@ -340,7 +340,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec) ...@@ -340,7 +340,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec)
switch (type) { switch (type) {
case TYPE_STRING: case TYPE_STRING:
valp = new(g) TYPVAL<PSZ>((PSZ)value); valp = new(g) TYPVAL<PSZ>((PSZ)value, prec);
break; break;
case TYPE_SHORT: case TYPE_SHORT:
valp = new(g) TYPVAL<short>(*(short*)value, TYPE_SHORT); valp = new(g) TYPVAL<short>(*(short*)value, TYPE_SHORT);
...@@ -1209,12 +1209,12 @@ void TYPVAL<TYPE>::Print(PGLOBAL g, char *ps, uint z) ...@@ -1209,12 +1209,12 @@ void TYPVAL<TYPE>::Print(PGLOBAL g, char *ps, uint z)
/***********************************************************************/ /***********************************************************************/
/* STRING public constructor from a constant string. */ /* STRING public constructor from a constant string. */
/***********************************************************************/ /***********************************************************************/
TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING) TYPVAL<PSZ>::TYPVAL(PSZ s, short c) : VALUE(TYPE_STRING)
{ {
Strp = s; Strp = s;
Len = strlen(s); Len = strlen(s);
Clen = Len; Clen = Len;
Ci = false; Ci = (c == 1);
} // end of STRING constructor } // end of STRING constructor
/***********************************************************************/ /***********************************************************************/
......
...@@ -216,7 +216,7 @@ template <> ...@@ -216,7 +216,7 @@ template <>
class DllExport TYPVAL<PSZ>: public VALUE { class DllExport TYPVAL<PSZ>: public VALUE {
public: public:
// Constructors // Constructors
TYPVAL(PSZ s); TYPVAL(PSZ s, short c = 0);
TYPVAL(PGLOBAL g, PSZ s, int n, int c); TYPVAL(PGLOBAL g, PSZ s, int n, int c);
// Implementation // Implementation
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment