diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2015-01-30 10:57:00 +0100 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2015-01-30 10:57:00 +0100 |
commit | fd1ca70bb3710ae280bd11b3650820dd62002419 (patch) | |
tree | 4bf2d015e61dc83733c146a7cca4025ead296bde /storage/connect | |
parent | 9a2dc7dfed6b56c529b2de865a15929bee2eceaf (diff) | |
download | mariadb-git-fd1ca70bb3710ae280bd11b3650820dd62002419.tar.gz |
- Enhance JSON tables handling.
modified:
storage/connect/json.cpp
storage/connect/json.h
storage/connect/mysql-test/connect/r/json.result
storage/connect/mysql-test/connect/t/json.test
storage/connect/tabjson.cpp
storage/connect/tabjson.h
- Avoid crash when a partition table name pattern is ill formed
(such as using place holder %i instead of %s)
modified:
storage/connect/ha_connect.cc
Diffstat (limited to 'storage/connect')
-rw-r--r-- | storage/connect/ha_connect.cc | 6 | ||||
-rw-r--r-- | storage/connect/json.cpp | 8 | ||||
-rw-r--r-- | storage/connect/json.h | 3 | ||||
-rw-r--r-- | storage/connect/mysql-test/connect/r/json.result | 40 | ||||
-rw-r--r-- | storage/connect/mysql-test/connect/t/json.test | 4 | ||||
-rw-r--r-- | storage/connect/tabjson.cpp | 477 | ||||
-rw-r--r-- | storage/connect/tabjson.h | 20 |
7 files changed, 326 insertions, 232 deletions
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 5bc6f84a9df..2765a7315f5 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -997,8 +997,12 @@ char *ha_connect::GetRealString(const char *s) char *sv; if (IsPartitioned() && s) { - sv= (char*)PlugSubAlloc(xp->g, NULL, strlen(s) + strlen(partname)); +// sv= (char*)PlugSubAlloc(xp->g, NULL, strlen(s) + strlen(partname)); + // With wrong string pattern, the size of the constructed string + // can be more than strlen(s) + strlen(partname) + sv= (char*)PlugSubAlloc(xp->g, NULL, 0); sprintf(sv, s, partname); + PlugSubAlloc(xp->g, NULL, strlen(sv) + 1); } else sv= (char*)s; diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index c49678769b7..0d15c8eed21 100644 --- a/storage/connect/json.cpp +++ b/storage/connect/json.cpp @@ -576,9 +576,9 @@ bool SerializeObject(JOUT *js, PJOB jobp) else if (js->WriteChr(','))
return true;
- if (js->WriteChr('\"') ||
+ if (js->WriteChr('"') ||
js->WriteStr(pair->Key) ||
- js->WriteChr('\"') ||
+ js->WriteChr('"') ||
js->WriteChr(':') ||
SerializeValue(js, pair->Val))
return true;
@@ -725,13 +725,13 @@ bool JOUTFILE::Escape(const char *s) for (unsigned int i = 0; i < strlen(s); i++)
switch (s[i]) {
+ case '"': fputs("\\\"", Stream); break;
+ case '\\': fputs("\\\\", Stream); break;
case '\t': fputs("\\t", Stream); break;
case '\n': fputs("\\n", Stream); break;
case '\r': fputs("\\r", Stream); break;
case '\b': fputs("\\b", Stream); break;
case '\f': fputs("\\f", Stream); break;
- case '\\': fputs("\\\\", Stream); break;
- case '"': fputs("\\\"", Stream); break;
default:
fputc(s[i], Stream);
break;
diff --git a/storage/connect/json.h b/storage/connect/json.h index f0748108dd6..7f16ccf025a 100644 --- a/storage/connect/json.h +++ b/storage/connect/json.h @@ -18,7 +18,8 @@ enum JTYP {TYPE_STRG = 1, TYPE_BOOL = 4,
TYPE_INTG = 7,
TYPE_JSON = 12,
- TYPE_JAR, TYPE_JOB,
+ TYPE_JAR,
+ TYPE_JOB,
TYPE_JVAL};
class JOUT;
diff --git a/storage/connect/mysql-test/connect/r/json.result b/storage/connect/mysql-test/connect/r/json.result index 094bb669d18..e832685c855 100644 --- a/storage/connect/mysql-test/connect/r/json.result +++ b/storage/connect/mysql-test/connect/r/json.result @@ -89,8 +89,8 @@ ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher L UPDATE t1 SET AuthorFN = 'Philippe' WHERE AuthorLN = 'Knab'; SELECT * FROM t1 WHERE ISBN = '9782212090819'; ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year -9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999 -9782212090819 fr applications Philippe Knab Construire une application XML Eyrolles Paris 1999 +9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999 +9782212090819 fr applications François Knab Construire une application XML Eyrolles Paris 1999 # # To add an author a new table must be created # @@ -104,8 +104,8 @@ William J. Pardi INSERT INTO t2 VALUES('Charles','Dickens'); SELECT * FROM t1; ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year -9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999 -9782212090819 fr applications Philippe Knab Construire une application XML Eyrolles Paris 1999 +9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999 +9782212090819 fr applications François Knab Construire une application XML Eyrolles Paris 1999 9782840825685 fr applications William J. Pardi XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999 9782840825685 fr applications Charles Dickens XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999 DROP TABLE t1; @@ -127,11 +127,11 @@ line "SUBJECT": "applications", "AUTHOR": [ { - "FIRSTNAME": "Jean-Christophe", + "FIRSTNAME": "Philippe", "LASTNAME": "Bernadac" }, { - "FIRSTNAME": "Philippe", + "FIRSTNAME": "François", "LASTNAME": "Knab" } ], @@ -192,7 +192,7 @@ Janet 4 Car 17.00 Janet 5 Beer+Car+Beer+Food 57.00 DROP TABLE t1; # -# Cannot be fully expanded +# Now it can be fully expanded # CREATE TABLE t1 ( WHO CHAR(12), @@ -201,7 +201,31 @@ WHAT CHAR(32) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:WHAT', AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT') ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn'; SELECT * FROM t1; -ERROR HY000: Got error 174 'Cannot expand more than one array' from CONNECT +WHO WEEK WHAT AMOUNT +Joe 3 Beer 18.00 +Joe 3 Food 12.00 +Joe 3 Food 19.00 +Joe 3 Car 20.00 +Joe 4 Beer 19.00 +Joe 4 Beer 16.00 +Joe 4 Food 17.00 +Joe 4 Food 17.00 +Joe 4 Beer 14.00 +Joe 5 Beer 14.00 +Joe 5 Food 12.00 +Beth 3 Beer 16.00 +Beth 4 Food 17.00 +Beth 4 Beer 15.00 +Beth 5 Food 12.00 +Beth 5 Beer 20.00 +Janet 3 Car 19.00 +Janet 3 Food 18.00 +Janet 3 Beer 18.00 +Janet 4 Car 17.00 +Janet 5 Beer 14.00 +Janet 5 Car 12.00 +Janet 5 Beer 19.00 +Janet 5 Food 12.00 DROP TABLE t1; # # Expand expense in 3 one week tables diff --git a/storage/connect/mysql-test/connect/t/json.test b/storage/connect/mysql-test/connect/t/json.test index a7e630ed0cf..91cb6308557 100644 --- a/storage/connect/mysql-test/connect/t/json.test +++ b/storage/connect/mysql-test/connect/t/json.test @@ -128,7 +128,7 @@ SELECT * FROM t1; DROP TABLE t1;
--echo #
---echo # Cannot be fully expanded
+--echo # Now it can be fully expanded
--echo #
CREATE TABLE t1 (
WHO CHAR(12),
@@ -136,7 +136,7 @@ WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER', WHAT CHAR(32) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
---error ER_GET_ERRMSG
+#--error ER_GET_ERRMSG
SELECT * FROM t1;
DROP TABLE t1;
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index a22f490f398..f7723376598 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -119,12 +119,12 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp) Fpos = -1; Spos = N = 0; Limit = tdp->Limit; + NextSame = 0; + SameRow = 0; + Xval = -1; Pretty = tdp->Pretty; Strict = tdp->Strict; - NextSame = false; Comma = false; - SameRow = 0; - Xval = -1; } // end of TDBJSN standard constructor TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) @@ -137,12 +137,12 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp) Spos = tdbp->Spos; N = tdbp->N; Limit = tdbp->Limit; - Pretty = tdbp->Pretty; - Strict = tdbp->Strict; NextSame = tdbp->NextSame; - Comma = tdbp->Comma; SameRow = tdbp->SameRow; Xval = tdbp->Xval; + Pretty = tdbp->Pretty; + Strict = tdbp->Strict; + Comma = tdbp->Comma; } // end of TDBJSN copy constructor // Used for update @@ -221,14 +221,9 @@ bool TDBJSN::OpenDB(PGLOBAL g) /*******************************************************************/ /* Table already open replace it at its beginning. */ /*******************************************************************/ - for (PJCOL cp = (PJCOL)Columns; cp; cp = (PJCOL)cp->GetNext()) { - cp->Nx = 0; - cp->Arp = NULL; - } // endfor cp - Fpos= -1; Spos = 0; - NextSame = false; + NextSame = 0; SameRow = 0; } else { /*******************************************************************/ @@ -292,7 +287,8 @@ int TDBJSN::ReadDB(PGLOBAL g) N++; if (NextSame) { - SameRow++; + SameRow = NextSame; + NextSame = 0; return RC_OK; } else if ((rc = TDBDOS::ReadDB(g)) == RC_OK) if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) { @@ -333,21 +329,20 @@ int TDBJSN::ReadDB(PGLOBAL g) } // end of PrepareWriting -/* ----------------------------- JSNCOL ------------------------------- */ +/* ---------------------------- JSONCOL ------------------------------ */ /***********************************************************************/ -/* JSNCOL public constructor. */ +/* JSONCOL public constructor. */ /***********************************************************************/ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) : DOSCOL(g, cdp, tdbp, cprec, i, "DOS") { Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); - Arp = NULL; Jpath = cdp->GetFmt(); MulVal = NULL; Nodes = NULL; - Nod = Nx =0; - Ival = -1; + Nod = 0; + Xnod = -1; Xpd = false; Parsed = false; } // end of JSONCOL constructor @@ -359,13 +354,11 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp) { Tjp = col1->Tjp; - Arp = col1->Arp; Jpath = col1->Jpath; MulVal = col1->MulVal; Nodes = col1->Nodes; Nod = col1->Nod; - Ival = col1->Ival; - Nx = col1->Nx; + Xnod = col1->Xnod; Xpd = col1->Xpd; Parsed = col1->Parsed; } // end of JSONCOL copy constructor @@ -387,17 +380,16 @@ bool JSONCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) } // end of SetBuffer /***********************************************************************/ -/* Analyse array processing options. */ +/* Check whether this object is expanded. */ /***********************************************************************/ bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b) { - if (Tjp->Xcol && nm && !strcmp(nm, Tjp->Xcol) && - (Tjp->Xval < 0 || Tjp->Xval == i)) { + if ((Tjp->Xcol && nm && !strcmp(nm, Tjp->Xcol) && + (Tjp->Xval < 0 || Tjp->Xval == i)) || Xpd) { Xpd = true; // Expandable object Nodes[i].Op = OP_XX; - Tjp->Xval = i; } else if (b) { - strcpy(g->Message, "Cannot expand more than one array"); + strcpy(g->Message, "Cannot expand more than one branch"); return true; } // endif Xcol @@ -490,6 +482,38 @@ bool JSONCOL::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);
+
+ 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 @@ -507,8 +531,7 @@ bool JSONCOL::ParseJpath(PGLOBAL g) if (Parsed) return false; // Already done - - if (InitValue(g)) + else if (InitValue(g)) return true; else if (!Jpath) Jpath = Name; @@ -552,47 +575,223 @@ bool JSONCOL::ParseJpath(PGLOBAL g) void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n) { if (val) { - if (Nodes[n].Op == OP_NUM) - vp->SetValue(1); - else { - again: - switch (val->GetValType()) { - case TYPE_STRG: - case TYPE_INTG: - case TYPE_DBL: - vp->SetValue_pval(val->GetValue()); - break; - case TYPE_BOOL: - if (vp->IsTypeNum()) - vp->SetValue(val->GetInteger() ? 1 : 0); - else - vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false")); - + switch (val->GetValType()) { + case TYPE_STRG: + case TYPE_INTG: + case TYPE_DBL: + vp->SetValue_pval(val->GetValue()); + break; + case TYPE_BOOL: + if (vp->IsTypeNum()) + vp->SetValue(val->GetInteger() ? 1 : 0); + else + vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false")); + + break; + case TYPE_JAR: + SetJsonValue(g, vp, val->GetArray()->GetValue(0), n); + break; + case TYPE_JOB: +// if (!vp->IsTypeNum() || !Strict) { + vp->SetValue_psz(val->GetObject()->GetText(g)); break; - case TYPE_JAR: - val = val->GetArray()->GetValue(0); - goto again; - case TYPE_JOB: - if (!vp->IsTypeNum()) { - vp->SetValue_psz(val->GetObject()->GetText(g)); - break; - } // endif Type +// } // endif Type - default: - vp->Reset(); - } // endswitch Type - - } // endelse + default: + vp->Reset(); + } // endswitch Type } else vp->Reset(); } // end of SetJsonValue +/***********************************************************************/
+/* ReadColumn: */
+/***********************************************************************/
+void JSONCOL::ReadColumn(PGLOBAL g)
+ {
+ if (!Tjp->SameRow || Xnod >= Tjp->SameRow)
+ Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0));
+
+ } // end of ReadColumn
+
+/***********************************************************************/
+/* GetColumnValue: */
+/***********************************************************************/
+PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
+ {
+ int n = Nod - 1;
+ int nextsame = 0;
+ bool expd = false;
+ PJAR arp;
+ PJVAL val = NULL;
+
+//for (; i < Nod-1 && row; i++) {
+ for (; i < Nod && row; i++) {
+ if (Nodes[i].Op == OP_NUM) {
+ Value->SetValue(row->GetType() == TYPE_JAR ? row->size() : 1);
+ return(Value);
+ } else switch (row->GetType()) {
+ case TYPE_JOB:
+ if (!Nodes[i].Key) {
+ // Expected Array was not there
+ if (i < Nod-1)
+ continue;
+ else
+ val = new(g) JVALUE(row);
+
+ } else
+ val = ((PJOB)row)->GetValue(Nodes[i].Key);
+
+ break;
+ case TYPE_JAR:
+ arp = (PJAR)row;
+
+ if (!Nodes[i].Key) {
+ if (Nodes[i].Op != OP_NULL) {
+ if (Nodes[i].Rank) {
+ val = arp->GetValue(Nodes[i].Rank - 1);
+ } else if (Nodes[i].Op == OP_XX) {
+ return ExpandArray(g, arp, i);
+ } else
+ return CalculateArray(g, arp, i);
+
+ } else
+ val = NULL;
+
+ } else if (i < Nod-1) {
+ strcpy(g->Message, "Unexpected array");
+ val = NULL; // Not an expected array
+ } else
+ val = arp->GetValue(0);
+
+ break;
+ case TYPE_JVAL:
+ val = (PJVAL)row;
+ break;
+ default:
+ sprintf(g->Message, "Invalid row JSON type %d", row->GetType());
+ val = NULL;
+ } // endswitch Type
+
+ if (i < Nod-1)
+ row = (val) ? val->GetJson() : NULL;
+
+ } // endfor i
+
+ SetJsonValue(g, Value, val, n);
+ return Value;
+ } // end of GetColumnValue
+
+/***********************************************************************/
+/* ExpandArray: */
+/***********************************************************************/
+PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n)
+ {
+ int ars;
+ PJVAL jvp;
+ JVALUE jval;
+
+ ars = MY_MIN(Tjp->Limit, arp->size());
+ jvp = arp->GetValue(Nodes[n].Nx);
+
+ if (n < Nod - 1 && jvp->GetJson()) {
+ jval.SetValue(GetColumnValue(g, jvp->GetJson(), n + 1));
+ jvp = &jval;
+ } // endif n
+
+ if (n >= Tjp->NextSame) {
+ if (++Nodes[n].Nx == ars) {
+ Nodes[n].Nx = 0;
+ Xnod = 0;
+ } else
+ Xnod = n;
+
+ Tjp->NextSame = Xnod;
+ } // endif NextSame
+
+ SetJsonValue(g, Value, jvp, n);
+ return Value;
+ } // end of ExpandArray
+
+/***********************************************************************/
+/* CalculateArray: */
+/***********************************************************************/
+PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n)
+ {
+ int i, ars;
+ bool err;
+ OPVAL op = Nodes[n].Op;
+ PVAL val[2], vp = Nodes[n].Valp;
+ PJVAL jvp;
+ JVALUE jval;
+
+ vp->Reset();
+ ars = MY_MIN(Tjp->Limit, arp->size());
+
+ for (i = 0; i < ars; i++) {
+ jvp = arp->GetValue(i);
+
+ if (n < Nod - 1 && jvp->GetJson()) {
+ jval.SetValue(GetColumnValue(g, jvp->GetJson(), n + 1));
+ jvp = &jval;
+ } // endif n
+
+ if (!i) {
+ SetJsonValue(g, vp, jvp, n);
+ continue;
+ } else
+ SetJsonValue(g, MulVal, jvp, n);
+
+ if (!MulVal->IsZero()) {
+ switch (op) {
+ case OP_CNC:
+ if (Nodes[n].CncVal) {
+ val[0] = Nodes[n].CncVal;
+ err = vp->Compute(g, val, 1, op);
+ } // endif CncVal
+
+ 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;
+ err = vp->Compute(g, val, 2, OP_ADD);
+ break;
+ default:
+ val[0] = Nodes[n].Valp;
+ val[1] = MulVal;
+ err = vp->Compute(g, val, 2, op);
+ } // endswitch Op
+
+ if (err)
+ vp->Reset();
+
+ } // endif Zero
+
+ } // endfor i
+
+ if (op == OP_SEP) {
+ // Calculate average
+ MulVal->SetValue(ars);
+ val[0] = vp;
+ val[1] = MulVal;
+
+ if (vp->Compute(g, val, 2, OP_DIV))
+ vp->Reset();
+
+ } // endif Op
+
+ return vp;
+ } // end of CalculateArray
+
/***********************************************************************/ /* GetRow: Get the object containing this column. */ /***********************************************************************/ -PJSON JSONCOL::GetRow(PGLOBAL g, int mode) +PJSON JSONCOL::GetRow(PGLOBAL g) { PJVAL val; PJAR arp; @@ -610,23 +809,15 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode) case TYPE_JAR: if (!Nodes[i].Key) { if (Nodes[i].Op != OP_NULL) { - Ival = i; arp = (PJAR)row; - if (mode < 2) // First pass - Arp = arp; - - if (Nodes[i].Op != OP_XX) { - if (Nodes[i].Rank) - val = arp->GetValue(Nodes[i].Rank - 1); - else - val = arp->GetValue(arp == Arp ? Nx : 0); - - } else - val = arp->GetValue(Tjp->SameRow); - - } else - val = NULL; + if (Nodes[i].Rank)
+ val = arp->GetValue(Nodes[i].Rank - 1);
+ else
+ val = arp->GetValue(Nodes[i].Nx);
+
+ } else
+ val = NULL;
} else { strcpy(g->Message, "Unexpected array"); @@ -644,7 +835,7 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode) if (val) { row = val->GetJson(); - } else if (mode == 1) { // mode write + } else { // Construct missing objects for (i++; row && i < Nod; i++) { if (!Nodes[i].Key) { @@ -668,8 +859,7 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode) } // endfor i break; - } else - row = NULL; + } // endelse } // endfor i @@ -677,131 +867,6 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode) } // end of GetRow /***********************************************************************/ -/* ReadColumn: */ -/***********************************************************************/ -void JSONCOL::ReadColumn(PGLOBAL g) - { - int mode = 0, n = Nod - 1; - PJSON row; - PJVAL val = NULL; - - evenmore: - row = GetRow(g, mode); - - more: - if (row) switch (row->GetType()) { - case TYPE_JOB: - if (Nodes[n].Key) - val = row->GetValue(Nodes[n].Key); - else - val = new(g) JVALUE(row); - - break; - case TYPE_JAR: - // Multiple column ? - if (Nodes[n].Op != OP_NULL) { - Arp = (PJAR)row; - val = Arp->GetValue(Nodes[n].Rank > 0 ? - Nodes[n].Rank - 1 : - Nodes[n].Op == OP_XX ? Tjp->SameRow : Nx); - Ival = n; - } else - val = NULL; - - break; - case TYPE_JVAL: - val = (PJVAL)row; - break; - default: - sprintf(g->Message, "Wrong return value type %d", row->GetType()); - Value->Reset(); - return; - } // endswitch Type - - if (!Nx /*|| (Xpd)*/) - SetJsonValue(g, Value, val, n); - - if (Arp) { - // Multiple column - int ars = (Nodes[Ival].Rank > 0) ? 1 : MY_MIN(Tjp->Limit, Arp->size()); - - if (Nodes[Ival].Op == OP_XX) { - if (ars > Tjp->SameRow + 1) - Tjp->NextSame = true; // More to come - else { - Tjp->NextSame = false; - Arp = NULL; - } // endelse - - } else { - if (Nx && val) { - SetJsonValue(g, MulVal, val, Ival); - - if (!MulVal->IsZero()) { - PVAL val[2]; - bool err; - - switch (Nodes[Ival].Op) { - case OP_CNC: - if (Nodes[Ival].CncVal) { - val[0] = Nodes[Ival].CncVal; - err = Value->Compute(g, val, 1, Nodes[Ival].Op); - } // endif CncVal - - val[0] = MulVal; - err = Value->Compute(g, val, 1, Nodes[Ival].Op); - break; - case OP_NUM: - case OP_SEP: - val[0] = Value; - val[1] = MulVal; - err = Value->Compute(g, val, 2, OP_ADD); - break; - default: - val[0] = Value; - val[1] = MulVal; - err = Value->Compute(g, val, 2, Nodes[Ival].Op); - } // endswitch Op - - if (err) - Value->Reset(); - - } // endif Zero - - } // endif Nx - - if (ars > ++Nx) { - if (Ival != n) { - mode = 2; - goto evenmore; - } else - goto more; - - } else { - if (Nodes[Ival].Op == OP_SEP) { - // Calculate average - PVAL val[2]; - - MulVal->SetValue(ars); - val[0] = Value; - val[1] = MulVal; - - if (Value->Compute(g, val, 2, OP_DIV)) - Value->Reset(); - - } // endif Op - - Arp = NULL; - Nx = 0; - } // endif ars - - } // endif Op - - } // endif Arp - - } // end of ReadColumn - -/***********************************************************************/ /* WriteColumn: */ /***********************************************************************/ void JSONCOL::WriteColumn(PGLOBAL g) @@ -821,7 +886,7 @@ void JSONCOL::WriteColumn(PGLOBAL g) PJOB objp = NULL; PJAR arp = NULL; PJVAL jvp = NULL; - PJSON row = GetRow(g, 1); + PJSON row = GetRow(g); JTYP type = row->GetType(); switch (row->GetType()) { @@ -1176,11 +1241,6 @@ bool TDBJSON::OpenDB(PGLOBAL g) /*******************************************************************/ /* Table already open replace it at its beginning. */ /*******************************************************************/ - for (PJCOL cp = (PJCOL)Columns; cp; cp = (PJCOL)cp->GetNext()) { - cp->Nx = 0; - cp->Arp = NULL; - } // endfor cp - Fpos= -1; Spos = 0; NextSame = false; @@ -1218,7 +1278,8 @@ int TDBJSON::ReadDB(PGLOBAL g) N++; if (NextSame) { - SameRow++; + SameRow = NextSame; + NextSame = false; rc = RC_OK; } else if (++Fpos < (signed)Doc->size()) { Row = Doc->GetValue(Fpos); diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h index b815ccf21ce..a152db72fa8 100644 --- a/storage/connect/tabjson.h +++ b/storage/connect/tabjson.h @@ -15,6 +15,7 @@ enum JMODE {MODE_OBJECT, MODE_ARRAY, MODE_VALUE}; typedef class JSONDEF *PJDEF; typedef class TDBJSON *PJTDB; typedef class JSONCOL *PJCOL; +typedef class JARLST *PJARS; class TDBJSN; @@ -25,7 +26,9 @@ 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 Nx; // Same row number } JNODE, *PJNODE; /***********************************************************************/ @@ -98,11 +101,11 @@ class TDBJSN : public TDBDOS { int N; // The current Rownum int Limit; // Limit of multiple values int Pretty; // Depends on file structure - bool Strict; // Strict syntax checking - bool NextSame; // Same next row - bool Comma; // Row has final comma + int NextSame; // Same next row int SameRow; // Same row nb int Xval; // Index of expandable array + bool Strict; // Strict syntax checking + bool Comma; // Row has final comma }; // end of class TDBJSN /* -------------------------- JSONCOL class -------------------------- */ @@ -130,8 +133,11 @@ class JSONCOL : public DOSCOL { protected: bool CheckExpand(PGLOBAL g, int i, PSZ nm, bool b); bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm); - PJSON GetRow(PGLOBAL g, int mode); + PVAL GetColumnValue(PGLOBAL g, PJSON row, int i);
+ PVAL ExpandArray(PGLOBAL g, PJAR arp, int n);
+ PVAL CalculateArray(PGLOBAL g, PJAR arp, int n);
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n); + PJSON GetRow(PGLOBAL g); // Default constructor not to be used JSONCOL(void) {} @@ -139,12 +145,10 @@ class JSONCOL : public DOSCOL { // Members TDBJSN *Tjp; // To the JSN table block PVAL MulVal; // To value used by multiple column - PJAR Arp; // The intermediate array char *Jpath; // The json path - JNODE *Nodes ; // The intermediate objects + JNODE *Nodes; // The intermediate objects int Nod; // The number of intermediate objects - int Ival; // Index of multiple values - int Nx; // The last read sub-row + int Xnod; // Index of multiple values bool Xpd; // True for expandable column bool Parsed; // True when parsed }; // end of class JSONCOL |