From a35424829a4534ad63a80f30a73adb0ce74f742e Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 26 Dec 2020 19:44:38 +0100 Subject: [PATCH] - Continue BSON implementation + fix create modified ha_connect.cc --- storage/connect/bson.cpp | 174 ++++++++++++++++++---------------- storage/connect/bson.h | 28 +++--- storage/connect/bsonudf.cpp | 8 +- storage/connect/ha_connect.cc | 8 +- storage/connect/tabbson.cpp | 39 ++++---- 5 files changed, 132 insertions(+), 125 deletions(-) diff --git a/storage/connect/bson.cpp b/storage/connect/bson.cpp index df95bd4c9c801..cdb619d07ca79 100644 --- a/storage/connect/bson.cpp +++ b/storage/connect/bson.cpp @@ -59,38 +59,6 @@ void trans_func(unsigned int u, _EXCEPTION_POINTERS* pExp) { char* GetExceptionDesc(PGLOBAL g, unsigned int e); #endif // SE_CATCH -#if 0 -char* GetJsonNull(void); - -/***********************************************************************/ -/* IsNum: check whether this string is all digits. */ -/***********************************************************************/ -bool IsNum(PSZ s) { - for (char* p = s; *p; p++) - if (*p == ']') - break; - else if (!isdigit(*p) || *p == '-') - return false; - - return true; -} // end of IsNum - -/***********************************************************************/ -/* NextChr: return the first found '[' or Sep pointer. */ -/***********************************************************************/ -char* NextChr(PSZ s, char sep) { - char* p1 = strchr(s, '['); - char* p2 = strchr(s, sep); - - if (!p2) - return p1; - else if (p1) - return MY_MIN(p1, p2); - - return p2; -} // end of NextChr -#endif // 0 - /* --------------------------- Class BDOC ---------------------------- */ /***********************************************************************/ @@ -180,7 +148,7 @@ PBVAL BDOC::ParseJson(PGLOBAL g, char* js, size_t lng) if (bvp->Type != TYPE_UNKNOWN) { bvp->To_Val = ParseAsArray(i); bvp->Type = TYPE_JAR; - } else if ((bvp->To_Val = MOF(ParseValue(i)))) + } else if ((bvp->To_Val = MOF(ParseValue(i, NewVal())))) bvp->Type = TYPE_JVAL; else throw 4; @@ -269,11 +237,11 @@ OFFSET BDOC::ParseArray(int& i) sprintf(G->Message, "Unexpected value near %.*s", ARGS); throw 1; } else if (lastvlp) { - vlp = ParseValue(i); + vlp = ParseValue(i, NewVal()); lastvlp->Next = MOF(vlp); lastvlp = vlp; } else - firstvlp = lastvlp = ParseValue(i); + firstvlp = lastvlp = ParseValue(i, NewVal()); level = (b) ? 1 : 2; break; @@ -303,10 +271,10 @@ OFFSET BDOC::ParseObject(int& i) case '"': if (level < 2) { key = ParseString(++i); - bpp = SubAllocPair(key); + bpp = NewPair(key); if (lastbpp) { - lastbpp->Next = MOF(bpp); + lastbpp->Vlp.Next = MOF(bpp); lastbpp = bpp; } else firstbpp = lastbpp = bpp; @@ -320,7 +288,7 @@ OFFSET BDOC::ParseObject(int& i) break; case ':': if (level == 2) { - lastbpp->Vlp = MOF(ParseValue(++i)); + ParseValue(++i, GetVlp(lastbpp)); level = 3; } else { sprintf(G->Message, "Unexpected ':' near %.*s", ARGS); @@ -362,10 +330,8 @@ OFFSET BDOC::ParseObject(int& i) /***********************************************************************/ /* Parse a JSON Value. */ /***********************************************************************/ -PBVAL BDOC::ParseValue(int& i) +PBVAL BDOC::ParseValue(int& i, PBVAL bvp) { - PBVAL bvp = NewVal(); - for (; i < len; i++) switch (s[i]) { case '\n': @@ -750,7 +716,7 @@ bool BDOC::SerializeObject(OFFSET obp) if (jp->WriteChr('{')) return true; - for (prp; prp; prp = MPP(prp->Next)) { + for (prp; prp; prp = GetNext(prp)) { if (first) first = false; else if (jp->WriteChr(',')) @@ -760,7 +726,7 @@ bool BDOC::SerializeObject(OFFSET obp) jp->WriteStr(MZP(prp->Key)) || jp->WriteChr('"') || jp->WriteChr(':') || - SerializeValue(MVP(prp->Vlp))) + SerializeValue(GetVlp(prp))) return true; } // endfor i @@ -883,15 +849,35 @@ void BJSON::MemSet(size_t size) /* ------------------------ Bobject functions ------------------------ */ /***********************************************************************/ +/* Set a pair vlp to some PVAL values. */ +/***********************************************************************/ +void BJSON::SetPairValue(PBPR brp, PBVAL bvp) +{ + if (bvp) { + brp->Vlp.To_Val = bvp->To_Val; + brp->Vlp.Nd = bvp->Nd; + brp->Vlp.Type = bvp->Type; + } else { + brp->Vlp.To_Val = 0; + brp->Vlp.Nd = 0; + brp->Vlp.Type = TYPE_NULL; + } // endif bvp + +} // end of SetPairValue + + /***********************************************************************/ /* Sub-allocate and initialize a BPAIR. */ /***********************************************************************/ -PBPR BJSON::SubAllocPair(OFFSET key, OFFSET val) +PBPR BJSON::NewPair(OFFSET key, int type) { PBPR bpp = (PBPR)BsonSubAlloc(sizeof(BPAIR)); bpp->Key = key; - bpp->Vlp = val; - bpp->Next = 0; + bpp->Vlp.Ktp = TYPE_STRG; + bpp->Vlp.Type = type; + bpp->Vlp.To_Val = 0; + bpp->Vlp.Nd = 0; + bpp->Vlp.Next = 0; return bpp; } // end of SubAllocPair @@ -905,7 +891,7 @@ int BJSON::GetObjectSize(PBVAL bop, bool b) for (PBPR brp = GetObject(bop); brp; brp = GetNext(brp)) // If b return only non null pairs - if (!b || (brp->Vlp && GetVal(brp)->Type != TYPE_NULL)) + if (!b || (brp->Vlp.To_Val && brp->Vlp.Type != TYPE_NULL)) n++; return n; @@ -914,20 +900,21 @@ int BJSON::GetObjectSize(PBVAL bop, bool b) /***********************************************************************/ /* Add a new pair to an Object and return it. */ /***********************************************************************/ -void BJSON::AddPair(PBVAL bop, PSZ key, OFFSET val) +PBVAL BJSON::AddPair(PBVAL bop, PSZ key, int type) { CheckType(bop, TYPE_JOB); PBPR brp; - OFFSET nrp = NewPair(key, val); + OFFSET nrp = NewPair(key, type); if (bop->To_Val) { - for (brp = GetObject(bop); brp->Next; brp = GetNext(brp)); + for (brp = GetObject(bop); brp->Vlp.Next; brp = GetNext(brp)); - brp->Next = nrp; + brp->Vlp.Next = nrp; } else bop->To_Val = nrp; bop->Nd++; + return GetVlp(MPP(nrp)); } // end of AddPair /***********************************************************************/ @@ -953,7 +940,7 @@ PBVAL BJSON::GetObjectValList(PBVAL bop) PBVAL arp = NewVal(TYPE_JAR); for (PBPR brp = GetObject(bop); brp; brp = GetNext(brp)) - AddArrayValue(arp, brp->Vlp); + AddArrayValue(arp, GetVlp(brp)); return arp; } // end of GetObjectValList @@ -967,7 +954,7 @@ PBVAL BJSON::GetKeyValue(PBVAL bop, PSZ key) for (PBPR brp = GetObject(bop); brp; brp = GetNext(brp)) if (!strcmp(GetKey(brp), key)) - return GetVal(brp); + return GetVlp(brp); return NULL; } // end of GetKeyValue; @@ -993,11 +980,11 @@ PSZ BJSON::GetObjectText(PGLOBAL g, PBVAL bop, PSTRG text) b = false; } // endif text - if (b && !brp->Next && !strcmp(MZP(brp->Key), "$date")) { + if (b && !brp->Vlp.Next && !strcmp(MZP(brp->Key), "$date")) { int i; PSZ s; - GetValueText(g, MVP(brp->Vlp), text); + GetValueText(g, GetVlp(brp), text); s = text->GetStr(); i = (s[1] == '-' ? 2 : 1); @@ -1013,10 +1000,10 @@ PSZ BJSON::GetObjectText(PGLOBAL g, PBVAL bop, PSTRG text) } // endif text - } else for (PBPR brp = GetObject(bop); brp; brp = GetNext(brp)) { - GetValueText(g, GetVal(brp), text); + } else for (; brp; brp = GetNext(brp)) { + GetValueText(g, GetVlp(brp), text); - if (brp->Next) + if (brp->Vlp.Next) text->Append(' '); } // endfor brp @@ -1041,18 +1028,18 @@ void BJSON::SetKeyValue(PBVAL bop, OFFSET bvp, PSZ key) if (bop->To_Val) { for (brp = GetObject(bop); brp; brp = GetNext(brp)) - if (!strcmp(GetKey(brp), key)) { - brp->Vlp = bvp; - return; - } else + if (!strcmp(GetKey(brp), key)) + break; + else prp = brp; if (!brp) - prp->Next = NewPair(key, bvp); + brp = MPP(prp->Vlp.Next = NewPair(key)); } else - bop->To_Val = NewPair(key, bvp); + brp = MPP(bop->To_Val = NewPair(key)); + SetPairValue(brp, MVP(bvp)); bop->Nd++; } // end of SetKeyValue @@ -1066,7 +1053,7 @@ PBVAL BJSON::MergeObject(PBVAL bop1, PBVAL bop2) if (bop1->To_Val) for (PBPR brp = GetObject(bop2); brp; brp = GetNext(brp)) - SetKeyValue(bop1, brp->Vlp, GetKey(brp)); + SetKeyValue(bop1, GetVlp(brp), GetKey(brp)); else { bop1->To_Val = bop2->To_Val; @@ -1087,9 +1074,9 @@ void BJSON::DeleteKey(PBVAL bop, PCSZ key) for (brp = GetObject(bop); brp; brp = GetNext(brp)) if (!strcmp(MZP(brp->Key), key)) { if (pbrp) { - pbrp->Next = brp->Next; + pbrp->Vlp.Next = brp->Vlp.Next; } else - bop->To_Val = brp->Next; + bop->To_Val = brp->Vlp.Next; bop->Nd--; break; @@ -1106,7 +1093,7 @@ bool BJSON::IsObjectNull(PBVAL bop) CheckType(bop, TYPE_JOB); for (PBPR brp = GetObject(bop); brp; brp = GetNext(brp)) - if (brp->Vlp && (MVP(brp->Vlp))->Type != TYPE_NULL) + if (brp->Vlp.To_Val && brp->Vlp.Type != TYPE_NULL) return false; return true; @@ -1368,6 +1355,25 @@ int BJSON::GetSize(PBVAL vlp, bool b) } // end of GetSize +PBVAL BJSON::GetBson(PBVAL bvp) +{ + PBVAL bp = NULL; + + switch (bvp->Type) { + case TYPE_JAR: + bp = MVP(bvp->To_Val); + break; + case TYPE_JOB: + bp = GetVlp(MPP(bvp->To_Val)); + break; + default: + bp = bvp; + break; + } // endswitch Type + + return bp; +} // end of GetBson + /***********************************************************************/ /* Return the Value's as a Value struct. */ /***********************************************************************/ @@ -1378,22 +1384,22 @@ PVAL BJSON::GetValue(PGLOBAL g, PBVAL vp) PBVAL vlp = vp->Type == TYPE_JVAL ? MVP(vp->To_Val) : vp; switch (vlp->Type) { - case TYPE_STRG: - case TYPE_DBL: - case TYPE_BINT: - valp = AllocateValue(g, MP(vlp->To_Val), vlp->Type, vlp->Nd); - break; - case TYPE_INTG: - case TYPE_BOOL: - valp = AllocateValue(g, vlp, vlp->Type); - break; - case TYPE_FLOAT: - d = (double)vlp->F; - valp = AllocateValue(g, &d, TYPE_DOUBLE, vlp->Nd); - break; - default: - valp = NULL; - break; + case TYPE_STRG: + case TYPE_DBL: + case TYPE_BINT: + valp = AllocateValue(g, MP(vlp->To_Val), vlp->Type, vlp->Nd); + break; + case TYPE_INTG: + case TYPE_BOOL: + valp = AllocateValue(g, vlp, vlp->Type); + break; + case TYPE_FLOAT: + d = (double)vlp->F; + valp = AllocateValue(g, &d, TYPE_DOUBLE, vlp->Nd); + break; + default: + valp = NULL; + break; } // endswitch Type return valp; diff --git a/storage/connect/bson.h b/storage/connect/bson.h index ca776dd19507b..a09f9c3ef8993 100644 --- a/storage/connect/bson.h +++ b/storage/connect/bson.h @@ -37,7 +37,8 @@ typedef struct _jvalue { bool B; // A boolean value True or false (0) }; short Nd; // Number of decimals - short Type; // The value type + char Type; // The value type + char Ktp; // The key type OFFSET Next; // Offset to the next value in array } BVAL, *PBVAL; // end of struct BVALUE @@ -46,13 +47,12 @@ typedef struct _jvalue { /***********************************************************************/ typedef struct _jpair { OFFSET Key; // Offset to this pair key name - OFFSET Vlp; // To the value of the pair - OFFSET Next; // Offset to the next pair in object + BVAL Vlp; // The value of the pair } BPAIR, *PBPR; // end of struct BPAIR char* NextChr(PSZ s, char sep); char* GetJsonNull(void); -const char* GetFmt(int type, bool un); +const char* GetFmt(int type, bool un); DllExport bool IsNum(PSZ s); @@ -81,9 +81,9 @@ class BJSON : public BLOCK { // SubAlloc functions void* BsonSubAlloc(size_t size); - PBPR SubAllocPair(OFFSET key, OFFSET val = 0); - OFFSET NewPair(PSZ key, OFFSET val = 0) - {return MOF(SubAllocPair(DupStr(key), val));} + PBPR NewPair(OFFSET key, int type = TYPE_NULL); + OFFSET NewPair(PSZ key, int type = TYPE_NULL) + {return MOF(NewPair(DupStr(key), type));} PBVAL NewVal(int type = TYPE_NULL); PBVAL NewVal(PVAL valp); PBVAL SubAllocVal(OFFSET toval, int type = TYPE_NULL, short nd = 0); @@ -110,13 +110,15 @@ class BJSON : public BLOCK { // Object functions inline PBPR GetObject(PBVAL bop) {return MPP(bop->To_Val);} - inline PBPR GetNext(PBPR brp) { return MPP(brp->Next); } + inline PBPR GetNext(PBPR brp) { return MPP(brp->Vlp.Next); } + void SetPairValue(PBPR brp, PBVAL bvp); int GetObjectSize(PBVAL bop, bool b = false); PSZ GetObjectText(PGLOBAL g, PBVAL bop, PSTRG text); PBVAL MergeObject(PBVAL bop1, PBVAL bop2); - void AddPair(PBVAL bop, PSZ key, OFFSET val = 0); - PSZ GetKey(PBPR prp) {return MZP(prp->Key);} - PBVAL GetVal(PBPR prp) {return MVP(prp->Vlp);} + PBVAL AddPair(PBVAL bop, PSZ key, int type = TYPE_NULL); + PSZ GetKey(PBPR prp) {return prp ? MZP(prp->Key) : NULL;} + PBVAL GetTo_Val(PBPR prp) {return prp ? MVP(prp->Vlp.To_Val) : NULL;} + PBVAL GetVlp(PBPR prp) {return prp ? (PBVAL)&prp->Vlp : NULL;} PBVAL GetKeyValue(PBVAL bop, PSZ key); PBVAL GetKeyList(PBVAL bop); PBVAL GetObjectValList(PBVAL bop); @@ -131,7 +133,7 @@ class BJSON : public BLOCK { PBVAL GetNext(PBVAL vlp) {return MVP(vlp->Next);} //PJSON GetJsp(void) { return (DataType == TYPE_JSON ? Jsp : NULL); } PSZ GetValueText(PGLOBAL g, PBVAL vlp, PSTRG text); - inline PBVAL GetBson(PBVAL bvp) { return IsJson(bvp) ? MVP(bvp->To_Val) : bvp; } + PBVAL GetBson(PBVAL bvp); PSZ GetString(PBVAL vp, char* buff = NULL); int GetInteger(PBVAL vp); long long GetBigint(PBVAL vp); @@ -178,7 +180,7 @@ class BDOC : public BJSON { protected: OFFSET ParseArray(int& i); OFFSET ParseObject(int& i); - PBVAL ParseValue(int& i); + PBVAL ParseValue(int& i, PBVAL bvp); OFFSET ParseString(int& i); void ParseNumeric(int& i, PBVAL bvp); OFFSET ParseAsArray(int& i); diff --git a/storage/connect/bsonudf.cpp b/storage/connect/bsonudf.cpp index 76ecce5133baf..d43444a9bd071 100644 --- a/storage/connect/bsonudf.cpp +++ b/storage/connect/bsonudf.cpp @@ -856,7 +856,7 @@ my_bool BJNX::LocateObject(PGLOBAL g, PBVAL jobp) if (Jp->WriteStr(MZP(pair->Key))) return true; - if (LocateValue(g, MVP(pair->Vlp))) + if (LocateValue(g, GetVlp(pair))) return true; } // endfor i @@ -976,7 +976,7 @@ my_bool BJNX::LocateObjectAll(PGLOBAL g, PBVAL jobp) for (PBPR pair = GetObject(jobp); pair; pair = GetNext(pair)) { Jpnp[I].Key = MZP(pair->Key); - if (LocateValueAll(g, MVP(pair->Vlp))) + if (LocateValueAll(g, GetVlp(pair))) return true; } // endfor i @@ -1020,8 +1020,8 @@ my_bool BJNX::CompareTree(PGLOBAL g, PBVAL jp1, PBVAL jp2) PBPR p1 = GetObject(jp1), p2 = GetObject(jp2); // Keys can be differently ordered - for (; found && p1 && p2; p1 = MPP(p1->Next)) - found = CompareValues(g, MVP(p1->Vlp), GetKeyValue(jp2, MZP(p1->Key))); + for (; found && p1 && p2; p1 = GetNext(p1)) + found = CompareValues(g, GetVlp(p1), GetKeyValue(jp2, GetKey(p1))); } else if (jp1->Type == TYPE_JVAL) { found = CompareTree(g, MVP(jp1->To_Val), (MVP(jp2->To_Val))); diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index d6cbcbc077fbc..9b40b5c9a132d 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -170,7 +170,7 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.07.0002 December 19, 2020"; + char version[]= "Version 1.07.0002 December 25, 2020"; #if defined(__WIN__) char compver[]= "Version 1.07.0002 " __DATE__ " " __TIME__; char slash= '\\'; @@ -6440,9 +6440,9 @@ int ha_connect::create(const char *name, TABLE *table_arg, // Check table type if (type == TAB_UNDEF) { options->type= (options->srcdef) ? "MYSQL" : -#if defined(BSON_SUPPORT) +#if defined(REST_SUPPORT) (options->http) ? "JSON" : -#endif // BSON_SUPPORT +#endif // REST_SUPPORT (options->tabname) ? "PROXY" : "DOS"; type= GetTypeID(options->type); sprintf(g->Message, "No table_type. Will be set to %s", options->type); @@ -6460,7 +6460,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, DBUG_RETURN(HA_ERR_INTERNAL_ERROR); inward= IsFileType(type) && !options->filename && - (type != TAB_JSON || !cnc.length); + ((type != TAB_JSON && type != TAB_BSON) || !cnc.length); if (options->data_charset) { const CHARSET_INFO *data_charset; diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index 7635a6afe704e..69dd5749122cd 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -342,7 +342,7 @@ int BSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) strncpy(colname, bp->GetKey(jpp), 64); fmt[bf] = 0; - if (Find(g, bp->GetVal(jpp), colname, MY_MIN(lvl, 0))) + if (Find(g, bp->GetVlp(jpp), colname, MY_MIN(lvl, 0))) goto err; } // endfor jpp @@ -444,7 +444,7 @@ bool BSONDISC::Find(PGLOBAL g, PBVAL jvp, PCSZ key, int j) strncat(strncat(colname, "_", n), k, n - 1); } // endif Key - if (Find(g, bp->GetVal(jrp), k, j + 1)) + if (Find(g, bp->GetVlp(jrp), k, j + 1)) return true; *p = *pc = 0; @@ -691,7 +691,7 @@ PBVAL BTUTIL::MakeTopTree(PGLOBAL g, int type) } // endif Val Tp->Row = val; - Tp->Row->Type = type; + if (Tp->Row) Tp->Row->Type = type; } else top = Tp->Row = NewVal(type); @@ -1052,18 +1052,20 @@ PBVAL BCUTIL::GetRow(PGLOBAL g) } else { // Construct missing objects for (i++; row && i < nod; i++) { + int type; + if (nodes[i].Op == OP_XX) break; else if (!nodes[i].Key) // Construct intermediate array - nwr = NewVal(TYPE_JAR); + type = TYPE_JAR; else - nwr = NewVal(TYPE_JOB); + type = TYPE_JOB; if (row->Type == TYPE_JOB) { - SetKeyValue(row, MOF(nwr), nodes[i - 1].Key); + nwr = AddPair(row, nodes[i - 1].Key, type); } else if (row->Type == TYPE_JAR) { - AddArrayValue(row, nwr); + AddArrayValue(row, (nwr = NewVal(type))); } else { strcpy(g->Message, "Wrong type when writing new row"); nwr = NULL; @@ -2258,19 +2260,16 @@ int TDBBSON::MakeDocument(PGLOBAL g) Docp = jsp; else { // The table is void or is just one object or one value - Docp = Bp->NewVal(TYPE_JAR); - - if (val) - Bp->AddArrayValue(Docp, val); - else if (jsp) - Bp->AddArrayValue(Docp, Bp->DupVal(jsp)); - - if (objp) - Bp->SetKeyValue(objp, Bp->DupVal(Docp), key); - else if (arp) - Bp->SetArrayValue(arp, Bp->DupVal(Docp), i); - else - Top = Docp; + if (objp) { + Docp = Bp->GetKeyValue(objp, key); + Docp->To_Val = Bp->MOF(Bp->DupVal(Docp)); + Docp->Type = TYPE_JAR; + } else if (arp) { + Docp = Bp->NewVal(TYPE_JAR); + Bp->AddArrayValue(Docp, jsp); + Bp->SetArrayValue(arp, Docp, i); + } else + Top = Docp = Bp->NewVal(TYPE_JAR); } // endif jsp