diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2021-02-16 00:31:27 +0100 |
---|---|---|
committer | Daniel Black <daniel@mariadb.org> | 2021-04-08 19:43:25 +1000 |
commit | 5e13a8d7446601a5ff4aeb67cefabaf0597cb8b0 (patch) | |
tree | 04dbbe79583da079644ceab74fe38b67d310751d | |
parent | 39399ef63de8dacacccab23dbeda1d9eeafeec29 (diff) | |
download | mariadb-git-5e13a8d7446601a5ff4aeb67cefabaf0597cb8b0.tar.gz |
- Add new JPATH features
modified: storage/connect/bson.cpp
modified: storage/connect/bsonudf.cpp
modified: storage/connect/bsonudf.h
modified: storage/connect/json.cpp
modified: storage/connect/jsonudf.cpp
modified: storage/connect/jsonudf.h
modified: storage/connect/mysql-test/connect/r/json_udf.result
modified: storage/connect/tabbson.cpp
modified: storage/connect/tabjson.cpp
modified: storage/connect/tabjson.h
-rw-r--r-- | storage/connect/bson.cpp | 15 | ||||
-rw-r--r-- | storage/connect/bsonudf.cpp | 40 | ||||
-rw-r--r-- | storage/connect/bsonudf.h | 3 | ||||
-rw-r--r-- | storage/connect/json.cpp | 3 | ||||
-rw-r--r-- | storage/connect/jsonudf.cpp | 206 | ||||
-rw-r--r-- | storage/connect/jsonudf.h | 6 | ||||
-rw-r--r-- | storage/connect/mysql-test/connect/r/json_udf.result | 10 | ||||
-rw-r--r-- | storage/connect/tabbson.cpp | 2 | ||||
-rw-r--r-- | storage/connect/tabjson.cpp | 62 | ||||
-rw-r--r-- | storage/connect/tabjson.h | 5 |
10 files changed, 230 insertions, 122 deletions
diff --git a/storage/connect/bson.cpp b/storage/connect/bson.cpp index ca97f9be6be..a0a421657bd 100644 --- a/storage/connect/bson.cpp +++ b/storage/connect/bson.cpp @@ -1351,12 +1351,17 @@ PBVAL BJSON::NewVal(PVAL valp) /***********************************************************************/ /* Sub-allocate and initialize a BVAL from another BVAL. */ /***********************************************************************/ -PBVAL BJSON::DupVal(PBVAL bvlp) { - PBVAL bvp = NewVal(); +PBVAL BJSON::DupVal(PBVAL bvlp) +{ + if (bvlp) { + PBVAL bvp = NewVal(); + + *bvp = *bvlp; + bvp->Next = 0; + return bvp; + } else + return NULL; - *bvp = *bvlp; - bvp->Next = 0; - return bvp; } // end of DupVal /***********************************************************************/ diff --git a/storage/connect/bsonudf.cpp b/storage/connect/bsonudf.cpp index d43023fdd29..a56db4d731b 100644 --- a/storage/connect/bsonudf.cpp +++ b/storage/connect/bsonudf.cpp @@ -117,7 +117,7 @@ BJNX::BJNX(PGLOBAL g) : BDOC(g) Jp = NULL; Nodes = NULL; Value = NULL; - MulVal = NULL; + //MulVal = NULL; Jpath = NULL; Buf_Type = TYPE_STRING; Long = len; @@ -148,7 +148,7 @@ BJNX::BJNX(PGLOBAL g, PBVAL row, int type, int len, int prec, my_bool wr) : BDOC Jp = NULL; Nodes = NULL; Value = AllocateValue(g, type, len, prec); - MulVal = NULL; + //MulVal = NULL; Jpath = NULL; Buf_Type = type; Long = len; @@ -273,40 +273,6 @@ my_bool BJNX::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm) return true; } // endif's -#if 0 - // For calculated arrays, a local Value must be used - switch (jnp->Op) { - case OP_NUM: - jnp->Valp = AllocateValue(g, TYPE_INT); - break; - case OP_ADD: - case OP_MULT: - case OP_SEP: - if (!IsTypeChar(Buf_Type)) - jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision()); - else - jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2); - - break; - case OP_MIN: - case OP_MAX: - jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision()); - break; - case OP_CNC: - if (IsTypeChar(Buf_Type)) - jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision()); - else - jnp->Valp = AllocateValue(g, TYPE_STRING, 512); - - break; - default: - break; - } // endswitch Op - - if (jnp->Valp) - MulVal = AllocateValue(g, jnp->Valp); -#endif // 0 - return false; } // end of SetArrayOptions @@ -452,6 +418,8 @@ PBVAL BJNX::MakeJson(PGLOBAL g, PBVAL bvp, int n) { PBVAL vlp, jvp = bvp; + Jb = false; + if (n < Nod -1) { if (bvp->Type == TYPE_JAR) { int ars = GetArraySize(bvp); diff --git a/storage/connect/bsonudf.h b/storage/connect/bsonudf.h index bbfd1ceed80..0fe3715617e 100644 --- a/storage/connect/bsonudf.h +++ b/storage/connect/bsonudf.h @@ -41,7 +41,6 @@ typedef struct _jnode { PSZ Key; // The key used for object OPVAL Op; // Operator used for this node PVAL CncVal; // To cont value used for OP_CNC - PVAL Valp; // The internal array VALUE int Rank; // The rank in array int Rx; // Read row number int Nx; // Next to read row number @@ -153,7 +152,7 @@ protected: JOUTSTR *Jp; JNODE *Nodes; // The intermediate objects PVAL Value; - PVAL MulVal; // To value used by multiple column + //PVAL MulVal; // To value used by multiple column char *Jpath; // The json path int Buf_Type; int Long; diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index ac5f5a122cc..f65294429db 100644 --- a/storage/connect/json.cpp +++ b/storage/connect/json.cpp @@ -54,6 +54,7 @@ char *GetExceptionDesc(PGLOBAL g, unsigned int e); #endif // SE_CATCH char *GetJsonNull(void); +int GetDefaultPrec(void); /***********************************************************************/ /* IsNum: check whether this string is all digits. */ @@ -1762,7 +1763,7 @@ void JVALUE::SetBigint(PGLOBAL g, long long ll) void JVALUE::SetFloat(PGLOBAL g, double f) { F = f; - Nd = 6; + Nd = GetDefaultPrec(); DataType = TYPE_DBL; } // end of SetFloat diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index abc70a0f93a..7db01af2f2b 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -72,7 +72,7 @@ JSNX::JSNX(PGLOBAL g, PJSON row, int type, int len, int prec, my_bool wr) Jp = NULL; Nodes = NULL; Value = AllocateValue(g, type, len, prec); - MulVal = NULL; + //MulVal = NULL; Jpath = NULL; Buf_Type = type; Long = len; @@ -198,38 +198,6 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) return true; } // endif's - // For calculated arrays, a local Value must be used - switch (jnp->Op) { - case OP_NUM: - jnp->Valp = AllocateValue(g, TYPE_INT); - break; - case OP_ADD: - case OP_MULT: - case OP_SEP: - if (!IsTypeChar(Buf_Type)) - jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision()); - else - jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2); - - break; - case OP_MIN: - case OP_MAX: - jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision()); - break; - case OP_CNC: - if (IsTypeChar(Buf_Type)) - jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision()); - else - jnp->Valp = AllocateValue(g, TYPE_STRING, 512); - - break; - default: - break; - } // endswitch Op - - if (jnp->Valp) - MulVal = AllocateValue(g, jnp->Valp); - return false; } // end of SetArrayOptions @@ -312,7 +280,7 @@ my_bool JSNX::ParseJpath(PGLOBAL g) } // endfor i, p Nod = i; - MulVal = AllocateValue(g, Value); + //MulVal = AllocateValue(g, Value); if (trace(1)) for (i = 0; i < Nod; i++) @@ -324,23 +292,6 @@ my_bool JSNX::ParseJpath(PGLOBAL g) } // end of ParseJpath /*********************************************************************************/ -/* MakeJson: Serialize the json item and set value to it. */ -/*********************************************************************************/ -PVAL JSNX::MakeJson(PGLOBAL g, PJSON jsp) -{ - if (Value->IsTypeNum()) { - strcpy(g->Message, "Cannot make Json for a numeric value"); - Value->Reset(); - } else if (jsp->GetType() != TYPE_JAR && jsp->GetType() != TYPE_JOB) { - strcpy(g->Message, "Target is not an array or object"); - Value->Reset(); - } else - Value->SetValue_psz(Serialize(g, jsp, NULL, 0)); - - return Value; -} // end of MakeJson - -/*********************************************************************************/ /* SetValue: Set a value from a JVALUE contains. */ /*********************************************************************************/ void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val) @@ -350,6 +301,7 @@ void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val) if (Jb) { vp->SetValue_psz(Serialize(g, val->GetJsp(), NULL, 0)); + Jb = false; } else switch (val->GetValType()) { case TYPE_DTM: case TYPE_STRG: @@ -395,6 +347,52 @@ void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val) } // end of SetJsonValue /*********************************************************************************/ +/* MakeJson: Serialize the json item and set value to it. */ +/*********************************************************************************/ +PJVAL JSNX::MakeJson(PGLOBAL g, PJSON jsp, int n) +{ + Jb = false; + + if (Value->IsTypeNum()) { + strcpy(g->Message, "Cannot make Json for a numeric value"); + return NULL; + } else if (jsp->GetType() != TYPE_JAR && jsp->GetType() != TYPE_JOB) { + strcpy(g->Message, "Target is not an array or object"); + return NULL; + } else if (n < Nod -1) { + if (jsp->GetType() == TYPE_JAR) { + int ars = jsp->GetSize(false); + PJNODE jnp = &Nodes[n]; + PJAR jarp = new(g) JARRAY; + + jnp->Op = OP_EQ; + + for (jnp->Rank = 0; jnp->Rank < ars; jnp->Rank++) + jarp->AddArrayValue(g, GetRowValue(g, jsp, n)); + + jarp->InitArray(g); + jnp->Op = OP_XX; + jnp->Rank = 0; + jsp = jarp; + } else if(jsp->GetType() == TYPE_JOB) { + PJSON jp; + PJOB jobp = new(g) JOBJECT; + + for (PJPR prp = ((PJOB)jsp)->GetFirst(); prp; prp = prp->Next) { + jp = (prp->Val->DataType == TYPE_JSON) ? prp->Val->Jsp : prp->Val; + jobp->SetKeyValue(g, GetRowValue(g, jp, n + 1), prp->Key); + } // endfor prp + + jsp = jobp; + } // endif Type + + } // endif + + Jb = true; + return new(g) JVALUE(jsp); +} // end of MakeJson + +/*********************************************************************************/ /* GetJson: */ /*********************************************************************************/ PJVAL JSNX::GetJson(PGLOBAL g) @@ -437,8 +435,7 @@ PJVAL JSNX::GetRowValue(PGLOBAL g, PJSON row, int i, my_bool b) val = new(g) JVALUE(g, Value); return val; } else if (Nodes[i].Op == OP_XX) { - Jb = b; - return new(g)JVALUE(row); + return MakeJson(g, row, i); } else switch (row->GetType()) { case TYPE_JOB: if (!Nodes[i].Key) { @@ -505,6 +502,88 @@ PVAL JSNX::ExpandArray(PGLOBAL g, PJAR arp, int n) } // end of ExpandArray /*********************************************************************************/ +/* Get the value used for calculating the array. */ +/*********************************************************************************/ +PVAL JSNX::GetCalcValue(PGLOBAL g, PJAR jap, int n) +{ + // For calculated arrays, a local Value must be used + int lng = 0; + short type, prec = 0; + bool b = n < Nod - 1; + PVAL valp; + PJVAL vlp, vp; + OPVAL op = Nodes[n].Op; + + switch (op) { + case OP_NUM: + type = TYPE_INT; + break; + case OP_ADD: + case OP_MULT: + if (!IsTypeNum(Buf_Type)) { + type = TYPE_INT; + prec = 0; + + for (vlp = jap->GetArrayValue(0); vlp; vlp = vlp->Next) { + vp = (b && vlp->GetJsp()) ? GetRowValue(g, vlp, n + 1) : vlp; + + switch (vp->DataType) { + case TYPE_BINT: + if (type == TYPE_INT) + type = TYPE_BIGINT; + + break; + case TYPE_DBL: + case TYPE_FLOAT: + type = TYPE_DOUBLE; + prec = MY_MAX(prec, vp->Nd); + break; + default: + break; + } // endswitch Type + + } // endfor vlp + + } else { + type = Buf_Type; + prec = GetPrecision(); + } // endif Buf_Type + + break; + case OP_SEP: + if (IsTypeChar(Buf_Type)) { + type = TYPE_DOUBLE; + prec = 2; + } else { + type = Buf_Type; + prec = GetPrecision(); + } // endif Buf_Type + + break; + case OP_MIN: + case OP_MAX: + type = Buf_Type; + lng = Long; + prec = GetPrecision(); + break; + case OP_CNC: + type = TYPE_STRING; + + if (IsTypeChar(Buf_Type)) { + lng = (Long) ? Long : 512; + prec = GetPrecision(); + } else + lng = 512; + + break; + default: + break; + } // endswitch Op + + return valp = AllocateValue(g, type, lng, prec); +} // end of GetCalcValue + +/*********************************************************************************/ /* CalculateArray: */ /*********************************************************************************/ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) @@ -512,7 +591,8 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) int i, ars = arp->size(), nv = 0; bool err; OPVAL op = Nodes[n].Op; - PVAL val[2], vp = Nodes[n].Valp; + PVAL val[2], vp = GetCalcValue(g, arp, n); + PVAL mulval = AllocateValue(g, vp); PJVAL jvrp, jvp; JVALUE jval; @@ -545,9 +625,9 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) SetJsonValue(g, vp, jvp); continue; } else - SetJsonValue(g, MulVal, jvp); + SetJsonValue(g, mulval, jvp); - if (!MulVal->IsNull()) { + if (!mulval->IsNull()) { switch (op) { case OP_CNC: if (Nodes[n].CncVal) { @@ -555,18 +635,18 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) err = vp->Compute(g, val, 1, op); } // endif CncVal - val[0] = MulVal; + val[0] = mulval; err = vp->Compute(g, val, 1, op); break; // case OP_NUM: case OP_SEP: - val[0] = Nodes[n].Valp; - val[1] = MulVal; + val[0] = vp; + val[1] = mulval; err = vp->Compute(g, val, 2, OP_ADD); break; default: - val[0] = Nodes[n].Valp; - val[1] = MulVal; + val[0] = vp; + val[1] = mulval; err = vp->Compute(g, val, 2, op); } // endswitch Op @@ -588,9 +668,9 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n) if (op == OP_SEP) { // Calculate average - MulVal->SetValue(nv); + mulval->SetValue(nv); val[0] = vp; - val[1] = MulVal; + val[1] = mulval; if (vp->Compute(g, val, 2, OP_DIV)) vp->Reset(); diff --git a/storage/connect/jsonudf.h b/storage/connect/jsonudf.h index 689a02ebbc5..ada0dbcd96b 100644 --- a/storage/connect/jsonudf.h +++ b/storage/connect/jsonudf.h @@ -44,7 +44,6 @@ typedef struct _jnode { PSZ Key; // The key used for object OPVAL Op; // Operator used for this node PVAL CncVal; // To cont value used for OP_CNC - PVAL Valp; // The internal array VALUE int Rank; // The rank in array int Rx; // Read row number int Nx; // Next to read row number @@ -334,8 +333,9 @@ protected: my_bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm); PVAL GetColumnValue(PGLOBAL g, PJSON row, int i); PVAL ExpandArray(PGLOBAL g, PJAR arp, int n); + PVAL GetCalcValue(PGLOBAL g, PJAR bap, int n); PVAL CalculateArray(PGLOBAL g, PJAR arp, int n); - PVAL MakeJson(PGLOBAL g, PJSON jsp); + PJVAL MakeJson(PGLOBAL g, PJSON jsp, int i); void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val); PJSON GetRow(PGLOBAL g); my_bool CompareValues(PJVAL v1, PJVAL v2); @@ -358,7 +358,7 @@ protected: JOUTSTR *Jp; JNODE *Nodes; // The intermediate objects PVAL Value; - PVAL MulVal; // To value used by multiple column + //PVAL MulVal; // To value used by multiple column char *Jpath; // The json path int Buf_Type; int Long; diff --git a/storage/connect/mysql-test/connect/r/json_udf.result b/storage/connect/mysql-test/connect/r/json_udf.result index 8315fc3f3bf..e3ee84d9084 100644 --- a/storage/connect/mysql-test/connect/r/json_udf.result +++ b/storage/connect/mysql-test/connect/r/json_udf.result @@ -322,7 +322,7 @@ JsonGet_String(Json_Make_Array(45,28,36,45,89),'3') 45 SELECT JsonGet_String(Json_Make_Array(45,28,36,45,89),'["+"]') "list",'=' as "egal",JsonGet_String(Json_Make_Array(45,28,36,45,89),'[+]') "sum"; list egal sum -45+28+36+45+89 = 243.00 +45+28+36+45+89 = 243 SELECT JsonGet_String(Json_Make_Array(Json_Make_Array(45,28),Json_Make_Array(36,45,89)),'1.0'); JsonGet_String(Json_Make_Array(Json_Make_Array(45,28),Json_Make_Array(36,45,89)),'1.0') 36 @@ -349,10 +349,10 @@ Warnings: Warning 1105 SELECT department, JsonGet_String(Json_Make_Object(department, Json_Array_Grp(salary) "Json_salaries"),'salaries.[+]') Sumsal FROM t3 GROUP BY department; department Sumsal -0021 28500.00 -0318 72230.00 -0319 89800.95 -2452 45900.00 +0021 28500.000000 +0318 72230.000000 +0319 89800.950000 +2452 45900.000000 SELECT JsonGet_Int(@j1, '4'); JsonGet_Int(@j1, '4') 89 diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index db63b8e78db..bbc2c54c80f 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -881,7 +881,7 @@ PBVAL BCUTIL::GetRowValue(PGLOBAL g, PBVAL row, int i) } // endfor i return bvp; -} // end of GetColumnValue +} // end of GetRowValue /***********************************************************************/ /* GetColumnValue: */ diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index fb5a64c7d55..96aa5db683a 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -1610,7 +1610,7 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj) /***********************************************************************/ /* MakeJson: Serialize the json item and set value to it. */ /***********************************************************************/ -PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp) +PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp, int n) { if (Value->IsTypeNum()) { strcpy(g->Message, "Cannot make Json for a numeric column"); @@ -1621,6 +1621,7 @@ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp) } // endif Warned Value->Reset(); + return Value; #if 0 } else if (Value->GetType() == TYPE_BIN) { if ((unsigned)Value->GetClen() >= sizeof(BSON)) { @@ -1634,13 +1635,66 @@ PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp) Value->SetValue_char(NULL, 0); } // endif Clen #endif // 0 - } else - Value->SetValue_psz(Serialize(g, jsp, NULL, 0)); + } else if (n < Nod - 1) { + if (jsp->GetType() == TYPE_JAR) { + int ars = jsp->GetSize(false); + PJNODE jnp = &Nodes[n]; + PJAR jvp = new(g) JARRAY; + + for (jnp->Rank = 0; jnp->Rank < ars; jnp->Rank++) + jvp->AddArrayValue(g, GetRowValue(g, jsp, n)); + + jnp->Rank = 0; + jvp->InitArray(g); + jsp = jvp; + } else if (jsp->Type == TYPE_JOB) { + PJOB jvp = new(g) JOBJECT; + + for (PJPR prp = ((PJOB)jsp)->GetFirst(); prp; prp = prp->Next) + jvp->SetKeyValue(g, GetRowValue(g, prp->Val, n + 1), prp->Key); + jsp = jvp; + } // endif Type + + } // endif + + Value->SetValue_psz(Serialize(g, jsp, NULL, 0)); return Value; } // end of MakeJson /***********************************************************************/ +/* GetRowValue: */ +/***********************************************************************/ +PJVAL JSONCOL::GetRowValue(PGLOBAL g, PJSON row, int i) +{ + int n = Nod - 1; + PJVAL val = NULL; + + for (; i < Nod && row; i++) { + switch (row->GetType()) { + case TYPE_JOB: + val = (Nodes[i].Key) ? ((PJOB)row)->GetKeyValue(Nodes[i].Key) : NULL; + break; + case TYPE_JAR: + val = ((PJAR)row)->GetArrayValue(Nodes[i].Rank); + break; + case TYPE_JVAL: + val = (PJVAL)row; + break; + default: + sprintf(g->Message, "Invalid row JSON type %d", row->GetType()); + val = NULL; + } // endswitch Type + + if (i < Nod-1) + row = (val) ? val->GetJson() : NULL; + + } // endfor i + + return val; +} // end of GetRowValue + +/***********************************************************************/ /* SetValue: Set a value from a JVALUE contains. */ /***********************************************************************/ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL jvp) @@ -1740,7 +1794,7 @@ PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i) Value->SetValue(row->GetType() == TYPE_JAR ? ((PJAR)row)->size() : 1); return(Value); } else if (Nodes[i].Op == OP_XX) { - return MakeJson(G, row); + return MakeJson(G, row, i); } else switch (row->GetType()) { case TYPE_JOB: if (!Nodes[i].Key) { diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h index b47dc9b0665..147bef484a6 100644 --- a/storage/connect/tabjson.h +++ b/storage/connect/tabjson.h @@ -230,8 +230,9 @@ public: PVAL GetColumnValue(PGLOBAL g, PJSON row, int i); PVAL ExpandArray(PGLOBAL g, PJAR arp, int n); PVAL CalculateArray(PGLOBAL g, PJAR arp, int n); - PVAL MakeJson(PGLOBAL g, PJSON jsp); - void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val); + PVAL MakeJson(PGLOBAL g, PJSON jsp, int n); + PJVAL GetRowValue(PGLOBAL g, PJSON row, int i); + void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val); PJSON GetRow(PGLOBAL g); // Default constructor not to be used |