summaryrefslogtreecommitdiff
path: root/storage/connect/jsonudf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/connect/jsonudf.cpp')
-rw-r--r--storage/connect/jsonudf.cpp1992
1 files changed, 1444 insertions, 548 deletions
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
index 0b40f1d18cf..40685ae0f0e 100644
--- a/storage/connect/jsonudf.cpp
+++ b/storage/connect/jsonudf.cpp
@@ -36,7 +36,7 @@ static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i);
/*********************************************************************************/
/* 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, my_bool wr)
{
Row = row;
Jvalp = NULL;
@@ -58,6 +58,8 @@ JSNX::JSNX(PGLOBAL g, PJSON row, int type, int len, int prec)
Xpd = false;
Parsed = false;
Found = false;
+ Wr = wr;
+ Jb = false;
} // end of JSNX constructor
/*********************************************************************************/
@@ -71,6 +73,7 @@ my_bool JSNX::SetJpath(PGLOBAL g, char *path, my_bool jb)
Value->SetNullable(true);
+#if 0
if (jb) {
// Path must return a Json item
size_t n = strlen(path);
@@ -82,9 +85,13 @@ my_bool JSNX::SetJpath(PGLOBAL g, char *path, my_bool jb)
Jpath = path;
} else
+#endif // 0
Jpath = path;
// Parse the json path
+ Parsed = false;
+ Nod = 0;
+ Jb = jb;
return ParseJpath(g);
} // end of SetJpath
@@ -117,7 +124,14 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
if (!n) {
// Default specifications
if (jnp->Op != OP_EXP) {
- if (b) {
+ if (Wr) {
+ // Force append
+ jnp->Rank = INT_MAX32;
+ jnp->Op = OP_LE;
+ } else if (Jb) {
+ // Return a Json item
+ jnp->Op = OP_XX;
+ } else if (b) {
// Return 1st value (B is the index base)
jnp->Rank = B;
jnp->Op = OP_LE;
@@ -133,6 +147,9 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
// Return nth value
jnp->Rank = atoi(p) - B;
jnp->Op = OP_EQ;
+ } else if (Wr) {
+ sprintf(g->Message, "Invalid specification %s in a write path", p);
+ return true;
} else if (n == 1) {
// Set the Op value;
switch (*p) {
@@ -240,8 +257,12 @@ my_bool JSNX::ParseJpath(PGLOBAL g)
return true;
} else if (*p == '*') {
- // Return JSON
- Nodes[i].Op = OP_XX;
+ if (Wr) {
+ sprintf(g->Message, "Invalid specification %c in a write path", *p);
+ return true;
+ } else // Return JSON
+ Nodes[i].Op = OP_XX;
+
} else {
Nodes[i].Key = p;
Nodes[i].Op = OP_EXIST;
@@ -262,7 +283,10 @@ PVAL JSNX::MakeJson(PGLOBAL g, PJSON jsp)
if (Value->IsTypeNum()) {
strcpy(g->Message, "Cannot make Json for a numeric value");
Value->Reset();
- } else
+ } else if (jsp->GetType() != TYPE_JAR && jsp->GetType() != TYPE_JOB) {
+ strcpy(g->Message, "Target is not an array or object");
+ Value->Reset();
+ } else
Value->SetValue_psz(Serialize(g, jsp, NULL, 0));
return Value;
@@ -274,32 +298,34 @@ PVAL JSNX::MakeJson(PGLOBAL g, PJSON jsp)
void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
{
if (val) {
- switch (val->GetValType()) {
- case TYPE_STRG:
- case TYPE_INTG:
- case TYPE_BINT:
- case TYPE_DBL:
- vp->SetValue_pval(val->GetValue());
- break;
- case TYPE_BOOL:
- if (vp->IsTypeNum())
- vp->SetValue(val->GetInteger() ? 1 : 0);
- else
- vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false"));
+ if (Jb) {
+ vp->SetValue_psz(Serialize(g, val->GetJsp(), NULL, 0));
+ } else switch (val->GetValType()) {
+ case TYPE_STRG:
+ case TYPE_INTG:
+ case TYPE_BINT:
+ case TYPE_DBL:
+ vp->SetValue_pval(val->GetValue());
+ break;
+ case TYPE_BOOL:
+ if (vp->IsTypeNum())
+ vp->SetValue(val->GetInteger() ? 1 : 0);
+ else
+ vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false"));
- break;
- case TYPE_JAR:
- SetJsonValue(g, vp, val->GetArray()->GetValue(0), n);
- break;
- case TYPE_JOB:
- // if (!vp->IsTypeNum() || !Strict) {
- vp->SetValue_psz(val->GetObject()->GetText(g, NULL));
- break;
- // } // endif Type
+ break;
+ case TYPE_JAR:
+ SetJsonValue(g, vp, val->GetArray()->GetValue(0), n);
+ break;
+ case TYPE_JOB:
+ // if (!vp->IsTypeNum() || !Strict) {
+ vp->SetValue_psz(val->GetObject()->GetText(g, NULL));
+ break;
+ // } // endif Type
- default:
- vp->Reset();
- } // endswitch Type
+ default:
+ vp->Reset();
+ } // endswitch Type
} else {
vp->SetNull(true);
@@ -313,7 +339,7 @@ void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
/*********************************************************************************/
PJVAL JSNX::GetJson(PGLOBAL g)
{
- return GetValue(g, Row, 0);
+ return GetRowValue(g, Row, 0);
} // end of GetJson
/*********************************************************************************/
@@ -332,17 +358,16 @@ PVAL JSNX::GetColumnValue(PGLOBAL g, PJSON row, int i)
int n = Nod - 1;
PJVAL val = NULL;
- val = GetValue(g, row, i);
+ val = GetRowValue(g, row, i);
SetJsonValue(g, Value, val, n);
return Value;
} // end of GetColumnValue
/*********************************************************************************/
-/* GetValue: */
+/* GetRowValue: */
/*********************************************************************************/
-PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i, my_bool b)
+PJVAL JSNX::GetRowValue(PGLOBAL g, PJSON row, int i, my_bool b)
{
-//int n = Nod - 1;
my_bool expd = false;
PJAR arp;
PJVAL val = NULL;
@@ -353,11 +378,8 @@ PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i, my_bool b)
val = new(g) JVALUE(g, Value);
return val;
} else if (Nodes[i].Op == OP_XX) {
- if (b)
- return new(g)JVALUE(g, MakeJson(g, row));
- else
- return new(g)JVALUE(row);
-
+ Jb = b;
+ return new(g)JVALUE(row);
} else switch (row->GetType()) {
case TYPE_JOB:
if (!Nodes[i].Key) {
@@ -388,11 +410,11 @@ PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i, my_bool b)
else
return new(g) JVALUE(g, CalculateArray(g, arp, i));
- } else if (i < Nod-1) {
- strcpy(g->Message, "Unexpected array");
- val = NULL; // Not an expected array
- } else
+ } else {
+ // Unexpected array, unwrap it as [0]
val = arp->GetValue(0);
+ i--;
+ } // endif's
break;
case TYPE_JVAL:
@@ -404,13 +426,15 @@ PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i, my_bool b)
} // endswitch Type
if (i < Nod-1)
- row = (val) ? val->GetJson() : NULL;
+ if (!(row = (val) ? val->GetJsp() : NULL))
+ val = NULL;
+// row = (val) ? val->GetJson() : NULL;
} // endfor i
// SetJsonValue(g, Value, val, n);
return val;
-} // end of GetValue
+} // end of GetRowValue
/*********************************************************************************/
/* ExpandArray: */
@@ -503,6 +527,166 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
} // end of CalculateArray
/*********************************************************************************/
+/* CheckPath: Checks whether the path exists in the document. */
+/*********************************************************************************/
+my_bool JSNX::CheckPath(PGLOBAL g)
+{
+ PJVAL val;
+ PJSON row = Row;
+
+ for (int i = 0; i < Nod && row; i++) {
+ val = NULL;
+
+ if (Nodes[i].Op == OP_NUM || Nodes[i].Op == OP_XX) {
+ } else switch (row->GetType()) {
+ case TYPE_JOB:
+ if (Nodes[i].Key)
+ val = ((PJOB)row)->GetValue(Nodes[i].Key);
+
+ break;
+ case TYPE_JAR:
+ if (!Nodes[i].Key)
+ if (Nodes[i].Op == OP_EQ || Nodes[i].Op == OP_LE)
+ val = ((PJAR)row)->GetValue(Nodes[i].Rank);
+
+ break;
+ case TYPE_JVAL:
+ val = (PJVAL)row;
+ break;
+ default:
+ sprintf(g->Message, "Invalid row JSON type %d", row->GetType());
+ } // endswitch Type
+
+ if (i < Nod-1)
+ if (!(row = (val) ? val->GetJsp() : NULL))
+ val = NULL;
+
+ } // endfor i
+
+ return (val != NULL);
+} // end of CheckPath
+
+/***********************************************************************/
+/* GetRow: Set the complete path of the object to be set. */
+/***********************************************************************/
+PJSON JSNX::GetRow(PGLOBAL g)
+{
+ PJVAL val = NULL;
+ PJAR arp;
+ PJSON nwr, row = Row;
+
+ for (int i = 0; i < Nod - 1 && row; i++) {
+ if (Nodes[i].Op == OP_XX)
+ break;
+ else switch (row->GetType()) {
+ case TYPE_JOB:
+ if (!Nodes[i].Key)
+ // Expected Array was not there, wrap the value
+ continue;
+
+ 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
+ val = arp->GetValue(Nodes[i].Rx);
+
+ } else {
+ // Unexpected array, unwrap it as [0]
+ val = arp->GetValue(0);
+ i--;
+ } // 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
+
+/***********************************************************************/
+/* WriteValue: */
+/***********************************************************************/
+my_bool JSNX::WriteValue(PGLOBAL g, PJVAL jvalp)
+{
+ PJOB objp = NULL;
+ PJAR arp = NULL;
+ PJVAL jvp = NULL;
+ PJSON row = GetRow(g);
+
+ if (!row)
+ return true;
+
+ 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:
+ strcpy(g->Message, "Invalid target type");
+ return true;
+ } // endswitch Type
+
+ if (arp) {
+ if (!Nodes[Nod-1].Key) {
+ if (Nodes[Nod-1].Op == OP_EQ)
+ arp->SetValue(g, jvalp, Nodes[Nod-1].Rank);
+ else
+ arp->AddValue(g, jvalp);
+
+ arp->InitArray(g);
+ } // endif Key
+
+ } else if (objp) {
+ if (Nodes[Nod-1].Key)
+ objp->SetValue(g, jvalp, Nodes[Nod-1].Key);
+
+ } else if (jvp)
+ jvp->SetValue(jvalp);
+
+ return false;
+} // end of WriteValue
+
+/*********************************************************************************/
/* Locate a value in a JSON tree: */
/*********************************************************************************/
PSZ JSNX::Locate(PGLOBAL g, PJSON jsp, PJVAL jvp, int k)
@@ -802,15 +986,17 @@ my_bool JSNX::AddPath(void)
/* --------------------------------- JSON UDF ---------------------------------- */
-#define BMX (_MAX_PATH - 1)
+// BSON size should be equal on Linux and Windows
+#define BMX 255
typedef struct BSON *PBSON;
/*********************************************************************************/
/* Structure used to return binary json. */
/*********************************************************************************/
struct BSON {
- char Msg[_MAX_PATH];
+ char Msg[BMX + 1];
char *Filename;
+ PGLOBAL G;
int Pretty;
ulong Reslen;
my_bool Changed;
@@ -824,16 +1010,21 @@ struct BSON {
/*********************************************************************************/
static PBSON JbinAlloc(PGLOBAL g, UDF_ARGS *args, ulong len, PJSON jsp)
{
- PBSON bsp = (PBSON)PlugSubAlloc(g, NULL, sizeof(BSON));
+ PBSON bsp = (PBSON)PlgDBSubAlloc(g, NULL, sizeof(BSON));
+
+ if (bsp) {
+ strcpy(bsp->Msg, "Binary Json");
+ bsp->Msg[BMX] = 0;
+ bsp->Filename = NULL;
+ bsp->G = g;
+ bsp->Pretty = 2;
+ bsp->Reslen = len;
+ bsp->Changed = false;
+ bsp->Top = bsp->Jsp = jsp;
+ bsp->Bsp = (IsJson(args, 0) == 3) ? (PBSON)args->args[0] : NULL;
+ } else
+ PUSH_WARNING(g->Message);
- strcpy(bsp->Msg, "Binary Json");
- bsp->Msg[BMX] = 0;
- bsp->Filename = NULL;
- bsp->Pretty = 2;
- bsp->Reslen = len;
- bsp->Changed = false;
- bsp->Top = bsp->Jsp = jsp;
- bsp->Bsp = (IsJson(args, 0) == 3) ? (PBSON)args->args[0] : NULL;
return bsp;
} /* end of JbinAlloc */
@@ -942,8 +1133,7 @@ static char *MakeResult(PGLOBAL g, UDF_ARGS *args, PJSON top, uint n = 2)
if (IsJson(args, 0) == 2) {
// Make the change in the json file
- char *msg;
- int pretty = 2;
+ int pretty = 2;
for (uint i = n; i < args->arg_count; i++)
if (args->arg_type[i] == INT_RESULT) {
@@ -951,8 +1141,8 @@ static char *MakeResult(PGLOBAL g, UDF_ARGS *args, PJSON top, uint n = 2)
break;
} // endif type
- if ((msg = Serialize(g, top, MakePSZ(g, args, 0), pretty)))
- PUSH_WARNING(msg);
+ if (!Serialize(g, top, MakePSZ(g, args, 0), pretty))
+ PUSH_WARNING(g->Message);
str = NULL;
} else if (IsJson(args, 0) == 3) {
@@ -960,10 +1150,8 @@ static char *MakeResult(PGLOBAL g, UDF_ARGS *args, PJSON top, uint n = 2)
if (bsp->Filename) {
// Make the change in the json file
- char *msg;
-
- if ((msg = Serialize(g, top, bsp->Filename, bsp->Pretty)))
- PUSH_WARNING(msg);
+ if (!Serialize(g, top, bsp->Filename, bsp->Pretty))
+ PUSH_WARNING(g->Message);
str = bsp->Filename;
} else if (!(str = Serialize(g, top, NULL, 0)))
@@ -983,8 +1171,11 @@ static PBSON MakeBinResult(PGLOBAL g, UDF_ARGS *args, PJSON top, ulong len, int
{
PBSON bsnp = JbinAlloc(g, args, len, top);
+ if (!bsnp)
+ return NULL;
+
if (IsJson(args, 0) == 2) {
- int pretty = 2;
+ int pretty = 0;
for (uint i = n; i < args->arg_count; i++)
if (args->arg_type[i] == INT_RESULT) {
@@ -994,9 +1185,10 @@ static PBSON MakeBinResult(PGLOBAL g, UDF_ARGS *args, PJSON top, ulong len, int
bsnp->Pretty = pretty;
- if (bsnp->Filename = (char*)args->args[0])
- strncpy(bsnp->Msg, (char*)args->args[0], BMX);
- else
+ if (bsnp->Filename = (char*)args->args[0]) {
+ bsnp->Filename = MakePSZ(g, args, 0);
+ strncpy(bsnp->Msg, bsnp->Filename, BMX);
+ } else
strncpy(bsnp->Msg, "null filename", BMX);
} else if (IsJson(args, 0) == 3) {
@@ -1063,6 +1255,14 @@ static int IsJson(UDF_ARGS *args, uint i)
} // end of IsJson
/*********************************************************************************/
+/* GetMemPtr: returns the memory pointer used by this argument. */
+/*********************************************************************************/
+static PGLOBAL GetMemPtr(PGLOBAL g, UDF_ARGS *args, uint i)
+{
+ return (IsJson(args, i) == 3) ? ((PBSON)args->args[i])->G : g;
+} // end of GetMemPtr
+
+/*********************************************************************************/
/* GetFileLength: returns file size in number of bytes. */
/*********************************************************************************/
static long GetFileLength(char *fn)
@@ -1161,8 +1361,8 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
} else
memlen += sizeof(JARRAY);
- switch (args->arg_type[i]) {
- case STRING_RESULT:
+ switch (args->arg_type[i]) {
+ case STRING_RESULT:
if (n == 2 && args->args[i]) {
if ((signed)i != j) {
m = MY_MIN(args->lengths[i], sizeof(fn) - 1);
@@ -1173,11 +1373,14 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
} // endif i
memlen += fl * M;
- } else if (IsJson(args, i) == 3)
- memlen += sizeof(JVALUE);
- else if (IsJson(args, i) == 1)
+ } else if (n == 1) {
+ if (i == 0)
+ memlen += sizeof(BSON); // For Jbin functions
+
memlen += args->lengths[i] * M; // Estimate parse memory
-
+ } else if (n == 3)
+ memlen += sizeof(JVALUE);
+
memlen += sizeof(TYPVAL<PSZ>);
break;
case INT_RESULT:
@@ -1202,18 +1405,32 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
/*********************************************************************************/
/* Check if the calculated memory is enough. */
/*********************************************************************************/
-static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args,
- uint n, my_bool obj, my_bool mod = false)
+static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args, uint n,
+ my_bool m, my_bool obj = false, my_bool mod = false)
{
unsigned long rl, ml;
+ my_bool b = false;
- n = MY_MIN(n, args->arg_count);
+ n = MY_MIN(n, args->arg_count);
for (uint i = 0; i < n; i++)
- if (IsJson(args, i) == 2) {
+ if (IsJson(args, i) == 2 ||
+ (b = (m && !i && args->arg_type[0] == STRING_RESULT && !IsJson(args, 0)))) {
if (CalcLen(args, obj, rl, ml, mod))
return true;
- else if (ml > g->Sarea_Size) {
+ else if (b) {
+ ulong len;
+ char *p = args->args[0];
+
+ // Is this a file name?
+ if (!strchr("[{ \t\r\n", *p) && (len = GetFileLength(p)))
+ ml += len * (M + 1);
+ else
+ ml += args->lengths[0] * M;
+
+ } // endif b
+
+ if (ml > g->Sarea_Size) {
free(g->Sarea);
if (!(g->Sarea = PlugAllocMem(g, ml))) {
@@ -1588,7 +1805,7 @@ char *json_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result,
PGLOBAL g = (PGLOBAL)initid->ptr;
if (!g->Xchk) {
- if (!CheckMemory(g, initid, args, args->arg_count, false)) {
+ if (!CheckMemory(g, initid, args, args->arg_count, true)) {
char *p;
PJSON top;
PJAR arp;
@@ -1672,7 +1889,7 @@ char *json_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
goto fin;
} // endif Xchk
- if (!CheckMemory(g, initid, args, 2, false, true)) {
+ if (!CheckMemory(g, initid, args, 2, false, false, true)) {
int *x;
uint n = 2;
PJSON jsp, top;
@@ -1686,9 +1903,11 @@ char *json_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (CheckPath(g, args, jsp, jvp, 2))
PUSH_WARNING(g->Message);
else if (jvp && jvp->GetValType() == TYPE_JAR) {
+ PGLOBAL gb = GetMemPtr(g, args, 0);
+
arp = jvp->GetArray();
- arp->AddValue(g, MakeValue(g, args, 1), x);
- arp->InitArray(g);
+ arp->AddValue(gb, MakeValue(gb, args, 1), x);
+ arp->InitArray(gb);
str = MakeResult(g, args, top, n);
} else {
PUSH_WARNING("First argument target is not an array");
@@ -1705,10 +1924,11 @@ char *json_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = str;
-fin:
+ fin:
if (!str) {
*res_length = 0;
*is_null = 1;
+ *error = 1;
} else
*res_length = strlen(str);
@@ -1740,7 +1960,7 @@ my_bool json_array_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of json_array_delete_init
char *json_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
char *str = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -1748,11 +1968,10 @@ char *json_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (g->Xchk) {
// This constant function was recalled
str = (char*)g->Xchk;
- *res_length = strlen(str);
- return str;
+ goto fin;
} // endif Xchk
- if (!CheckMemory(g, initid, args, 1, false, true)) {
+ if (!CheckMemory(g, initid, args, 1, false, false, true)) {
int *x;
uint n = 1;
PJSON top;
@@ -1766,7 +1985,7 @@ char *json_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
else if (jvp && jvp->GetValType() == TYPE_JAR) {
arp = jvp->GetArray();
arp->DeleteValue(*x);
- arp->InitArray(g);
+ arp->InitArray(GetMemPtr(g, args, 0));
str = MakeResult(g, args, top, n);
} else {
PUSH_WARNING("First argument target is not an array");
@@ -1783,7 +2002,14 @@ char *json_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = str;
- *res_length = (str) ? strlen(str) : 0;
+ fin:
+ if (!str) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = strlen(str);
+
return str;
} // end of json_array_delete
@@ -1793,7 +2019,7 @@ void json_array_delete_deinit(UDF_INIT* initid)
} // end of json_array_delete_deinit
/*********************************************************************************/
-/* Make a Json Oject containing all the parameters. */
+/* Make a Json Object containing all the parameters. */
/*********************************************************************************/
my_bool json_object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
@@ -1810,7 +2036,7 @@ char *json_object(UDF_INIT *initid, UDF_ARGS *args, char *result,
PGLOBAL g = (PGLOBAL)initid->ptr;
if (!g->Xchk) {
- if (!CheckMemory(g, initid, args, args->arg_count, true)) {
+ if (!CheckMemory(g, initid, args, args->arg_count, false, false, true)) {
PJOB objp = new(g)JOBJECT;
for (uint i = 0; i < args->arg_count; i++)
@@ -1837,7 +2063,7 @@ void json_object_deinit(UDF_INIT* initid)
} // end of json_object_deinit
/*********************************************************************************/
-/* Make a Json Oject containing all not null parameters. */
+/* Make a Json Object containing all not null parameters. */
/*********************************************************************************/
my_bool json_object_nonull_init(UDF_INIT *initid, UDF_ARGS *args,
char *message)
@@ -1855,7 +2081,7 @@ char *json_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
PGLOBAL g = (PGLOBAL)initid->ptr;
if (!g->Xchk) {
- if (!CheckMemory(g, initid, args, args->arg_count, true)) {
+ if (!CheckMemory(g, initid, args, args->arg_count, false, true)) {
PJVAL jvp;
PJOB objp = new(g)JOBJECT;
@@ -1884,6 +2110,55 @@ void json_object_nonull_deinit(UDF_INIT* initid)
} // end of json_object_nonull_deinit
/*********************************************************************************/
+/* Make a Json Object containing all the key/value parameters. */
+/*********************************************************************************/
+my_bool json_object_key_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ if (args->arg_count % 2) {
+ strcpy(message, "This function must have an even number of arguments");
+ return true;
+ } // endif arg_count
+
+ CalcLen(args, true, reslen, memlen);
+ return JsonInit(initid, args, message, false, reslen, memlen);
+} // end of json_object_key_init
+
+char *json_object_key(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *, char *)
+{
+ char *str = NULL;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ if (!g->Xchk) {
+ if (!CheckMemory(g, initid, args, args->arg_count, false, true)) {
+ PJOB objp = new(g)JOBJECT;
+
+ for (uint i = 0; i < args->arg_count; i += 2)
+ objp->SetValue(g, MakeValue(g, args, i+1), MakePSZ(g, args, i));
+
+ str = Serialize(g, objp, NULL, 0);
+ } // endif CheckMemory
+
+ if (!str)
+ str = strcpy(result, g->Message);
+
+ // Keep result of constant function
+ g->Xchk = (initid->const_item) ? str : NULL;
+ } else
+ str = (char*)g->Xchk;
+
+ *res_length = strlen(str);
+ return str;
+} // end of json_object_key
+
+void json_object_key_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of json_object_key_deinit
+
+/*********************************************************************************/
/* Add or replace a value in a Json Object. */
/*********************************************************************************/
my_bool json_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
@@ -1897,13 +2172,13 @@ my_bool json_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
strcpy(message, "First argument must be a json item");
return true;
} else
- CalcLen(args, false, reslen, memlen, true);
+ CalcLen(args, true, reslen, memlen, true);
return JsonInit(initid, args, message, true, reslen, memlen);
} // end of json_object_add_init
char *json_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
char *key, *str = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -1911,14 +2186,14 @@ char *json_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (g->Xchk) {
// This constant function was recalled
str = (char*)g->Xchk;
- *res_length = strlen(str);
- return str;
+ goto fin;
} // endif Xchk
- if (!CheckMemory(g, initid, args, 2, false, true)) {
- PJOB jobp;
- PJVAL jvp;
- PJSON jsp, top;
+ if (!CheckMemory(g, initid, args, 2, false, true, true)) {
+ PJOB jobp;
+ PJVAL jvp;
+ PJSON jsp, top;
+ PGLOBAL gb = GetMemPtr(g, args, 0);
jvp = MakeValue(g, args, 0, &top);
jsp = jvp->GetJson();
@@ -1927,9 +2202,9 @@ char *json_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
PUSH_WARNING(g->Message);
else if (jvp && jvp->GetValType() == TYPE_JOB) {
jobp = jvp->GetObject();
- jvp = MakeValue(g, args, 1);
- key = MakeKey(g, args, 1);
- jobp->SetValue(g, jvp, key);
+ jvp = MakeValue(gb, args, 1);
+ key = MakeKey(gb, args, 1);
+ jobp->SetValue(gb, jvp, key);
str = MakeResult(g, args, top);
} else {
PUSH_WARNING("First argument target is not an object");
@@ -1946,7 +2221,14 @@ char *json_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = str;
- *res_length = strlen(str);
+ fin:
+ if (!str) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = strlen(str);
+
return str;
} // end of json_object_add
@@ -1972,13 +2254,13 @@ my_bool json_object_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
strcpy(message, "Second argument must be a key string");
return true;
} else
- CalcLen(args, false, reslen, memlen, true);
+ CalcLen(args, true, reslen, memlen, true);
return JsonInit(initid, args, message, true, reslen, memlen);
} // end of json_object_delete_init
char *json_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
char *str = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -1986,11 +2268,10 @@ char *json_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (g->Xchk) {
// This constant function was recalled
str = (char*)g->Xchk;
- *res_length = strlen(str);
- return str;
+ goto fin;
} // endif Xchk
- if (!CheckMemory(g, initid, args, 1, false, true)) {
+ if (!CheckMemory(g, initid, args, 1, false, true, true)) {
char *key;
PJOB jobp;
PJSON jsp, top;
@@ -2001,7 +2282,7 @@ char *json_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (CheckPath(g, args, jsp, jvp, 2))
PUSH_WARNING(g->Message);
else if (jvp && jvp->GetValType() == TYPE_JOB) {
- key = MakeKey(g, args, 1);
+ key = MakeKey(GetMemPtr(g, args, 0), args, 1);
jobp = jvp->GetObject();
jobp->DeleteKey(key);
str = MakeResult(g, args, top);
@@ -2020,7 +2301,14 @@ char *json_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = str;
- *res_length = strlen(str);
+ fin:
+ if (!str) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = strlen(str);
+
return str;
} // end of json_object_delete
@@ -2055,7 +2343,7 @@ char *json_object_list(UDF_INIT *initid, UDF_ARGS *args, char *result,
PGLOBAL g = (PGLOBAL)initid->ptr;
if (!g->N) {
- if (!CheckMemory(g, initid, args, 1, false)) {
+ if (!CheckMemory(g, initid, args, 1, true, true)) {
char *p;
PJSON jsp;
PJVAL jvp = MakeValue(g, args, 0);
@@ -2186,7 +2474,7 @@ my_bool json_object_grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
unsigned long reslen, memlen, n = GetJsonGrpSize();
if (args->arg_count != 2) {
- strcpy(message, "This function requires 2 arguments (value, key)");
+ strcpy(message, "This function requires 2 arguments (key, value)");
return true;
} else if (IsJson(args, 0) == 3) {
strcpy(message, "This function does not support Jbin arguments");
@@ -2214,8 +2502,7 @@ void json_object_grp_add(UDF_INIT *initid, UDF_ARGS *args, char*, char*)
PJOB objp = (PJOB)g->Activityp;
if (g->N-- > 0)
- objp->SetValue(g, MakeValue(g, args, 0),
- (args->arg_count == 1) ? MakeKey(g, args, 0) : MakePSZ(g, args, 1));
+ objp->SetValue(g, MakeValue(g, args, 1), MakePSZ(g, args, 0));
} // end of json_object_grp_add
@@ -2273,7 +2560,7 @@ my_bool json_item_merge_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of json_item_merge_init
char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
char *str = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -2281,11 +2568,10 @@ char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (g->Xchk) {
// This constant function was recalled
str = (char*)g->Xchk;
- *res_length = strlen(str);
- return str;
+ goto fin;
} // endif Xchk
- if (!CheckMemory(g, initid, args, 2, false, true)) {
+ if (!CheckMemory(g, initid, args, 2, false, false, true)) {
PJSON top;
PJVAL jvp;
PJSON jsp[2] = {NULL, NULL};
@@ -2303,8 +2589,8 @@ char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endfor i
if (jsp[0]) {
- if (jsp[0]->Merge(g, jsp[1]))
- PUSH_WARNING(g->Message);
+ if (jsp[0]->Merge(GetMemPtr(g, args, 0), jsp[1]))
+ PUSH_WARNING(GetMemPtr(g, args, 0)->Message);
else
str = MakeResult(g, args, top);
@@ -2320,7 +2606,14 @@ char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = str;
- *res_length = strlen(str);
+ fin:
+ if (!str) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = strlen(str);
+
return str;
} // end of json_item_merge
@@ -2349,7 +2642,7 @@ my_bool json_get_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} else
CalcLen(args, false, reslen, memlen);
- if (n == 2) {
+ if (n == 2 && args->args[0]) {
char fn[_MAX_PATH];
long fl;
@@ -2366,7 +2659,10 @@ my_bool json_get_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
char *json_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *)
{
- char *str = NULL;
+ char *p, *path, *str = NULL;
+ PJSON jsp;
+ PJVAL jvp;
+ PJSNX jsx;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
@@ -2375,51 +2671,47 @@ char *json_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p, *path;
- PJSON jsp;
- PJSNX jsx;
- PJVAL jvp;
-
- if (!g->Xchk) {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true, true)) {
+ PUSH_WARNING("CheckMemory error");
+ goto fin;
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- return NULL;
- } // endif jsp
-
- } else
- jsp = jvp->GetJson();
-
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ return NULL;
+ } // endif jsp
} else
- jsp = (PJSON)g->Xchk;
+ jsp = jvp->GetJson();
+
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- path = MakePSZ(g, args, 1);
- jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
+ } else
+ jsp = (PJSON)g->Xchk;
- if (jsx->SetJpath(g, path, true)) {
- PUSH_WARNING(g->Message);
- *is_null = 1;
- return NULL;
- } // endif SetJpath
+ path = MakePSZ(g, args, 1);
+ jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
- jsx->ReadValue(g);
+ if (jsx->SetJpath(g, path, true)) {
+ PUSH_WARNING(g->Message);
+ *is_null = 1;
+ return NULL;
+ } // endif SetJpath
- if (!jsx->GetValue()->IsNull())
- str = jsx->GetValue()->GetCharValue();
+ jsx->ReadValue(g);
- if (initid->const_item)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)str;
+ if (!jsx->GetValue()->IsNull())
+ str = jsx->GetValue()->GetCharValue();
- } // endif CheckMemory
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)str;
fin:
if (!str) {
@@ -2464,7 +2756,7 @@ my_bool jsonget_string_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
CalcLen(args, false, reslen, memlen);
memlen += more;
- if (n == 2) {
+ if (n == 2 && args->args[0]) {
char fn[_MAX_PATH];
long fl;
@@ -2481,8 +2773,11 @@ my_bool jsonget_string_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
char *jsonget_string(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *)
{
+ char *p, *path, *str = NULL;
int rc;
- char *str = NULL;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
@@ -2491,67 +2786,64 @@ char *jsonget_string(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p, *path;
- PJSON jsp;
- PJSNX jsx;
- PJVAL jvp;
+ // Save stack and allocation environment and prepare error return
+ if (g->jump_level == MAX_JUMP) {
+ PUSH_WARNING(MSG(TOO_MANY_JUMPS));
+ *is_null = 1;
+ return NULL;
+ } // endif jump_level
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- PUSH_WARNING(MSG(TOO_MANY_JUMPS));
- *is_null = 1;
- return NULL;
- } // endif jump_level
+ if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
+ PUSH_WARNING(g->Message);
+ str = NULL;
+ goto err;
+ } // endif rc
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- PUSH_WARNING(g->Message);
- str = NULL;
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
goto err;
- } // endif rc
-
- if (!g->Xchk) {
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- goto err;
- } // endif jsp
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif jsp
- } else
- jsp = jvp->GetJson();
+ } else
+ jsp = jvp->GetJson();
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- } else
- jsp = (PJSON)g->Xchk;
+ } else
+ jsp = (PJSON)g->Xchk;
- path = MakePSZ(g, args, 1);
- jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
+ path = MakePSZ(g, args, 1);
+ jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
- if (jsx->SetJpath(g, path)) {
- PUSH_WARNING(g->Message);
- goto err;
- } // endif SetJpath
+ if (jsx->SetJpath(g, path)) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif SetJpath
- jsx->ReadValue(g);
+ jsx->ReadValue(g);
- if (!jsx->GetValue()->IsNull())
- str = jsx->GetValue()->GetCharValue();
+ if (!jsx->GetValue()->IsNull())
+ str = jsx->GetValue()->GetCharValue();
- if (initid->const_item)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)str;
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)str;
- err:
- g->jump_level--;
- } // endif CheckMemory
+ err:
+ g->jump_level--;
-fin:
+ fin:
if (!str) {
*is_null = 1;
*res_length = 0;
@@ -2594,6 +2886,11 @@ my_bool jsonget_int_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
long long jsonget_int(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error)
{
+ char *p, *path;
+ long long n;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
@@ -2606,67 +2903,60 @@ long long jsonget_int(UDF_INIT *initid, UDF_ARGS *args,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p, *path;
- long long n;
- PJSON jsp;
- PJSNX jsx;
- PJVAL jvp;
-
- if (!g->Xchk) {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
+ if (g->Mrr) *error = 1;
+ *is_null = 1;
+ return 0LL;
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- if (g->Mrr) *error = 1;
- *is_null = 1;
- return 0;
- } // endif jsp
-
- } else
- jsp = jvp->GetJson();
-
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ if (g->Mrr) *error = 1;
+ *is_null = 1;
+ return 0;
+ } // endif jsp
} else
- jsp = (PJSON)g->Xchk;
+ jsp = jvp->GetJson();
- path = MakePSZ(g, args, 1);
- jsx = new(g) JSNX(g, jsp, TYPE_BIGINT);
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- if (jsx->SetJpath(g, path)) {
- PUSH_WARNING(g->Message);
- *is_null = 1;
- return 0;
- } // endif SetJpath
+ } else
+ jsp = (PJSON)g->Xchk;
- jsx->ReadValue(g);
+ path = MakePSZ(g, args, 1);
+ jsx = new(g) JSNX(g, jsp, TYPE_BIGINT);
- if (jsx->GetValue()->IsNull()) {
- PUSH_WARNING("Value not found");
- *is_null = 1;
- return 0;
- } // endif IsNull
+ if (jsx->SetJpath(g, path)) {
+ PUSH_WARNING(g->Message);
+ *is_null = 1;
+ return 0;
+ } // endif SetJpath
- n = jsx->GetValue()->GetBigintValue();
+ jsx->ReadValue(g);
- if (initid->const_item) {
- // Keep result of constant function
- long long *np = (long long*)PlugSubAlloc(g, NULL, sizeof(long long));
- *np = n;
- g->Activityp = (PACTIVITY)np;
- } // endif const_item
+ if (jsx->GetValue()->IsNull()) {
+ *is_null = 1;
+ return 0;
+ } // endif IsNull
- return n;
- } // endif CheckMemory
+ n = jsx->GetValue()->GetBigintValue();
- if (g->Mrr) *error = 1;
- *is_null = 1;
- return 0LL;
+ if (initid->const_item) {
+ // Keep result of constant function
+ long long *np = (long long*)PlugSubAlloc(g, NULL, sizeof(long long));
+ *np = n;
+ g->Activityp = (PACTIVITY)np;
+ } // endif const_item
+
+ return n;
} // end of jsonget_int
void jsonget_int_deinit(UDF_INIT* initid)
@@ -2711,6 +3001,11 @@ my_bool jsonget_real_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
double jsonget_real(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error)
{
+ char *p, *path;
+ double d;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
@@ -2723,66 +3018,59 @@ double jsonget_real(UDF_INIT *initid, UDF_ARGS *args,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p, *path;
- double d;
- PJSON jsp;
- PJSNX jsx;
- PJVAL jvp;
-
- if (!g->Xchk) {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
+ if (g->Mrr) *error = 1;
+ *is_null = 1;
+ return 0.0;
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- *is_null = 1;
- return 0.0;
- } // endif jsp
-
- } else
- jsp = jvp->GetJson();
-
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ *is_null = 1;
+ return 0.0;
+ } // endif jsp
} else
- jsp = (PJSON)g->Xchk;
+ jsp = jvp->GetJson();
- path = MakePSZ(g, args, 1);
- jsx = new(g) JSNX(g, jsp, TYPE_DOUBLE);
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- if (jsx->SetJpath(g, path)) {
- PUSH_WARNING(g->Message);
- *is_null = 1;
- return 0.0;
- } // endif SetJpath
+ } else
+ jsp = (PJSON)g->Xchk;
- jsx->ReadValue(g);
+ path = MakePSZ(g, args, 1);
+ jsx = new(g) JSNX(g, jsp, TYPE_DOUBLE);
- if (jsx->GetValue()->IsNull()) {
- PUSH_WARNING("Value not found");
- *is_null = 1;
- return 0.0;
- } // endif IsNull
+ if (jsx->SetJpath(g, path)) {
+ PUSH_WARNING(g->Message);
+ *is_null = 1;
+ return 0.0;
+ } // endif SetJpath
- d = jsx->GetValue()->GetFloatValue();
+ jsx->ReadValue(g);
- if (initid->const_item) {
- // Keep result of constant function
- double *dp = (double*)PlugSubAlloc(g, NULL, sizeof(double));
- *dp = d;
- g->Activityp = (PACTIVITY)dp;
- } // endif const_item
+ if (jsx->GetValue()->IsNull()) {
+ *is_null = 1;
+ return 0.0;
+ } // endif IsNull
- return d;
- } // endif CheckMemory
+ d = jsx->GetValue()->GetFloatValue();
- if (g->Mrr) *error = 1;
- *is_null = 1;
- return 0.0;
+ if (initid->const_item) {
+ // Keep result of constant function
+ double *dp = (double*)PlugSubAlloc(g, NULL, sizeof(double));
+ *dp = d;
+ g->Activityp = (PACTIVITY)dp;
+ } // endif const_item
+
+ return d;
} // end of jsonget_real
void jsonget_real_deinit(UDF_INIT* initid)
@@ -2824,7 +3112,11 @@ my_bool jsonlocate_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
char *jsonlocate(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *error)
{
- char *path = NULL;
+ char *p, *path = NULL;
+ int k, rc;
+ PJVAL jvp, jvp2;
+ PJSON jsp;
+ PJSNX jsx;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
@@ -2841,75 +3133,68 @@ char *jsonlocate(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p;
- int k, rc;
- 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
- // 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 ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- PUSH_WARNING(g->Message);
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, !g->Xchk)) {
+ PUSH_WARNING("CheckMemory error");
*error = 1;
- path = NULL;
goto err;
- } // endif rc
-
- if (!g->Xchk) {
+ } else
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
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif jsp
} else
- jsp = (PJSON)g->Xchk;
+ jsp = jvp->GetJson();
- // The item to locate
- jvp2 = MakeValue(g, args, 1);
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- k = (args->arg_count > 2) ? (int)*(long long*)args->args[2] : 1;
+ } else
+ jsp = (PJSON)g->Xchk;
- jsx = new(g) JSNX(g, jsp, TYPE_STRING);
- path = jsx->Locate(g, jsp, jvp2, k);
+ // The item to locate
+ jvp2 = MakeValue(g, args, 1);
- if (initid->const_item)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)path;
+ k = (args->arg_count > 2) ? (int)*(long long*)args->args[2] : 1;
- err:
- g->jump_level--;
+ jsx = new(g) JSNX(g, jsp, TYPE_STRING);
+ path = jsx->Locate(g, jsp, jvp2, k);
- if (!path) {
- *res_length = 0;
- *is_null = 1;
- } else
- *res_length = strlen(path);
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)path;
- return path;
- } // endif CheckMemory
+ err:
+ g->jump_level--;
- *error = 1;
- *is_null = 1;
- return NULL;
+ if (!path) {
+ *res_length = 0;
+ *is_null = 1;
+ } else
+ *res_length = strlen(path);
+
+ return path;
} // end of jsonlocate
void jsonlocate_deinit(UDF_INIT* initid)
@@ -2951,7 +3236,11 @@ my_bool json_locate_all_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
char *json_locate_all(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *error)
{
- char *path = NULL;
+ char *p, *path = NULL;
+ int rc, mx = 10;
+ PJVAL jvp, jvp2;
+ PJSON jsp;
+ PJSNX jsx;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
@@ -2969,82 +3258,416 @@ char *json_locate_all(UDF_INIT *initid, UDF_ARGS *args, char *result,
} 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
- // 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 ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- PUSH_WARNING(g->Message);
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
*error = 1;
- path = NULL;
goto err;
- } // endif rc
-
- if (!g->Xchk) {
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- goto err;
- } // endif jsp
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif jsp
- } else
- jsp = jvp->GetJson();
+ } else
+ jsp = jvp->GetJson();
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- } else
- jsp = (PJSON)g->Xchk;
+ } else
+ jsp = (PJSON)g->Xchk;
- // The item to locate
- jvp2 = MakeValue(g, args, 1);
+ // The item to locate
+ jvp2 = MakeValue(g, args, 1);
- if (args->arg_count > 2)
- mx = (int)*(long long*)args->args[2];
+ 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);
+ 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->Activityp = (PACTIVITY)path;
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)path;
- err:
- g->jump_level--;
+ err:
+ g->jump_level--;
- if (!path) {
- *res_length = 0;
+ if (!path) {
+ *res_length = 0;
+ *is_null = 1;
+ } else
+ *res_length = strlen(path);
+
+ return path;
+} // end of json_locate_all
+
+void json_locate_all_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of json_locate_all_deinit
+
+/*********************************************************************************/
+/* Check whether the document contains a value or item. */
+/*********************************************************************************/
+my_bool jsoncontains_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen, more = 1024;
+ int n = IsJson(args, 0);
+
+ if (args->arg_count < 2) {
+ strcpy(message, "At least 2 arguments required");
+ return true;
+ } else if (!n && args->arg_type[0] != STRING_RESULT) {
+ strcpy(message, "First argument must be a json item");
+ return true;
+ } else if (args->arg_count > 2 && args->arg_type[2] != INT_RESULT) {
+ strcpy(message, "Third argument is not an integer (index)");
+ return true;
+ } else if (args->arg_count > 3) {
+ if (args->arg_type[3] == INT_RESULT && args->args[3])
+ more += (unsigned long)*(long long*)args->args[3];
+ else
+ strcpy(message, "Fourth argument is not an integer (memory)");
+
+ } // endif's
+
+ CalcLen(args, false, reslen, memlen);
+ memlen += more;
+
+ if (IsJson(args, 0) != 3)
+ memlen += 1000; // TODO: calculate this
+
+ return JsonInit(initid, args, message, false, reslen, memlen);
+} // end of jsoncontains_init
+
+long long jsoncontains(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *p, res[256];
+ long long n;
+ unsigned long reslen;
+
+ *is_null = 0;
+ p = jsonlocate(initid, args, res, &reslen, is_null, error);
+ n = (*is_null) ? 0LL : 1LL;
+ return n;
+} // end of jsoncontains
+
+void jsoncontains_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of jsoncontains_deinit
+
+/*********************************************************************************/
+/* Check whether the document contains a path. */
+/*********************************************************************************/
+my_bool jsoncontains_path_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen, more = 1024;
+ int n = IsJson(args, 0);
+
+ if (args->arg_count < 2) {
+ strcpy(message, "At least 2 arguments required");
+ return true;
+ } else if (!n && args->arg_type[0] != STRING_RESULT) {
+ strcpy(message, "First argument must be a json item");
+ return true;
+ } else if (args->arg_type[1] != STRING_RESULT) {
+ strcpy(message, "Second argument is not a string (path)");
+ return true;
+ } else if (args->arg_count > 2) {
+ if (args->arg_type[2] == INT_RESULT && args->args[2])
+ more += (unsigned long)*(long long*)args->args[2];
+ else
+ strcpy(message, "Third argument is not an integer (memory)");
+
+ } // endif's
+
+ CalcLen(args, false, reslen, memlen);
+ memlen += more;
+
+ if (IsJson(args, 0) != 3)
+ memlen += 1000; // TODO: calculate this
+
+ return JsonInit(initid, args, message, true, reslen, memlen);
+} // end of jsoncontains_path_init
+
+long long jsoncontains_path(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *p, *path;
+ long long n;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ if (g->N) {
+ if (!g->Activityp) {
*is_null = 1;
+ return 0LL;
} else
- *res_length = strlen(path);
+ return *(long long*)g->Activityp;
- return path;
- } // endif CheckMemory
+ } else if (initid->const_item)
+ g->N = 1;
+
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
+ goto err;
+ } else
+ jvp = MakeValue(g, args, 0);
- *error = 1;
+ 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;
+
+ path = MakePSZ(g, args, 1);
+ jsx = new(g)JSNX(g, jsp, TYPE_BIGINT);
+
+ if (jsx->SetJpath(g, path)) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif SetJpath
+
+ n = (jsx->CheckPath(g)) ? 1LL : 0LL;
+
+ if (initid->const_item) {
+ // Keep result of constant function
+ long long *np = (long long*)PlugSubAlloc(g, NULL, sizeof(long long));
+ *np = n;
+ g->Activityp = (PACTIVITY)np;
+ } // endif const_item
+
+ return n;
+
+ err:
+ if (g->Mrr) *error = 1;
*is_null = 1;
- return NULL;
-} // end of json_locate_all
+ return 0LL;
+} // end of jsoncontains_path
-void json_locate_all_deinit(UDF_INIT* initid)
+void jsoncontains_path_deinit(UDF_INIT* initid)
{
JsonFreeMem((PGLOBAL)initid->ptr);
-} // end of json_locate_all_deinit
+} // end of jsoncontains_path_deinit
+
+/*********************************************************************************/
+/* Set Json items of a Json document according to path. */
+/*********************************************************************************/
+my_bool json_set_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+ int n = IsJson(args, 0);
+
+ if (!(args->arg_count % 2)) {
+ strcpy(message, "This function must have an odd number of arguments");
+ return true;
+ } else if (!n && args->arg_type[0] != STRING_RESULT) {
+ strcpy(message, "First argument must be a json item");
+ return true;
+ } else
+ CalcLen(args, false, reslen, memlen);
+
+ if (n == 2 && args->args[0]) {
+ char fn[_MAX_PATH];
+ long fl;
+
+ memcpy(fn, args->args[0], args->lengths[0]);
+ fn[args->lengths[0]] = 0;
+ fl = GetFileLength(fn);
+ memlen += fl * 3;
+ } else if (n != 3)
+ memlen += args->lengths[0] * 3;
+
+ return JsonInit(initid, args, message, true, reslen, memlen);
+} // end of json_set_item_init
+
+char *json_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *p, *path, *str = NULL;
+ int w, rc;
+ my_bool b = true;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PGLOBAL gb = GetMemPtr(g, args, 0);
+
+ if (g->N) {
+ str = (char*)g->Activityp;
+ goto fin;
+ } else if (initid->const_item)
+ g->N = 1;
+
+ if (!strcmp(result, "$insert"))
+ w = 1;
+ else if (!strcmp(result, "$update"))
+ w = 2;
+ else
+ w = 0;
+
+ // Save stack and allocation environment and prepare error return
+ if (g->jump_level == MAX_JUMP) {
+ PUSH_WARNING(MSG(TOO_MANY_JUMPS));
+ *error = 1;
+ goto fin;
+ } // endif jump_level
+
+ if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
+ PUSH_WARNING(g->Message);
+ str = NULL;
+ goto err;
+ } // endif rc
+
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true, false, true)) {
+ PUSH_WARNING("CheckMemory error");
+ goto err;
+ } else
+ 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;
+
+ jsx = new(g)JSNX(g, jsp, TYPE_STRING, initid->max_length, 0, true);
+
+ for (uint i = 1; i+1 < args->arg_count; i += 2) {
+ jvp = MakeValue(gb, args, i);
+ path = MakePSZ(g, args, i+1);
+
+ if (jsx->SetJpath(g, path, false)) {
+ PUSH_WARNING(g->Message);
+ continue;
+ } // endif SetJpath
+
+ if (w) {
+ jsx->ReadValue(g);
+ b = jsx->GetValue()->IsNull();
+ b = (w == 1) ? b : !b;
+ } // endif w
+
+ if (b && jsx->WriteValue(gb, jvp))
+ PUSH_WARNING(g->Message);
+
+ } // endfor i
+
+ // In case of error or file, return unchanged argument
+ if (!(str = MakeResult(g, args, jsp, INT_MAX32)))
+ str = MakePSZ(g, args, 0);
+
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)str;
+
+ err:
+ g->jump_level--;
+
+ fin:
+ if (!str) {
+ *is_null = 1;
+ *res_length = 0;
+ } else
+ *res_length = strlen(str);
+
+ return str;
+} // end of json_set_item
+
+void json_set_item_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of json_set_item_deinit
+
+/*********************************************************************************/
+/* Insert Json items of a Json document according to path. */
+/*********************************************************************************/
+my_bool json_insert_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ return json_set_item_init(initid, args, message);
+} // end of json_insert_item_init
+
+char *json_insert_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *p)
+{
+ strcpy(result, "$insert");
+ return json_set_item(initid, args, result, res_length, is_null, p);
+} // end of json_insert_item
+
+void json_insert_item_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of json_insert_item_deinit
+
+/*********************************************************************************/
+/* Update Json items of a Json document according to path. */
+/*********************************************************************************/
+my_bool json_update_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ return json_set_item_init(initid, args, message);
+} // end of json_update_item_init
+
+char *json_update_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *p)
+{
+ strcpy(result, "$update");
+ return json_set_item(initid, args, result, res_length, is_null, p);
+} // end of json_update_item
+
+void json_update_item_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of json_update_item_deinit
/*********************************************************************************/
/* Returns a json file as a json string. */
@@ -3085,7 +3708,7 @@ my_bool json_file_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
more += fl * M;
memlen += more;
- return JsonInit(initid, args, message, false, reslen, memlen);
+ return JsonInit(initid, args, message, true, reslen, memlen);
} // end of json_file_init
char *json_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
@@ -3140,13 +3763,14 @@ char *json_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
PUSH_WARNING(g->Message);
} else
- str = GetJsonFile(g, fn);
+ if (!(str = GetJsonFile(g, fn)))
+ PUSH_WARNING(g->Message);
if (initid->const_item)
// Keep result of constant function
g->Xchk = str;
-fin:
+ fin:
if (!str) {
*res_length = 0;
*is_null = 1;
@@ -3183,7 +3807,7 @@ my_bool jfile_make_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
char *jfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *)
{
- char *p, *str, *msg, *fn = NULL;
+ char *p, *str = NULL, *fn = NULL;
int n, pretty = 2;
PJSON jsp;
PJVAL jvp;
@@ -3195,8 +3819,6 @@ char *jfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- PlugSubSet(g, g->Sarea, g->Sarea_Size);
-
if ((n = IsJson(args, 0)) == 3) {
// Get default file name and pretty
PBSON bsp = (PBSON)args->args[0];
@@ -3207,14 +3829,18 @@ char *jfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result,
fn = args->args[0];
if (!g->Xchk) {
- jvp = MakeValue(g, args, 0);
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
+ goto fin;
+ } else
+ jvp = MakeValue(g, args, 0);
if ((p = jvp->GetString())) {
if (!strchr("[{ \t\r\n", *p)) {
// Is this a file name?
if (!(p = GetJsonFile(g, p))) {
PUSH_WARNING(g->Message);
- return NULL;
+ goto fin;
} else
fn = jvp->GetString();
@@ -3222,7 +3848,7 @@ char *jfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!(jsp = ParseJson(g, p, strlen(p)))) {
PUSH_WARNING(g->Message);
- return NULL;
+ goto fin;
} // endif jsp
jvp->SetValue(jsp);
@@ -3249,9 +3875,9 @@ char *jfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endswitch arg_type
if (fn) {
- if ((msg = Serialize(g, jvp->GetJson(), fn, pretty)))
- PUSH_WARNING(msg);
- } else
+ if (!Serialize(g, jvp->GetJson(), fn, pretty))
+ PUSH_WARNING(g->Message);
+ } else
PUSH_WARNING("Missing file name");
str= fn;
@@ -3283,35 +3909,41 @@ my_bool jbin_array_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
unsigned long reslen, memlen;
CalcLen(args, false, reslen, memlen);
- return JsonInit(initid, args, message, false, reslen, memlen);
+ return JsonInit(initid, args, message, true, reslen, memlen);
} // end of jbin_array_init
char *jbin_array(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *)
+ unsigned long *res_length, char *is_null, char *error)
{
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;
+ PJAR arp = new(g) JARRAY;
+
+ bsp = JbinAlloc(g, args, initid->max_length, arp);
+ strcat(bsp->Msg, " array");
for (uint i = 0; i < args->arg_count; i++)
arp->AddValue(g, MakeValue(g, args, i));
arp->InitArray(g);
- bsp = JbinAlloc(g, args, initid->max_length, arp);
- strcat(bsp->Msg, " array");
- } else {
- bsp = JbinAlloc(g, args, initid->max_length, NULL);
- strncpy(bsp->Msg, g->Message, 139);
- } // endif CheckMemory
+ } else
+ if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
+ strncpy(bsp->Msg, g->Message, 139);
// Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_array
@@ -3329,17 +3961,18 @@ my_bool jbin_array_add_values_init(UDF_INIT *initid, UDF_ARGS *args, char *messa
} // end of jbin_array_add_values_init
char *jbin_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *is_null, char *)
+ unsigned long *res_length, char *is_null, char *error)
{
PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = (PBSON)g->Xchk;
if (!bsp || bsp->Changed) {
- if (!CheckMemory(g, initid, args, args->arg_count, false)) {
- char *p;
- PJSON top;
- PJAR arp;
- PJVAL jvp = MakeValue(g, args, 0, &top);
+ if (!CheckMemory(g, initid, args, args->arg_count, true)) {
+ char *p;
+ PJSON top;
+ PJAR arp;
+ PJVAL jvp = MakeValue(g, args, 0, &top);
+ PGLOBAL gb = GetMemPtr(g, args, 0);
if ((p = jvp->GetString())) {
if (!(top = ParseJson(g, p, strlen(p)))) {
@@ -3351,28 +3984,36 @@ char *jbin_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif p
if (jvp->GetValType() != TYPE_JAR) {
- arp = new(g)JARRAY;
- arp->AddValue(g, jvp);
+ arp = new(gb)JARRAY;
+ arp->AddValue(gb, jvp);
} else
arp = jvp->GetArray();
for (uint i = 1; i < args->arg_count; i++)
- arp->AddValue(g, MakeValue(g, args, i));
+ arp->AddValue(gb, MakeValue(gb, args, i));
- arp->InitArray(g);
- bsp = JbinAlloc(g, args, initid->max_length, top);
- strcat(bsp->Msg, " array");
- bsp->Jsp = arp;
- } else {
- bsp = JbinAlloc(g, args, initid->max_length, NULL);
- strncpy(bsp->Msg, g->Message, BMX);
- } // endif CheckMemory
+ arp->InitArray(gb);
+
+ if ((bsp = JbinAlloc(g, args, initid->max_length, top))) {
+ strcat(bsp->Msg, " array");
+ bsp->Jsp = arp;
+ } // endif bsp
+
+ } else
+ if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
+ strncpy(bsp->Msg, g->Message, BMX);
// Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_array_add_values
@@ -3390,7 +4031,7 @@ my_bool jbin_array_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_array_add_init
char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
int n = 2;
PJSON top = NULL;
@@ -3403,7 +4044,7 @@ char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
return (char*)bsp;
} // endif bsp
- if (!CheckMemory(g, initid, args, 2, false, true)) {
+ if (!CheckMemory(g, initid, args, 2, false, false, true)) {
int *x = NULL;
uint n = 2;
// PJSON jsp;
@@ -3417,9 +4058,11 @@ char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (CheckPath(g, args, top, jvp, n))
PUSH_WARNING(g->Message);
else if (jvp && jvp->GetValType() == TYPE_JAR) {
+ PGLOBAL gb = GetMemPtr(g, args, 0);
+
arp = jvp->GetArray();
- arp->AddValue(g, MakeValue(g, args, 1), x);
- arp->InitArray(g);
+ arp->AddValue(gb, MakeValue(gb, args, 1), x);
+ arp->InitArray(gb);
} else {
PUSH_WARNING("First argument is not an array");
// if (g->Mrr) *error = 1; (only if no path)
@@ -3434,7 +4077,13 @@ char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_array_add
@@ -3452,7 +4101,7 @@ my_bool jbin_array_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_array_delete_init
char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
PJSON top = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -3464,7 +4113,7 @@ char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
return (char*)bsp;
} // endif bsp
- if (!CheckMemory(g, initid, args, 1, false, true)) {
+ if (!CheckMemory(g, initid, args, 1, false, false, true)) {
int *x;
uint n = 1;
PJAR arp;
@@ -3476,7 +4125,7 @@ char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
if ((x = GetIntArgPtr(g, args, n))) {
arp = jvp->GetArray();
arp->DeleteValue(*x);
- arp->InitArray(g);
+ arp->InitArray(GetMemPtr(g, args, 0));
} else
PUSH_WARNING("Missing or null array index");
@@ -3494,7 +4143,13 @@ char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_array_delete
@@ -3504,7 +4159,7 @@ void jbin_array_delete_deinit(UDF_INIT* initid)
} // end of jbin_array_delete_deinit
/*********************************************************************************/
-/* Make a Json Oject containing all the parameters. */
+/* Make a Json Object containing all the parameters. */
/*********************************************************************************/
my_bool jbin_object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
@@ -3515,7 +4170,7 @@ my_bool jbin_object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_object_init
char *jbin_object(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *)
+ unsigned long *res_length, char *is_null, char *error)
{
PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = (PBSON)g->Xchk;
@@ -3527,18 +4182,24 @@ char *jbin_object(UDF_INIT *initid, UDF_ARGS *args, char *result,
for (uint i = 0; i < args->arg_count; i++)
objp->SetValue(g, MakeValue(g, args, i), MakeKey(g, args, i));
- bsp = JbinAlloc(g, args, initid->max_length, objp);
- strcat(bsp->Msg, " object");
- } else {
- bsp = JbinAlloc(g, args, initid->max_length, NULL);
- strncpy(bsp->Msg, g->Message, BMX);
- } // endif CheckMemory
+ if ((bsp = JbinAlloc(g, args, initid->max_length, objp)))
+ strcat(bsp->Msg, " object");
+
+ } else
+ if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
+ strncpy(bsp->Msg, g->Message, BMX);
// Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_object
@@ -3548,24 +4209,24 @@ void jbin_object_deinit(UDF_INIT* initid)
} // end of jbin_object_deinit
/*********************************************************************************/
-/* Make a Json Oject containing all not null parameters. */
+/* Make a Json Object containing all not null parameters. */
/*********************************************************************************/
my_bool jbin_object_nonull_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
unsigned long reslen, memlen;
CalcLen(args, true, reslen, memlen);
- return JsonInit(initid, args, message, false, reslen, memlen);
+ return JsonInit(initid, args, message, true, reslen, memlen);
} // end of jbin_object_nonull_init
char *jbin_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *)
+ unsigned long *res_length, char *is_null, char *error)
{
PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = (PBSON)g->Xchk;
if (!bsp || bsp->Changed) {
- if (!CheckMemory(g, initid, args, args->arg_count, true)) {
+ if (!CheckMemory(g, initid, args, args->arg_count, false, true)) {
PJVAL jvp;
PJOB objp = new(g)JOBJECT;
@@ -3573,18 +4234,24 @@ char *jbin_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!(jvp = MakeValue(g, args, i))->IsNull())
objp->SetValue(g, jvp, MakeKey(g, args, i));
- bsp = JbinAlloc(g, args, initid->max_length, objp);
- strcat(bsp->Msg, " object");
- } else {
- bsp = JbinAlloc(g, args, initid->max_length, NULL);
- strncpy(bsp->Msg, g->Message, BMX);
- } // endif CheckMemory
+ if ((bsp = JbinAlloc(g, args, initid->max_length, objp)))
+ strcat(bsp->Msg, " object");
+
+ } else
+ if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
+ strncpy(bsp->Msg, g->Message, BMX);
// Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_object_nonull
@@ -3594,6 +4261,61 @@ void jbin_object_nonull_deinit(UDF_INIT* initid)
} // end of jbin_object_nonull_deinit
/*********************************************************************************/
+/* Make a Json Object containing all the key/value parameters. */
+/*********************************************************************************/
+my_bool jbin_object_key_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ if (args->arg_count % 2) {
+ strcpy(message, "This function must have an even number of arguments");
+ return true;
+ } // endif arg_count
+
+ CalcLen(args, true, reslen, memlen);
+ return JsonInit(initid, args, message, true, reslen, memlen);
+} // end of jbin_object_key_init
+
+char *jbin_object_key(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PBSON bsp = (PBSON)g->Xchk;
+
+ if (!bsp || bsp->Changed) {
+ if (!CheckMemory(g, initid, args, args->arg_count, false, true)) {
+ PJOB objp = new(g)JOBJECT;
+
+ for (uint i = 0; i < args->arg_count; i += 2)
+ objp->SetValue(g, MakeValue(g, args, i+1), MakePSZ(g, args, i));
+
+ if ((bsp = JbinAlloc(g, args, initid->max_length, objp)))
+ strcat(bsp->Msg, " object");
+
+ } else
+ if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
+ strncpy(bsp->Msg, g->Message, BMX);
+
+ // Keep result of constant function
+ g->Xchk = (initid->const_item) ? bsp : NULL;
+ } // endif bsp
+
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
+ return (char*)bsp;
+} // end of jbin_object_key
+
+void jbin_object_key_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of jbin_object_key_deinit
+
+/*********************************************************************************/
/* Add or replace a value in a Json Object. */
/*********************************************************************************/
my_bool jbin_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
@@ -3602,7 +4324,7 @@ my_bool jbin_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_object_add_init
char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
PJSON top = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -3615,7 +4337,7 @@ char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
return (char*)bsp;
} // endif bsp
- if (!CheckMemory(g, initid, args, 2, false, true)) {
+ if (!CheckMemory(g, initid, args, 2, false, true, true)) {
char *key;
PJOB jobp;
PJVAL jvp = MakeValue(g, args, 0, &top);
@@ -3624,10 +4346,12 @@ char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (CheckPath(g, args, jsp, jvp, 2))
PUSH_WARNING(g->Message);
else if (jvp && jvp->GetValType() == TYPE_JOB) {
+ PGLOBAL gb = GetMemPtr(g, args, 0);
+
jobp = jvp->GetObject();
- jvp = MakeValue(g, args, 1);
- key = MakeKey(g, args, 1);
- jobp->SetValue(g, jvp, key);
+ jvp = MakeValue(gb, args, 1);
+ key = MakeKey(gb, args, 1);
+ jobp->SetValue(gb, jvp, key);
} else {
PUSH_WARNING("First argument target is not an object");
// if (g->Mrr) *error = 1; (only if no path)
@@ -3642,7 +4366,13 @@ char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_object_add
@@ -3660,7 +4390,7 @@ my_bool jbin_object_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_object_delete_init
char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
PJSON top = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -3673,7 +4403,7 @@ char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
return (char*)bsp;
} // endif bsp
- if (!CheckMemory(g, initid, args, 1, false, true)) {
+ if (!CheckMemory(g, initid, args, 1, false, true, true)) {
char *key;
PJOB jobp;
PJVAL jvp = MakeValue(g, args, 0, &top);
@@ -3699,7 +4429,13 @@ char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_object_delete
@@ -3724,7 +4460,7 @@ char *jbin_object_list(UDF_INIT *initid, UDF_ARGS *args, char *result,
PBSON bsp = (PBSON)g->Xchk;
if (!bsp || bsp->Changed) {
- if (!CheckMemory(g, initid, args, 1, false)) {
+ if (!CheckMemory(g, initid, args, 1, true, true)) {
char *p;
PJSON jsp;
PJVAL jvp = MakeValue(g, args, 0);
@@ -3747,14 +4483,20 @@ char *jbin_object_list(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif CheckMemory
- bsp = JbinAlloc(g, args, initid->max_length, jarp);
- strcat(bsp->Msg, " array");
+ if ((bsp = JbinAlloc(g, args, initid->max_length, jarp)))
+ strcat(bsp->Msg, " array");
// Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_object_list
@@ -3772,10 +4514,14 @@ my_bool jbin_get_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_get_item_init
char *jbin_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *is_null, char *)
+ unsigned long *res_length, char *is_null, char *error)
{
- PGLOBAL g = (PGLOBAL)initid->ptr;
+ char *p, *path;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
PBSON bsp = NULL;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
bsp = (PBSON)g->Activityp;
@@ -3783,56 +4529,54 @@ char *jbin_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- if (!CheckMemory(g, initid, args, 1, false)) {
- char *p, *path;
- PJSON jsp;
- PJSNX jsx;
- PJVAL jvp;
-
- if (!g->Xchk) {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true, true)) {
+ PUSH_WARNING("CheckMemory error");
+ goto fin;
+ } else
jvp = MakeValue(g, args, 0);
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- return NULL;
- } // endif jsp
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto fin;
+ } // endif jsp
- } else
- jsp = jvp->GetJson();
+ } else
+ jsp = jvp->GetJson();
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
- } else
- jsp = (PJSON)g->Xchk;
+ } else
+ jsp = (PJSON)g->Xchk;
- path = MakePSZ(g, args, 1);
- jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
+ path = MakePSZ(g, args, 1);
+ jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
- if (jsx->SetJpath(g, path, true)) {
- PUSH_WARNING(g->Message);
- *is_null = 1;
- return NULL;
- } // endif SetJpath
+ if (jsx->SetJpath(g, path, false)) {
+ PUSH_WARNING(g->Message);
+ goto fin;
+ } // endif SetJpath
- // Get the json tree
- jvp = jsx->GetValue(g, jsp, 0, false);
+ // Get the json tree
+ if ((jvp = jsx->GetRowValue(g, jsp, 0, false))) {
+ jsp = (jvp->GetJsp()) ? jvp->GetJsp() : new(g) JVALUE(g, jvp->GetValue());
- if (jvp->GetJsp()) {
- bsp = JbinAlloc(g, args, initid->max_length, jvp->GetJsp());
+ if ((bsp = JbinAlloc(g, args, initid->max_length, jsp)))
strcat(bsp->Msg, " item");
- } // end of Jsp
+ else
+ *error = 1;
- if (initid->const_item)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)bsp;
+ } // endif jvp
- } // endif CheckMemory
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)bsp;
-fin:
+ fin:
if (!bsp) {
*is_null = 1;
*res_length = 0;
@@ -3856,7 +4600,7 @@ my_bool jbin_item_merge_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_item_merge_init
char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
- unsigned long *res_length, char *, char *error)
+ unsigned long *res_length, char *is_null, char *error)
{
PJSON top = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
@@ -3868,9 +4612,10 @@ char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
return (char*)bsp;
} // endif bsp
- if (!CheckMemory(g, initid, args, 2, false, true)) {
- PJVAL jvp;
- PJSON jsp[2] = {NULL, NULL};
+ if (!CheckMemory(g, initid, args, 2, false, false, true)) {
+ PJVAL jvp;
+ PJSON jsp[2] = {NULL, NULL};
+ PGLOBAL gb = GetMemPtr(g, args, 0);
for (int i = 0; i < 2; i++) {
jvp = MakeValue(g, args, i);
@@ -3884,8 +4629,8 @@ char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endfor i
- if (jsp[0] && jsp[0]->Merge(g, jsp[1]))
- PUSH_WARNING(g->Message);
+ if (jsp[0] && jsp[0]->Merge(gb, jsp[1]))
+ PUSH_WARNING(gb->Message);
} // endif CheckMemory
@@ -3896,7 +4641,13 @@ char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
- *res_length = sizeof(BSON);
+ if (!bsp) {
+ *is_null = 1;
+ *error = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
return (char*)bsp;
} // end of jbin_item_merge
@@ -3906,6 +4657,147 @@ void jbin_item_merge_deinit(UDF_INIT* initid)
} // end of jbin_item_merge_deinit
/*********************************************************************************/
+/* Set Json items of a Json document according to path. */
+/*********************************************************************************/
+my_bool jbin_set_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ return json_set_item_init(initid, args, message);
+} // end of jbin_set_item_init
+
+char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *p, *path;
+ int w;
+ my_bool b = true;
+ PJSON jsp;
+ PJSNX jsx;
+ PJVAL jvp;
+ PBSON bsp = NULL;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PGLOBAL gb = GetMemPtr(g, args, 0);
+
+ if (g->N) {
+ bsp = (PBSON)g->Activityp;
+ goto fin;
+ } else if (initid->const_item)
+ g->N = 1;
+
+ if (!strcmp(result, "$insert"))
+ w = 1;
+ else if (!strcmp(result, "$update"))
+ w = 2;
+ else
+ w = 0;
+
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true, false, true)) {
+ PUSH_WARNING("CheckMemory error");
+ } else
+ jvp = MakeValue(g, args, 0);
+
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto fin;
+ } // 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;
+
+ jsx = new(g)JSNX(g, jsp, TYPE_STRING, initid->max_length, 0, true);
+
+ for (uint i = 1; i+1 < args->arg_count; i += 2) {
+ jvp = MakeValue(gb, args, i);
+ path = MakePSZ(g, args, i+1);
+
+ if (jsx->SetJpath(g, path, false)) {
+ PUSH_WARNING(g->Message);
+ continue;
+ } // endif SetJpath
+
+ if (w) {
+ jsx->ReadValue(g);
+ b = jsx->GetValue()->IsNull();
+ b = (w == 1) ? b : !b;
+ } // endif w
+
+ if (b && jsx->WriteValue(gb, jvp))
+ PUSH_WARNING(g->Message);
+
+ } // endfor i
+
+ if (!(bsp = MakeBinResult(g, args, jsp, initid->max_length, INT_MAX32)))
+ *error = 1;
+
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)bsp;
+
+ fin:
+ if (!bsp) {
+ *is_null = 1;
+ *res_length = 0;
+ } else
+ *res_length = sizeof(BSON);
+
+ return (char*)bsp;
+} // end of jbin_set_item
+
+void jbin_set_item_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of jbin_set_item_deinit
+
+/*********************************************************************************/
+/* Insert Json items of a Json document according to path. */
+/*********************************************************************************/
+my_bool jbin_insert_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ return json_set_item_init(initid, args, message);
+} // end of jbin_insert_item_init
+
+char *jbin_insert_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *p)
+{
+ strcpy(result, "$insert");
+ return jbin_set_item(initid, args, result, res_length, is_null, p);
+} // end of jbin_insert_item
+
+void jbin_insert_item_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of jbin_insert_item_deinit
+
+/*********************************************************************************/
+/* Update Json items of a Json document according to path. */
+/*********************************************************************************/
+my_bool jbin_update_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ return json_set_item_init(initid, args, message);
+} // end of jbin_update_item_init
+
+char *jbin_update_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *p)
+{
+ strcpy(result, "$update");
+ return jbin_set_item(initid, args, result, res_length, is_null, p);
+} // end of jbin_update_item
+
+void jbin_update_item_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of jbin_update_item_deinit
+
+/*********************************************************************************/
/* Returns a json file as a json item. */
/*********************************************************************************/
my_bool jbin_file_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
@@ -3939,7 +4831,7 @@ my_bool jbin_file_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
reslen += fl;
more += fl * M;
memlen += more;
- return JsonInit(initid, args, message, false, reslen, memlen);
+ return JsonInit(initid, args, message, true, reslen, memlen);
} // end of jbin_file_init
char *jbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
@@ -3976,10 +4868,14 @@ char *jbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
else if (pretty == 3)
pretty = pty;
- bsp = JbinAlloc(g, args, len, jsp);
- strcat(bsp->Msg, " file");
- bsp->Filename = fn;
- bsp->Pretty = pretty;
+ if ((bsp = JbinAlloc(g, args, len, jsp))) {
+ strcat(bsp->Msg, " file");
+ bsp->Filename = fn;
+ bsp->Pretty = pretty;
+ } else {
+ *error = 1;
+ goto fin;
+ } // endif bsp
// Check whether a path was specified
if (CheckPath(g, args, jsp, jvp, 1)) {
@@ -3993,7 +4889,7 @@ char *jbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
-fin:
+ fin:
if (!bsp) {
*res_length = 0;
*is_null = 1;