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 @@
#define JSONMAX 10 // JSON Default max grp size
extern "C" {
char version[]= "Version 1.04.0003 October 25, 2015";
char version[]= "Version 1.04.0005 November 20, 2015";
#if defined(__WIN__)
char compver[]= "Version 1.04.0003 " __DATE__ " " __TIME__;
char compver[]= "Version 1.04.0005 " __DATE__ " " __TIME__;
char slash= '\\';
#else // !__WIN__
char slash= '/';
......@@ -6274,10 +6274,6 @@ bool ha_connect::FileExists(const char *fn, bool bf)
int n;
struct stat info;
if (check_access(ha_thd(), FILE_ACL, table->s->db.str,
NULL, NULL, 0, 0))
return true;
#if defined(__WIN__)
s= "\\";
#else // !__WIN__
......
......@@ -1282,6 +1282,18 @@ PSZ JVALUE::GetText(PGLOBAL g, PSZ text)
return text;
} // 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. */
/***********************************************************************/
......
......@@ -271,8 +271,8 @@ class JVALUE : public JSON {
virtual double GetFloat(void);
virtual PSZ GetString(void);
virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual void SetValue(PVAL valp) {Value = valp; Jsp = NULL;}
virtual void SetValue(PJSON jsp) {Jsp = jsp; Value = NULL;}
virtual void SetValue(PJSON jsp);
virtual void SetValue(PVAL valp) { Value = valp; Jsp = NULL; }
virtual void SetString(PGLOBAL g, PSZ s, short c = 0);
virtual void SetInteger(PGLOBAL g, int n);
virtual void SetBigint(PGLOBAL g, longlong ll);
......
......@@ -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,7 @@ JSNX::JSNX(PGLOBAL g, PJSON row, int type, int len, int prec)
Xpd = false;
Parsed = false;
Found = false;
Wr = wr;
} // end of JSNX constructor
/*********************************************************************************/
......@@ -85,6 +86,8 @@ my_bool JSNX::SetJpath(PGLOBAL g, char *path, my_bool jb)
Jpath = path;
// Parse the json path
Parsed = false;
Nod = 0;
return ParseJpath(g);
} // end of SetJpath
......@@ -117,7 +120,11 @@ 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 (b) {
// Return 1st value (B is the index base)
jnp->Rank = B;
jnp->Op = OP_LE;
......@@ -388,11 +395,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,7 +411,9 @@ 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
......@@ -502,6 +511,163 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
return vp;
} // 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: */
/*********************************************************************************/
......@@ -824,8 +990,9 @@ 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;
......@@ -834,6 +1001,9 @@ static PBSON JbinAlloc(PGLOBAL g, UDF_ARGS *args, ulong len, PJSON jsp)
bsp->Changed = false;
bsp->Top = bsp->Jsp = jsp;
bsp->Bsp = (IsJson(args, 0) == 3) ? (PBSON)args->args[0] : NULL;
} else
PUSH_WARNING(g->Message);
return bsp;
} /* end of JbinAlloc */
......@@ -983,6 +1153,9 @@ 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;
......@@ -1793,7 +1966,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)
{
......@@ -1837,7 +2010,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)
......@@ -1883,6 +2056,55 @@ void json_object_nonull_deinit(UDF_INIT* initid)
JsonFreeMem((PGLOBAL)initid->ptr);
} // 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. */
/*********************************************************************************/
......@@ -2379,10 +2601,9 @@ char *json_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
char *p, *path;
PJSON jsp;
PJSNX jsx;
PJVAL jvp;
if (!g->Xchk) {
jvp = MakeValue(g, args, 0);
PJVAL jvp = MakeValue(g, args, 0);
if ((p = jvp->GetString())) {
if (!(jsp = ParseJson(g, p, strlen(p)))) {
......@@ -2647,7 +2868,7 @@ long long jsonget_int(UDF_INIT *initid, UDF_ARGS *args,
jsx->ReadValue(g);
if (jsx->GetValue()->IsNull()) {
PUSH_WARNING("Value not found");
// PUSH_WARNING("Value not found");
*is_null = 1;
return 0;
} // endif IsNull
......@@ -2763,7 +2984,7 @@ double jsonget_real(UDF_INIT *initid, UDF_ARGS *args,
jsx->ReadValue(g);
if (jsx->GetValue()->IsNull()) {
PUSH_WARNING("Value not found");
// PUSH_WARNING("Value not found");
*is_null = 1;
return 0.0;
} // endif IsNull
......@@ -3047,77 +3268,417 @@ void json_locate_all_deinit(UDF_INIT* initid)
} // 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) {
strcpy(message, "This function only accepts 1 to 4 arguments");
if (args->arg_count < 2) {
strcpy(message, "At least 2 arguments required");
return true;
} else if (!args->args[0] || args->arg_type[0] != STRING_RESULT) {
strcpy(message, "First argument must be a constant string (file name)");
} else if (!n && args->arg_type[0] != STRING_RESULT) {
strcpy(message, "First argument must be a json item");
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);
} else if (args->arg_count > 2 && args->arg_type[2] != INT_RESULT) {
strcpy(message, "Third argument is not an integer (index)");
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];
} 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)");
} // endfor i
} // endif's
initid->maybe_null = 1;
CalcLen(args, false, reslen, memlen);
fl = GetFileLength(args->args[0]);
reslen += fl;
memlen += more;
if (initid->const_item)
more += fl;
if (IsJson(args, 0) != 3)
memlen += 1000; // TODO: calculate this
if (args->arg_count > 1)
more += fl * M;
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;
return JsonInit(initid, args, message, false, reslen, memlen);
} // end of json_file_init
char *json_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
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 *str, *fn;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->N) {
str = (char*)g->Xchk;
goto fin;
if (!g->Activityp) {
*is_null = 1;
return 0LL;
} else
return *(long long*)g->Activityp;
} 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;
if (!CheckMemory(g, initid, args, 1, false)) {
char *p, *path;
long long n;
PJSON jsp;
PJVAL jvp = NULL;
PJSNX jsx;
PJVAL jvp;
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;
if (!g->Xchk) {
jvp = MakeValue(g, args, 0);
/*******************************************************************************/
/* Parse the json file and allocate its tree structure. */
/*******************************************************************************/
if (!(jsp = ParseJsonFile(g, fn, &pty, len))) {
if ((p = jvp->GetString())) {
if (!(jsp = ParseJson(g, p, strlen(p)))) {
PUSH_WARNING(g->Message);
str = NULL;
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
......@@ -3283,11 +3844,11 @@ 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;
......@@ -3300,18 +3861,24 @@ char *jbin_array(UDF_INIT *initid, UDF_ARGS *args, char *result,
arp->AddValue(g, MakeValue(g, args, i));
arp->InitArray(g);
bsp = JbinAlloc(g, args, initid->max_length, arp);
if ((bsp = JbinAlloc(g, args, initid->max_length, arp)))
strcat(bsp->Msg, " array");
} else {
bsp = JbinAlloc(g, args, initid->max_length, NULL);
} else
if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
strncpy(bsp->Msg, g->Message, 139);
} // endif CheckMemory
// Keep result of constant function
g->Xchk = (initid->const_item) ? bsp : NULL;
} // endif bsp
if (!bsp) {
*is_null = 1;
*error = 1;
} else
*res_length = sizeof(BSON);
return (char*)bsp;
} // end of jbin_array
......@@ -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
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;
......@@ -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->InitArray(g);
bsp = JbinAlloc(g, args, initid->max_length, top);
if ((bsp = JbinAlloc(g, args, initid->max_length, top))) {
strcat(bsp->Msg, " array");
bsp->Jsp = arp;
} else {
bsp = JbinAlloc(g, args, initid->max_length, NULL);
} // endif bsp
} else
if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
strncpy(bsp->Msg, g->Message, BMX);
} // endif CheckMemory
// 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_array_add_values
......@@ -3390,7 +3964,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;
......@@ -3434,7 +4008,13 @@ char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
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 +4032,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;
......@@ -3494,7 +4074,13 @@ char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
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 +4090,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 +4101,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 +4113,23 @@ 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);
if ((bsp = JbinAlloc(g, args, initid->max_length, objp)))
strcat(bsp->Msg, " object");
} else {
bsp = JbinAlloc(g, args, initid->max_length, NULL);
} else
if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
strncpy(bsp->Msg, g->Message, BMX);
} // endif CheckMemory
// 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
......@@ -3548,18 +4139,18 @@ 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;
......@@ -3573,18 +4164,23 @@ 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);
if ((bsp = JbinAlloc(g, args, initid->max_length, objp)))
strcat(bsp->Msg, " object");
} else {
bsp = JbinAlloc(g, args, initid->max_length, NULL);
} else
if ((bsp = JbinAlloc(g, args, initid->max_length, NULL)))
strncpy(bsp->Msg, g->Message, BMX);
} // endif CheckMemory
// 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_nonull
......@@ -3593,6 +4189,60 @@ void jbin_object_nonull_deinit(UDF_INIT* initid)
JsonFreeMem((PGLOBAL)initid->ptr);
} // 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. */
/*********************************************************************************/
......@@ -3602,7 +4252,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;
......@@ -3642,7 +4292,13 @@ char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
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 +4316,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;
......@@ -3699,7 +4355,13 @@ char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
if (!bsp) {
*is_null = 1;
*error = 1;
*res_length = 0;
} else
*res_length = sizeof(BSON);
return (char*)bsp;
} // end of jbin_object_delete
......@@ -3747,14 +4409,19 @@ char *jbin_object_list(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif CheckMemory
bsp = JbinAlloc(g, args, initid->max_length, jarp);
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
if (!bsp) {
*is_null = 1;
*error = 1;
} else
*res_length = sizeof(BSON);
return (char*)bsp;
} // end of jbin_object_list
......@@ -3772,7 +4439,7 @@ 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;
PBSON bsp = NULL;
......@@ -3821,10 +4488,13 @@ char *jbin_get_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Get the json tree
jvp = jsx->GetValue(g, jsp, 0, false);
if (jvp->GetJsp()) {
bsp = JbinAlloc(g, args, initid->max_length, jvp->GetJsp());
if (jvp && jvp->GetJsp()) {
if ((bsp = JbinAlloc(g, args, initid->max_length, jvp->GetJsp())))
strcat(bsp->Msg, " item");
} // end of Jsp
else
*error = 1;
} // endif jvp
if (initid->const_item)
// Keep result of constant function
......@@ -3856,7 +4526,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;
......@@ -3896,7 +4566,13 @@ char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
// Keep result of constant function
g->Xchk = bsp;
if (!bsp) {
*is_null = 1;
*error = 1;
*res_length = 0;
} else
*res_length = sizeof(BSON);
return (char*)bsp;
} // end of jbin_item_merge
......@@ -3905,6 +4581,150 @@ void jbin_item_merge_deinit(UDF_INIT* initid)
JsonFreeMem((PGLOBAL)initid->ptr);
} // 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. */
/*********************************************************************************/
......@@ -3976,10 +4796,14 @@ char *jbin_file(UDF_INIT *initid, UDF_ARGS *args, char *result,
else if (pretty == 3)
pretty = pty;
bsp = JbinAlloc(g, args, len, jsp);
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)) {
......
......@@ -61,6 +61,10 @@ extern "C" {
DllExport char *json_object_nonull(UDF_EXEC_ARGS);
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 char *json_object_add(UDF_EXEC_ARGS);
DllExport void json_object_add_deinit(UDF_INIT*);
......@@ -105,6 +109,10 @@ extern "C" {
DllExport double jsonget_real(UDF_INIT*, UDF_ARGS*, char*, char*);
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 char *jsonlocate(UDF_EXEC_ARGS);
DllExport void jsonlocate_deinit(UDF_INIT*);
......@@ -113,6 +121,22 @@ extern "C" {
DllExport char *json_locate_all(UDF_EXEC_ARGS);
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 char *json_file(UDF_EXEC_ARGS);
DllExport void json_file_deinit(UDF_INIT*);
......@@ -145,6 +169,10 @@ extern "C" {
DllExport char *jbin_object_nonull(UDF_EXEC_ARGS);
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 char *jbin_object_add(UDF_EXEC_ARGS);
DllExport void jbin_object_add_deinit(UDF_INIT*);
......@@ -165,6 +193,18 @@ extern "C" {
DllExport char *jbin_item_merge(UDF_EXEC_ARGS);
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 char *jbin_file(UDF_EXEC_ARGS);
DllExport void jbin_file_deinit(UDF_INIT*);
......@@ -189,7 +229,7 @@ typedef struct _jpn {
class JSNX : public BLOCK {
public:
// 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
int GetPrecision(void) {return Prec;}
......@@ -201,6 +241,8 @@ public:
void ReadValue(PGLOBAL g);
PJVAL GetValue(PGLOBAL g, PJSON row, int i, my_bool b = true);
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 *LocateAll(PGLOBAL g, PJSON jsp, PJVAL jvp, int mx = 10);
......@@ -211,6 +253,7 @@ protected:
PVAL CalculateArray(PGLOBAL g, PJAR arp, int n);
PVAL MakeJson(PGLOBAL g, PJSON jsp);
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n);
PJSON GetRow(PGLOBAL g);
my_bool LocateArray(PJAR jarp);
my_bool LocateObject(PJOB jobp);
my_bool LocateValue(PJVAL jvp);
......@@ -244,4 +287,5 @@ protected:
my_bool Xpd; // True for expandable column
my_bool Parsed; // True when parsed
my_bool Found; // Item found by locate
my_bool Wr; // Write mode
}; // end of class JSNX
......@@ -334,8 +334,6 @@ JsonGet_Int(@j2,'qty')
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')
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;
sum
170
......@@ -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');
JsonGet_Real('{"qty":56,"price":3.141600,"truc":"machin","garanty":null}','chose')
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;
department Sumsal
0021 28500.000000000000000
......
......@@ -9,40 +9,40 @@ if (!$HA_CONNECT_SO) {
--skip Needs a dynamically built ha_connect.so
}
CREATE FUNCTION json_array RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_array_add RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_array_add_values RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_array_delete RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_object RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_object_nonull RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_object_add RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_object_delete RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_object_list RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jsonvalue RETURNS STRING SONAME 'ha_connect';
CREATE AGGREGATE FUNCTION json_array_grp RETURNS STRING SONAME 'ha_connect';
CREATE AGGREGATE FUNCTION json_object_grp RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_item_merge RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_get_item RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jsonget_string RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jsonget_int RETURNS INTEGER SONAME 'ha_connect';
CREATE FUNCTION jsonget_real RETURNS REAL SONAME 'ha_connect';
CREATE FUNCTION jsonlocate RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_locate_all RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_file RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jfile_make RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION json_serialize RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_array RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_array_add_values RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_array_add RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_array_delete RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_object RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_object_nonull RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_object_add RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_object_delete RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_object_list RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_get_item RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_item_merge RETURNS STRING SONAME 'ha_connect';
CREATE FUNCTION jbin_file RETURNS STRING SONAME 'ha_connect';
--eval CREATE FUNCTION json_array RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_array_add RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_array_add_values RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_array_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_object RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_object_nonull RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_object_add RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_object_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_object_list RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jsonvalue RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE AGGREGATE FUNCTION json_array_grp RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE AGGREGATE FUNCTION json_object_grp RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_item_merge RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_get_item RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jsonget_string RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jsonget_int RETURNS INTEGER SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jsonget_real RETURNS REAL SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jsonlocate RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_locate_all RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_file RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jfile_make RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION json_serialize RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_array RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_array_add_values RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_array_add RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_array_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_object RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_object_nonull RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_object_add RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_object_delete RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_object_list RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_get_item RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_item_merge RETURNS STRING SONAME '$HA_CONNECT_SO';
--eval CREATE FUNCTION jbin_file RETURNS STRING SONAME '$HA_CONNECT_SO';
--enable_query_log
......@@ -1107,7 +1107,7 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
} else switch (row->GetType()) {
case TYPE_JOB:
if (!Nodes[i].Key) {
// Expected Array was not there
// Expected Array was not there, wrap the value
if (i < Nod-1)
continue;
else
......@@ -1128,11 +1128,11 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
else
return 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:
......@@ -1275,29 +1275,30 @@ PJSON JSONCOL::GetRow(PGLOBAL g)
PJAR arp;
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)
break;
else switch (row->GetType()) {
case TYPE_JOB:
if (!Nodes[i].Key)
// Expected Array was not there
// Expected Array was not there, wrap the value
continue;
val = ((PJOB)row)->GetValue(Nodes[i].Key);
break;
case TYPE_JAR:
if (!Nodes[i].Key) {
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 {
strcpy(g->Message, "Unexpected array");
val = NULL; // Not an expected array
// Unexpected array, unwrap it as [0]
val = arp->GetValue(0);
i--;
} // endif Nodes
break;
......@@ -1370,7 +1371,6 @@ void JSONCOL::WriteColumn(PGLOBAL g)
PJAR arp = NULL;
PJVAL jvp = NULL;
PJSON jsp, row = GetRow(g);
JTYP type = row->GetType();
switch (row->GetType()) {
case TYPE_JOB: objp = (PJOB)row; break;
......
......@@ -2440,7 +2440,7 @@ void DTVAL::SetTimeShift(void)
} // end of SetTimeShift
#if defined(connect_EXPORTS)
//#if defined(connect_EXPORTS)
// Added by Alexander Barkov
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)
TIME_to_localtime(tm, &ltime);
return tm;
} // end of gmtime_mysql
#else
#define gmtime_mysql(T,B) gmtime((const time_t *)T)
#endif
//#else
//#define gmtime_mysql(T,B) gmtime((const time_t *)T)
//#endif
/***********************************************************************/
/* GetGmTime: returns a pointer to a static tm structure obtained */
......@@ -2493,7 +2493,7 @@ struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
return datm;
} // end of GetGmTime
#if defined(connect_EXPORTS)
//#if defined(connect_EXPORTS)
// Added by Alexander Barkov
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);
return error_code ? (time_t) -1 : t;
}
#else
#define mktime_mysql mktime
#endif
//#else
//#define mktime_mysql mktime
//#endif
/***********************************************************************/
/* 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