Commit 1d239d8c authored by Olivier Bertrand's avatar Olivier Bertrand

Make changes required by version 10.1.9 (see Sergei's mmail):

Use PlgDBSuballoc in JbinAlloc to avoid unsupported longjmp's.
  modified:   storage/connect/ha_connect.cc
  modified:   storage/connect/jsonudf.cpp
  modified:   storage/connect/jsonudf.h
  modified:   storage/connect/mysql-test/connect/r/json_udf.result
  modified:   storage/connect/mysql-test/connect/t/json_udf.inc
  modified:   storage/connect/tabjson.cpp
  modified:   storage/connect/value.cpp
Add new UDF functions jsoncontains, jsoncontains_path, json_set_item,
json_insert_item, json_update_item, jbin_set_item, jbin_insert_item,
jbin_update_item
  modified:   storage/connect/json.cpp
  modified:   storage/connect/json.h
  modified:   storage/connect/jsonudf.cpp
  modified:   storage/connect/jsonudf.h
parent 0a852591
...@@ -169,9 +169,9 @@ ...@@ -169,9 +169,9 @@
#define JSONMAX 10 // JSON Default max grp size #define JSONMAX 10 // JSON Default max grp size
extern "C" { extern "C" {
char version[]= "Version 1.04.0003 October 25, 2015"; char version[]= "Version 1.04.0005 November 20, 2015";
#if defined(__WIN__) #if defined(__WIN__)
char compver[]= "Version 1.04.0003 " __DATE__ " " __TIME__; char compver[]= "Version 1.04.0005 " __DATE__ " " __TIME__;
char slash= '\\'; char slash= '\\';
#else // !__WIN__ #else // !__WIN__
char slash= '/'; char slash= '/';
...@@ -6274,10 +6274,6 @@ bool ha_connect::FileExists(const char *fn, bool bf) ...@@ -6274,10 +6274,6 @@ bool ha_connect::FileExists(const char *fn, bool bf)
int n; int n;
struct stat info; struct stat info;
if (check_access(ha_thd(), FILE_ACL, table->s->db.str,
NULL, NULL, 0, 0))
return true;
#if defined(__WIN__) #if defined(__WIN__)
s= "\\"; s= "\\";
#else // !__WIN__ #else // !__WIN__
......
...@@ -1282,6 +1282,18 @@ PSZ JVALUE::GetText(PGLOBAL g, PSZ text) ...@@ -1282,6 +1282,18 @@ PSZ JVALUE::GetText(PGLOBAL g, PSZ text)
return text; return text;
} // end of GetText } // end of GetText
void JVALUE::SetValue(PJSON jsp)
{
if (jsp->GetType() == TYPE_JVAL) {
Jsp = jsp->GetJsp();
Value = jsp->GetValue();
} else {
Jsp = jsp;
Value = NULL;
} // endif Type
} // end of SetValue;
/***********************************************************************/ /***********************************************************************/
/* Set the Value's value as the given integer. */ /* Set the Value's value as the given integer. */
/***********************************************************************/ /***********************************************************************/
......
...@@ -271,9 +271,9 @@ class JVALUE : public JSON { ...@@ -271,9 +271,9 @@ class JVALUE : public JSON {
virtual double GetFloat(void); virtual double GetFloat(void);
virtual PSZ GetString(void); virtual PSZ GetString(void);
virtual PSZ GetText(PGLOBAL g, PSZ text); virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual void SetValue(PVAL valp) {Value = valp; Jsp = NULL;} virtual void SetValue(PJSON jsp);
virtual void SetValue(PJSON jsp) {Jsp = jsp; Value = NULL;} virtual void SetValue(PVAL valp) { Value = valp; Jsp = NULL; }
virtual void SetString(PGLOBAL g, PSZ s, short c = 0); 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);
......
...@@ -36,7 +36,7 @@ static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i); ...@@ -36,7 +36,7 @@ static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i);
/*********************************************************************************/ /*********************************************************************************/
/* 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, my_bool wr)
{ {
Row = row; Row = row;
Jvalp = NULL; Jvalp = NULL;
...@@ -58,6 +58,7 @@ JSNX::JSNX(PGLOBAL g, PJSON row, int type, int len, int prec) ...@@ -58,6 +58,7 @@ JSNX::JSNX(PGLOBAL g, PJSON row, int type, int len, int prec)
Xpd = false; Xpd = false;
Parsed = false; Parsed = false;
Found = false; Found = false;
Wr = wr;
} // end of JSNX constructor } // end of JSNX constructor
/*********************************************************************************/ /*********************************************************************************/
...@@ -85,6 +86,8 @@ my_bool JSNX::SetJpath(PGLOBAL g, char *path, my_bool jb) ...@@ -85,6 +86,8 @@ my_bool JSNX::SetJpath(PGLOBAL g, char *path, my_bool jb)
Jpath = path; Jpath = path;
// Parse the json path // Parse the json path
Parsed = false;
Nod = 0;
return ParseJpath(g); return ParseJpath(g);
} // end of SetJpath } // end of SetJpath
...@@ -117,7 +120,11 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) ...@@ -117,7 +120,11 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
if (!n) { if (!n) {
// Default specifications // Default specifications
if (jnp->Op != OP_EXP) { if (jnp->Op != OP_EXP) {
if (b) { if (Wr) {
// Force append
jnp->Rank = INT_MAX32;
jnp->Op = OP_LE;
} else if (b) {
// Return 1st value (B is the index base) // Return 1st value (B is the index base)
jnp->Rank = B; jnp->Rank = B;
jnp->Op = OP_LE; jnp->Op = OP_LE;
...@@ -388,11 +395,11 @@ PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i, my_bool b) ...@@ -388,11 +395,11 @@ PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i, my_bool b)
else else
return new(g) JVALUE(g, CalculateArray(g, arp, i)); return new(g) JVALUE(g, CalculateArray(g, arp, i));
} else if (i < Nod-1) { } else {
strcpy(g->Message, "Unexpected array"); // Unexpected array, unwrap it as [0]
val = NULL; // Not an expected array
} else
val = arp->GetValue(0); val = arp->GetValue(0);
i--;
} // endif's
break; break;
case TYPE_JVAL: case TYPE_JVAL:
...@@ -404,7 +411,9 @@ PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i, my_bool b) ...@@ -404,7 +411,9 @@ PJVAL JSNX::GetValue(PGLOBAL g, PJSON row, int i, my_bool b)
} // endswitch Type } // endswitch Type
if (i < Nod-1) if (i < Nod-1)
row = (val) ? val->GetJson() : NULL; if (!(row = (val) ? val->GetJsp() : NULL))
val = NULL;
// row = (val) ? val->GetJson() : NULL;
} // endfor i } // endfor i
...@@ -502,6 +511,163 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) ...@@ -502,6 +511,163 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
return vp; return vp;
} // end of CalculateArray } // 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+1].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].Op == OP_EQ)
arp->SetValue(g, jvalp, Nodes[Nod-1].Rank);
else
arp->AddValue(g, jvalp);
arp->InitArray(g);
} 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: */ /* Locate a value in a JSON tree: */
/*********************************************************************************/ /*********************************************************************************/
...@@ -824,16 +990,20 @@ struct BSON { ...@@ -824,16 +990,20 @@ struct BSON {
/*********************************************************************************/ /*********************************************************************************/
static PBSON JbinAlloc(PGLOBAL g, UDF_ARGS *args, ulong len, PJSON jsp) 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->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; return bsp;
} /* end of JbinAlloc */ } /* end of JbinAlloc */
...@@ -983,6 +1153,9 @@ static PBSON MakeBinResult(PGLOBAL g, UDF_ARGS *args, PJSON top, ulong len, int ...@@ -983,6 +1153,9 @@ static PBSON MakeBinResult(PGLOBAL g, UDF_ARGS *args, PJSON top, ulong len, int
{ {
PBSON bsnp = JbinAlloc(g, args, len, top); PBSON bsnp = JbinAlloc(g, args, len, top);
if (!bsnp)
return NULL;
if (IsJson(args, 0) == 2) { if (IsJson(args, 0) == 2) {
int pretty = 2; int pretty = 2;
...@@ -1793,7 +1966,7 @@ void json_array_delete_deinit(UDF_INIT* initid) ...@@ -1793,7 +1966,7 @@ void json_array_delete_deinit(UDF_INIT* initid)
} // end of json_array_delete_deinit } // 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) my_bool json_object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
...@@ -1837,7 +2010,7 @@ void json_object_deinit(UDF_INIT* initid) ...@@ -1837,7 +2010,7 @@ void json_object_deinit(UDF_INIT* initid)
} // end of json_object_deinit } // 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, my_bool json_object_nonull_init(UDF_INIT *initid, UDF_ARGS *args,
char *message) char *message)
...@@ -1883,6 +2056,55 @@ void json_object_nonull_deinit(UDF_INIT* initid) ...@@ -1883,6 +2056,55 @@ void json_object_nonull_deinit(UDF_INIT* initid)
JsonFreeMem((PGLOBAL)initid->ptr); JsonFreeMem((PGLOBAL)initid->ptr);
} // end of json_object_nonull_deinit } // 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, 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. */ /* Add or replace a value in a Json Object. */
/*********************************************************************************/ /*********************************************************************************/
...@@ -2379,10 +2601,9 @@ char *json_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -2379,10 +2601,9 @@ char *json_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
char *p, *path; char *p, *path;
PJSON jsp; PJSON jsp;
PJSNX jsx; PJSNX jsx;
PJVAL jvp;
if (!g->Xchk) { if (!g->Xchk) {
jvp = MakeValue(g, args, 0); PJVAL jvp = MakeValue(g, args, 0);
if ((p = jvp->GetString())) { if ((p = jvp->GetString())) {
if (!(jsp = ParseJson(g, p, strlen(p)))) { if (!(jsp = ParseJson(g, p, strlen(p)))) {
...@@ -2647,7 +2868,7 @@ long long jsonget_int(UDF_INIT *initid, UDF_ARGS *args, ...@@ -2647,7 +2868,7 @@ long long jsonget_int(UDF_INIT *initid, UDF_ARGS *args,
jsx->ReadValue(g); jsx->ReadValue(g);
if (jsx->GetValue()->IsNull()) { if (jsx->GetValue()->IsNull()) {
PUSH_WARNING("Value not found"); // PUSH_WARNING("Value not found");
*is_null = 1; *is_null = 1;
return 0; return 0;
} // endif IsNull } // endif IsNull
...@@ -2763,7 +2984,7 @@ double jsonget_real(UDF_INIT *initid, UDF_ARGS *args, ...@@ -2763,7 +2984,7 @@ double jsonget_real(UDF_INIT *initid, UDF_ARGS *args,
jsx->ReadValue(g); jsx->ReadValue(g);
if (jsx->GetValue()->IsNull()) { if (jsx->GetValue()->IsNull()) {
PUSH_WARNING("Value not found"); // PUSH_WARNING("Value not found");
*is_null = 1; *is_null = 1;
return 0.0; return 0.0;
} // endif IsNull } // endif IsNull
...@@ -3047,141 +3268,481 @@ void json_locate_all_deinit(UDF_INIT* initid) ...@@ -3047,141 +3268,481 @@ void json_locate_all_deinit(UDF_INIT* initid)
} // end of json_locate_all_deinit } // end of json_locate_all_deinit
/*********************************************************************************/ /*********************************************************************************/
/* Returns a json file as a json string. */ /* Check whether the document contains a value or item. */
/*********************************************************************************/ /*********************************************************************************/
my_bool json_file_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool jsoncontains_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen, fl, more = 1024; unsigned long reslen, memlen, more = 1024;
int n = IsJson(args, 0);
if (args->arg_count < 1 || args->arg_count > 4) { if (args->arg_count < 2) {
strcpy(message, "This function only accepts 1 to 4 arguments"); strcpy(message, "At least 2 arguments required");
return true; return true;
} else if (!args->args[0] || args->arg_type[0] != STRING_RESULT) { } else if (!n && args->arg_type[0] != STRING_RESULT) {
strcpy(message, "First argument must be a constant string (file name)"); strcpy(message, "First argument must be a json item");
return true; return true;
} // endif's args[0] } else if (args->arg_count > 2 && args->arg_type[2] != INT_RESULT) {
strcpy(message, "Third argument is not an integer (index)");
for (unsigned int i = 1; i < args->arg_count; i++) { return true;
if (!(args->arg_type[i] == INT_RESULT || args->arg_type[i] == STRING_RESULT)) { } else if (args->arg_count > 3) {
sprintf(message, "Argument %d is not an integer or a string (pretty or path)", i); if (args->arg_type[3] == INT_RESULT && args->args[3])
return true; more += (unsigned long)*(long long*)args->args[3];
} // endif arg_type else
strcpy(message, "Fourth argument is not an integer (memory)");
// Take care of eventual memory argument
if (args->arg_type[i] == INT_RESULT && args->args[i])
more += (ulong)*(longlong*)args->args[i];
} // endfor i } // endif's
initid->maybe_null = 1;
CalcLen(args, false, reslen, memlen); CalcLen(args, false, reslen, memlen);
fl = GetFileLength(args->args[0]); memlen += more;
reslen += fl;
if (initid->const_item)
more += fl;
if (args->arg_count > 1) if (IsJson(args, 0) != 3)
more += fl * M; memlen += 1000; // TODO: calculate this
memlen += more;
return JsonInit(initid, args, message, false, reslen, memlen); return JsonInit(initid, args, message, false, reslen, memlen);
} // end of json_file_init } // end of jsoncontains_init
char *json_file(UDF_INIT *initid, UDF_ARGS *args, char *result, long long jsoncontains(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 *str, *fn; char *p, res[256];
PGLOBAL g = (PGLOBAL)initid->ptr; long long n;
unsigned long reslen;
if (g->N) {
str = (char*)g->Xchk;
goto fin;
} else if (initid->const_item)
g->N = 1;
PlugSubSet(g, g->Sarea, g->Sarea_Size);
fn = MakePSZ(g, args, 0);
if (args->arg_count > 1) {
int len, pretty, pty = 3;
PJSON jsp;
PJVAL jvp = NULL;
pretty = (args->arg_type[1] == INT_RESULT) ? (int)*(longlong*)args->args[1]
: (args->arg_count > 2 && args->arg_type[2] == INT_RESULT)
? (int)*(longlong*)args->args[2] : 3;
/*******************************************************************************/
/* Parse the json file and allocate its tree structure. */
/*******************************************************************************/
if (!(jsp = ParseJsonFile(g, fn, &pty, len))) {
PUSH_WARNING(g->Message);
str = NULL;
goto fin;
} // endif jsp
if (pty == 3)
PUSH_WARNING("File pretty format cannot be determined");
else if (pretty != 3 && pty != pretty)
PUSH_WARNING("File pretty format doesn't match the specified pretty value");
else if (pretty == 3)
pretty = pty;
// Check whether a path was specified
if (CheckPath(g, args, jsp, jvp, 1)) {
PUSH_WARNING(g->Message);
str = NULL;
goto fin;
} else if (jvp)
jsp = jvp->GetJson();
if (!(str = Serialize(g, jsp, NULL, 0)))
PUSH_WARNING(g->Message);
} else
str = GetJsonFile(g, fn);
if (initid->const_item)
// Keep result of constant function
g->Xchk = str;
fin:
if (!str) {
*res_length = 0;
*is_null = 1;
} else
*res_length = strlen(str);
return str; *is_null = 0;
} // end of json_file p = jsonlocate(initid, args, res, &reslen, is_null, error);
n = (*is_null) ? 0LL : 1LL;
return n;
} // end of jsoncontains
void json_file_deinit(UDF_INIT* initid) void jsoncontains_deinit(UDF_INIT* initid)
{ {
JsonFreeMem((PGLOBAL)initid->ptr); JsonFreeMem((PGLOBAL)initid->ptr);
} // end of json_file_deinit } // end of jsoncontains_deinit
/*********************************************************************************/ /*********************************************************************************/
/* Make a json file from a json item. */ /* Check whether the document contains a path. */
/*********************************************************************************/ /*********************************************************************************/
my_bool jfile_make_init(UDF_INIT *initid, UDF_ARGS *args, char *message) my_bool jsoncontains_path_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen, more = 1024; unsigned long reslen, memlen, more = 1024;
int n = IsJson(args, 0);
if (args->arg_count < 1 || args->arg_count > 3) { if (args->arg_count < 2) {
strcpy(message, "Wrong number of arguments"); strcpy(message, "At least 2 arguments required");
return true; return true;
} else if (!IsJson(args, 0) && args->arg_type[0] != STRING_RESULT) { } else if (!n && args->arg_type[0] != STRING_RESULT) {
strcpy(message, "First argument must be a json item"); strcpy(message, "First argument must be a json item");
return true; return true;
} // endif } 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); CalcLen(args, false, reslen, memlen);
return JsonInit(initid, args, message, true, reslen, memlen); memlen += more;
} // end of jfile_make_init
char *jfile_make(UDF_INIT *initid, UDF_ARGS *args, char *result, if (IsJson(args, 0) != 3)
unsigned long *res_length, char *is_null, char *) 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)
{
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
if (!g->Activityp) {
*is_null = 1;
return 0LL;
} else
return *(long long*)g->Activityp;
} 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) {
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
} 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);
*is_null = 1;
return 0;
} // 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;
} // endif CheckMemory
if (g->Mrr) *error = 1;
*is_null = 1;
return 0LL;
} // end of jsoncontains_path
void jsoncontains_path_deinit(UDF_INIT* initid)
{
JsonFreeMem((PGLOBAL)initid->ptr);
} // 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) {
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 *)
{
int w, rc;
my_bool b = true;
char *str = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
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;
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
if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
PUSH_WARNING(g->Message);
str = 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;
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(g, args, i);
path = MakePSZ(g, args, i+1);
if (jsx->SetJpath(g, path, false)) {
PUSH_WARNING(g->Message);
*is_null = 1;
goto err;
} // endif SetJpath
if (w) {
jsx->ReadValue(g);
b = jsx->GetValue()->IsNull();
b = (w == 1) ? b : !b;
} // endif w
if (b && jsx->WriteValue(g, jvp))
PUSH_WARNING(g->Message);
} // endfor i
str = Serialize(g, jsp, NULL, 0);
if (initid->const_item)
// Keep result of constant function
g->Activityp = (PACTIVITY)str;
err:
g->jump_level--;
} // endif CheckMemory
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. */
/*********************************************************************************/
my_bool json_file_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
unsigned long reslen, memlen, fl, more = 1024;
if (args->arg_count < 1 || args->arg_count > 4) {
strcpy(message, "This function only accepts 1 to 4 arguments");
return true;
} else if (!args->args[0] || args->arg_type[0] != STRING_RESULT) {
strcpy(message, "First argument must be a constant string (file name)");
return true;
} // endif's args[0]
for (unsigned int i = 1; i < args->arg_count; i++) {
if (!(args->arg_type[i] == INT_RESULT || args->arg_type[i] == STRING_RESULT)) {
sprintf(message, "Argument %d is not an integer or a string (pretty or path)", i);
return true;
} // endif arg_type
// Take care of eventual memory argument
if (args->arg_type[i] == INT_RESULT && args->args[i])
more += (ulong)*(longlong*)args->args[i];
} // endfor i
initid->maybe_null = 1;
CalcLen(args, false, reslen, memlen);
fl = GetFileLength(args->args[0]);
reslen += fl;
if (initid->const_item)
more += fl;
if (args->arg_count > 1)
more += fl * M;
memlen += more;
return JsonInit(initid, args, message, false, reslen, memlen);
} // end of json_file_init
char *json_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *error)
{
char *str, *fn;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
str = (char*)g->Xchk;
goto fin;
} else if (initid->const_item)
g->N = 1;
PlugSubSet(g, g->Sarea, g->Sarea_Size);
fn = MakePSZ(g, args, 0);
if (args->arg_count > 1) {
int len, pretty, pty = 3;
PJSON jsp;
PJVAL jvp = NULL;
pretty = (args->arg_type[1] == INT_RESULT) ? (int)*(longlong*)args->args[1]
: (args->arg_count > 2 && args->arg_type[2] == INT_RESULT)
? (int)*(longlong*)args->args[2] : 3;
/*******************************************************************************/
/* Parse the json file and allocate its tree structure. */
/*******************************************************************************/
if (!(jsp = ParseJsonFile(g, fn, &pty, len))) {
PUSH_WARNING(g->Message);
str = NULL;
goto fin;
} // endif jsp
if (pty == 3)
PUSH_WARNING("File pretty format cannot be determined");
else if (pretty != 3 && pty != pretty)
PUSH_WARNING("File pretty format doesn't match the specified pretty value");
else if (pretty == 3)
pretty = pty;
// Check whether a path was specified
if (CheckPath(g, args, jsp, jvp, 1)) {
PUSH_WARNING(g->Message);
str = NULL;
goto fin;
} else if (jvp)
jsp = jvp->GetJson();
if (!(str = Serialize(g, jsp, NULL, 0)))
PUSH_WARNING(g->Message);
} else
str = GetJsonFile(g, fn);
if (initid->const_item)
// Keep result of constant function
g->Xchk = str;
fin:
if (!str) {
*res_length = 0;
*is_null = 1;
} else
*res_length = strlen(str);
return str;
} // end of json_file
void json_file_deinit(UDF_INIT* initid)
{
JsonFreeMem((PGLOBAL)initid->ptr);
} // end of json_file_deinit
/*********************************************************************************/
/* Make a json file from a json item. */
/*********************************************************************************/
my_bool jfile_make_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
unsigned long reslen, memlen, more = 1024;
if (args->arg_count < 1 || args->arg_count > 3) {
strcpy(message, "Wrong number of arguments");
return true;
} else if (!IsJson(args, 0) && args->arg_type[0] != STRING_RESULT) {
strcpy(message, "First argument must be a json item");
return true;
} // endif
CalcLen(args, false, reslen, memlen);
return JsonInit(initid, args, message, true, reslen, memlen);
} // end of jfile_make_init
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, *msg, *fn = NULL;
int n, pretty = 2; int n, pretty = 2;
...@@ -3283,11 +3844,11 @@ my_bool jbin_array_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -3283,11 +3844,11 @@ my_bool jbin_array_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
unsigned long reslen, memlen; unsigned long reslen, memlen;
CalcLen(args, false, 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 } // end of jbin_array_init
char *jbin_array(UDF_INIT *initid, UDF_ARGS *args, char *result, 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; PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = (PBSON)g->Xchk; PBSON bsp = (PBSON)g->Xchk;
...@@ -3300,18 +3861,24 @@ char *jbin_array(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -3300,18 +3861,24 @@ char *jbin_array(UDF_INIT *initid, UDF_ARGS *args, char *result,
arp->AddValue(g, MakeValue(g, args, i)); arp->AddValue(g, MakeValue(g, args, i));
arp->InitArray(g); arp->InitArray(g);
bsp = JbinAlloc(g, args, initid->max_length, arp);
strcat(bsp->Msg, " array"); if ((bsp = JbinAlloc(g, args, initid->max_length, arp)))
} else { strcat(bsp->Msg, " array");
bsp = JbinAlloc(g, args, initid->max_length, NULL);
strncpy(bsp->Msg, g->Message, 139); } else
} // endif CheckMemory if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
strncpy(bsp->Msg, g->Message, 139);
// Keep result of constant function // Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL; g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp } // endif bsp
*res_length = sizeof(BSON); if (!bsp) {
*is_null = 1;
*error = 1;
} else
*res_length = sizeof(BSON);
return (char*)bsp; return (char*)bsp;
} // end of jbin_array } // end of jbin_array
...@@ -3329,7 +3896,7 @@ my_bool jbin_array_add_values_init(UDF_INIT *initid, UDF_ARGS *args, char *messa ...@@ -3329,7 +3896,7 @@ my_bool jbin_array_add_values_init(UDF_INIT *initid, UDF_ARGS *args, char *messa
} // end of jbin_array_add_values_init } // end of jbin_array_add_values_init
char *jbin_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result, 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; PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = (PBSON)g->Xchk; PBSON bsp = (PBSON)g->Xchk;
...@@ -3360,19 +3927,26 @@ char *jbin_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -3360,19 +3927,26 @@ char *jbin_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result,
arp->AddValue(g, MakeValue(g, args, i)); arp->AddValue(g, MakeValue(g, args, i));
arp->InitArray(g); arp->InitArray(g);
bsp = JbinAlloc(g, args, initid->max_length, top);
strcat(bsp->Msg, " array"); if ((bsp = JbinAlloc(g, args, initid->max_length, top))) {
bsp->Jsp = arp; strcat(bsp->Msg, " array");
} else { bsp->Jsp = arp;
bsp = JbinAlloc(g, args, initid->max_length, NULL); } // endif bsp
strncpy(bsp->Msg, g->Message, BMX);
} // endif CheckMemory } else
if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
strncpy(bsp->Msg, g->Message, BMX);
// Keep result of constant function // Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL; g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp } // endif bsp
*res_length = sizeof(BSON); if (!bsp) {
*is_null = 1;
*error = 1;
} else
*res_length = sizeof(BSON);
return (char*)bsp; return (char*)bsp;
} // end of jbin_array_add_values } // end of jbin_array_add_values
...@@ -3390,7 +3964,7 @@ my_bool jbin_array_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -3390,7 +3964,7 @@ my_bool jbin_array_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_array_add_init } // end of jbin_array_add_init
char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result, 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; int n = 2;
PJSON top = NULL; PJSON top = NULL;
...@@ -3434,7 +4008,13 @@ char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -3434,7 +4008,13 @@ char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function // Keep result of constant function
g->Xchk = bsp; 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; return (char*)bsp;
} // end of jbin_array_add } // end of jbin_array_add
...@@ -3452,7 +4032,7 @@ my_bool jbin_array_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -3452,7 +4032,7 @@ my_bool jbin_array_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_array_delete_init } // end of jbin_array_delete_init
char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, 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; PJSON top = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr; PGLOBAL g = (PGLOBAL)initid->ptr;
...@@ -3494,7 +4074,13 @@ char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -3494,7 +4074,13 @@ char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function // Keep result of constant function
g->Xchk = bsp; 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; return (char*)bsp;
} // end of jbin_array_delete } // end of jbin_array_delete
...@@ -3504,7 +4090,7 @@ void jbin_array_delete_deinit(UDF_INIT* initid) ...@@ -3504,7 +4090,7 @@ void jbin_array_delete_deinit(UDF_INIT* initid)
} // end of jbin_array_delete_deinit } // 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) my_bool jbin_object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
...@@ -3515,7 +4101,7 @@ my_bool jbin_object_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -3515,7 +4101,7 @@ my_bool jbin_object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_object_init } // end of jbin_object_init
char *jbin_object(UDF_INIT *initid, UDF_ARGS *args, char *result, 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; PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = (PBSON)g->Xchk; PBSON bsp = (PBSON)g->Xchk;
...@@ -3527,18 +4113,23 @@ char *jbin_object(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -3527,18 +4113,23 @@ char *jbin_object(UDF_INIT *initid, UDF_ARGS *args, char *result,
for (uint i = 0; i < args->arg_count; i++) for (uint i = 0; i < args->arg_count; i++)
objp->SetValue(g, MakeValue(g, args, i), MakeKey(g, args, i)); objp->SetValue(g, MakeValue(g, args, i), MakeKey(g, args, i));
bsp = JbinAlloc(g, args, initid->max_length, objp); if ((bsp = JbinAlloc(g, args, initid->max_length, objp)))
strcat(bsp->Msg, " object"); strcat(bsp->Msg, " object");
} else {
bsp = JbinAlloc(g, args, initid->max_length, NULL); } else
strncpy(bsp->Msg, g->Message, BMX); if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
} // endif CheckMemory strncpy(bsp->Msg, g->Message, BMX);
// Keep result of constant function // Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL; g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp } // endif bsp
*res_length = sizeof(BSON); if (!bsp) {
*is_null = 1;
*error = 1;
} else
*res_length = sizeof(BSON);
return (char*)bsp; return (char*)bsp;
} // end of jbin_object } // end of jbin_object
...@@ -3548,18 +4139,18 @@ void jbin_object_deinit(UDF_INIT* initid) ...@@ -3548,18 +4139,18 @@ void jbin_object_deinit(UDF_INIT* initid)
} // end of jbin_object_deinit } // 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) my_bool jbin_object_nonull_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{ {
unsigned long reslen, memlen; unsigned long reslen, memlen;
CalcLen(args, true, 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 } // end of jbin_object_nonull_init
char *jbin_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result, 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; PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = (PBSON)g->Xchk; PBSON bsp = (PBSON)g->Xchk;
...@@ -3573,18 +4164,23 @@ char *jbin_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -3573,18 +4164,23 @@ char *jbin_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!(jvp = MakeValue(g, args, i))->IsNull()) if (!(jvp = MakeValue(g, args, i))->IsNull())
objp->SetValue(g, jvp, MakeKey(g, args, i)); objp->SetValue(g, jvp, MakeKey(g, args, i));
bsp = JbinAlloc(g, args, initid->max_length, objp); if ((bsp = JbinAlloc(g, args, initid->max_length, objp)))
strcat(bsp->Msg, " object"); strcat(bsp->Msg, " object");
} else {
bsp = JbinAlloc(g, args, initid->max_length, NULL); } else
strncpy(bsp->Msg, g->Message, BMX); if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
} // endif CheckMemory strncpy(bsp->Msg, g->Message, BMX);
// Keep result of constant function // Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL; g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp } // endif bsp
*res_length = sizeof(BSON); if (!bsp) {
*is_null = 1;
*error = 1;
} else
*res_length = sizeof(BSON);
return (char*)bsp; return (char*)bsp;
} // end of jbin_object_nonull } // end of jbin_object_nonull
...@@ -3593,6 +4189,60 @@ void jbin_object_nonull_deinit(UDF_INIT* initid) ...@@ -3593,6 +4189,60 @@ void jbin_object_nonull_deinit(UDF_INIT* initid)
JsonFreeMem((PGLOBAL)initid->ptr); JsonFreeMem((PGLOBAL)initid->ptr);
} // end of jbin_object_nonull_deinit } // 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, 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;
} 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. */ /* Add or replace a value in a Json Object. */
/*********************************************************************************/ /*********************************************************************************/
...@@ -3602,7 +4252,7 @@ my_bool jbin_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -3602,7 +4252,7 @@ my_bool jbin_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_object_add_init } // end of jbin_object_add_init
char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result, 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; PJSON top = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr; PGLOBAL g = (PGLOBAL)initid->ptr;
...@@ -3642,7 +4292,13 @@ char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -3642,7 +4292,13 @@ char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function // Keep result of constant function
g->Xchk = bsp; 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; return (char*)bsp;
} // end of jbin_object_add } // end of jbin_object_add
...@@ -3660,7 +4316,7 @@ my_bool jbin_object_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -3660,7 +4316,7 @@ my_bool jbin_object_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_object_delete_init } // end of jbin_object_delete_init
char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, 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; PJSON top = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr; PGLOBAL g = (PGLOBAL)initid->ptr;
...@@ -3699,7 +4355,13 @@ char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -3699,7 +4355,13 @@ char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function // Keep result of constant function
g->Xchk = bsp; 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; return (char*)bsp;
} // end of jbin_object_delete } // end of jbin_object_delete
...@@ -3747,14 +4409,19 @@ char *jbin_object_list(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -3747,14 +4409,19 @@ char *jbin_object_list(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif CheckMemory } // endif CheckMemory
bsp = JbinAlloc(g, args, initid->max_length, jarp); if ((bsp = JbinAlloc(g, args, initid->max_length, jarp)))
strcat(bsp->Msg, " array"); strcat(bsp->Msg, " array");
// Keep result of constant function // Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL; g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp } // endif bsp
*res_length = sizeof(BSON); if (!bsp) {
*is_null = 1;
*error = 1;
} else
*res_length = sizeof(BSON);
return (char*)bsp; return (char*)bsp;
} // end of jbin_object_list } // end of jbin_object_list
...@@ -3772,7 +4439,7 @@ my_bool jbin_get_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -3772,7 +4439,7 @@ my_bool jbin_get_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_get_item_init } // end of jbin_get_item_init
char *jbin_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result, 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; PGLOBAL g = (PGLOBAL)initid->ptr;
PBSON bsp = NULL; PBSON bsp = NULL;
...@@ -3821,10 +4488,13 @@ char *jbin_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -3821,10 +4488,13 @@ char *jbin_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Get the json tree // Get the json tree
jvp = jsx->GetValue(g, jsp, 0, false); jvp = jsx->GetValue(g, jsp, 0, false);
if (jvp->GetJsp()) { if (jvp && jvp->GetJsp()) {
bsp = JbinAlloc(g, args, initid->max_length, jvp->GetJsp()); if ((bsp = JbinAlloc(g, args, initid->max_length, jvp->GetJsp())))
strcat(bsp->Msg, " item"); strcat(bsp->Msg, " item");
} // end of Jsp else
*error = 1;
} // endif jvp
if (initid->const_item) if (initid->const_item)
// Keep result of constant function // Keep result of constant function
...@@ -3856,7 +4526,7 @@ my_bool jbin_item_merge_init(UDF_INIT *initid, UDF_ARGS *args, char *message) ...@@ -3856,7 +4526,7 @@ my_bool jbin_item_merge_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
} // end of jbin_item_merge_init } // end of jbin_item_merge_init
char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result, 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; PJSON top = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr; PGLOBAL g = (PGLOBAL)initid->ptr;
...@@ -3896,7 +4566,13 @@ char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -3896,7 +4566,13 @@ char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function // Keep result of constant function
g->Xchk = bsp; 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; return (char*)bsp;
} // end of jbin_item_merge } // end of jbin_item_merge
...@@ -3905,6 +4581,150 @@ void jbin_item_merge_deinit(UDF_INIT* initid) ...@@ -3905,6 +4581,150 @@ void jbin_item_merge_deinit(UDF_INIT* initid)
JsonFreeMem((PGLOBAL)initid->ptr); JsonFreeMem((PGLOBAL)initid->ptr);
} // end of jbin_item_merge_deinit } // 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)
{
int w;
my_bool b = true;
PBSON bsp = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
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 (!CheckMemory(g, initid, args, 1, false)) {
char *p, *path;
PJSON jsp;
PJSNX jsx;
PJVAL jvp;
if (!g->Xchk) {
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
} 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(g, args, i);
path = MakePSZ(g, args, i+1);
if (jsx->SetJpath(g, path, false)) {
PUSH_WARNING(g->Message);
*is_null = 1;
return NULL;
} // endif SetJpath
if (w) {
jsx->ReadValue(g);
b = jsx->GetValue()->IsNull();
b = (w == 1) ? b : !b;
} // endif w
if (b && jsx->WriteValue(g, jvp))
PUSH_WARNING(g->Message);
} // endfor i
if ((bsp = JbinAlloc(g, args, initid->max_length, jsp)))
strcat(bsp->Msg, " item");
else
*error = 1;
if (initid->const_item)
// Keep result of constant function
g->Activityp = (PACTIVITY)bsp;
} // endif CheckMemory
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. */ /* Returns a json file as a json item. */
/*********************************************************************************/ /*********************************************************************************/
...@@ -3976,10 +4796,14 @@ char *jbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result, ...@@ -3976,10 +4796,14 @@ char *jbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
else if (pretty == 3) else if (pretty == 3)
pretty = pty; pretty = pty;
bsp = JbinAlloc(g, args, len, jsp); if ((bsp = JbinAlloc(g, args, len, jsp))) {
strcat(bsp->Msg, " file"); strcat(bsp->Msg, " file");
bsp->Filename = fn; bsp->Filename = fn;
bsp->Pretty = pretty; bsp->Pretty = pretty;
} else {
*error = 1;
goto fin;
} // endif bsp
// Check whether a path was specified // Check whether a path was specified
if (CheckPath(g, args, jsp, jvp, 1)) { if (CheckPath(g, args, jsp, jvp, 1)) {
......
...@@ -61,6 +61,10 @@ extern "C" { ...@@ -61,6 +61,10 @@ extern "C" {
DllExport char *json_object_nonull(UDF_EXEC_ARGS); DllExport char *json_object_nonull(UDF_EXEC_ARGS);
DllExport void json_object_nonull_deinit(UDF_INIT*); DllExport void json_object_nonull_deinit(UDF_INIT*);
DllExport my_bool json_object_key_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_object_key(UDF_EXEC_ARGS);
DllExport void json_object_key_deinit(UDF_INIT*);
DllExport my_bool json_object_add_init(UDF_INIT*, UDF_ARGS*, char*); DllExport my_bool json_object_add_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_object_add(UDF_EXEC_ARGS); DllExport char *json_object_add(UDF_EXEC_ARGS);
DllExport void json_object_add_deinit(UDF_INIT*); DllExport void json_object_add_deinit(UDF_INIT*);
...@@ -105,6 +109,10 @@ extern "C" { ...@@ -105,6 +109,10 @@ extern "C" {
DllExport double jsonget_real(UDF_INIT*, UDF_ARGS*, char*, char*); DllExport double jsonget_real(UDF_INIT*, UDF_ARGS*, char*, char*);
DllExport void jsonget_real_deinit(UDF_INIT*); DllExport void jsonget_real_deinit(UDF_INIT*);
DllExport my_bool jsoncontains_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport long long jsoncontains(UDF_EXEC_ARGS);
DllExport void jsoncontains_deinit(UDF_INIT*);
DllExport my_bool jsonlocate_init(UDF_INIT*, UDF_ARGS*, char*); DllExport my_bool jsonlocate_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jsonlocate(UDF_EXEC_ARGS); DllExport char *jsonlocate(UDF_EXEC_ARGS);
DllExport void jsonlocate_deinit(UDF_INIT*); DllExport void jsonlocate_deinit(UDF_INIT*);
...@@ -113,6 +121,22 @@ extern "C" { ...@@ -113,6 +121,22 @@ extern "C" {
DllExport char *json_locate_all(UDF_EXEC_ARGS); DllExport char *json_locate_all(UDF_EXEC_ARGS);
DllExport void json_locate_all_deinit(UDF_INIT*); DllExport void json_locate_all_deinit(UDF_INIT*);
DllExport my_bool jsoncontains_path_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport long long jsoncontains_path(UDF_EXEC_ARGS);
DllExport void jsoncontains_path_deinit(UDF_INIT*);
DllExport my_bool json_set_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_set_item(UDF_EXEC_ARGS);
DllExport void json_set_item_deinit(UDF_INIT*);
DllExport my_bool json_insert_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_insert_item(UDF_EXEC_ARGS);
DllExport void json_insert_item_deinit(UDF_INIT*);
DllExport my_bool json_update_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *json_update_item(UDF_EXEC_ARGS);
DllExport void json_update_item_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*);
...@@ -145,6 +169,10 @@ extern "C" { ...@@ -145,6 +169,10 @@ extern "C" {
DllExport char *jbin_object_nonull(UDF_EXEC_ARGS); DllExport char *jbin_object_nonull(UDF_EXEC_ARGS);
DllExport void jbin_object_nonull_deinit(UDF_INIT*); DllExport void jbin_object_nonull_deinit(UDF_INIT*);
DllExport my_bool jbin_object_key_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_object_key(UDF_EXEC_ARGS);
DllExport void jbin_object_key_deinit(UDF_INIT*);
DllExport my_bool jbin_object_add_init(UDF_INIT*, UDF_ARGS*, char*); DllExport my_bool jbin_object_add_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_object_add(UDF_EXEC_ARGS); DllExport char *jbin_object_add(UDF_EXEC_ARGS);
DllExport void jbin_object_add_deinit(UDF_INIT*); DllExport void jbin_object_add_deinit(UDF_INIT*);
...@@ -165,6 +193,18 @@ extern "C" { ...@@ -165,6 +193,18 @@ extern "C" {
DllExport char *jbin_item_merge(UDF_EXEC_ARGS); DllExport char *jbin_item_merge(UDF_EXEC_ARGS);
DllExport void jbin_item_merge_deinit(UDF_INIT*); DllExport void jbin_item_merge_deinit(UDF_INIT*);
DllExport my_bool jbin_set_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_set_item(UDF_EXEC_ARGS);
DllExport void jbin_set_item_deinit(UDF_INIT*);
DllExport my_bool jbin_insert_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_insert_item(UDF_EXEC_ARGS);
DllExport void jbin_insert_item_deinit(UDF_INIT*);
DllExport my_bool jbin_update_item_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_update_item(UDF_EXEC_ARGS);
DllExport void jbin_update_item_deinit(UDF_INIT*);
DllExport my_bool jbin_file_init(UDF_INIT*, UDF_ARGS*, char*); DllExport my_bool jbin_file_init(UDF_INIT*, UDF_ARGS*, char*);
DllExport char *jbin_file(UDF_EXEC_ARGS); DllExport char *jbin_file(UDF_EXEC_ARGS);
DllExport void jbin_file_deinit(UDF_INIT*); DllExport void jbin_file_deinit(UDF_INIT*);
...@@ -189,7 +229,7 @@ typedef struct _jpn { ...@@ -189,7 +229,7 @@ typedef struct _jpn {
class JSNX : public BLOCK { class JSNX : public BLOCK {
public: public:
// Constructors // Constructors
JSNX(PGLOBAL g, PJSON row, int type, int len = 64, int prec = 0); JSNX(PGLOBAL g, PJSON row, int type, int len = 64, int prec = 0, my_bool wr = false);
// Implementation // Implementation
int GetPrecision(void) {return Prec;} int GetPrecision(void) {return Prec;}
...@@ -201,6 +241,8 @@ public: ...@@ -201,6 +241,8 @@ public:
void ReadValue(PGLOBAL g); void ReadValue(PGLOBAL g);
PJVAL GetValue(PGLOBAL g, PJSON row, int i, my_bool b = true); PJVAL GetValue(PGLOBAL g, PJSON row, int i, my_bool b = true);
PJVAL GetJson(PGLOBAL g); PJVAL GetJson(PGLOBAL g);
my_bool CheckPath(PGLOBAL g);
my_bool WriteValue(PGLOBAL g, PJVAL jvalp);
char *Locate(PGLOBAL g, PJSON jsp, PJVAL jvp, int k = 1); char *Locate(PGLOBAL g, PJSON jsp, PJVAL jvp, int k = 1);
char *LocateAll(PGLOBAL g, PJSON jsp, PJVAL jvp, int mx = 10); char *LocateAll(PGLOBAL g, PJSON jsp, PJVAL jvp, int mx = 10);
...@@ -211,6 +253,7 @@ protected: ...@@ -211,6 +253,7 @@ protected:
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);
...@@ -244,4 +287,5 @@ protected: ...@@ -244,4 +287,5 @@ protected:
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 my_bool Found; // Item found by locate
my_bool Wr; // Write mode
}; // end of class JSNX }; // end of class JSNX
...@@ -334,8 +334,6 @@ JsonGet_Int(@j2,'qty') ...@@ -334,8 +334,6 @@ JsonGet_Int(@j2,'qty')
SELECT JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose'); SELECT JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose');
JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose') JsonGet_Int('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose')
NULL NULL
Warnings:
Warning 1105 Value not found
SELECT JsonGet_Int(JsonGet_String(Json_Array(Json_Array(45,28),Json_Array(36,45,89)),'[1]:*'),'[+]') sum; SELECT JsonGet_Int(JsonGet_String(Json_Array(Json_Array(45,28),Json_Array(36,45,89)),'[1]:*'),'[+]') sum;
sum sum
170 170
...@@ -381,8 +379,6 @@ JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','price ...@@ -381,8 +379,6 @@ JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','price
SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose'); SELECT JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose');
JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose') JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose')
NULL NULL
Warnings:
Warning 1105 Value not found
SELECT department, JsonGet_Real(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"),'salaries:[+]') Sumsal FROM t3 GROUP BY department; SELECT department, JsonGet_Real(Json_Object(department, Json_Array_Grp(salary) "Json_salaries"),'salaries:[+]') Sumsal FROM t3 GROUP BY department;
department Sumsal department Sumsal
0021 28500.000000000000000 0021 28500.000000000000000
......
...@@ -9,40 +9,40 @@ if (!$HA_CONNECT_SO) { ...@@ -9,40 +9,40 @@ if (!$HA_CONNECT_SO) {
--skip Needs a dynamically built ha_connect.so --skip Needs a dynamically built ha_connect.so
} }
CREATE FUNCTION json_array RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_array RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_array_add RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_array_add RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_array_add_values RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_array_add_values RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_array_delete RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_array_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_object RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_object RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_object_nonull RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_object_nonull RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_object_add RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_object_add RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_object_delete RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_object_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_object_list RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_object_list RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jsonvalue RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jsonvalue RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE AGGREGATE FUNCTION json_array_grp RETURNS STRING SONAME 'ha_connect'; --eval CREATE AGGREGATE FUNCTION json_array_grp RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE AGGREGATE FUNCTION json_object_grp RETURNS STRING SONAME 'ha_connect'; --eval CREATE AGGREGATE FUNCTION json_object_grp RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_item_merge RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_item_merge RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_get_item RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_get_item RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jsonget_string RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jsonget_string RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jsonget_int RETURNS INTEGER SONAME 'ha_connect'; --eval CREATE FUNCTION jsonget_int RETURNS INTEGER SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jsonget_real RETURNS REAL SONAME 'ha_connect'; --eval CREATE FUNCTION jsonget_real RETURNS REAL SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jsonlocate RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jsonlocate RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_locate_all RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_locate_all RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_file RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_file RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jfile_make RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jfile_make RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION json_serialize RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION json_serialize RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jbin_array RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jbin_array RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jbin_array_add_values RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jbin_array_add_values RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jbin_array_add RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jbin_array_add RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jbin_array_delete RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jbin_array_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jbin_object RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jbin_object RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jbin_object_nonull RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jbin_object_nonull RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jbin_object_add RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jbin_object_add RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jbin_object_delete RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jbin_object_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jbin_object_list RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jbin_object_list RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jbin_get_item RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jbin_get_item RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jbin_item_merge RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jbin_item_merge RETURNS STRING SONAME '$HA_CONNECT_SO';
CREATE FUNCTION jbin_file RETURNS STRING SONAME 'ha_connect'; --eval CREATE FUNCTION jbin_file RETURNS STRING SONAME '$HA_CONNECT_SO';
--enable_query_log --enable_query_log
...@@ -578,7 +578,7 @@ PJSON TDBJSN::FindRow(PGLOBAL g) ...@@ -578,7 +578,7 @@ PJSON TDBJSN::FindRow(PGLOBAL g)
} // end of FindRow } // end of FindRow
/***********************************************************************/ /***********************************************************************/
/* OpenDB: Data Base open routine for JSN access method. */ /* OpenDB: Data Base open routine for JSN access method. */
/***********************************************************************/ /***********************************************************************/
bool TDBJSN::OpenDB(PGLOBAL g) bool TDBJSN::OpenDB(PGLOBAL g)
{ {
...@@ -1107,7 +1107,7 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i) ...@@ -1107,7 +1107,7 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
} else switch (row->GetType()) { } else switch (row->GetType()) {
case TYPE_JOB: case TYPE_JOB:
if (!Nodes[i].Key) { if (!Nodes[i].Key) {
// Expected Array was not there // Expected Array was not there, wrap the value
if (i < Nod-1) if (i < Nod-1)
continue; continue;
else else
...@@ -1128,11 +1128,11 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i) ...@@ -1128,11 +1128,11 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
else else
return CalculateArray(g, arp, i); return CalculateArray(g, arp, i);
} else if (i < Nod-1) { } else {
strcpy(g->Message, "Unexpected array"); // Unexpected array, unwrap it as [0]
val = NULL; // Not an expected array val = arp->GetValue(0);
} else i--;
val = arp->GetValue(0); } // endif's
break; break;
case TYPE_JVAL: case TYPE_JVAL:
...@@ -1275,30 +1275,31 @@ PJSON JSONCOL::GetRow(PGLOBAL g) ...@@ -1275,30 +1275,31 @@ PJSON JSONCOL::GetRow(PGLOBAL g)
PJAR arp; PJAR arp;
PJSON nwr, row = Tjp->Row; PJSON nwr, row = Tjp->Row;
for (int i = 0; i < Nod-1 && row; i++) { for (int i = 0; i < Nod && row; i++) {
if (Nodes[i+1].Op == OP_XX) if (Nodes[i+1].Op == OP_XX)
break; break;
else switch (row->GetType()) { else switch (row->GetType()) {
case TYPE_JOB: case TYPE_JOB:
if (!Nodes[i].Key) if (!Nodes[i].Key)
// Expected Array was not there // Expected Array was not there, wrap the value
continue; continue;
val = ((PJOB)row)->GetValue(Nodes[i].Key); val = ((PJOB)row)->GetValue(Nodes[i].Key);
break; break;
case TYPE_JAR: case TYPE_JAR:
if (!Nodes[i].Key) { arp = (PJAR)row;
arp = (PJAR)row;
if (!Nodes[i].Key) {
if (Nodes[i].Op == OP_EQ) if (Nodes[i].Op == OP_EQ)
val = arp->GetValue(Nodes[i].Rank); val = arp->GetValue(Nodes[i].Rank);
else else
val = arp->GetValue(Nodes[i].Rx); val = arp->GetValue(Nodes[i].Rx);
} else { } else {
strcpy(g->Message, "Unexpected array"); // Unexpected array, unwrap it as [0]
val = NULL; // Not an expected array val = arp->GetValue(0);
} // endif Nodes i--;
} // endif Nodes
break; break;
case TYPE_JVAL: case TYPE_JVAL:
...@@ -1370,7 +1371,6 @@ void JSONCOL::WriteColumn(PGLOBAL g) ...@@ -1370,7 +1371,6 @@ void JSONCOL::WriteColumn(PGLOBAL g)
PJAR arp = NULL; PJAR arp = NULL;
PJVAL jvp = NULL; PJVAL jvp = NULL;
PJSON jsp, row = GetRow(g); PJSON jsp, row = GetRow(g);
JTYP type = row->GetType();
switch (row->GetType()) { switch (row->GetType()) {
case TYPE_JOB: objp = (PJOB)row; break; case TYPE_JOB: objp = (PJOB)row; break;
......
...@@ -2440,7 +2440,7 @@ void DTVAL::SetTimeShift(void) ...@@ -2440,7 +2440,7 @@ void DTVAL::SetTimeShift(void)
} // end of SetTimeShift } // end of SetTimeShift
#if defined(connect_EXPORTS) //#if defined(connect_EXPORTS)
// Added by Alexander Barkov // Added by Alexander Barkov
static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime) static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime)
{ {
...@@ -2462,9 +2462,9 @@ static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm) ...@@ -2462,9 +2462,9 @@ static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm)
TIME_to_localtime(tm, &ltime); TIME_to_localtime(tm, &ltime);
return tm; return tm;
} // end of gmtime_mysql } // end of gmtime_mysql
#else //#else
#define gmtime_mysql(T,B) gmtime((const time_t *)T) //#define gmtime_mysql(T,B) gmtime((const time_t *)T)
#endif //#endif
/***********************************************************************/ /***********************************************************************/
/* GetGmTime: returns a pointer to a static tm structure obtained */ /* GetGmTime: returns a pointer to a static tm structure obtained */
...@@ -2493,7 +2493,7 @@ struct tm *DTVAL::GetGmTime(struct tm *tm_buffer) ...@@ -2493,7 +2493,7 @@ struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
return datm; return datm;
} // end of GetGmTime } // end of GetGmTime
#if defined(connect_EXPORTS) //#if defined(connect_EXPORTS)
// Added by Alexander Barkov // Added by Alexander Barkov
static time_t mktime_mysql(struct tm *ptm) static time_t mktime_mysql(struct tm *ptm)
{ {
...@@ -2504,9 +2504,9 @@ static time_t mktime_mysql(struct tm *ptm) ...@@ -2504,9 +2504,9 @@ static time_t mktime_mysql(struct tm *ptm)
time_t t= TIME_to_timestamp(current_thd, &ltime, &error_code); time_t t= TIME_to_timestamp(current_thd, &ltime, &error_code);
return error_code ? (time_t) -1 : t; return error_code ? (time_t) -1 : t;
} }
#else //#else
#define mktime_mysql mktime //#define mktime_mysql mktime
#endif //#endif
/***********************************************************************/ /***********************************************************************/
/* MakeTime: calculates a date value from a tm structures using the */ /* MakeTime: calculates a date value from a tm structures using the */
......
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