From ef0829ef40eb4136eed4282057baa4126dd66b69 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 1 May 2021 22:29:38 +0200 Subject: [PATCH 01/18] - Major update of the json/bson/mongo table types programs. Fix several bugs, chiefly concerning CURL operations. modified: storage/connect/bson.cpp modified: storage/connect/cmgfam.cpp modified: storage/connect/cmgoconn.cpp modified: storage/connect/cmgoconn.h modified: storage/connect/colblk.h modified: storage/connect/ha_connect.cc modified: storage/connect/jmgfam.cpp modified: storage/connect/jmgoconn.cpp modified: storage/connect/jmgoconn.h modified: storage/connect/json.cpp modified: storage/connect/json.h modified: storage/connect/mysql-test/connect/r/bson_mongo_c.result modified: storage/connect/mysql-test/connect/r/json_mongo_c.result modified: storage/connect/mysql-test/connect/r/mongo_c.result modified: storage/connect/mysql-test/connect/r/mongo_java_2.result modified: storage/connect/mysql-test/connect/r/mongo_java_3.result modified: storage/connect/mysql-test/connect/std_data/Mongo2.jar modified: storage/connect/mysql-test/connect/std_data/Mongo3.jar modified: storage/connect/tabbson.cpp modified: storage/connect/tabbson.h modified: storage/connect/tabcmg.cpp modified: storage/connect/tabcmg.h modified: storage/connect/tabjmg.cpp modified: storage/connect/tabjmg.h modified: storage/connect/tabjson.cpp modified: storage/connect/tabjson.h --- storage/connect/bson.cpp | 11 +- storage/connect/cmgfam.cpp | 5 + storage/connect/cmgoconn.cpp | 467 +++++++++++------- storage/connect/cmgoconn.h | 19 +- storage/connect/colblk.h | 3 +- storage/connect/ha_connect.cc | 15 +- storage/connect/jmgfam.cpp | 12 +- storage/connect/jmgoconn.cpp | 149 ++++-- storage/connect/jmgoconn.h | 11 +- storage/connect/json.cpp | 27 +- storage/connect/json.h | 2 +- .../mysql-test/connect/r/bson_mongo_c.result | 2 +- .../mysql-test/connect/r/json_mongo_c.result | 2 +- .../mysql-test/connect/r/mongo_c.result | 34 +- .../mysql-test/connect/r/mongo_java_2.result | 24 +- .../mysql-test/connect/r/mongo_java_3.result | 24 +- .../mysql-test/connect/std_data/Mongo2.jar | Bin 623907 -> 624130 bytes .../mysql-test/connect/std_data/Mongo3.jar | Bin 1705776 -> 1706054 bytes storage/connect/tabbson.cpp | 15 +- storage/connect/tabbson.h | 8 +- storage/connect/tabcmg.cpp | 153 +++--- storage/connect/tabcmg.h | 6 +- storage/connect/tabjmg.cpp | 26 +- storage/connect/tabjmg.h | 7 +- storage/connect/tabjson.cpp | 41 +- storage/connect/tabjson.h | 4 +- 26 files changed, 673 insertions(+), 394 deletions(-) diff --git a/storage/connect/bson.cpp b/storage/connect/bson.cpp index a0a421657bd..060e8b1e394 100644 --- a/storage/connect/bson.cpp +++ b/storage/connect/bson.cpp @@ -1205,15 +1205,14 @@ void BJSON::SetArrayValue(PBVAL bap, PBVAL nvp, int n) int i = 0; PBVAL bvp = NULL; - if (bap->To_Val) - for (bvp = GetArray(bap); bvp; i++, bvp = GetNext(bvp)) - if (i == n) { - SetValueVal(bvp, nvp); - return; - } + for (bvp = GetArray(bap); i < n; i++, bvp = bvp ? GetNext(bvp) : NULL) + if (!bvp) + AddArrayValue(bap, NewVal()); if (!bvp) AddArrayValue(bap, MOF(nvp)); + else + SetValueVal(bvp, nvp); } // end of SetValue diff --git a/storage/connect/cmgfam.cpp b/storage/connect/cmgfam.cpp index 690c087c2bb..a3afc154224 100644 --- a/storage/connect/cmgfam.cpp +++ b/storage/connect/cmgfam.cpp @@ -56,6 +56,7 @@ CMGFAM::CMGFAM(PJDEF tdp) : DOSFAM((PDOSDEF)NULL) Pcg.Coll_name = tdp->Collname; Pcg.Options = tdp->Options; Pcg.Filter = tdp->Filter; + Pcg.Line = NULL; Pcg.Pipe = tdp->Pipe && tdp->Options != NULL; Lrecl = tdp->Lrecl + tdp->Ending; } else { @@ -64,6 +65,7 @@ CMGFAM::CMGFAM(PJDEF tdp) : DOSFAM((PDOSDEF)NULL) Pcg.Coll_name = NULL; Pcg.Options = NULL; Pcg.Filter = NULL; + Pcg.Line = NULL; Pcg.Pipe = false; Lrecl = 0; } // endif tdp @@ -88,6 +90,7 @@ CMGFAM::CMGFAM(PBDEF tdp) : DOSFAM((PDOSDEF)NULL) Pcg.Coll_name = tdp->Collname; Pcg.Options = tdp->Options; Pcg.Filter = tdp->Filter; + Pcg.Line = NULL; Pcg.Pipe = tdp->Pipe && tdp->Options != NULL; Lrecl = tdp->Lrecl + tdp->Ending; } else { @@ -96,6 +99,7 @@ CMGFAM::CMGFAM(PBDEF tdp) : DOSFAM((PDOSDEF)NULL) Pcg.Coll_name = NULL; Pcg.Options = NULL; Pcg.Filter = NULL; + Pcg.Line = NULL; Pcg.Pipe = false; Lrecl = 0; } // endif tdp @@ -280,6 +284,7 @@ int CMGFAM::ReadBuffer(PGLOBAL g) /***********************************************************************/ int CMGFAM::WriteBuffer(PGLOBAL g) { + Pcg.Line = Tdbp->GetLine(); return Cmgp->Write(g); } // end of WriteBuffer diff --git a/storage/connect/cmgoconn.cpp b/storage/connect/cmgoconn.cpp index 474f940a8cf..7aa35253514 100644 --- a/storage/connect/cmgoconn.cpp +++ b/storage/connect/cmgoconn.cpp @@ -1,7 +1,7 @@ /************ CMgoConn C++ Functions Source Code File (.CPP) ***********/ -/* Name: CMgoConn.CPP Version 1.0 */ +/* Name: CMgoConn.CPP Version 1.1 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2017 */ +/* (C) Copyright to the author Olivier BERTRAND 2017 - 2021 */ /* */ /* This file contains the MongoDB C connection classes functions. */ /***********************************************************************/ @@ -24,7 +24,7 @@ bool CMgoConn::IsInit = false; -bool IsNum(PSZ s); +bool IsArray(PSZ s); bool MakeSelector(PGLOBAL g, PFIL fp, PSTRG s); /* --------------------------- Class INCOL --------------------------- */ @@ -47,12 +47,13 @@ void INCOL::AddCol(PGLOBAL g, PCOL colp, char *jp) break; if (!kp) { - icp = new(g) INCOL(IsNum(p)); + icp = new(g) INCOL(); kcp = (PKC)PlugSubAlloc(g, NULL, sizeof(KEYCOL)); kcp->Next = NULL; kcp->Incolp = icp; kcp->Colp = NULL; kcp->Key = PlugDup(g, jp); + kcp->Array = IsArray(p); if (Klist) { for (kp = Klist; kp->Next; kp = kp->Next); @@ -73,6 +74,7 @@ void INCOL::AddCol(PGLOBAL g, PCOL colp, char *jp) kcp->Incolp = NULL; kcp->Colp = colp; kcp->Key = jp; + kcp->Array = IsArray(jp); if (Klist) { for (kp = Klist; kp->Next; kp = kp->Next); @@ -168,10 +170,11 @@ bool CMgoConn::Connect(PGLOBAL g) mongo_init(true); #endif // !__WIN__ - Uri = mongoc_uri_new(Pcg->Uristr); + Uri = mongoc_uri_new_with_error(Pcg->Uristr, &Error); if (!Uri) { - sprintf(g->Message, "Failed to parse URI: \"%s\"", Pcg->Uristr); + sprintf(g->Message, "Failed to parse URI: \"%s\" Msg: %s", + Pcg->Uristr, Error.message); return true; } // endif Uri @@ -228,8 +231,8 @@ bool CMgoConn::Connect(PGLOBAL g) int CMgoConn::CollSize(PGLOBAL g) { int cnt; - bson_t *query; - const char *jf = NULL; + bson_t* query; + const char* jf = NULL; if (Pcg->Pipe) return 10; @@ -237,7 +240,7 @@ int CMgoConn::CollSize(PGLOBAL g) jf = Pcg->Filter; if (jf) { - query = bson_new_from_json((const uint8_t *)jf, -1, &Error); + query = bson_new_from_json((const uint8_t*)jf, -1, &Error); if (!query) { htrc("Wrong filter: %s", Error.message); @@ -247,8 +250,17 @@ int CMgoConn::CollSize(PGLOBAL g) } else query = bson_new(); +#if defined(NDEBUG) cnt = (int)mongoc_collection_count(Collection, - MONGOC_QUERY_NONE, query, 0, 0, NULL, &Error); + MONGOC_QUERY_NONE, query, 0, 0, NULL, &Error); +#else + if (jf) + cnt = (int)mongoc_collection_count_documents(Collection, + query, NULL, NULL, NULL, &Error); + else + cnt = (int)mongoc_collection_estimated_document_count( + Collection, NULL, NULL, NULL, &Error); +#endif if (cnt < 0) { htrc("Collection count: %s", Error.message); @@ -260,30 +272,81 @@ int CMgoConn::CollSize(PGLOBAL g) } // end of CollSize /***********************************************************************/ -/* OpenDB: Data Base open routine for MONGO access method. */ +/* Project: make the projection avoid path collision. */ +/***********************************************************************/ +void CMgoConn::Project(PGLOBAL g, PSTRG s) +{ + bool m, b = false; + size_t n; + PSZ path; + PCOL cp; + PTDB tp = Pcg->Tdbp; + PTHP hp, php = NULL, * nphp = &php; + + for (cp = tp->GetColumns(); cp; cp = cp->GetNext()) { + path = cp->GetJpath(g, true); + + for (hp = php; hp; hp = hp->Next) { + if (strlen(path) < strlen(hp->Path)) { + n = strlen(path); + m = true; + } else { + n = strlen(hp->Path); + m = false; + } // endif path + + if (!strncmp(path, hp->Path, n)) + break; + + } // endfor hp + + if (!hp) { + // New path + hp = (PTHP)PlugSubAlloc(g, NULL, sizeof(PTH)); + hp->Path = path; + hp->Next = NULL; + *nphp = hp; + nphp = &hp->Next; + } else if (m) // Smaller path must replace longer one + hp->Path = path; + + } // endfor cp + + for (hp = php; hp; hp = hp->Next) { + if (b) + s->Append(",\""); + else + b = true; + + s->Append(hp->Path); + s->Append("\":1"); + } // endfor hp + +} // end of Project + +/***********************************************************************/ +/* MakeCursor: make the cursor used to retrieve documents. */ /***********************************************************************/ bool CMgoConn::MakeCursor(PGLOBAL g) { const char *p; - bool id, b = false, all = false; + bool id, all = false; PCSZ options = Pcg->Options; PTDB tp = Pcg->Tdbp; PCOL cp; PSTRG s = NULL; PFIL filp = tp->GetFilter(); - id = (tp->GetMode() != MODE_READ); + id = (tp->GetMode() == MODE_UPDATE || tp->GetMode() == MODE_DELETE); if (options && !stricmp(options, "all")) { options = NULL; all = true; - } // endif Options - - for (cp = tp->GetColumns(); cp; cp = cp->GetNext()) - if (!strcmp(cp->GetName(), "_id")) - id = true; - else if (cp->GetFmt() && !strcmp(cp->GetFmt(), "*") && !options) + } else for (cp = tp->GetColumns(); cp && !all; cp = cp->GetNext()) + if (cp->GetFmt() && !strcmp(cp->GetFmt(), "*") && !options) all = true; + else if (!id) + id = !strcmp(cp->GetFmt() ? cp->GetFmt() : cp->GetName(), "_id"); if (Pcg->Pipe) { if (trace(1)) @@ -311,23 +374,14 @@ bool CMgoConn::MakeCursor(PGLOBAL g) tp->SetFilter(NULL); // Not needed anymore } // endif To_Filter - if (!all && tp->GetColumns()) { + if (tp->GetColumns() && !strstr(s->GetStr(), "$project")) { // Project list s->Append(",{\"$project\":{\""); if (!id) s->Append("_id\":0,\""); - for (cp = tp->GetColumns(); cp; cp = cp->GetNext()) { - if (b) - s->Append(",\""); - else - b = true; - - s->Append(cp->GetJpath(g, true)); - s->Append("\":1"); - } // endfor cp - + Project(g, s); s->Append("}}"); } // endif all @@ -377,7 +431,7 @@ bool CMgoConn::MakeCursor(PGLOBAL g) if (MakeSelector(g, filp, s)) { strcpy(g->Message, "Failed making selector"); - return NULL; + return true; } // endif Selector tp->SetFilter(NULL); // Not needed anymore @@ -391,7 +445,7 @@ bool CMgoConn::MakeCursor(PGLOBAL g) if (!Query) { sprintf(g->Message, "Wrong filter: %s", Error.message); - return NULL; + return true; } // endif Query } else @@ -413,16 +467,7 @@ bool CMgoConn::MakeCursor(PGLOBAL g) if (!id) s->Append("_id\":0,\""); - for (cp = tp->GetColumns(); cp; cp = cp->GetNext()) { - if (b) - s->Append(",\""); - else - b = true; - - s->Append(cp->GetJpath(g, true)); - s->Append("\":1"); - } // endfor cp - + Project(g, s); s->Append("}}"); s->Resize(s->GetLength() + 1); p = s->GetStr(); @@ -435,7 +480,7 @@ bool CMgoConn::MakeCursor(PGLOBAL g) if (!Opts) { sprintf(g->Message, "Wrong options: %s", Error.message); - return NULL; + return true; } // endif Opts } // endif all @@ -495,44 +540,54 @@ void CMgoConn::ShowDocument(bson_iter_t *iter, const bson_t *doc, const char *k) key = bson_iter_key(iter); htrc("Found element key: \"%s\"\n", key); - if (BSON_ITER_HOLDS_UTF8(iter)) - htrc("%s.%s=\"%s\"\n", k, key, bson_iter_utf8(iter, NULL)); - else if (BSON_ITER_HOLDS_INT32(iter)) - htrc("%s.%s=%d\n", k, key, bson_iter_int32(iter)); - else if (BSON_ITER_HOLDS_INT64(iter)) - htrc("%s.%s=%lld\n", k, key, bson_iter_int64(iter)); - else if (BSON_ITER_HOLDS_DOUBLE(iter)) - htrc("%s.%s=%g\n", k, key, bson_iter_double(iter)); - else if (BSON_ITER_HOLDS_DATE_TIME(iter)) - htrc("%s.%s=date(%lld)\n", k, key, bson_iter_date_time(iter)); - else if (BSON_ITER_HOLDS_OID(iter)) { - char str[25]; + switch (bson_iter_type(iter)) { + case BSON_TYPE_UTF8: + htrc("%s.%s=\"%s\"\n", k, key, bson_iter_utf8(iter, NULL)); + break; + case BSON_TYPE_INT32: + htrc("%s.%s=%d\n", k, key, bson_iter_int32(iter)); + break; + case BSON_TYPE_INT64: + htrc("%s.%s=%lld\n", k, key, bson_iter_int64(iter)); + break; + case BSON_TYPE_DOUBLE: + htrc("%s.%s=%g\n", k, key, bson_iter_double(iter)); + break; + case BSON_TYPE_DATE_TIME: + htrc("%s.%s=date(%lld)\n", k, key, bson_iter_date_time(iter)); + break; + case BSON_TYPE_OID: { + char str[25]; - bson_oid_to_string(bson_iter_oid(iter), str); - htrc("%s.%s=%s\n", k, key, str); - } else if (BSON_ITER_HOLDS_DECIMAL128(iter)) { - char *str = NULL; - bson_decimal128_t dec; + bson_oid_to_string(bson_iter_oid(iter), str); + htrc("%s.%s=%s\n", k, key, str); + } break; + case BSON_TYPE_DECIMAL128: { + char* str = NULL; + bson_decimal128_t dec; - bson_iter_decimal128(iter, &dec); - bson_decimal128_to_string(&dec, str); - htrc("%s.%s=%s\n", k, key, str); - } else if (BSON_ITER_HOLDS_DOCUMENT(iter)) { - bson_iter_t child; + bson_iter_decimal128(iter, &dec); + bson_decimal128_to_string(&dec, str); + htrc("%s.%s=%s\n", k, key, str); + } break; + case BSON_TYPE_DOCUMENT: { + bson_iter_t child; - if (bson_iter_recurse(iter, &child)) - ShowDocument(&child, NULL, key); + if (bson_iter_recurse(iter, &child)) + ShowDocument(&child, NULL, key); - } else if (BSON_ITER_HOLDS_ARRAY(iter)) { - bson_t *arr; - bson_iter_t itar; - const uint8_t *data = NULL; - uint32_t len = 0; + } break; + case BSON_TYPE_ARRAY: { + bson_t* arr; + bson_iter_t itar; + const uint8_t* data = NULL; + uint32_t len = 0; - bson_iter_array(iter, &len, &data); - arr = bson_new_from_data(data, len); - ShowDocument(&itar, arr, key); - } // endif's + bson_iter_array(iter, &len, &data); + arr = bson_new_from_data(data, len); + ShowDocument(&itar, arr, key); + } break; + } // endswitch iter } // endwhile bson_iter_next @@ -545,7 +600,7 @@ void CMgoConn::ShowDocument(bson_iter_t *iter, const bson_t *doc, const char *k) /***********************************************************************/ void CMgoConn::MakeColumnGroups(PGLOBAL g) { - Fpc = new(g) INCOL(false); + Fpc = new(g) INCOL(); for (PCOL colp = Pcg->Tdbp->GetColumns(); colp; colp = colp->GetNext()) if (!colp->IsSpecial()) @@ -560,7 +615,7 @@ bool CMgoConn::DocWrite(PGLOBAL g, PINCOL icp) { for (PKC kp = icp->Klist; kp; kp = kp->Next) if (kp->Incolp) { - bool isdoc = !kp->Incolp->Array; + bool isdoc = !kp->Array; if (isdoc) BSON_APPEND_DOCUMENT_BEGIN(icp->Child, kp->Key, kp->Incolp->Child); @@ -582,7 +637,7 @@ bool CMgoConn::DocWrite(PGLOBAL g, PINCOL icp) } // end of DocWrite /***********************************************************************/ -/* WriteDB: Data Base write routine for DOS access method. */ +/* WriteDB: Data Base write routine for CMGO access method. */ /***********************************************************************/ int CMgoConn::Write(PGLOBAL g) { @@ -590,22 +645,45 @@ int CMgoConn::Write(PGLOBAL g) PTDB tp = Pcg->Tdbp; if (tp->GetMode() == MODE_INSERT) { - Fpc->Init(); + if (!Pcg->Line) { + Fpc->Init(); - if (DocWrite(g, Fpc)) - return RC_FX; + if (DocWrite(g, Fpc)) + return RC_FX; - if (trace(2)) { - char *str = bson_as_json(Fpc->Child, NULL); - htrc("Inserting: %s\n", str); - bson_free(str); - } // endif trace + if (trace(2)) { + char* str = bson_as_json(Fpc->Child, NULL); + htrc("Inserting: %s\n", str); + bson_free(str); + } // endif trace - if (!mongoc_collection_insert(Collection, MONGOC_INSERT_NONE, - Fpc->Child, NULL, &Error)) { - sprintf(g->Message, "Mongo insert: %s", Error.message); - rc = RC_FX; - } // endif insert + if (!mongoc_collection_insert(Collection, MONGOC_INSERT_NONE, + Fpc->Child, NULL, &Error)) { + sprintf(g->Message, "Mongo insert: %s", Error.message); + rc = RC_FX; + } // endif insert + + } else { + const uint8_t* val = (const uint8_t*)Pcg->Line; + bson_t* doc = bson_new_from_json(val, -1, &Error); + + if (doc && trace(2)) { + char* str = bson_as_json(doc, NULL); + htrc("Inserting: %s\n", str); + bson_free(str); + } // endif trace + + if (!doc) { + sprintf(g->Message, "bson_new_from_json: %s", Error.message); + rc = RC_FX; + } else if (!mongoc_collection_insert(Collection, + MONGOC_INSERT_NONE, doc, NULL, &Error)) { + sprintf(g->Message, "Mongo insert: %s", Error.message); + bson_destroy(doc); + rc = RC_FX; + } // endif insert + + } // endif Line } else { bool b = false; @@ -614,19 +692,26 @@ int CMgoConn::Write(PGLOBAL g) bson_iter_init(&iter, Document); - if (bson_iter_find(&iter, "_id")) { - if (BSON_ITER_HOLDS_OID(&iter)) - b = BSON_APPEND_OID(query, "_id", bson_iter_oid(&iter)); - else if (BSON_ITER_HOLDS_INT32(&iter)) - b = BSON_APPEND_INT32(query, "_id", bson_iter_int32(&iter)); - else if (BSON_ITER_HOLDS_INT64(&iter)) - b = BSON_APPEND_INT64(query, "_id", bson_iter_int64(&iter)); - else if (BSON_ITER_HOLDS_DOUBLE(&iter)) - b = BSON_APPEND_DOUBLE(query, "_id", bson_iter_double(&iter)); - else if (BSON_ITER_HOLDS_UTF8(&iter)) - b = BSON_APPEND_UTF8(query, "_id", bson_iter_utf8(&iter, NULL)); - - } // endif iter + if (bson_iter_find(&iter, "_id")) + switch (bson_iter_type(&iter)) { + case BSON_TYPE_OID: + b = BSON_APPEND_OID(query, "_id", bson_iter_oid(&iter)); + break; + case BSON_TYPE_UTF8: + b = BSON_APPEND_UTF8(query, "_id", bson_iter_utf8(&iter, NULL)); + break; + case BSON_TYPE_INT32: + b = BSON_APPEND_INT32(query, "_id", bson_iter_int32(&iter)); + break; + case BSON_TYPE_INT64: + b = BSON_APPEND_INT64(query, "_id", bson_iter_int64(&iter)); + break; + case BSON_TYPE_DOUBLE: + b = BSON_APPEND_DOUBLE(query, "_id", bson_iter_double(&iter)); + break; + default: + break; + } // endswitch iter if (b) { if (trace(2)) { @@ -721,7 +806,7 @@ void CMgoConn::Close(void) char *CMgoConn::Mini(PGLOBAL g, PCOL colp, const bson_t *bson, bool b) { char *s, *str = NULL; - char *Mbuf = (char*)PlugSubAlloc(g, NULL, colp->GetLength() + 1); + char *Mbuf = (char*)PlugSubAlloc(g, NULL, (size_t)colp->GetLength() + 1); int i, k = 0; bool ok = true; @@ -759,97 +844,100 @@ char *CMgoConn::Mini(PGLOBAL g, PCOL colp, const bson_t *bson, bool b) /***********************************************************************/ void CMgoConn::GetColumnValue(PGLOBAL g, PCOL colp) { - char *jpath = colp->GetJpath(g, false); - PVAL value = colp->GetValue(); + char *jpath = colp->GetJpath(g, false); + bool b = false; + PVAL value = colp->GetValue(); + bson_iter_t Iter; // Used to retrieve column value + bson_iter_t Desc; // Descendant iter - if (!strcmp(jpath, "*")) { + if (!*jpath || !strcmp(jpath, "*")) { value->SetValue_psz(Mini(g, colp, Document, false)); } else if (bson_iter_init(&Iter, Document) && bson_iter_find_descendant(&Iter, jpath, &Desc)) { - if (BSON_ITER_HOLDS_UTF8(&Desc)) - value->SetValue_psz((PSZ)bson_iter_utf8(&Desc, NULL)); - else if (BSON_ITER_HOLDS_INT32(&Desc)) - value->SetValue(bson_iter_int32(&Desc)); - else if (BSON_ITER_HOLDS_INT64(&Desc)) - value->SetValue(bson_iter_int64(&Desc)); - else if (BSON_ITER_HOLDS_DOUBLE(&Desc)) - value->SetValue(bson_iter_double(&Desc)); - else if (BSON_ITER_HOLDS_DATE_TIME(&Desc)) - value->SetValue(bson_iter_date_time(&Desc) / 1000); - else if (BSON_ITER_HOLDS_BOOL(&Desc)) { - bool b = bson_iter_bool(&Desc); + switch (bson_iter_type(&Desc)) { + case BSON_TYPE_UTF8: + value->SetValue_psz((PSZ)bson_iter_utf8(&Desc, NULL)); + break; + case BSON_TYPE_INT32: + value->SetValue(bson_iter_int32(&Desc)); + break; + case BSON_TYPE_INT64: + value->SetValue(bson_iter_int64(&Desc)); + break; + case BSON_TYPE_DOUBLE: + value->SetValue(bson_iter_double(&Desc)); + break; + case BSON_TYPE_DATE_TIME: + value->SetValue(bson_iter_date_time(&Desc) / 1000); + break; + case BSON_TYPE_BOOL: + b = bson_iter_bool(&Desc); - if (value->IsTypeNum()) - value->SetValue(b ? 1 : 0); - else - value->SetValue_psz(b ? "true" : "false"); + if (value->IsTypeNum()) + value->SetValue(b ? 1 : 0); + else + value->SetValue_psz(b ? "true" : "false"); - } else if (BSON_ITER_HOLDS_OID(&Desc)) { - char str[25]; + break; + case BSON_TYPE_OID: { + char str[25]; - bson_oid_to_string(bson_iter_oid(&Desc), str); - value->SetValue_psz(str); - } else if (BSON_ITER_HOLDS_NULL(&Iter)) { - // Apparently this does not work... - value->Reset(); - value->SetNull(true); - } else if (BSON_ITER_HOLDS_DECIMAL128(&Desc)) { - char *str = NULL; - bson_decimal128_t dec; + bson_oid_to_string(bson_iter_oid(&Desc), str); + value->SetValue_psz(str); + } break; + case BSON_TYPE_ARRAY: + b = true; + // passthru + case BSON_TYPE_DOCUMENT: + { // All this because MongoDB can return the wrong type + int i = 0; + const uint8_t *data = NULL; + uint32_t len = 0; - bson_iter_decimal128(&Desc, &dec); - bson_decimal128_to_string(&dec, str); - value->SetValue_psz(str); - bson_free(str); - } else if (BSON_ITER_HOLDS_DOCUMENT(&Iter)) { - bson_t *doc; - const uint8_t *data = NULL; - uint32_t len = 0; + for (; i < 2; i++) { + if (b) // Try array first + bson_iter_array(&Desc, &len, &data); + else + bson_iter_document(&Desc, &len, &data); - bson_iter_document(&Desc, &len, &data); + if (!data) { + len = 0; + b = !b; + } else + break; - if (data) { - doc = bson_new_from_data(data, len); - value->SetValue_psz(Mini(g, colp, doc, false)); - bson_destroy(doc); - } else { - // ... but we can come here in case of NULL! - value->Reset(); - value->SetNull(true); - } // endif data - - } else if (BSON_ITER_HOLDS_ARRAY(&Iter)) { - bson_t *arr; - const uint8_t *data = NULL; - uint32_t len = 0; - - bson_iter_array(&Desc, &len, &data); - - if (data) { - arr = bson_new_from_data(data, len); - value->SetValue_psz(Mini(g, colp, arr, true)); - bson_destroy(arr); - } else { - // This is a bug in returning the wrong type - // This fix is only for document items - bson_t *doc; - - bson_iter_document(&Desc, &len, &data); + } // endfor i if (data) { - doc = bson_new_from_data(data, len); - value->SetValue_psz(Mini(g, colp, doc, false)); + bson_t *doc = bson_new_from_data(data, len); + + value->SetValue_psz(Mini(g, colp, doc, b)); bson_destroy(doc); } else { // ... or we can also come here in case of NULL! value->Reset(); value->SetNull(true); - } // endif data + } // endif data - } // endif data + } break; + case BSON_TYPE_NULL: + // Apparently this does not work... + value->Reset(); + value->SetNull(true); + break; + case BSON_TYPE_DECIMAL128: { + char* str = NULL; + bson_decimal128_t dec; - } else - value->Reset(); + bson_iter_decimal128(&Desc, &dec); + bson_decimal128_to_string(&dec, str); + value->SetValue_psz(str); + bson_free(str); + } break; + default: + value->Reset(); + break; + } // endswitch Desc } else { // Field does not exist @@ -875,7 +963,28 @@ bool CMgoConn::AddValue(PGLOBAL g, PCOL colp, bson_t *doc, char *key, bool upd) } else switch (colp->GetResultType()) { case TYPE_STRING: - rc = BSON_APPEND_UTF8(doc, key, value->GetCharValue()); + if (colp->Stringify()) { + const uint8_t *val = (const uint8_t*)value->GetCharValue(); + bson_t *bsn = bson_new_from_json(val, -1, &Error); + + if (!bsn) { + sprintf (g->Message, "AddValue: %s", Error.message); + return true; + } else if (*key) { + if (*val == '[') + rc = BSON_APPEND_ARRAY(doc, key, bsn); + else + rc = BSON_APPEND_DOCUMENT(doc, key, bsn); + + } else { + bson_copy_to (bsn, doc); + rc = true; + } // endif's + + bson_free(bsn); + } else + rc = BSON_APPEND_UTF8(doc, key, value->GetCharValue()); + break; case TYPE_INT: case TYPE_SHORT: diff --git a/storage/connect/cmgoconn.h b/storage/connect/cmgoconn.h index b1216ac576c..5c9fb4f763d 100644 --- a/storage/connect/cmgoconn.h +++ b/storage/connect/cmgoconn.h @@ -28,11 +28,8 @@ typedef struct mongo_parms { PCSZ Coll_name; PCSZ Options; PCSZ Filter; + PCSZ Line; bool Pipe; -//PCSZ User; // User connect info -//PCSZ Pwd; // Password connect info -//int Fsize; // Fetch size -//bool Scrollable; // Scrollable cursor } CMGOPARM, *PCPARM; typedef struct KEYCOL { @@ -40,15 +37,23 @@ typedef struct KEYCOL { PINCOL Incolp; PCOL Colp; char *Key; + bool Array; } *PKC; +typedef struct _path_list *PTHP; + +typedef struct _path_list { + PSZ Path; + PTHP Next; +} PTH; + /***********************************************************************/ /* Used when inserting values in a MongoDB collection. */ /***********************************************************************/ class INCOL : public BLOCK { public: // Constructor - INCOL(bool ar) { Child = bson_new(); Klist = NULL; Array = ar; } + INCOL(void) { Child = bson_new(); Klist = NULL; } // Methods void AddCol(PGLOBAL g, PCOL colp, char *jp); @@ -58,7 +63,6 @@ public: //Members bson_t *Child; PKC Klist; - bool Array; }; // end of INCOL; /***********************************************************************/ @@ -80,6 +84,7 @@ public: bool IsConnected(void) { return m_Connected; } bool Connect(PGLOBAL g); int CollSize(PGLOBAL g); + void CMgoConn::Project(PGLOBAL g, PSTRG s); bool MakeCursor(PGLOBAL g); int ReadNext(PGLOBAL g); PSZ GetDocument(PGLOBAL g); @@ -108,8 +113,6 @@ protected: bson_t *Query; // MongoDB cursor filter bson_t *Opts; // MongoDB cursor options bson_error_t Error; - bson_iter_t Iter; // Used to retrieve column value - bson_iter_t Desc; // Descendant iter PINCOL Fpc; // To insert INCOL classes PFBLOCK fp; bool m_Connected; diff --git a/storage/connect/colblk.h b/storage/connect/colblk.h index b22933d9ebb..f303528f982 100644 --- a/storage/connect/colblk.h +++ b/storage/connect/colblk.h @@ -38,7 +38,8 @@ class DllExport COLBLK : public XOBJECT { virtual PTDB GetTo_Tdb(void) {return To_Tdb;} virtual int GetClustered(void) {return 0;} virtual int IsClustered(void) {return FALSE;} - virtual PSZ GetJpath(PGLOBAL g, bool proj) {return NULL;} + virtual bool Stringify(void) {return FALSE;} + virtual PSZ GetJpath(PGLOBAL g, bool proj) {return NULL;} PCOL GetNext(void) {return Next;} PSZ GetName(void) {return Name;} int GetIndex(void) {return Index;} diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index b3c0b0c69b2..f85035d6e06 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -5470,14 +5470,13 @@ static bool add_field(String* sql, TABTYPE ttp, const char* field_name, int typ, } // endif rem if (fmt && *fmt) { - switch (ttp) { - case TAB_JSON: error |= sql->append(" JPATH='"); break; -#if defined(BSON_SUPPORT) - case TAB_BSON: error |= sql->append(" JPATH='"); break; -#endif // BSON_SUPPORT - case TAB_XML: error |= sql->append(" XPATH='"); break; - default: error |= sql->append(" FIELD_FORMAT='"); - } // endswitch ttp + switch (ttp) { + case TAB_MONGO: + case TAB_BSON: + case TAB_JSON: error |= sql->append(" JPATH='"); break; + case TAB_XML: error |= sql->append(" XPATH='"); break; + default: error |= sql->append(" FIELD_FORMAT='"); + } // endswitch ttp error |= sql->append_for_single_quote(fmt, strlen(fmt)); error |= sql->append("'"); diff --git a/storage/connect/jmgfam.cpp b/storage/connect/jmgfam.cpp index 2d45753ec63..d7f469cf4fe 100644 --- a/storage/connect/jmgfam.cpp +++ b/storage/connect/jmgfam.cpp @@ -1,11 +1,11 @@ /************ JMONGO FAM C++ Program Source Code File (.CPP) ***********/ /* PROGRAM NAME: jmgfam.cpp */ /* ------------- */ -/* Version 1.1 */ +/* Version 1.2 */ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 20017 - 2020 */ +/* (C) Copyright to the author Olivier BERTRAND 20017 - 2021 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -241,8 +241,8 @@ bool JMGFAM::OpenTableFile(PGLOBAL g) return true; } // endif Mode - if (Mode == MODE_INSERT) - Jcp->MakeColumnGroups(g, Tdbp); +//if (Mode == MODE_INSERT) +// Jcp->MakeColumnGroups(g, Tdbp); if (Mode != MODE_UPDATE) return Jcp->MakeCursor(g, Tdbp, Options, Filter, Pipe); @@ -346,14 +346,14 @@ int JMGFAM::ReadBuffer(PGLOBAL g) } // end of ReadBuffer /***********************************************************************/ -/* WriteBuffer: File write routine for MGO access method. */ +/* WriteBuffer: File write routine for JMG access method. */ /***********************************************************************/ int JMGFAM::WriteBuffer(PGLOBAL g) { int rc = RC_OK; if (Mode == MODE_INSERT) { - rc = Jcp->DocWrite(g); + rc = Jcp->DocWrite(g, Tdbp->GetLine()); } else if (Mode == MODE_DELETE) { rc = Jcp->DocDelete(g, false); } else if (Mode == MODE_UPDATE) { diff --git a/storage/connect/jmgoconn.cpp b/storage/connect/jmgoconn.cpp index 0af91bc78cd..a4091e88bbf 100644 --- a/storage/connect/jmgoconn.cpp +++ b/storage/connect/jmgoconn.cpp @@ -1,7 +1,7 @@ /************ JMgoConn C++ Functions Source Code File (.CPP) ***********/ -/* Name: JMgoConn.CPP Version 1.1 */ +/* Name: JMgoConn.CPP Version 1.2 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2017 */ +/* (C) Copyright to the author Olivier BERTRAND 2017 - 2021 */ /* */ /* This file contains the MongoDB Java connection classes functions. */ /***********************************************************************/ @@ -24,7 +24,7 @@ #define nullptr 0 -bool IsNum(PSZ s); +bool IsArray(PSZ s); bool MakeSelector(PGLOBAL g, PFIL fp, PSTRG s); /* --------------------------- Class JNCOL --------------------------- */ @@ -43,19 +43,21 @@ void JNCOL::AddCol(PGLOBAL g, PCOL colp, PSZ jp) *p++ = 0; for (kp = Klist; kp; kp = kp->Next) - if (kp->Jncolp && !strcmp(jp, kp->Key)) + if (kp->Jncolp && ((kp->Key && !strcmp(jp, kp->Key)) + || (!kp->Key && IsArray(jp) && kp->N == atoi(jp)))) break; if (!kp) { - icp = new(g) JNCOL(IsNum(p)); + icp = new(g) JNCOL(); kcp = (PJKC)PlugSubAlloc(g, NULL, sizeof(JKCOL)); kcp->Next = NULL; kcp->Jncolp = icp; kcp->Colp = NULL; + kcp->Array = IsArray(jp); - if (Array) { + if (kcp->Array) { kcp->Key = NULL; - kcp->N = atoi(p); + kcp->N = atoi(jp); } else { kcp->Key = PlugDup(g, jp); kcp->N = 0; @@ -75,12 +77,12 @@ void JNCOL::AddCol(PGLOBAL g, PCOL colp, PSZ jp) icp->AddCol(g, colp, p); } else { kcp = (PJKC)PlugSubAlloc(g, NULL, sizeof(JKCOL)); - kcp->Next = NULL; kcp->Jncolp = NULL; kcp->Colp = colp; + kcp->Array = IsArray(jp); - if (Array) { + if (kcp->Array) { kcp->Key = NULL; kcp->N = atoi(jp); } else { @@ -108,7 +110,7 @@ JMgoConn::JMgoConn(PGLOBAL g, PCSZ collname, PCSZ wrapper) CollName = collname; readid = fetchid = getdocid = objfldid = fcollid = acollid = mkdocid = docaddid = mkarid = araddid = insertid = updateid = - deleteid = gcollid = countid = rewindid = nullptr; + deleteid = gcollid = countid = rewindid = mkbsonid = nullptr; DiscFunc = "MongoDisconnect"; Fpc = NULL; m_Fetch = 0; @@ -235,7 +237,7 @@ bool JMgoConn::MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options, PCSZ filter, bool pipe) { const char *p; - bool b = false, id = (tdbp->GetMode() != MODE_READ), all = false; + bool id, b = false, all = false; uint len; PCOL cp; PSZ jp; @@ -246,13 +248,14 @@ bool JMgoConn::MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options, if (Options && !stricmp(Options, "all")) { Options = NULL; all = true; - } // endif Options + } else + id = (tdbp->GetMode() == MODE_UPDATE || tdbp->GetMode() == MODE_DELETE); - for (cp = tdbp->GetColumns(); cp; cp = cp->GetNext()) - if (!strcmp(cp->GetName(), "_id")) - id = true; - else if (cp->GetFmt() && !strcmp(cp->GetFmt(), "*") && (!Options || pipe)) + for (cp = tdbp->GetColumns(); cp && !all; cp = cp->GetNext()) + if (cp->GetFmt() && !strcmp(cp->GetFmt(), "*") && (!Options || pipe)) all = true; + else if (!id) + id = !strcmp(cp->GetJpath(g, false), "_id"); if (pipe && Options) { if (trace(1)) @@ -535,7 +538,7 @@ PSZ JMgoConn::GetDocument(void) /***********************************************************************/ void JMgoConn::MakeColumnGroups(PGLOBAL g, PTDB tdbp) { - Fpc = new(g) JNCOL(false); + Fpc = new(g) JNCOL(); for (PCOL colp = tdbp->GetColumns(); colp; colp = colp->GetNext()) if (!colp->IsSpecial()) @@ -553,7 +556,7 @@ bool JMgoConn::GetMethodId(PGLOBAL g, MODE mode) return true; if (gmID(g, docaddid, "DocAdd", - "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z")) + "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;I)Z")) return true; if (gmID(g, updateid, "CollUpdate", "(Ljava/lang/Object;)J")) @@ -563,14 +566,19 @@ bool JMgoConn::GetMethodId(PGLOBAL g, MODE mode) if (gmID(g, mkdocid, "MakeDocument", "()Ljava/lang/Object;")) return true; + if (gmID(g, mkbsonid, "MakeBson", + "(Ljava/lang/String;I)Ljava/lang/Object;")) + return true; + if (gmID(g, docaddid, "DocAdd", - "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z")) + "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;I)Z")) return true; if (gmID(g, mkarid, "MakeArray", "()Ljava/lang/Object;")) return true; - if (gmID(g, araddid, "ArrayAdd", "(Ljava/lang/Object;ILjava/lang/Object;)Z")) + if (gmID(g, araddid, "ArrayAdd", + "(Ljava/lang/Object;ILjava/lang/Object;I)Z")) return true; if (gmID(g, insertid, "CollInsert", "(Ljava/lang/Object;)Z")) @@ -638,49 +646,82 @@ jobject JMgoConn::MakeObject(PGLOBAL g, PCOL colp, bool&error ) return val; } // end of MakeObject +/***********************************************************************/ +/* Stringify. */ +/***********************************************************************/ +bool JMgoConn::Stringify(PCOL colp) +{ + bool b = false; + + if (colp) + b = (colp->Stringify() && colp->GetResultType() == TYPE_STRING); + + return b; +} // end of Stringify + /***********************************************************************/ /* MakeDoc. */ /***********************************************************************/ jobject JMgoConn::MakeDoc(PGLOBAL g, PJNCOL jcp) { - bool error = false; + int j; + bool b, error = false; jobject parent, child, val; jstring jkey; - - if (jcp->Array) + PJKC kp = jcp->Klist; + + if (kp->Array) parent = env->CallObjectMethod(job, mkarid); else parent = env->CallObjectMethod(job, mkdocid); - for (PJKC kp = jcp->Klist; kp; kp = kp->Next) + for (j = 0; kp; j = 0, kp = kp->Next) { + if (Stringify(kp->Colp)) { + switch (*kp->Colp->GetCharValue()) { + case '{': j = 1; break; + case '[': j = 2; break; + default: break; + } // endswitch + + b = (!kp->Key || !*kp->Key || *kp->Key == '*'); + } else + b = false; + if (kp->Jncolp) { if (!(child = MakeDoc(g, kp->Jncolp))) return NULL; - if (!jcp->Array) { + if (!kp->Array) { jkey = env->NewStringUTF(kp->Key); - if (env->CallBooleanMethod(job, docaddid, parent, jkey, child)) + if (env->CallBooleanMethod(job, docaddid, parent, jkey, child, j)) return NULL; env->DeleteLocalRef(jkey); } else - if (env->CallBooleanMethod(job, araddid, parent, kp->N, child)) + if (env->CallBooleanMethod(job, araddid, parent, kp->N, child, j)) return NULL; + env->DeleteLocalRef(child); } else { if (!(val = MakeObject(g, kp->Colp, error))) { if (error) return NULL; - } else if (!jcp->Array) { - jkey = env->NewStringUTF(kp->Key); + } else if (!kp->Array) { + if (!b) { + jkey = env->NewStringUTF(kp->Key); - if (env->CallBooleanMethod(job, docaddid, parent, jkey, val)) - return NULL; + if (env->CallBooleanMethod(job, docaddid, parent, jkey, val, j)) + return NULL; - env->DeleteLocalRef(jkey); - } else if (env->CallBooleanMethod(job, araddid, parent, kp->N, val)) { + env->DeleteLocalRef(jkey); + } else { + env->DeleteLocalRef(parent); + parent = env->CallObjectMethod(job, mkbsonid, val, j); + } // endif b + + } else if (env->CallBooleanMethod(job, araddid, parent, kp->N, val, j)) { if (Check(-1)) sprintf(g->Message, "ArrayAdd: %s", Msg); else @@ -689,19 +730,38 @@ jobject JMgoConn::MakeDoc(PGLOBAL g, PJNCOL jcp) return NULL; } // endif ArrayAdd + env->DeleteLocalRef(val); } // endif Jncolp + } // endfor kp + return parent; } // end of MakeDoc /***********************************************************************/ /* Insert a new document in the collation. */ /***********************************************************************/ -int JMgoConn::DocWrite(PGLOBAL g) +int JMgoConn::DocWrite(PGLOBAL g, PCSZ line) { - jobject doc; + int rc = RC_OK; + jobject doc = nullptr; - if (!Fpc || !(doc = MakeDoc(g, Fpc))) + if (line) { + int j; + jobject val = env->NewStringUTF(line); + + switch (*line) { + case '{': j = 1; break; + case '[': j = 2; break; + default: j = 0; break; + } // endswitch line + + doc = env->CallObjectMethod(job, mkbsonid, val, j); + env->DeleteLocalRef(val); + } else if (Fpc) + doc = MakeDoc(g, Fpc); + + if (!doc) return RC_FX; if (env->CallBooleanMethod(job, insertid, doc)) { @@ -710,10 +770,11 @@ int JMgoConn::DocWrite(PGLOBAL g) else sprintf(g->Message, "CollInsert: unknown error"); - return RC_FX; + rc = RC_FX; } // endif Insert - return RC_OK; + env->DeleteLocalRef(doc); + return rc; } // end of DocWrite /***********************************************************************/ @@ -721,7 +782,7 @@ int JMgoConn::DocWrite(PGLOBAL g) /***********************************************************************/ int JMgoConn::DocUpdate(PGLOBAL g, PTDB tdbp) { - int rc = RC_OK; + int j = 0, rc = RC_OK; bool error; PCOL colp; jstring jkey; @@ -734,8 +795,14 @@ int JMgoConn::DocUpdate(PGLOBAL g, PTDB tdbp) if (error) return RC_FX; + else if (Stringify(colp)) + switch (*colp->GetCharValue()) { + case '{': j = 1; break; + case '[': j = 2; break; + default: break; + } // endswitch - if (env->CallBooleanMethod(job, docaddid, updlist, jkey, val)) + if (env->CallBooleanMethod(job, docaddid, updlist, jkey, val, j)) return RC_OK; env->DeleteLocalRef(jkey); @@ -745,7 +812,7 @@ int JMgoConn::DocUpdate(PGLOBAL g, PTDB tdbp) upd = env->CallObjectMethod(job, mkdocid); jkey = env->NewStringUTF("$set"); - if (env->CallBooleanMethod(job, docaddid, upd, jkey, updlist)) + if (env->CallBooleanMethod(job, docaddid, upd, jkey, updlist, 0)) return RC_OK; env->DeleteLocalRef(jkey); diff --git a/storage/connect/jmgoconn.h b/storage/connect/jmgoconn.h index 8ee7985d760..9fed1907abc 100644 --- a/storage/connect/jmgoconn.h +++ b/storage/connect/jmgoconn.h @@ -25,6 +25,7 @@ typedef struct JKCOL { PCOL Colp; char *Key; int N; + bool Array; } *PJKC; /***********************************************************************/ @@ -33,18 +34,18 @@ typedef struct JKCOL { class JNCOL : public BLOCK { public: // Constructor - JNCOL(bool ar) { Klist = NULL; Array = ar; } +//JNCOL(bool ar) { Klist = NULL; Array = ar; } + JNCOL(void) { Klist = NULL; } // Methods void AddCol(PGLOBAL g, PCOL colp, PSZ jp); //Members PJKC Klist; - bool Array; }; // end of JNCOL; /***********************************************************************/ -/* JMgoConn class. */ +/* JMgoConn class. */ /***********************************************************************/ class JMgoConn : public JAVAConn { friend class TDBJMG; @@ -81,11 +82,12 @@ public: bool GetMethodId(PGLOBAL g, MODE mode); jobject MakeObject(PGLOBAL g, PCOL colp, bool& error); jobject MakeDoc(PGLOBAL g, PJNCOL jcp); - int DocWrite(PGLOBAL g); + int DocWrite(PGLOBAL g, PCSZ line); int DocUpdate(PGLOBAL g, PTDB tdbp); int DocDelete(PGLOBAL g, bool all); bool Rewind(void); PSZ GetDocument(void); + bool Stringify(PCOL colp); protected: // Members @@ -100,6 +102,7 @@ protected: jmethodID getdocid; // The GetDoc method ID jmethodID objfldid; // The ObjectField method ID jmethodID mkdocid; // The MakeDocument method ID + jmethodID mkbsonid; // The MakeBson method ID jmethodID docaddid; // The DocAdd method ID jmethodID mkarid; // The MakeArray method ID jmethodID araddid; // The ArrayAdd method ID diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index f65294429db..b1f9f10957b 100644 --- a/storage/connect/json.cpp +++ b/storage/connect/json.cpp @@ -77,6 +77,24 @@ bool IsNum(PSZ s) return true; } // end of IsNum +/***********************************************************************/ +/* IsArray: check whether this is a Mongo array path. */ +/***********************************************************************/ +bool IsArray(PSZ s) +{ + char* p = s; + + if (!p || !*p) + return false; + else for (; *p; p++) + if (*p == '.') + break; + else if (!isdigit(*p)) + return false; + + return true; +} // end of IsArray + /***********************************************************************/ /* NextChr: return the first found '[' or Sep pointer. */ /***********************************************************************/ @@ -1326,9 +1344,9 @@ bool JARRAY::Merge(PGLOBAL g, PJSON jsp) } // end of Merge /***********************************************************************/ -/* Set the nth Value of the Array Value list. */ +/* Set the nth Value of the Array Value list or add it. */ /***********************************************************************/ -bool JARRAY::SetArrayValue(PGLOBAL g, PJVAL jvp, int n) +void JARRAY::SetArrayValue(PGLOBAL g, PJVAL jvp, int n) { int i = 0; PJVAL jp, *jpp = &First; @@ -1339,7 +1357,6 @@ bool JARRAY::SetArrayValue(PGLOBAL g, PJVAL jvp, int n) *jpp = jvp; jvp->Next = (jp ? jp->Next : NULL); - return false; } // end of SetValue /***********************************************************************/ @@ -1417,7 +1434,7 @@ bool JARRAY::IsNull(void) /***********************************************************************/ JVALUE::JVALUE(PJSON jsp) : JSON() { - if (jsp->GetType() == TYPE_JVAL) { + if (jsp && jsp->GetType() == TYPE_JVAL) { PJVAL jvp = (PJVAL)jsp; // Val = ((PJVAL)jsp)->GetVal(); @@ -1434,7 +1451,7 @@ JVALUE::JVALUE(PJSON jsp) : JSON() } else { Jsp = jsp; // Val = NULL; - DataType = TYPE_JSON; + DataType = Jsp ? TYPE_JSON : TYPE_NULL; Nd = 0; } // endif Type diff --git a/storage/connect/json.h b/storage/connect/json.h index 3a026f5df22..ef5f6c7b7de 100644 --- a/storage/connect/json.h +++ b/storage/connect/json.h @@ -184,7 +184,7 @@ class JARRAY : public JSON { // Specific PJVAL AddArrayValue(PGLOBAL g, PJVAL jvp = NULL, int* x = NULL); - bool SetArrayValue(PGLOBAL g, PJVAL jvp, int i); + void SetArrayValue(PGLOBAL g, PJVAL jvp, int i); void InitArray(PGLOBAL g); protected: diff --git a/storage/connect/mysql-test/connect/r/bson_mongo_c.result b/storage/connect/mysql-test/connect/r/bson_mongo_c.result index 83bf7cd1974..e2273be4bec 100644 --- a/storage/connect/mysql-test/connect/r/bson_mongo_c.result +++ b/storage/connect/mysql-test/connect/r/bson_mongo_c.result @@ -363,7 +363,7 @@ _id item prices_0 prices_1 prices_2 prices_3 prices_4 1 journal 87 45 63 12 78 2 notebook 123 456 789 NULL NULL 3 paper 5 7 3 8 NULL -4 planner 25 71 44 27 NULL +4 planner 25 71 NULL 44 27 5 postcard 5 7 3 8 NULL DROP TABLE t1; # diff --git a/storage/connect/mysql-test/connect/r/json_mongo_c.result b/storage/connect/mysql-test/connect/r/json_mongo_c.result index 482ccc85b57..6d4957167fc 100644 --- a/storage/connect/mysql-test/connect/r/json_mongo_c.result +++ b/storage/connect/mysql-test/connect/r/json_mongo_c.result @@ -363,7 +363,7 @@ _id item prices_0 prices_1 prices_2 prices_3 prices_4 1 journal 87 45 63 12 78 2 notebook 123 456 789 NULL NULL 3 paper 5 7 3 8 NULL -4 planner 25 71 44 27 NULL +4 planner 25 71 NULL 44 27 5 postcard 5 7 3 8 NULL DROP TABLE t1; # diff --git a/storage/connect/mysql-test/connect/r/mongo_c.result b/storage/connect/mysql-test/connect/r/mongo_c.result index 8b86ce32943..899a123dc5f 100644 --- a/storage/connect/mysql-test/connect/r/mongo_c.result +++ b/storage/connect/mysql-test/connect/r/mongo_c.result @@ -64,23 +64,23 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `_id` char(24) NOT NULL, - `address_building` char(10) NOT NULL `FIELD_FORMAT`='address.building', - `address_coord` varchar(512) NOT NULL `FIELD_FORMAT`='address.coord', - `address_street` char(38) NOT NULL `FIELD_FORMAT`='address.street', - `address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', + `address_building` char(10) NOT NULL `JPATH`='address.building', + `address_coord` varchar(512) NOT NULL `JPATH`='address.coord', + `address_street` char(38) NOT NULL `JPATH`='address.street', + `address_zipcode` char(5) NOT NULL `JPATH`='address.zipcode', `borough` char(13) NOT NULL, `cuisine` char(64) NOT NULL, - `grades_0` varchar(512) DEFAULT NULL `FIELD_FORMAT`='grades.0', + `grades_0` varchar(512) DEFAULT NULL `JPATH`='grades.0', `name` char(98) NOT NULL, `restaurant_id` char(8) NOT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MONGO' `TABNAME`='restaurants' `OPTION_LIST`='Depth=1,Driver=C,Version=0' `DATA_CHARSET`='utf8' SELECT * FROM t1 LIMIT 5; _id address_building address_coord address_street address_zipcode borough cuisine grades_0 name restaurant_id -58ada47de5a51ddfcd5ed51c 1007 Morris Park Ave 10462 Bronx Bakery {"date":{"$date":1393804800000},"grade":"A","score":2} Morris Park Bake Shop 30075445 -58ada47de5a51ddfcd5ed51d 469 Flatbush Avenue 11225 Brooklyn Hamburgers {"date":{"$date":1419897600000},"grade":"A","score":8} Wendy'S 30112340 -58ada47de5a51ddfcd5ed51e 351 West 57 Street 10019 Manhattan Irish {"date":{"$date":1409961600000},"grade":"A","score":2} Dj Reynolds Pub And Restaurant 30191841 -58ada47de5a51ddfcd5ed51f 2780 Stillwell Avenue 11224 Brooklyn American {"date":{"$date":1402358400000},"grade":"A","score":5} Riviera Caterer 40356018 -58ada47de5a51ddfcd5ed520 97-22 63 Road 11374 Queens Jewish/Kosher {"date":{"$date":1416787200000},"grade":"Z","score":20} Tov Kosher Kitchen 40356068 +58ada47de5a51ddfcd5ed51c 1007 [-73.856076999999999089,40.848447000000000173] Morris Park Ave 10462 Bronx Bakery {"date":{"$date":1393804800000},"grade":"A","score":2} Morris Park Bake Shop 30075445 +58ada47de5a51ddfcd5ed51d 469 [-73.96170399999999745,40.66294200000000103] Flatbush Avenue 11225 Brooklyn Hamburgers {"date":{"$date":1419897600000},"grade":"A","score":8} Wendy'S 30112340 +58ada47de5a51ddfcd5ed51e 351 [-73.985135599999992451,40.767691900000002647] West 57 Street 10019 Manhattan Irish {"date":{"$date":1409961600000},"grade":"A","score":2} Dj Reynolds Pub And Restaurant 30191841 +58ada47de5a51ddfcd5ed51f 2780 [-73.982419999999990523,40.579504999999997494] Stillwell Avenue 11224 Brooklyn American {"date":{"$date":1402358400000},"grade":"A","score":5} Riviera Caterer 40356018 +58ada47de5a51ddfcd5ed520 97-22 [-73.860115199999995639,40.731173900000001709] 63 Road 11374 Queens Jewish/Kosher {"date":{"$date":1416787200000},"grade":"Z","score":20} Tov Kosher Kitchen 40356068 DROP TABLE t1; # # Dropping a column @@ -249,14 +249,14 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `_id` char(24) NOT NULL, - `address_building` char(6) NOT NULL `FIELD_FORMAT`='address.building', - `address_coord_0` double(12,6) NOT NULL `FIELD_FORMAT`='address.coord.0', - `address_street` char(25) NOT NULL `FIELD_FORMAT`='address.street', - `address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', + `address_building` char(6) NOT NULL `JPATH`='address.building', + `address_coord_0` double(12,6) NOT NULL `JPATH`='address.coord.0', + `address_street` char(25) NOT NULL `JPATH`='address.street', + `address_zipcode` char(5) NOT NULL `JPATH`='address.zipcode', `borough` char(13) NOT NULL, - `grades_0_date` datetime NOT NULL `FIELD_FORMAT`='grades.0.date', - `grades_0_grade` char(14) NOT NULL `FIELD_FORMAT`='grades.0.grade', - `grades_0_score` int(11) NOT NULL `FIELD_FORMAT`='grades.0.score', + `grades_0_date` datetime NOT NULL `JPATH`='grades.0.date', + `grades_0_grade` char(14) NOT NULL `JPATH`='grades.0.grade', + `grades_0_score` int(11) NOT NULL `JPATH`='grades.0.score', `name` char(32) NOT NULL, `restaurant_id` char(8) NOT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MONGO' `TABNAME`='restaurants' `COLIST`='{"projection":{"cuisine":0}}' `FILTER`='{"cuisine":"French","borough":{"$ne":"Manhattan"}}' `OPTION_LIST`='Driver=C,level=2,version=0' diff --git a/storage/connect/mysql-test/connect/r/mongo_java_2.result b/storage/connect/mysql-test/connect/r/mongo_java_2.result index cccda2760d6..bcedd717cc4 100644 --- a/storage/connect/mysql-test/connect/r/mongo_java_2.result +++ b/storage/connect/mysql-test/connect/r/mongo_java_2.result @@ -64,13 +64,13 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `_id` char(24) NOT NULL, - `address_building` char(10) NOT NULL `FIELD_FORMAT`='address.building', - `address_coord` char(41) NOT NULL `FIELD_FORMAT`='address.coord', - `address_street` char(38) NOT NULL `FIELD_FORMAT`='address.street', - `address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', + `address_building` char(10) NOT NULL `JPATH`='address.building', + `address_coord` char(41) NOT NULL `JPATH`='address.coord', + `address_street` char(38) NOT NULL `JPATH`='address.street', + `address_zipcode` char(5) NOT NULL `JPATH`='address.zipcode', `borough` char(13) NOT NULL, `cuisine` char(64) NOT NULL, - `grades_0` char(99) DEFAULT NULL `FIELD_FORMAT`='grades.0', + `grades_0` char(99) DEFAULT NULL `JPATH`='grades.0', `name` char(98) NOT NULL, `restaurant_id` char(8) NOT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MONGO' `TABNAME`='restaurants' `OPTION_LIST`='Depth=1,Driver=Java,Version=2' `DATA_CHARSET`='utf8' @@ -249,14 +249,14 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `_id` char(24) NOT NULL, - `address_building` char(6) NOT NULL `FIELD_FORMAT`='address.building', - `address_coord_0` double(18,14) NOT NULL `FIELD_FORMAT`='address.coord.0', - `address_street` char(25) NOT NULL `FIELD_FORMAT`='address.street', - `address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', + `address_building` char(6) NOT NULL `JPATH`='address.building', + `address_coord_0` double(18,14) NOT NULL `JPATH`='address.coord.0', + `address_street` char(25) NOT NULL `JPATH`='address.street', + `address_zipcode` char(5) NOT NULL `JPATH`='address.zipcode', `borough` char(13) NOT NULL, - `grades_0_date` datetime NOT NULL `FIELD_FORMAT`='grades.0.date', - `grades_0_grade` char(14) NOT NULL `FIELD_FORMAT`='grades.0.grade', - `grades_0_score` int(2) NOT NULL `FIELD_FORMAT`='grades.0.score', + `grades_0_date` datetime NOT NULL `JPATH`='grades.0.date', + `grades_0_grade` char(14) NOT NULL `JPATH`='grades.0.grade', + `grades_0_score` int(2) NOT NULL `JPATH`='grades.0.score', `name` char(32) NOT NULL, `restaurant_id` char(8) NOT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MONGO' `TABNAME`='restaurants' `COLIST`='{"cuisine":0}' `FILTER`='{"cuisine":"French","borough":{"$ne":"Manhattan"}}' `OPTION_LIST`='Driver=Java,level=2,version=2' diff --git a/storage/connect/mysql-test/connect/r/mongo_java_3.result b/storage/connect/mysql-test/connect/r/mongo_java_3.result index ae39148a156..3183d4984d6 100644 --- a/storage/connect/mysql-test/connect/r/mongo_java_3.result +++ b/storage/connect/mysql-test/connect/r/mongo_java_3.result @@ -64,13 +64,13 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `_id` char(24) NOT NULL, - `address_building` char(10) NOT NULL `FIELD_FORMAT`='address.building', - `address_coord` char(39) NOT NULL `FIELD_FORMAT`='address.coord', - `address_street` char(38) NOT NULL `FIELD_FORMAT`='address.street', - `address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', + `address_building` char(10) NOT NULL `JPATH`='address.building', + `address_coord` char(39) NOT NULL `JPATH`='address.coord', + `address_street` char(38) NOT NULL `JPATH`='address.street', + `address_zipcode` char(5) NOT NULL `JPATH`='address.zipcode', `borough` char(13) NOT NULL, `cuisine` char(64) NOT NULL, - `grades_0` char(84) DEFAULT NULL `FIELD_FORMAT`='grades.0', + `grades_0` char(84) DEFAULT NULL `JPATH`='grades.0', `name` char(98) NOT NULL, `restaurant_id` char(8) NOT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MONGO' `TABNAME`='restaurants' `OPTION_LIST`='Depth=1,Driver=Java,Version=3' `DATA_CHARSET`='utf8' @@ -249,14 +249,14 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `_id` char(24) NOT NULL, - `address_building` char(6) NOT NULL `FIELD_FORMAT`='address.building', - `address_coord_0` double(18,14) NOT NULL `FIELD_FORMAT`='address.coord.0', - `address_street` char(25) NOT NULL `FIELD_FORMAT`='address.street', - `address_zipcode` char(5) NOT NULL `FIELD_FORMAT`='address.zipcode', + `address_building` char(6) NOT NULL `JPATH`='address.building', + `address_coord_0` double(18,14) NOT NULL `JPATH`='address.coord.0', + `address_street` char(25) NOT NULL `JPATH`='address.street', + `address_zipcode` char(5) NOT NULL `JPATH`='address.zipcode', `borough` char(13) NOT NULL, - `grades_0_date` datetime NOT NULL `FIELD_FORMAT`='grades.0.date', - `grades_0_grade` char(14) NOT NULL `FIELD_FORMAT`='grades.0.grade', - `grades_0_score` int(2) NOT NULL `FIELD_FORMAT`='grades.0.score', + `grades_0_date` datetime NOT NULL `JPATH`='grades.0.date', + `grades_0_grade` char(14) NOT NULL `JPATH`='grades.0.grade', + `grades_0_score` int(2) NOT NULL `JPATH`='grades.0.score', `name` char(32) NOT NULL, `restaurant_id` char(8) NOT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MONGO' `TABNAME`='restaurants' `COLIST`='{"cuisine":0}' `FILTER`='{"cuisine":"French","borough":{"$ne":"Manhattan"}}' `OPTION_LIST`='Driver=Java,level=2,version=3' diff --git a/storage/connect/mysql-test/connect/std_data/Mongo2.jar b/storage/connect/mysql-test/connect/std_data/Mongo2.jar index 9be654bd4c8e2a1a3fd159c2a69acb5acc55011c..ae485805d6a9f63bce2b2c0e12a42c3817f60618 100644 GIT binary patch delta 34056 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

n4T;mFW)Z-@Mgt2S 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 delta 33514 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 {=;Er-3$?bU0v9?M+X zH_vT9(sV3N-S_E+*0Jb09glmP3gh%T>U*2-y&hu=ho4gVqozL+vVbFPRm)%;{0cw6x3H{-i}DRVBz9Ev>KzB50O|Dt?#Mx9%? z+Fiz3jREmzh0jJjrK2P}@+`fqE`)y8J6hr2yY@M$Q>W|bi}XhypN@Lzw0OVU`J17T z61a;cFu*oQdbV=`|5Ru6#mKEiL!|hoxgTo=ayBlwtT(+_wC(tt9_>f`x{VG7^?WM*irW?u_1cJTm6ctHisRr;5hdGN}%7y>s^P9bWiV!$njkGUwNcU3sY<2cxy# zdL}D$37W?SD|Xo~j?)n6k^6jFRCk@$o4CpSVjhMuo~CP!%6Yd5KIw5Yy=?6D(Dco( zU(3b&Z_BsLf91z6&+|GTd(zLrH^#dqW6mDS%%tu5cIElIS^}S3I{)$TSd+(s${ z`6~Jvir@8~+>sgjwp&)HN%H8+Et5s-0!qs@;CMO=9ZL#wnv7{P1X*+VF@FF z{=4qKFdbGH-|<`i1OIRO)R5hD!16z7lPMv2Zj(PdEWXwJ%oUmXVW-no6~3}IuWQ*U zQ4s})LBA_L;zydbwEyt1#ZJws{C@t)lj}nImu*FlJvVIY|JcMvZk&+}qgo6tuug6; zDXZ)4opsaioKHMUaFVzFV^_0Xe1>yRmx{rI1E(jKv^`^=8J-X*Px!M84E+-fc7Y4R zcTW5{FTAa#Do*W>%!Y<@+2ht1^Ge2{=&qYa>AE=R5sgWzptzCX!o(@J-pz`*3r~q zzTK_INEcdDw)rTWc=RjfQbLwHB~;G8d%HJ_a(GPIU+25P@t}aK)5QrwJl&C6nO#eY zCV6tkW{G@wuu(d~;)r!Y>+X8?ym5DL%KMi?8*c6vB9AS+xWf8EiOGs6ea}C_C8o(^ zp7p_h0xHF2zB|eUYTS(B{lh5zV&~TV(&xBO$+hK53M!ceo8)CCygn{i)?KUi&LY2c z>d=+Cfv%>c`2m;qES5T6uIP1fleb{4!kNRLUVQXaR`7|l{qvmPV^?%kZ~c!c1qJjS zjh5A{bRQ`m9#P}}zN0C*p~A;YMK6wISL({+U%GYGu`j^il`31JrRT}O;YtIt*{4ij z;W(QZD*7Y}V!kj1N=oO(QwX>{4lmhYv5t&`lq?u1sR%Im%A}W&<`3Yc*$Ru~vQL}x zfw-?sz7jRtQJlO)VbOaME>K~SY>A@19YLOdK@QvooS~*bmjXAsI*4h&U zhs-dH0~PRnhn(5#t7tO}QnaULcWtGYYz~=+lV_tGTv5uV(9hgDV3gq3cP4+yVE9uU zSMp%1fx!QRpHu=H*9bH@&}2dTAXA~_)oxQ_kZ{smA>5A2YPpgP**A#T2q!6&Smo9c zV&Rrl7K9Hm1%Un#bh-ISQ7S$Nh7g5Im!zDLz>O)%zmSNJ%Fe%_2o#1Pa_wb#Zjfk6 z=~Xp?x9bn+^HW#FOJ-ePg=Y>hybojk;2tlS^AlQsqKtw|18Cq&9^Csn;}MQzfx4ee zp_1;0ZFpcyDy#3}yi0c1mi&!|T8Zz|2|^~y2rx&Pk|hTkEC||XO@VaWDB&boaB7q} zt7P4)A|eY>jZhdJ4307dfnzk4H{11X74B}AGtfH*;v@#J9%It8?b^q1ILszFkT3=v zu)RYUmy)eCpkMO5YsZYIxDW3L9Z_87#}6}}&VACGK}qYMNh$e-Mrf`y5Q%>S2@Duv zRFmw85B%9rzjxw_VCJIWlBU7!EDToS@aqCGsA(Iaeu?;$7$I(VEnyM+H&Za%{|~_k zjTLSwgfnl2k#-Ww!pg$olVlPL=uX1wktUPwV4|`st8pX(k>P}o{|b0E$rMCRvq<~? zCLX~_W{Sy+_{<`O5Gwr@p(jS-1rbwBIx;0n;w2Qwzd#Iw*blhXXtg2GYGb0_Q8hNp zkQhk16zMTO44{dPK;U^oEtKZxG*b?7RVMu;VlRAUn) z+E?L7YQ>nqE`WoOdrqXAGkk%Ow_>j{sq)eO`pg}_*#(@xS z13M~8DUQ^;lZb4?dIQq9l0+e#|_DyJpP1c6nui+{sIZXb;4>vae%~+xLzdfH^PBf`9R<-MBpvy65-XqK%l^6F_3Q^ zq+miNeOaGLrTTTJMb2cKntD{(%_^g4OoDw!>S%4v2grTwbBFWbX9kC+EFlU8X(#Vx)awOiW@bbr*p_p~M$+e8(FzfGpI&14))FvQUb`Srb9sFcw0{kThi$p&_KKB$VOc znP9UNEYWcVN)s*|>&s9C1H4m%{~1-KJi;_ZU|A*Md~knrXz0jhElMBJEzxX~lz~Ze z(13FOUk8Fv8Q8o1=Ta_meDQ%ShiI8m0*Pm|KOxu5Des72VO4j{iozs3f^{Y5MbPjr z8;T2|21W#dM~P=x6tVz5GZ8@t%1y#!Xt({al%h|>3|sMil4FS?i(Du}gmi4S^mL;T zS%IzR!5j~YG_ZB2)Zyj}c~I;LIaq>2v=nk+6=g4{XwW&~q5?|=@%E#L;f#@O{uCmO zu(cl|7(_AUScIkse5ND8@Mac44;A6Zg&;pRQ*PtVz_Rk1672YIworx%O6af}0*%h? zJ}NAs3)MS`Sq`a-rd%Ry!)7-Wjhu<4FbMae`vG)}4DxXoC6I6py4*v8_fQTIM3~Pv zr%`4hIw=%o0tl-}4hc`AloHP{kKpPfjUtS!+(#+E(;rJA2xEb1RTe*DaD;*oser1Q ztHu%nOfNX2s^(IxaW>cph!8`L=233pFvRUNsIhU#hXQ!R0Mjg5|Ro&$RcOP1orVaIvsQl}hY}vmJgBVN%zm#t}nc7bJi+TGUVi z_*V?FdJZ**0CHSF15$dh_vq^WuUJG!pXyDN9= zcc2op3E()7h6p%PR};dqu7etmq&rbta1jXfPSXEq%vwP;pV24ve5sZl}1!E)*KC^seCwh z1meXBcIYG$Z_JWFGUBKfM4g~BAB6G3n{d=C_|6$KH|H?ar!kXSjVB*EiDIDWFK~PF z@*tI$s6bR)>0xRMCuPuVUw)h_h42BYGERdS9;fo-_9M2Zsh|JNbS2<=jrtUmfNiRr zZ&3M>CD*C`glDkn6a|8TxiB@q7g4PV3^s2-Oc!2I2u!n8L_Wi>D#-Q6R52pzSnxV) zsk4E#8C-S!c|v`F+oUiKS9lQ7Pw0-d2lyshp2czK;Y`xm+*`2D10A}>w=aE0x6f{ zBN14XfKUs5l?Q{CFf+V(X>V}*vAX$Y$r1&=R;*bUcJk9W3lQ`m03t+?i()h}Vh0D; zPWK7FVKd$-1=<(l87t2s6&e+}rbOfHolvzA2!!`Qux%mc!8r@ytZ`3+mP!Dzkq{^d z4lIB*9W{sMLDWE#K5Y>}gw;sH0=Q1MGN#oNGbXl_D>_D_Bl?y!i5ZFk3>a!f|hz;V;rX|iCRCbvAIVgvg zFar<#7DFbIM`@h1JXrMz)b0bJ?O%hz;9}SqtMX{`h;D)xPXSF7(LYPeB*?KA(^)`6 zh~&jQz*|fc1OxWa*yci-)C@Nu5Oe3>B0+jeXbD8rf=g+^1SOgj$WR&W1|itD5;nzC zRWu2(*#Rcr=mXjTVo=&c+8FV5PZezh{|aD_!RQr1<5IZadG>^sN?A$7FXz= z0(_^_X^3k#jY_Q1G5?`J5U~s%nPh&UIT31MlMx5QK zXrQRB*uW|S`c-00gtlW8C=N1Q;R@xh6`ix~KqH7i%sYZ|(K5OgR(r^nWptH)BLw1C zL9t)mU?PoIPH!8XK2FJTt>#?x;QCcv`>*riaQNdo;7(Ymn71p`_q({%_N;Ebt+ z9Nb5bBYH7Zi#Vx8Y!A^jh(!9AU&awSgQ$jo`IViZGYQK%lq}?PKHZRDs!%|8#9Jjc zYeOAa$f4`>tAy3>=P;CjO#z(>%2q>%Z@WS7BXR?8l`rXH;9v#477rmTbWXQ`8DIz| ztLehXoyT;3g4?bJx*-CAoTGcV9mRYhhWxIjcX1qqwQ1PRf_>Az9E{^PdL+2bVVS{Ab>BO-M($PsLwp;*ixnxT} z&=qH>3tZR0@c#3WE=0&cqXH5tpkb$a>6|W#S)1a=5(k|FFx_^4p^FeaFw7T-K_Et! zFae%>RT6kq8{q2CqJs*5IMeeF(*+3(Jm?~v<1#{jMvR2)w27~9-+QEa(i*Iu?yP;>%<(iT1#W zHVu3YfQ!z25k?U%8(U*znY&Yrae~Msv^I*=8A9OnddSvQfuTp_IbIP2hJ}=>Fxm(c zpg;}ejygk`XfW{k3NZ*Sm6bq$AZ*Z&4H(2r0DvhtZNwm^55P%o8X`THLA;Ye;K=7h zs$eY|(^J}tu>==_H9`~yDr^~i|LKzW0RlDxVh<5)(6uvGz1R>Cw-GK&G8Qs8{Rt+A z4hob+Iu;4EyQ!N1{~QD%U}V=Ft})N zk6?rm?cM)7LkfYIgTz{ROA5n@*qOku%D`$fZ1CTYFcidbMNvsOr@fnDzp=T>SVHt0 zR0eXcjFCuW#hs^+QaT(Sx~;v>s3m}qrxa*^&R`-gj~M1e#bP`$U|}_bj#DB?9fLUY z1DJDAJP?jxQ4xU##tota&o_rMA;uW@10wp05k*LPp8&<{yke+=%q_4%w7g~f#>FAc zT?{WGl;5*)A_-u<6}|un?_qEj)0JhAb5kEz{eo6D4O(2;;_i%w{6@ppTvrmJ7^hj^G^tKw4Quc?r{t zn2^}cOf6guNF)V5MY5!jPG@Es;Y|!UHwpqzxHIMOF$j!{BEcD&??GsVh4_~*lNTsP z!wlKz&-5ZNkX``WBL-_LbHJI;dC-njYv2cc2mS>FEf~+s?A_-Aq-iN z#VjP;38@AMf_F!moEKv7t2I~?59_-um$`(n4DvPwgS+54m)%LGEaiWedHP`1Nu~~v zXTwa)&u0>EVuAG&sJuTL?zSJCWiBQv67o_2G6|5E!F48a5{ZUO3b83>5_b&{&6~_? zL};+;fhZd2Dr2(1{R9>RFw2=&>}++$i01F?cFtz;$>`3AL#BD?@= z_XJ@Y+8}^pH)MZ05$+8RH!#Bp44M;&d^0nL;D_=DkUtG9*~1ddwtp)M#$GV5<8k_{ zCGzAYlXI9q@rL0-*w56(xp($6rO8#w*%d01Yh0a3WL_TpUpV>i+MmkB;kgbEPe6E> z{{L?TKi7y+9T4%ENxYpo0KbtHb+cvk^nt%Kiwf>fGntC0$hYtAY&{DHet;i!E(SR! z*;%HVK=%t1e+3BUe}POgOd(VWy-6d5jXz{~K+cTJ!;=X0)#n=TWR6m1Z?F&s$H$ob z7`3?7=Ac#z56^uT505Gr^*c*Qt%zQ`5m7+(+Jp3Fw?n>BbRHfRE=n3$`;}>gv1@I3 zu<|g8hi4vS$xURmFk5$#8VHqO;eyXtY`s1UQX#beQc5fag#%1UAUi-jx3K?D=oL(>l@V2Yf8|3H8O7ZbTWlw1bApoE8R zIVpV36x8zrEM4xR3CKrDO)!hJHziBzL5rFpC3k>t7Gz()paTp>I9mOH_ngQUm$I|2 zssW>6rYJT(x3cyN6^_^VpYb_YAf*o0d2p}f!>dr_p+X2%1s{!AxR&3ecgpocgM^?# zid+Vsk17{s>0Pk)Cy_huHxmOZAir&pA2-#*N+?+Z zy(=Yy@jEW5vLzU5-T|wPJ08!gFiP1GrXsGn%?Q-|@DmK0?#PnFp_wSusSbr^`#$9d z4Szk=iDJU)!LJb}afQNQ6hgWh!Lm`N8YX>x#;N=qsAmGq2stim9A1K~Q6{myuRzCX zwV{yN=+!Ht)CA$BDzeVoY|@k%dglsv<+xXIx+pY=0i6UZd&Zw@JJ>SDG{x1vjE=qC ziH=2YNrB!mCb0mVMlt^H35+NfI!xJ4!Q5??unYJ>g}GB{TlZf+nd3xCwB6MHAprFt zK|Q#s(|Z0=cSCAipI_rpYJcxv%)AK>#(4r_Cj0+l_CXA$PdZiLss@yx`9Bg&zH+Fu zT?ZIC=u9-5=ih(Kt8eUB+b!rAA!v-=3T>tiW;M4CyV6`QjFVR|lVz}w?QaBL| zivKsCD!{B?OeJvO7vX+^heaC8p;EN{d?FLa!8>e(R-aL@ zoiGlDH`wsfJ*-g38iZOTL4&!q=@3Cl4KY^>ElxgN45?;AD(+S!58&^|h~C;c1tn;R z;Sz+VnW9Q)m_n8wdxuW4Z(snpi#bM;1lG!sW&?QZO&o02exafWHw*8NCB1kBNNjlh!E*yUYqP9v-;xnejKENzlSu zaeUy}9}eqwl+k)a45^8w7$)F|AxoO#HXj2^z?*W)ICLL`US2>zAFyywrhET+R02f} z!4LNYR=5;clUS1I#W_0o0*@WBG>d(*@@ppaNh3^3r5P&n@LYC8>Gd%x%frRX&O_{X z_~DLE+H#yLyk{o>8m5Ts>ifxaaR=mj0&-R3;u`M^x=1WzjB8+!&~p(O6H`d3$wg)F zhEl;h7-SZaH=*zw=^8L3v(x~*l{X`ke~Z7oRtGuMz&6c2W_v<{aH zZ}kboSKXYH(xXCF$AkXjup58G^{;&>?&Ss?H?R@rBdRf$NW4kA%0EN@Y=OR#L7OBwUSv&lQ(-C#wV3-IvB zaB=lW16?#0u~p`$!*SmZfL(N$JMapj9G>%QQSga_C|DbZTtOj6&VyMDNZ3UurtcfH z!dC|&_Zs-&&K&Ool++NjaL3&cqfjFr9#-amo1Nta5-1*l7Q*X>c-mqE)I#0grNN-@ zgh5y3QhxXiHb5TKGgx@*>KWS?>jDiu3IDw$Zrb|x945;MV>o3RP@4j?H3!DhjEmvs zZh|4aoG1et_&AO}!GwMhdC^WlYpHOs;-RQUBsJEZ_KUINtiI*aK7M9 z_<%uz_6VfK{dpDTaqA}r*V6s(L^bC5;PC;dZ!^@Fo7Ks2f)zT0Vz&L`%F9>6$HOxL z_kGaGGyW2%2-?%rutc=sf*BjI_4F+FLD;!&N&I($KEfh{EMBq(nB?X7fu9fR`9_3{ z+6pfn!kd!7hmR$WF=E(6S-Hayb-^XI#SFPTJgH(c2UPR1h!+=~C^tKqe~~g^kV#Cn zVNx%y)k0$zhW&RPKMVNrvkbAcHt$WjcnB7X6Lb#ux=Gss6!Ei&byF8Vl*4c&gWb!a z!jewpSzr^qV}zR@N?%$DO&^)Z!^6E*PF{u$keN|$F#?d$f%Rli8AKKb@aiTVbZ%qu zGto)sRh7OE@E2r>Q>p?n0+ksp^0o*q7rLYzez?o;SP;+`Ms!Tx^ zv17Xmp%k}`WUxG#ECZH7d6@0vg}JX(VSa6b+0M<=G#CgAad^%bf|YtE6yyuB#K2}D zqD+<ovMw_Cgn-drW1n44R#Uldhh{!q@9& zAsY3)(13T)09`Ipr(~QoZ!cK{zze2Kupj0W#(&?U%Zb6zWg1XR?%5+F?e8E-a8H<% z?sG(-nlAfsoL>f60>fdv+K1HL?cwGv7dE8<>1Aigb`yoNbuQvKt4lLwhpwXx@WQaA&HwKlVR{v%pAFuKvWT7Qca%+X zH4cUsU5TW!nhn8;PjGPPY!>k%@&pS0Qip?|&1Pv}x=ZgpZM+KVZVt&z|WaX*Q^T9A#VX@8llL0rySj2&GCmc&z{~8_}yn%0` z&{a29qW!9?$$y}DG7OvYjG?e-JILTiCs_pxF-Ci}GF8|GVv3^d6&yFH^)h zd$wodXk~pS;PBF|6p)9;cuicxEy%BjU~cD z8;wTW{EQ%wCCL(_NXro%;dNZ1WRFY1L0$6y!Wlp#l%xA+45@-4XX96O(Y-t7xo07Ei=+d1sTa0HX^v&zAO$&0AMnbs@B@Z> zR#8O#5c_wn7Ap&R)LT=4?IMaefR}}Zz&%-x z5%nl?@j?u#4us`6a78%?pR&i`VgOzqri0+!M5oD0c*px2R?8JQ6RUGcf8zj>2J9oQSZ6sd841imDJEn2N#muw@OdSS$*+O2^=G;Fc<<1w2LJB8M@!IC|BZ zIKPrsgN95W0~u=2cJ!k4jP3mv6c=*>#Sv$@6%ayMe~JS9PZKGLOBGOulIHvY%iS^# zTmfPloE60a4LEpp1t`>jTS<61n{S3MvQXTchbWE+TNi{-RO%=|;VJYcy7|KO*Vcsa z&y5&d61}BOT%V4IaB@g9_@>EH0(UeCyIzZq`5M6rA65PDif3&LN@{^K)zN~32RcxQ zBG{u<-M%F^k)g6_At<1{to|XZ*P;p`>#$h63ZSJ=Q~t38<*z z3>qGuAQhBK7QNt&zf0+iRJK_N8BV|t_r6^c{Lo=pWBmS{qx?XpiEjAe-s+TT0#{v@ z4Mw%tTyY=}QlOQ_t(&7ZDAHxk#l8Mn7e<4oLj@#Vstz{2U<((|eaJyWSfBQA8sXMi z9<0&hltUK0Ku*px0)={akec&(xWC10u{aI)vL76bGsD&32K!|Ub5A~6qztNCDXL-56r zQ#`*>c>Wp;t^nr2Lw%h8aw7;QZ=-_gZB*TVPbCHKJzo79rokc@9PSxfGYUL1Vj1J3 zf1#t@qoF5b;AnL9frT|=P;3RdTxo!9R)s5>!eT+CG2B5V#8CzQeUEqF@rTnsc%JD1 zMR89Jo$)9=v5Na{4C7F80Qj4*ltEJ_m4UrY#3ZVhI64f%B;tkhCU-qt%|z)faeYsj zKn`PvP>2#}H(`lj0bxnJ1th3$JPe8sm%9B&sKDkpRUMd`avZx~7zVeUF+-N4 zaF0_|;Ch-m2ee5Mg}V7PFZB%M*#tj|T)gcH!R~qRo;SQGF9clYasuT)7piD<4aeDB zr%L|2tJIu5k*)><(g#1>)As%Ae|a&%x4FdD;E=XnA$r{44SmXea=p0tFFgae%p;D7 zt_Vq77Jxnof{lt>*G2bGdOgh5n*|H5e1qQF2wlxhb?OmHB?jOXeF5SBo|6EQ88qx| z4KCQgj5z%2tgcva4hAk6rpi1n|GaqemsAKGHe;#aA-sdK>3sSZCkV76ILRz%4si?G z!7g(cUMF)7cr6Mx??%D%FcW^gx4(QBp4T|TR|VWh6Tf;;Dk%W3`qMGTV~ys_ifil8 zAijhjWiBO2K;D8l@8GFgV>SgX`2amQmy2ll2MD)dEy8lGweEvzIHXX4>2AtJtFmq9N%LW_^SfUR4unC z?*}knenEO}T0ItcXUUmr6s@3(mcq9lme6zXmj}e*Vmu1YfV&aM4wPGQ9NGlIl;^TE z&?HBb!uEogtgY0cnEO!HYM33|tHB(3U^Jgt-tM8lesddA*+D8rE)V1@0``2)Dxi2i z6n#M%)X!%b;E^XSfRJPVSJ#!m<(PHx7H@BlA}t9eevLu4G+9O^OOZ5DsYqp_ zL`2H+StiDEETh4E#w;VeB7c%a+fUZ?cs!%n-i+z4v+Qxi#PW`@MdgbMCq4 zo_p@O=bn4d%adC7Ro$>%k6nv;!40=Z7Ek6B>CLE|SpkE{5I3kE@#G0q5CoOUKKJ%p zRMJ=5XkM@`e7Z4+19j}DHvaMA(Mv3lPk_{N+Sj!gRrNzOg>nZgdReKuzYUinPR3w$ zEJ2=A)~4z6<<`1T+H zMoolB)T~&YxJg0sBM{jDH%Y(Yp*5s7gz^b1I_adksXuHEJ+Olek07?ZB6dv>jZj)) zL+hKV^vf5NdiI0bpCR~@&A4H_phwk(8}(eE(m!gPa{f0Q`x6lh$SNsJ74#^`Xv7nr z+?1MEEZfhn|2jbB^3>kS74)BBZE(`5o4V!t!ImCFba`s;<_S_%Z-{#YPH(xTVHvw< zxeQZ~S!XO3^eF5QtUWHr932S>#)DjTpd*(G(t!a=OMdV#_~>TgczP3{G&g@jT>}(H zq5y5n*ol8y6nrRJl%a*Xc{1>OD+Jj4U6s+t;V%pmI3tTcR|;H)h8x(_Vz7$awo2d* z0w>s&y$g0D)(CLpKn?622=J@50&Kg^U|a91HPztIX%7^*848ql-|g!}v(Ew*^+je0 z(^w&82v7^w7H zgG;@k2duDp;*FsjAs;RWb)VVaQ^_F3ja!VL%Ylq#u$KAQOXcO#j>Rzxd zVe228VKGVQ)lCxjT>Wcql;owy* zFlZla5J(K@K0fZX4Xk(>5uuF8o?fAThg-w#u@4Xbh^B9_)I4+z&CEXSP^YQt_Ns?L zkgq$d$l@+mO{h<(7C;4u0=d{v-?E^$l}l}ZW^OBYeTlyI!9eBBV|2edtrU6^sx*ya zSzf(hh~sph(L=5H!^-5;l!Vl{n9h?@`5R09%a*wNq)5F#Wy$wq&!VJsmdKkiZIT0$OR7H&&0sBu67vQC% ztxQ}CytBBQxt?R7^{&u_k0eszI6;4ZgrXK7G#UvuQ85hMoE1%}+{ZF-b}VI#RMe+f z8vwD~8EZv-6RbQ5wNs7xV+YlI7;->7M|P)>QQCyPKML@xi5%|1im61Hq?ZYyjqc-0 zXGbZnJeHbs#Q*p#sOt(=lkCifF(P|H-4z~8MyiWG=jOwc2eIfJV5RaMo#$LKg@Jy4 zm}c!8!!Ww8c?{f)P?Tk&t6`eR_Ze>f5`ja3mK*Ov3^OOMxRmX^TT3?6EV~{#%r_%zG*&AuXXf@$9;aS#X6R5ga*Bx2u zW-1!3-9DC$Mt9w|F-QwCjnN)>bjIH-=Is>Vm@%p|uR4F=!f9BU6C#ARQqN&Uf)piT zA}Q#8ZYX^YlH2&oYbvdns>W!WxK9N7nOZ_QW3eOUv!c+NsflRc{oDgKlUO41p>R2l zn2i3_5i2`-8KoUasu{1c!!l0-^r9CSv*56wq>oXr;MDU#Ziv7)KbM3EC!C)m;cTEk>Gz!-Q{x$i`rYU31NzAFbTTi?eXqd5tO zB8OQWT#U5R&FDd2#AzZH$H9fKX~*GR$QC^bjX6&Qe7gsSJ5#Zz5%yDqOk&8V-W-V{ zTKou|X!H|E3_Ai|tgM^gPWb4N%#jjF37essU$WQN_h;pv{A2%B!j{ zpoU(!3S+s!W(P>)LE2SfT@lDgMP^=)aMl0A?Aai}&~Av)s%{)Od=f_FJ6I3|4>7i^ zO?UkAbr+=r7_l!5ME6MxrhiXT9J<$ynP5t~&)Hz3S!!BByZ+t7XPh8yYTXrsMP-7M(NMe)bGLD*pQBnKU~G&f00 zbni%lvKJ-Lu_Q%QV|cCo(0L#Dv*=&GaM+nhrYV}^?lT3e;@e3^`g*dlweG^zeih`pPr)8KkfI(Tqe>1DyUTHf z*zzf@&pxtCRZnSetScI@f}b7O+vNO}|3NBBMO26qQ*kBD)p#f3sLc(~$00bERsP9g zMz7x1+)TwpA3r8Ipx#tHk@cGj@XM1m;081#Q*{Sk`)_+a$NcmKb2(JMc#aNyfTQjH zsY)B6+nbDy=S2qgqQRGpP57fpF5eHkXS}}2+yoY^d_>!NMbIw-FHX9l@qKS|nCojO zNIvr4DPyGSTL$wqbmo7DLGaKrP0JvUXW--a1h^ngJ1+dhz|$Tvup?F0P@AR!99qS| zt!N+~)rf(NW8j_!%ABSqRrV=eFGs=*E@Lssi?zEo6;IRj_=vT;)|?tnSK9Zj>x2+O z>pq(tthp27Zsu=JZ8UW{c>Ur)%cg5l{C+?zpE_GpWov79dNW;f{&wl0{Hrbbq^l0- z)PvN>4p>k3p>S7SpJrx1ds1q;#%~MSS^9OryJjzIM=DL%(ua>3e2Wi~FQC6ifv(w5czi0X-B4)72ST2H!3dkU1mBCsTt&Gsu|;%F0wa za1WBzJFTq=y4nt1$^Pf*IA}Twnz@0rjj)TyXl)r3&EW_{XKL2fdnUM+PM|R}l@2`U zoZg_lZvpwwR2X$zpD{b@#5Fp(-|Dn7jTYo*@|8He6kup_(Y{WGlTr%Y>SekA*U zMV82L>OQfvD0`OX=L%+_tNdBCG8=2LrY37mqa_2`dzdR&TXNXGDoc?1WofZ-bQU-~ zoh!f&IrweoU0IqUN*K={gyDv-5IFZaTGBIQ4!{70XpBL2l7Eh#ofz5M&tH!5-z8pdN8yGrBQRbowr2T{gUueaA{2tDfqnPA;Uu}}x%tx1}j|<$``D!Aw$@d|FBQZ5&u?w&u zulAF2ijk_-Hz!!*mS-5mMWejI9n`jfU^RLA9$D1b=&dm63`kH+qB|FWtIHB@1wCuryB_^Ts^% z<9JJe&*iCWCv8u1VKZ17d%q%&dF^dMidt~H+6%6u@8%q70owcccG7omW_DN5wW4ouDia^ zOV+jDNUiUzYLMDLc4V^Y3XK@De?#g?-K*IVf=^VYOocJBcVRysJ#Kjb|QhWH!BQZD|{z0SdR%#0Bkxjx{=i*um-+$PT!UZ7@x=OX|P;YVqmIO!Lx3()=fLm{*NSH*%K0&Gsp*Xqqpu*QoGuw&`5e zq6JEOEh@`X(vu8sG~4X6Tze*Ady%noo}SHDC9&oeu0_l8BbAIknZ2{%p|Sgfd`gtzo_&fhHq>~me&Jv3 zA$Hn$pL^XGZ3pn}&8N@0<;gaDV-I%7nL1iZRcIYu74&?0tyhbF~v8bX7r&+N%uir=-yJB_kJjDs-pysuvAj z&K&jaw-P&FU3sCyKtC$dHB+NVHu1>w4U4^&+?P)+GRi64v-{gXbZ0ra-_FjV5F1+j zQ8@Lh@m&q=?@jhm3?IoKy1elb-=61&RWD3cO3G08c2>=MyyaKgQg{F0J*B2!yjrZ8 zao5`=^gr_dP<$OY)Esoi_+_)Nd_@0y3mMNu%XYITr1z6Lsja3GbA7g{oe*)`pf>nz zeNM?`(JF&!Ud2_1ctpEIzGUpDTgo}GOpWg87IT#ENkSe z%u6`?X2SYMqkMCLQ$AOL*2m8iar)$V`L)I}O1h?RZ^vYY`q}+h_eopznAF6Uk+Vzp z{L^&F=TX)}bFIL!^-6Vlau(zBm_D|FC#r&VxSe;#JvsYjweE}V1Nyrc?rl#k8h03M z8Q87Cyb{!qeXynH;$`z#tF@l0TmwFxOErjd^Oui_Ui1#Mw;p{a>)>xzake(PEo${t zt==)h)#;#s2U*Vbk_wtx#*NJa>V*!a4Ch&dSE**R7}Avf8L(=aId+m=BlpW_w zP8t_S`k(vawZA&YEbUi;@vVz5gRdqzcI71*CR&!QzOLf!`c&S_)+F8}SL{OVh-j8; zI={ckMN1Kx>Q8<~5usHDQPsaYYv;I0?w|G;5uXu#dds<4?qlpu+H`or5=phfDY+!g zLCw%eBkOXky2Fy@MI2xQ5$W*QeU_-HUFa2b{NG{&85P z%`8H;U+FGi!LNkJ24s?mqvuNZ&c6v#+l|=1*ugmp{D``$cBSX8CN%1mo=N0!B5hq5BZ%g99J{;E8~BT_D7{`q;$ z7caCmCEXDrVR6hO$$h04oy~R#E;W;U++_SLTJ}J=ulQ3k&%JuX1XU%oKG!CTW!cLY zmbd5#MDV%lrtY*dH5dTlR$pyH3c4ipmz$@rC-a?^nrnGftWj^CtSI*47?1ASP#6B8 zmp22hC%D`TI?7L79Pjm`wNCcjLmK^@z!v^NWpd(Hxq{%WYncWUB}U@;PHM)ki&VG! zjtkGZ_WGXK&DP$zOT584Cw=+MhAmh7R`~=d9$FBiDS6HE=CyvYn~%GbOZr9cDV@*X z?Ad;^>(#vtH#>UE?l(7c*E+iRoE-!YdXFkkl1Q)zR3#fzCL`36_KeG8m(>E zH9rKmQ%ARkR!5|m9O7PF|7h>YdYa)oQvBoW1s7K=^%C$25*B{P{5&tw@Acrt_u~~m zsso#YO6!kJ3P1I{xtdr#sxVk#HmAmY=Ux|)>qaw&Zz^6t-qHJeN;1zCOEo_nL3pOW zpZaX)wKJ>2k_)%gKB)Zo(_BC}*vH;w>}z0X<^DpglN)S#c79ZH;+sz#Y9X|S|+R(cto{_YU%bepY$5cV=_qz_T_i( z>M=g)OqMKmS#Roa_Ev*b>hfb3=xaR3ET+XtH;s7==r+;m3_`J4q&`#mRTeq%(Ot8& zsq(?p{@6z{QD<*O+*g*oxN~D{+7x}=0U4{kSCdzbMSM}~j4WuZ|FpW*Vz6Iso}eh% z;Q4zaGe18S>15|cI))kEAGZwV+4T0iuzj9f1SK! zvq@8$(dfdQu`>=Uu|V&qvSu5Yj`NnBT9-EEa$F*6WN2`dG|zxPf7GY4{wb5mWtQVP zEtR^G8UAFdx_+jcx!xoGOYpjY1m~?$Jh$e*6fm9EVXADXkdB{wKgd!xM(T}vmy5Np zLaPsndHRy6x23q^ms8q)t?#eDlr^sM@j7zslFB8)i}iaQ^37b=oJsQ@mnI)E@?bU> z%HQC#&`f;W|JGp5$%4bTygxg+1TcF_sOtrr^tbIzeQc$e{V|p-b0bOW;*w+klx{j> z^(uUQW*X*ZC;Wbs=Sga!%MI(b_F5MfEbp*#w&JRcoG9NoSitR`Q!vwr@v2~zLisX064@YV?uiEa)yKD7UGi&~H+1|GLLKb(dwlTLP z20R=Rco3Z>zFfv)Te6LX9M`C}wPyjLEe7sI7Fu@u zJuZwRJUDy5WXD;zgoN}R%io{QezCYM!?R=Mr-S@4FOIZM@@J&Z$sCbg^z7szFx_+| z*DAmJV!>25V0^7^~_V>FHH6Qv7mYW947B($HhF>ueykiw^zS2^sKUl9DojsNFX zVLs-|*V`J0JYRm8NHQ$ktvtx|BpUD5?HsbM^IV`~Z96q2+m=5S-jVXtt$1PU7n;@8 z39^@7Y^qyzhk~l3a?9AZw~l=4g6P#Vi$x#54oQrm@hfceUFe?Db*Zmqg}ZLshSr&Y zO=90R1aLn$q19IWbS|~s(EH<@UPVFsrGVBA;mnScjKF{cscvA!#*`^dA-C^-KZ1sQ zU&v(fB*@EOeQ{LgS5k)Nj>?OlgSgJC*c^Xnqw#&679rOxZGigKHLm>gyX9T-?nmop z0-ark4-D-YUf95VV724%*ryj`=ApK`J)Hj$qHTOx@R`rIQ+0`n{VOXS%0|ULi8-B_ z!H*W|WHWQQ_X&o^1?qbMx`vh~6SN(Jy(E0l2Q@YN{4}r{)+F+CCOEuKgE_vVFds6t= z$y|lprmGr5xlxu66$;d!rujzpCygnjE5{PYcFvEj8_P@CbY@LT!=_ZMipM%=v5f7EAf`O}@&`@AoA4Xi&_sC}%k^u>0?D@BzbJDqwr zm%gLAUl;B_q-1!|sKd+M>0W91nJFHreV1-zb`0@J4f1Vrytk5hCgt4YpTdh>+!8&) zn$J3>KQ;awTk_IRKUKy?{_-5(T@7O=ySH4gZnN+(UMiL#ozwjwwsPM?mGm;H z*rmD4oPCxUt}!{LgfVuB8E|FT`;OQ>+w{yXntLaXm%-Tm|HxE_l z+Y*O(e5#A?zIC>K-W>2ySl-<4bd<*ZrNKL&$#ByHVw6>~?QT?OR^*2vjx#=dpbDE`@uUDu}&{ok`>FCZeP1@)bCch+nQ?HJ`m(WlBfr^vU ztDbC5$t&$uiL`yVJGrqRaHu zs_oz}o^&kw$vBhrQfSrVxF>1T=67$jEPKvl9IySh>kIdgkD6baNT*qopL^`WGF{K} z#7EgHonzNPpk<{9k^98MUNMHCsIGb+&Sgm5kPoW0C$t82GkEb5L zSnsCyO>4{LTQNdpT zUW@h0UR$6LK&vU*aGuaLqd(Jn=Stl4206VaWrM*NKfbMO+vzOVAsDGo>NcJ?!~Cdd zJN?={)XtSCa9G|(@8LrgzsRebqOUwu*D`*je)yaM6H7@Yt!!=_og%KkzcA12_^CC& z)y77PyG?Ixy*8L^oRYcm*%gZ$^WKdb2LD=8l9*Ih=QQNZd;Cn!PlIdE5?htOhP<#Z zEvm6QV&m$x;dG1Bpd^L-k)a^=$ho|m;-Yn;Z)1JY%fis~H1UqONS~Bz$7$Mc4HdqM zM@4}>Wy5orAJ@rmn&M3wZaz98%b2mX-1o*Q`mpQ`f6>-Gd+h~QuD!VTXv2whOJe(% zRC-kp5$sat+l?-MM`Fl@jjDLa%n(9nxI^XUyk%aRS!ettX@Pp~X_`-DMMLnXZYTGP z^qocHI{L5MKc-$Kl{hFk34iB1WvraA3_F{>GSuqZ($HvTiRTiRJ%@K688fUoeyQeo zWySGu4Ks)4fvQ$VvgBZPd`3$7<|ECT-GTFuq~3R-=ch(dMbv&T?b|t2Z+f!qeDB3~ zum5SHXuC=m6m#W837d-@GG1zxcj4$NtV8NWhwn`-+s@;QEmU0H<)`!lyp&Q7cQhEk z-6L}~wc+|3o5nUKw+y%1SJ53e1e4EPvtLR$r+nk0T9N#a>VQGIrctOuq;>(_=TJ^t zU2;{!?(U7LnqINdqgM*bn-4`C)uayD+gLbCUrONS(L11C&`diWGI6NP`KI7M&D`4Q z*GgKw)9bwErg@&!rCYC%ek!(g>c$8bzV6<0yEzdBYxSJfq_;9p*T1~Rc=_=9g&Wx0 z#Ks3a%dXyy-`jra=@NV818yM_*)I3E)UJ449~#}Vq;_O6u;~#nHp`WbEw0slaEGz! z%BWPf%S*0wrD5GAwaa1`4X=8#!z#ylQ;k!=>EiPJHR}(zaoNlpKHwbKvu9d;u~B2X zP|u=O;MsSp6?WfFlZ;ZC!#ARzP(PdwG+XWH>v+N`&Hn?}<11c~i?{lmiMv`YVD4Kx zuBoPGROs!xk?+&=HPT#C`v#M!7PM3{;8Uo*?2FLfZNN_BW<(X7W#- zq(-=DdVRIdxp!J{b)U#ulE}8$yiGkf&VNv>7BQPgzPUVBxn8vprmcJY!Fyfthf6n4oc}QXBll*!!-GNagL`_R!z1QQ zuf~+Z!M@m6g>T*zT)V!d?@)F6gSE>OSGUglVpVZ-%knY)iW58ofnO|NugnWrk^RjJ zR3-TpG_1VB?``;XRP(EfLpJ}Yr*G2tg5i+`t0JY76mJEn$r=jE9)GgPL{Pub@cjJj zuOi2dL-=ggZICl@`bwCg`)EGiCNSDKDM4YHwzLjSE#;pil^+(nb@!Gb#qE;Cl-f*G z^9g(LTMuq+EKIyyX0`2;^hUxI-;43Qw8;44&F5_lZ%l=MDO?~hBVI)Jjcoq0#cJoL zRhIUfoMX3z>&L8`lF3~Yx-dnu)i2}PsNuf6HCu`PTjg}i{O^Wc6H(z_I&tU09n#F! zuGBe9lQ{Y4?k0sA zQLmak2XdD5t+GGcM|o-e%>FEC+w|O??}c{6t7oj4pUj^4t?rkq5mh&8)Y+#vxH{J2 z2v^{@#WOVhpe>7zs@+$XxT?wwZw{zGV7x?#7m_)7)=<>Pz&%}wVu);7$vRg^||y%Sj+L`-Dbo~`9kV+L+JTPqUr_~pCRAXqJ! zr>3`OSpeV3$HH~{Yfc@^ztB={{MKxjvLn&e>4e=f$D=Ex60{Cyj}uJDW>Nb4ws?n7 zE%~C~*$`Y^>s~242IlTG$P7-(XXrf~P0mwlIhAb5|BLa%;j?GFn43+XUFi7hh`v?3 zU6O2%Ru$VRe|$2=G;~Ti$G1H;Gb$&yWuP>%ctZYjjH;Yb)egDsu3N;GBx^eF*wuO@ zAz3#2>GQrNeW&uD@Fblp^bSzf*wI(t)G4l$AlxT%!)wo)#$DGB$L&Oh3(xzXUv7R||T^&ZL(1+VbmvyU~`X0F>x3`~lew9SjU zwWVy5x1fL6TzB26qzTcY54riFw>Gc-aZI#-xFsj>^tW*>BY5B0ImI*3_rbBau_bZJ zARxsdOJZ`<1a*cX{%zjxcxH&zgm6$~@RShu;?ad2+Z&Tw1PiYhUAyM7{7lU2$_}m< z4%<$4PwrA{)qknKs6+oH^VImZaQ-Sy56oF*8@VNFaB%SMphbn{5f{y8KC4SdRxIy| zIp(*=dgUweGl#njB=>rs9?r=)r1|?o)X2N{m!r5c9=J73@&!0VnBCG}*?vfUhF`UN zDBIcJJ8h~eh`z{D#MdNYrrtauh9|ei|A2I0gWIczSwj7XmUL0Q9}BoLD?4Qq66GGO z>%Dx<#b?l+z+`F~m^SoXB)e8VirW<)(k9%qKEl6JT!H6C9sc|O)gP2A@jL{xevas`hz@*5b+?vH80K+@nud)U{?DUoPitd!=;4 z(#sp2Of{nN>wdebJ{Y)CnoiDVcB>30mZqoL@av3zFAO++UZH1YkO245Q;*C;>kRus zdmktz*SqaM8E|Tb(mqX348oR9>dw8#yf8YoL+#xy3*s#^+N9j#m(1rYr??7oncE~R zyZ27XRfVs+xLUAWt~)kgPU)NI(vJ-kzhcGfHJ3zdV)aH(EG=KPS>v|Iz?2}fE$r&z zj|R4xQEQDXck}O+&NWrJ>iEw-h3PGi9*5m1a$G&p!$f{nj{7gm7`paz%jY^82m3q~`0~FrnG;_^FLW8+p!C{A9(Y*P7*N;)SYKMVBqlq;Fhk#am># zmzh3V@lzr{oZ!hfuto}m`%j+QE)7Uhz=tt#&?hM!(<=#oQ)N_MlA*GrO3CG%UYJ)M zZS~Zr>LHSqXUN#boi!)Di-Ul!@t4>4HDmI&P-||CF09Nh)c(BVl)A<=<%hZ5l<_>O z+AAS9@x6twmYF=|q94xJduq^~ZdRA)L1s?vv0UG4oHx0lckq6N4VTF|9g*+VlD#XW zOpC91ing6}i!SO2P@n&O>96tD7kvh5%i9Wy#oF3WtadX>DeTBmyH8u*wWsaG51|zo zL--54ZN{U8$M1QsIjpou-r;#)%`)o!{ViW>l7tS5uOsZs&1&Z55aEk4^Hvq?Sol%BB4Jf`5?7nv>NdBkotYc3yp2`smn$D_ohF$6I+T6XV#evn zN-QtB)Im2nuVz4aVvtaz_aS@p;H8km-O4el&w9$AnCmLfZ`*ab+jQ!_LZp4cw^xyx zK&VqAQv4#nP*Y6v_jmr7j0LtZfeKW_5;nCSXC`yk6vw%r%IRyqs*!VHZ~5Xi##>+OB_w9fx69<|ym_$evPj0+!)gOQB2DGC#9}Ft&er^o zH{b8=>OcRhLC)scc>Hx(=Mlw~j#oU4_xY4LL>meD8O)d6{9vh{WygnMA+KeU7Bv*^ z!&WQajdd$MvF@(X3~zewv(YS1WkXu9aQ!cl)X(E)H0FAns$D0!LAIKe=pBRC9;Mk` z@ms=t4`bpfRbASO7we8K(^9(iP<%Jv_WiQ$r911^=g}8wF*ehZfY{xr$rZvj>c+Lj z#U3U%CACtd+dmFllnnkfR1Xj7;~w9~T_0-uF0t!(`IpaMzh6Hj^=|l!8}Igj)D{!5 zLURLY(!^;~=4Qu}2djqdXC{{GyrB4}SDY4q(Hv0He5N8yMWJ)ky*ugY*Tep4GI9y2 z_*(d~wYqd`f1}S{qpxb(-AB0EsF;^>(KVF}|LE5Cyo+3ZMtnnAUG9e0cy*1>SiWs- z8tbcT>be`!E*Blp6sbf!yUQ_gz3^GCPOImqHB6`C#2W{gtAFN%je-o9_;@o&ES<`r>~`k!QS1QcOLi4`*?rr ziHjZq`=VWynt62gt?9216|52)bdr=P$+<|bPIEKStlQfYaKYl9;Q`wss)d)hz4X^HdYq0h;4<*Y^(0#kWC&MdfO znd7ytF?-rVEVkR({Xl-l73RaQr_aer6(#)2i!$qOW$3Ic-)D5PJuo4vp}8vgVXoDh z7-fbvc6Gz*>#tsH-|6u?JF2lef63X-{5&OH@p9LbBP+$uKa{-Nl_R$=JVj>V*rI|T z34@{%7n~BSM)%&Ww2rR(y1(!G6$35uil7hTsY|Z7Cq9gGj9tBLuGE?4cX>>q_)9@H zDid>Gn3|0HU(+v!s_LVIYhe4=cP{`pWL z#(c2RWZ-4a8rRGxgl#pQvU zwVn+qsHa=`?uy=!5|u7-TO+UhMT(=V{i{8V51B5n3+?o*e^ER;5A)XiBiFs8=eyO(?D)co-uM$Z*vw=~X=h?Ovz$MC5i*-dEDQ4F>; zjdzOr?sM{hQrbh=hwC@1M3_lX6(SnXJqS5uF}&hCt(ST3j{5O{^GZiw3{Z9@?kI`5 zwcv{3qM77t+6^W2zL9tP2<9hjOxnuIhi}hw-&aw2&2sh5!p@|D52yAx5w}|YRIuvd zeG{HrDlBnSvi5YFKi`3oRWIIeX)SGkNz>7ebn4oHDXO>`A2bZz-?tz;LgMM~{i4S9 zOJXnV%DAsRs#3{}&h_6FDDHRaLz9xdUWC77=6ki+T;{y_U54Q430Yg-FO?b(WofbO^0wCFe!n=;K+%ZV}=ql*XLx>9zSG z{n)|K@s6t1>8z-27jAYO=Tc9KR|u^BP1iQP8W?+iTIgoE3jtI8aZh2&pR#W6IN1Kd z>*U^_bBS;CBfh^Jk`}zh)Fp1nIH4$i=T*#+u9V`Kp zox3ZlxO-8r&*5!N@~mv2wCo3oHM&%=40b$2L+<2oOJloNFv!>w9R{^*z1;`Iu0)6p@Reg27jo%1g+*pG+8p|DNC z1T1SMWQ9E-kr6+@sb?3g-QUDkwW zcQxx6l(O4zSIV##jK9kzTPF4U8j8Q?JY09!04s2?As#L&c9Xyb*ff@Fum*hw9h@g} zdH>}vHc^+Ci-DG63C<>-pmFtDu&0+CVH4#*_HM4DWHu45D2M6o<*H*pvZ4a>T+fgN z2K%_I5jR%AvxvM{<9db!Xy4EE6Cr~~*$4&vJis-^-dq?R%8K4yut~sG$@tcCWaI^Rn0Z^*QQ{xqhLjMxVqUAK=FMLV^-{94$ruVK&_4| z3`q?=Aq$%7xelUdR^S6TC<#rnD4|JXi{Enb0_o>mDaf{Xn6QW#BvL?6GglyI*TL!d za7?a)iwt7hxm?g3+_pF)h}d$}K*I$=K_}O~zeWN$@+TU^%09rPhwBc?My$X93kSIh zk%+i$zJ1}kfac={oZQS10gp$xP9P?@w+>AFF~;*`UTHA%jjQi39D~n-K=c=vIh}2F zJkU(HF!-_EOBw62Rx;I?AR1>iHsr>s2$GawTW*|qT#|bU8p%=yG)i-qv6&|B>5#_oF?n*_J!m2>4Nfdo;O1;b zR*eCl6uEz)Eyvo2fS}HO8%fK`kJvABh791+;(m{axMSPaati?AReyw^CC07cUVw}a zHIM`CYq`Jt6*pL|B{we^HsDr6gIF@)L<|xsz+@wL0YdO-U=3#>PYd_Ce_! z_b5c|1lU0g7kh*PtlEMojWt>D5CLsJw+iC+hlnk~oHEv-fBx`&9S(P=H44Uq9d!VF(XZF9~oeW-Z=neO#zr4UUb!Q*9 zJ~Akt5AZpV$PX+&a%ZZt7h^e%y_oJUhB#0a=K08p4OST7dTC4W>_<+3K9#|`-MIJibz%hl#0V$~emR}k`BBz|< zIUhdLfp;2@1s{7RhZ_-myv*|vt;_24!AJp*Ali*E^~z#vTwq@n=fa=??P4B*zmd2b zkmunt9#yu4AghAs+24@}IT5hi6+Bdsaf9a{Dtlqp#su>BdGwH4cw`1Y;7LcR1dncr z3j@<8o};Layou}n5TY&c0Jg9vJP*7(i8J<3$xxtMg(aSS{=Hn)SL=sRQ;(5=} z_BNk1P#xv@2R$!30liQ(!Q;ZoMJ_NG!Dk6f!<{i79Gv7?hDQF@5@sXGrUYKB(48Su z`J0Dx9&n6?)qypw!jxdlF&ArdLz*~fAP}6<_G0z&V5>M`gdG`)@3u$-duf6yS_D_b z)e|aGB}d>KN$}{=&?C@6up(g$IULsxC!SkCC=g`Z84o@d5qo@_Km$x|LOWvohX=OZ z8E&G4RfJ<~2>{%|AxL8Qa}ju8NLY?0;ckKKgn@<;;TL;hR)+zMObGkX9F`p5*;WDr z$%P*r;WHWVnG?nkBbL@!w>6Y&p%nqe1YY8CnwmF*3JzEitPu;AtNau^ng+?@nTgy2QFdlx~BZ5UjA_(%itHiU8{Rr_v&Ivd9MnEJq- zuV+tKj##kzNG#cb@RdCV9+WiMzwmsnmqego8-3xKgnJJmk{zNfZ(=ww?8hKtg}$)P zJ#{7k6u|azg!vc;5dgRM5yCl!W~HBhP2|S}0$}7uxDiy?hW>gdVm6T;VWUIm@jFL*4{SB#3+{JQZ;ed8{!S`Z4ARv?6;V?gZdhs%U~3_VgHRS6@UDDv`l0Okh92f&qlj zvRCC;Mhc6IB|K&?03CA|$%MDXa7r(F#_Jm{lxZr*d|GLQg@1``mPR0AGsj`VbT|$Z zCYDBsLzAJdGMIT9v^|6cfn6p+2bJc3ArheR65;UQ3vyTrB*r9?KwvK6-T#O3g6KlR zQZ@qMUVY708^A1Z4CO#bRRDTb1R-P*{Q1aDf+BM0tQ;dJV8j}qfPGNgZNlLHC;(wP z7`sp4^g(b91q>2}LES@wI`WQMFrPFg-$Ee&=l@5s(#<4AU|dhQiU#66Fl!)?Z6E|7 zBJ{ruCisp(0=J%UvJD0+1)GTJg~1LWDwH7!rk@dv&>UD;{)Rt>!tNxpi6D(&u6Mk% zup|a2Qo!JIf+&JnVqxiFaL(Emf(bIwyLn_qP~1k)My|q>Ae5DYm9#-eZ#@ZpEc1ro zhj`!t!hs3kb|+yGG9K(s6fww%h)KO8yu|}1Sr2ZnKZ99xVX)#oAsMCO=N|~1bKNXk z!3b#NHJ=Hb!!>^B%u*oorwnmYDXwN5g(!*DM!=+DGDOfoGT`Q8A)s`GP>cF{7~?Vk z6012zguMd>If?=%m3SKw;Q?3%IMRuW(2XNZdNQD7E|Jrq-p-}VVDMQEn>hv3ceFI| zD~c)BNDQ(U!JaA->EN~k@fG5U&tV||A||Mv$IrSfeXtFSh^R_(2J&H#qG1kAUqs|b zRRh**oH>rn2R~O5<&od;<_70uw1$Z4Ay=Ugt{FdObB003V%HKWAbrgr#q~;Hyy8<> zFo5uBBq_&ke5{G$z(J3=5w$9}KSQtHRwR;fmf)>1@hzHz7dci?V||;6=pZp0zVsA^-0j z>{dKO2>2Z)%KrZopZF8`kZkW1{5`50V4B{0uhqV=0CZz+T^F(PQ2O)20y^V{vbY0@&7cXvGsRiSIZO%gP)q7(h6ebK}d3ZG4X4S=dvB z_7X{m8y@u>ZZvSWpZFOec%s3PH)r7;%lIeapVJVlEI>pUocv4-{M*-%D1x2KfOk9V zzYskT!U_!l5l&9WQ$DV=X(r6}%rT+?hX?Bzjz{P41d-D;;f@~3gl%=u4`LJ=Icrvk zP_V7%AiVh(u>ck3*{y-YSI)uSb0dLt9R=%uV2Se(HlvbykO}|I9JmOOYS2W^&ZlEI z-|q7aQQ#p)qN0g-#=|vZ!QhG{iF5M6jfn>cTc9i$22wJld;jl5jD7(gwKe9ER1rKI ztT^9jC6d|Sv5gZ2)JUB38eZKvVvxaQO_Jc>nI9K}xrsytL+eOnHlx`0c94dKRHo(r#_BD_dM7Q7M>3?&elj0dKZPwiaC%E#r$%L)QiOYqcoT~P2#*$4DTa(j_FoY?1h!MS6$qG%IiQ6(}$N zB~sS^$oo2nRQf+WZsd^!5D^cxCq*y`5DH10TZ35>L4*RfUL^&i0Gln-ECh?W3eUab z`YyXJ~y3Z_{Ok7CiIBrk;EPQbY>{!W_ypW)^eaF4nDCap&ZZg19b3?jl{oSVD` zA@QTI+hHjM{-Kc9Bg5bUg>!#RCtDyQZbzKQ@k(fVPa*OFjxe7|O8~zF*$_DiX(b3w z$&jtk7#K?H*(Q7U5*E#FC9*6w4Pf>-sz~05tif)4HONYUs7yYFn6U%|SsLVe#0am` zaJm$>K zoZG!wZo_vNB3SKhm;|&u$oKxsSI&dXhe_Rm9g~?SnTGrdnX6$q5_5+k4=N6mwg0;o z2H8r2g?{Aq$Sm-_Yzdn=OdHDJ=}|K0^(hQ^Wh^Tadhh35h6Hviko<`~5DJa}+k0?J zeGDQSu$KYwkaiKR2!Cz@(kIEg5Og$>oQQr3p8gXDo73Q^)3M}CWFCzK@?3V|1`y&j zws;X6xk09}#DU)nWRgA68B$#q-p&3&FwIAB&pPLm=OQ5-wy`CZVrwlxTY4=qz`3V{gcOGmj2^1Q5UP|UhodrJ9v6f87s5i(D z*t22SD`O+|3>BbQMHWW89%duadj3yf#LA*3z_pt35O^FHja`xjV$g}I8q!u9w%=` zW`xa)GSHhLd!wLWJ!9}$6pV6FYX67$g+LkoAEGRUGW9>iT{Ozf{}3^L$~HC;@9m&| zbgYYuB7zk*!fs@_5M?ehJFL{W7$TTJ6RZr0!jxU8TZGvNN8mlue9CW*Pj9g8EQCQK zAJ)y94^s}$Z! z=%rBT*llYH3Dawa%s+3UShCj!aNp9=PiXdeNFv;hjxS+Q=4_^HLWbb57s9-3AiJ6t z2rt=65k$hw!h)?Z3d1cZy?^Tmg^7Xv$YQu_Zp2S716FXm?# zXUPWI?I@fV=6DeQSsdH`0={kzbD+FrTL+da++?_DH0(- z*-5Y+RBpy%4x^iV}fr16NSNZf8SpzI_EnTl|W_3w%#gjw1nZMz^vlWE=+S zag+`;@m~l(*qHeLBVAqFT);=@xOsbot%3V&Q}L`2;xgZgoJI)r|<*gN0bxn zl7VkPXi$Fa*&Eoai#?;D*L$o_5tXsUoiI-@n82vpp2j`#Cm@@(nApg+dfn5(Lg*jSS+#MU6Aj{2xTb>4g4&^ z8jjt1%b;Vs4nxTgjZs3-L_Cq<6Co@NR{fx?ojvlw?ns$e2$SiCJE&%cQjJ8#3rV*b zuP_$a4Rhrq9^T&^ZYy{ffgilQJ;>B}?i}IerNC=KUS7=n9Sqy~LcC2#Harkz<8;0EnF6^nDy6h7VsV!@C+G?B0Q?711Q0()7V7)Cb=Pn#Zyef8kJ}-Px z!s4E9&$|z8Nsb8_nA!)(ZHF7L5lZf`jgbMjkMX*r8)!T!!Dm@;Ad1(CJsrTafEw~D zjzfRbG0kjV8dfhZ$p`e(c*9XR;0u|Tz;Fou1e4Zc2}ugp$W7%15*K&}kfEVHQ~{hl z!*)M_V$UGm@QrY0fWeRH4Zv3QPzf)(h5|5j-=UKe40mPVev>yCeV7FM06rugr}|T| z;?M9%ZPLigIj6BgAB?o{4k3HPJul5J?*KZ*4;3D~2(BE0<^Sd=?=!R>+a&5#IyOwC z!n?7bymfzTi+4nV!*IXbe?ck(sPg!%w#pa>76TL#RT0g`6BLfret{A1%17m#A#gK5 zM4V+iexM~v?Lyq}9SjkEU?M@ynmtO&V7Jw&!azozI*E1-o~43SsT2$nshCL@3?;{T z)N*!uz?*Gca(u{{5tvb&6sepyfVdqYM@3LLpIX3n4yS*h0XRjDZN@(|4ALY)k2>`n zdu#p&s9Q>Xhcwvw0q$AO%92>d7-Int(55a&elc1}ea&V8l-E&zAiu&_kkE(|jOBo7 zK&?e-1K%gJoGwkkWSnL~<+RkStdjB-W}Y)!sP5>STi7TovqWWpH3z7uFT!R!UKWB| z3cU58qAv;oY<~=q7_353=})yrj}Y06t@{ouSV)aI!CHNK) ztb$)UbzP&1ppkgPANLDp{Y4ejg^0*5B&_2D3&8@W;C)p-p#C`+!rlcyMq-lx5eAsI zP;Vk0FhM9|@L3F-CQ6ckn&9R#XDZ2=reF<2)v`x*u>c= zgn&G@_dON81;>qL-bWS1jNKbKWfg8c zHJTvylMCk77u>W^#0(E!K^{pWR>KX`>Mm}{xuB3l+ljIOJDnhyALt9v-m(ul80X|e z#o%lqV5deyr$Zb8f|@i;{0Q;4+VI)89DEKUZohC@q zLE>r}=Ux)eQxM??w(DpKDAA4@(ak=(-FG!*%Gmh1i-rC~8-7*dmaXcK?$ z4!E8WP<5ewLXwIfqUj>5<6k7CIL+e9r7A&7wcN`6#mRYDCFZ9WX zFHHnhS3D?h`_jaLVFc|yJG^m)mqpQ(k-wY@l)O8fJ;ir!@4U8NgOr1}OtAp#gTc&{B{J ztZ)OeuW0BkVPz++oxPv%aBCEXyX~fsqzI7ir_oW0#x3Rx+9Es={P1TB-||G^s0Zy1C0epV*C>HYBqr1 z9^jb!&5yA29Sq3`|CS!JCptuDS&s#-C6Vt94oQ@&n&B- zF7%&Ih5*bcJJ1|F@J8;^#lV&VIvokSxQ@OOq+Fwa_-nUdBl55`R9&a%p_%xg^VM|D z6&(Kj-34qUbNaeVPe`etaEGQ#vF&gN1P!!?m9VfnSr2G7(9ZLuy z5Zz4wiVo%MGbAKp=JVnHyVp-&__r-t!&wMF7OV(sr`~7!6Ly&6ms_*wpdt*Ve+KCV z{}DhDGaICnG5h&2{Om{IWHg)gHiBhXta!ep3JCp5k4Hjs!N5gj|biPk)J#fh&2R;xc zz;^{j0siSIBy#>&4u+dF2o~qNgt7wu0V6)ioWZvY83e!6E0N|C#=fXRBi@|L*UBEw zS^_|zlg%AK+2$kp@efKN#D|TjLD!8e;A>-BZpli%`Iz29Nm)Qs=HqNzd|B3L@KKfT zCz1uX7)}&W=i~j`w2(*vdW-nBBLQJU2`f7!Voln7yqMWCJ`#AkgwKNGP?nYdzyQL# zIGVAXf^<ce9BAO33-}gryJ$7ovc5x_m2;T)5M4b}R&g2n7_c<$Hl(+!udfP@%`i z`OiX_h>#pO%hv{c!~d0oz1YuNA}ruaD-;ccL;^{|FLxy;8h(> zJ4XDvCxiqN5+nq7h~Sz8cL+{#D^MJY77IldmqID-aBwNbDFi4K3Iy+0TuO2I-?ek^ z34fmEDVce9c6N4lc6QI6v$Rurd%+1)4y5Y_O4aFsPo^6DNTJROrGM2(ol2d05;PuDoof>nYeQWz(>O@!l6ExAiS`@+65{HD-d^ZFF)e z$L3n<@N;|U{E49?s=nGzCl9Y-O!DDCGD^Cll`0){r$ntxqFU}`Ntazo?W~(B{2hIn zZ)XqP1L-}q2Pl}_Dh0(N`{I@iWhQ8%u3HQ8GC?<>(?^D>1py zR6_ysv)F6GL1GRfPs+K1$WoxIM-Vq3jDHNXBP|F!-sT5 zc`I2B#=|;!8Xm7x<|g<%h%7y-6U!zxQ%IV>l6_P+Ntm7m9>$q*QYV(3i26bTXa*#e zx^lwW?0_RfpYzp+lKSU#B6nfutSLhobxtRrX0kUD7_r?&ok;8OQ6wCAWFml!Qnp^# z^%6}|;RGBT$*Sz~BV8(EdKmCP7b_fs?V!oh41>k|L)}DSU2Mgg6*JHoTbv5@S~01?vk4UqUwSseX$Tcy(8k{wViidhlOW zUdb@)cZpWJJ8hI*A42NcmPD4?6poNKO$ToKpuukDJ*U< zV}OxY)X7E;LubY4gL6!<%BVd0wj8M7@%u4hA=NV!l#yqA!7r-Jj@66lkg%63iWbp_ zb9e#JC$kW^*%yB znsO+cD&hrhKJf4sdolJe77doA>n$X;w%$lSTr~tMdn@bXg)NxZscfZCie9|^k)vF% z+E`f@tge@Dth7%x#*(a|`XB{jONcz5&ch0X$y}KE1pba7)9S$4=QPm|6;@y~Hsd_0 zgCJAspaJKrTI%D!Vz>Io7^IwUtCt@%Pzx#v9rZ~9&c+6$?1n+FwQy3Y4xKz{@i7XrGYbKj{b@$gD3sD6_k;uah61y zVoBnUdb<*}M1M=PW%(WhBicx2IwEoPpY(Ht5twC|nm5y37Lt35p1-Zbl0!;YlDF!` zmK%MSfSDv1FTulXPujusGq>sQi&_xgV(|{WUc6C3=-(9SP%L}(asem1oXN10%sSAg z{sFyDj*ew)D|t%Uvwqdf(=)Oo8QV-ETY^31n0}fF!p{_QEIHQ*sX?QQdU@WTCEMu8 zU=q_95v$-O{dnPy%tuEyc10?0uIt4%rUI?S9+Q%OSO1>34ZDH*2SP<^aS~-Pn8>*% zu42l($1oWiNeUh_iFfQ3d>uia6u?57C4HkrqPfI0nwoR?~Oh~tag}@!Lg93 z&9Si2M;Y|W{18J|VPxtF3fP^5HZ04--wu-20(%)}ErtluIyYw<<&+LL%ob&sJ0vxO zBfXC_{2&F>x3wS$PwS%%=Vh1DOpy`^h&oa@1!3rDoMB_mGMt^z3L>`^HvIShvnzZw z2P=pr37nu+w~$y*XST*J$ju|>03~;A!y++G(cN+6P#ago&c=p&B2i$|2&<)S zdxJ%ZYiZacx{cXX<&b4<(cr>u48ES7LD>olo)BeN4e9M%5lZh)2A$_@C+(zPWngf;jV-1gZE7%AIFoNjA zjDgC@NrsW4ZdN3{lfj=%nTJkY)*g|2>I{Q?xSNChg|TND&T$2#SR4VIXV~cx*QuL? zC_R@MeiWLru}X;qM3YkCXG5H@2%EhaeCjU-xvGAVg0b7XlgmK%rRxKgwrdUY35A>U zIRPzMx4~fL4mNi+90)~h%ID37`X0^hd)$y)nYhzn=c*`ZQgaXW8N2jBLt;+arXz;s zTr^v`0@qo%GSlH!XG9j`X~Sy>XZSLxFa=-Qc%kYR7XO5Zq&Y&le zf5V}QW*d$QQ^+DNvTP}0S>@Y??ZSL4nsS?T3Zx9@wc0<=?KQdGoTIOJ< zeFJv)XNHDCWO0+R5H09Xyk8mm2$3}2D6}3~FCx>NL&iMH^-l(|t<3`ejzh+50bxCh zBDs~navAGzuVQ||nmD5;7LDyfjb}MpL9J_eYqc1X)D!AOSdBY{Cd|e#pC5q;i((Bk z7UHs5KPUBq*l(kZVZw53J;=g3I2PqhKBGKH!RDPq-$G7CZ_H_InkpHK*Ry%%!^SWx zC^1%I?2VnHww>TzlM5M3%VyH~OJc$l|Dr}Y)43-x$u=v6OB&yc?2L^d#xbTC4N8Z~ z#?fxCqB%t{6RUt*LevF6NF*VZ4MEDZ>c%{rC^IaMCVi_Lt;&3=$`*&0!0$t>jiebPH_JSzt7!!<3M3jQ>b?qm!7s zT9h^`C3_i<@oLd)rIg}BjVncvVBHI==oQ^qV?8dMd4!apCz}VjLX<@lj9H=rwFuD- zM1Hv82cwz$3X}b2hEc3u*`FbEjQX7Alm_#RlT{}wrI?o*<(o@VwnO={+$fH(>|AYp z$K8u7zs|UlOJslQHW@dF3UIoXxrUznxzlJ<0=60F2@XyyxNV|Wz?O$7-3|*Q=!jtm z#(TmZW9cyNma0!F)BZ3v7Pfb1Tp(JN$g9S9;r{Nd=J)Sh24&neV;R|Bbk1fr1;)#uDau)0sOC}9Ngl_iP_&=c_bGqk2rf6l1uSxEE(>YfGaf_&u&B6FPKlzwp!bfj( zCb_bZ#bcEGW>ZBmr%|FZ+G(0Aic3(m(jvDhMd*p#_*?N$N3<#r&$@AH0qT$&k)~kM zdK7|u*Eo|{Ir1zvIk(BF%qna;EFS)`F#)0o!{n;hXx-&~Al$(Iv&&3l=;(;m)EVP^wHrXU!Fl7rjChX}1q+_+GnB-}B zw%C&#J1Le8qcodgx*(dSDQG84m%`%T%~D;&%}$sEx!Z_omrxQ5Lf)h$3ry|!c9w$J zAs@fu!3Yiq&M*a%Ta)qZ8ACNt3E6CNh=BrR9i{JflU()EzX@CL{=3U`Na)5u-uq2U z#osglDQJpK?4I!q`Qai*0MUCQDIrsKjKd<*NEDIa-0)8(hEeQc7e zZ7qjPpAHNE_S{rfNYk>Fl>bbD|37EOJClr^Im#6LY&!h^mnr6Jo+vmh7QiN4L6TrF z8x>uk`5GS#3XUZ$=f+deKEkJa1-)qEbDT73K4nyX^Y>z;^1U-EGieqAVT%OwG9d$o zixGxpGdL>F%h$Bs%9_XX1&V@ss;tS8G`Gz`)GP5#%m;H21C;#D z&9ej%ri&$`=eY_KT`Th|p3LNGZ5A)gDxKSy<-;6AX^vEmWSCcp;%q(5rm3tnGd8R` zne9|ifO4p#S#G^Eo2wWF81a}*Dc{9>ncJMrO%P#FYIQfS5T`iV!*y1$=0fC~`NotF0>6<0+bnmP`P#SDeRHGWfCCB5IVvk%0PG3%g<#3s927pH^=S`xLG2xV@FWs*?R zo%Nml8T;@Z%$77^PWS#7IA)T#3V!gf)nXFD*^Wv=nB^ayQsOa7ZnCtXC5R-2TcoSd zoSo8?{^6EMq8!`0XT<2d7LQkJMd^pX;6dJxaTf6cE%guuXz{iZ-xg%m^e$%cC)-vd z%EcD3h;yX;dwone*z&_e>`5XcZY^%f7V&L%NlRg-IkVj6l9pWL;~LERKBX*k1O&+q z9#Dd#>?>{gRX7KGXf*m8wDaIv7-T~QOEtk^!u?6B?KS^hhqqvP!+Jw_GalI|_RhC2FLF1*HTux{^D;v{{P z#b0SP)*|CP>(yIREcjB%c*{v4omy6zHyPJPd04vcHf+^zoQ&e8sg@9-9rCX`0>m1( zd7I0hL~X}vG;O9Om*B8`ky=`rJj-%dltdl!bSwT@g4Evu-~D@@YHun|8NJXVr$e`y zoIBB7w-&2bmEC0{qj$pI{g$Z)JO7iVlNi|i&;#}BmTN3oyjje7nMbFswQTl|&H3hm zAKpUf)4yv`dRK@0qt_(=dP_7H(7vkOMK)Zrgp$$QEqFGt-jYW&dFDAwenuoe?80Pr zaig>tDSFoGSw_FbQkz?SZg;^@AgqGui7}lVZnVGhK(QPXo7J*zi*oa{MeGVIsP?ST zK-ObXW?Zm%yQ@&3?<0Yc(#^{8E0zu7N#4y4XjGeUYY^$P7dr;4Us^88O}9SQFw!>M z8c6onLHgq-eCD zSTAcZ=PXROeiT)-@5AAt%Be=y!Qw0#ZLrd|i**SvzO%d4;vqZdWTJJDC_a9&HII;hBVkIrpR7-~JO%Yf3spePLlTc7?OgPWHBwZ4 zaE(;?iT4db6H9xw~ir9BpyR1vFUHCO$dVX@-mz~;~2cp`+-#+ zc%$_wsOJ|km%uY3l;i(dF9wVrS_ zS`=c67P8p3@xPVZR+~Kj#8{0SHu>E?{2ivOa@yon!rY+HX@t`nVYVRAP*$jK9-BO7 zBi-GP95{^)=KgtY-+6SM5*TZfU)E$LGvjP>$Atb(HlBgHgA3cvi*8_E);YoUS=a#T zMv$c6aawhH37fwNrwp{Eob7>VBOAMCf5#r;u?n`<^4SFKp{iAElRP{{`KOv~A}{pI zfEu#vX}igzv&aUP)w1Oi#ZfVm-Za}^BK)v%dbyQNUIoA$Z(4>;oLi)qkcuM^7f4#2ha<)fu*qFM zH)l2FWDd58Cl>@m&!waev#sZcN6D5usIA-uS8k=`Oq+Z?A@6xarzsb3u<_iFwtB)e zbo^7IflM<81}W)tY&XRw0^HiA)LUhfYeo7u`Lf!!l6y286^GW?rU^j}*4q*|hq{Hb zXuYk2?^mzX8OixqHcO6^5G3z5TddM_vrTLnDERxSkcx&xk@U?re5m#kI;qx9+g{H; zjoNK9NvqSqmb%X-pRz!Uyky#CjJUc7ZSs6E#KkCEkJ?rUA&~}qj56Yc?F|2$&4f2z z*+R(VKT&YpY1>Kxgi1K(d`Twx3 z6fqYu(M4D_U}JavrcG@7DbVjvA(!c&eH9bTw)?h?Ifxcz{y(;#a%w>8J+%cZy&l=* z$1^uPMdvczz*#R0#cUAu(k8#hLjNX}uVDxD-7DL4ArldkwbzeiUW45ays`brIkag? zulLeo3jF%2C_@G9NVMRNa;yz@Z=d{4ZPU8VwPEM-`gy-D^pqIUF2lrkyBeu@9BpkHr_l}*0^uo_r8veRWZD5D$M zGez`f@eM;OfTZ1nTU2jum*a)$S){dHPX?~C8cB33`xCdGWXU~O0C|27v7}CGyLcgi z^^If%l6v=%zg25v*Lm1pEf=7C-_G8g+fhN#l`reM^~vsRU&AY8^E`%ofU>TO>SDCD zWa$4;#oTY~@}p49l^HR!hy4Z*@d_F*TT44gLI3U-D!FTm`UkBy4zp)|#py#imqw@_ z$?8b^-X5rAj_W=@yE92}N#Clw95CPk)?ES&MLyU=m zGwsVo&%h{AO8L2Vx!0`fs@Ue+eT4_QiIo=FJ;Nnoefsnfw&r7&+T}4?)jgT0w-5S>}3ZL`~QhWo5{$fv-NUk760 zaKk}+7}@j$fzq_wzEia1`U{Al9Od&qyG(^JjU|vp2kc@OarQy`R-r+U+Z-OFO#Ic} zLYR!fhx}>}C3%k9uQBIQJ{`BO5N@{ev|T>TV0uu6N#7TU+WVg)OKg44E>2S_5F~n5 zK`(ydbt;E1+dGJfJMMPVX+rBKcKK;EmI%Fjs+t9zN$dxkN}4~*~wOMdXod!k-SDo=@aCTZz9udh-~TxPT$uEK#M{g zO+=5=G78GLM1NpZxCj+YkpW6$i$lB?OrTsoO7vHD*d25Dsb-qb=TrJtbI2qSW0Vy) zDa~s+k62L%ILA{u(_IBCd8lRhg_W=}hF@rzM?XKBXgP z&CKH@1>QPCqv-vvo|mbGd3@!<%WFhol3L0sg2T{K&M;?kDKD>%eR^U4$=fH`%VP&> zJ-C%R2yU-Fy}S15)PbR_URJNbz(966+h5=R&_U<#-%c@@#rG_@4*DebJtTa!{6 zTE40_t7KGJ4bjHG%ZS zmrhuDSL&KQ<$b)o#$p?-sHXgbR9b$PG1W*;^mK|HgXLu)V^jlhqR5RhPBW7+WbN6R zgS@@G6v&Cz$f(*4IIn!hW(jOd3u?Rwe0ydpJ)OJ`7MIEg4HH2O8^#Fk>Yyu1=Za$4ozZWLOI z3H&C$!I4qW+vS@RHMlnyh@0iae%m!%KIc=X@2vDbE@CV%%@Ku5wblIi80<#;1c(XxI+X7!uppqI`$m`agLx7y86ycHCW(UfgI zoFQ=yT{th_y#mVb8^frJD>$93eBVzgUoueM2kxXTf9D5^ob_e0fuuEXiS7)k2pO|8 z!Euq~iq1St#_E-KE!|+2I_S>48XbDf1~Qry?Je8Cg_h4Zmq|{VLvwM#nOg~rjQJ#Y zC1(jH)Kq$Cg-Yo8#Q|Pk4vo<33rX)v&io9O=a)my7cgB{ptN1wW*OO5$ytP<+J$Vc z(if;c7;JGGSqoRrTE3zn*;GS#w>9?I-{EM+5TLc@$XHE&sf>6tpt4i!uuZ89m49DL z$;G&ZuTjeSOC)cS(@H`Tonqq1n+Wpt%arUSO%i4KUXreF z)tI7NR*#JE@=C7nh2Y}(v+@?%l;q6EPz#&anK1>yCO^C*+!N%L>oa+gXc~n!SdFY67l>Mg((cR#gm@~J!vsfVQ{Uc`|{7%xUIqg3G%_r%g zG6NJo?6o8fnsntB^A zp-?AjRzt+aZqWn1`yg)U%H<3US<5)|=~CPVNC!Ue?1ME>RRP-yVo z;;wg~Zx!5>s@1vqK8hEUP>-6BF!NVRv6IC$r28ftQYF)I>0zy&@@J4oVw>2 z)#cV;tHshsJ$k~Ceng@CngUPS0_d5IBh;Xu7c%Y7b+55s2E6Yq)IdYRU6juxhDBK=GVLj3e^E?LN;S< zs)O&|T}qXqayVt>z9m`0bNz)o8)=yU4-;$CcSwm zrQdnxO&&b;Ec3D9@TY<#ZvBiKsNi&o3wr99Zg!-lahOa?(^skd0G!M zf#D5?<(Kb;lXSHtUo95u<>eQbb4)z{K=IuD*Ec^Bu?l7kh26E|zi%K(tS|G#?)6bm z+aNNbzB8UVLWf(K{?zjqpewZVT%ys3R5$oUks0%aCaaq*`okaCYH%Dab{AgoNtJC( zPemOeHqtZIDYllEP|6=pvM1FkmfBB1@$D4mLwdMS0}Vmk!WGhh+#5lfrimFg(R;|O zgJ_e(H>aack0LA5-4ZsbK1e3I%xBRK@U z8-twGgOhP-C7+8cg$~NS82vsP4R>iYJl%^!2LsBTW(Jk8sShXPGD|UvuTk>m0i2AR zEDN)^6Y#8W=K?U}nI1Xg7uYUzIn3V>qX?;z$Ir=C9{7z-#q?C%6t%rOjL{3m zi1k2wdF|M&;%zMOur~Jb-L-24aCh*l#Shr3;@Jh7B7^VQ47zsTrsc6aGwB9+^+FF+o}RpIF8fd40=)NTQXKb45?sZ}bI)yIEhmL=-ljsFM=$CmuUkr2*0%z$ViA=mZgg%($qOrSGVbXV-L`>}dn9o(F6k`H6$@z% za$pK4oZOC*4^*LKyj|K_q7PE?-fEQWB)FE-?DnIXwF-Vng_X*pL$twiPz{PN z&jt5x0|^neczw9DQ)Ib^DEVkzPJY%#Dy?q|^1gHk}HA3~;MN9Lh9QtotX>(&cNa)g)latyxqnJZgEfTx-D%x|9vW zX;Y9_LpfeI)HjH1?jVQmp$@3K$Y?UNBf{(R4$e4k)$ooW?;bdXoqX@1v^(XB*%S!ry>612>6zhU* zA>3>lKsKnn{or{gk)mCkxd|>fH40l%`l^b7 z#bNEsm`Ajuqu~OI3M1>gh$-a2zYp>qgz2mSIpgrTUr2TrnW-7OLfh->NPJg0E?ZGb z=w?cB(Q8s2yv^%C_HD4;myFr%8&2+al>zJnrLW#8=%4|^H+Vzl`FncWH>gK81~wk62A_H-S$Ct zltzc&uKSYH*We%&%ev!imktgG94`_&=hI*(-y(gxi%i}74r!DHY5yRsX|w3(_sF5{ zGK+rE9d_3}r4%d4+e0Q%m3x3}dr4aKa7J^Zjt0ed{(rt?*(={952HS&^r-iY9z(Bq z6?;kTdxE~{6Q|1yUJJ6u#*X!hHlqPk(ST%41M+&~Qq5PsF~CQ#IvBoL*_S1%n!LPL zB0OkgE8e}J_-InMryNy_dZFG54nLA&_j3{FDPdsW!XwTPDdbrnXDMcuLH_&oR`^U) zG)aqETAfLZBAxomz3^duQBy!|Mvo-;gtpk*`<>ED)%7D4>%io#a3>{`{i@wt=VR2| z0D(a}nq@T3O#(uDGNE2f0 z?+lBlj}bf{5UiE2%Y0x{bF)jHYW795HTaYaftqq-~1=S)k|X@E07 zcY$dG&?4_vWX%9)X--Lt1Ljs+@_B%m=k^!5J}?}@?|fB(u^mYq=q$qwKk>&$5qqIV zF`(i-T7`5W!;egA=U0TRuOOGPPcNd5x$Q~HP^bMXJKhZ$x4t)QI1!FiLL=z}FG26x zEyUU$U*_lAive8>Pb#W`&h5m66M4sOKHj+V-=evhU9~&|!Tq}hN%A1s&FO=HYS=@I zV%P8r=UYbsd;53*a0#!SNnm$Z z`5cd{iOuB72-&9TYcS9%E+ECnI4xfdv_;$J|1b!(&&KG{CWGC13H2&tk<<(wiH4M1 z!lbc#jLGhiviq|rZ|O>v$CnH*fBE0s zg9!R)QQOeaKe%$Zr&)+OOvTK;%*nW5*+y<6yJ6a7k01N74YZ+CiME4ZTvze9{$#v( za8b#4Bqjju8-%f_9b3z?ReUajTb=b-D9Hh~e>@cUaN7fbo19%FdyWL;o&bRVT`j;& z%H8qPk%SOAA&#M_tN&wHn3=@SDdm350q|AQ8q3n9%?h~apLnlIv z{i({+k-n1<=x|pwf55b~T;kgW*vJ}OEoVo6{~~80=OppCKVxmRpm3u~cb#*FFPby9pRjmAQvRy+|5sfOeIl;nk zice-;9y{A|;2MTUJeCe+JZKPpb-=M7( zH5O@~#0AQdxKn3^D71g{$CmL};@tUaT^X0677_{7=xNYmOC6OQN^lLf#rV|`8z#YO+%&+w4jQwt)?%AkYyOB|~n@34p z&TVoR3MstvO9M>W6Y#txsGU-<-^Pe84eH8tKJ;ZX?JdWX3SIb$z=I)wrIC#G1fn)Szc6vB<) zye2<3gNDz7Dx=1$03!*+W;Qd{n&b}K)1k#*Fqn3!)9pu&Uo%UrL>C7YKQI!|AEB^z z#?sH>&@Z#Zwx-WNQ%n0}B0LO#(n22+4waXPM=&jV>RqKqL3Bxo)~<9?7jryr6}PZ0 ze%_+&*=SMRGS0*0;#TtMp=gmg`1$lr7@wnHChY=d;0lh%#p8TiKFz%H-Ab7LHh#6! z;^?0_6xWf9?tD52H4b0J$+&mi;W5?Jn+slkWLLDS>7C>Rcar;)(0XDIb;Gtt_jf>@ z>H%I}c%0?&^J<4jA>3JRAg6-m1m;a3HE@pyAce>s?F`C`I^e;>4dz1A!;JT<2M^bm zW2rSydTr!96z+VC1DehgtCPZWR*h%^FQ|{*J#9F4oZ?X2U@n5mbt)n2tV(7Vn~Ulz z%m=S;7U$8+%gKoOGG|*#c?&Li@NluY&Hd=6>ugu4aMdns@43lHAgMdIL5$*Z%E6+}HVVZs=V`5OI8@%%Je(5kYvi@+O) zVz6mZXaA!peDCNL0{WW8VnA*9>C)o9kXj4cYePi+cO0K#@DCtw7t0CRuml=fK6>zQ zKf8D^(2MfCbCE3@FjV+m=u4ahSP;nAWLk9+n%6*1pbdz@As%?#*3R+05>K?A4V}&a zuMIMZMh`r$Z#R%OOQdO+FNFfd>>dEz;?AGjjNUPN(SK;@4H!l{vwt7vfycG(VWiD6 zDX`Zv2)rHP30NkF;_sCAFrNnxSG&iu);d=kO4HP;n^6ad1x? zf_K+b@pzZ6u74;S#$17OE1e^TNKRo^CUt z{w$1>Y8u;=7{u|o!akJX#`{Pz1OH-$N({1v)`l@_z;(5QYsYtLA#r$T>1x#7b)-rT zA;;#4)zp))ng4!^x{D(L()vr)@f@G9MvlI;H4tN*%*hkhI14gGZmm3+>lAv{46oA$ z<6S>+=)*PA2!^$gkUfo)zf8roR zBL3wwZw)6OT8cy%{Q1yT%Lm`3qKaKebKTf+w@^z%A&rb=UokUoZIR`q%r#+^x=-uNH8* zPQ5-=1YyAfyC-XgWU-sXd#f{*H7NhMWBE$0lraPqiMw;4(${e@U`LpJp8LU z9>qej*wn6Ew(4lH3fx3VJ5gsjGo|38D?8;NUP#IJ9h_`*1lZjRv&e{X$#lYcig>AY zzP5QdesTn^^iEUcm}#fLJ06fM#aZ|(_b~Mu-z**-Nzk||n#L84A?FomI_vI6lNt_d zh^}@ZSxC{KPREgyUCuOyDr&3ra1a!0uFq+xsRdt)RiOs5Zja1VZtjNt-c{s0V^V;XRIV5h zNb>BJMrp7IfLlo_AdH;bEqRA2??qLWmy3k%m9ZmXFL>Y9)bfJKyelpq8lE*vz2JbR z6#{aaYIt3bLihGMqk`zjKiK$F@=|i>Bn}k&q+w^m6ZKxK`8oy! zkTVBlXI!Tu2fBITwgshX@Jb2F! zI>i~?s6*i0>%neLumWKL*j({smYVl={cio z=oqaEK7F{TXNPg#uUPMZNcPZ$^;5Gq3(Dk1Z`Ov7)YRzRWuQl)X@}*(f&+)4+nd2E zPdra%Pnf?OO3t6ac7Od}rN!F(3iL)s4kKs33yAP|?skas#*Lsw!iez%o`}5vRqpTS zJp$hLksiEOM`V~CMtNn&s=Pep+!2uwTjq^@Tn?>ygVrQ!T61H(2fpHO0>AiqF2C34 zwIrBqfCfKivIqX)q=3q#&oR-}UOT?uunvXBAx^c{6mm|}7K$R>j>;%7@+h>fpXmXZ zG6T0TP^o@w+WkxcrDu5n2K)$nxdEe&0nliH2jJo{d4By1<#k!&!8>UZQ6Tun+CSby z-7^SnRW<77S*zmnlX4c9c*yZ0 z>It!%P;+V1o?8LEhu+Ypz`ty!lEvd)-AUB7Wh?PM?TjEbPKqsp^aa(9|BO2B;#XVv z=57xCvKwQ4NVx7d+A;SB470O{|JudPNn|mn<@=z?ry*hEJucz9)50uU|H*ZQ zpjDgktKGw1@RUNs$et&dm*|@?T#*k{%n#2vuhD?_vYfzJZFW}U3E4Uy$0y8ub__tIdr6iu3P-mUK(2$eg%yU z<HPb@Sz{a7H;QC5frEq}`$)%R%|&Fk_6Su7fzrd=Z|Jd_lDH*}79Vw*!(3 zaP2y+b{!7wQ#;T|x?{JP#gJ9^t~-wa-wb$d3~51%UBt3(RGmNvdmD~vQl|M|zAk7% zSL9l68dZ;q=MVpCnHpx&7*3NyZEF2CmCU>-S`|92;@(rJ_5iG?Mb&ReQSoF{gTMgN ztDVR>X03ia@nB#~2A?DqM2Qvo8L4h$)Q!9E|Qx5$LP(K#rU;Kd)8QX%B z%U_b@^h+SuX~oI&RPrWDUe$(^->78$Wss|8aB|bj;>pL9T@yw;gFBVYn==>h+Mdk3 z?5xae`t#y#``@4o)}vk80JIH{kZAAf|CFo#!hfP3-#(n&^-p<}brdDX4&daBk%56^ z;(N)vMtOzttcgluyvQqZHC`G2@~JRN<>^V9RaiTC;i9e`VZuQ$q1L}A{J`<+C*x}Q z8&_mxdqQO;P2;|QXk{Rt*j~l@sn}KVxH^CA@Ivv6%ft_6X)Hgym4M+<~6K`M3Yab?dgF({{qAt847|T|N#?zw0!UXLrPada(K4Z**7(1?0pp&9CD5 zhYD_${&vkXOqYRpORlO$^yvaB)I^L0f^Z2kUZCfudw3UW7B0a7?TQB#ch5#^7TwC; zhN(IN(zG7FyFA77*{E8^-R&v9US8u-wRW(bNhdGv$*q>6_fb#R#*`9AGX8ez$f)~b zB#nRF0H4vs^OjIN&C)17teF;XB(9m#nY z%kvL-SLdp{C>D?^?kuS9i5}dHEgbEH8L)t~e}L*w+FkqwyX#5c=&z!~d%;1p$0RN+ zr_cm?*ExR}5`B48WxB?>ZO++0x}PbO_mAP}q9W^H-TN51+K^m+Jvsb9u1h{WfZ~<5 z&~lOZ>K9x&`JwRHn(u;EbY$S4?a}M!5k0m2Sys>Sd!EXue(fo$eQxFCL`N{bq4rF4>btei z{uqrW@BgY(@$Mt57I-tOmfLW~Gst=!MR|EiL{zZRBZxevynN9rFPPNHmQ7E84qg^(89XT85Jsy>u4m zCOA*Y={UAV^^5#h&L{Q$1-WRlN)9A_l7b7e`JR`%MgfJZX#q$GUWo~D%j@KqGoc!N z9bFp$YuBZPnsPCxU(xDQDW$l_w4U%E$hmrQa-|-@2J*vy(rODRZ((oFqkY1RUt@Wj zjLWF+9Ney&Cg9HhmP4}!2HQxTPh#?~*zaz8qc2uGNR6s!@VAGkcpb@lE!q=Z{!*7D72{YGo{N{DR4l?7tY{F8M^qIRs+#rYo%mLIwgTV`O@tKH;SN@jk>G#MPGMc(8{;lGJ$(1ki5&0)7%Z6jtw2BQ65y?O1a`CSu%xR5Nw$mS} zEGKh(=4FR|eLlg8YC6FB`8CySea7%}p1QQhhJi2LWfs1`l(gAf=AwtF%%6RUDG1kD7=2y2$a`;*7VVhos+x%K5O2-7 z&)qq|1Haz~nzZn7@xwd?R?YtYD4uhishM-C#9g)SN>E5N>Kgv#6JJ>6iL-OXeL?<^ zz{z0=Atti#fN1A$xidB_fuGjI*w?O$>XhR6eZDU7dPX)ClT?9|+m;W(7POxbb8F!J zY}KNtU|ns>z2xc-R7pPf0)n~<#H@gW{RISjmWq3(CJIWIF8 ztQ1u{L`Ul8lD2O}0c+~10Dh8h-0|*XE~9zdvB=d9k!NWX8b%ChArbiU|G2z!bB3T;?@*HtZKWFdnIoEr#vdHPdU zF;XwkB~HeS1lhYCF$TGclT(2%p5j=yZSi@BAy6_V=Yyu@gQ$QeT*dCNqK{z`r4)5n zL{3w(bqZ-8>Ix^Ne+a=r60F&n)e6R69&EuV^}#5O){N4wnG_$%);(PM&|ru;J(H84 zXX0Z#!`{j+|BLc!%;vlvvqD@RXJ->bz&o&5<%N)^i$eTK?xu2nSwI0TuwJ0`joci9 zFEFX^csv2myFAGVb;XgQp~BRSH&l&21Z~Gdb8X@rvy)2Ud$D7^H#nwXUaXJtqz$rF z6_Qs6fqi#|@NEHRi)yR#6dDW%Jq5fr&J^88@#VQ0+UlU~m&4?|&J{zJ=vK>(M zUVqn%nDj22&(0&1SC*qg^*|3j%F*@oE=wRqJ2n?sM~r%x-6#1tXRVN|>aUItgc!on)8(d-^^&pkdx#Um_@pAD$8p%U99JKOU|vWFQ~HP%^oiXvB`)A@9e)P&KjY z)CPg9NNq_y$+C;cv1#_00e_(>UvG(QE~qUOK&}@EHIj4TqPqCTuY1!2F5|vhTR)Ef ze@bFfjEBk9rS`FlOLsd_JOQgq?NU3rlt=Nq4wsAd;an%WaB~Hfr6)JahXyircptZ- zfE$%n0N)+b*aK z+({dOJy$MgzpiYj;`1`mbMCdcuojL}51E|yk=U00Dij^rFVyUQd!!558R!KQjfK}C zqxASWFpL(e!0mf89F2F5q?9;PeMD%Sd(!;(r^QE0qeZ(-IgNaJEXOa(Ek<;+*OxQ= z5Ktn}8QN~|Ihowf?GjJ&BO*}Qi6ykKi`-fkYI3L8WEkZgUe0-&BV7EHu!q_?KEp6= zHHSWra`}ICOziQj=GER{IRA&nYm@&I?qVUNLmn6Rr+rKIY`-6X7kJ_I+O=i$I<=Y* zQhzO?U%6UhOs6%ky6zYz(#v0EdY!kah0LT-q@0jaBGJUjyFGZ5B3!!H!D|BwgZ=|KSMM@c}NC;+Y<@c^uhk~Qz8ymH4>9*@JhrgrGP7#6a@ zx9WOY+H2kk6>26Kd0h$24|{*}e(F@<{Sc0-YVaG+c;IiI4hyS3b(qb0!-vSKEcYg=+&wEmk`Vz=dll_9Su|e=Yda; z!Oa}*11s^-5cvL)7NEyRPsB+7xnjq*nP^)Iq*l|k&G{r}p~sNr$CBmX7)T9!p#^Z4 znz-r9o55(e1MRM^5m@H6ipOJx7*{FQtZGe%uQ&$`Y}$=OP+oVHITxwvQWiXwC18W*%Iq2 zKt{!ixx{g&Ymx0x>?uM)5lurAk6hEqHy`ohTS9u#!(FNYU6+w_0S;4%3ye`*8K zq6iQC{@kLKTwhX*LvMEugBWW$=;&2@W%*1yGDd2vBOY9#Sih``*1A~-& zt*XvJGK$JE)R*!u*W|plMdgS)P03B`P;x#pvbJa;SEEod@b2PZ4CRH?(>T#|%A3@H z^ERhz)PG2MiH%fVASqT{_CWpO;GJ&5c~go@HP%z|rsk9!PhNq{qTG$)WB1V)2p^+Q zv`2osx1!KmT+b0DP&j{EO36cNx6$Eq6A8j`HeN3nOFyJr77_|-M%3yIl7f$95JO3+ zL$Q(&ldB^qcPZ)O@6A*>wrFR6`06Um+u9urXBQ4VS<;n{EAos=_#0pQp@RK;=)%~b z;=Hs{;QfaW{ZQTy{dB=(Mk!hIX3Fc{U*$!(J%3=Ku!2{i_(=Fqtfm1Y266o2Z-w!h z$r@E2F@Gx5oq>>`ofy{Qi$17(ZW+vUD@#k2PnE`2!hDik#uW|@&meoY_+=zDT16O5 z>#u)|q%uT)#=bF9Vhrh57NK@y8R=*TP>D}RL4H<7>_o-9`Yos`_7EOo{~rH&{Dj~! zKw0d;B$X9Yi1PdFBP&t$2h45SE!~ClD6~2^=$^8uXXRo_$xGg#FemHEfgHb*%dEcw zcJ4b(4x6^%dDkK5%ei97(sE*n-+g*YiDSMP_^3|1sa|Ufm-3{X+=q%R58;EcK~EJ1 zIf%3?FDqWZ3cQnt$;|R1(&g#*zEWwlqbmeQdo&p5W*Evr9zh)IHBWB1=O12Uk5PdR zvh=7fu#omEVO!s1wyY1u=O7`|=1P0rg|M_ds>|!~!K{51pl1J5T?OOP*dxJcB92rI} zbNcFWK?q*$&r1`>T;79M(r!moBbZp9a5SRwQZ(w!u!c2*J+H$C2kluR8lCd*l( zLNb`8@OWOsw2*1Zu6(S%R;N2Z2}Dvg1R+lwcK2gzP*ciGa;3;F3QvLDB4&YL#%hrw z_vVLDW;u%|GsCPmkP|6VXO@J`+Fl{tk z4y$C3pOqd34A}P2Tj$o2wPsg=#AD&2)`)O@0C83opX0xH(w_Q1#6kMrm^PMr<#rc{ zBEzQ305hd3q}7RJ%zWfjRiWCvGXGY52tjQjsE&tXc*4rDQDkEtePOnZ!@V=T8U#Ja z#{@+YV?KQz59VIV+?HQ3|BAuw@9G9nyK{vrED~O+eV3?L97(S3s>|immn(b+7Q}&u z1ikaC1u^M9V6g#_YbFA=w&80ElIPW3RoVE?>vQ7G|IiwG_EzgA;RzH~oQ$jC65sn; zS_AcUFUsmG%O1P2KC66hK>wd0;w63yXbjV~JlBm(ujvXQ?`yh(N$+4+AS+e0b@$Ko zbFD+r+uF3ZX$5zw7=|rY$@K^Qg5x}xUz<5DtR%3HYRZjJV=avK8i{0iZP(XEIpkez z8~xT~Z}^vX=niEiijzGZ#PZNk%UOah59v!F+QS$BrcmLjx9u$7Hi4#|cLU|8lmP{zp5B*dMlf8C_cq%rWYGYnp)>R)w66y%4{T~m} zX8=DM{i@AbTQ&8-Ppu<1FFWWDCgcHrGXkqtet0Vn{9`G9akD(W^dtP8zrqvjQmOjX zsVnrk8$NF=m4D(Z{HKl{_#z$kfn;-CIb;vjg~h(>rUE=KH_BZPyg7q8uV{U&nEKQc z^L%vH(al-tlor7`H>kE^i;F4;yn{R+ipq?&MgF*R<8W4JFbZks*r%h^LSlK@x<2YI zFpiVczSrXbB`#fJL&d**K`Z^9*$Q}}*6>HBljW(d2=b}E$Qp+FC(Kv?*Z}{WJA?T% zDKvrfP8BV>^xQaoAE5L-RqZBX)GP{3VRi2=_}F{^D0(7Ni>f@A3oMo<1b%EXq@V#Y zDh~eCNHZK;&*#w0d3ujMzfD6T4Ro#A8`f!{!9T{f9o02zi9Wx3kMNI9jvB)tyC=rF zc6T~-1;rO3ndu@4Z20S_g4ZB&F07`VUH{%fp}3De-4)3i*sJE{y*B_|0H`(`L||u) zLX)@ZtsXaEwQGQmYPOwrl#?t|^cJ$Am)!f>PkCc^sXW{f(oi~HWJB<>_o_Sx>E2M5 z8$)@PgDTHXGV92R@iyhP!d{!G&q|)Eyrf3pH94;GaJ@%MS#BZa#r(l}=Nie?!gEUg z?-D1+G?tlsoyH*VxxvXJ8@t3O>Nikw?OU9j)C?Xz@+Ky^FO6lZ3{3!Ne$NANvkBIF zo9<#9s3(;C=6R3kj*+?-z1Kw3(@p=;mgM_Ww>x`!hc7wH^R23U!)DBD))D*?8 zpJ5&OZ#hHzHxPas9a&vd$^4hvLILDqQ)!NnX3*dFl?tfj$2QwWQF0w@o~f0M`VTph z`zo1d6tL~B3b2z;3#8@KnuFIUlr(6G#oA_zA%IM6F6-Msd3XpSd3bW$T<$&STY#5o zRe5>bSM@AOPtP|L7O9KatKF@76RzSz$hH>3tAG5p^4``MTiY;)XvfN>C>4(b9FYd@ z+RTEtzr8eg1qzulAhokyW(+MPw()16Sw7PWP)Z!>(OvE;KceJO@tmB{N(6-heLj?! ziumD;_@R}#y%=fVO3GZ?3WXPxq=jS2x-McEFZpIp?%q)7C0e1KG%r@BP!~DW20L1x zT4TSDMrz)7t?3DxRViA4Ek|gcP_5Z``c1GpXscHArs~>~{J6lJ_!|el2lkJsoJmb~ zZ7m*O-0CJhVM-gQ@>^pSAY%O!N`BswlhfN_RF!WlCe6Q6j?{Soy=I^;ZAU+8zFK^R4j%Zv?G1tC_u+EXhPQ(PB|57Bq1OmXp4fwvVOkrh-9R?w z2IUPMrt)%;tWgF$>R&F+UMT~B^`o@_e4Q7QA@7&P6wvm2Ex)?OH>>-w1QcVOfMU^${435{mwEc8Vdx-|di z!;=HBI&Hn+iI-sgLp1w*ImG%m}CsITdEP&BiVgXFlsE8yn_TEJS z6$`NhONP>k9UEA&Ac74=h3~g_@4fFXytAL%>w4R}?+4fyp(kGV+{A}~(8M!FAGfd1+ZPIR2yaRE13Veva zRFk>m!K?hfBF*c*m4%{FJfMIY4;29Gp`zSZv(8WN3g2+Ft{QrMeJbO12LC(W=*g;P z5Uvnv;X}2Z_y}l%7|@-n5z(<7yz~t;!lS%OD9V!rP89p@TI;&J`xOGzfB<~cx$urc zTaW`2#isc>epC}09&4-l{@ijVYsExyJ$qKroy;9@)q~*7N3#hP0(5pd%xw@*VEi1v)kcVvjgbvKm z!*!knQ+U@?0HP-2oX7CGXcx568VixZCW>lrTNPC>Nt%+CQ@~SoRe;ZAu|jr5tL9ik zxW2Yk-7#O!XJP^BE4LAEJ|d>kLA}kmxTdEI!}|n7%(A|c&(#Tr0GnLpG{%O+H9A!U z7A;_Reu?XSV+zHw-A>k~f(`^QL&@L%-S~&v+U)o_v%91!myR>||3!J)}Rpn$J zZ-9H?$fB{(JNeE8CzC`&l6;!+S@MFpD`DN)XqvoC5B4+oert8LwY*XBuh-8+E=!Cl zew+%^4jBr$`HwY1#aWUuM$Uo|dyjJI*rAa>YRsbPUr$KsxTqjpY@MUq9`&b7Iwfe$ z{MZnBox**E)?nW~Fr_Y(LZ7|nhlE#oWP7-d-2(q<>F6Id;58kMwmBzy|GSizJ-PfF z4oM}Cl62SUH;9#1Ag3t?q3hPa4W=J2<*G2TM8+$Juu94+@-s_IEVoufh|}hM ztbG~kXlYf|{*5Xbe(4-(C3D{#u<41XXXatCv1o@Rsm)xF?^-bOu(_hMUpT$)@@-Vu z8?BgMIp1f=pyvT)b-hP9ys~BFmGdRWe)B+{tYhTJd1CF$a&~6Y?GYN!@Pkjo1{BI} zQBM!6HMtzlkc<}c6Q`ry&cr1`*8!jX>lz7u)8N&~$-jZ&uTW_p4(ilMgu2>jNdaPD z0q@g!#1k6Sj6}_Pa(In9#SdVWnim1-hc>4oc`N$8d`ceCnYb*#$#H`c{pN!_s0$-U z`PrBm!WR3WFRg=6-UYZ0KYIFhXZT{MOc1SX+xr>w0d0n=@X)%wD71@!T5R3y&`4;n zKlV)d=2RR&QJ#Xh0@TdMf9XrKr+$b^cdS>t*5W5z<`>9q)eW|I|w zVUqx$Qw0XtO94rtG63PCycAsL52TF_lhdpX>IgpR()Kz`9)`e+4->9O5I>yaB;HXr z=H$!oqQ9`hGAYA)cwR;Z)Ltwt{4`yRv{o3`a ze<(7gF4l<$WQr-np%@KihDgJa!9T^1P&RyhY<~pe_lMT`$mlKJmXR~*m)WqJ%~=%= z{t2!ocw0sUI4Txa>Muc>4Tesd7Pv&$N)Y_l_QNmHRbC%y_%b|?@R`^F#rhFmd2uL2Qw<+?T!HuA zYg1oQzXi)tztg9x0t}%*2?Zpc;Q@L@w=#4E01t90z+18MoJz@SZc=hf5-Dw|1Wxb{ zISwJ8qt)?l{N)aXvW=i)=QSb!pz4P(Qt~K!jE1zFfPAh|yWlHE9wljS!t9Q6irH z5Xg}r3x45q&MI-H;IZKO<7Ns* zIO$Dr22R8`VKN7;1)CP_DA`M~2a!R^pYW9J8iZRpeQawJ=PuadmxbKyR(7A>z3zsJ z@o{x)oI?{cSy$b2Sg;OUk9AW3p5n?JCdgfy*0l#qvtBQ5i*<7QCS?Z7@vT-)4Bow! z%bBxYbS!J1E-|I(JHy}_yjSi^UiyD^k%bPtCc+* zhuq|{SN&{jRxSMQ*XXa_fB&c4WjF*U=Pitp&9A!8OC#Q8GVx86?J*e*OksGsTzdSp>Z54VBYcli@?)sKK+P^9ueO00_p(IWaT4FSl2PY6gAr zf_^W-M_IG+28mow%Z<`G*gp7Itr=rj8l1$Md>&(~RS0sL0xpl`0d9gIf`(7LyyHK> zh@CC(%hk*euMEqY2pwnZshEYF_zPTdzla2|5_WI|hJ}F<`-XxceUQwRV_3G3;k$1V z59xlGaCuQvc*$M#o&2!<_n!<}5NYeIm}O*dLb2bikked*A&7ZV$IVDP8^zM5Y!(Mt zyB@PPZ90OLpLEv!O#DXROUQ0`qC+eZ z_i$|&ca47DVzK)YO#XYdmD*4F3cS}2ag zIb4tzxa%v1FMe;U7G^m@1M1%G-NQU+tSts+evvumjf~eAf-iTUg9q{;f8%QM=X{Xy z^$jzn$thc!<-?4rr~@yL`BxdQ7UC`!s=%hrmOp$B`~+B#$9JotB4>7>-!p_@3wGhO zQKXST$91-~RHll}f%`P^3vMw)ruxLuT!okJVrz`jFIaN|7#}pFrX1E9Z&vS?j@Ali zNgFzlmT_o7`MaeU{;YJ(^D{jFuhj>G^hvIbX+;F!Rbv<99 zQah^k5kIw*@pwxB!ZC$<#e>&+9Mz}Q92Ku~XJp~2$<3`vX#(QXQ}Gh|GDT;I6>;G@pL?9%C4LdzWPuo`$X@g z`#^0x^l=cT<$FAno{Zsvz1X@QwpThrJ8v%vGwCg-*|XYYQgZJhWaR(wwQ!w8aV&p( zeQWDt=!veo@Y?P*ltI&nsjSK1L!!)aJ-S(Lg)~2)jdkE;-a1^y>q$YPRP~ZX6#Mrm zmgcoj@|7X`Kt3^+kvHuV!`#chDUKb$oqqhl_rF==8MJJiN-Zc>=p9n)?cNj&yt?Fx-Un%)T2qSmguXASF8nGYbIa3*V+kSD~$EoWa?>#7w zz9hsSH5@pDK}`?n#CxN?4uHdia7GR}AYN4wX!AJk2sr!<4*WFX!fXb;c|a$=r&38d zJf6qMfe|V*()FOUuoiR>X-($KX-aRqOVgS!lG9Ad;Dt)9Eqec8?H1Tuj~2$SxJ>zz zX6hmg6{ah^%03dCLl`PTms7GE`D>ZThUuv8A(WH3lBP8x{)Z&drc$zd6f6F~A)Of5 z-=Sp7H8RKHL% zeP%2g*hl;|;ToD>0&UtVGALfG46{b>qbRY>UY6D;L1j_>*z)Yw_Imp|`&2bTr;Ycj z_MqXUR`&V^EyUDOVWA-cMEM>#sYDq@efOzI=>b&((*Bq!#wlflEKN+M;xm_F`*Bh(JW+SyTIoVVEFwA3AgKahlpf|fzeFxs(fqZ{b*IaO$CwJ1u_Co-0 zLysFvIhDsZB~d5E5pwiNyCLQ9{AZ{3#DEY(^D~q_af*R%N%R(8=LcIuvnmK}@*D(? zh$Fe@5GQTkqc%6(MRBO>&psLOBzg{!k8aa(*+0dvJSRpGeR7(f^&5R`ft8S=xb}pF$&fuaKS~4=5k@x4tiM-XU z#D+h@IQ21_@x4mhYz5x`UvbLyp<;uIo`ipo^)<9@#qVk^!k6NlJJTtMf6lvw zYhd_V_W0sffkwc4pXC0l^A=FKbGn}X44rp^MO``6ABDsvO$;taX54<44p}{6b3VAt zc}`J|BsxuMa{JOy<>DerZa|)uG_d2Z1Zn6j0dQ$G@N6zhj4c&c2U&J?j*ZRaMLuxPn8K~)CCo&;JG<3L!Qxkej z@i=teh|^FvoZHUOeIuCFHGJ)A`ZiWN{&*KFYfNfpN-H)UGr@h1I~kBEa<^+y8h#X- zD@O@@o%%H=+ki3_mgFxXpHW{g4H@jIX+SQ07InX|eez~*EKz&jFG*lZa9lVF_?m$jo7UTOjf7}VA zx9a($LGe<1eosuYB&of#Aob0z8gl;!O+&>6*AbxCn$w+Z$`WTBVLAQs%u(vMm?QH1 zB6^T~nV&^A@?`~*#@SK;+J{p99YQ8$OYz1QN|`&79M9HyG2InWO2{a(JqO`r{T%Tl zP*>f~cITlGIstd&RJUs^gPt0rsVDT>f?{sHj1Bt^_^(hmKesc4QimSCZxle*p z^jMhToyMv_ z@37NhEV=V-x6@n(eV;4c$7FK_g_*7)Ev|^Gq%}hvZRkrIv@Cv!CuS{~e?`2&?1Acm z-38R;Zj-87!kwW&=}G%+sXkU$QACG5q}f%Sdo${_<01za{e}wc!yn&87RPIZ=v;`u z$*}&?rtdb&Vt)cjzA7277!;#{`!r-kq6XiDhS^&f3k|~i8t5w+9X_0>v2IZ{)K{pE zp2$@EEDmaj%>j+dlK;e)q*A8skm!8~h4nk2u_XaF#1X!IuBzo`=<6En;;!I@=6+bn z;2}J*#iW~j9gON96&b}|mliEfgI>$(1i5ovs-NWzP&%C=O>gMDS>9ok;*?69@8Wx^ z=o`|<4hJYXCXJCF-Vndp|G}w8=U7NZPfj)Fq#AjVLFZi%Yaw`7-P4DsEeC!$@Gz<3 z_iHA@FS{vSVwQLlCAQ9HZ1~>J_zJ^2=c4-EG_z;xb)Fy?4dkgXp`RW-k1}niM0&HRV(+z;BwXXUft>bqr^Y8j9hRZ8xb4sOI=bDO^epcY3y86+g4Ym(?;VC?)-?}9S;@W#V9et zRjVSgX!^`g2IYfI`z9=H8U7=v?44`lqx6%QeboX3RZ~*)0oXM602|qEsxMu~?L_4p zVJPOu1}{&FR}+r{@$`@JjlzT&NH_)(@`FHqF9w~4d(fD0Q3VjLq9r4rE)ciBM>foR zW`lz0%@VxE&wNXvtzBq0>X6W>fOZEC)yiqyR!ds6(K-trE?|f5IrVrBu=LI~-l4v> zhxR+d4eZ-%*+YXuhOUVn%?_i!fe?cqo-%O54>H&j%ZEB!!Ld4qo}apdq&|jYUFt-9 zAByq~yq0Y>1KC}mW6_-?;O^O{rU7P#BrAB>6&p~ z?%$W;KXj8G({XtWt2qp$WHo6sKx;)tJeJ&T3Qc=An5=v(h2O~ndMKsnNXcWVldyUM zp!G1BY%XX+aLz^ZUIes5?b6JuYGddK8E;1HQlzGm3|>ZsqqU@Xl-5OXTEU2uwz$^) z9d+4`KNqe}Y2&oy@>p#{5@Ie6k(WEnSrQ2k`3WAmR8 zqnZV#24V3sOzTLr$RGWTgcNK%pHL@7m3ukT?}T7pkx%Vn~~E2?#o z-0hXLWf4NjcaAf3!Yj#Ymniw_DMtQu63vKCvz@30Zf{F%lMaC+pesJw#$)Ei_=YpQ zSR7TB1ob>mZ(+I$(fQ4x&8duY_*vNX>OS%1i#aW_UbTlhvQbTb>-gt$G9IrVyq2mu z=ryD)N|)2{iblHDj0}4v&M8w{b?e~|bEaTe!^A@IGr7nzHM^j6tTx}dPt^cl4+iG< z))F%rKCnbwvdYhLT}>PPQ`C=N-D;dep&lfqMBK4^nmntcFJP6Z8m};qD-_D^SN?FZ z%^bQ@MIRdH+th_?6y;9BOC`UGEJeL9-ee-ZzM*xfzH=aK1bf{lwr_N6W#|^Ugw9fwzlll2%hs0!i?{_2V<7hfmrJ+KdSmn#tk`wpQE!KW3Stk*j z7ahkv)EcHo6GN-*P}IJ*^xJu;ayo48%5jW-NJ8I=t6omtLkGsA%nb-(wH#{LbCUX2 zoOd|9md{ok_m>9p4mPJ~=L#urDT1#FRYq1{sPLg*H=(VPn67o*h%2?=+ zvnaCPXDu08u5}_7?Hw zva3ttzZ384DV(WmNBe{$@Iiicqtr~yP{+*9g4~rQDS{+Met2I(;O6i_iX?qMfIhvh zNS}iLu^L5E`d1qR-HbTe*eP~cbUi-}v_bK|pb5Bgnr@|5=F*kvw1QtHjF}oa1C1+a zY}HDxw=-lgRqO*rlu@mA6%zI2pEBv&kt|AY(?g{9|IyA?xDs6`rDSTBV*)foFT&wJ z2>9YJW*GKSGVqFzU}O;}(4EO`Z*ff5yomflzu-(q)%YMTc%*<;5%W(vJE6RVSK3UY zcYB!v>%ysF*;o<#%O_oZXX+*s#+9awfoybF(wW0_ zJC~E3a%q}YN;BsyC-pu{BeLITP-d?TvPN#ob#j zUx2)}g>?ENahpmhX|ZJ07hMY`ZVIKW-brrDlsaF*ZP!0`WbY9>2atXmB zV*M4d^W0-(%2!F8Efn7WgdG`n+|H47%n&W=9{0#66`Jo2uW(aT7u`{|9l4wftZRkj zUL7jHBkhVn$D_OzQe$2TdaVw(NnC|g8g1US^6!$;3TZgBsRX6Yz4Zt6O-SELX%lr4 zrCQw=s7aOLj*9hrT|@4`N{t1!U|47~CGu`wBLzJ*8FdY*e8=`aphb|5c#? z*B9DZkxdIl_;))~m(bnpLx{ZivE6hG1?sJGf!fSSUz=E#!_|l4 ztv!MN`oD{{Ex>V+lv!0}e65t=;Ax8FO zdo6v_R-U6Lj|>Z=t7gjG?`P4QHwHja0cc75rrSajdty^l??#f0@g!J|sa_1gD=AlZ z8zgG%)x_IaFLs*&_?M9dW_h4Hk-?Rc@BBsSrHpP*thIQj{jT&Jm_zELfY#7!T}+|) z&U_u-7&p<2-*R*|fd*}z$RHEFCu=P$DdmA%jH%v@aOapyY}(tv9aK>S)(MKgijbW_Q2(WWRQ&J$F}s!Aw8l2Q9sINJCPUc%O!>8(wh JwWbT`{|BuKzmEU_ delta 82796 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 diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index 8477d22d364..aae9a11b28c 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -1171,7 +1171,7 @@ bool BSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Collname = GetStringCatInfo(g, "Name", (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); Collname = GetStringCatInfo(g, "Tabname", Collname); - Options = GetStringCatInfo(g, "Colist", NULL); + Options = GetStringCatInfo(g, "Colist", Xcol ? "all" : NULL); Filter = GetStringCatInfo(g, "Filter", NULL); Pipe = GetBoolCatInfo("Pipeline", false); Driver = GetStringCatInfo(g, "Driver", NULL); @@ -1215,7 +1215,7 @@ PTDB BSONDEF::GetTable(PGLOBAL g, MODE m) if (Lrecl) { // Allocate the parse work memory - G = PlugInit(NULL, (size_t)Lrecl * (Pretty < 0 ? 2 : 4)); + G = PlugInit(NULL, (size_t)Lrecl * (Pretty < 0 ? 3 : 5)); } else { strcpy(g->Message, "LRECL is not defined"); return NULL; @@ -1249,6 +1249,7 @@ PTDB BSONDEF::GetTable(PGLOBAL g, MODE m) #endif // !MONGO_SUPPORT } // endif Driver + Pretty = 4; // Not a file } else if (Zipped) { #if defined(ZIP_SUPPORT) if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { @@ -1676,6 +1677,7 @@ BSONCOL::BSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) Xpd = false; Parsed = false; Warned = false; + Sgfy = false; } // end of BSONCOL constructor /***********************************************************************/ @@ -1695,6 +1697,7 @@ BSONCOL::BSONCOL(BSONCOL* col1, PTDB tdbp) : DOSCOL(col1, tdbp) Xpd = col1->Xpd; Parsed = col1->Parsed; Warned = col1->Warned; + Sgfy = col1->Sgfy; } // end of BSONCOL copy constructor /***********************************************************************/ @@ -1966,8 +1969,10 @@ PSZ BSONCOL::GetJpath(PGLOBAL g, bool proj) if (*p1 == '$') p1++; if (*p1 == '.') p1++; mgopath = PlugDup(g, p1); - } else + } else { + Sgfy = true; return NULL; + } // endif for (p1 = p2 = mgopath; *p1; p1++) if (i) { // Inside [] @@ -2005,6 +2010,7 @@ PSZ BSONCOL::GetJpath(PGLOBAL g, bool proj) case '*': if (*(p2 - 1) == '.' && !*(p1 + 1)) { p2--; // Suppress last :* + Sgfy = true; break; } // endif p2 @@ -2013,6 +2019,9 @@ PSZ BSONCOL::GetJpath(PGLOBAL g, bool proj) break; } // endswitch p1; + if (*(p2 - 1) == '.') + p2--; + *p2 = 0; return mgopath; } else diff --git a/storage/connect/tabbson.h b/storage/connect/tabbson.h index e9c5cc6477f..7f41bba6bd9 100644 --- a/storage/connect/tabbson.h +++ b/storage/connect/tabbson.h @@ -1,7 +1,7 @@ /*************** tabbson H Declares Source Code File (.H) **************/ -/* Name: tabbson.h Version 1.0 */ +/* Name: tabbson.h Version 1.1 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2020 */ +/* (C) Copyright to the author Olivier BERTRAND 2020 - 2021 */ /* */ /* This file contains the BSON classes declares. */ /***********************************************************************/ @@ -242,7 +242,8 @@ public: BSONCOL(BSONCOL* colp, PTDB tdbp); // Constructor used in copy process // Implementation - virtual int GetAmType(void) { return Tbp->GetAmType(); } + virtual int GetAmType(void) { return Tbp->GetAmType(); } + virtual bool Stringify(void) { return Sgfy; } // Methods virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check); @@ -270,6 +271,7 @@ protected: bool Xpd; // True for expandable column bool Parsed; // True when parsed bool Warned; // True when warning issued + bool Sgfy; // True if stringified }; // end of class BSONCOL /* -------------------------- TDBBSON class -------------------------- */ diff --git a/storage/connect/tabcmg.cpp b/storage/connect/tabcmg.cpp index f2ff721627c..1552bdde58a 100644 --- a/storage/connect/tabcmg.cpp +++ b/storage/connect/tabcmg.cpp @@ -1,6 +1,6 @@ /************** tabcmg C++ Program Source Code File (.CPP) *************/ -/* PROGRAM NAME: tabcmg Version 1.1 */ -/* (C) Copyright to the author Olivier BERTRAND 2017 */ +/* PROGRAM NAME: tabcmg Version 1.2 */ +/* (C) Copyright to the author Olivier BERTRAND 2017 - 2021 */ /* This program are the C MongoDB class DB execution routines. */ /***********************************************************************/ @@ -84,69 +84,80 @@ bool CMGDISC::FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc, bcol.Cbn = false; - if (BSON_ITER_HOLDS_UTF8(iter)) { - bcol.Type = TYPE_STRING; - bcol.Len = strlen(bson_iter_utf8(iter, NULL)); - } else if (BSON_ITER_HOLDS_INT32(iter)) { - bcol.Type = TYPE_INT; - bcol.Len = 11; // bson_iter_int32(iter) - } else if (BSON_ITER_HOLDS_INT64(iter)) { - bcol.Type = TYPE_BIGINT; - bcol.Len = 22; // bson_iter_int64(iter) - } else if (BSON_ITER_HOLDS_DOUBLE(iter)) { - bcol.Type = TYPE_DOUBLE; - bcol.Len = 12; - bcol.Scale = 6; // bson_iter_double(iter) - } else if (BSON_ITER_HOLDS_DATE_TIME(iter)) { - bcol.Type = TYPE_DATE; - bcol.Len = 19; // bson_iter_date_time(iter) - } else if (BSON_ITER_HOLDS_BOOL(iter)) { - bcol.Type = TYPE_TINY; - bcol.Len = 1; - } else if (BSON_ITER_HOLDS_OID(iter)) { - bcol.Type = TYPE_STRING; - bcol.Len = 24; // bson_iter_oid(iter) - } else if (BSON_ITER_HOLDS_DECIMAL128(iter)) { - bcol.Type = TYPE_DECIM; - bcol.Len = 32; // bson_iter_decimal128(iter, &dec) - } else if (BSON_ITER_HOLDS_DOCUMENT(iter)) { - if (lvl < 0) - continue; - else if (lvl <= k) { + switch (bson_iter_type(iter)) { + case BSON_TYPE_UTF8: bcol.Type = TYPE_STRING; - bcol.Len = 512; - } else { - bson_iter_t child; + bcol.Len = strlen(bson_iter_utf8(iter, NULL)); + break; + case BSON_TYPE_INT32: + bcol.Type = TYPE_INT; + bcol.Len = 11; // bson_iter_int32(iter) + break; + case BSON_TYPE_INT64: + bcol.Type = TYPE_BIGINT; + bcol.Len = 22; // bson_iter_int64(iter) + break; + case BSON_TYPE_DOUBLE: + bcol.Type = TYPE_DOUBLE; + bcol.Len = 12; + bcol.Scale = 6; // bson_iter_double(iter) + break; + case BSON_TYPE_DATE_TIME: + bcol.Type = TYPE_DATE; + bcol.Len = 19; // bson_iter_date_time(iter) + break; + case BSON_TYPE_BOOL: + bcol.Type = TYPE_TINY; + bcol.Len = 1; + break; + case BSON_TYPE_OID: + bcol.Type = TYPE_STRING; + bcol.Len = 24; // bson_iter_oid(iter) + break; + case BSON_TYPE_DECIMAL128: + bcol.Type = TYPE_DECIM; + bcol.Len = 32; // bson_iter_decimal128(iter, &dec) + break; + case BSON_TYPE_DOCUMENT: + if (lvl < 0) + continue; + else if (lvl <= k) { + bcol.Type = TYPE_STRING; + bcol.Len = 512; + } else { + bson_iter_t child; - if (bson_iter_recurse(iter, &child)) - if (FindInDoc(g, &child, NULL, colname, fmt, k + 1, false)) + if (bson_iter_recurse(iter, &child)) + if (FindInDoc(g, &child, NULL, colname, fmt, k + 1, false)) + return true; + + newcol = false; + } // endif lvl + + break; + case BSON_TYPE_ARRAY: + if (lvl < 0) + continue; + else if (lvl <= k) { + bcol.Type = TYPE_STRING; + bcol.Len = 512; + } else { + bson_t* arr; + bson_iter_t itar; + const uint8_t* data = NULL; + uint32_t len = 0; + + bson_iter_array(iter, &len, &data); + arr = bson_new_from_data(data, len); + + if (FindInDoc(g, &itar, arr, colname, fmt, k + 1, !all)) return true; - newcol = false; - } // endif lvl + newcol = false; + } // endif lvl - } else if (BSON_ITER_HOLDS_ARRAY(iter)) { - if (lvl < 0) - continue; - else if (lvl <= k) { - bcol.Type = TYPE_STRING; - bcol.Len = 512; - } else { - bson_t *arr; - bson_iter_t itar; - const uint8_t *data = NULL; - uint32_t len = 0; - - bson_iter_array(iter, &len, &data); - arr = bson_new_from_data(data, len); - - if (FindInDoc(g, &itar, arr, colname, fmt, k + 1, !all)) - return true; - - newcol = false; - } // endif lvl - - } // endif's + break; + } // endswitch iter if (newcol) AddColumn(g, colname, fmt, k); @@ -178,6 +189,7 @@ TDBCMG::TDBCMG(MGODEF *tdp) : TDBEXT(tdp) Pcg.Coll_name = tdp->Tabname; Pcg.Options = tdp->Colist; Pcg.Filter = tdp->Filter; + Pcg.Line = NULL; Pcg.Pipe = tdp->Pipe && tdp->Colist != NULL; B = tdp->Base ? 1 : 0; } else { @@ -186,6 +198,7 @@ TDBCMG::TDBCMG(MGODEF *tdp) : TDBEXT(tdp) Pcg.Coll_name = NULL; Pcg.Options = NULL; Pcg.Filter = NULL; + Pcg.Line = NULL; Pcg.Pipe = false; B = 0; } // endif tdp @@ -381,7 +394,21 @@ MGOCOL::MGOCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) : EXTCOL(cdp, tdbp, cprec, i, "MGO") { Tmgp = (PTDBCMG)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); - Jpath = cdp->GetFmt() ? cdp->GetFmt() : cdp->GetName(); + Sgfy = false; + + if ((Jpath = cdp->GetFmt())) { + int n = strlen(Jpath) - 1; + + if (Jpath[n] == '*') { + Jpath = PlugDup(g, cdp->GetFmt()); + if (Jpath[n - 1] == '.') n--; + Jpath[n] = 0; + Sgfy = true; + } // endif Jpath + + } else + Jpath = cdp->GetName(); + } // end of MGOCOL constructor /***********************************************************************/ @@ -392,6 +419,7 @@ MGOCOL::MGOCOL(MGOCOL *col1, PTDB tdbp) : EXTCOL(col1, tdbp) { Tmgp = col1->Tmgp; Jpath = col1->Jpath; + Sgfy = col1->Sgfy; } // end of MGOCOL copy constructor /***********************************************************************/ @@ -419,6 +447,9 @@ PSZ MGOCOL::GetJpath(PGLOBAL g, bool proj) } else *p2++ = *p1; + if (*(p2 - 1) == '.') + p2--; + *p2 = 0; return projpath; } else diff --git a/storage/connect/tabcmg.h b/storage/connect/tabcmg.h index 260f2def8a2..44448590da1 100644 --- a/storage/connect/tabcmg.h +++ b/storage/connect/tabcmg.h @@ -1,7 +1,7 @@ /**************** tabcmg H Declares Source Code File (.H) **************/ -/* Name: tabcmg.h Version 1.2 */ +/* Name: tabcmg.h Version 1.3 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2017 */ +/* (C) Copyright to the author Olivier BERTRAND 2017 - 2021 */ /* */ /* This file contains the MongoDB classes declares. */ /***********************************************************************/ @@ -96,6 +96,7 @@ public: // Implementation virtual int GetAmType(void) { return Tmgp->GetAmType(); } + virtual bool Stringify(void) { return Sgfy; } // Methods virtual PSZ GetJpath(PGLOBAL g, bool proj); @@ -109,6 +110,7 @@ protected: // Members TDBCMG *Tmgp; // To the MGO table block char *Jpath; // The json path + bool Sgfy; // True if stringified }; // end of class MGOCOL /***********************************************************************/ diff --git a/storage/connect/tabjmg.cpp b/storage/connect/tabjmg.cpp index 850d9e5fa9b..300091f78ad 100644 --- a/storage/connect/tabjmg.cpp +++ b/storage/connect/tabjmg.cpp @@ -384,7 +384,7 @@ int TDBJMG::WriteDB(PGLOBAL g) int rc = RC_OK; if (Mode == MODE_INSERT) { - rc = Jcp->DocWrite(g); + rc = Jcp->DocWrite(g, NULL); } else if (Mode == MODE_DELETE) { rc = Jcp->DocDelete(g, false); } else if (Mode == MODE_UPDATE) { @@ -420,8 +420,21 @@ JMGCOL::JMGCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) : EXTCOL(cdp, tdbp, cprec, i, "MGO") { Tmgp = (PTDBJMG)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); - Jpath = cdp->GetFmt() ? cdp->GetFmt() : cdp->GetName(); -//Mbuf = NULL; + Sgfy = false; + + if ((Jpath = cdp->GetFmt())) { + int n = strlen(Jpath) - 1; + + if (Jpath[n] == '*') { + Jpath = PlugDup(g, cdp->GetFmt()); + if (Jpath[n - 1] == '.') n--; + Jpath[n] = 0; + Sgfy = true; + } // endif Jpath + + } else + Jpath = cdp->GetName(); + } // end of JMGCOL constructor /***********************************************************************/ @@ -432,7 +445,7 @@ JMGCOL::JMGCOL(JMGCOL *col1, PTDB tdbp) : EXTCOL(col1, tdbp) { Tmgp = col1->Tmgp; Jpath = col1->Jpath; -//Mbuf = col1->Mbuf; + Sgfy = col1->Sgfy; } // end of JMGCOL copy constructor /***********************************************************************/ @@ -442,7 +455,7 @@ PSZ JMGCOL::GetJpath(PGLOBAL g, bool proj) { if (Jpath) { if (proj) { - char *p1, *p2, *projpath = PlugDup(g, Jpath); + char* p1, * p2, * projpath = PlugDup(g, Jpath); int i = 0; for (p1 = p2 = projpath; *p1; p1++) @@ -460,6 +473,9 @@ PSZ JMGCOL::GetJpath(PGLOBAL g, bool proj) } else *p2++ = *p1; + if (*(p2 - 1) == '.') + p2--; + *p2 = 0; return projpath; } else diff --git a/storage/connect/tabjmg.h b/storage/connect/tabjmg.h index 5a637145cff..e8f08730b89 100644 --- a/storage/connect/tabjmg.h +++ b/storage/connect/tabjmg.h @@ -1,7 +1,7 @@ /**************** tabjmg H Declares Source Code File (.H) **************/ -/* Name: tabjmg.h Version 1.1 */ +/* Name: tabjmg.h Version 1.2 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2017 */ +/* (C) Copyright to the author Olivier BERTRAND 2017 - 2021 */ /* */ /* This file contains the MongoDB classes using the Java Driver. */ /***********************************************************************/ @@ -106,6 +106,7 @@ public: // Implementation virtual int GetAmType(void) {return Tmgp->GetAmType();} + virtual bool Stringify(void) { return Sgfy; } // Methods //virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check); @@ -123,7 +124,7 @@ protected: // Members TDBJMG *Tmgp; // To the MGO table block char *Jpath; // The json path -//char *Mbuf; // The Mini buffer + bool Sgfy; // True if stringified }; // end of class JMGCOL /***********************************************************************/ diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index dee4b737a89..dfcf3ee2d4f 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -178,7 +178,7 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) lvl = GetIntegerTableOption(g, topt, "Depth", lvl); sep = GetStringTableOption(g, topt, "Separator", "."); strfy = GetStringTableOption(g, topt, "Stringify", NULL); - sz = GetIntegerTableOption(g, topt, "Jsize", 250); + sz = GetIntegerTableOption(g, topt, "Jsize", 1024); limit = GetIntegerTableOption(g, topt, "Limit", 10); /*********************************************************************/ @@ -647,7 +647,7 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Collname = GetStringCatInfo(g, "Name", (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); Collname = GetStringCatInfo(g, "Tabname", Collname); - Options = GetStringCatInfo(g, "Colist", NULL); + Options = GetStringCatInfo(g, "Colist", Xcol ? "all" : NULL); Filter = GetStringCatInfo(g, "Filter", NULL); Pipe = GetBoolCatInfo("Pipeline", false); Driver = GetStringCatInfo(g, "Driver", NULL); @@ -716,6 +716,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) #endif // !MONGO_SUPPORT } // endif Driver + Pretty = 4; // Not a file } else if (Zipped) { #if defined(ZIP_SUPPORT) if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) { @@ -761,7 +762,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) G->jump_level = 0; ((TDBJSN*)tdbp)->G = G; #endif // 0 - ((TDBJSN*)tdbp)->G = PlugInit(NULL, (size_t)Lrecl * (Pretty >= 0 ? 10 : 2)); + ((TDBJSN*)tdbp)->G = PlugInit(NULL, (size_t)Lrecl * (Pretty >= 0 ? 12 : 4)); } else { strcpy(g->Message, "LRECL is not defined"); return NULL; @@ -1277,6 +1278,7 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) Xpd = false; Parsed = false; Warned = false; + Sgfy = false; } // end of JSONCOL constructor /***********************************************************************/ @@ -1296,6 +1298,7 @@ JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp) Xpd = col1->Xpd; Parsed = col1->Parsed; Warned = col1->Warned; + Sgfy = col1->Sgfy; } // end of JSONCOL copy constructor /***********************************************************************/ @@ -1568,8 +1571,10 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj) if (*p1 == '$') p1++; if (*p1 == '.') p1++; mgopath = PlugDup(g, p1); - } else + } else { + Sgfy = true; return NULL; + } // endif for (p1 = p2 = mgopath; *p1; p1++) if (i) { // Inside [] @@ -1607,6 +1612,7 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj) case '*': if (*(p2 - 1) == '.' && !*(p1 + 1)) { p2--; // Suppress last :* + Sgfy = true; break; } // endif p2 @@ -1615,6 +1621,9 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj) break; } // endswitch p1; + if (*(p2 - 1) == '.') + p2--; + *p2 = 0; return mgopath; } else @@ -2127,10 +2136,14 @@ void JSONCOL::WriteColumn(PGLOBAL g) if (Nodes[Nod-1].Op == OP_XX) { s = Value->GetCharValue(); - if (!(jsp = ParseJson(G, s, strlen(s)))) { - strcpy(g->Message, s); - throw 666; - } // endif jsp + if (s && *s) { + if (!(jsp = ParseJson(G, s, strlen(s)))) { + strcpy(g->Message, s); + throw 666; + } // endif jsp + + } else + jsp = NULL; if (arp) { if (Nod > 1 && Nodes[Nod-2].Op == OP_EQ) @@ -2560,8 +2573,8 @@ int TDBJSON::WriteDB(PGLOBAL g) if (Mode == MODE_INSERT) { Doc->AddArrayValue(g, vp); Row = new(g) JOBJECT; - } else if (Doc->SetArrayValue(g, vp, Fpos)) - return RC_FX; + } else + Doc->SetArrayValue(g, vp, Fpos); } else if (Jmode == MODE_ARRAY) { PJVAL vp = new(g) JVALUE(Row); @@ -2569,15 +2582,15 @@ int TDBJSON::WriteDB(PGLOBAL g) if (Mode == MODE_INSERT) { Doc->AddArrayValue(g, vp); Row = new(g) JARRAY; - } else if (Doc->SetArrayValue(g, vp, Fpos)) - return RC_FX; + } else + Doc->SetArrayValue(g, vp, Fpos); } else { // if (Jmode == MODE_VALUE) if (Mode == MODE_INSERT) { Doc->AddArrayValue(g, (PJVAL)Row); Row = new(g) JVALUE; - } else if (Doc->SetArrayValue(g, (PJVAL)Row, Fpos)) - return RC_FX; + } else + Doc->SetArrayValue(g, (PJVAL)Row, Fpos); } // endif Jmode diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h index 1062928d410..523015c66b2 100644 --- a/storage/connect/tabjson.h +++ b/storage/connect/tabjson.h @@ -216,7 +216,8 @@ public: JSONCOL(JSONCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation - virtual int GetAmType(void) {return Tjp->GetAmType();} + virtual int GetAmType(void) {return Tjp->GetAmType();} + virtual bool Stringify(void) { return Sgfy; } // Methods virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check); @@ -251,6 +252,7 @@ public: bool Xpd; // True for expandable column bool Parsed; // True when parsed bool Warned; // True when warning issued + bool Sgfy; // True if stringified }; // end of class JSONCOL /* -------------------------- TDBJSON class -------------------------- */ From 2294f9de8d939688b2ca34858ce72eecb19fb472 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sun, 2 May 2021 11:03:21 +0200 Subject: [PATCH 02/18] Fix compile warning as error --- storage/connect/cmgoconn.cpp | 10 +++++----- storage/connect/ha_connect.cc | 6 +++--- storage/connect/json.h | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/storage/connect/cmgoconn.cpp b/storage/connect/cmgoconn.cpp index 7aa35253514..cd2a8b63cdb 100644 --- a/storage/connect/cmgoconn.cpp +++ b/storage/connect/cmgoconn.cpp @@ -250,16 +250,16 @@ int CMgoConn::CollSize(PGLOBAL g) } else query = bson_new(); -#if defined(NDEBUG) - cnt = (int)mongoc_collection_count(Collection, - MONGOC_QUERY_NONE, query, 0, 0, NULL, &Error); -#else +#if defined(DEVELOPMENT) if (jf) cnt = (int)mongoc_collection_count_documents(Collection, query, NULL, NULL, NULL, &Error); else cnt = (int)mongoc_collection_estimated_document_count( - Collection, NULL, NULL, NULL, &Error); + Collection, NULL, NULL, NULL, &Error); +#else + cnt = (int)mongoc_collection_count(Collection, + MONGOC_QUERY_NONE, query, 0, 0, NULL, &Error); #endif if (cnt < 0) { diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index f85035d6e06..041c29dc111 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -170,9 +170,9 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.07.0002 March 22, 2021"; + char version[]= "Version 1.07.0003 March 22, 2021"; #if defined(__WIN__) - char compver[]= "Version 1.07.0002 " __DATE__ " " __TIME__; + char compver[]= "Version 1.07.0003 " __DATE__ " " __TIME__; char slash= '\\'; #else // !__WIN__ char slash= '/'; @@ -7511,7 +7511,7 @@ maria_declare_plugin(connect) 0x0107, /* version number (1.07) */ NULL, /* status variables */ connect_system_variables, /* system variables */ - "1.07.0002", /* string version */ + "1.07.0003", /* string version */ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ } maria_declare_plugin_end; diff --git a/storage/connect/json.h b/storage/connect/json.h index ef5f6c7b7de..26b73faef12 100644 --- a/storage/connect/json.h +++ b/storage/connect/json.h @@ -66,6 +66,7 @@ const char* GetFmt(int type, bool un); PJSON ParseJson(PGLOBAL g, char* s, size_t n, int* prty = NULL, bool* b = NULL); PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty); DllExport bool IsNum(PSZ s); +bool IsArray(PSZ s); /***********************************************************************/ /* Class JDOC. The class for parsing and serializing json documents. */ From 3b5dabeb96167c35df66475c5cb9be083065e941 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sun, 2 May 2021 11:59:54 +0200 Subject: [PATCH 03/18] Typo --- storage/connect/ha_connect.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 041c29dc111..583e4f94e91 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.0003 March 22, 2021"; + char version[]= "Version 1.07.0003 April 02, 2021"; #if defined(__WIN__) char compver[]= "Version 1.07.0003 " __DATE__ " " __TIME__; char slash= '\\'; From 5ae67c6d6387fa6e5c207fd9aea6741fb78073a5 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 5 May 2021 00:31:21 +0200 Subject: [PATCH 04/18] - All this concern Json or Mongo tables based on MongoDB collections. - Limit decimals of doubles printed from MongoDB Done in function Mini for Mongo C Driver and Java Driver Done in function SerializeValue for Java tables using the J Driver modified: storage/connect/cmgoconn.cpp modified: storage/connect/json.cpp modified: storage/connect/json.h modified: storage/connect/tabjmg.cpp - Fix crash when using BSON_TYPE_DECIMAL128 modified: storage/connect/cmgoconn.cpp - Collection name default to table name Fix it when creating tables via discovery modified: storage/connect/ha_connect.cc modified: storage/connect/tabbson.cpp modified: storage/connect/tabjson.cpp --- storage/connect/cmgoconn.cpp | 58 +++++++++++++++++++++++++---------- storage/connect/ha_connect.cc | 7 +++-- storage/connect/json.cpp | 5 +-- storage/connect/json.h | 4 +-- storage/connect/tabbson.cpp | 3 +- storage/connect/tabjmg.cpp | 1 + storage/connect/tabjson.cpp | 3 +- 7 files changed, 53 insertions(+), 28 deletions(-) diff --git a/storage/connect/cmgoconn.cpp b/storage/connect/cmgoconn.cpp index cd2a8b63cdb..91952ab0706 100644 --- a/storage/connect/cmgoconn.cpp +++ b/storage/connect/cmgoconn.cpp @@ -26,6 +26,7 @@ bool CMgoConn::IsInit = false; bool IsArray(PSZ s); bool MakeSelector(PGLOBAL g, PFIL fp, PSTRG s); +int GetDefaultPrec(void); /* --------------------------- Class INCOL --------------------------- */ @@ -563,7 +564,7 @@ void CMgoConn::ShowDocument(bson_iter_t *iter, const bson_t *doc, const char *k) htrc("%s.%s=%s\n", k, key, str); } break; case BSON_TYPE_DECIMAL128: { - char* str = NULL; + char str[BSON_DECIMAL128_STRING]; bson_decimal128_t dec; bson_iter_decimal128(iter, &dec); @@ -805,23 +806,51 @@ void CMgoConn::Close(void) /***********************************************************************/ char *CMgoConn::Mini(PGLOBAL g, PCOL colp, const bson_t *bson, bool b) { - char *s, *str = NULL; - char *Mbuf = (char*)PlugSubAlloc(g, NULL, (size_t)colp->GetLength() + 1); - int i, k = 0; - bool ok = true; + char *s, *str = NULL; + char *Mbuf = (char*)PlugSubAlloc(g, NULL, (size_t)colp->GetLength() + 1); + int i, j = 0, k = 0, n = 0, m = GetDefaultPrec(); + bool ok = true, dbl = false; + double d; + size_t len; if (b) - s = str = bson_array_as_json(bson, NULL); + s = str = bson_array_as_json(bson, &len); else - s = str = bson_as_json(bson, NULL); + s = str = bson_as_json(bson, &len); + + if (len > (size_t)colp->GetLength()) { + sprintf(g->Message, "Value too long for column %s", colp->GetName()); + bson_free(str); + throw (int)TYPE_AM_MGO; + } // endif len for (i = 0; i < colp->GetLength() && s[i]; i++) { switch (s[i]) { case ' ': if (ok) continue; + break; case '"': ok = !ok; + break; + case '.': + if (j) dbl = true; + break; default: + if (ok) { + if (isdigit(s[i])) { + if (!j) j = k; + if (dbl) n++; + } else if (dbl && n > m) { + Mbuf[k] = 0; + d = atof(Mbuf + j); + n = sprintf(Mbuf + j, "%.*f", m, d); + k = j + n; + j = n = 0; + } else if (j) + j = n = 0; + + } // endif ok + break; } // endswitch s[i] @@ -830,11 +859,6 @@ char *CMgoConn::Mini(PGLOBAL g, PCOL colp, const bson_t *bson, bool b) bson_free(str); - if (i >= colp->GetLength()) { - sprintf(g->Message, "Value too long for column %s", colp->GetName()); - throw (int)TYPE_AM_MGO; - } // endif i - Mbuf[k] = 0; return Mbuf; } // end of Mini @@ -926,13 +950,13 @@ void CMgoConn::GetColumnValue(PGLOBAL g, PCOL colp) value->SetNull(true); break; case BSON_TYPE_DECIMAL128: { - char* str = NULL; + char str[BSON_DECIMAL128_STRING]; bson_decimal128_t dec; bson_iter_decimal128(&Desc, &dec); bson_decimal128_to_string(&dec, str); value->SetValue_psz(str); - bson_free(str); +// bson_free(str); } break; default: value->Reset(); @@ -956,10 +980,10 @@ bool CMgoConn::AddValue(PGLOBAL g, PCOL colp, bson_t *doc, char *key, bool upd) PVAL value = colp->GetValue(); if (value->IsNull()) { - if (upd) +// if (upd) rc = BSON_APPEND_NULL(doc, key); - else - return false; +// else +// return false; } else switch (colp->GetResultType()) { case TYPE_STRING: diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 583e4f94e91..5f210f649f5 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.0003 April 02, 2021"; + char version[]= "Version 1.07.0003 May 02, 2021"; #if defined(__WIN__) char compver[]= "Version 1.07.0003 " __DATE__ " " __TIME__; char slash= '\\'; @@ -5940,9 +5940,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, if (!fn && !zfn && !mul && !dsn) sprintf(g->Message, "Missing %s file name", topt->type); - else - ok= true; + else if (dsn && !topt->tabname) + topt->tabname= tab; + ok= true; break; #if defined(JAVA_SUPPORT) case TAB_MONGO: diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index b1f9f10957b..b376a8c5c27 100644 --- a/storage/connect/json.cpp +++ b/storage/connect/json.cpp @@ -245,6 +245,7 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, char* fn, int pretty) { try { jdp = new(g) JDOC; // MUST BE ALLOCATED BEFORE jp !!!!! + jdp->dfp = GetDefaultPrec(); if (!jsp) { strcpy(g->Message, "Null json tree"); @@ -1005,8 +1006,8 @@ bool JDOC::SerializeValue(PJVAL jvp) case TYPE_BINT: sprintf(buf, "%lld", jvp->LLn); return js->WriteStr(buf); - case TYPE_DBL: - sprintf(buf, "%.*lf", jvp->Nd, jvp->F); + case TYPE_DBL: // dfp to limit to the default number of decimals + sprintf(buf, "%.*f", MY_MIN(jvp->Nd, dfp), jvp->F); return js->WriteStr(buf); case TYPE_NULL: return js->WriteStr("null"); diff --git a/storage/connect/json.h b/storage/connect/json.h index 26b73faef12..566cb64cc23 100644 --- a/storage/connect/json.h +++ b/storage/connect/json.h @@ -75,7 +75,7 @@ class JDOC: public BLOCK { friend PJSON ParseJson(PGLOBAL, char*, size_t, int*, bool*); friend PSZ Serialize(PGLOBAL, PJSON, char*, int); public: - JDOC(void) : js(NULL), s(NULL), len(0), pty(NULL) {} + JDOC(void) : js(NULL), s(NULL), len(0), dfp(0), pty(NULL) {} void SetJp(JOUT* jp) { js = jp; } @@ -94,7 +94,7 @@ public: private: JOUT* js; char *s; - int len; + int len, dfp; bool *pty; }; // end of class JDOC diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index aae9a11b28c..d36b9718cd6 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -218,8 +218,7 @@ int BSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) if (tdp->Uri) { #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) - tdp->Collname = GetStringTableOption(g, topt, "Name", NULL); - tdp->Collname = GetStringTableOption(g, topt, "Tabname", tdp->Collname); + tdp->Collname = GetStringTableOption(g, topt, "Tabname", NULL); tdp->Schema = GetStringTableOption(g, topt, "Dbname", "test"); tdp->Options = (PSZ)GetStringTableOption(g, topt, "Colist", "all"); tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false); diff --git a/storage/connect/tabjmg.cpp b/storage/connect/tabjmg.cpp index 300091f78ad..b02bf6a7f36 100644 --- a/storage/connect/tabjmg.cpp +++ b/storage/connect/tabjmg.cpp @@ -505,6 +505,7 @@ char *JMGCOL::Mini(PGLOBAL g, const bson_t *bson, bool b) switch (s[i]) { case ' ': if (ok) continue; + break; case '"': ok = !ok; default: diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index dfcf3ee2d4f..4a8031113d2 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -222,8 +222,7 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) if (tdp->Uri) { #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) - tdp->Collname = GetStringTableOption(g, topt, "Name", NULL); - tdp->Collname = GetStringTableOption(g, topt, "Tabname", tdp->Collname); + tdp->Collname = GetStringTableOption(g, topt, "Tabname", NULL); tdp->Schema = GetStringTableOption(g, topt, "Dbname", "test"); tdp->Options = (PSZ)GetStringTableOption(g, topt, "Colist", "all"); tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false); From 17533c1ffc018b410d5fe01a54c225d4fc7f75cd Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 17 May 2021 19:17:31 +0200 Subject: [PATCH 05/18] - Put all jar files in the SHARE directory (was PLUGIN) modified: sql/mysqld.h modified: storage/connect/CMakeLists.txt modified: storage/connect/javaconn.cpp modified: storage/connect/mycat.cc modified: storage/connect/mycat.h - Get a handled on a not pooled client This to avoid a .50 delay when closing modified: storage/connect/cmgoconn.cpp modified: storage/connect/cmgoconn.h - Allow FIELD_FORMAT options for DECIMAL type modified: storage/connect/tabdos.cpp - Update tests and result to reflect last changes Also because Oracle password has changed modified: storage/connect/mysql-test/connect/r/jdbc_oracle.result modified: storage/connect/mysql-test/connect/r/json_java_2.result modified: storage/connect/mysql-test/connect/r/json_java_3.result modified: storage/connect/mysql-test/connect/r/json_mongo_c.result modified: storage/connect/mysql-test/connect/r/mongo_c.result modified: storage/connect/mysql-test/connect/r/odbc_oracle.result modified: storage/connect/mysql-test/connect/t/jdbc_oracle.test modified: storage/connect/mysql-test/connect/t/odbc_oracle.test - Typo modified: storage/connect/reldef.cpp --- sql/mysqld.h | 2 +- storage/connect/CMakeLists.txt | 4 +- storage/connect/cmgoconn.cpp | 22 ++++++-- storage/connect/cmgoconn.h | 2 +- storage/connect/javaconn.cpp | 16 ++---- storage/connect/mycat.cc | 9 ++++ storage/connect/mycat.h | 3 +- .../mysql-test/connect/r/jdbc_oracle.result | 8 +-- .../mysql-test/connect/r/json_java_2.result | 2 +- .../mysql-test/connect/r/json_java_3.result | 2 +- .../mysql-test/connect/r/json_mongo_c.result | 6 +-- .../mysql-test/connect/r/mongo_c.result | 36 ++++++------- .../mysql-test/connect/r/odbc_oracle.result | 38 +++++++------- .../mysql-test/connect/t/jdbc_oracle.test | 8 +-- .../mysql-test/connect/t/odbc_oracle.test | 30 +++++------ storage/connect/reldef.cpp | 3 +- storage/connect/tabdos.cpp | 51 ++++++++++++------- 17 files changed, 136 insertions(+), 106 deletions(-) diff --git a/sql/mysqld.h b/sql/mysqld.h index 64e5aef5946..44b0491f138 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -536,7 +536,7 @@ extern ulonglong my_pcre_frame_size; */ extern my_bool opt_large_pages; extern uint opt_large_page_size; -extern char lc_messages_dir[FN_REFLEN]; +extern MYSQL_PLUGIN_IMPORT char lc_messages_dir[FN_REFLEN]; extern char *lc_messages_dir_ptr, *log_error_file_ptr; extern MYSQL_PLUGIN_IMPORT char reg_ext[FN_EXTLEN]; extern MYSQL_PLUGIN_IMPORT uint reg_ext_length; diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 96b8d877ee0..d75c57a9b1b 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -410,12 +410,12 @@ IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/JavaWrappers.jar ${CMAKE_CURRENT_BINARY_DIR}/JdbcInterface.jar - DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine) + DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT connect-engine) IF(CONNECT_WITH_MONGO) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/Mongo2.jar ${CMAKE_CURRENT_SOURCE_DIR}/Mongo3.jar - DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine) + DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT connect-engine) ENDIF() ENDIF() diff --git a/storage/connect/cmgoconn.cpp b/storage/connect/cmgoconn.cpp index 91952ab0706..5a81799c4a2 100644 --- a/storage/connect/cmgoconn.cpp +++ b/storage/connect/cmgoconn.cpp @@ -123,11 +123,12 @@ CMgoConn::CMgoConn(PGLOBAL g, PCPARM pcg) { Pcg = pcg; Uri = NULL; - Pool = NULL; +//Pool = NULL; Client = NULL; Database = NULL; Collection = NULL; Cursor = NULL; + Document = NULL; Query = NULL; Opts = NULL; Fpc = NULL; @@ -179,6 +180,7 @@ bool CMgoConn::Connect(PGLOBAL g) return true; } // endif Uri +#if 0 // Create a new client pool instance Pool = mongoc_client_pool_new(Uri); mongoc_client_pool_set_error_api(Pool, 2); @@ -189,13 +191,24 @@ bool CMgoConn::Connect(PGLOBAL g) // Create a new client instance Client = mongoc_client_pool_pop(Pool); +#else + // Create a new client instance + Client = mongoc_client_new_from_uri (Uri); if (!Client) { sprintf(g->Message, "Failed to get Client"); return true; } // endif Client - // Get a handle on the collection Coll_name + // Register the application name so we can track it in the profile logs + // on the server. This can also be done from the URI (see other examples). + mongoc_client_set_appname (Client, "Connect"); + + // Get a handle on the database + // Database = mongoc_client_get_database (Client, Pcg->Db_name); +#endif // 0 + + // Get a handle on the collection Collection = mongoc_client_get_collection(Client, Pcg->Db_name, Pcg->Coll_name); if (!Collection) { @@ -794,8 +807,9 @@ void CMgoConn::Close(void) if (Opts) bson_destroy(Opts); if (Cursor) mongoc_cursor_destroy(Cursor); if (Collection) mongoc_collection_destroy(Collection); - if (Client) mongoc_client_pool_push(Pool, Client); - if (Pool) mongoc_client_pool_destroy(Pool); +//if (Client) mongoc_client_pool_push(Pool, Client); +//if (Pool) mongoc_client_pool_destroy(Pool); + if (Client) mongoc_client_destroy(Client); if (Uri) mongoc_uri_destroy(Uri); if (Fpc) Fpc->Destroy(); if (fp) fp->Count = 0; diff --git a/storage/connect/cmgoconn.h b/storage/connect/cmgoconn.h index 5c9fb4f763d..c69f53b366f 100644 --- a/storage/connect/cmgoconn.h +++ b/storage/connect/cmgoconn.h @@ -104,7 +104,7 @@ protected: // Members PCPARM Pcg; mongoc_uri_t *Uri; - mongoc_client_pool_t *Pool; // Thread safe client pool +//mongoc_client_pool_t *Pool; // Thread safe client pool mongoc_client_t *Client; // The MongoDB client mongoc_database_t *Database; // The MongoDB database mongoc_collection_t *Collection; // The MongoDB collection diff --git a/storage/connect/javaconn.cpp b/storage/connect/javaconn.cpp index 3737c82a02e..34b844f59b0 100644 --- a/storage/connect/javaconn.cpp +++ b/storage/connect/javaconn.cpp @@ -58,6 +58,7 @@ extern char *JvmPath; // The connect_jvm_path global variable value extern char *ClassPath; // The connect_class_path global variable value char *GetPluginDir(void); +char *GetMessageDir(void); char *GetJavaWrapper(void); // The connect_java_wrapper variable value /***********************************************************************/ @@ -400,24 +401,17 @@ bool JAVAConn::Open(PGLOBAL g) jpop->Append(ClassPath); } // endif ClassPath -#if 0 - // Java source will be compiled as a jar file installed in the plugin dir + // All wrappers are pre-compiled in JavaWrappers.jar in the share dir jpop->Append(sep); - jpop->Append(GetPluginDir()); - jpop->Append("JdbcInterface.jar"); -#endif // 0 - - // All wrappers are pre-compiled in JavaWrappers.jar in the plugin dir - jpop->Append(sep); - jpop->Append(GetPluginDir()); + jpop->Append(GetMessageDir()); jpop->Append("JavaWrappers.jar"); #if defined(MONGO_SUPPORT) jpop->Append(sep); - jpop->Append(GetPluginDir()); + jpop->Append(GetMessageDir()); jpop->Append("Mongo3.jar"); jpop->Append(sep); - jpop->Append(GetPluginDir()); + jpop->Append(GetMessageDir()); jpop->Append("Mongo2.jar"); #endif // MONGO_SUPPORT diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index e3fa00e119f..4a7e65eb01f 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -123,6 +123,15 @@ char *GetPluginDir(void) return opt_plugin_dir; } // end of GetPluginDir +/***********************************************************************/ +/* Get the lc_messages_dir, it is where error messages for various */ +/* languages are installed, and by default the INSTALL_MYSQLSHAREDIR. */ +/***********************************************************************/ +char *GetMessageDir(void) +{ + return lc_messages_dir; +} // end of GetMessageDir + /***********************************************************************/ /* Get a unique enum table type ID. */ /***********************************************************************/ diff --git a/storage/connect/mycat.h b/storage/connect/mycat.h index 6473f7a5c11..147148f4a57 100644 --- a/storage/connect/mycat.h +++ b/storage/connect/mycat.h @@ -78,7 +78,8 @@ struct ha_table_option_struct { typedef class ha_connect *PHC; -char *GetPluginDir(void); +char *GetPluginDir(void); +char *GetMessageDir(void); TABTYPE GetTypeID(const char *type); bool IsFileType(TABTYPE type); bool IsExactType(TABTYPE type); diff --git a/storage/connect/mysql-test/connect/r/jdbc_oracle.result b/storage/connect/mysql-test/connect/r/jdbc_oracle.result index d895a9aed87..21a2d10fef7 100644 --- a/storage/connect/mysql-test/connect/r/jdbc_oracle.result +++ b/storage/connect/mysql-test/connect/r/jdbc_oracle.result @@ -3,7 +3,7 @@ command varchar(128) not null, number int(5) not null flag=1, message varchar(255) flag=2) ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='jdbc:oracle:thin:@localhost:1521:xe' -OPTION_LIST='User=system,Password=Choupy01,Execsrc=1'; +OPTION_LIST='User=system,Password=Biscote01,Execsrc=1'; SELECT * FROM t2 WHERE command = 'drop table employee'; command number message drop table employee 0 Execute: java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist @@ -23,14 +23,14 @@ Warnings: Warning 1105 Affected rows CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=tables CONNECTION='jdbc:oracle:thin:@localhost:1521:xe' -OPTION_LIST='User=system,Password=Choupy01'; +OPTION_LIST='User=system,Password=Biscote01'; SELECT * FROM t1 WHERE table_name='employee'; Table_Cat Table_Schema Table_Name Table_Type Remark NULL SYSTEM EMPLOYEE TABLE NULL DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='EMPLOYEE' CATFUNC=columns CONNECTION='jdbc:oracle:thin:@localhost:1521:xe' -OPTION_LIST='User=system,Password=Choupy01'; +OPTION_LIST='User=system,Password=Biscote01'; SELECT * FROM t1; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks NULL SYSTEM EMPLOYEE ID 3 NUMBER 38 0 0 10 0 NULL @@ -42,7 +42,7 @@ CREATE SERVER 'oracle' FOREIGN DATA WRAPPER 'oracle.jdbc.driver.OracleDriver' OP HOST 'jdbc:oracle:thin:@localhost:1521:xe', DATABASE 'SYSTEM', USER 'system', -PASSWORD 'Choupy01', +PASSWORD 'Biscote01', PORT 0, SOCKET '', OWNER 'SYSTEM'); diff --git a/storage/connect/mysql-test/connect/r/json_java_2.result b/storage/connect/mysql-test/connect/r/json_java_2.result index e0b08889f40..c05501013a5 100644 --- a/storage/connect/mysql-test/connect/r/json_java_2.result +++ b/storage/connect/mysql-test/connect/r/json_java_2.result @@ -10,7 +10,7 @@ SELECT * from t1 limit 3; Document {"_id":{"$oid":"58ada47de5a51ddfcd5ed51c"},"address":{"building":"1007","coord":[-73.856077,40.848447],"street":"Morris Park Ave","zipcode":"10462"},"borough":"Bronx","cuisine":"Bakery","grades":[{"date":{"$date":"2014-03-03T00:00:00.000Z"},"grade":"A","score":2},{"date":{"$date":"2013-09-11T00:00:00.000Z"},"grade":"A","score":6},{"date":{"$date":"2013-01-24T00:00:00.000Z"},"grade":"A","score":10},{"date":{"$date":"2011-11-23T00:00:00.000Z"},"grade":"A","score":9},{"date":{"$date":"2011-03-10T00:00:00.000Z"},"grade":"B","score":14}],"name":"Morris Park Bake Shop","restaurant_id":"30075445"} {"_id":{"$oid":"58ada47de5a51ddfcd5ed51d"},"address":{"building":"469","coord":[-73.961704,40.662942],"street":"Flatbush Avenue","zipcode":"11225"},"borough":"Brooklyn","cuisine":"Hamburgers","grades":[{"date":{"$date":"2014-12-30T00:00:00.000Z"},"grade":"A","score":8},{"date":{"$date":"2014-07-01T00:00:00.000Z"},"grade":"B","score":23},{"date":{"$date":"2013-04-30T00:00:00.000Z"},"grade":"A","score":12},{"date":{"$date":"2012-05-08T00:00:00.000Z"},"grade":"A","score":12}],"name":"Wendy'S","restaurant_id":"30112340"} -{"_id":{"$oid":"58ada47de5a51ddfcd5ed51e"},"address":{"building":"351","coord":[-73.98513559999999,40.7676919],"street":"West 57 Street","zipcode":"10019"},"borough":"Manhattan","cuisine":"Irish","grades":[{"date":{"$date":"2014-09-06T00:00:00.000Z"},"grade":"A","score":2},{"date":{"$date":"2013-07-22T00:00:00.000Z"},"grade":"A","score":11},{"date":{"$date":"2012-07-31T00:00:00.000Z"},"grade":"A","score":12},{"date":{"$date":"2011-12-29T00:00:00.000Z"},"grade":"A","score":12}],"name":"Dj Reynolds Pub And Restaurant","restaurant_id":"30191841"} +{"_id":{"$oid":"58ada47de5a51ddfcd5ed51e"},"address":{"building":"351","coord":[-73.985136,40.767692],"street":"West 57 Street","zipcode":"10019"},"borough":"Manhattan","cuisine":"Irish","grades":[{"date":{"$date":"2014-09-06T00:00:00.000Z"},"grade":"A","score":2},{"date":{"$date":"2013-07-22T00:00:00.000Z"},"grade":"A","score":11},{"date":{"$date":"2012-07-31T00:00:00.000Z"},"grade":"A","score":12},{"date":{"$date":"2011-12-29T00:00:00.000Z"},"grade":"A","score":12}],"name":"Dj Reynolds Pub And Restaurant","restaurant_id":"30191841"} DROP TABLE t1; # # Test catfunc diff --git a/storage/connect/mysql-test/connect/r/json_java_3.result b/storage/connect/mysql-test/connect/r/json_java_3.result index b9ba919507d..b74f92bfee2 100644 --- a/storage/connect/mysql-test/connect/r/json_java_3.result +++ b/storage/connect/mysql-test/connect/r/json_java_3.result @@ -10,7 +10,7 @@ SELECT * from t1 limit 3; Document {"_id":{"$oid":"58ada47de5a51ddfcd5ed51c"},"address":{"building":"1007","coord":[-73.856077,40.848447],"street":"Morris Park Ave","zipcode":"10462"},"borough":"Bronx","cuisine":"Bakery","grades":[{"date":{"$date":1393804800000},"grade":"A","score":2},{"date":{"$date":1378857600000},"grade":"A","score":6},{"date":{"$date":1358985600000},"grade":"A","score":10},{"date":{"$date":1322006400000},"grade":"A","score":9},{"date":{"$date":1299715200000},"grade":"B","score":14}],"name":"Morris Park Bake Shop","restaurant_id":"30075445"} {"_id":{"$oid":"58ada47de5a51ddfcd5ed51d"},"address":{"building":"469","coord":[-73.961704,40.662942],"street":"Flatbush Avenue","zipcode":"11225"},"borough":"Brooklyn","cuisine":"Hamburgers","grades":[{"date":{"$date":1419897600000},"grade":"A","score":8},{"date":{"$date":1404172800000},"grade":"B","score":23},{"date":{"$date":1367280000000},"grade":"A","score":12},{"date":{"$date":1336435200000},"grade":"A","score":12}],"name":"Wendy'S","restaurant_id":"30112340"} -{"_id":{"$oid":"58ada47de5a51ddfcd5ed51e"},"address":{"building":"351","coord":[-73.98513559999999,40.7676919],"street":"West 57 Street","zipcode":"10019"},"borough":"Manhattan","cuisine":"Irish","grades":[{"date":{"$date":1409961600000},"grade":"A","score":2},{"date":{"$date":1374451200000},"grade":"A","score":11},{"date":{"$date":1343692800000},"grade":"A","score":12},{"date":{"$date":1325116800000},"grade":"A","score":12}],"name":"Dj Reynolds Pub And Restaurant","restaurant_id":"30191841"} +{"_id":{"$oid":"58ada47de5a51ddfcd5ed51e"},"address":{"building":"351","coord":[-73.985136,40.767692],"street":"West 57 Street","zipcode":"10019"},"borough":"Manhattan","cuisine":"Irish","grades":[{"date":{"$date":1409961600000},"grade":"A","score":2},{"date":{"$date":1374451200000},"grade":"A","score":11},{"date":{"$date":1343692800000},"grade":"A","score":12},{"date":{"$date":1325116800000},"grade":"A","score":12}],"name":"Dj Reynolds Pub And Restaurant","restaurant_id":"30191841"} DROP TABLE t1; # # Test catfunc diff --git a/storage/connect/mysql-test/connect/r/json_mongo_c.result b/storage/connect/mysql-test/connect/r/json_mongo_c.result index 6d4957167fc..008e41f63d1 100644 --- a/storage/connect/mysql-test/connect/r/json_mongo_c.result +++ b/storage/connect/mysql-test/connect/r/json_mongo_c.result @@ -8,9 +8,9 @@ ENGINE=CONNECT TABLE_TYPE=JSON TABNAME=restaurants CONNECTION='mongodb://localho OPTION_LIST='Driver=C,Version=0' DATA_CHARSET=utf8; SELECT * from t1 limit 3; Document -{"_id":{"$oid":"58ada47de5a51ddfcd5ed51c"},"address":{"building":"1007","coord":[-73.856076999999999089,40.848447000000000173],"street":"Morris Park Ave","zipcode":"10462"},"borough":"Bronx","cuisine":"Bakery","grades":[{"date":{"$date":1393804800000},"grade":"A","score":2},{"date":{"$date":1378857600000},"grade":"A","score":6},{"date":{"$date":1358985600000},"grade":"A","score":10},{"date":{"$date":1322006400000},"grade":"A","score":9},{"date":{"$date":1299715200000},"grade":"B","score":14}],"name":"Morris Park Bake Shop","restaurant_id":"30075445"} -{"_id":{"$oid":"58ada47de5a51ddfcd5ed51d"},"address":{"building":"469","coord":[-73.96170399999999745,40.66294200000000103],"street":"Flatbush Avenue","zipcode":"11225"},"borough":"Brooklyn","cuisine":"Hamburgers","grades":[{"date":{"$date":1419897600000},"grade":"A","score":8},{"date":{"$date":1404172800000},"grade":"B","score":23},{"date":{"$date":1367280000000},"grade":"A","score":12},{"date":{"$date":1336435200000},"grade":"A","score":12}],"name":"Wendy'S","restaurant_id":"30112340"} -{"_id":{"$oid":"58ada47de5a51ddfcd5ed51e"},"address":{"building":"351","coord":[-73.985135599999992451,40.767691900000002647],"street":"West 57 Street","zipcode":"10019"},"borough":"Manhattan","cuisine":"Irish","grades":[{"date":{"$date":1409961600000},"grade":"A","score":2},{"date":{"$date":1374451200000},"grade":"A","score":11},{"date":{"$date":1343692800000},"grade":"A","score":12},{"date":{"$date":1325116800000},"grade":"A","score":12}],"name":"Dj Reynolds Pub And Restaurant","restaurant_id":"30191841"} +{"_id":{"$oid":"58ada47de5a51ddfcd5ed51c"},"address":{"building":"1007","coord":[-73.856077,40.848447],"street":"Morris Park Ave","zipcode":"10462"},"borough":"Bronx","cuisine":"Bakery","grades":[{"date":{"$date":1393804800000},"grade":"A","score":2},{"date":{"$date":1378857600000},"grade":"A","score":6},{"date":{"$date":1358985600000},"grade":"A","score":10},{"date":{"$date":1322006400000},"grade":"A","score":9},{"date":{"$date":1299715200000},"grade":"B","score":14}],"name":"Morris Park Bake Shop","restaurant_id":"30075445"} +{"_id":{"$oid":"58ada47de5a51ddfcd5ed51d"},"address":{"building":"469","coord":[-73.961704,40.662942],"street":"Flatbush Avenue","zipcode":"11225"},"borough":"Brooklyn","cuisine":"Hamburgers","grades":[{"date":{"$date":1419897600000},"grade":"A","score":8},{"date":{"$date":1404172800000},"grade":"B","score":23},{"date":{"$date":1367280000000},"grade":"A","score":12},{"date":{"$date":1336435200000},"grade":"A","score":12}],"name":"Wendy'S","restaurant_id":"30112340"} +{"_id":{"$oid":"58ada47de5a51ddfcd5ed51e"},"address":{"building":"351","coord":[-73.985136,40.767692],"street":"West 57 Street","zipcode":"10019"},"borough":"Manhattan","cuisine":"Irish","grades":[{"date":{"$date":1409961600000},"grade":"A","score":2},{"date":{"$date":1374451200000},"grade":"A","score":11},{"date":{"$date":1343692800000},"grade":"A","score":12},{"date":{"$date":1325116800000},"grade":"A","score":12}],"name":"Dj Reynolds Pub And Restaurant","restaurant_id":"30191841"} DROP TABLE t1; # # Test catfunc diff --git a/storage/connect/mysql-test/connect/r/mongo_c.result b/storage/connect/mysql-test/connect/r/mongo_c.result index 899a123dc5f..5b29bb54d3a 100644 --- a/storage/connect/mysql-test/connect/r/mongo_c.result +++ b/storage/connect/mysql-test/connect/r/mongo_c.result @@ -8,9 +8,9 @@ ENGINE=CONNECT TABLE_TYPE=MONGO TABNAME=restaurants OPTION_LIST='Driver=C,Version=0' DATA_CHARSET=utf8; SELECT * from t1 limit 3; Document -{"_id":{"$oid":"58ada47de5a51ddfcd5ed51c"},"address":{"building":"1007","coord":[-73.856076999999999089,40.848447000000000173],"street":"Morris ParkAve", "zipcode":"10462"},"borough":"Bronx","cuisine":"Bakery","grades":[{"date":{"$date":1393804800000},"grade":"A","score":2},{"date":{"$date":1378857600000},"grade":"A","score":6},{"date":{"$date":1358985600000},"grade":"A","score":10},{"date":{"$date":1322006400000},"grade":"A","score":9},{"date":{"$date":1299715200000},"grade":"B","score":14}],"name":"Morris ParkBakeShop", "restaurant_id":"30075445"} -{"_id":{"$oid":"58ada47de5a51ddfcd5ed51d"},"address":{"building":"469","coord":[-73.96170399999999745,40.66294200000000103],"street":"Flatbush Avenue", "zipcode":"11225"},"borough":"Brooklyn","cuisine":"Hamburgers","grades":[{"date":{"$date":1419897600000},"grade":"A","score":8},{"date":{"$date":1404172800000},"grade":"B","score":23},{"date":{"$date":1367280000000},"grade":"A","score":12},{"date":{"$date":1336435200000},"grade":"A","score":12}],"name":"Wendy'S","restaurant_id":"30112340"} -{"_id":{"$oid":"58ada47de5a51ddfcd5ed51e"},"address":{"building":"351","coord":[-73.985135599999992451,40.767691900000002647],"street":"West 57Street", "zipcode":"10019"},"borough":"Manhattan","cuisine":"Irish","grades":[{"date":{"$date":1409961600000},"grade":"A","score":2},{"date":{"$date":1374451200000},"grade":"A","score":11},{"date":{"$date":1343692800000},"grade":"A","score":12},{"date":{"$date":1325116800000},"grade":"A","score":12}],"name":"Dj ReynoldsPubAndRestaurant", "restaurant_id":"30191841"} +{"_id":{"$oid":"58ada47de5a51ddfcd5ed51c"},"address":{"building":"1007","coord":[-73.856077,40.848447],"street":"Morris Park Ave","zipcode":"10462"},"borough":"Bronx","cuisine":"Bakery","grades":[{"date":{"$date":1393804800000.000000},"grade":"A","score":2},{"date":{"$date":1378857600000.000000},"grade":"A","score":6},{"date":{"$date":1358985600000.000000},"grade":"A","score":10},{"date":{"$date":1322006400000.000000},"grade":"A","score":9},{"date":{"$date":1299715200000.000000},"grade":"B","score":14}],"name":"Morris Park Bake Shop","restaurant_id":"30075445"} +{"_id":{"$oid":"58ada47de5a51ddfcd5ed51d"},"address":{"building":"469","coord":[-73.961704,40.662942],"street":"Flatbush Avenue","zipcode":"11225"},"borough":"Brooklyn","cuisine":"Hamburgers","grades":[{"date":{"$date":1419897600000.000000},"grade":"A","score":8},{"date":{"$date":1404172800000.000000},"grade":"B","score":23},{"date":{"$date":1367280000000.000000},"grade":"A","score":12},{"date":{"$date":1336435200000.000000},"grade":"A","score":12}],"name":"Wendy'S","restaurant_id":"30112340"} +{"_id":{"$oid":"58ada47de5a51ddfcd5ed51e"},"address":{"building":"351","coord":[-73.985136,40.767692],"street":"West 57 Street","zipcode":"10019"},"borough":"Manhattan","cuisine":"Irish","grades":[{"date":{"$date":1409961600000.000000},"grade":"A","score":2},{"date":{"$date":1374451200000.000000},"grade":"A","score":11},{"date":{"$date":1343692800000.000000},"grade":"A","score":12},{"date":{"$date":1325116800000.000000},"grade":"A","score":12}],"name":"Dj Reynolds Pub And Restaurant","restaurant_id":"30191841"} DROP TABLE t1; # # Test catfunc @@ -76,11 +76,11 @@ t1 CREATE TABLE `t1` ( ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MONGO' `TABNAME`='restaurants' `OPTION_LIST`='Depth=1,Driver=C,Version=0' `DATA_CHARSET`='utf8' SELECT * FROM t1 LIMIT 5; _id address_building address_coord address_street address_zipcode borough cuisine grades_0 name restaurant_id -58ada47de5a51ddfcd5ed51c 1007 [-73.856076999999999089,40.848447000000000173] Morris Park Ave 10462 Bronx Bakery {"date":{"$date":1393804800000},"grade":"A","score":2} Morris Park Bake Shop 30075445 -58ada47de5a51ddfcd5ed51d 469 [-73.96170399999999745,40.66294200000000103] Flatbush Avenue 11225 Brooklyn Hamburgers {"date":{"$date":1419897600000},"grade":"A","score":8} Wendy'S 30112340 -58ada47de5a51ddfcd5ed51e 351 [-73.985135599999992451,40.767691900000002647] West 57 Street 10019 Manhattan Irish {"date":{"$date":1409961600000},"grade":"A","score":2} Dj Reynolds Pub And Restaurant 30191841 -58ada47de5a51ddfcd5ed51f 2780 [-73.982419999999990523,40.579504999999997494] Stillwell Avenue 11224 Brooklyn American {"date":{"$date":1402358400000},"grade":"A","score":5} Riviera Caterer 40356018 -58ada47de5a51ddfcd5ed520 97-22 [-73.860115199999995639,40.731173900000001709] 63 Road 11374 Queens Jewish/Kosher {"date":{"$date":1416787200000},"grade":"Z","score":20} Tov Kosher Kitchen 40356068 +58ada47de5a51ddfcd5ed51c 1007 [-73.856077,40.848447] Morris Park Ave 10462 Bronx Bakery {"date":{"$date":1393804800000},"grade":"A","score":2} Morris Park Bake Shop 30075445 +58ada47de5a51ddfcd5ed51d 469 [-73.961704,40.662942] Flatbush Avenue 11225 Brooklyn Hamburgers {"date":{"$date":1419897600000},"grade":"A","score":8} Wendy'S 30112340 +58ada47de5a51ddfcd5ed51e 351 [-73.985136,40.767692] West 57 Street 10019 Manhattan Irish {"date":{"$date":1409961600000},"grade":"A","score":2} Dj Reynolds Pub And Restaurant 30191841 +58ada47de5a51ddfcd5ed51f 2780 [-73.982420,40.579505] Stillwell Avenue 11224 Brooklyn American {"date":{"$date":1402358400000},"grade":"A","score":5} Riviera Caterer 40356018 +58ada47de5a51ddfcd5ed520 97-22 [-73.860115,40.731174] 63 Road 11374 Queens Jewish/Kosher {"date":{"$date":1416787200000},"grade":"Z","score":20} Tov Kosher Kitchen 40356068 DROP TABLE t1; # # Dropping a column @@ -89,16 +89,16 @@ CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MONGO TABNAME=restaurants DATA_CHARSET COLIST='{"projection":{"grades":0}}' OPTION_LIST='Driver=C,Version=0,level=0' ; SELECT * FROM t1 LIMIT 10; _id address borough cuisine name restaurant_id -58ada47de5a51ddfcd5ed51c {"building":"1007","coord":[-73.856076999999999089,40.848447000000000173],"street":"Morris ParkAve", "zipcode":"10462"} Bronx Bakery Morris Park Bake Shop 30075445 -58ada47de5a51ddfcd5ed51d {"building":"469","coord":[-73.96170399999999745,40.66294200000000103],"street":"Flatbush Avenue", "zipcode":"11225"} Brooklyn Hamburgers Wendy'S 30112340 -58ada47de5a51ddfcd5ed51e {"building":"351","coord":[-73.985135599999992451,40.767691900000002647],"street":"West 57Street", "zipcode":"10019"} Manhattan Irish Dj Reynolds Pub And Restaurant 30191841 -58ada47de5a51ddfcd5ed51f {"building":"2780","coord":[-73.982419999999990523,40.579504999999997494],"street":"Stillwell Avenue", "zipcode":"11224"} Brooklyn American Riviera Caterer 40356018 -58ada47de5a51ddfcd5ed520 {"building":"97-22","coord":[-73.860115199999995639,40.731173900000001709],"street":"63 Road", "zipcode":"11374"} Queens Jewish/Kosher Tov Kosher Kitchen 40356068 -58ada47de5a51ddfcd5ed521 {"building":"8825","coord":[-73.880382699999998408,40.764312400000001446],"street":"Astoria Boulevard", "zipcode":"11369"} Queens American Brunos On The Boulevard 40356151 -58ada47de5a51ddfcd5ed522 {"building":"2206","coord":[-74.137728600000002643,40.611957199999999091],"street":"Victory Boulevard", "zipcode":"10314"} Staten Island Jewish/Kosher Kosher Island 40356442 -58ada47de5a51ddfcd5ed523 {"building":"7114","coord":[-73.906850599999998508,40.619903399999998328],"street":"Avenue U", "zipcode":"11234"} Brooklyn Delicatessen Wilken'S Fine Food 40356483 -58ada47de5a51ddfcd5ed524 {"building":"6409","coord":[-74.005288999999990551,40.628886000000001388],"street":"11 Avenue", "zipcode":"11219"} Brooklyn American Regina Caterers 40356649 -58ada47de5a51ddfcd5ed525 {"building":"1839","coord":[-73.948260899999993967,40.640827100000002758],"street":"Nostrand Avenue", "zipcode":"11226"} Brooklyn Ice Cream, Gelato, Yogurt, Ices Taste The Tropics Ice Cream 40356731 +58ada47de5a51ddfcd5ed51c {"building":"1007","coord":[-73.856077,40.848447],"street":"Morris Park Ave","zipcode":"10462"} Bronx Bakery Morris Park Bake Shop 30075445 +58ada47de5a51ddfcd5ed51d {"building":"469","coord":[-73.961704,40.662942],"street":"Flatbush Avenue","zipcode":"11225"} Brooklyn Hamburgers Wendy'S 30112340 +58ada47de5a51ddfcd5ed51e {"building":"351","coord":[-73.985136,40.767692],"street":"West 57 Street","zipcode":"10019"} Manhattan Irish Dj Reynolds Pub And Restaurant 30191841 +58ada47de5a51ddfcd5ed51f {"building":"2780","coord":[-73.982420,40.579505],"street":"Stillwell Avenue","zipcode":"11224"} Brooklyn American Riviera Caterer 40356018 +58ada47de5a51ddfcd5ed520 {"building":"97-22","coord":[-73.860115,40.731174],"street":"63 Road","zipcode":"11374"} Queens Jewish/Kosher Tov Kosher Kitchen 40356068 +58ada47de5a51ddfcd5ed521 {"building":"8825","coord":[-73.880383,40.764312],"street":"Astoria Boulevard","zipcode":"11369"} Queens American Brunos On The Boulevard 40356151 +58ada47de5a51ddfcd5ed522 {"building":"2206","coord":[-74.137729,40.611957],"street":"Victory Boulevard","zipcode":"10314"} Staten Island Jewish/Kosher Kosher Island 40356442 +58ada47de5a51ddfcd5ed523 {"building":"7114","coord":[-73.906851,40.619903],"street":"Avenue U","zipcode":"11234"} Brooklyn Delicatessen Wilken'S Fine Food 40356483 +58ada47de5a51ddfcd5ed524 {"building":"6409","coord":[-74.005289,40.628886],"street":"11 Avenue","zipcode":"11219"} Brooklyn American Regina Caterers 40356649 +58ada47de5a51ddfcd5ed525 {"building":"1839","coord":[-73.948261,40.640827],"street":"Nostrand Avenue","zipcode":"11226"} Brooklyn Ice Cream, Gelato, Yogurt, Ices Taste The Tropics Ice Cream 40356731 DROP TABLE t1; # # Specifying Jpath diff --git a/storage/connect/mysql-test/connect/r/odbc_oracle.result b/storage/connect/mysql-test/connect/r/odbc_oracle.result index acb7d9a74c9..317aacef7a9 100644 --- a/storage/connect/mysql-test/connect/r/odbc_oracle.result +++ b/storage/connect/mysql-test/connect/r/odbc_oracle.result @@ -10,7 +10,7 @@ SET NAMES utf8; # All tables in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Tables; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Table_Type Remark @@ -20,7 +20,7 @@ NULL MTR V1 VIEW NULL DROP TABLE t1; # All tables in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Tables TABNAME='%.%'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Table_Type Remark @@ -30,7 +30,7 @@ NULL MTR V1 VIEW NULL DROP TABLE t1; # All tables "T1" in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Tables TABNAME='%.T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Table_Type Remark @@ -38,7 +38,7 @@ NULL MTR T1 TABLE NULL DROP TABLE t1; # All tables "T1" in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Tables TABNAME='T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Table_Type Remark @@ -46,7 +46,7 @@ NULL MTR T1 TABLE NULL DROP TABLE t1; # Table "T1" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Tables TABNAME='MTR.T1'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Table_Type Remark @@ -54,7 +54,7 @@ NULL MTR T1 TABLE NULL DROP TABLE t1; # All tables in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Tables TABNAME='MTR.%'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Table_Type Remark @@ -68,7 +68,7 @@ DROP TABLE t1; # All columns in all schemas (limited with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Columns; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks @@ -80,7 +80,7 @@ Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Bu DROP TABLE t1; # All columns in all schemas (limited with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Columns TABNAME='%.%'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks @@ -91,7 +91,7 @@ Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Bu MTR V1 B 6 NUMBER 38 40 NULL NULL 1 DROP TABLE t1; # All tables "T1" in all schemas (limited with WHERE) -CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' CATFUNC=Columns TABNAME='%.T1'; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Columns TABNAME='%.T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks MTR T1 A 3 DECIMAL 38 40 0 10 1 @@ -99,7 +99,7 @@ Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Bu DROP TABLE t1; # Table "T1" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Columns TABNAME='MTR.T1'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks @@ -108,7 +108,7 @@ Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Bu DROP TABLE t1; # All tables "T1" in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Columns TABNAME='%.T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks @@ -121,14 +121,14 @@ DROP TABLE t1; # Table "T1" in the default schema ("MTR") CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' TABNAME='T1'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `A` decimal(40,0) DEFAULT NULL, `B` double DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' `TABLE_TYPE`='ODBC' `TABNAME`='T1' +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' `TABLE_TYPE`='ODBC' `TABNAME`='T1' SELECT * FROM t1 ORDER BY A; A B 10 1000000000 @@ -157,14 +157,14 @@ DROP VIEW v1; DROP TABLE t1; # Table "T1" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' TABNAME='MTR.T1'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `A` decimal(40,0) DEFAULT NULL, `B` double DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.T1' +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.T1' SELECT * FROM t1; A B 10 1000000000 @@ -173,14 +173,14 @@ A B DROP TABLE t1; # View "V1" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' TABNAME='MTR.V1'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `A` decimal(40,0) DEFAULT NULL, `B` double DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.V1' +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.V1' SELECT * FROM t1; A B 10 1000000000 @@ -209,13 +209,13 @@ DROP VIEW v1; DROP TABLE t1; # Table "T2" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' TABNAME='MTR.T2'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `A` varchar(64) DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.T2' +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.T2' SELECT * FROM t1; A test diff --git a/storage/connect/mysql-test/connect/t/jdbc_oracle.test b/storage/connect/mysql-test/connect/t/jdbc_oracle.test index 1316352d4f5..0a475102ff7 100644 --- a/storage/connect/mysql-test/connect/t/jdbc_oracle.test +++ b/storage/connect/mysql-test/connect/t/jdbc_oracle.test @@ -8,20 +8,20 @@ CREATE TABLE t2 ( number int(5) not null flag=1, message varchar(255) flag=2) ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='jdbc:oracle:thin:@localhost:1521:xe' -OPTION_LIST='User=system,Password=Choupy01,Execsrc=1'; +OPTION_LIST='User=system,Password=Biscote01,Execsrc=1'; SELECT * FROM t2 WHERE command = 'drop table employee'; SELECT * FROM t2 WHERE command = 'create table employee (id int not null, name varchar(32), title char(16), salary number(8,2))'; SELECT * FROM t2 WHERE command = "insert into employee values(4567,'Johnson', 'Engineer', 12560.50)"; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=tables CONNECTION='jdbc:oracle:thin:@localhost:1521:xe' -OPTION_LIST='User=system,Password=Choupy01'; +OPTION_LIST='User=system,Password=Biscote01'; SELECT * FROM t1 WHERE table_name='employee'; DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='EMPLOYEE' CATFUNC=columns CONNECTION='jdbc:oracle:thin:@localhost:1521:xe' -OPTION_LIST='User=system,Password=Choupy01'; +OPTION_LIST='User=system,Password=Biscote01'; SELECT * FROM t1; DROP TABLE t1; @@ -32,7 +32,7 @@ CREATE SERVER 'oracle' FOREIGN DATA WRAPPER 'oracle.jdbc.driver.OracleDriver' OP HOST 'jdbc:oracle:thin:@localhost:1521:xe', DATABASE 'SYSTEM', USER 'system', -PASSWORD 'Choupy01', +PASSWORD 'Biscote01', PORT 0, SOCKET '', OWNER 'SYSTEM'); diff --git a/storage/connect/mysql-test/connect/t/odbc_oracle.test b/storage/connect/mysql-test/connect/t/odbc_oracle.test index 18d29f69f1a..2a6eb5b7fce 100644 --- a/storage/connect/mysql-test/connect/t/odbc_oracle.test +++ b/storage/connect/mysql-test/connect/t/odbc_oracle.test @@ -78,42 +78,42 @@ SET NAMES utf8; --echo # All tables in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Tables; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --echo # All tables in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Tables TABNAME='%.%'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --echo # All tables "T1" in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Tables TABNAME='%.T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --echo # All tables "T1" in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Tables TABNAME='T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --echo # Table "T1" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Tables TABNAME='MTR.T1'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --echo # All tables in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Tables TABNAME='MTR.%'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; @@ -127,7 +127,7 @@ DROP TABLE t1; --echo # All columns in all schemas (limited with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Columns; # Disable warnings to avoid "Result limited to 20000 lines" --disable_warnings @@ -137,7 +137,7 @@ DROP TABLE t1; --echo # All columns in all schemas (limited with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Columns TABNAME='%.%'; # Disable warnings to avoid "Result limited to 20000 lines" --disable_warnings @@ -146,20 +146,20 @@ SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --echo # All tables "T1" in all schemas (limited with WHERE) -CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' CATFUNC=Columns TABNAME='%.T1'; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Columns TABNAME='%.T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --echo # Table "T1" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Columns TABNAME='MTR.T1'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --echo # All tables "T1" in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' CATFUNC=Columns TABNAME='%.T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; DROP TABLE t1; @@ -172,7 +172,7 @@ DROP TABLE t1; --echo # Table "T1" in the default schema ("MTR") CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' TABNAME='T1'; SHOW CREATE TABLE t1; SELECT * FROM t1 ORDER BY A; @@ -189,7 +189,7 @@ DROP TABLE t1; --echo # Table "T1" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' TABNAME='MTR.T1'; SHOW CREATE TABLE t1; SELECT * FROM t1; @@ -197,7 +197,7 @@ DROP TABLE t1; --echo # View "V1" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' TABNAME='MTR.V1'; SHOW CREATE TABLE t1; SELECT * FROM t1; @@ -214,7 +214,7 @@ DROP TABLE t1; --echo # Table "T2" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT -TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=newmtr' +TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtrnew' TABNAME='MTR.T2'; SHOW CREATE TABLE t1; SELECT * FROM t1; diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 2d3c6a6aacd..bb25d4803d9 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -93,8 +93,7 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info) if (check_valid_path(module, strlen(module))) { strcpy(g->Message, "Module cannot contain a path"); return NULL; - } - else + } else PlugSetPath(soname, module, GetPluginDir()); // The exported name is always in uppercase diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index 8c57157f5a9..6c42ab2c810 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -2535,6 +2535,7 @@ void DOSCOL::ReadColumn(PGLOBAL g) char *p = NULL; int i, rc; int field; + bool err = false; double dval; PTDBDOS tdbp = (PTDBDOS)To_Tdb; @@ -2578,33 +2579,39 @@ void DOSCOL::ReadColumn(PGLOBAL g) case TYPE_SHORT: case TYPE_TINY: case TYPE_BIGINT: - if (Value->SetValue_char(p, field - Dcm)) { - sprintf(g->Message, "Out of range value for column %s at row %d", - Name, tdbp->RowNumber(g)); - PushWarning(g, tdbp); - } // endif SetValue_char - + err = Value->SetValue_char(p, field - Dcm); break; case TYPE_DOUBLE: - Value->SetValue_char(p, field); - dval = Value->GetFloatValue(); + if (!(err = Value->SetValue_char(p, field))) { + dval = Value->GetFloatValue(); - for (i = 0; i < Dcm; i++) - dval /= 10.0; + for (i = 0; i < Dcm; i++) + dval /= 10.0; + + Value->SetValue(dval); + } // endif err - Value->SetValue(dval); break; default: - Value->SetValue_char(p, field); + err = Value->SetValue_char(p, field); + + if (!err && Buf_Type == TYPE_DECIM) { + char* s = Value->GetCharValue(); + + if (!(err = ((i = strlen(s)) >= Value->GetClen()))) { + for (int d = Dcm + 1; d; i--, d--) + s[i + 1] = s[i]; + + s[i + 1] = '.'; + } // endif err + + } // endif DECIM + break; - } // endswitch Buf_Type + } // endswitch Buf_Type else - if (Value->SetValue_char(p, field)) { - sprintf(g->Message, "Out of range value for column %s at row %d", - Name, tdbp->RowNumber(g)); - PushWarning(g, tdbp); - } // endif SetValue_char + err = Value->SetValue_char(p, field); break; default: @@ -2612,6 +2619,12 @@ void DOSCOL::ReadColumn(PGLOBAL g) throw 34; } // endswitch Ftype + if (err) { + sprintf(g->Message, "Out of range value for column %s at row %d", + Name, tdbp->RowNumber(g)); + PushWarning(g, tdbp); + } // endif err + // Set null when applicable if (Nullable) Value->SetNull(Value->IsZero()); @@ -2702,7 +2715,7 @@ void DOSCOL::WriteColumn(PGLOBAL g) case TYPE_DECIM: strcpy(fmt, (Ldz) ? "%0*.*lf" : "%*.*lf"); len = field + ((Nod && Dcm) ? 1 : 0); - snprintf(Buf, len, fmt, len, Dcm, Value->GetFloatValue()); + snprintf(Buf, len + 1, fmt, len, Dcm, Value->GetFloatValue()); len = strlen(Buf); if (Nod && Dcm) From e0edfc277f564752720950159e8a7c2803df8ad3 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 18 May 2021 16:42:19 +0200 Subject: [PATCH 06/18] - Fix MDEV-25715 modified: storage/connect/bsonudf.cpp modified: storage/connect/jsonudf.cpp --- storage/connect/bsonudf.cpp | 6 +++--- storage/connect/jsonudf.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/storage/connect/bsonudf.cpp b/storage/connect/bsonudf.cpp index a56db4d731b..d3174580e7f 100644 --- a/storage/connect/bsonudf.cpp +++ b/storage/connect/bsonudf.cpp @@ -4682,7 +4682,7 @@ char *bfile_convert(UDF_INIT* initid, UDF_ARGS* args, char* result, str = (char*)g->Xchk; if (!str) { - PUSH_WARNING(g->Message ? g->Message : "Unexpected error"); + PUSH_WARNING(*g->Message ? g->Message : "Unexpected error"); *is_null = 1; *error = 1; *res_length = 0; @@ -4742,7 +4742,7 @@ char *bfile_bjson(UDF_INIT *initid, UDF_ARGS *args, char *result, if (!g->Xchk) { int msgid = MSGID_OPEN_MODE_STRERROR; - FILE *fout; + FILE *fout = NULL; FILE *fin; if (!(fin = global_fopen(g, msgid, fn, "rt"))) @@ -4805,7 +4805,7 @@ char *bfile_bjson(UDF_INIT *initid, UDF_ARGS *args, char *result, str = (char*)g->Xchk; if (!str) { - if (g->Message) + if (*g->Message) str = strcpy(result, g->Message); else str = strcpy(result, "Unexpected error"); diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 7db01af2f2b..1f635002e7e 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -5943,7 +5943,7 @@ char *jfile_convert(UDF_INIT* initid, UDF_ARGS* args, char* result, str = (char*)g->Xchk; if (!str) { - PUSH_WARNING(g->Message ? g->Message : "Unexpected error"); + PUSH_WARNING(*g->Message ? g->Message : "Unexpected error"); *is_null = 1; *error = 1; *res_length = 0; @@ -6004,7 +6004,7 @@ char *jfile_bjson(UDF_INIT *initid, UDF_ARGS *args, char *result, if (!g->Xchk) { int msgid = MSGID_OPEN_MODE_STRERROR; - FILE *fout; + FILE *fout = NULL; FILE *fin; if (!(fin = global_fopen(g, msgid, fn, "rt"))) @@ -6071,7 +6071,7 @@ char *jfile_bjson(UDF_INIT *initid, UDF_ARGS *args, char *result, str = (char*)g->Xchk; if (!str) { - if (g->Message) + if (*g->Message) str = strcpy(result, g->Message); else str = strcpy(result, "Unexpected error"); From be7e41db96b0a05b4896be875b8797089100b7b6 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 24 May 2021 16:56:12 +0200 Subject: [PATCH 07/18] - Mongo defined columns modified: storage/connect/cmgoconn.cpp modified: storage/connect/cmgoconn.h - Change default array LIMIT from 10 to 50 modified: storage/connect/ha_connect.cc modified: storage/connect/tabbson.cpp modified: storage/connect/tabjson.cpp modified: storage/connect/tabxml.cpp --- storage/connect/cmgoconn.cpp | 21 +++++++++++++++++---- storage/connect/cmgoconn.h | 1 + storage/connect/ha_connect.cc | 6 +++--- storage/connect/tabbson.cpp | 4 ++-- storage/connect/tabjson.cpp | 4 ++-- storage/connect/tabxml.cpp | 2 +- 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/storage/connect/cmgoconn.cpp b/storage/connect/cmgoconn.cpp index 5a81799c4a2..6ab9e781994 100644 --- a/storage/connect/cmgoconn.cpp +++ b/storage/connect/cmgoconn.cpp @@ -300,6 +300,7 @@ void CMgoConn::Project(PGLOBAL g, PSTRG s) for (cp = tp->GetColumns(); cp; cp = cp->GetNext()) { path = cp->GetJpath(g, true); + // Resolve path collision for (hp = php; hp; hp = hp->Next) { if (strlen(path) < strlen(hp->Path)) { n = strlen(path); @@ -318,6 +319,7 @@ void CMgoConn::Project(PGLOBAL g, PSTRG s) // New path hp = (PTHP)PlugSubAlloc(g, NULL, sizeof(PTH)); hp->Path = path; + hp->Name = cp->GetName(); hp->Next = NULL; *nphp = hp; nphp = &hp->Next; @@ -332,8 +334,16 @@ void CMgoConn::Project(PGLOBAL g, PSTRG s) else b = true; - s->Append(hp->Path); - s->Append("\":1"); + if (*hp->Path == '{') { + // This is a Mongo defined column + s->Append(hp->Name); + s->Append("\":"); + s->Append(hp->Path); + } else { + s->Append(hp->Path); + s->Append("\":1"); + } // endif Path + } // endfor hp } // end of Project @@ -885,9 +895,12 @@ void CMgoConn::GetColumnValue(PGLOBAL g, PCOL colp) char *jpath = colp->GetJpath(g, false); bool b = false; PVAL value = colp->GetValue(); - bson_iter_t Iter; // Used to retrieve column value - bson_iter_t Desc; // Descendant iter + bson_iter_t Iter; // Used to retrieve column value + bson_iter_t Desc; // Descendant iter + if (*jpath == '{') + jpath = colp->GetName(); // This is a Mongo defined column + if (!*jpath || !strcmp(jpath, "*")) { value->SetValue_psz(Mini(g, colp, Document, false)); } else if (bson_iter_init(&Iter, Document) && diff --git a/storage/connect/cmgoconn.h b/storage/connect/cmgoconn.h index c69f53b366f..f37a96cb7b9 100644 --- a/storage/connect/cmgoconn.h +++ b/storage/connect/cmgoconn.h @@ -44,6 +44,7 @@ typedef struct _path_list *PTHP; typedef struct _path_list { PSZ Path; + PSZ Name; PTHP Next; } PTH; diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 5f210f649f5..416bbb5d071 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -167,10 +167,10 @@ #define SZCONV 1024 // Default converted text size #define SZWORK 67108864 // Default work area size 64M #define SZWMIN 4194304 // Minimum work area size 4M -#define JSONMAX 10 // JSON Default max grp size +#define JSONMAX 50 // JSON Default max grp size extern "C" { - char version[]= "Version 1.07.0003 May 02, 2021"; + char version[]= "Version 1.07.0003 May 22, 2021"; #if defined(__WIN__) char compver[]= "Version 1.07.0003 " __DATE__ " " __TIME__; char slash= '\\'; @@ -508,7 +508,7 @@ char *GetJsonNull(void) int GetDefaultDepth(void) {return THDVAR(current_thd, default_depth);} int GetDefaultPrec(void) {return THDVAR(current_thd, default_prec);} uint GetJsonGrpSize(void) - {return connect_hton ? THDVAR(current_thd, json_grp_size) : 10;} + {return connect_hton ? THDVAR(current_thd, json_grp_size) : 50;} size_t GetWorkSize(void) {return (size_t)THDVAR(current_thd, work_size);} void SetWorkSize(size_t) { diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index d36b9718cd6..c6758b21707 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -173,7 +173,7 @@ int BSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) lvl = GetIntegerTableOption(g, topt, "Depth", lvl); sep = GetStringTableOption(g, topt, "Separator", "."); sz = GetIntegerTableOption(g, topt, "Jsize", 1024); - limit = GetIntegerTableOption(g, topt, "Limit", 10); + limit = GetIntegerTableOption(g, topt, "Limit", 50); strfy = GetStringTableOption(g, topt, "Stringify", NULL); /*********************************************************************/ @@ -1159,7 +1159,7 @@ bool BSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Objname = GetStringCatInfo(g, "Object", NULL); Xcol = GetStringCatInfo(g, "Expand", NULL); Pretty = GetIntCatInfo("Pretty", 2); - Limit = GetIntCatInfo("Limit", 10); + Limit = GetIntCatInfo("Limit", 50); Base = GetIntCatInfo("Base", 0) ? 1 : 0; Sep = *GetStringCatInfo(g, "Separator", "."); Accept = GetBoolCatInfo("Accept", false); diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index 4a8031113d2..cad098e0f9b 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -179,7 +179,7 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) sep = GetStringTableOption(g, topt, "Separator", "."); strfy = GetStringTableOption(g, topt, "Stringify", NULL); sz = GetIntegerTableOption(g, topt, "Jsize", 1024); - limit = GetIntegerTableOption(g, topt, "Limit", 10); + limit = GetIntegerTableOption(g, topt, "Limit", 50); /*********************************************************************/ /* Open the input file. */ @@ -635,7 +635,7 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Objname = GetStringCatInfo(g, "Object", NULL); Xcol = GetStringCatInfo(g, "Expand", NULL); Pretty = GetIntCatInfo("Pretty", 2); - Limit = GetIntCatInfo("Limit", 10); + Limit = GetIntCatInfo("Limit", 50); Base = GetIntCatInfo("Base", 0) ? 1 : 0; Sep = *GetStringCatInfo(g, "Separator", "."); Accept = GetBoolCatInfo("Accept", false); diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp index 6065bb1b5d2..d7f199a8092 100644 --- a/storage/connect/tabxml.cpp +++ b/storage/connect/tabxml.cpp @@ -525,7 +525,7 @@ bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) XmlDB = GetStringCatInfo(g, "XmlDB", NULL); Nslist = GetStringCatInfo(g, "Nslist", NULL); DefNs = GetStringCatInfo(g, "DefNs", NULL); - Limit = GetIntCatInfo("Limit", 10); + Limit = GetIntCatInfo("Limit", 50); Xpand = GetBoolCatInfo("Expand", false); Header = GetIntCatInfo("Header", 0); GetCharCatInfo("Xmlsup", "*", buf, sizeof(buf)); From 5f64276fb2bd4a400927105cf5d536b82e01fbd2 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 8 Jun 2021 17:44:43 +0200 Subject: [PATCH 08/18] - Fix MDEV-25863 : Replace __WIN__ by _WIN32 modified: storage/connect/array.cpp modified: storage/connect/blkfil.cpp modified: storage/connect/block.h modified: storage/connect/bson.cpp modified: storage/connect/cmgoconn.cpp modified: storage/connect/colblk.cpp modified: storage/connect/domdoc.cpp modified: storage/connect/filamap.cpp modified: storage/connect/filamdbf.cpp modified: storage/connect/filamfix.cpp modified: storage/connect/filamgz.cpp modified: storage/connect/filamtxt.cpp modified: storage/connect/filamvct.cpp modified: storage/connect/filamzip.cpp modified: storage/connect/filter.cpp modified: storage/connect/filter.h modified: storage/connect/fmdlex.c modified: storage/connect/global.h modified: storage/connect/ha_connect.cc modified: storage/connect/javaconn.cpp modified: storage/connect/javaconn.h modified: storage/connect/jdbconn.cpp modified: storage/connect/jmgfam.cpp modified: storage/connect/json.cpp modified: storage/connect/macutil.cpp modified: storage/connect/macutil.h modified: storage/connect/maputil.cpp modified: storage/connect/mycat.cc modified: storage/connect/myconn.cpp modified: storage/connect/myconn.h modified: storage/connect/myutil.cpp modified: storage/connect/odbconn.cpp modified: storage/connect/odbconn.h modified: storage/connect/os.h modified: storage/connect/osutil.c modified: storage/connect/plgdbsem.h modified: storage/connect/plgdbutl.cpp modified: storage/connect/plugutil.cpp modified: storage/connect/rcmsg.c modified: storage/connect/reldef.cpp modified: storage/connect/reldef.h modified: storage/connect/tabdos.cpp modified: storage/connect/tabext.cpp modified: storage/connect/tabfix.cpp modified: storage/connect/tabfmt.cpp modified: storage/connect/tabjdbc.cpp modified: storage/connect/tabmac.cpp modified: storage/connect/tabmac.h modified: storage/connect/tabmul.cpp modified: storage/connect/tabmul.h modified: storage/connect/tabmysql.cpp modified: storage/connect/taboccur.cpp modified: storage/connect/tabodbc.cpp modified: storage/connect/tabpivot.cpp modified: storage/connect/tabrest.cpp modified: storage/connect/tabrest.h modified: storage/connect/tabsys.cpp modified: storage/connect/tabtbl.cpp modified: storage/connect/tabutil.cpp modified: storage/connect/tabvct.cpp modified: storage/connect/tabwmi.cpp modified: storage/connect/tabxcl.cpp modified: storage/connect/tabxml.cpp modified: storage/connect/valblk.cpp modified: storage/connect/value.cpp modified: storage/connect/xindex.cpp modified: storage/connect/xindex.h - Fix Date errors and SSL warnings modified: storage/connect/mysql-test/connect/r/jdbc.result modified: storage/connect/mysql-test/connect/r/jdbc_new.result modified: storage/connect/mysql-test/connect/t/jdbc.test modified: storage/connect/mysql-test/connect/t/jdbc_new.test - Update java source files modified: storage/connect/Mongo2Interface.java modified: storage/connect/Mongo3Interface.java added: storage/connect/Client2.java added: storage/connect/Client3.java added: storage/connect/TestInsert2.java added: storage/connect/TestInsert3.java --- storage/connect/Client2.java | 130 ++++++++++++ storage/connect/Client3.java | 154 ++++++++++++++ storage/connect/Mongo2Interface.java | 136 +++++++++++-- storage/connect/Mongo3Interface.java | 190 ++++++++++++++---- storage/connect/TestInsert2.java | 131 ++++++++++++ storage/connect/TestInsert3.java | 131 ++++++++++++ storage/connect/array.cpp | 6 +- storage/connect/blkfil.cpp | 6 +- storage/connect/block.h | 6 +- storage/connect/bson.cpp | 2 +- storage/connect/cmgoconn.cpp | 6 +- storage/connect/colblk.cpp | 4 +- storage/connect/domdoc.cpp | 2 +- storage/connect/filamap.cpp | 16 +- storage/connect/filamdbf.cpp | 10 +- storage/connect/filamfix.cpp | 40 ++-- storage/connect/filamgz.cpp | 16 +- storage/connect/filamtxt.cpp | 26 +-- storage/connect/filamvct.cpp | 72 +++---- storage/connect/filamzip.cpp | 18 +- storage/connect/filter.cpp | 6 +- storage/connect/filter.h | 2 +- storage/connect/fmdlex.c | 4 +- storage/connect/global.h | 16 +- storage/connect/ha_connect.cc | 62 +++--- storage/connect/javaconn.cpp | 28 +-- storage/connect/javaconn.h | 10 +- storage/connect/jdbconn.cpp | 14 +- storage/connect/jmgfam.cpp | 6 +- storage/connect/json.cpp | 2 +- storage/connect/macutil.cpp | 6 +- storage/connect/macutil.h | 6 +- storage/connect/maputil.cpp | 2 +- storage/connect/mycat.cc | 22 +- storage/connect/myconn.cpp | 12 +- storage/connect/myconn.h | 12 +- .../connect/mysql-test/connect/r/jdbc.result | 18 +- .../mysql-test/connect/r/jdbc_new.result | 50 ++--- .../connect/mysql-test/connect/t/jdbc.test | 10 +- .../mysql-test/connect/t/jdbc_new.test | 32 +-- storage/connect/myutil.cpp | 6 +- storage/connect/odbconn.cpp | 16 +- storage/connect/odbconn.h | 4 +- storage/connect/os.h | 10 +- storage/connect/osutil.c | 2 +- storage/connect/plgdbsem.h | 6 +- storage/connect/plgdbutl.cpp | 30 +-- storage/connect/plugutil.cpp | 26 +-- storage/connect/rcmsg.c | 4 +- storage/connect/reldef.cpp | 36 ++-- storage/connect/reldef.h | 6 +- storage/connect/tabdos.cpp | 18 +- storage/connect/tabext.cpp | 2 +- storage/connect/tabfix.cpp | 6 +- storage/connect/tabfmt.cpp | 8 +- storage/connect/tabjdbc.cpp | 2 +- storage/connect/tabmac.cpp | 6 +- storage/connect/tabmac.h | 6 +- storage/connect/tabmul.cpp | 80 ++++---- storage/connect/tabmul.h | 22 +- storage/connect/tabmysql.cpp | 6 +- storage/connect/taboccur.cpp | 2 +- storage/connect/tabodbc.cpp | 2 +- storage/connect/tabpivot.cpp | 2 +- storage/connect/tabrest.cpp | 16 +- storage/connect/tabrest.h | 6 +- storage/connect/tabsys.cpp | 20 +- storage/connect/tabtbl.cpp | 8 +- storage/connect/tabutil.cpp | 2 +- storage/connect/tabvct.cpp | 6 +- storage/connect/tabwmi.cpp | 4 +- storage/connect/tabxcl.cpp | 2 +- storage/connect/tabxml.cpp | 28 +-- storage/connect/valblk.cpp | 2 +- storage/connect/value.cpp | 14 +- storage/connect/xindex.cpp | 28 +-- storage/connect/xindex.h | 2 +- 77 files changed, 1317 insertions(+), 551 deletions(-) create mode 100644 storage/connect/Client2.java create mode 100644 storage/connect/Client3.java create mode 100644 storage/connect/TestInsert2.java create mode 100644 storage/connect/TestInsert3.java diff --git a/storage/connect/Client2.java b/storage/connect/Client2.java new file mode 100644 index 00000000000..6dbf4188032 --- /dev/null +++ b/storage/connect/Client2.java @@ -0,0 +1,130 @@ +package wrappers; + +import java.io.BufferedReader; +import java.io.Console; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Set; + +public class Client2 { + static boolean DEBUG = true; + static final Console c = System.console(); + static Mongo2Interface jdi = null; + + public static void main(String[] args) { + int rc, m, i = 0; + boolean brc; + Set columns; + String[] parms = new String[4]; + + jdi = new Mongo2Interface(DEBUG); + + parms[0] = getLine("URI: ", false); + parms[1] = getLine("DB: ", false); + parms[2] = null; + parms[3] = null; + + if (parms[0] == null) + parms[0] = "mongodb://localhost:27017"; + + if (parms[1] == null) + parms[1] = "test"; + + rc = jdi.MongoConnect(parms); + + if (rc == 0) { + String name, pipeline, query, fields; + System.out.println("Successfully connected to " + parms[1]); + + while ((name = getLine("Collection: ", false)) != null) { + if (jdi.GetCollection(name)) + System.out.println("GetCollection failed"); + else + System.out.println("Collection size: " + jdi.GetCollSize()); + + pipeline = getLine("Pipeline: ", false); + + if (pipeline == null) { + query = getLine("Filter: ", false); + fields = getLine("Proj: ", false); + brc = jdi.FindColl(query, fields); + } else + brc = jdi.AggregateColl(pipeline); + + System.out.println("Returned brc = " + brc); + + if (!brc) { + for (i = 0; i < 10; i++) { + m = jdi.ReadNext(); + + if (m > 0) { + columns = jdi.GetColumns(); + + for (String col : columns) + System.out.println(col + "=" + jdi.GetField(col)); + + if (pipeline == null) { + if (name.equalsIgnoreCase("gtst")) + System.out.println("gtst=" + jdi.GetField("*")); + + if (name.equalsIgnoreCase("inventory")) { + System.out.println("warehouse=" + jdi.GetField("instock.0.warehouse")); + System.out.println("quantity=" + jdi.GetField("instock.1.qty")); + } // endif inventory + + if (name.equalsIgnoreCase("restaurants")) { + System.out.println("score=" + jdi.GetField("grades.0.score")); + System.out.println("date=" + jdi.GetField("grades.0.date")); + } // endif restaurants + + } // endif pipeline + + } else if (m < 0) { + System.out.println("ReadNext: " + jdi.GetErrmsg()); + break; + } else + break; + + } // endfor i + + } // endif brc + + } // endwhile name + + rc = jdi.MongoDisconnect(); + System.out.println("Disconnect returned " + rc); + } else + System.out.println(jdi.GetErrmsg() + " rc=" + rc); + + } // end of main + + // ================================================================== + private static String getLine(String p, boolean b) { + String response; + + if (c != null) { + // Standard console mode + if (b) { + response = new String(c.readPassword(p)); + } else + response = c.readLine(p); + + } else { + // For instance when testing from Eclipse + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + + System.out.print(p); + + try { + // Cannot suppress echo for password entry + response = in.readLine(); + } catch (IOException e) { + response = ""; + } // end of try/catch + + } // endif c + + return (response.isEmpty()) ? null : response; + } // end of getLine + +} // end of class Client diff --git a/storage/connect/Client3.java b/storage/connect/Client3.java new file mode 100644 index 00000000000..0d3914cdd0d --- /dev/null +++ b/storage/connect/Client3.java @@ -0,0 +1,154 @@ +package wrappers; + +import java.io.BufferedReader; +import java.io.Console; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Set; + +public class Client3 { + static boolean DEBUG = true; + static final Console c = System.console(); + static Mongo3Interface jdi = null; + + public static void main(String[] args) { + int rc, level = 0; + boolean brc, desc = false; + Set columns; + String[] parms = new String[4]; + + jdi = new Mongo3Interface(DEBUG); + + parms[0] = getLine("URI: ", false); + parms[1] = getLine("Database: ", false); + parms[2] = null; + parms[3] = null; + + if (parms[0] == null) + parms[0] = "mongodb://localhost:27017"; + + if (parms[1] == null) + parms[1] = "test"; + + rc = jdi.MongoConnect(parms); + + if (rc == 0) { + String name, pipeline, query, fields; + System.out.println("Successfully connected to " + parms[0]); + + while ((name = getLine("Collection: ", false)) != null) { + if (jdi.GetCollection(name)) + System.out.println("GetCollection failed"); + else + System.out.println("Collection size: " + jdi.GetCollSize()); + + pipeline = getLine("Pipeline: ", false); + + if (pipeline == null || (desc = pipeline.equals("*"))) { + query = getLine("Filter: ", false); + fields = getLine("Proj: ", false); + + if (desc) + level = Integer.parseInt(getLine("Level: ", false)); + + brc = jdi.FindColl(query, fields); + } else + brc = jdi.AggregateColl(pipeline); + + System.out.println("Returned brc = " + brc); + + if (!brc && !desc) { + for (int i = 0; jdi.ReadNext() > 0 && i < 10; i++) { + columns = jdi.GetColumns(); + + for (String col : columns) + System.out.println(col + "=" + jdi.GetField(col)); + + if (name.equalsIgnoreCase("gtst")) + System.out.println("gtst=" + jdi.GetField("*")); + + if (name.equalsIgnoreCase("inventory")) { + System.out.println("warehouse=" + jdi.GetField("instock.0.warehouse")); + System.out.println("quantity=" + jdi.GetField("instock.1.qty")); + } // endif inventory + + if (name.equalsIgnoreCase("restaurants")) { + System.out.println("score=" + jdi.GetField("grades.0.score")); + System.out.println("date=" + jdi.GetField("grades.0.date")); + } // endif inventory + + } // endfor i + + } else if (desc) { + int ncol; + + for (int i = 0; (ncol = jdi.ReadNext()) > 0 && i < 2; i++) { + if (discovery(null, "", ncol, level)) + break; + + System.out.println("--------------"); + } // endfor i + + } // endif desc + + } // endwhile query + + rc = jdi.MongoDisconnect(); + System.out.println("Disconnect returned " + rc); + } else + System.out.println(jdi.GetErrmsg() + " rc=" + rc); + + } // end of main + + private static boolean discovery(Object obj, String name, int ncol, int level) { + int[] val = new int[5]; + Object ret = null; + String bvn = null; + + for (int k = 0; k < ncol; k++) { + ret = jdi.ColumnDesc(obj, k, val, level); + bvn = jdi.ColDescName(); + + if (ret != null) + discovery(ret, name.concat(bvn).concat("."), val[4], level - 1); + else if (val[0] > 0) + System.out.println( + name + bvn + ": type=" + val[0] + " length=" + val[1] + " prec=" + val[2] + " nullable=" + val[3]); + else if (val[0] < 0) + System.out.println(jdi.GetErrmsg()); + + } // endfor k + + return false; + } // end of discovery + + // ================================================================== + private static String getLine(String p, boolean b) { + String response; + + if (c != null) { + // Standard console mode + if (b) { + response = new String(c.readPassword(p)); + } else + response = c.readLine(p); + + } else { + // For instance when testing from Eclipse + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + + System.out.print(p); + + try { + // Cannot suppress echo for password entry + response = in.readLine(); + } catch (IOException e) { + response = ""; + } // end of try/catch + + } // endif c + + return (response.isEmpty()) ? null : response; + } // end of getLine + +} // end of class Client diff --git a/storage/connect/Mongo2Interface.java b/storage/connect/Mongo2Interface.java index 106dd4a4d63..5d27fe467d6 100644 --- a/storage/connect/Mongo2Interface.java +++ b/storage/connect/Mongo2Interface.java @@ -21,6 +21,7 @@ import com.mongodb.util.JSON; public class Mongo2Interface { boolean DEBUG = false; String Errmsg = "No error"; + String ovalName = null; Set Colnames = null; Cursor cursor = null; MongoClient client = null; @@ -220,7 +221,7 @@ public class Mongo2Interface { System.out.println("Class doc = " + doc.getClass()); Colnames = doc.keySet(); - return 1; + return Colnames.size(); } else return 0; @@ -253,30 +254,106 @@ public class Mongo2Interface { } // end of GetColumns - public String ColumnDesc(int n, int[] val) { - // if (rsmd == null) { - // System.out.println("No result metadata"); - // return null; - // } else try { - // val[0] = rsmd.getColumnType(n); - // val[1] = rsmd.getPrecision(n); - // val[2] = rsmd.getScale(n); - // val[3] = rsmd.isNullable(n); - // return rsmd.getColumnLabel(n); - // } catch (SQLException se) { - // SetErrmsg(se); - // } //end try/catch + public Object ColumnDesc(Object obj, int n, int[] val, int lvl) { + Object ret = null; + Object oval = ((obj != null) ? obj : doc); + BasicDBObject dob = (oval instanceof BasicDBObject) ? (BasicDBObject) oval : null; + BasicDBList ary = (oval instanceof BasicDBList) ? (BasicDBList) oval : null; + try { + if (ary != null) { + oval = ary.get(n); + ovalName = Integer.toString(n); + } else if (dob != null) { + // String[] k = dob.keySet().toArray(new String[0]); + Object[] k = dob.keySet().toArray(); + oval = dob.get(k[n]); + ovalName = (String) k[n]; + } else + ovalName = "x" + Integer.toString(n); + + if (DEBUG) + System.out.println("Class of " + ovalName + " = " + oval.getClass()); + + val[0] = 0; // ColumnType + val[1] = 0; // Precision + val[2] = 0; // Scale + val[3] = 0; // Nullable + val[4] = 0; // ncol + + if (oval == null) { + val[3] = 1; + } else if (oval instanceof String) { + val[0] = 1; + val[1] = ((String) oval).length(); + } else if (oval instanceof org.bson.types.ObjectId) { + val[0] = 1; + val[1] = ((org.bson.types.ObjectId) oval).toString().length(); + } else if (oval instanceof Integer) { + val[0] = 7; + val[1] = Integer.toString(((Integer) oval).intValue()).length(); + } else if (oval instanceof Long) { + val[0] = 5; + val[1] = Long.toString(((Long) oval).longValue()).length(); + } else if (oval instanceof Date) { + Long TS = (((Date) oval).getTime() / 1000); + val[0] = 8; + val[1] = TS.toString().length(); + } else if (oval instanceof Double) { + String d = Double.toString(((Double) oval).doubleValue()); + int i = d.indexOf('.') + 1; + + val[0] = 2; + val[1] = d.length(); + val[2] = (i > 0) ? val[1] - i : 0; + } else if (oval instanceof Boolean) { + val[0] = 4; + val[1] = 1; + } else if (oval instanceof BasicDBObject) { + if (lvl > 0) { + ret = oval; + val[0] = 1; + val[4] = ((BasicDBObject) oval).size(); + } else if (lvl == 0) { + val[0] = 1; + val[1] = oval.toString().length(); + } // endif lvl + + } else if (oval instanceof BasicDBList) { + if (lvl > 0) { + ret = oval; + val[0] = 2; + val[4] = ((BasicDBList) oval).size(); + } else if (lvl == 0) { + val[0] = 1; + val[1] = oval.toString().length(); + } // endif lvl + + } else { + SetErrmsg("Type " + " of " + ovalName + " not supported"); + val[0] = -1; + } // endif's + + return ret; + } catch (Exception ex) { + SetErrmsg(ex); + } // end try/catch + + val[0] = -1; return null; } // end of ColumnDesc + public String ColDescName() { + return ovalName; + } // end of ColDescName + protected Object GetFieldObject(String path) { Object o = null; BasicDBObject dob = null; BasicDBList lst = null; String[] names = null; - if (path == null || path.equals("*")) + if (path == null || path.equals("") || path.equals("*")) return doc; else if (doc instanceof BasicDBObject) dob = doc; @@ -325,9 +402,10 @@ public class Mongo2Interface { if (o != null) { if (o instanceof Date) { - Integer TS = (int) (((Date) o).getTime() / 1000); + Long TS = (((Date) o).getTime() / 1000); return TS.toString(); - } // endif Date + } else if (o instanceof Boolean) + return (Boolean) o ? "1" : "0"; return o.toString(); } else @@ -335,13 +413,25 @@ public class Mongo2Interface { } // end of GetField + public Object MakeBson(String s, int json) { + if (json == 1 || json == 2) { + return com.mongodb.util.JSON.parse(s); + } else + return null; + + } // end of MakeBson + public Object MakeDocument() { return new BasicDBObject(); } // end of MakeDocument - public boolean DocAdd(Object bdc, String key, Object val) { + public boolean DocAdd(Object bdc, String key, Object val, int json) { try { - ((BasicDBObject) bdc).append(key, val); + if (json != 0 && val instanceof String) + ((BasicDBObject) bdc).append(key, JSON.parse((String) val)); + else + ((BasicDBObject) bdc).append(key, val); + } catch (MongoException me) { SetErrmsg(me); return true; @@ -354,9 +444,13 @@ public class Mongo2Interface { return new BasicDBList(); } // end of MakeArray - public boolean ArrayAdd(Object bar, int n, Object val) { + public boolean ArrayAdd(Object bar, int n, Object val, int json) { try { - ((BasicDBList) bar).put(n, val); + if (json != 0 && val instanceof String) + ((BasicDBList) bar).put(n, JSON.parse((String) val)); + else + ((BasicDBList) bar).put(n, val); + } catch (MongoException me) { SetErrmsg(me); return true; diff --git a/storage/connect/Mongo3Interface.java b/storage/connect/Mongo3Interface.java index f587c01b391..73175e13aa3 100644 --- a/storage/connect/Mongo3Interface.java +++ b/storage/connect/Mongo3Interface.java @@ -1,5 +1,6 @@ package wrappers; +//import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Date; @@ -9,6 +10,7 @@ import java.util.Set; import org.bson.BsonArray; import org.bson.BsonBoolean; import org.bson.BsonDateTime; +//import org.bson.BsonDecimal128; import org.bson.BsonDocument; import org.bson.BsonDouble; import org.bson.BsonInt32; @@ -18,6 +20,7 @@ import org.bson.BsonString; import org.bson.BsonValue; import org.bson.Document; import org.bson.conversions.Bson; +//import org.bson.types.Decimal128; import com.mongodb.MongoClient; import com.mongodb.MongoClientURI; @@ -34,6 +37,7 @@ import com.mongodb.client.result.UpdateResult; public class Mongo3Interface { boolean DEBUG = false; String Errmsg = "No error"; + String bvalName = null; Set Colnames = null; MongoClient client = null; MongoDatabase db = null; @@ -167,7 +171,7 @@ public class Mongo3Interface { try { if (query != null) { - Bson dbq = Document.parse((query != null) ? query : "{}"); + Bson dbq = Document.parse(query); finditer = coll.find(dbq); } else finditer = coll.find(); @@ -218,17 +222,23 @@ public class Mongo3Interface { } // end of Rewind public int ReadNext() { - if (cursor.hasNext()) { - doc = cursor.next(); + try { + if (cursor.hasNext()) { + doc = cursor.next(); - if (DEBUG) - System.out.println("Class doc = " + doc.getClass()); + if (DEBUG) + System.out.println("Class doc = " + doc.getClass()); - Colnames = doc.keySet(); - return 1; - } else - return 0; + Colnames = doc.keySet(); + return Colnames.size(); + } else + return 0; + } catch (MongoException mx) { + SetErrmsg(mx); + } // end try/catch + + return -1; } // end of ReadNext public boolean Fetch(int row) { @@ -254,13 +264,11 @@ public class Mongo3Interface { } // end of GetColumns public String ColumnName(int n) { - int i = 1; + if (n < Colnames.size()) + return (String) Colnames.toArray()[n]; + else + return null; - for (String name : Colnames) - if (i++ == n) - return name; - - return null; } // end of ColumnName public int ColumnType(int n, String name) { @@ -278,30 +286,111 @@ public class Mongo3Interface { return 666; // Not a type } // end of ColumnType - public String ColumnDesc(int n, int[] val) { - // if (rsmd == null) { - // System.out.println("No result metadata"); - // return null; - // } else try { - // val[0] = rsmd.getColumnType(n); - // val[1] = rsmd.getPrecision(n); - // val[2] = rsmd.getScale(n); - // val[3] = rsmd.isNullable(n); - // return rsmd.getColumnLabel(n); - // } catch (SQLException se) { - // SetErrmsg(se); - // } //end try/catch + public Object ColumnDesc(Object obj, int n, int[] val, int lvl) { + Object ret = null; + BsonValue bval = (BsonValue) ((obj != null) ? obj : doc); + BsonDocument dob = (bval instanceof BsonDocument) ? (BsonDocument) bval : null; + BsonArray ary = (bval instanceof BsonArray) ? (BsonArray) bval : null; + try { + if (ary != null) { + bval = ary.get(n); + bvalName = Integer.toString(n); + } else if (dob != null) { + // String[] k = dob.keySet().toArray(new String[0]); + Object[] k = dob.keySet().toArray(); + bval = dob.get(k[n]); + bvalName = (String) k[n]; + } else + bvalName = "x" + Integer.toString(n); + + val[0] = 0; // ColumnType + val[1] = 0; // Precision + val[2] = 0; // Scale + val[3] = 0; // Nullable + val[4] = 0; // ncol + + if (bval.isString()) { + val[0] = 1; + val[1] = bval.asString().getValue().length(); + } else if (bval.isInt32()) { + val[0] = 7; + val[1] = Integer.toString(bval.asInt32().getValue()).length(); + } else if (bval.isInt64()) { + val[0] = 5; + val[1] = Long.toString(bval.asInt64().getValue()).length(); + } else if (bval.isObjectId()) { + val[0] = 1; + val[1] = bval.asObjectId().getValue().toString().length(); + } else if (bval.isDateTime()) { + Long TS = (bval.asDateTime().getValue() / 1000); + val[0] = 8; + val[1] = TS.toString().length(); + } else if (bval.isDouble()) { + String d = Double.toString(bval.asDouble().getValue()); + int i = d.indexOf('.') + 1; + + val[0] = 2; + val[1] = d.length(); + val[2] = (i > 0) ? val[1] - i : 0; + } else if (bval.isBoolean()) { + val[0] = 4; + val[1] = 1; + } else if (bval.isDocument()) { + if (lvl > 0) { + ret = bval; + val[0] = 1; + val[4] = bval.asDocument().keySet().size(); + } else if (lvl == 0) { + val[0] = 1; + val[1] = bval.asDocument().toJson().length(); + } // endif lvl + + } else if (bval.isArray()) { + if (lvl > 0) { + ret = bval; + val[0] = 2; + val[4] = bval.asArray().size(); + } else if (lvl == 0) { + val[0] = 1; + util = new BsonDocument("arr", bval.asArray()); + String s = util.toJson(); + int i1 = s.indexOf('['); + int i2 = s.lastIndexOf(']'); + val[1] = i2 - i1 + 1; + } // endif lvl + + } else if (bval.isDecimal128()) { + val[0] = 9; + val[1] = bval.asDecimal128().toString().length(); + } else if (bval.isNull()) { + val[0] = 0; + val[3] = 1; + } else { + SetErrmsg("Type " + bval.getBsonType() + " of " + bvalName + " not supported"); + val[0] = -1; + } // endif's + + return ret; + } catch (Exception ex) { + SetErrmsg(ex); + } // end try/catch + + val[0] = -1; return null; } // end of ColumnDesc + public String ColDescName() { + return bvalName; + } // end of ColDescName + protected BsonValue GetFieldObject(String path) { BsonValue o = doc; BsonDocument dob = null; BsonArray ary = null; String[] names = null; - if (path == null || path.equals("*")) + if (path == null || path.equals("") || path.equals("*")) return doc; else if (o instanceof BsonDocument) dob = doc; @@ -362,6 +451,8 @@ public class Mongo3Interface { return TS.toString(); } else if (o.isDouble()) { return Double.toString(o.asDouble().getValue()); + } else if (o.isBoolean()) { + return o.asBoolean().getValue() ? "1" : "0"; } else if (o.isDocument()) { return o.asDocument().toJson(); } else if (o.isArray()) { @@ -370,6 +461,8 @@ public class Mongo3Interface { int i1 = s.indexOf('['); int i2 = s.lastIndexOf(']'); return s.substring(i1, i2 + 1); + } else if (o.isDecimal128()) { + return o.asDecimal128().toString(); } else if (o.isNull()) { return null; } else @@ -380,14 +473,33 @@ public class Mongo3Interface { } // end of GetField - protected BsonValue ObjToBson(Object val) { + public Object MakeBson(String s, int json) { + BsonValue bval; + + if (json == 1) + bval = BsonDocument.parse(s); + else if (json == 2) + bval = BsonArray.parse(s); + else + bval = null; + + return bval; + } // end of MakeBson + + protected BsonValue ObjToBson(Object val, int json) { BsonValue bval = null; if (val == null) bval = bsonull; - else if (val.getClass() == String.class) - bval = new BsonString((String) val); - else if (val.getClass() == Integer.class) + else if (val.getClass() == String.class) { + if (json == 1) + bval = BsonDocument.parse((String) val); + else if (json == 2) + bval = BsonArray.parse((String) val); + else + bval = new BsonString((String) val); + + } else if (val.getClass() == Integer.class) bval = new BsonInt32((int) val); else if (val.getClass() == Double.class) bval = new BsonDouble((double) val); @@ -401,6 +513,8 @@ public class Mongo3Interface { bval = (BsonDocument) val; else if (val.getClass() == BsonArray.class) bval = (BsonArray) val; + // else if (val.getClass() == BigDecimal.class) + // bval = new BsonDecimal128((BigDecimal) val); return bval; } // end of ObjToBson @@ -409,9 +523,9 @@ public class Mongo3Interface { return new BsonDocument(); } // end of MakeDocument - public boolean DocAdd(Object bdc, String key, Object val) { + public boolean DocAdd(Object bdc, String key, Object val, int json) { try { - ((BsonDocument) bdc).append(key, ObjToBson(val)); + ((BsonDocument) bdc).append(key, ObjToBson(val, json)); } catch (MongoException me) { SetErrmsg(me); return true; @@ -424,12 +538,12 @@ public class Mongo3Interface { return new BsonArray(); } // end of MakeArray - public boolean ArrayAdd(Object bar, int n, Object val) { + public boolean ArrayAdd(Object bar, int n, Object val, int json) { try { for (int i = ((BsonArray) bar).size(); i < n; i++) ((BsonArray) bar).add(bsonull); - ((BsonArray) bar).add(ObjToBson(val)); + ((BsonArray) bar).add(ObjToBson(val, json)); } catch (MongoException me) { SetErrmsg(me); return true; @@ -501,4 +615,4 @@ public class Mongo3Interface { return n; } // end of CollDelete -} // end of class MongoInterface +} // end of class Mongo3Interface diff --git a/storage/connect/TestInsert2.java b/storage/connect/TestInsert2.java new file mode 100644 index 00000000000..e1a7cb4f98b --- /dev/null +++ b/storage/connect/TestInsert2.java @@ -0,0 +1,131 @@ +package wrappers; + +import java.io.BufferedReader; +import java.io.Console; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Date; + +public class TestInsert2 { + static boolean DEBUG = true; + static final Console c = System.console(); + static Mongo2Interface jdi = null; + + public static void main(String[] args) { + int rc; + String[] parms = new String[4]; + + jdi = new Mongo2Interface(DEBUG); + + parms[0] = getLine("URI: ", false); + parms[1] = getLine("Database: ", false); + parms[2] = null; + parms[3] = null; + + if (parms[0] == null) + parms[0] = "mongodb://localhost:27017"; + + if (parms[1] == null) + parms[1] = "test"; + + rc = jdi.MongoConnect(parms); + + if (rc == 0) { + Object bdoc = jdi.MakeDocument(); + + if (jdi.DocAdd(bdoc, "_id", (Object) 1, 0)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.DocAdd(bdoc, "Name", (Object) "Smith", 0)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.DocAdd(bdoc, "Age", (Object) 39, 0)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.DocAdd(bdoc, "Pi", (Object) 3.14, 0)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.DocAdd(bdoc, "Phone", (Object) "{\"ext\":[4,5,7]}", 1)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.DocAdd(bdoc, "Scores", (Object) "[24,2,13]", 2)) + System.out.println(jdi.GetErrmsg()); + + Object bar = jdi.MakeArray(); + + for (int i = 1; i < 3; i++) + if (jdi.ArrayAdd(bar, i, (Object) (Math.random() * 10.0), 0)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.DocAdd(bdoc, "Prices", bar, 0)) + System.out.println(jdi.GetErrmsg()); + + Object dat = new Date(); + + if (jdi.DocAdd(bdoc, "Date", dat, 0)) + System.out.println(jdi.GetErrmsg()); + + System.out.println(bdoc); + + // Try to update + if (!jdi.GetCollection("updtest") && !jdi.FindColl(null, null)) { + if (jdi.CollDelete(true) < 0) + System.out.println(jdi.GetErrmsg()); + + if (jdi.CollInsert(bdoc)) + System.out.println(jdi.GetErrmsg()); + + Object updlist = jdi.MakeDocument(); + + if (jdi.DocAdd(updlist, "Age", (Object) 45, 0)) + System.out.println(jdi.GetErrmsg()); + + Object upd = jdi.MakeDocument(); + + if (jdi.DocAdd(upd, "$set", updlist, 0)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.ReadNext() > 0 && jdi.CollUpdate(upd) < 0) + System.out.println(jdi.GetErrmsg()); + + if (!jdi.Rewind() && jdi.ReadNext() > 0) + System.out.println(jdi.GetDoc()); + else + System.out.println("Failed Rewind"); + + } // endif n + + } // endif rc + + } // end of main + + // ================================================================== + private static String getLine(String p, boolean b) { + String response; + + if (c != null) { + // Standard console mode + if (b) { + response = new String(c.readPassword(p)); + } else + response = c.readLine(p); + + } else { + // For instance when testing from Eclipse + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + + System.out.print(p); + + try { + // Cannot suppress echo for password entry + response = in.readLine(); + } catch (IOException e) { + response = ""; + } // end of try/catch + + } // endif c + + return (response.isEmpty()) ? null : response; + } // end of getLine + +} diff --git a/storage/connect/TestInsert3.java b/storage/connect/TestInsert3.java new file mode 100644 index 00000000000..a56a361e7aa --- /dev/null +++ b/storage/connect/TestInsert3.java @@ -0,0 +1,131 @@ +package wrappers; + +import java.io.BufferedReader; +import java.io.Console; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Date; + +public class TestInsert3 { + static boolean DEBUG = true; + static final Console c = System.console(); + static Mongo3Interface jdi = null; + + public static void main(String[] args) { + int rc; + String[] parms = new String[4]; + + jdi = new Mongo3Interface(DEBUG); + + parms[0] = getLine("URI: ", false); + parms[1] = getLine("Database: ", false); + parms[2] = null; + parms[3] = null; + + if (parms[0] == null) + parms[0] = "mongodb://localhost:27017"; + + if (parms[1] == null) + parms[1] = "test"; + + rc = jdi.MongoConnect(parms); + + if (rc == 0) { + Object bdoc = jdi.MakeDocument(); + + if (jdi.DocAdd(bdoc, "_id", (Object) 1, 0)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.DocAdd(bdoc, "Name", (Object) "Smith", 0)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.DocAdd(bdoc, "Age", (Object) 39, 0)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.DocAdd(bdoc, "Pi", (Object) 3.14, 0)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.DocAdd(bdoc, "Phone", (Object) "{\"ext\":[4,5,7]}", 1)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.DocAdd(bdoc, "Scores", (Object) "[24,2,13]", 2)) + System.out.println(jdi.GetErrmsg()); + + Object bar = jdi.MakeArray(); + + for (int i = 0; i < 2; i++) + if (jdi.ArrayAdd(bar, i, (Object) (Math.random() * 10.0), 0)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.DocAdd(bdoc, "Prices", bar, 0)) + System.out.println(jdi.GetErrmsg()); + + Object dat = new Date(); + + if (jdi.DocAdd(bdoc, "Date", dat, 0)) + System.out.println(jdi.GetErrmsg()); + + System.out.println(bdoc); + + // Try to update + if (!jdi.GetCollection("updtest") && !jdi.FindColl(null, null)) { + if (jdi.CollDelete(true) < 0) + System.out.println(jdi.GetErrmsg()); + + if (jdi.CollInsert(bdoc)) + System.out.println(jdi.GetErrmsg()); + + Object updlist = jdi.MakeDocument(); + + if (jdi.DocAdd(updlist, "Age", (Object) 40, 0)) + System.out.println(jdi.GetErrmsg()); + + Object upd = jdi.MakeDocument(); + + if (jdi.DocAdd(upd, "$set", updlist, 0)) + System.out.println(jdi.GetErrmsg()); + + if (jdi.ReadNext() > 0 && jdi.CollUpdate(upd) < 0) + System.out.println(jdi.GetErrmsg()); + + if (!jdi.Rewind() && jdi.ReadNext() > 0) + System.out.println(jdi.GetDoc()); + else + System.out.println("Failed Rewind"); + + } // endif n + + } // endif rc + + } // end of main + + // ================================================================== + private static String getLine(String p, boolean b) { + String response; + + if (c != null) { + // Standard console mode + if (b) { + response = new String(c.readPassword(p)); + } else + response = c.readLine(p); + + } else { + // For instance when testing from Eclipse + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + + System.out.print(p); + + try { + // Cannot suppress echo for password entry + response = in.readLine(); + } catch (IOException e) { + response = ""; + } // end of try/catch + + } // endif c + + return (response.isEmpty()) ? null : response; + } // end of getLine + +} diff --git a/storage/connect/array.cpp b/storage/connect/array.cpp index 84a686cc145..0e7e3ffc701 100644 --- a/storage/connect/array.cpp +++ b/storage/connect/array.cpp @@ -19,14 +19,14 @@ #include "sql_class.h" //#include "sql_time.h" -#if defined(__WIN__) +#if defined(_WIN32) //#include -#else // !__WIN__ +#else // !_WIN32 #include #include #include #include // for uintprt_h -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include required application header files */ diff --git a/storage/connect/blkfil.cpp b/storage/connect/blkfil.cpp index 76c9d09ac93..93ae5a5ef0c 100644 --- a/storage/connect/blkfil.cpp +++ b/storage/connect/blkfil.cpp @@ -20,13 +20,13 @@ #include "sql_class.h" //#include "sql_time.h" -#if defined(__WIN__) +#if defined(_WIN32) //#include -#else // !__WIN__ +#else // !_WIN32 #include #include #include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include application header files: */ diff --git a/storage/connect/block.h b/storage/connect/block.h index c10fc4761ac..e8871277d48 100644 --- a/storage/connect/block.h +++ b/storage/connect/block.h @@ -24,11 +24,11 @@ #if !defined(BLOCK_DEFINED) #define BLOCK_DEFINED -#if defined(__WIN__) && !defined(NOEX) +#if defined(_WIN32) && !defined(NOEX) #define DllExport __declspec( dllexport ) -#else // !__WIN__ +#else // !_WIN32 #define DllExport -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Definition of class BLOCK with its method function new. */ diff --git a/storage/connect/bson.cpp b/storage/connect/bson.cpp index 060e8b1e394..bf03f47a10d 100644 --- a/storage/connect/bson.cpp +++ b/storage/connect/bson.cpp @@ -30,7 +30,7 @@ #define CheckType(X,Y) #endif -#if defined(__WIN__) +#if defined(_WIN32) #define EL "\r\n" #else #define EL "\n" diff --git a/storage/connect/cmgoconn.cpp b/storage/connect/cmgoconn.cpp index 6ab9e781994..f3fc30fa9e2 100644 --- a/storage/connect/cmgoconn.cpp +++ b/storage/connect/cmgoconn.cpp @@ -161,16 +161,16 @@ bool CMgoConn::Connect(PGLOBAL g) } // endif name if (!IsInit) -#if defined(__WIN__) +#if defined(_WIN32) __try { mongo_init(true); } __except (EXCEPTION_EXECUTE_HANDLER) { strcpy(g->Message, "Cannot load MongoDB C driver"); return true; } // end try/except -#else // !__WIN__ +#else // !_WIN32 mongo_init(true); -#endif // !__WIN__ +#endif // !_WIN32 Uri = mongoc_uri_new_with_error(Pcg->Uristr, &Error); diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp index a9cf43f3d96..7bbebaaa889 100644 --- a/storage/connect/colblk.cpp +++ b/storage/connect/colblk.cpp @@ -297,9 +297,9 @@ FIDBLK::FIDBLK(PCOLUMN cp, OPVAL op) : SPCBLK(cp), Op(op) Buf_Type = TYPE_STRING; *Format.Type = 'C'; Format.Length = Long; -#if defined(__WIN__) +#if defined(_WIN32) Format.Prec = 1; // Case insensitive -#endif // __WIN__ +#endif // _WIN32 Constant = (!To_Tdb->GetDef()->GetMultiple() && To_Tdb->GetAmType() != TYPE_AM_PLG && To_Tdb->GetAmType() != TYPE_AM_PLM); diff --git a/storage/connect/domdoc.cpp b/storage/connect/domdoc.cpp index 9ae34a3b9ef..9da73bdc770 100644 --- a/storage/connect/domdoc.cpp +++ b/storage/connect/domdoc.cpp @@ -4,7 +4,7 @@ /******************************************************************/ #include "my_global.h" #include -#if defined(__WIN__) +#if defined(_WIN32) //#include #if defined(MSX2) #import "msxml2.dll" //Does not exist on Vista diff --git a/storage/connect/filamap.cpp b/storage/connect/filamap.cpp index 18ba0b1018f..9f873e4f180 100644 --- a/storage/connect/filamap.cpp +++ b/storage/connect/filamap.cpp @@ -17,12 +17,12 @@ /* Include relevant sections of the System header files. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #if defined(__BORLANDC__) #define __MFC_COMPAT__ // To define min/max as macro #endif // __BORLANDC__ //#include -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) #include #include @@ -30,7 +30,7 @@ #include #endif // !UNIX #include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include application header files: */ @@ -197,11 +197,11 @@ bool MAPFAM::OpenTableFile(PGLOBAL g) return true; } // endif Memory -#if defined(__WIN__) +#if defined(_WIN32) if (mode != MODE_DELETE) { -#else // !__WIN__ +#else // !_WIN32 if (mode == MODE_READ) { -#endif // !__WIN__ +#endif // !_WIN32 CloseFileHandle(hFile); // Not used anymore hFile = INVALID_HANDLE_VALUE; // For Fblock } // endif Mode @@ -468,7 +468,7 @@ int MAPFAM::DeleteRecords(PGLOBAL g, int irc) /*****************************************************************/ n = (int)(Tpos - Memory); -#if defined(__WIN__) +#if defined(_WIN32) DWORD drc = SetFilePointer(fp->Handle, n, NULL, FILE_BEGIN); if (drc == 0xFFFFFFFF) { @@ -498,7 +498,7 @@ int MAPFAM::DeleteRecords(PGLOBAL g, int irc) #endif // UNIX } // endif Abort -#if defined(__WIN__) +#if defined(_WIN32) CloseHandle(fp->Handle); #else // UNIX close(fp->Handle); diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index 542159fd172..a93fba52a50 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -22,12 +22,12 @@ /* Include relevant sections of the System header files. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include //#include //#include -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) #include #include @@ -35,7 +35,7 @@ //#include #endif // !UNIX //#include -#endif // !__WIN__ +#endif // !_WIN32 #include #include #include @@ -649,7 +649,7 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g) To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen); if (mode == MODE_INSERT) { -#if defined(__WIN__) +#if defined(_WIN32) /************************************************************************/ /* Now we can revert to binary mode in particular because the eventual */ /* writing of a new header must be done in binary mode to avoid */ @@ -659,7 +659,7 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g) sprintf(g->Message, MSG(BIN_MODE_FAIL), strerror(errno)); return true; } // endif setmode -#endif // __WIN__ +#endif // _WIN32 /************************************************************************/ /* If this is a new file, the header must be generated. */ diff --git a/storage/connect/filamfix.cpp b/storage/connect/filamfix.cpp index 0a98ec5b54a..e0002f6f784 100644 --- a/storage/connect/filamfix.cpp +++ b/storage/connect/filamfix.cpp @@ -17,7 +17,7 @@ /* Include relevant sections of the System header files. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #include @@ -25,7 +25,7 @@ #define __MFC_COMPAT__ // To define min/max as macro #endif // __BORLANDC__ //#include -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) #include #include @@ -34,7 +34,7 @@ #endif // !UNIX #include #include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include application header files: */ @@ -338,7 +338,7 @@ int FIXFAM::ReadBuffer(PGLOBAL g) } else if (feof(Stream)) { rc = RC_EF; } else { -#if defined(__WIN__) +#if defined(_WIN32) sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL)); #else sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno)); @@ -678,7 +678,7 @@ BGXFAM::BGXFAM(PBGXFAM txfp) : FIXFAM(txfp) /***********************************************************************/ bool BGXFAM::BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, int org) { -#if defined(__WIN__) +#if defined(_WIN32) char buf[256]; DWORD drc; LARGE_INTEGER of; @@ -694,14 +694,14 @@ bool BGXFAM::BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, int org) sprintf(g->Message, MSG(SFP_ERROR), buf); return true; } // endif -#else // !__WIN__ +#else // !_WIN32 if (lseek64(h, pos, org) < 0) { // sprintf(g->Message, MSG(ERROR_IN_LSK), errno); sprintf(g->Message, "lseek64: %s", strerror(errno)); printf("%s\n", g->Message); return true; } // endif -#endif // !__WIN__ +#endif // !_WIN32 return false; } // end of BigSeek @@ -714,7 +714,7 @@ int BGXFAM::BigRead(PGLOBAL g __attribute__((unused)), { int rc; -#if defined(__WIN__) +#if defined(_WIN32) DWORD nbr, drc, len = (DWORD)req; bool brc = ReadFile(h, inbuf, len, &nbr, NULL); @@ -736,12 +736,12 @@ int BGXFAM::BigRead(PGLOBAL g __attribute__((unused)), rc = -1; } else rc = (int)nbr; -#else // !__WIN__ +#else // !_WIN32 size_t len = (size_t)req; ssize_t nbr = read(h, inbuf, len); rc = (int)nbr; -#endif // !__WIN__ +#endif // !_WIN32 return rc; } // end of BigRead @@ -753,7 +753,7 @@ bool BGXFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req) { bool rc = false; -#if defined(__WIN__) +#if defined(_WIN32) DWORD nbw, drc, len = (DWORD)req; bool brc = WriteFile(h, inbuf, len, &nbw, NULL); @@ -781,7 +781,7 @@ bool BGXFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req) rc = true; } // endif brc || nbw -#else // !__WIN__ +#else // !_WIN32 size_t len = (size_t)req; ssize_t nbw = write(h, inbuf, len); @@ -796,7 +796,7 @@ bool BGXFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req) rc = true; } // endif nbr -#endif // !__WIN__ +#endif // !_WIN32 return rc; } // end of BigWrite @@ -831,7 +831,7 @@ bool BGXFAM::OpenTableFile(PGLOBAL g) if (trace(1)) htrc("OpenTableFile: filename=%s mode=%d\n", filename, mode); -#if defined(__WIN__) +#if defined(_WIN32) DWORD rc, access, creation, share = 0; /*********************************************************************/ @@ -989,7 +989,7 @@ int BGXFAM::Cardinality(PGLOBAL g) PlugSetPath(filename, To_File, Tdbp->GetPath()); -#if defined(__WIN__) // OB +#if defined(_WIN32) // OB LARGE_INTEGER len; DWORD rc = 0; @@ -1348,7 +1348,7 @@ int BGXFAM::DeleteRecords(PGLOBAL g, int irc) /*****************************************************************/ /* Remove extra records. */ /*****************************************************************/ -#if defined(__WIN__) +#if defined(_WIN32) if (BigSeek(g, Hfile, (BIGINT)Tpos * (BIGINT)Lrecl)) return RC_FX; @@ -1358,12 +1358,12 @@ int BGXFAM::DeleteRecords(PGLOBAL g, int irc) sprintf(g->Message, MSG(SETEOF_ERROR), drc); return RC_FX; } // endif error -#else // !__WIN__ +#else // !_WIN32 if (ftruncate64(Hfile, (BIGINT)(Tpos * Lrecl))) { sprintf(g->Message, MSG(TRUNCATE_ERROR), strerror(errno)); return RC_FX; } // endif -#endif // !__WIN__ +#endif // !_WIN32 } // endif UseTemp @@ -1388,7 +1388,7 @@ bool BGXFAM::OpenTempFile(PGLOBAL g) strcat(PlugRemoveType(tempname, tempname), ".t"); remove(tempname); // Be sure it does not exist yet -#if defined(__WIN__) +#if defined(_WIN32) Tfile = CreateFile(tempname, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); @@ -1528,7 +1528,7 @@ void BGXFAM::CloseTableFile(PGLOBAL g, bool abort) void BGXFAM::Rewind(void) { #if 0 // This is probably unuseful because file is accessed directly -#if defined(__WIN__) //OB +#if defined(_WIN32) //OB SetFilePointer(Hfile, 0, NULL, FILE_BEGIN); #else // UNIX lseek64(Hfile, 0, SEEK_SET); diff --git a/storage/connect/filamgz.cpp b/storage/connect/filamgz.cpp index 880db54c91d..1f785fc73ac 100644 --- a/storage/connect/filamgz.cpp +++ b/storage/connect/filamgz.cpp @@ -17,21 +17,21 @@ /* Include relevant MariaDB header file. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #if defined(__BORLANDC__) #define __MFC_COMPAT__ // To define min/max as macro #endif //#include -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) #include #else // !UNIX #include #endif #include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include application header files: */ @@ -89,11 +89,11 @@ int GZFAM::Zerror(PGLOBAL g) strcpy(g->Message, gzerror(Zfile, &errnum)); if (errnum == Z_ERRNO) -#if defined(__WIN__) +#if defined(_WIN32) sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(NULL)); -#else // !__WIN__ +#else // !_WIN32 sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno)); -#endif // !__WIN__ +#endif // !_WIN32 return (errnum == Z_STREAM_END) ? RC_EF : RC_FX; } // end of Zerror @@ -764,9 +764,9 @@ bool GZXFAM::AllocateBuffer(PGLOBAL g) if (Tdbp->GetFtype() < 2) // if not binary, the file is physically a text file for (int len = Lrecl; len <= Buflen; len += Lrecl) { -#if defined(__WIN__) +#if defined(_WIN32) To_Buf[len - 2] = '\r'; -#endif // __WIN__ +#endif // _WIN32 To_Buf[len - 1] = '\n'; } // endfor len diff --git a/storage/connect/filamtxt.cpp b/storage/connect/filamtxt.cpp index 30ce19a5d37..13779858d48 100644 --- a/storage/connect/filamtxt.cpp +++ b/storage/connect/filamtxt.cpp @@ -17,7 +17,7 @@ /* Include relevant sections of the System header files. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #include @@ -25,7 +25,7 @@ #define __MFC_COMPAT__ // To define min/max as macro #endif // __BORLANDC__ //#include -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) || defined(UNIV_LINUX) #include #include @@ -36,7 +36,7 @@ #include #endif // !UNIX #include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include application header files: */ @@ -82,7 +82,7 @@ TXTFAM::TXTFAM(PDOSDEF tdp) To_File = NULL; Lrecl = 0; Eof = false; -#if defined(__WIN__) +#if defined(_WIN32) Ending = 2; #else Ending = 1; @@ -731,7 +731,7 @@ int DOSFAM::SkipRecord(PGLOBAL g, bool header) if (feof(Stream)) return RC_EF; -#if defined(__WIN__) +#if defined(_WIN32) sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL)); #else sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(0)); @@ -814,7 +814,7 @@ int DOSFAM::ReadBuffer(PGLOBAL g) if (trace(2)) htrc(" Read: To_Buf=%p p=%c\n", To_Buf, p); -#if defined(__WIN__) +#if defined(_WIN32) if (Bin) { // Data file is read in binary so CRLF remains #else @@ -848,7 +848,7 @@ int DOSFAM::ReadBuffer(PGLOBAL g) } else if (feof(Stream)) { rc = RC_EF; } else { -#if defined(__WIN__) +#if defined(_WIN32) sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL)); #else sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(0)); @@ -1043,7 +1043,7 @@ int DOSFAM::DeleteRecords(PGLOBAL g, int irc) /*****************************************************************/ /* Remove extra records. */ /*****************************************************************/ -#if defined(__WIN__) +#if defined(_WIN32) if (chsize(h, Tpos)) { sprintf(g->Message, MSG(CHSIZE_ERROR), strerror(errno)); close(h); @@ -1482,7 +1482,7 @@ int BLKFAM::ReadBuffer(PGLOBAL g) } else if (feof(Stream)) { rc = RC_EF; } else { -#if defined(__WIN__) +#if defined(_WIN32) sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL)); #else sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno)); @@ -1567,11 +1567,11 @@ int BLKFAM::WriteBuffer(PGLOBAL g) Spos = GetNextPos(); // New start position // Prepare the output buffer -#if defined(__WIN__) +#if defined(_WIN32) crlf = "\r\n"; #else crlf = "\n"; -#endif // __WIN__ +#endif // _WIN32 strcat(strcpy(OutBuf, Tdbp->GetLine()), crlf); len = strlen(OutBuf); } else { @@ -1871,7 +1871,7 @@ int BINFAM::ReadBuffer(PGLOBAL g) } else if (feof(Stream)) { rc = RC_EF; } else { -#if defined(__WIN__) +#if defined(_WIN32) sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL)); #else sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(0)); @@ -2065,7 +2065,7 @@ int DOSFAM::DeleteRecords(PGLOBAL g, int irc) /*****************************************************************/ /* Remove extra records. */ /*****************************************************************/ -#if defined(__WIN__) +#if defined(_WIN32) if (chsize(h, Tpos)) { sprintf(g->Message, MSG(CHSIZE_ERROR), strerror(errno)); close(h); diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp index 5a3e025cd55..7a3c43e507f 100644 --- a/storage/connect/filamvct.cpp +++ b/storage/connect/filamvct.cpp @@ -21,7 +21,7 @@ /* Include relevant MariaDB header file. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #if defined(__BORLANDC__) @@ -29,7 +29,7 @@ #endif // __BORLAND__ //#include #include -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) #include #include @@ -40,7 +40,7 @@ #include #endif // !UNIX #include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include application header files: */ @@ -371,11 +371,11 @@ bool VCTFAM::MakeEmptyFile(PGLOBAL g, PCSZ fn) int h, n; PlugSetPath(filename, fn, Tdbp->GetPath()); -#if defined(__WIN__) +#if defined(_WIN32) h= global_open(g, MSGID_OPEN_EMPTY_FILE, filename, _O_CREAT | _O_WRONLY, S_IREAD | S_IWRITE); -#else // !__WIN__ +#else // !_WIN32 h= global_open(g, MSGID_OPEN_EMPTY_FILE, filename, O_CREAT | O_WRONLY, S_IREAD | S_IWRITE); -#endif // !__WIN__ +#endif // !_WIN32 if (h == -1) return true; @@ -1672,7 +1672,7 @@ int VCMFAM::DeleteRecords(PGLOBAL g, int irc) // Remove extra blocks n = Block * Blksize; -#if defined(__WIN__) +#if defined(_WIN32) DWORD drc = SetFilePointer(fp->Handle, n, NULL, FILE_BEGIN); if (drc == 0xFFFFFFFF) { @@ -2579,11 +2579,11 @@ bool VECFAM::ReadBlock(PGLOBAL g, PVCTCOL colp) char fn[_MAX_PATH]; sprintf(fn, Colfn, colp->Index); -#if defined(__WIN__) +#if defined(_WIN32) if (feof(Streams[i])) -#else // !__WIN__ +#else // !_WIN32 if (errno == NO_ERROR) -#endif // !__WIN__ +#endif // !_WIN32 sprintf(g->Message, MSG(BAD_READ_NUMBER), (int) n, fn); else sprintf(g->Message, MSG(READ_ERROR), @@ -2979,7 +2979,7 @@ int VMPFAM::DeleteRecords(PGLOBAL g, int irc) /*****************************************************************/ n = Tpos * Clens[i]; -#if defined(__WIN__) +#if defined(_WIN32) DWORD drc = SetFilePointer(fp->Handle, n, NULL, FILE_BEGIN); if (drc == 0xFFFFFFFF) { @@ -3059,7 +3059,7 @@ BGVFAM::BGVFAM(PBGVFAM txfp) : VCTFAM(txfp) /***********************************************************************/ bool BGVFAM::BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, bool b) { -#if defined(__WIN__) +#if defined(_WIN32) char buf[256]; DWORD drc, m = (b) ? FILE_END : FILE_BEGIN; LARGE_INTEGER of; @@ -3075,12 +3075,12 @@ bool BGVFAM::BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, bool b) sprintf(g->Message, MSG(SFP_ERROR), buf); return true; } // endif -#else // !__WIN__ +#else // !_WIN32 if (lseek64(h, pos, (b) ? SEEK_END : SEEK_SET) < 0) { sprintf(g->Message, MSG(ERROR_IN_LSK), errno); return true; } // endif -#endif // !__WIN__ +#endif // !_WIN32 return false; } // end of BigSeek @@ -3092,7 +3092,7 @@ bool BGVFAM::BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req) { bool rc = false; -#if defined(__WIN__) +#if defined(_WIN32) DWORD nbr, drc, len = (DWORD)req; bool brc = ReadFile(h, inbuf, len, &nbr, NULL); @@ -3118,7 +3118,7 @@ bool BGVFAM::BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req) rc = true; } // endif brc || nbr -#else // !__WIN__ +#else // !_WIN32 size_t len = (size_t)req; ssize_t nbr = read(h, inbuf, len); @@ -3133,7 +3133,7 @@ bool BGVFAM::BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req) rc = true; } // endif nbr -#endif // !__WIN__ +#endif // !_WIN32 return rc; } // end of BigRead @@ -3145,7 +3145,7 @@ bool BGVFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req) { bool rc = false; -#if defined(__WIN__) +#if defined(_WIN32) DWORD nbw, drc, len = (DWORD)req; bool brc = WriteFile(h, inbuf, len, &nbw, NULL); @@ -3173,7 +3173,7 @@ bool BGVFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req) rc = true; } // endif brc || nbw -#else // !__WIN__ +#else // !_WIN32 size_t len = (size_t)req; ssize_t nbw = write(h, inbuf, len); @@ -3188,7 +3188,7 @@ bool BGVFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req) rc = true; } // endif nbr -#endif // !__WIN__ +#endif // !_WIN32 return rc; } // end of BigWrite @@ -3214,7 +3214,7 @@ int BGVFAM::GetBlockInfo(PGLOBAL g) if (Header == 2) strcat(PlugRemoveType(filename, filename), ".blk"); -#if defined(__WIN__) +#if defined(_WIN32) LARGE_INTEGER len; h = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, @@ -3226,11 +3226,11 @@ int BGVFAM::GetBlockInfo(PGLOBAL g) } // endif h if (h == INVALID_HANDLE_VALUE || !len.QuadPart) { -#else // !__WIN__ +#else // !_WIN32 h = open64(filename, O_RDONLY, 0); if (h == INVALID_HANDLE_VALUE || !_filelength(h)) { -#endif // !__WIN__ +#endif // !_WIN32 // Consider this is a void table if (trace(1)) htrc("Void table h=%d\n", h); @@ -3291,17 +3291,17 @@ bool BGVFAM::SetBlockInfo(PGLOBAL g) strcat(PlugRemoveType(filename, filename), ".blk"); if (h == INVALID_HANDLE_VALUE) { -#if defined(__WIN__) +#if defined(_WIN32) DWORD creation = (b) ? OPEN_EXISTING : TRUNCATE_EXISTING; h = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL); -#else // !__WIN__ +#else // !_WIN32 int oflag = (b) ? O_RDWR : O_RDWR | O_TRUNC; h = open64(filename, oflag, 0); -#endif // !__WIN__ +#endif // !_WIN32 if (h == INVALID_HANDLE_VALUE) { sprintf(g->Message, "Error opening header file %s", filename); @@ -3339,7 +3339,7 @@ bool BGVFAM::MakeEmptyFile(PGLOBAL g, PCSZ fn) PlugSetPath(filename, fn, Tdbp->GetPath()); -#if defined(__WIN__) +#if defined(_WIN32) PCSZ p; DWORD rc; bool brc; @@ -3391,7 +3391,7 @@ bool BGVFAM::MakeEmptyFile(PGLOBAL g, PCSZ fn) CloseHandle(h); return true; -#else // !__WIN__ +#else // !_WIN32 int h; BIGINT pos; @@ -3420,7 +3420,7 @@ bool BGVFAM::MakeEmptyFile(PGLOBAL g, PCSZ fn) sprintf(g->Message, MSG(MAKE_EMPTY_FILE), To_File, strerror(errno)); close(h); return true; -#endif // !__WIN__ +#endif // !_WIN32 } // end of MakeEmptyFile /***********************************************************************/ @@ -3451,7 +3451,7 @@ bool BGVFAM::OpenTableFile(PGLOBAL g) htrc("OpenTableFile: filename=%s mode=%d Last=%d\n", filename, mode, Last); -#if defined(__WIN__) +#if defined(_WIN32) DWORD access, creation, share = 0, rc = 0; /*********************************************************************/ @@ -3779,7 +3779,7 @@ int BGVFAM::WriteBuffer(PGLOBAL g) if (!Closing && !MaxBlk) { // Close the VCT file and reopen it in mode Insert -//#if defined(__WIN__) //OB +//#if defined(_WIN32) //OB // CloseHandle(Hfile); //#else // UNIX // close(Hfile); @@ -3906,7 +3906,7 @@ int BGVFAM::DeleteRecords(PGLOBAL g, int irc) /***************************************************************/ /* Remove extra records. */ /***************************************************************/ -#if defined(__WIN__) +#if defined(_WIN32) BIGINT pos = (BIGINT)Block * (BIGINT)Blksize; if (BigSeek(g, Hfile, pos)) @@ -3918,12 +3918,12 @@ int BGVFAM::DeleteRecords(PGLOBAL g, int irc) sprintf(g->Message, MSG(SETEOF_ERROR), drc); return RC_FX; } // endif error -#else // !__WIN__ +#else // !_WIN32 if (ftruncate64(Hfile, (BIGINT)(Tpos * Lrecl))) { sprintf(g->Message, MSG(TRUNCATE_ERROR), strerror(errno)); return RC_FX; } // endif -#endif // !__WIN__ +#endif // !_WIN32 } else // MaxBlk // Clean the unused space in the file, this is required when // inserting again with a partial column list. @@ -3960,7 +3960,7 @@ bool BGVFAM::OpenTempFile(PGLOBAL g) else if (MakeEmptyFile(g, tempname)) return true; -#if defined(__WIN__) +#if defined(_WIN32) DWORD access = (MaxBlk) ? OPEN_EXISTING : CREATE_NEW; Tfile = CreateFile(tempname, GENERIC_WRITE, 0, NULL, @@ -4231,7 +4231,7 @@ void BGVFAM::Rewind(void) CurNum = Nrec - 1; #if 0 // This is probably unuseful as the file is directly accessed -#if defined(__WIN__) //OB +#if defined(_WIN32) //OB SetFilePointer(Hfile, 0, NULL, FILE_BEGIN); #else // UNIX lseek64(Hfile, 0, SEEK_SET); diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp index eeb23e1f053..3d576e97ebb 100644 --- a/storage/connect/filamzip.cpp +++ b/storage/connect/filamzip.cpp @@ -17,7 +17,7 @@ /* Include relevant sections of the System header files. */ /***********************************************************************/ #include "my_global.h" -#if !defined(__WIN__) +#if !defined(_WIN32) #if defined(UNIX) #include #include @@ -27,7 +27,7 @@ #include #endif // !UNIX #include -#endif // !__WIN__ +#endif // !_WIN32 #include /***********************************************************************/ @@ -154,7 +154,7 @@ static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, PCSZ pat, char *buf) /*********************************************************************/ strcpy(filename, pat); -#if defined(__WIN__) +#if defined(_WIN32) char drive[_MAX_DRIVE], direc[_MAX_DIR]; WIN32_FIND_DATA FileData; HANDLE hSearch; @@ -210,7 +210,7 @@ static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, PCSZ pat, char *buf) return true; } // endif FindClose -#else // !__WIN__ +#else // !_WIN32 struct stat fileinfo; char fn[FN_REFLEN], direc[FN_REFLEN], pattern[FN_HEADLEN], ftype[FN_EXTLEN]; DIR *dir; @@ -251,7 +251,7 @@ static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, PCSZ pat, char *buf) // Close the dir handle. closedir(dir); -#endif // !__WIN__ +#endif // !_WIN32 return false; } // end of ZipFiles @@ -275,9 +275,9 @@ bool ZipLoadFile(PGLOBAL g, PCSZ zfn, PCSZ fn, PCSZ entry, bool append, bool mul if (!entry) { // entry defaults to the file name char* p = strrchr((char*)fn, '/'); -#if defined(__WIN__) +#if defined(_WIN32) if (!p) p = strrchr((char*)fn, '\\'); -#endif // __WIN__ +#endif // _WIN32 entp = (p) ? p + 1 : entry; } else entp = entry; @@ -467,7 +467,7 @@ UNZIPUTL::UNZIPUTL(PCSZ tgt, PCSZ pw, bool mul) memset(fn, 0, sizeof(fn)); // Init the case mapping table. -#if defined(__WIN__) +#if defined(_WIN32) for (int i = 0; i < 256; ++i) mapCaseTable[i] = toupper(i); #else for (int i = 0; i < 256; ++i) mapCaseTable[i] = i; @@ -487,7 +487,7 @@ UNZIPUTL::UNZIPUTL(PDOSDEF tdp) memset(fn, 0, sizeof(fn)); // Init the case mapping table. -#if defined(__WIN__) +#if defined(_WIN32) for (int i = 0; i < 256; ++i) mapCaseTable[i] = toupper(i); #else for (int i = 0; i < 256; ++i) mapCaseTable[i] = i; diff --git a/storage/connect/filter.cpp b/storage/connect/filter.cpp index 7082b082c67..afcd2adfab0 100644 --- a/storage/connect/filter.cpp +++ b/storage/connect/filter.cpp @@ -13,13 +13,13 @@ //#include "sql_class.h" //#include "sql_time.h" -#if defined(__WIN__) +#if defined(_WIN32) //#include -#else // !__WIN__ +#else // !_WIN32 #include #include #include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ diff --git a/storage/connect/filter.h b/storage/connect/filter.h index c6ab8fddd35..12ac3a169c1 100644 --- a/storage/connect/filter.h +++ b/storage/connect/filter.h @@ -106,7 +106,7 @@ class FILTERX : public FILTER { // Fake operator new used to change a filter into a derived filter void * operator new(size_t, PFIL filp) {return filp;} -#if defined(__WIN__) +#if defined(_WIN32) // Avoid warning C4291 by defining a matching dummy delete operator void operator delete(void *, PFIL) {} #else diff --git a/storage/connect/fmdlex.c b/storage/connect/fmdlex.c index 729b1b883c1..1fb2b3fee65 100644 --- a/storage/connect/fmdlex.c +++ b/storage/connect/fmdlex.c @@ -22,12 +22,12 @@ */ #define FLEX_SCANNER -#ifdef __WIN__ +#ifdef _WIN32 #define __STDC__ 1 #define isatty _isatty #endif #include -#ifndef __WIN__ +#ifndef _WIN32 #include #endif diff --git a/storage/connect/global.h b/storage/connect/global.h index 8774285e54b..eb3d4106477 100644 --- a/storage/connect/global.h +++ b/storage/connect/global.h @@ -14,11 +14,11 @@ #include /* time_t type declaration */ #include /* Long jump declarations */ -#if defined(__WIN__) && !defined(NOEX) +#if defined(_WIN32) && !defined(NOEX) #define DllExport __declspec( dllexport ) -#else // !__WIN__ +#else // !_WIN32 #define DllExport -#endif // !__WIN__ +#endif // !_WIN32 #if defined(DOMDOC_SUPPORT) || defined(LIBXML2_SUPPORT) #define XML_SUPPORT 1 @@ -43,11 +43,11 @@ #define STEP(I) MSG_##I #endif // !XMSG and !NEWMSG -#if defined(__WIN__) +#if defined(_WIN32) #define CRLF 2 -#else // !__WIN__ +#else // !_WIN32 #define CRLF 1 -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Define access to the thread based trace value. */ @@ -204,9 +204,9 @@ DllExport char *PlugReadMessage(PGLOBAL, int, char *); #elif defined(NEWMSG) DllExport char *PlugGetMessage(PGLOBAL, int); #endif // XMSG || NEWMSG -#if defined(__WIN__) +#if defined(_WIN32) DllExport short GetLineLength(PGLOBAL); // Console line length -#endif // __WIN__ +#endif // _WIN32 DllExport PGLOBAL PlugInit(LPCSTR, size_t); // Plug global initialization DllExport PGLOBAL PlugExit(PGLOBAL); // Plug global termination DllExport LPSTR PlugRemoveType(LPSTR, LPCSTR); diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 416bbb5d071..01fe7a6d2b3 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -139,10 +139,10 @@ //#include "reldef.h" #include "tabcol.h" #include "xindex.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include "tabwmi.h" -#endif // __WIN__ +#endif // _WIN32 #include "connect.h" #include "user_connect.h" #include "ha_connect.h" @@ -170,13 +170,13 @@ #define JSONMAX 50 // JSON Default max grp size extern "C" { - char version[]= "Version 1.07.0003 May 22, 2021"; -#if defined(__WIN__) + char version[]= "Version 1.07.0003 June 06, 2021"; +#if defined(_WIN32) char compver[]= "Version 1.07.0003 " __DATE__ " " __TIME__; char slash= '\\'; -#else // !__WIN__ +#else // !_WIN32 char slash= '/'; -#endif // !__WIN__ +#endif // !_WIN32 } // extern "C" #if MYSQL_VERSION_ID > 100200 @@ -802,11 +802,11 @@ static int connect_init_func(void *p) } #endif // 0 (LINUX) -#if defined(__WIN__) +#if defined(_WIN32) sql_print_information("CONNECT: %s", compver); -#else // !__WIN__ +#else // !_WIN32 sql_print_information("CONNECT: %s", version); -#endif // !__WIN__ +#endif // !_WIN32 pthread_mutex_init(&parmut, NULL); pthread_mutex_init(&usrmut, NULL); pthread_mutex_init(&tblmut, NULL); @@ -865,9 +865,9 @@ static int connect_done_func(void *) JAVAConn::ResetJVM(); #endif // JAVA_SUPPORT -#if !defined(__WIN__) +#if !defined(_WIN32) PROFILE_End(); -#endif // !__WIN__ +#endif // !_WIN32 pthread_mutex_lock(&usrmut); for (pc= user_connect::to_users; pc; pc= pn) { @@ -941,11 +941,11 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg) xp= (table) ? GetUser(ha_thd(), NULL) : NULL; if (xp) xp->SetHandler(this); -#if defined(__WIN__) +#if defined(_WIN32) datapath= ".\\"; -#else // !__WIN__ +#else // !_WIN32 datapath= "./"; -#endif // !__WIN__ +#endif // !_WIN32 tdbp= NULL; sdvalin1= sdvalin2= sdvalin3= sdvalin4= NULL; sdvalout= NULL; @@ -4549,11 +4549,11 @@ static bool checkPrivileges(THD *thd, TABTYPE type, PTOS options, strcpy(dbpath, mysql_real_data_home); if (db) -#if defined(__WIN__) +#if defined(_WIN32) strcat(strcat(dbpath, db), "\\"); -#else // !__WIN__ +#else // !_WIN32 strcat(strcat(dbpath, db), "/"); -#endif // !__WIN__ +#endif // !_WIN32 (void)fn_format(path, options->filename, dbpath, "", MY_RELATIVE_PATH | MY_UNPACK_FILENAME); @@ -5607,9 +5607,9 @@ static int connect_assisted_discovery(handlerton *, THD* thd, PCSZ user, fn, db, host, pwd, sep, tbl, src; PCSZ col, ocl, rnk, pic, fcl, skc, zfn; char *tab, *dsn, *shm, *dpath, *url; -#if defined(__WIN__) +#if defined(_WIN32) PCSZ nsp= NULL, cls= NULL; -#endif // __WIN__ +#endif // _WIN32 //int hdr, mxe; int port= 0, mxr= 0, rc= 0, mul= 0, lrecl= 0; //PCSZ tabtyp= NULL; @@ -5670,10 +5670,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, skc= GetListOption(g, "skipcol", topt->oplist, NULL); rnk= GetListOption(g, "rankcol", topt->oplist, NULL); pwd= GetListOption(g, "password", topt->oplist); -#if defined(__WIN__) +#if defined(_WIN32) nsp= GetListOption(g, "namespace", topt->oplist); cls= GetListOption(g, "class", topt->oplist); -#endif // __WIN__ +#endif // _WIN32 port= atoi(GetListOption(g, "port", topt->oplist, "0")); #if defined(ODBC_SUPPORT) // tabtyp= GetListOption(g, "Tabtype", topt->oplist, NULL); @@ -5904,11 +5904,11 @@ static int connect_assisted_discovery(handlerton *, THD* thd, ok= false; break; -#if defined(__WIN__) +#if defined(_WIN32) case TAB_WMI: ok= true; break; -#endif // __WIN__ +#endif // _WIN32 case TAB_PIVOT: supfnc= FNC_NO; case TAB_PRX: @@ -6072,11 +6072,11 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case TAB_CSV: qrp= CSVColumns(g, dpath, topt, fnc == FNC_COL); break; -#if defined(__WIN__) +#if defined(_WIN32) case TAB_WMI: qrp= WMIColumns(g, nsp, cls, fnc == FNC_COL); break; -#endif // __WIN__ +#endif // _WIN32 case TAB_PRX: case TAB_TBL: case TAB_XCL: @@ -6606,11 +6606,11 @@ int ha_connect::create(const char *name, TABLE *table_arg, // on Windows and libxml2 otherwise switch (toupper(*xsup)) { case '*': -#if defined(__WIN__) +#if defined(_WIN32) dom= true; -#else // !__WIN__ +#else // !_WIN32 dom= false; -#endif // !__WIN__ +#endif // !_WIN32 break; case 'M': case 'D': @@ -6993,11 +6993,11 @@ bool ha_connect::FileExists(const char *fn, bool bf) int n; struct stat info; -#if defined(__WIN__) +#if defined(_WIN32) s= "\\"; -#else // !__WIN__ +#else // !_WIN32 s= "/"; -#endif // !__WIN__ +#endif // !_WIN32 if (IsPartitioned()) { sprintf(tfn, fn, GetPartName()); diff --git a/storage/connect/javaconn.cpp b/storage/connect/javaconn.cpp index 34b844f59b0..2b288e3cdc6 100644 --- a/storage/connect/javaconn.cpp +++ b/storage/connect/javaconn.cpp @@ -6,24 +6,24 @@ /* This file contains the JAVA connection classes functions. */ /***********************************************************************/ -#if defined(__WIN__) +#if defined(_WIN32) // This is needed for RegGetValue #define _WINVER 0x0601 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0601 -#endif // __WIN__ +#endif // _WIN32 /***********************************************************************/ /* Include relevant MariaDB header file. */ /***********************************************************************/ #include //#include -#if defined(__WIN__) +#if defined(_WIN32) #include // for getcwd #if defined(__BORLANDC__) #define __MFC_COMPAT__ // To define min/max as macro #endif // __BORLANDC__ -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) #include #else // !UNIX @@ -31,7 +31,7 @@ #include #include // for getenv #define NODW -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Required objects includes. */ @@ -47,9 +47,9 @@ #include "valblk.h" #include "osutil.h" -#if defined(__WIN__) +#if defined(_WIN32) extern "C" HINSTANCE s_hModule; // Saved module handle -#endif // __WIN__ +#endif // _WIN32 #define nullptr 0 //TYPCONV GetTypeConv(); @@ -200,11 +200,11 @@ int JAVAConn::GetMaxValue(int n) void JAVAConn::ResetJVM(void) { if (LibJvm) { -#if defined(__WIN__) +#if defined(_WIN32) FreeLibrary((HMODULE)LibJvm); -#else // !__WIN__ +#else // !_WIN32 dlclose(LibJvm); -#endif // !__WIN__ +#endif // !_WIN32 LibJvm = NULL; CreateJavaVM = NULL; GetCreatedJavaVMs = NULL; @@ -227,7 +227,7 @@ bool JAVAConn::GetJVM(PGLOBAL g) if (!LibJvm) { char soname[512]; -#if defined(__WIN__) +#if defined(_WIN32) for (ntry = 0; !LibJvm && ntry < 3; ntry++) { if (!ntry && JvmPath) { strcat(strcpy(soname, JvmPath), "\\jvm.dll"); @@ -295,7 +295,7 @@ bool JAVAConn::GetJVM(PGLOBAL g) LibJvm = NULL; #endif // _DEBUG } // endif LibJvm -#else // !__WIN__ +#else // !_WIN32 const char *error = NULL; for (ntry = 0; !LibJvm && ntry < 2; ntry++) { @@ -336,7 +336,7 @@ bool JAVAConn::GetJVM(PGLOBAL g) LibJvm = NULL; #endif // _DEBUG } // endif LibJvm -#endif // !__WIN__ +#endif // !_WIN32 } // endif LibJvm @@ -378,7 +378,7 @@ bool JAVAConn::Open(PGLOBAL g) char *cp = NULL; char sep; -#if defined(__WIN__) +#if defined(_WIN32) sep = ';'; #define N 1 //#define N 2 diff --git a/storage/connect/javaconn.h b/storage/connect/javaconn.h index 73812f6ab3b..963b8c1a6ac 100644 --- a/storage/connect/javaconn.h +++ b/storage/connect/javaconn.h @@ -27,9 +27,9 @@ //efine MAX_CURSOR_NAME 18 // Max size of a cursor name //efine DEFAULT_FIELD_TYPE 0 // TYPE_NULL -#if !defined(__WIN__) +#if !defined(_WIN32) typedef unsigned char *PUCHAR; -#endif // !__WIN__ +#endif // !_WIN32 enum JCATINFO { JCAT_TAB = 1, // JDBC Tables @@ -104,11 +104,11 @@ public: protected: // Members -#if defined(__WIN__) +#if defined(_WIN32) static HANDLE LibJvm; // Handle to the jvm DLL -#else // !__WIN__ +#else // !_WIN32 static void *LibJvm; // Handle for the jvm shared library -#endif // !__WIN__ +#endif // !_WIN32 static CRTJVM CreateJavaVM; static GETJVM GetCreatedJavaVMs; #if defined(_DEBUG) diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index 2cb75e0adc1..20918745316 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -6,19 +6,19 @@ /* This file contains the JDBC connection classes functions. */ /***********************************************************************/ -#if defined(__WIN__) +#if defined(_WIN32) // This is needed for RegGetValue #define _WINVER 0x0601 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0601 -#endif // __WIN__ +#endif // _WIN32 /***********************************************************************/ /* Include relevant MariaDB header file. */ /***********************************************************************/ #include #include -#if defined(__WIN__) +#if defined(_WIN32) //nclude //nclude #include // for getcwd @@ -26,7 +26,7 @@ #define __MFC_COMPAT__ // To define min/max as macro #endif // __BORLANDC__ //#include -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) #include #else // !UNIX @@ -36,7 +36,7 @@ #include // for getenv //nclude #define NODW -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Required objects includes. */ @@ -53,9 +53,9 @@ #include "osutil.h" -//#if defined(__WIN__) +//#if defined(_WIN32) //extern "C" HINSTANCE s_hModule; // Saved module handle -//#endif // __WIN__ +//#endif // _WIN32 #define nullptr 0 TYPCONV GetTypeConv(); diff --git a/storage/connect/jmgfam.cpp b/storage/connect/jmgfam.cpp index d7f469cf4fe..670781da6f5 100644 --- a/storage/connect/jmgfam.cpp +++ b/storage/connect/jmgfam.cpp @@ -17,7 +17,7 @@ /* Include relevant sections of the System header files. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) //#include //#include //#include @@ -25,7 +25,7 @@ #define __MFC_COMPAT__ // To define min/max as macro #endif // __BORLANDC__ //#include -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) || defined(UNIV_LINUX) //#include #include @@ -36,7 +36,7 @@ //#include #endif // !UNIX //#include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include application header files: */ diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index b376a8c5c27..9b7145bb498 100644 --- a/storage/connect/json.cpp +++ b/storage/connect/json.cpp @@ -23,7 +23,7 @@ #define ARGS MY_MIN(24,(int)len-i),s+MY_MAX(i-3,0) -#if defined(__WIN__) +#if defined(_WIN32) #define EL "\r\n" #else #define EL "\n" diff --git a/storage/connect/macutil.cpp b/storage/connect/macutil.cpp index f95f3adcc6e..93cd0bcb5e1 100644 --- a/storage/connect/macutil.cpp +++ b/storage/connect/macutil.cpp @@ -2,11 +2,11 @@ /* MACUTIL: Author Olivier Bertrand -- 2008-2012 */ /* From the article and sample code by Khalid Shaikh. */ /***********************************************************************/ -#if defined(__WIN__) +#if defined(_WIN32) #include "my_global.h" -#else // !__WIN__ +#else // !_WIN32 #error This is WINDOWS only DLL -#endif // !__WIN__ +#endif // !_WIN32 #include "global.h" #include "plgdbsem.h" #include "macutil.h" diff --git a/storage/connect/macutil.h b/storage/connect/macutil.h index c80bd58e20a..69a785dc9da 100644 --- a/storage/connect/macutil.h +++ b/storage/connect/macutil.h @@ -1,10 +1,10 @@ // MACUTIL.H Olivier Bertrand 2008-2012 // Get Mac Addresses via GetAdaptersInfo -#if defined(__WIN__) +#if defined(_WIN32) #include -#else // !__WIN__ +#else // !_WIN32 #error This is WINDOWS only -#endif // !__WIN__ +#endif // !_WIN32 #include "block.h" typedef class MACINFO *MACIP; diff --git a/storage/connect/maputil.cpp b/storage/connect/maputil.cpp index 87263b3adf6..e4ad70f5032 100644 --- a/storage/connect/maputil.cpp +++ b/storage/connect/maputil.cpp @@ -14,7 +14,7 @@ #include "plgdbsem.h" #include "maputil.h" -#ifdef __WIN__ +#ifdef _WIN32 /***********************************************************************/ /* In Insert mode, just open the file for append. Otherwise */ /* create the mapping file object. The map handle can be released */ diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index 4a7e65eb01f..d4b182b4c64 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -62,10 +62,10 @@ #include "tabvct.h" #endif // VCT_SUPPORT #include "tabsys.h" -#if defined(__WIN__) +#if defined(_WIN32) #include "tabmac.h" #include "tabwmi.h" -#endif // __WIN__ +#endif // _WIN32 //#include "tabtbl.h" #include "tabxcl.h" #include "tabtbl.h" @@ -105,9 +105,9 @@ /***********************************************************************/ /* Extern static variables. */ /***********************************************************************/ -#if defined(__WIN__) +#if defined(_WIN32) extern "C" HINSTANCE s_hModule; // Saved module handle -#endif // !__WIN__ +#endif // !_WIN32 #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) bool MongoEnabled(void); #endif // JAVA_SUPPORT || CMGO_SUPPORT @@ -161,10 +161,10 @@ TABTYPE GetTypeID(const char *type) : (!stricmp(type, "MYSQL")) ? TAB_MYSQL : (!stricmp(type, "MYPRX")) ? TAB_MYSQL : (!stricmp(type, "DIR")) ? TAB_DIR -#if defined(__WIN__) +#if defined(_WIN32) : (!stricmp(type, "MAC")) ? TAB_MAC : (!stricmp(type, "WMI")) ? TAB_WMI -#endif // __WIN__ +#endif // _WIN32 : (!stricmp(type, "TBL")) ? TAB_TBL : (!stricmp(type, "XCOL")) ? TAB_XCL : (!stricmp(type, "OCCUR")) ? TAB_OCCUR @@ -383,11 +383,11 @@ uint GetFuncID(const char *func) /***********************************************************************/ CATALOG::CATALOG(void) { -#if defined(__WIN__) +#if defined(_WIN32) //DataPath= ".\\"; -#else // !__WIN__ +#else // !_WIN32 //DataPath= "./"; -#endif // !__WIN__ +#endif // !_WIN32 memset(&Ctb, 0, sizeof(CURTAB)); Cbuf= NULL; Cblen= 0; @@ -481,10 +481,10 @@ PTABDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am) #if defined(JAVA_SUPPORT) case TAB_JDBC: tdp= new(g) JDBCDEF; break; #endif // JAVA_SUPPORT -#if defined(__WIN__) +#if defined(_WIN32) case TAB_MAC: tdp= new(g) MACDEF; break; case TAB_WMI: tdp= new(g) WMIDEF; break; -#endif // __WIN__ +#endif // _WIN32 case TAB_OEM: tdp= new(g) OEMDEF; break; case TAB_TBL: tdp= new(g) TBLDEF; break; case TAB_XCL: tdp= new(g) XCLDEF; break; diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index 4303a9e191b..945c4e698be 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -35,11 +35,11 @@ #include "my_sys.h" #include "mysqld_error.h" #endif // !MYSQL_PREPARED_STATEMENTS -#if defined(__WIN__) +#if defined(_WIN32) //#include -#else // !__WIN__ +#else // !_WIN32 #include "osutil.h" -#endif // !__WIN__ +#endif // !_WIN32 #include "global.h" #include "plgdbsem.h" @@ -492,15 +492,15 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db, //mysql_options(m_DB, MYSQL_OPT_READ_TIMEOUT, &nrt); //mysql_options(m_DB, MYSQL_OPT_WRITE_TIMEOUT, ...); -#if defined(__WIN__) +#if defined(_WIN32) if (!strcmp(host, ".")) { mysql_options(m_DB, MYSQL_OPT_NAMED_PIPE, NULL); pipe = mysqld_unix_port; } // endif host -#else // !__WIN__ +#else // !_WIN32 if (!strcmp(host, "localhost")) pipe = mysqld_unix_port; -#endif // !__WIN__ +#endif // !_WIN32 #if 0 if (pwd && !strcmp(pwd, "*")) { diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h index 9ebd37527a6..5f64f933878 100644 --- a/storage/connect/myconn.h +++ b/storage/connect/myconn.h @@ -7,24 +7,24 @@ /* DO NOT define DLL_EXPORT in your application so these items are */ /* declared are imported from the Myconn DLL. */ /***********************************************************************/ -#if defined(__WIN__) +#if defined(_WIN32) #include -#else // !__WIN__ +#else // !_WIN32 #include -#endif // !__WIN__ +#endif // !_WIN32 #include #include #include "myutil.h" -#if defined(__WIN__) && defined(MYCONN_EXPORTS) +#if defined(_WIN32) && defined(MYCONN_EXPORTS) #if defined(DLL_EXPORT) #define DllItem _declspec(dllexport) #else // !DLL_EXPORT #define DllItem _declspec(dllimport) #endif // !DLL_EXPORT -#else // !__WIN__ || !MYCONN_EXPORTS +#else // !_WIN32 || !MYCONN_EXPORTS #define DllItem -#endif // !__WIN__ +#endif // !_WIN32 #define MYSQL_ENABLED 0x00000001 #define MYSQL_LOGON 0x00000002 diff --git a/storage/connect/mysql-test/connect/r/jdbc.result b/storage/connect/mysql-test/connect/r/jdbc.result index 0dbdf851860..b42311b8136 100644 --- a/storage/connect/mysql-test/connect/r/jdbc.result +++ b/storage/connect/mysql-test/connect/r/jdbc.result @@ -1,4 +1,5 @@ -SET GLOBAL time_zone='+1:00'; +SET GLOBAL time_zone='+0:00'; +SET time_zone='+0:00'; CREATE DATABASE connect; USE connect; CREATE TABLE t2 ( @@ -16,7 +17,7 @@ id msg tm dt dtm ts # Testing JDBC connection to MySQL driver # USE test; -CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=t2 CONNECTION='jdbc:mysql://localhost:PORT/connect?user=root'; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=t2 CONNECTION='jdbc:mysql://localhost:PORT/connect?user=root&useSSL=false'; SELECT * FROM t1; id msg tm dt dtm ts 455000000000 A very big number 18:10:25 2016-03-16 1999-12-11 23:01:52 2015-07-24 09:32:45 @@ -26,7 +27,7 @@ Note 1105 t2: 1 affected rows SELECT * FROM t1; id msg tm dt dtm ts 455000000000 A very big number 18:10:25 2016-03-16 1999-12-11 23:01:52 2015-07-24 09:32:45 -786325481247 Hello! 19:45:03 1933-08-09 1985-11-12 09:02:44 2014-06-17 10:32:01 +786325481247 Hello! 19:45:03 1933-08-10 1985-11-12 09:02:44 2014-06-17 10:32:01 DELETE FROM t1 WHERE msg = 'Hello!'; Warnings: Note 1105 t2: 1 affected rows @@ -37,7 +38,7 @@ DROP TABLE t1; # # Testing JDBC view # -CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC SRCDEF='select id, msg, tm, dt from t2' CONNECTION='jdbc:mysql://localhost:PORT/connect?user=root'; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC SRCDEF='select id, msg, tm, dt from t2' CONNECTION='jdbc:mysql://localhost:PORT/connect?user=root&useSSL=false'; SELECT * FROM t1; id msg tm dt 455000000000 A very big number 18:10:25 2016-03-16 @@ -74,7 +75,7 @@ SELECT * FROM t3; name city birth hired Donald Atlanta 1999-04-01 2016-03-31 Mick New York 1980-01-20 2002-09-11 -CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=boys CONNECTION='jdbc:mysql://localhost:PORT/connect?user=root' OPTION_LIST='scrollable=1'; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=boys CONNECTION='jdbc:mysql://localhost:PORT/connect?user=root&useSSL=false' OPTION_LIST='scrollable=1'; SELECT * FROM t1; name city birth hired John Boston 1986-01-25 2010-06-02 @@ -100,9 +101,9 @@ George San Jose 1981-08-10 2010-06-02 Sam Chicago 1979-11-22 2007-10-10 James Dallas 1992-05-13 2009-12-14 Bill Boston 1986-09-11 2008-02-10 -Donald Atlanta 1999-03-31 2016-03-30 -Mick New York 1980-01-20 2002-09-10 -Tom Seatle 2002-03-15 1970-01-01 +Donald Atlanta 1999-04-01 2016-03-31 +Mick New York 1980-01-20 2002-09-11 +Tom Seatle 2002-03-15 NULL DROP TABLE t3; # # Testing JDBC join operations @@ -280,3 +281,4 @@ DROP TABLE t1; DROP TABLE connect.tx1; DROP DATABASE connect; SET GLOBAL time_zone=SYSTEM; +SET time_zone=SYSTEM; diff --git a/storage/connect/mysql-test/connect/r/jdbc_new.result b/storage/connect/mysql-test/connect/r/jdbc_new.result index 33d8bd3b7d8..a47fb9ccaf9 100644 --- a/storage/connect/mysql-test/connect/r/jdbc_new.result +++ b/storage/connect/mysql-test/connect/r/jdbc_new.result @@ -2,7 +2,8 @@ connect master,127.0.0.1,root,,test,$MASTER_MYPORT,; connect slave,127.0.0.1,root,,test,$SLAVE_MYPORT,; connection master; connection slave; -SET GLOBAL time_zone='+1:00'; +SET GLOBAL time_zone='+0:00'; +SET time_zone='+0:00'; CREATE TABLE t1 (a int, b char(10)); INSERT INTO t1 VALUES (NULL,NULL),(0,'test00'),(1,'test01'),(2,'test02'),(3,'test03'); SELECT * FROM t1; @@ -16,31 +17,32 @@ NULL NULL # Testing errors # connection master; -SET GLOBAL time_zone='+1:00'; +SET GLOBAL time_zone='+0:00'; +SET time_zone='+0:00'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC -CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=unknown'; +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=unknown&useSSL=false'; ERROR HY000: Connecting: java.sql.SQLException: Access denied for user 'unknown'@'localhost' (using password: NO) rc=-2 CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC -CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/unknown?user=root'; +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/unknown?user=root&useSSL=false'; ERROR HY000: Connecting: java.sql.SQLSyntaxErrorException: Unknown database 'unknown' rc=-2 CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='unknown' - CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false'; ERROR HY000: Cannot get columns from unknown SHOW CREATE TABLE t1; ERROR 42S02: Table 'test.t1' doesn't exist CREATE TABLE t1 (x int, y char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC -CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `x` int(11) DEFAULT NULL, `y` char(10) DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`=JDBC +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false' `TABLE_TYPE`=JDBC SELECT * FROM t1; ERROR HY000: Got error 174 'ExecuteQuery: java.sql.SQLSyntaxErrorException: Unknown column 'x' in 'field list'' from CONNECT DROP TABLE t1; CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC -CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false'; connection slave; ALTER TABLE t1 RENAME t1backup; connection master; @@ -54,13 +56,13 @@ DROP TABLE t1; # Testing SELECT, etc. # CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC -CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(10) DEFAULT NULL, `b` char(10) DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`='JDBC' +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false' `TABLE_TYPE`='JDBC' SELECT * FROM t1; a b NULL NULL @@ -70,13 +72,13 @@ NULL NULL 3 test03 DROP TABLE t1; CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='t1' - CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` char(10) DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`=JDBC `TABNAME`='t1' +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false' `TABLE_TYPE`=JDBC `TABNAME`='t1' SELECT * FROM t1; a b NULL NULL @@ -86,13 +88,13 @@ NULL NULL 3 test03 DROP TABLE t1; CREATE TABLE t1 (a INT NOT NULL, b CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=JDBC -CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, `b` char(10) NOT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`=JDBC +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false' `TABLE_TYPE`=JDBC SELECT * FROM t1; a b 0 @@ -102,13 +104,13 @@ a b 3 test03 DROP TABLE t1; CREATE TABLE t1 (a char(10), b int) ENGINE=CONNECT TABLE_TYPE=JDBC -CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` char(10) DEFAULT NULL, `b` int(11) DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`=JDBC +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false' `TABLE_TYPE`=JDBC SELECT * FROM t1; a b NULL NULL @@ -138,7 +140,7 @@ t1 CREATE TABLE `t1` ( INSERT INTO t1 VALUES(100,3333,41235,1234567890,235000000000,3.14159265,3.14159265,3141.59265); connection master; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC -CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -150,7 +152,7 @@ t1 CREATE TABLE `t1` ( `f` double(14,0) DEFAULT NULL, `g` double(24,0) DEFAULT NULL, `h` decimal(27,5) DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`='JDBC' +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false' `TABLE_TYPE`='JDBC' SELECT * FROM t1; a b c d e f g h 100 3333 41235 1234567890 235000000000 3 3 3141.59265 @@ -173,13 +175,13 @@ a b Welcome Hello, World connection master; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC -CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` char(12) DEFAULT NULL, `b` varchar(12) DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`='JDBC' +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false' `TABLE_TYPE`='JDBC' SELECT * FROM t1; a b Welcome Hello, World @@ -209,7 +211,7 @@ a b c d e 2003-05-27 2003-05-27 10:45:23 10:45:23 2003-05-27 10:45:23 2003 connection master; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC -CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -218,13 +220,15 @@ t1 CREATE TABLE `t1` ( `c` time DEFAULT NULL, `d` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `e` year(4) DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`='JDBC' +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root&useSSL=false' `TABLE_TYPE`='JDBC' SELECT * FROM t1; a b c d e -2003-05-27 2003-05-27 11:45:23 10:45:23 2003-05-27 10:45:23 2003 +2003-05-27 2003-05-27 10:45:23 10:45:23 2003-05-27 10:45:23 2003 DROP TABLE t1; connection slave; DROP TABLE t1; SET GLOBAL time_zone=SYSTEM; +SET time_zone=SYSTEM; connection master; SET GLOBAL time_zone=SYSTEM; +SET time_zone=SYSTEM; diff --git a/storage/connect/mysql-test/connect/t/jdbc.test b/storage/connect/mysql-test/connect/t/jdbc.test index 58a527a3e6b..79809f4eaf3 100644 --- a/storage/connect/mysql-test/connect/t/jdbc.test +++ b/storage/connect/mysql-test/connect/t/jdbc.test @@ -1,6 +1,7 @@ -- source windows.inc -- source jdbconn.inc -SET GLOBAL time_zone='+1:00'; +SET GLOBAL time_zone='+0:00'; +SET time_zone='+0:00'; let $MYSQLD_DATADIR= `select @@datadir`; --copy_file $MTR_SUITE_DIR/std_data/girls.txt $MYSQLD_DATADIR/test/girls.txt @@ -27,7 +28,7 @@ SELECT * FROM t2; --echo # USE test; --replace_result $PORT PORT ---eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=t2 CONNECTION='jdbc:mysql://localhost:$PORT/connect?user=root' +--eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=t2 CONNECTION='jdbc:mysql://localhost:$PORT/connect?user=root&useSSL=false' SELECT * FROM t1; INSERT INTO t1 VALUES(786325481247, 'Hello!', '19:45:03', '1933-08-10', '1985-11-12 09:02:44', '2014-06-17 10:32:01'); SELECT * FROM t1; @@ -39,7 +40,7 @@ DROP TABLE t1; --echo # Testing JDBC view --echo # --replace_result $PORT PORT ---eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC SRCDEF='select id, msg, tm, dt from t2' CONNECTION='jdbc:mysql://localhost:$PORT/connect?user=root' +--eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC SRCDEF='select id, msg, tm, dt from t2' CONNECTION='jdbc:mysql://localhost:$PORT/connect?user=root&useSSL=false' SELECT * FROM t1; SELECT msg, dt FROM t1; DROP TABLE t1, connect.t2; @@ -67,7 +68,7 @@ INSERT INTO t3 VALUES('Donald','Atlanta','1999-04-01','2016-03-31'),('Mick','New SELECT * FROM t3; --replace_result $PORT PORT ---eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=boys CONNECTION='jdbc:mysql://localhost:$PORT/connect?user=root' OPTION_LIST='scrollable=1' +--eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=boys CONNECTION='jdbc:mysql://localhost:$PORT/connect?user=root&useSSL=false' OPTION_LIST='scrollable=1' SELECT * FROM t1; UPDATE t1 SET city = 'Phoenix' WHERE name = 'Henry'; INSERT INTO t1 SELECT * FROM t3; @@ -145,4 +146,5 @@ DROP TABLE connect.tx1; DROP DATABASE connect; --remove_file $MYSQLD_DATADIR/test/girls.txt SET GLOBAL time_zone=SYSTEM; +SET time_zone=SYSTEM; -- source jdbconn_cleanup.inc diff --git a/storage/connect/mysql-test/connect/t/jdbc_new.test b/storage/connect/mysql-test/connect/t/jdbc_new.test index 36e8f36ced0..1eaafdfbf43 100644 --- a/storage/connect/mysql-test/connect/t/jdbc_new.test +++ b/storage/connect/mysql-test/connect/t/jdbc_new.test @@ -9,7 +9,8 @@ connection master; -- source jdbconn.inc connection slave; -SET GLOBAL time_zone='+1:00'; +SET GLOBAL time_zone='+0:00'; +SET time_zone='+0:00'; CREATE TABLE t1 (a int, b char(10)); INSERT INTO t1 VALUES (NULL,NULL),(0,'test00'),(1,'test01'),(2,'test02'),(3,'test03'); @@ -19,33 +20,34 @@ SELECT * FROM t1; --echo # Testing errors --echo # connection master; -SET GLOBAL time_zone='+1:00'; +SET GLOBAL time_zone='+0:00'; +SET time_zone='+0:00'; # Bad user name # Suppress "mysql_real_connect failed:" (printed in _DEBUG build) --replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " "" --error ER_UNKNOWN_ERROR eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC - CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=unknown'; + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=unknown&useSSL=false'; # Bad database name --replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " "" --error ER_UNKNOWN_ERROR eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC - CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/unknown?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/unknown?user=root&useSSL=false'; # Bad table name --replace_result $SLAVE_MYPORT SLAVE_PORT --error ER_UNKNOWN_ERROR eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='unknown' - CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root&useSSL=false'; --error ER_NO_SUCH_TABLE SHOW CREATE TABLE t1; # Bad column name --replace_result $SLAVE_MYPORT SLAVE_PORT eval CREATE TABLE t1 (x int, y char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC - CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root&useSSL=false'; --replace_result $SLAVE_MYPORT SLAVE_PORT SHOW CREATE TABLE t1; --error ER_GET_ERRMSG @@ -55,7 +57,7 @@ DROP TABLE t1; # The remote table disappeared --replace_result $SLAVE_MYPORT SLAVE_PORT eval CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC - CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root&useSSL=false'; connection slave; ALTER TABLE t1 RENAME t1backup; @@ -77,7 +79,7 @@ DROP TABLE t1; # Automatic table structure --replace_result $SLAVE_MYPORT SLAVE_PORT eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC - CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root&useSSL=false'; --replace_result $SLAVE_MYPORT SLAVE_PORT SHOW CREATE TABLE t1; SELECT * FROM t1; @@ -86,7 +88,7 @@ DROP TABLE t1; # Explicit table structure --replace_result $SLAVE_MYPORT SLAVE_PORT eval CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='t1' - CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root&useSSL=false'; --replace_result $SLAVE_MYPORT SLAVE_PORT SHOW CREATE TABLE t1; SELECT * FROM t1; @@ -95,7 +97,7 @@ DROP TABLE t1; # Explicit table structure: remote NULL, local NOT NULL --replace_result $SLAVE_MYPORT SLAVE_PORT eval CREATE TABLE t1 (a INT NOT NULL, b CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=JDBC - CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root&useSSL=false'; --replace_result $SLAVE_MYPORT SLAVE_PORT SHOW CREATE TABLE t1; SELECT * FROM t1; @@ -104,7 +106,7 @@ DROP TABLE t1; # Explicit table structure with wrong column types --replace_result $SLAVE_MYPORT SLAVE_PORT eval CREATE TABLE t1 (a char(10), b int) ENGINE=CONNECT TABLE_TYPE=JDBC - CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root&useSSL=false'; --replace_result $SLAVE_MYPORT SLAVE_PORT SHOW CREATE TABLE t1; SELECT * FROM t1; @@ -125,7 +127,7 @@ INSERT INTO t1 VALUES(100,3333,41235,1234567890,235000000000,3.14159265,3.141592 connection master; --replace_result $SLAVE_MYPORT SLAVE_PORT eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC - CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root&useSSL=false'; --replace_result $SLAVE_MYPORT SLAVE_PORT SHOW CREATE TABLE t1; SELECT * FROM t1; @@ -146,7 +148,7 @@ SELECT * FROM t1; connection master; --replace_result $SLAVE_MYPORT SLAVE_PORT eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC - CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root&useSSL=false'; --replace_result $SLAVE_MYPORT SLAVE_PORT SHOW CREATE TABLE t1; SELECT * FROM t1; @@ -167,7 +169,7 @@ SELECT * FROM t1; connection master; --replace_result $SLAVE_MYPORT SLAVE_PORT eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC - CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root&useSSL=false'; --replace_result $SLAVE_MYPORT SLAVE_PORT SHOW CREATE TABLE t1; SELECT * FROM t1; @@ -176,8 +178,10 @@ DROP TABLE t1; connection slave; DROP TABLE t1; SET GLOBAL time_zone=SYSTEM; +SET time_zone=SYSTEM; connection master; SET GLOBAL time_zone=SYSTEM; +SET time_zone=SYSTEM; -- source jdbconn_cleanup.inc diff --git a/storage/connect/myutil.cpp b/storage/connect/myutil.cpp index ed25abc4bc5..1c73ded5e05 100644 --- a/storage/connect/myutil.cpp +++ b/storage/connect/myutil.cpp @@ -13,11 +13,11 @@ /************************************************************************/ #include "my_global.h" #include -#if defined(__WIN__) +#if defined(_WIN32) //#include -#else // !__WIN__ +#else // !_WIN32 #include "osutil.h" -#endif // !__WIN__ +#endif // !_WIN32 #include "global.h" #include "plgdbsem.h" diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index d08c6d1b7a5..5b20b33e240 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -11,7 +11,7 @@ /***********************************************************************/ #include #include -#if defined(__WIN__) +#if defined(_WIN32) //nclude //nclude #include // for getcwd @@ -45,13 +45,13 @@ #include "osutil.h" -#if defined(__WIN__) +#if defined(_WIN32) /***********************************************************************/ /* For dynamic load of ODBC32.DLL */ /***********************************************************************/ #pragma comment(lib, "odbc32.lib") extern "C" HINSTANCE s_hModule; // Saved module handle -#endif // __WIN__ +#endif // _WIN32 TYPCONV GetTypeConv(); int GetConvSize(); @@ -1280,15 +1280,15 @@ bool ODBConn::DriverConnect(DWORD Options) SWORD nResult; PUCHAR ConnOut = (PUCHAR)PlugSubAlloc(m_G, NULL, MAX_CONNECT_LEN); UWORD wConnectOption = SQL_DRIVER_COMPLETE; -#if defined(__WIN__) +#if defined(_WIN32) HWND hWndTop = GetForegroundWindow(); HWND hWnd = GetParent(hWndTop); if (hWnd == NULL) hWnd = GetDesktopWindow(); -#else // !__WIN__ +#else // !_WIN32 HWND hWnd = (HWND)1; -#endif // !__WIN__ +#endif // !_WIN32 PGLOBAL& g = m_G; PDBUSER dup = PlgGetUser(g); @@ -1301,10 +1301,10 @@ bool ODBConn::DriverConnect(DWORD Options) SQL_NTS, ConnOut, MAX_CONNECT_LEN, &nResult, wConnectOption); -#if defined(__WIN__) +#if defined(_WIN32) if (hWndTop) EnableWindow(hWndTop, true); -#endif // __WIN__ +#endif // _WIN32 // If user hit 'Cancel' if (rc == SQL_NO_DATA_FOUND) { diff --git a/storage/connect/odbconn.h b/storage/connect/odbconn.h index f98c67bd12f..7038f06e5f3 100644 --- a/storage/connect/odbconn.h +++ b/storage/connect/odbconn.h @@ -29,9 +29,9 @@ //efine MAX_CURSOR_NAME 18 // Max size of a cursor name //efine DEFAULT_FIELD_TYPE SQL_TYPE_NULL // pick "C" data type to match SQL data type -#if !defined(__WIN__) +#if !defined(_WIN32) typedef unsigned char *PUCHAR; -#endif // !__WIN__ +#endif // !_WIN32 // Field Flags, used to indicate status of fields //efine SQL_FIELD_FLAG_DIRTY 0x1 diff --git a/storage/connect/os.h b/storage/connect/os.h index 797692d47b2..7d0d5cabbb6 100644 --- a/storage/connect/os.h +++ b/storage/connect/os.h @@ -16,19 +16,19 @@ typedef off_t off64_t; #endif #endif -#if defined(__WIN__) +#if defined(_WIN32) typedef __int64 BIGINT; typedef _Null_terminated_ const char *PCSZ; -#else // !__WIN__ +#else // !_WIN32 typedef longlong BIGINT; #define FILE_BEGIN SEEK_SET #define FILE_CURRENT SEEK_CUR #define FILE_END SEEK_END typedef const char *PCSZ; -#endif // !__WIN__ +#endif // !_WIN32 -#if !defined(__WIN__) +#if !defined(_WIN32) typedef const void *LPCVOID; typedef const char *LPCTSTR; typedef const char *LPCSTR; @@ -65,6 +65,6 @@ typedef int HANDLE; #define _MAX_EXT FN_EXTLEN #define INVALID_HANDLE_VALUE (-1) #define __stdcall -#endif /* !__WIN__ */ +#endif /* !_WIN32 */ #endif /* _OS_H_INCLUDED */ diff --git a/storage/connect/osutil.c b/storage/connect/osutil.c index da896fec50e..278023f55a2 100644 --- a/storage/connect/osutil.c +++ b/storage/connect/osutil.c @@ -5,7 +5,7 @@ #include #include "osutil.h" -#ifdef __WIN__ +#ifdef _WIN32 my_bool CloseFileHandle(HANDLE h) { return !CloseHandle(h); diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index dd204d065ed..370bf69ffa0 100644 --- a/storage/connect/plgdbsem.h +++ b/storage/connect/plgdbsem.h @@ -581,11 +581,11 @@ typedef struct _colres { char Var; /* Type added information */ } COLRES; -#if defined(__WIN__) && !defined(NOEX) +#if defined(_WIN32) && !defined(NOEX) #define DllExport __declspec( dllexport ) -#else // !__WIN__ +#else // !_WIN32 #define DllExport -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Utility routines. */ diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index 7bc7c5f592b..6c1ce4ad6d3 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -39,12 +39,12 @@ /***********************************************************************/ #include "my_global.h" #include "my_pthread.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #include #define BIGMEM 1048576 // 1 Megabyte -#else // !__WIN__ +#else // !_WIN32 #include #include //#if defined(THREAD) @@ -52,7 +52,7 @@ //#endif // THREAD #include #define BIGMEM 2147483647 // Max int value -#endif // !__WIN__ +#endif // !_WIN32 #include /***********************************************************************/ @@ -89,11 +89,11 @@ extern "C" { extern char version[]; } // extern "C" -//#if defined(__WIN__) +//#if defined(_WIN32) //extern CRITICAL_SECTION parsec; // Used calling the Flex parser -//#else // !__WIN__ +//#else // !_WIN32 extern pthread_mutex_t parmut; -//#endif // !__WIN__ +//#endif // !_WIN32 // The debug trace used by the main thread FILE *pfile = NULL; @@ -386,11 +386,11 @@ char *SetPath(PGLOBAL g, const char *path) } // endif path if (*path != '.') { -#if defined(__WIN__) +#if defined(_WIN32) const char *s = "\\"; -#else // !__WIN__ +#else // !_WIN32 const char *s = "/"; -#endif // !__WIN__ +#endif // !_WIN32 strcat(strcat(strcat(strcpy(buf, "."), s), path), s); } else strcpy(buf, path); @@ -409,7 +409,7 @@ char *ExtractFromPath(PGLOBAL g, char *pBuff, char *FileName, OPVAL op) char *drive = NULL, *direc = NULL, *fname = NULL, *ftype = NULL; switch (op) { // Determine which part to extract -#if defined(__WIN__) +#if defined(_WIN32) case OP_FDISK: drive = pBuff; break; #endif // !UNIX case OP_FPATH: direc = pBuff; break; @@ -1249,7 +1249,7 @@ void *PlgDBalloc(PGLOBAL g, void *area, MBLOCK& mp) // For allocations greater than one fourth of remaining storage // in the area, do allocate from virtual storage. const char*v = "malloc"; -#if defined(__WIN__) +#if defined(_WIN32) if (mp.Size >= BIGMEM) { v = "VirtualAlloc"; mp.Memp = VirtualAlloc(NULL, mp.Size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); @@ -1352,7 +1352,7 @@ void PlgDBfree(MBLOCK& mp) { if (!mp.Sub && mp.Memp) { const char*v = "free"; -#if defined(__WIN__) +#if defined(_WIN32) if (mp.Size >= BIGMEM) { v = "VirtualFree"; VirtualFree(mp.Memp, 0, MEM_RELEASE); @@ -1554,11 +1554,11 @@ int FileComp(PGLOBAL g, char *file1, char *file2) bp[0] = buff1; bp[1] = buff2; for (i = 0; i < 2; i++) { -#if defined(__WIN__) +#if defined(_WIN32) h[i]= global_open(g, MSGID_NONE, fn[i], _O_RDONLY | _O_BINARY); -#else // !__WIN__ +#else // !_WIN32 h[i]= global_open(g, MSGOD_NONE, fn[i], O_RDONLY); -#endif // !__WIN__ +#endif // !_WIN32 if (h[i] == -1) { // if (errno != ENOENT) { diff --git a/storage/connect/plugutil.cpp b/storage/connect/plugutil.cpp index 9e1f006d605..4aecbadfc6a 100644 --- a/storage/connect/plugutil.cpp +++ b/storage/connect/plugutil.cpp @@ -44,7 +44,7 @@ /* */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) //#include #else #if defined(UNIX) || defined(UNIV_LINUX) @@ -81,9 +81,9 @@ #include "rcmsg.h" #endif // NEWMSG -#if defined(__WIN__) +#if defined(_WIN32) extern HINSTANCE s_hModule; /* Saved module handle */ -#endif // __WIN__ +#endif // _WIN32 #if defined(XMSG) extern char *msg_path; @@ -205,7 +205,7 @@ PGLOBAL PlugExit(PGLOBAL g) /***********************************************************************/ LPSTR PlugRemoveType(LPSTR pBuff, LPCSTR FileName) { -#if defined(__WIN__) +#if defined(_WIN32) char drive[_MAX_DRIVE]; #else char *drive = NULL; @@ -232,7 +232,7 @@ LPSTR PlugRemoveType(LPSTR pBuff, LPCSTR FileName) BOOL PlugIsAbsolutePath(LPCSTR path) { -#if defined(__WIN__) +#if defined(_WIN32) return ((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z')) && path[1] == ':'; #else @@ -250,7 +250,7 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath) char direc[_MAX_DIR], defdir[_MAX_DIR], tmpdir[_MAX_DIR]; char fname[_MAX_FNAME]; char ftype[_MAX_EXT]; -#if defined(__WIN__) +#if defined(_WIN32) char drive[_MAX_DRIVE], defdrv[_MAX_DRIVE]; #else char *drive = NULL, *defdrv = NULL; @@ -270,7 +270,7 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath) return pBuff; } // endif -#if !defined(__WIN__) +#if !defined(_WIN32) if (*FileName == '~') { if (_fullpath(pBuff, FileName, _MAX_PATH)) { if (trace(2)) @@ -281,7 +281,7 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath) return FileName; // Error, return unchanged name } // endif FileName -#endif // !__WIN__ +#endif // !_WIN32 if (prefix && strcmp(prefix, ".") && !PlugIsAbsolutePath(defpath)) { @@ -310,7 +310,7 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath) if (trace(2)) { htrc("after _splitpath: FileName=%s\n", FileName); -#if defined(__WIN__) +#if defined(_WIN32) htrc("drive=%s dir=%s fname=%s ext=%s\n", drive, direc, fname, ftype); htrc("defdrv=%s defdir=%s\n", defdrv, defdir); #else @@ -442,7 +442,7 @@ char *PlugGetMessage(PGLOBAL g, int mid) } // end of PlugGetMessage #endif // NEWMSG -#if defined(__WIN__) +#if defined(_WIN32) /***********************************************************************/ /* Return the line length of the console screen buffer. */ /***********************************************************************/ @@ -454,7 +454,7 @@ short GetLineLength(PGLOBAL g) return (b) ? coninfo.dwSize.X : 0; } // end of GetLineLength -#endif // __WIN__ +#endif // _WIN32 /***********************************************************************/ /* Program for memory allocation of work and language areas. */ @@ -464,7 +464,7 @@ bool AllocSarea(PGLOBAL g, size_t size) /*********************************************************************/ /* This is the allocation routine for the WIN32/UNIX/AIX version. */ /*********************************************************************/ -#if defined(__WIN__) +#if defined(_WIN32) if (size >= 1048576) // 1M g->Sarea = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); else @@ -500,7 +500,7 @@ bool AllocSarea(PGLOBAL g, size_t size) void FreeSarea(PGLOBAL g) { if (g->Sarea) { -#if defined(__WIN__) +#if defined(_WIN32) if (g->Sarea_Size >= 1048576) // 1M VirtualFree(g->Sarea, 0, MEM_RELEASE); else diff --git a/storage/connect/rcmsg.c b/storage/connect/rcmsg.c index 895f8f5862b..4cd443d88bb 100644 --- a/storage/connect/rcmsg.c +++ b/storage/connect/rcmsg.c @@ -21,9 +21,9 @@ #include "msgid.h" #endif // NEWMSG -#if !defined(__WIN__) +#if !defined(_WIN32) #define stricmp strcasecmp -#endif // !__WIN__ +#endif // !_WIN32 char *msglang(void); diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index bb25d4803d9..d7715a2ea9f 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -17,7 +17,7 @@ /* Include relevant MariaDB header file. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #else //#include // dlopen(), dlclose(), dlsym() ... @@ -52,9 +52,9 @@ #include "ha_connect.h" #include "mycat.h" -#if !defined(__WIN__) +#if !defined(_WIN32) extern handlerton *connect_hton; -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* External function. */ @@ -71,11 +71,11 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info) typedef PQRYRES(__stdcall* XCOLDEF) (PGLOBAL, void*, char*, char*, bool); const char* module, * subtype; char c, soname[_MAX_PATH], getname[40] = "Col"; -#if defined(__WIN__) +#if defined(_WIN32) HANDLE hdll; /* Handle to the external DLL */ -#else // !__WIN__ +#else // !_WIN32 void* hdll; /* Handle for the loaded shared library */ -#endif // !__WIN__ +#endif // !_WIN32 XCOLDEF coldef = NULL; PQRYRES qrp = NULL; @@ -103,7 +103,7 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info) if (!c) break; } // endfor i -#if defined(__WIN__) +#if defined(_WIN32) // Load the Dll implementing the table if (!(hdll = LoadLibrary(soname))) { char buf[256]; @@ -123,7 +123,7 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info) FreeLibrary((HMODULE)hdll); return NULL; } // endif coldef -#else // !__WIN__ +#else // !_WIN32 const char* error = NULL; // Load the desired shared library @@ -140,7 +140,7 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info) dlclose(hdll); return NULL; } // endif coldef -#endif // !__WIN__ +#endif // !_WIN32 // Just in case the external Get function does not set error messages sprintf(g->Message, "Error getting column info from %s", subtype); @@ -148,11 +148,11 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info) // Get the table column definition qrp = coldef(g, topt, tab, db, info); -#if defined(__WIN__) +#if defined(_WIN32) FreeLibrary((HMODULE)hdll); -#else // !__WIN__ +#else // !_WIN32 dlclose(hdll); -#endif // !__WIN__ +#endif // !_WIN32 return qrp; } // end of OEMColumns @@ -407,13 +407,13 @@ int TABDEF::GetColCatInfo(PGLOBAL g) // Take care of the column definitions i= poff= nof= nlg= 0; -#if defined(__WIN__) +#if defined(_WIN32) // Offsets of HTML and DIR tables start from 0, DBF at 1 loff= (trf == RECFM_DBF) ? 1 : (trf == RECFM_XML || trf == RECFM_DIR) ? -1 : 0; -#else // !__WIN__ +#else // !_WIN32 // Offsets of HTML tables start from 0, DIR and DBF at 1 loff = (trf == RECFM_DBF || trf == RECFM_DIR) ? 1 : (trf == RECFM_XML) ? -1 : 0; -#endif // !__WIN__ +#endif // !_WIN32 while (true) { // Default Offset depends on table format @@ -624,7 +624,7 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) strncat(strcpy(soname, GetPluginDir()), Module, sizeof(soname) - strlen(soname) - 1); -#if defined(__WIN__) +#if defined(_WIN32) // Is the DLL already loaded? if (!Hdll && !(Hdll = GetModuleHandle(soname))) // No, load the Dll implementing the function @@ -660,7 +660,7 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) FreeLibrary((HMODULE)Hdll); return NULL; } // endif getdef -#else // !__WIN__ +#else // !_WIN32 const char *error = NULL; #if 0 // Don't know what all this stuff does @@ -702,7 +702,7 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) dlclose(Hdll); return NULL; } // endif getdef -#endif // !__WIN__ +#endif // !_WIN32 // Just in case the external Get function does not set error messages sprintf(g->Message, MSG(DEF_ALLOC_ERROR), Subtype); diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h index 73e178ed51c..1b81ae9e3b3 100644 --- a/storage/connect/reldef.h +++ b/storage/connect/reldef.h @@ -146,11 +146,11 @@ class DllExport OEMDEF : public TABDEF { /* OEM table */ PTABDEF GetXdef(PGLOBAL g); // Members -#if defined(__WIN__) +#if defined(_WIN32) HANDLE Hdll; /* Handle to the external DLL */ -#else // !__WIN__ +#else // !_WIN32 void *Hdll; /* Handle for the loaded shared library */ -#endif // !__WIN__ +#endif // !_WIN32 PTABDEF Pxdef; /* Pointer to the external TABDEF class */ char *Module; /* Path/Name of the DLL implenting it */ char *Subtype; /* The name of the OEM table sub type */ diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index 6c42ab2c810..d2485bdc8ac 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -17,7 +17,7 @@ /* Include relevant sections of the System header files. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include // For testing only #include @@ -26,7 +26,7 @@ #define __MFC_COMPAT__ // To define min/max as macro #endif // __BORLANDC__ //#include -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) #include #include @@ -34,7 +34,7 @@ #include #endif // !UNIX #include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include application header files: */ @@ -233,11 +233,11 @@ void DOSDEF::RemoveOptValues(PGLOBAL g) // Delete any eventually ill formed non matching optimization file if (!GetOptFileName(g, filename)) -#if defined(__WIN__) +#if defined(_WIN32) DeleteFile(filename); #else // UNIX remove(filename); -#endif // __WIN__ +#endif // _WIN32 Optimized = 0; } // end of RemoveOptValues @@ -279,7 +279,7 @@ bool DOSDEF::DeleteIndexFile(PGLOBAL g, PIXDEF pxdf) /*********************************************************************/ if (sep) { // Indexes are save in separate files -#if defined(__WIN__) +#if defined(_WIN32) char drive[_MAX_DRIVE]; #else char *drive = NULL; @@ -296,7 +296,7 @@ bool DOSDEF::DeleteIndexFile(PGLOBAL g, PIXDEF pxdf) strcat(strcat(fname, "_"), pxdf->GetName()); _makepath(filename, drive, direc, fname, ftype); PlugSetPath(filename, filename, GetPath()); -#if defined(__WIN__) +#if defined(_WIN32) if (!DeleteFile(filename)) rc |= (GetLastError() != ERROR_FILE_NOT_FOUND); #else // UNIX @@ -313,7 +313,7 @@ bool DOSDEF::DeleteIndexFile(PGLOBAL g, PIXDEF pxdf) // Drop all indexes, delete the common file PlugSetPath(filename, Ofn, GetPath()); strcat(PlugRemoveType(filename, filename), ftype); -#if defined(__WIN__) +#if defined(_WIN32) if (!DeleteFile(filename)) rc = (GetLastError() != ERROR_FILE_NOT_FOUND); #else // UNIX @@ -1026,7 +1026,7 @@ bool TDBDOS::GetBlockValues(PGLOBAL g) #if 0 if (Mode == MODE_INSERT && Txfp->GetAmType() == TYPE_AM_DOS) return false; -#endif // __WIN__ +#endif // _WIN32 if (defp->Optimized || !(dup->Check & CHK_OPT)) return false; // Already done or to be redone diff --git a/storage/connect/tabext.cpp b/storage/connect/tabext.cpp index e9c7b2490d8..698f792b1f4 100644 --- a/storage/connect/tabext.cpp +++ b/storage/connect/tabext.cpp @@ -14,7 +14,7 @@ #include "sql_class.h" #include "sql_servers.h" #include "sql_string.h" -#if !defined(__WIN__) +#if !defined(_WIN32) #include "osutil.h" #endif diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp index 4a0a75460cd..5deb5fd0d40 100644 --- a/storage/connect/tabfix.cpp +++ b/storage/connect/tabfix.cpp @@ -17,7 +17,7 @@ /* Include relevant section of system dependant header files. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #include @@ -25,7 +25,7 @@ #define __MFC_COMPAT__ // To define min/max as macro #endif // __BORLANDC__ //#include -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) #include #include @@ -35,7 +35,7 @@ #include #endif // !UNIX #include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include application header files: */ diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp index 9a1e43dd798..cc49fdf9db7 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -20,7 +20,7 @@ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #include @@ -156,14 +156,14 @@ PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info) p = (char*)GetStringTableOption(g, topt, "Separator", ","); tdp->Sep = (strlen(p) == 2 && p[0] == '\\' && p[1] == 't') ? '\t' : *p; -#if defined(__WIN__) +#if defined(_WIN32) if (tdp->Sep == ',' || strnicmp(setlocale(LC_NUMERIC, NULL), "French", 6)) dechar = '.'; else dechar = ','; -#else // !__WIN__ +#else // !_WIN32 dechar = '.'; -#endif // !__WIN__ +#endif // !_WIN32 sep = tdp->Sep; tdp->Quoted = GetIntegerTableOption(g, topt, "Quoted", -1); diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index 06b6b3a9730..7a8eedad12b 100644 --- a/storage/connect/tabjdbc.cpp +++ b/storage/connect/tabjdbc.cpp @@ -38,7 +38,7 @@ #include "my_global.h" #include "sql_class.h" #include "sql_servers.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #if defined(__BORLANDC__) diff --git a/storage/connect/tabmac.cpp b/storage/connect/tabmac.cpp index 8260ab65391..ed161ac4be1 100644 --- a/storage/connect/tabmac.cpp +++ b/storage/connect/tabmac.cpp @@ -3,12 +3,12 @@ /* From the article and sample code by Khalid Shaikh. */ /* TABMAC: virtual table to get the list of MAC addresses. */ /***********************************************************************/ -#if defined(__WIN__) +#if defined(_WIN32) #include "my_global.h" //#include -#else // !__WIN__ +#else // !_WIN32 #error This is a WINDOWS only table type -#endif // !__WIN__ +#endif // !_WIN32 #include "global.h" #include "plgdbsem.h" //#include "catalog.h" diff --git a/storage/connect/tabmac.h b/storage/connect/tabmac.h index 47565bb2541..68135edb95f 100644 --- a/storage/connect/tabmac.h +++ b/storage/connect/tabmac.h @@ -1,11 +1,11 @@ // TABMAC.H Olivier Bertrand 2011-2012 // MAC: virtual table to Get Mac Addresses via GetAdaptersInfo -#if defined(__WIN__) +#if defined(_WIN32) #include #include -#else // !__WIN__ +#else // !_WIN32 #error This is a WINDOWS only table TYPE -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Definitions. */ diff --git a/storage/connect/tabmul.cpp b/storage/connect/tabmul.cpp index 649fc6706c6..d10f3cfab67 100644 --- a/storage/connect/tabmul.cpp +++ b/storage/connect/tabmul.cpp @@ -37,7 +37,7 @@ /* Include relevant section of system dependant header files. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #if defined(__BORLANDC__) @@ -166,11 +166,11 @@ bool TDBMUL::InitFileNames(PGLOBAL g) while (true) if ((rc = dirp->ReadDB(g)) == RC_OK) { -#if defined(__WIN__) +#if defined(_WIN32) strcat(strcpy(filename, dirp->Drive), dirp->Direc); -#else // !__WIN__ +#else // !_WIN32 strcpy(filename, dirp->Direc); -#endif // !__WIN__ +#endif // !_WIN32 strcat(strcat(filename, dirp->Fname), dirp->Ftype); pfn[n++] = PlugDup(g, filename); } else @@ -199,7 +199,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g) p = filename + strlen(filename) - 1; -#if !defined(__WIN__) +#if !defined(_WIN32) // Data files can be imported from Windows (having CRLF) if (*p == '\n' || *p == '\r') { // is this enough for Unix ??? @@ -566,11 +566,11 @@ bool TDBMSD::InitFileNames(PGLOBAL g) while (true) if ((rc = dirp->ReadDB(g)) == RC_OK) { -#if defined(__WIN__) +#if defined(_WIN32) strcat(strcpy(filename, dirp->Drive), dirp->Direc); -#else // !__WIN__ +#else // !_WIN32 strcpy(filename, dirp->Direc); -#endif // !__WIN__ +#endif // !_WIN32 strcat(strcat(filename, dirp->Fname), dirp->Ftype); pfn[n++] = PlugDup(g, filename); } else @@ -634,18 +634,18 @@ PTDB DIRDEF::GetTable(PGLOBAL g, MODE) void TDBDIR::Init(void) { iFile = 0; -#if defined(__WIN__) +#if defined(_WIN32) Dvalp = NULL; memset(&FileData, 0, sizeof(_finddata_t)); hSearch = INVALID_HANDLE_VALUE; *Drive = '\0'; -#else // !__WIN__ +#else // !_WIN32 memset(&Fileinfo, 0, sizeof(struct stat)); Entry = NULL; Dir = NULL; Done = false; *Pattern = '\0'; -#endif // !__WIN__ +#endif // !_WIN32 *Fpath = '\0'; *Direc = '\0'; *Fname = '\0'; @@ -674,7 +674,7 @@ char* TDBDIR::Path(PGLOBAL g) PCATLG cat = PlgGetCatalog(g); PTABDEF defp = (PTABDEF)To_Def; -#if defined(__WIN__) +#if defined(_WIN32) if (!*Drive) { PlugSetPath(Fpath, To_File, defp ? defp->GetPath() : NULL); _splitpath(Fpath, Drive, Direc, Fname, Ftype); @@ -682,7 +682,7 @@ char* TDBDIR::Path(PGLOBAL g) _makepath(Fpath, Drive, Direc, Fname, Ftype); // Usefull for TDBSDR return Fpath; -#else // !__WIN__ +#else // !_WIN32 if (!Done) { PlugSetPath(Fpath, To_File, defp ? defp->GetPath() : NULL); _splitpath(Fpath, NULL, Direc, Fname, Ftype); @@ -691,7 +691,7 @@ char* TDBDIR::Path(PGLOBAL g) } // endif Done return Pattern; -#endif // !__WIN__ +#endif // !_WIN32 } // end of Path /***********************************************************************/ @@ -709,7 +709,7 @@ int TDBDIR::GetMaxSize(PGLOBAL g) { if (MaxSize < 0) { int rc, n = -1; -#if defined(__WIN__) +#if defined(_WIN32) // Start searching files in the target directory. hSearch = FindFirstFile(Path(g), &FileData); @@ -750,7 +750,7 @@ int TDBDIR::GetMaxSize(PGLOBAL g) // Close the search handle. FindClose(hSearch); -#else // !__WIN__ +#else // !_WIN32 Path(g); // Start searching files in the target directory. @@ -774,7 +774,7 @@ int TDBDIR::GetMaxSize(PGLOBAL g) // Close the DIR handle. closedir(Dir); -#endif // !__WIN__ +#endif // !_WIN32 MaxSize = n; } // endif MaxSize @@ -800,10 +800,10 @@ bool TDBDIR::OpenDB(PGLOBAL g) } // endif use Use = USE_OPEN; -#if !defined(__WIN__) +#if !defined(_WIN32) Path(g); // Be sure it is done Dir = NULL; // For ReadDB -#endif // !__WIN__ +#endif // !_WIN32 return false; } // end of OpenDB @@ -814,7 +814,7 @@ int TDBDIR::ReadDB(PGLOBAL g) { int rc = RC_OK; -#if defined(__WIN__) +#if defined(_WIN32) do { if (hSearch == INVALID_HANDLE_VALUE) { /*****************************************************************/ @@ -877,7 +877,7 @@ int TDBDIR::ReadDB(PGLOBAL g) rc = RC_EF; } // endif Entry -#endif // !__WIN__ +#endif // !_WIN32 return rc; } // end of ReadDB @@ -905,17 +905,17 @@ int TDBDIR::DeleteDB(PGLOBAL g, int) /***********************************************************************/ void TDBDIR::CloseDB(PGLOBAL) { -#if defined(__WIN__) +#if defined(_WIN32) // Close the search handle. FindClose(hSearch); hSearch = INVALID_HANDLE_VALUE; -#else // !__WIN__ +#else // !_WIN32 // Close the DIR handle if (Dir) { closedir(Dir); Dir = NULL; } // endif dir -#endif // !__WIN__ +#endif // !_WIN32 iFile = 0; } // end of CloseDB @@ -950,7 +950,7 @@ DIRCOL::DIRCOL(DIRCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp) N = col1->N; } // end of DIRCOL copy constructor -#if defined(__WIN__) +#if defined(_WIN32) /***********************************************************************/ /* Retrieve time information from FileData. */ /***********************************************************************/ @@ -977,7 +977,7 @@ void DIRCOL::SetTimeValue(PGLOBAL g, FILETIME& ftime) Value->Reset(); } // end of SetTimeValue -#endif // __WIN__ +#endif // _WIN32 /***********************************************************************/ /* ReadColumn: what this routine does is to access the information */ @@ -993,19 +993,19 @@ void DIRCOL::ReadColumn(PGLOBAL g) /* Retrieve the information corresponding to the column number. */ /*********************************************************************/ switch (N) { -#if defined(__WIN__) +#if defined(_WIN32) case 0: Value->SetValue_psz(Tdbp->Drive); break; -#endif // __WIN__ +#endif // _WIN32 case 1: Value->SetValue_psz(Tdbp->Direc); break; case 2: Value->SetValue_psz(Tdbp->Fname); break; case 3: Value->SetValue_psz(Tdbp->Ftype); break; -#if defined(__WIN__) +#if defined(_WIN32) case 4: Value->SetValue((int)Tdbp->FileData.dwFileAttributes); break; case 5: Value->SetValue((int)Tdbp->FileData.nFileSizeLow); break; case 6: SetTimeValue(g, Tdbp->FileData.ftLastWriteTime); break; case 7: SetTimeValue(g, Tdbp->FileData.ftCreationTime); break; case 8: SetTimeValue(g, Tdbp->FileData.ftLastAccessTime); break; -#else // !__WIN__ +#else // !_WIN32 case 4: Value->SetValue((int)Tdbp->Fileinfo.st_mode); break; case 5: Value->SetValue((int)Tdbp->Fileinfo.st_size); break; case 6: Value->SetValue((int)Tdbp->Fileinfo.st_mtime); break; @@ -1013,7 +1013,7 @@ void DIRCOL::ReadColumn(PGLOBAL g) case 8: Value->SetValue((int)Tdbp->Fileinfo.st_atime); break; case 9: Value->SetValue((int)Tdbp->Fileinfo.st_uid); break; case 10: Value->SetValue((int)Tdbp->Fileinfo.st_gid); break; -#endif // !__WIN__ +#endif // !_WIN32 default: sprintf(g->Message, MSG(INV_DIRCOL_OFST), N); throw GetAmType(); @@ -1045,7 +1045,7 @@ int TDBSDR::FindInDir(PGLOBAL g) size_t m = strlen(Direc); // Start searching files in the target directory. -#if defined(__WIN__) +#if defined(_WIN32) HANDLE h; #if defined(PATHMATCHSPEC) @@ -1155,7 +1155,7 @@ int TDBSDR::FindInDir(PGLOBAL g) // Close the search handle. FindClose(h); -#else // !__WIN__ +#else // !_WIN32 int k; DIR *dir = opendir(Direc); @@ -1189,7 +1189,7 @@ int TDBSDR::FindInDir(PGLOBAL g) // Close the DIR handle. closedir(dir); -#endif // !__WIN__ +#endif // !_WIN32 return n; } // end of FindInDir @@ -1205,13 +1205,13 @@ bool TDBSDR::OpenDB(PGLOBAL g) Sub = (PSUBDIR)PlugSubAlloc(g, NULL, sizeof(SUBDIR)); Sub->Next = NULL; Sub->Prev = NULL; -#if defined(__WIN__) +#if defined(_WIN32) Sub->H = INVALID_HANDLE_VALUE; Sub->Len = strlen(Direc); -#else // !__WIN__ +#else // !_WIN32 Sub->D = NULL; Sub->Len = 0; -#endif // !__WIN__ +#endif // !_WIN32 } // endif To_Sub return TDBDIR::OpenDB(g); @@ -1224,7 +1224,7 @@ int TDBSDR::ReadDB(PGLOBAL g) { int rc; -#if defined(__WIN__) +#if defined(_WIN32) again: rc = TDBDIR::ReadDB(g); @@ -1280,7 +1280,7 @@ int TDBSDR::ReadDB(PGLOBAL g) } // endif H } // endif rc -#else // !__WIN__ +#else // !_WIN32 rc = RC_NF; again: @@ -1338,7 +1338,7 @@ int TDBSDR::ReadDB(PGLOBAL g) } // endif Entry -#endif // !__WIN__ +#endif // !_WIN32 return rc; } // end of ReadDB diff --git a/storage/connect/tabmul.h b/storage/connect/tabmul.h index 8a95a772c41..a9d3f88cc44 100644 --- a/storage/connect/tabmul.h +++ b/storage/connect/tabmul.h @@ -6,14 +6,14 @@ /* */ /* This file contains the TDBMUL and TDBDIR classes declares. */ /***********************************************************************/ -#if defined(__WIN__) +#if defined(_WIN32) #include -#else // !__WIN__ +#else // !_WIN32 #include #include #include #include -#endif // !__WIN__ +#endif // !_WIN32 //#include "osutil.h" #include "block.h" @@ -160,18 +160,18 @@ public: // Members PSZ To_File; // Points to file search pathname int iFile; // Index of currently retrieved file -#if defined(__WIN__) +#if defined(_WIN32) PVAL Dvalp; // Used to retrieve file date values WIN32_FIND_DATA FileData; // Find data structure HANDLE hSearch; // Search handle char Drive[_MAX_DRIVE]; // Drive name -#else // !__WIN__ +#else // !_WIN32 struct stat Fileinfo; // File info structure struct dirent *Entry; // Point to directory entry structure DIR *Dir; // To searched directory structure bool Done; // true when _splipath is done char Pattern[_MAX_FNAME+_MAX_EXT]; -#endif // !__WIN__ +#endif // !_WIN32 char Fpath[_MAX_PATH]; // Absolute file search pattern char Direc[_MAX_DIR]; // Search path char Fname[_MAX_FNAME]; // File name @@ -207,11 +207,11 @@ class TDBSDR : public TDBDIR { typedef struct _Sub_Dir { struct _Sub_Dir *Next; struct _Sub_Dir *Prev; -#if defined(__WIN__) +#if defined(_WIN32) HANDLE H; // Search handle -#else // !__WIN__ +#else // !_WIN32 DIR *D; -#endif // !__WIN__ +#endif // !_WIN32 size_t Len; // Initial directory name length } SUBDIR, *PSUBDIR; @@ -238,9 +238,9 @@ class DIRCOL : public COLBLK { protected: // Default constructor not to be used DIRCOL(void) {} -#if defined(__WIN__) +#if defined(_WIN32) void SetTimeValue(PGLOBAL g, FILETIME& ftime); -#endif // __WIN__ +#endif // _WIN32 // Members PTDBDIR Tdbp; // To DIR table diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index 7e165fb5a80..f8f995f211e 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -35,9 +35,9 @@ #include "my_global.h" #include "sql_class.h" #include "sql_servers.h" -#if defined(__WIN__) +#if defined(_WIN32) //#include -#else // !__WIN__ +#else // !_WIN32 //#include //#include #include @@ -46,7 +46,7 @@ #include "osutil.h" //#include //#include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include application header files: */ diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp index 07272d1b298..6bf2bd2b47f 100644 --- a/storage/connect/taboccur.cpp +++ b/storage/connect/taboccur.cpp @@ -13,7 +13,7 @@ /***********************************************************************/ #include "my_global.h" #include "table.h" // MySQL table definitions -#if defined(__WIN__) +#if defined(_WIN32) #include #include #if defined(__BORLANDC__) diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp index ba5c65e2c94..bede19f7344 100644 --- a/storage/connect/tabodbc.cpp +++ b/storage/connect/tabodbc.cpp @@ -36,7 +36,7 @@ /***********************************************************************/ #include "my_global.h" #include "sql_class.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #if defined(__BORLANDC__) diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp index 9121a0453e5..2dab1cba981 100644 --- a/storage/connect/tabpivot.cpp +++ b/storage/connect/tabpivot.cpp @@ -17,7 +17,7 @@ /***********************************************************************/ #include "my_global.h" #include "table.h" // MySQL table definitions -#if defined(__WIN__) +#if defined(_WIN32) #if defined(__BORLANDC__) #define __MFC_COMPAT__ // To define min/max as macro #endif diff --git a/storage/connect/tabrest.cpp b/storage/connect/tabrest.cpp index 4b6bb6a9e62..3b89d5232b7 100644 --- a/storage/connect/tabrest.cpp +++ b/storage/connect/tabrest.cpp @@ -13,10 +13,10 @@ #include // All MariaDB stuff #include #include -#if !defined(__WIN__) && !defined(_WINDOWS) +#if !defined(_WIN32) && !defined(_WINDOWS) #include #include -#endif // !__WIN__ && !_WINDOWS +#endif // !_WIN32 && !_WINDOWS /***********************************************************************/ /* Include application header files: */ @@ -67,7 +67,7 @@ int Xcurl(PGLOBAL g, PCSZ Http, PCSZ Uri, PCSZ filename) } else strcpy(buf, Http); -#if defined(__WIN__) +#if defined(_WIN32) char cmd[1024]; STARTUPINFO si; PROCESS_INFORMATION pi; @@ -90,7 +90,7 @@ int Xcurl(PGLOBAL g, PCSZ Http, PCSZ Uri, PCSZ filename) sprintf(g->Message, "CreateProcess curl failed (%d)", GetLastError()); rc = 1; } // endif CreateProcess -#else // !__WIN__ +#else // !_WIN32 char fn[600]; pid_t pID; @@ -130,7 +130,7 @@ int Xcurl(PGLOBAL g, PCSZ Http, PCSZ Uri, PCSZ filename) // Parent process wait(NULL); // Wait for the child to terminate } // endif pID -#endif // !__WIN__ +#endif // !_WIN32 return rc; } // end of Xcurl @@ -147,7 +147,7 @@ XGETREST GetRestFunction(PGLOBAL g) if (trace(515)) htrc("Looking for GetRest library\n"); -#if defined(__WIN__) || defined(_WINDOWS) +#if defined(_WIN32) || defined(_WINDOWS) HANDLE Hdll; const char* soname = "GetRest.dll"; // Module name @@ -176,7 +176,7 @@ XGETREST GetRestFunction(PGLOBAL g) FreeLibrary((HMODULE)Hdll); return NULL; } // endif getRestFnc -#else // !__WIN__ +#else // !_WIN32 void* Hso; const char* error = NULL; const char* soname = "GetRest.so"; // Module name @@ -195,7 +195,7 @@ XGETREST GetRestFunction(PGLOBAL g) dlclose(Hso); return NULL; } // endif getdef -#endif // !__WIN__ +#endif // !_WIN32 #else // REST_SOURCE getRestFnc = restGetFile; #endif // REST_SOURCE diff --git a/storage/connect/tabrest.h b/storage/connect/tabrest.h index 9cf2d10a6b8..9066a89b306 100644 --- a/storage/connect/tabrest.h +++ b/storage/connect/tabrest.h @@ -5,12 +5,12 @@ /***********************************************************************/ #pragma once -#if defined(__WIN__) +#if defined(_WIN32) static PCSZ slash = "\\"; -#else // !__WIN__ +#else // !_WIN32 static PCSZ slash = "/"; #define stricmp strcasecmp -#endif // !__WIN__ +#endif // !_WIN32 typedef int(__stdcall* XGETREST) (char*, bool, PCSZ, PCSZ, PCSZ); diff --git a/storage/connect/tabsys.cpp b/storage/connect/tabsys.cpp index f73a2b6578d..9a8e4a9c562 100644 --- a/storage/connect/tabsys.cpp +++ b/storage/connect/tabsys.cpp @@ -12,12 +12,12 @@ /* Include relevant sections of the System header files. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #if defined(__BORLANDC__) #define __MFC_COMPAT__ // To define min/max as macro #endif // __BORLANDC__ //#include -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) #include #include @@ -25,7 +25,7 @@ #include #endif // !UNIX #include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include application header files: */ @@ -36,9 +36,9 @@ #include "global.h" #include "plgdbsem.h" #include "reldef.h" -#if !defined(__WIN__) +#if !defined(_WIN32) #include "osutil.h" -#endif // !__WIN__ +#endif // !_WIN32 #include "filamtxt.h" #include "tabdos.h" #include "tabsys.h" @@ -48,10 +48,10 @@ #define CSZ 36 // Column section name length #define CDZ 256 // Column definition length -#if !defined(__WIN__) +#if !defined(_WIN32) #define GetPrivateProfileSectionNames(S,L,I) \ GetPrivateProfileString(NULL,NULL,"",S,L,I) -#endif // !__WIN__ +#endif // !_WIN32 /* -------------- Implementation of the INI classes ------------------ */ @@ -123,7 +123,7 @@ bool INIDEF::DeleteTableFile(PGLOBAL g) // Delete the INI table file if not protected if (!IsReadOnly()) { PlugSetPath(filename, Fn, GetPath()); -#if defined(__WIN__) +#if defined(_WIN32) rc = !DeleteFile(filename); #else // UNIX rc = remove(filename); @@ -345,9 +345,9 @@ int TDBINI::DeleteDB(PGLOBAL g, int irc) /***********************************************************************/ void TDBINI::CloseDB(PGLOBAL) { -#if !defined(__WIN__) +#if !defined(_WIN32) PROFILE_Close(Ifile); -#endif // !__WIN__ +#endif // !_WIN32 } // end of CloseDB // ------------------------ INICOL functions ---------------------------- diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index 1150824464f..b6277088bac 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -36,7 +36,7 @@ //#include "sql_base.h" #include "my_global.h" #include "table.h" // MySQL table definitions -#if defined(__WIN__) +#if defined(_WIN32) #include #include #if defined(__BORLANDC__) @@ -71,15 +71,15 @@ #include "tabmysql.h" #include "ha_connect.h" -#if defined(__WIN__) +#if defined(_WIN32) #if defined(__BORLANDC__) #define SYSEXIT void _USERENTRY #else #define SYSEXIT void #endif -#else // !__WIN__ +#else // !_WIN32 #define SYSEXIT void * -#endif // !__WIN__ +#endif // !_WIN32 extern pthread_mutex_t tblmut; diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index e187e6eaec5..47a882e11b1 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -14,7 +14,7 @@ #include "sql_class.h" #include "table.h" #include "field.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #if defined(__BORLANDC__) diff --git a/storage/connect/tabvct.cpp b/storage/connect/tabvct.cpp index 0ed466f6ffb..9cf5f41d1fe 100644 --- a/storage/connect/tabvct.cpp +++ b/storage/connect/tabvct.cpp @@ -35,7 +35,7 @@ /* Include relevant MariaDB header file. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #if defined(__BORLANDC__) @@ -149,7 +149,7 @@ bool VCTDEF::Erase(char *filename) for (i = 1, cdp = To_Cols; cdp; i++, cdp = cdp->GetNext()) { sprintf(filename, fpat, i); -//#if defined(__WIN__) +//#if defined(_WIN32) // rc |= !DeleteFile(filename); //#else // UNIX rc |= remove(filename); @@ -178,7 +178,7 @@ bool VCTDEF::Erase(char *filename) int VCTDEF::MakeFnPattern(char *fpat) { char pat[16]; -#if defined(__WIN__) +#if defined(_WIN32) char drive[_MAX_DRIVE]; #else char *drive = NULL; diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp index 8a8e1bcbcb6..a6aab7d2563 100644 --- a/storage/connect/tabwmi.cpp +++ b/storage/connect/tabwmi.cpp @@ -2,9 +2,9 @@ /* TABWMI: Author Olivier Bertrand -- PlugDB -- 2012 - 2017 */ /* TABWMI: Virtual table to get WMI information. */ /***********************************************************************/ -#if !defined(__WIN__) +#if !defined(_WIN32) #error This is a WINDOWS only table type -#endif // !__WIN__ +#endif // !_WIN32 #include "my_global.h" #include diff --git a/storage/connect/tabxcl.cpp b/storage/connect/tabxcl.cpp index 93a24accc3c..87fa799d87e 100644 --- a/storage/connect/tabxcl.cpp +++ b/storage/connect/tabxcl.cpp @@ -17,7 +17,7 @@ /***********************************************************************/ #include "my_global.h" #include "table.h" // MySQL table definitions -#if defined(__WIN__) +#if defined(_WIN32) #include #include #if defined(__BORLANDC__) diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp index d7f199a8092..cb428f5a94c 100644 --- a/storage/connect/tabxml.cpp +++ b/storage/connect/tabxml.cpp @@ -15,12 +15,12 @@ #include #include #include -#if defined(__WIN__) +#if defined(_WIN32) #include #include //#include #include -#else // !__WIN__ +#else // !_WIN32 #include #include #include @@ -28,7 +28,7 @@ //#include #include "osutil.h" #define _O_RDONLY O_RDONLY -#endif // !__WIN__ +#endif // !_WIN32 #include "resource.h" // for IDS_COLUMNS #define INCLUDE_TDBXML @@ -53,11 +53,11 @@ extern "C" char version[]; -#if defined(__WIN__) && defined(DOMDOC_SUPPORT) +#if defined(_WIN32) && defined(DOMDOC_SUPPORT) #define XMLSUP "MS-DOM" -#else // !__WIN__ +#else // !_WIN32 #define XMLSUP "libxml2" -#endif // !__WIN__ +#endif // !_WIN32 #define TYPE_UNKNOWN 12 /* Must be greater than other types */ #define XLEN(M) sizeof(M) - strlen(M) - 1 /* To avoid overflow*/ @@ -180,11 +180,11 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) tdp->Skip = GetBooleanTableOption(g, topt, "Skipnull", false); if (!(op = GetStringTableOption(g, topt, "Xmlsup", NULL))) -#if defined(__WIN__) +#if defined(_WIN32) tdp->Usedom = true; -#else // !__WIN__ +#else // !_WIN32 tdp->Usedom = false; -#endif // !__WIN__ +#endif // !_WIN32 else tdp->Usedom = (toupper(*op) == 'M' || toupper(*op) == 'D'); @@ -533,11 +533,11 @@ bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) // Note that if no support is specified, the default is MS-DOM // on Windows and libxml2 otherwise if (*buf == '*') -#if defined(__WIN__) +#if defined(_WIN32) Usedom = true; -#else // !__WIN__ +#else // !_WIN32 Usedom = false; -#endif // !__WIN__ +#endif // !_WIN32 else Usedom = (toupper(*buf) == 'M' || toupper(*buf) == 'D'); @@ -970,7 +970,7 @@ bool TDBXML::Initialize(PGLOBAL g) Docp->SetNofree(true); // For libxml2 -#if defined(__WIN__) +#if defined(_WIN32) } catch (_com_error e) { // We come here if a DOM command threw an error char buf[128]; @@ -984,7 +984,7 @@ bool TDBXML::Initialize(PGLOBAL g) sprintf(g->Message, "%s hr=%x", MSG(COM_ERROR), e.Error()); goto error; -#endif // __WIN__ +#endif // _WIN32 #if !defined(UNIX) } catch(...) { // Other errors diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp index b7c8c704e65..a993c1371c2 100644 --- a/storage/connect/valblk.cpp +++ b/storage/connect/valblk.cpp @@ -23,7 +23,7 @@ /* Include relevant MariaDB header file. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) //#include #else #include "osutil.h" diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index e710fefc624..1366362dac0 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -30,11 +30,11 @@ #include "sql_class.h" #include "sql_time.h" -#if defined(__WIN__) +#if defined(_WIN32) //#include -#else // !__WIN__ +#else // !_WIN32 #include -#endif // !__WIN__ +#endif // !_WIN32 #include @@ -77,12 +77,12 @@ int DTVAL::Shift = 0; /***********************************************************************/ bool PlugEvalLike(PGLOBAL, LPCSTR, LPCSTR, bool); -#if !defined(__WIN__) +#if !defined(_WIN32) extern "C" { PSZ strupr(PSZ s); PSZ strlwr(PSZ s); } -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Get a long long number from its character representation. */ @@ -1648,10 +1648,10 @@ int TYPVAL::CompareValue(PVAL vp) else n = strcmp(Strp, vp->GetCharValue()); -#if defined(__WIN__) +#if defined(_WIN32) if (n == _NLSCMPERROR) return n; // Here we should raise an error -#endif // __WIN__ +#endif // _WIN32 return (n > 0) ? 1 : (n < 0) ? -1 : 0; } // end of CompareValue diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp index 95f038d494c..84a730788e2 100644 --- a/storage/connect/xindex.cpp +++ b/storage/connect/xindex.cpp @@ -10,12 +10,12 @@ /* Include relevant sections of the System header files. */ /***********************************************************************/ #include "my_global.h" -#if defined(__WIN__) +#if defined(_WIN32) #include #include #include //#include -#else // !__WIN__ +#else // !_WIN32 #if defined(UNIX) #include #include @@ -25,7 +25,7 @@ #include #endif // !UNIX #include -#endif // !__WIN__ +#endif // !_WIN32 /***********************************************************************/ /* Include required application header files */ @@ -846,7 +846,7 @@ bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp) if ((sep = defp->GetBoolCatInfo("SepIndex", false))) { // Index is saved in a separate file -#if defined(__WIN__) +#if defined(_WIN32) char drive[_MAX_DRIVE]; #else char *drive = NULL; @@ -1000,7 +1000,7 @@ bool XINDEX::Init(PGLOBAL g) if (defp->SepIndex()) { // Index was saved in a separate file -#if defined(__WIN__) +#if defined(_WIN32) char drive[_MAX_DRIVE]; #else char *drive = NULL; @@ -1254,7 +1254,7 @@ bool XINDEX::MapInit(PGLOBAL g) if (defp->SepIndex()) { // Index was save in a separate file -#if defined(__WIN__) +#if defined(_WIN32) char drive[_MAX_DRIVE]; #else char *drive = NULL; @@ -1469,7 +1469,7 @@ bool XINDEX::GetAllSizes(PGLOBAL g,/* int &ndif,*/ int &numk) if (defp->SepIndex()) { // Index was saved in a separate file -#if defined(__WIN__) +#if defined(_WIN32) char drive[_MAX_DRIVE]; #else char *drive = NULL; @@ -2517,7 +2517,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode) if (trace(1)) htrc(" Xopen: filename=%s id=%d mode=%d\n", filename, id, mode); -#if defined(__WIN__) +#if defined(_WIN32) LONG high = 0; DWORD rc, drc, access, share, creation; @@ -2693,7 +2693,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode) /***********************************************************************/ bool XHUGE::Seek(PGLOBAL g, int low, int high, int origin) { -#if defined(__WIN__) +#if defined(_WIN32) LONG hi = high; DWORD rc = SetFilePointer(Hfile, low, &hi, origin); @@ -2729,7 +2729,7 @@ bool XHUGE::Read(PGLOBAL g, void *buf, int n, int size) { bool rc = false; -#if defined(__WIN__) +#if defined(_WIN32) bool brc; DWORD nbr, count = (DWORD)(n * size); @@ -2775,7 +2775,7 @@ bool XHUGE::Read(PGLOBAL g, void *buf, int n, int size) /***********************************************************************/ int XHUGE::Write(PGLOBAL g, void *buf, int n, int size, bool& rc) { -#if defined(__WIN__) +#if defined(_WIN32) bool brc; DWORD nbw, count = (DWORD)n * (DWORD) size; @@ -2817,7 +2817,7 @@ void XHUGE::Close(char *fn, int id) if (trace(1)) htrc("XHUGE::Close: fn=%s id=%d NewOff=%lld\n", fn, id, NewOff.Val); -#if defined(__WIN__) +#if defined(_WIN32) if (id >= 0 && fn) { CloseFileHandle(Hfile); Hfile = CreateFile(fn, GENERIC_READ | GENERIC_WRITE, 0, NULL, @@ -2832,7 +2832,7 @@ void XHUGE::Close(char *fn, int id) } // endif SetFilePointer } // endif id -#else // !__WIN__ +#else // !_WIN32 if (id >= 0 && fn) { if (Hfile != INVALID_HANDLE_VALUE) { if (lseek64(Hfile, id * sizeof(IOFF), SEEK_SET) >= 0) { @@ -2848,7 +2848,7 @@ void XHUGE::Close(char *fn, int id) htrc("(XHUGE)error reopening %s: %s\n", fn, strerror(errno)); } // endif id -#endif // !__WIN__ +#endif // !_WIN32 XLOAD::Close(); } // end of Close diff --git a/storage/connect/xindex.h b/storage/connect/xindex.h index 339d7e68b75..ce62f0591c1 100644 --- a/storage/connect/xindex.h +++ b/storage/connect/xindex.h @@ -350,7 +350,7 @@ class DllExport XLOAD : public BLOCK { protected: // Members -#if defined(__WIN__) +#if defined(_WIN32) HANDLE Hfile; // Handle to file or map #else // UNIX int Hfile; // Descriptor to file or map From ed70f76cf7cbe2195909c5e495a4b18347a7c58c Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 24 Jun 2021 00:46:12 +0200 Subject: [PATCH 09/18] - Make function strz return null when LEX_STRING is null modified: storage/connect/ha_connect.cc - Use NOTE instead of WARNING in connect_assisted_discovery This because MariaDB raise an error when doing so modified: storage/connect/ha_connect.cc modified: storage/connect/tabrest.cpp - Make MONGO tables recognize STRINGIFY and JsonAllPath modified: storage/connect/mongo.cpp modified: storage/connect/mongo.h modified: storage/connect/tabcmg.h modified: storage/connect/tabjmg.cpp modified: storage/connect/tabcmg.cpp modified: storage/connect/tabjmg.h - Fix OBJECT option for Pretty != 2 JSN and BSON tables Accept all syntaxes for the OBJECT option modified: storage/connect/tabbson.cpp modified: storage/connect/tabjson.cpp - Use my_snprintf in function xcurl (by vuvova) modified: storage/connect/tabrest.cpp - Format dates entered as integer when formatted modified: storage/connect/value.cpp modified: storage/connect/value.h --- storage/connect/ha_connect.cc | 30 +++++++----- storage/connect/mongo.cpp | 8 +-- storage/connect/mongo.h | 5 +- storage/connect/tabbson.cpp | 92 +++++++++++++++++++++++++---------- storage/connect/tabcmg.cpp | 7 ++- storage/connect/tabcmg.h | 1 + storage/connect/tabjmg.cpp | 9 ++-- storage/connect/tabjmg.h | 3 +- storage/connect/tabjson.cpp | 90 +++++++++++++++++++++++++--------- storage/connect/tabrest.cpp | 10 ++-- storage/connect/value.cpp | 28 +++++++++-- storage/connect/value.h | 3 +- 12 files changed, 201 insertions(+), 85 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 01fe7a6d2b3..a9a6e6732e9 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -290,10 +290,14 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, /****************************************************************************/ static char *strz(PGLOBAL g, LEX_STRING &ls) { - char *str= (char*)PlugSubAlloc(g, NULL, ls.length + 1); + char* str= NULL; + + if (ls.str) { + str= (char*)PlugSubAlloc(g, NULL, ls.length + 1); + memcpy(str, ls.str, ls.length); + str[ls.length] = 0; + } // endif str - memcpy(str, ls.str, ls.length); - str[ls.length]= 0; return str; } // end of strz @@ -5625,7 +5629,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #endif // JAVA_SUPPORT uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL); bool bif, ok= false, dbf= false; - TABTYPE ttp= TAB_UNDEF; + TABTYPE ttp= TAB_UNDEF, ttr=TAB_UNDEF; PQRYRES qrp= NULL; PCOLRES crp; PCONNECT xp= NULL; @@ -5707,7 +5711,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS"; ttp= GetTypeID(topt->type); sprintf(g->Message, "No table_type. Was set to %s", topt->type); - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); + push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, 0, g->Message); } else if (ttp == TAB_NIY) { sprintf(g->Message, "Unsupported table type %s", topt->type); rc= HA_ERR_INTERNAL_ERROR; @@ -5715,13 +5719,13 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #if defined(REST_SUPPORT) } else if (topt->http) { if (ttp == TAB_UNDEF) { - topt->type = "JSON"; - ttp= GetTypeID(topt->type); - sprintf(g->Message, "No table_type. Was set to %s", topt->type); - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); - } // endif ttp + ttr= TAB_JSON; + strcpy(g->Message, "No table_type. Was set to JSON"); + push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, 0, g->Message); + } else + ttr= ttp; - switch (ttp) { + switch (ttr) { case TAB_JSON: #if defined(BSON_SUPPORT) case TAB_BSON: @@ -5956,7 +5960,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #if defined(REST_SUPPORT) case TAB_REST: if (!topt->http) - sprintf(g->Message, "Missing %s HTTP address", topt->type); + strcpy(g->Message, "Missing REST HTTP option"); else ok = true; @@ -6176,7 +6180,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, // Restore language type if (ttp == TAB_REST) - ttp = GetTypeID(topt->type); + ttp = ttr; for (i= 0; !rc && i < qrp->Nblin; i++) { typ= len= prec= dec= flg= 0; diff --git a/storage/connect/mongo.cpp b/storage/connect/mongo.cpp index 5f10a89ee67..a9c4813684b 100644 --- a/storage/connect/mongo.cpp +++ b/storage/connect/mongo.cpp @@ -1,6 +1,6 @@ /************** mongo C++ Program Source Code File (.CPP) **************/ -/* PROGRAM NAME: mongo Version 1.0 */ -/* (C) Copyright to the author Olivier BERTRAND 2017 */ +/* PROGRAM NAME: mongo Version 1.1 */ +/* (C) Copyright to the author Olivier BERTRAND 2021 */ /* These programs are the MGODEF class execution routines. */ /***********************************************************************/ @@ -36,6 +36,7 @@ bool MakeSelector(PGLOBAL g, PFIL fp, PSTRG s); bool IsNum(PSZ s); int GetDefaultDepth(void); +bool JsonAllPath(void); /***********************************************************************/ /* Make selector json representation for Mongo tables. */ @@ -350,7 +351,7 @@ void MGODISC::AddColumn(PGLOBAL g, PCSZ colname, PCSZ fmt, int k) bcp->Name = PlugDup(g, colname); length[0] = MY_MAX(length[0], (signed)strlen(colname)); - if (k) { + if (k || JsonAllPath()) { bcp->Fmt = PlugDup(g, fmt); length[7] = MY_MAX(length[7], (signed)strlen(fmt)); } else @@ -395,6 +396,7 @@ bool MGODEF::DefineAM(PGLOBAL g, LPCSTR, int poff) Uri = GetStringCatInfo(g, "Connect", "mongodb://localhost:27017"); Colist = GetStringCatInfo(g, "Colist", NULL); Filter = GetStringCatInfo(g, "Filter", NULL); + Strfy = GetStringCatInfo(g, "Stringify", NULL); Base = GetIntCatInfo("Base", 0) ? 1 : 0; Version = GetIntCatInfo("Version", 3); diff --git a/storage/connect/mongo.h b/storage/connect/mongo.h index dcefac372c0..fddc491f2d0 100644 --- a/storage/connect/mongo.h +++ b/storage/connect/mongo.h @@ -1,7 +1,7 @@ /**************** mongo H Declares Source Code File (.H) ***************/ -/* Name: mongo.h Version 1.0 */ +/* Name: mongo.h Version 1.1 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2017 */ +/* (C) Copyright to the author Olivier BERTRAND 2021 */ /* */ /* This file contains the common MongoDB classes declares. */ /***********************************************************************/ @@ -82,6 +82,7 @@ protected: PSZ Wrapname; /* Java wrapper name */ PCSZ Colist; /* Options list */ PCSZ Filter; /* Filtering query */ + PCSZ Strfy; /* Stringify column */ int Base; /* The array index base */ int Version; /* The Java driver version */ bool Pipe; /* True is Colist is a pipeline */ diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index c6758b21707..abffd0b64df 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -1,5 +1,5 @@ /************* tabbson C++ Program Source Code File (.CPP) *************/ -/* PROGRAM NAME: tabbson Version 1.1 */ +/* PROGRAM NAME: tabbson Version 1.2 */ /* (C) Copyright to the author Olivier BERTRAND 2020 - 2021 */ /* This program are the BSON class DB execution routines. */ /***********************************************************************/ @@ -193,7 +193,11 @@ int BSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) if (!(tdp->Database = SetPath(g, db))) return 0; - tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); + if ((tdp->Objname = GetStringTableOption(g, topt, "Object", NULL))) { + if (*tdp->Objname == '$') tdp->Objname++; + if (*tdp->Objname == '.') tdp->Objname++; + } // endif Objname + tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2); tdp->Xcol = GetStringTableOption(g, topt, "Expand", NULL); @@ -603,33 +607,51 @@ void BSONDISC::AddColumn(PGLOBAL g) /***********************************************************************/ PBVAL BTUTIL::FindRow(PGLOBAL g) { - char *p, *objpath; + char *p, *objpath = PlugDup(g, Tp->Objname); + char *sep = (Tp->Sep == ':') ? ":[" : ".["; + bool bp = false, b = false; PBVAL jsp = Tp->Row; PBVAL val = NULL; - for (objpath = PlugDup(g, Tp->Objname); jsp && objpath; objpath = p) { - if ((p = strchr(objpath, Tp->Sep))) + for (; jsp && objpath; objpath = p, bp = b) { + if ((p = strpbrk(objpath + 1, sep))) { + b = (*p == '['); *p++ = 0; + } // endif p - if (*objpath != '[' && !IsNum(objpath)) { // objpass is a key + if (!bp && *objpath != '[' && !IsNum(objpath)) { // objpass is a key val = (jsp->Type == TYPE_JOB) ? GetKeyValue(jsp, objpath) : NULL; } else { - if (*objpath == '[') { - if (objpath[strlen(objpath) - 1] == ']') - objpath++; - else + if (bp || *objpath == '[') { // Old style + if (objpath[strlen(objpath) - 1] != ']') { + sprintf(g->Message, "Invalid Table path %s", Tp->Objname); return NULL; - } // endif [ + } else if (!bp) + objpath++; + + } // endif bp val = (jsp->Type == TYPE_JAR) ? - GetArrayValue(GetArray(jsp), atoi(objpath) - Tp->B) : NULL; + GetArrayValue(jsp, atoi(objpath) - Tp->B) : NULL; } // endif objpath // jsp = (val) ? val->GetJson() : NULL; jsp = val; } // endfor objpath + if (jsp && jsp->Type != TYPE_JOB) { + if (jsp->Type == TYPE_JAR) { + jsp = GetArrayValue(jsp, Tp->B); + + if (jsp->Type != TYPE_JOB) + jsp = NULL; + + } else + jsp = NULL; + + } // endif Type + return jsp; } // end of FindRow @@ -653,17 +675,22 @@ PBVAL BTUTIL::MakeTopTree(PGLOBAL g, int type) if (Tp->Objname) { if (!Tp->Row) { // Parse and allocate Objpath item(s) - char* p; - char *objpath = PlugDup(g, Tp->Objname); + char *p, *objpath = PlugDup(g, Tp->Objname); + char *sep = (Tp->Sep == ':') ? ":[" : ".["; int i; + bool bp = false, b = false; PBVAL objp = NULL; PBVAL arp = NULL; - for (; objpath; objpath = p) { - if ((p = strchr(objpath, Tp->Sep))) + for (; objpath; objpath = p, bp = b) { + if ((p = strpbrk(objpath + 1, sep))) { + b = (*p == '['); *p++ = 0; + } // endif p - if (*objpath != '[' && !IsNum(objpath)) { + + if (!bp && *objpath != '[' && !IsNum(objpath)) { + // objpass is a key objp = NewVal(TYPE_JOB); if (!top) @@ -675,15 +702,15 @@ PBVAL BTUTIL::MakeTopTree(PGLOBAL g, int type) val = NewVal(); SetKeyValue(objp, MOF(val), objpath); } else { - if (*objpath == '[') { + if (bp || *objpath == '[') { // Old style if (objpath[strlen(objpath) - 1] != ']') { sprintf(g->Message, "Invalid Table path %s", Tp->Objname); return NULL; - } else + } else if (!bp) objpath++; - } // endif objpath + } // endif bp if (!top) top = NewVal(TYPE_JAR); @@ -755,10 +782,16 @@ void BCUTIL::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL jvp) break; case TYPE_DATE: if (jvp->Type == TYPE_STRG) { - if (!((DTVAL*)vp)->IsFormatted()) - ((DTVAL*)vp)->SetFormat(g, "YYYY-MM-DDThh:mm:ssZ", 20, 0); + PSZ dat = GetString(jvp); + + if (!IsNum(dat)) { + if (!((DTVAL*)vp)->IsFormatted()) + ((DTVAL*)vp)->SetFormat(g, "YYYY-MM-DDThh:mm:ssZ", 20, 0); + + vp->SetValue_psz(dat); + } else + vp->SetValue(atoi(dat)); - vp->SetValue_psz(GetString(jvp)); } else vp->SetValue(GetInteger(jvp)); @@ -1156,7 +1189,12 @@ bool BSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) G = g; Schema = GetStringCatInfo(g, "DBname", Schema); Jmode = (JMODE)GetIntCatInfo("Jmode", MODE_OBJECT); - Objname = GetStringCatInfo(g, "Object", NULL); + + if ((Objname = GetStringCatInfo(g, "Object", NULL))) { + if (*Objname == '$') Objname++; + if (*Objname == '.') Objname++; + } // endif Objname + Xcol = GetStringCatInfo(g, "Expand", NULL); Pretty = GetIntCatInfo("Pretty", 2); Limit = GetIntCatInfo("Limit", 50); @@ -1935,6 +1973,10 @@ bool BSONCOL::ParseJpath(PGLOBAL g) // Analyse intermediate array processing if (SetArrayOptions(g, p, i, Nodes[i - 1].Key)) return true; + else if (Xpd && Tbp->Mode == MODE_DELETE) { + strcpy(g->Message, "Cannot delete expanded columns"); + return true; + } // endif Xpd } else if (*p == '*') { // Return JSON @@ -2237,8 +2279,6 @@ int TDBBSON::MakeDocument(PGLOBAL g) return RC_FX; if ((objpath = PlugDup(g, Objname))) { - if (*objpath == '$') objpath++; - if (*objpath == '.') objpath++; p1 = (*objpath == '[') ? objpath++ : NULL; /*********************************************************************/ diff --git a/storage/connect/tabcmg.cpp b/storage/connect/tabcmg.cpp index 1552bdde58a..608445bb1ab 100644 --- a/storage/connect/tabcmg.cpp +++ b/storage/connect/tabcmg.cpp @@ -1,5 +1,5 @@ /************** tabcmg C++ Program Source Code File (.CPP) *************/ -/* PROGRAM NAME: tabcmg Version 1.2 */ +/* PROGRAM NAME: tabcmg Version 1.3 */ /* (C) Copyright to the author Olivier BERTRAND 2017 - 2021 */ /* This program are the C MongoDB class DB execution routines. */ /***********************************************************************/ @@ -192,6 +192,7 @@ TDBCMG::TDBCMG(MGODEF *tdp) : TDBEXT(tdp) Pcg.Line = NULL; Pcg.Pipe = tdp->Pipe && tdp->Colist != NULL; B = tdp->Base ? 1 : 0; + Strfy = tdp->Strfy; } else { Pcg.Uristr = NULL; Pcg.Db_name = NULL; @@ -200,6 +201,7 @@ TDBCMG::TDBCMG(MGODEF *tdp) : TDBEXT(tdp) Pcg.Filter = NULL; Pcg.Line = NULL; Pcg.Pipe = false; + Strfy = NULL; B = 0; } // endif tdp @@ -213,6 +215,7 @@ TDBCMG::TDBCMG(TDBCMG *tdbp) : TDBEXT(tdbp) Cmgp = tdbp->Cmgp; Cnd = tdbp->Cnd; Pcg = tdbp->Pcg; + Strfy = tdbp->Strfy; B = tdbp->B; Fpos = tdbp->Fpos; N = tdbp->N; @@ -394,7 +397,7 @@ MGOCOL::MGOCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) : EXTCOL(cdp, tdbp, cprec, i, "MGO") { Tmgp = (PTDBCMG)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); - Sgfy = false; + Sgfy = (Tmgp->Strfy && !stricmp(Tmgp->Strfy, Name)); if ((Jpath = cdp->GetFmt())) { int n = strlen(Jpath) - 1; diff --git a/storage/connect/tabcmg.h b/storage/connect/tabcmg.h index 44448590da1..0a29a6ce909 100644 --- a/storage/connect/tabcmg.h +++ b/storage/connect/tabcmg.h @@ -75,6 +75,7 @@ protected: CMgoConn *Cmgp; // Points to a C Mongo connection class CMGOPARM Pcg; // Parms passed to Cmgp const Item *Cnd; // The first condition + PCSZ Strfy; // The stringified column int Fpos; // The current row index int N; // The current Rownum int B; // Array index base diff --git a/storage/connect/tabjmg.cpp b/storage/connect/tabjmg.cpp index b02bf6a7f36..9271873b800 100644 --- a/storage/connect/tabjmg.cpp +++ b/storage/connect/tabjmg.cpp @@ -1,6 +1,6 @@ /************** tabjmg C++ Program Source Code File (.CPP) *************/ -/* PROGRAM NAME: tabjmg Version 1.2 */ -/* (C) Copyright to the author Olivier BERTRAND 2017 */ +/* PROGRAM NAME: tabjmg Version 1.3 */ +/* (C) Copyright to the author Olivier BERTRAND 2021 */ /* This file contains the MongoDB classes using the Java Driver. */ /***********************************************************************/ @@ -166,6 +166,7 @@ TDBJMG::TDBJMG(PMGODEF tdp) : TDBEXT(tdp) Coll_name = tdp->Tabname; Options = tdp->Colist; Filter = tdp->Filter; + Strfy = tdp->Strfy; B = tdp->Base ? 1 : 0; Pipe = tdp->Pipe && Options != NULL; } else { @@ -177,6 +178,7 @@ TDBJMG::TDBJMG(PMGODEF tdp) : TDBEXT(tdp) Coll_name = NULL; Options = NULL; Filter = NULL; + Strfy = NULL; B = 0; Pipe = false; } // endif tdp @@ -197,6 +199,7 @@ TDBJMG::TDBJMG(TDBJMG *tdbp) : TDBEXT(tdbp) Coll_name = tdbp->Coll_name; Options = tdbp->Options; Filter = tdbp->Filter; + Strfy = tdbp->Strfy; B = tdbp->B; Fpos = tdbp->Fpos; N = tdbp->N; @@ -420,7 +423,7 @@ JMGCOL::JMGCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) : EXTCOL(cdp, tdbp, cprec, i, "MGO") { Tmgp = (PTDBJMG)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); - Sgfy = false; + Sgfy = (Tmgp->Strfy && !stricmp(Tmgp->Strfy, Name)); if ((Jpath = cdp->GetFmt())) { int n = strlen(Jpath) - 1; diff --git a/storage/connect/tabjmg.h b/storage/connect/tabjmg.h index e8f08730b89..bc89319527a 100644 --- a/storage/connect/tabjmg.h +++ b/storage/connect/tabjmg.h @@ -1,5 +1,5 @@ /**************** tabjmg H Declares Source Code File (.H) **************/ -/* Name: tabjmg.h Version 1.2 */ +/* Name: tabjmg.h Version 1.3 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2017 - 2021 */ /* */ @@ -83,6 +83,7 @@ protected: PCSZ Coll_name; PCSZ Options; // The MongoDB options PCSZ Filter; // The filtering query + PCSZ Strfy; // The stringified column PSZ Wrapname; // Java wrapper name int Fpos; // The current row index int N; // The current Rownum diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index cad098e0f9b..b05e4ca2c01 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -1,5 +1,5 @@ /************* tabjson C++ Program Source Code File (.CPP) *************/ -/* PROGRAM NAME: tabjson Version 1.8 */ +/* PROGRAM NAME: tabjson Version 1.9 */ /* (C) Copyright to the author Olivier BERTRAND 2014 - 2021 */ /* This program are the JSON class DB execution routines. */ /***********************************************************************/ @@ -191,13 +191,19 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) #endif // ZIP_SUPPORT tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL); - if (!tdp->Fn && topt->http) + if (!tdp->Fn && topt->http) { tdp->Fn = GetStringTableOption(g, topt, "Subtype", NULL); + topt->subtype = NULL; + } // endif fn if (!(tdp->Database = SetPath(g, db))) return 0; - tdp->Objname = GetStringTableOption(g, topt, "Object", NULL); + if ((tdp->Objname = GetStringTableOption(g, topt, "Object", NULL))) { + if (*tdp->Objname == '$') tdp->Objname++; + if (*tdp->Objname == '.') tdp->Objname++; + } // endif Objname + tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0; tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2); tdp->Xcol = GetStringTableOption(g, topt, "Expand", NULL); @@ -632,7 +638,12 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { Schema = GetStringCatInfo(g, "DBname", Schema); Jmode = (JMODE)GetIntCatInfo("Jmode", MODE_OBJECT); - Objname = GetStringCatInfo(g, "Object", NULL); + + if ((Objname = GetStringCatInfo(g, "Object", NULL))) { + if (*Objname == '$') Objname++; + if (*Objname == '.') Objname++; + } // endif Objname + Xcol = GetStringCatInfo(g, "Expand", NULL); Pretty = GetIntCatInfo("Pretty", 2); Limit = GetIntCatInfo("Limit", 50); @@ -950,23 +961,29 @@ int TDBJSN::EstimatedLength(void) /***********************************************************************/ PJSON TDBJSN::FindRow(PGLOBAL g) { - char *p, *objpath; + char *p, *objpath = PlugDup(g, Objname); + char *sep = (Sep == ':') ? ":[" : ".["; + bool bp = false, b = false; PJSON jsp = Row; PJVAL val = NULL; - for (objpath = PlugDup(g, Objname); jsp && objpath; objpath = p) { - if ((p = strchr(objpath, Sep))) + for (; jsp && objpath; objpath = p, bp = b) { + if ((p = strpbrk(objpath + 1, sep))) { + b = (*p == '['); *p++ = 0; + } // endif p - if (*objpath != '[' && !IsNum(objpath)) { // objpass is a key + if (!bp && *objpath != '[' && !IsNum(objpath)) { // objpass is a key val = (jsp->GetType() == TYPE_JOB) ? jsp->GetObject()->GetKeyValue(objpath) : NULL; } else { - if (*objpath == '[') { - if (objpath[strlen(objpath) - 1] == ']') - objpath++; - else + if (bp || *objpath == '[') { + if (objpath[strlen(objpath) - 1] != ']') { + sprintf(g->Message, "Invalid Table path %s", Objname); return NULL; + } else if (!bp) + objpath++; + } // endif [ val = (jsp->GetType() == TYPE_JAR) ? @@ -976,6 +993,18 @@ PJSON TDBJSN::FindRow(PGLOBAL g) jsp = (val) ? val->GetJson() : NULL; } // endfor objpath + if (jsp && jsp->GetType() != TYPE_JOB) { + if (jsp->GetType() == TYPE_JAR) { + jsp = jsp->GetArray()->GetArrayValue(B); + + if (jsp->GetType() != TYPE_JOB) + jsp = NULL; + + } else + jsp = NULL; + + } // endif Type + return jsp; } // end of FindRow @@ -1149,20 +1178,23 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) if (Objname) { if (!Val) { // Parse and allocate Objname item(s) - char *p; - char *objpath = PlugDup(g, Objname); + char *p, *objpath = PlugDup(g, Objname); + char *sep = (Sep == ':') ? ":[" : ".["; int i; + bool bp = false, b = false; PJOB objp; PJAR arp; PJVAL val = NULL; Top = NULL; - for (; objpath; objpath = p) { - if ((p = strchr(objpath, Sep))) + for (; objpath; objpath = p, bp = b) { + if ((p = strpbrk(objpath + 1, sep))) { + b = (*p == '['); *p++ = 0; + } // endif p - if (*objpath != '[' && !IsNum(objpath)) { + if (!bp && *objpath != '[' && !IsNum(objpath)) { objp = new(g) JOBJECT; if (!Top) @@ -1174,15 +1206,15 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) val = new(g) JVALUE; objp->SetKeyValue(g, val, objpath); } else { - if (*objpath == '[') { + if (bp || *objpath == '[') { // Old style if (objpath[strlen(objpath) - 1] != ']') { sprintf(g->Message, "Invalid Table path %s", Objname); - return RC_FX; - } else + return NULL; + } else if (!bp) objpath++; - } // endif objpath + } // endif bp arp = new(g) JARRAY; @@ -1537,6 +1569,10 @@ bool JSONCOL::ParseJpath(PGLOBAL g) // Analyse intermediate array processing if (SetArrayOptions(g, p, i, Nodes[i - 1].Key)) return true; + else if (Xpd && Tjp->Mode == MODE_DELETE) { + strcpy(g->Message, "Cannot delete expanded columns"); + return true; + } // endif Xpd } else if (*p == '*') { // Return JSON @@ -1752,10 +1788,16 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL jvp) break; case TYPE_DATE: if (jvp->GetValType() == TYPE_STRG) { - if (!((DTVAL*)vp)->IsFormatted()) - ((DTVAL*)vp)->SetFormat(g, "YYYY-MM-DDThh:mm:ssZ", 20, 0); + PSZ dat = jvp->GetString(g); + + if (!IsNum(dat)) { + if (!((DTVAL*)vp)->IsFormatted()) + ((DTVAL*)vp)->SetFormat(g, "YYYY-MM-DDThh:mm:ssZ", 20, 0); + + vp->SetValue_psz(dat); + } else + vp->SetValue(atoi(dat)); - vp->SetValue_psz(jvp->GetString(g)); } else vp->SetValue(jvp->GetInteger()); diff --git a/storage/connect/tabrest.cpp b/storage/connect/tabrest.cpp index 3b89d5232b7..c66d8d76f3d 100644 --- a/storage/connect/tabrest.cpp +++ b/storage/connect/tabrest.cpp @@ -1,5 +1,5 @@ /************** tabrest C++ Program Source Code File (.CPP) ************/ -/* PROGRAM NAME: tabrest Version 2.0 */ +/* PROGRAM NAME: tabrest Version 2.1 */ /* (C) Copyright to the author Olivier BERTRAND 2018 - 2021 */ /* This program is the REST Web API support for MariaDB. */ /* The way Connect handles NOSQL data returned by REST queries is */ @@ -37,7 +37,7 @@ #include "tabrest.h" #if defined(connect_EXPORTS) -#define PUSH_WARNING(M) push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0, M) +#define PUSH_WARNING(M) push_warning(current_thd, Sql_condition::WARN_LEVEL_NOTE, 0, M) #else #define PUSH_WARNING(M) htrc(M) #endif @@ -60,12 +60,12 @@ int Xcurl(PGLOBAL g, PCSZ Http, PCSZ Uri, PCSZ filename) if (Uri) { if (*Uri == '/' || Http[strlen(Http) - 1] == '/') - sprintf(buf, "%s%s", Http, Uri); + my_snprintf(buf, sizeof(buf)-1, "%s%s", Http, Uri); else - sprintf(buf, "%s/%s", Http, Uri); + my_snprintf(buf, sizeof(buf)-1, "%s/%s", Http, Uri); } else - strcpy(buf, Http); + my_snprintf(buf, sizeof(buf)-1, "%s", Http); #if defined(_WIN32) char cmd[1024]; diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 1366362dac0..8f2cb631feb 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -2643,9 +2643,9 @@ bool DTVAL::SetValue_pval(PVAL valp, bool chktype) } else if (valp->GetType() == TYPE_BIGINT && !(valp->GetBigintValue() % 1000)) { // Assuming that this timestamp is in milliseconds - Tval = (int)(valp->GetBigintValue() / 1000); + SetValue((int)(valp->GetBigintValue() / 1000)); } else - Tval = valp->GetIntValue(); + SetValue(valp->GetIntValue()); } else Reset(); @@ -2736,21 +2736,39 @@ void DTVAL::SetValue_pvblk(PVBLK blk, int n) } // end of SetValue +/***********************************************************************/ +/* DTVAL SetValue: get date as an integer. */ +/***********************************************************************/ +void DTVAL::SetValue(int n) +{ + Tval = n; + + if (Pdtp) { + size_t n = 0, slen = (size_t)Len + 1; + struct tm tm, *ptm= GetGmTime(&tm); + + if (ptm) + n = strftime(Sdate, slen, Pdtp->OutFmt, ptm); + + } // endif Pdtp + +} // end of SetValue + /***********************************************************************/ /* DTVAL GetCharString: get string representation of a date value. */ /***********************************************************************/ char *DTVAL::GetCharString(char *p) { if (Pdtp) { - size_t n = 0; + size_t n = 0, slen = (size_t)Len + 1; struct tm tm, *ptm= GetGmTime(&tm); if (ptm) - n = strftime(Sdate, Len + 1, Pdtp->OutFmt, ptm); + n = strftime(Sdate, slen, Pdtp->OutFmt, ptm); if (!n) { *Sdate = '\0'; - strncat(Sdate, "Error", Len + 1); + strncat(Sdate, "Error", slen); } // endif n return Sdate; diff --git a/storage/connect/value.h b/storage/connect/value.h index df6a55501b6..f709c7dbad0 100644 --- a/storage/connect/value.h +++ b/storage/connect/value.h @@ -418,7 +418,8 @@ class DllExport DTVAL : public TYPVAL { virtual bool SetValue_char(const char *p, int n); virtual void SetValue_psz(PCSZ s); virtual void SetValue_pvblk(PVBLK blk, int n); - virtual PSZ GetCharValue(void) { return Sdate; } + virtual void SetValue(int n); + virtual PSZ GetCharValue(void) { return Sdate; } virtual char *GetCharString(char *p); virtual int ShowValue(char *buf, int len); virtual bool FormatValue(PVAL vp, PCSZ fmt); From 330b32ebd95b25793c06e066c3f7829a22d0590f Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 24 Jun 2021 23:56:13 +0200 Subject: [PATCH 10/18] Fix clang compile error --- storage/connect/value.h | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/connect/value.h b/storage/connect/value.h index f709c7dbad0..9b4b9164fa5 100644 --- a/storage/connect/value.h +++ b/storage/connect/value.h @@ -412,6 +412,7 @@ class DllExport DTVAL : public TYPVAL { // Constructors DTVAL(PGLOBAL g, int n, int p, PCSZ fmt); DTVAL(int n); + using TYPVAL::SetValue; // Implementation virtual bool SetValue_pval(PVAL valp, bool chktype); From 5c5d60b89781616f9f12fed7f0215de2ea279d0b Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 25 Jun 2021 01:15:51 +0200 Subject: [PATCH 11/18] Fix compile error in value.h and remove unused variables in ha_connect.cc --- storage/connect/ha_connect.cc | 5 +---- storage/connect/value.h | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index a9a6e6732e9..5493f3b6730 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -4377,7 +4377,6 @@ int ha_connect::info(uint flag) // tdbp must be available to get updated info if (xp->CheckQuery(valid_query_id) || !tdbp) { PDBUSER dup= PlgGetUser(g); - PCATLG cat= (dup) ? dup->Catalog : NULL; if (xmod == MODE_ANY || xmod == MODE_ALTER) { // Pure info, not a query @@ -5615,7 +5614,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, PCSZ nsp= NULL, cls= NULL; #endif // _WIN32 //int hdr, mxe; - int port= 0, mxr= 0, rc= 0, mul= 0, lrecl= 0; + int port= 0, mxr= 0, rc= 0, mul= 0; //PCSZ tabtyp= NULL; #if defined(ODBC_SUPPORT) POPARM sop= NULL; @@ -5638,8 +5637,6 @@ static int connect_assisted_discovery(handlerton *, THD* thd, if (!g) return HA_ERR_INTERNAL_ERROR; - PDBUSER dup= PlgGetUser(g); - PCATLG cat= (dup) ? dup->Catalog : NULL; PTOS topt= table_s->option_struct; char buf[1024]; String sql(buf, sizeof(buf), system_charset_info); diff --git a/storage/connect/value.h b/storage/connect/value.h index 9b4b9164fa5..a0d947347c3 100644 --- a/storage/connect/value.h +++ b/storage/connect/value.h @@ -412,7 +412,7 @@ class DllExport DTVAL : public TYPVAL { // Constructors DTVAL(PGLOBAL g, int n, int p, PCSZ fmt); DTVAL(int n); - using TYPVAL::SetValue; + using TYPVAL::SetValue; // Implementation virtual bool SetValue_pval(PVAL valp, bool chktype); From 6239e2a4ec4dc6ef6e99be73b8c5d7ad6e02cfc5 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 25 Jun 2021 11:38:16 +0200 Subject: [PATCH 12/18] Fix clang compile error in tabjson.cpp and tabbson.cpp --- storage/connect/tabbson.cpp | 2 +- storage/connect/tabjson.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index abffd0b64df..dd37357ac6a 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -608,7 +608,7 @@ void BSONDISC::AddColumn(PGLOBAL g) PBVAL BTUTIL::FindRow(PGLOBAL g) { char *p, *objpath = PlugDup(g, Tp->Objname); - char *sep = (Tp->Sep == ':') ? ":[" : ".["; + char *sep = (char*)(Tp->Sep == ':' ? ":[" : ".["); bool bp = false, b = false; PBVAL jsp = Tp->Row; PBVAL val = NULL; diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index b05e4ca2c01..09077ecdf93 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -962,7 +962,7 @@ int TDBJSN::EstimatedLength(void) PJSON TDBJSN::FindRow(PGLOBAL g) { char *p, *objpath = PlugDup(g, Objname); - char *sep = (Sep == ':') ? ":[" : ".["; + char *sep = (char*)(Sep == ':' ? ":[" : ".["); bool bp = false, b = false; PJSON jsp = Row; PJVAL val = NULL; From af7a0895ac6f57db0d4c83bede1a6115e9e11c1f Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 25 Jun 2021 12:30:10 +0200 Subject: [PATCH 13/18] Fix clang compile error in tabjson.cpp and tabbson.cpp --- storage/connect/tabbson.cpp | 2 +- storage/connect/tabjson.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index dd37357ac6a..05c47014e5c 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -676,7 +676,7 @@ PBVAL BTUTIL::MakeTopTree(PGLOBAL g, int type) if (!Tp->Row) { // Parse and allocate Objpath item(s) char *p, *objpath = PlugDup(g, Tp->Objname); - char *sep = (Tp->Sep == ':') ? ":[" : ".["; + char *sep = (char*)(Tp->Sep == ':' ? ":[" : ".["); int i; bool bp = false, b = false; PBVAL objp = NULL; diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index 09077ecdf93..de85344f869 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -1179,7 +1179,7 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) if (!Val) { // Parse and allocate Objname item(s) char *p, *objpath = PlugDup(g, Objname); - char *sep = (Sep == ':') ? ":[" : ".["; + char *sep = (char*)(Sep == ':' ? ":[" : ".["); int i; bool bp = false, b = false; PJOB objp; From 7863554e429d008c88ceff9d48c00eb10ea7d133 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 25 Jun 2021 12:54:34 +0200 Subject: [PATCH 14/18] Fix clang compile error in tabjson and typo in tabbson.cpp --- storage/connect/tabbson.cpp | 2 +- storage/connect/tabjson.cpp | 6 +++--- storage/connect/tabjson.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index 05c47014e5c..7f5727a9713 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -1492,7 +1492,7 @@ int TDBBSN::EstimatedLength(void) } // end of Estimated Length /***********************************************************************/ -/* OpenDB: Data Base open routine for JSN access method. */ +/* OpenDB: Data Base open routine for BSN access method. */ /***********************************************************************/ bool TDBBSN::OpenDB(PGLOBAL g) { diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index de85344f869..2db42cc8cbf 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -1173,7 +1173,7 @@ int TDBJSN::ReadDB(PGLOBAL g) { /***********************************************************************/ /* Make the top tree from the object path. */ /***********************************************************************/ -int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) +bool TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) { if (Objname) { if (!Val) { @@ -1210,7 +1210,7 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) // Old style if (objpath[strlen(objpath) - 1] != ']') { sprintf(g->Message, "Invalid Table path %s", Objname); - return NULL; + return true; } else if (!bp) objpath++; @@ -1239,7 +1239,7 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) } else Top = jsp; - return RC_OK; + return false; } // end of MakeTopTree /***********************************************************************/ diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h index 523015c66b2..623e5b6d509 100644 --- a/storage/connect/tabjson.h +++ b/storage/connect/tabjson.h @@ -170,7 +170,7 @@ public: protected: PJSON FindRow(PGLOBAL g); - int MakeTopTree(PGLOBAL g, PJSON jsp); + bool MakeTopTree(PGLOBAL g, PJSON jsp); // Members PGLOBAL G; // Support of parse memory From 1c4b917f0e82081950ca256fd7698dab8f4722e6 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 25 Jun 2021 18:35:26 +0200 Subject: [PATCH 15/18] Fix clang compile error in value.cpp --- storage/connect/value.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 8f2cb631feb..803bf9688be 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -2744,11 +2744,11 @@ void DTVAL::SetValue(int n) Tval = n; if (Pdtp) { - size_t n = 0, slen = (size_t)Len + 1; + size_t slen = (size_t)Len + 1; struct tm tm, *ptm= GetGmTime(&tm); if (ptm) - n = strftime(Sdate, slen, Pdtp->OutFmt, ptm); + strftime(Sdate, slen, Pdtp->OutFmt, ptm); } // endif Pdtp From 0f18135ec8f90f5736829fb36cab3da9196fd09f Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 24 Jul 2021 16:28:57 +0200 Subject: [PATCH 16/18] - Make user variable prefix recognized by IsArgJson and IsJson modified: storage/connect/bsonudf.cpp modified: storage/connect/jsonudf.cpp - Stringify option is now a ; separated list of columns modified: storage/connect/json.cpp modified: storage/connect/json.h modified: storage/connect/mongo.h modified: storage/connect/tabbson.cpp modified: storage/connect/tabcmg.cpp modified: storage/connect/tabcmg.h modified: storage/connect/tabjmg.cpp modified: storage/connect/tabjmg.h modified: storage/connect/tabjson.cpp - PrepareColist not a static function anymore (+ typo) modified: storage/connect/taboccur.cpp - JDVC: Recognize schema (database) from a wrapper server modified: storage/connect/tabjdbc.cpp --- storage/connect/bsonudf.cpp | 19 +++++++--- storage/connect/json.cpp | 26 ++++++++++++- storage/connect/json.h | 1 + storage/connect/jsonudf.cpp | 17 +++++++-- storage/connect/mongo.h | 2 +- storage/connect/tabbson.cpp | 5 ++- storage/connect/tabcmg.cpp | 3 +- storage/connect/tabcmg.h | 2 +- storage/connect/tabjdbc.cpp | 3 ++ storage/connect/tabjmg.cpp | 15 +++++--- storage/connect/tabjmg.h | 2 +- storage/connect/tabjson.cpp | 5 ++- storage/connect/taboccur.cpp | 72 ++++++++++++++++++------------------ 13 files changed, 111 insertions(+), 61 deletions(-) diff --git a/storage/connect/bsonudf.cpp b/storage/connect/bsonudf.cpp index d3174580e7f..783be52602a 100644 --- a/storage/connect/bsonudf.cpp +++ b/storage/connect/bsonudf.cpp @@ -1889,24 +1889,31 @@ static int *GetIntArgPtr(PGLOBAL g, UDF_ARGS *args, uint& n) /*********************************************************************************/ int IsArgJson(UDF_ARGS *args, uint i) { - int n = 0; + char *pat = args->attributes[i]; + int n = 0; + + if (*pat == '@') { + pat++; + + if (*pat == '\'' || *pat == '"') + pat++; + + } // endif pat if (i >= args->arg_count || args->arg_type[i] != STRING_RESULT) { - } else if (!strnicmp(args->attributes[i], "Bson_", 5) || - !strnicmp(args->attributes[i], "Json_", 5)) { + } else if (!strnicmp(pat, "Bson_", 5) || !strnicmp(pat, "Json_", 5)) { if (!args->args[i] || strchr("[{ \t\r\n", *args->args[i])) n = 1; // arg should be is a json item // else // n = 2; // A file name may have been returned - } else if (!strnicmp(args->attributes[i], "Bbin_", 5)) { + } else if (!strnicmp(pat, "Bbin_", 5)) { if (args->lengths[i] == sizeof(BSON)) n = 3; // arg is a binary json item // else // n = 2; // A file name may have been returned - } else if (!strnicmp(args->attributes[i], "Bfile_", 6) || - !strnicmp(args->attributes[i], "Jfile_", 6)) { + } else if (!strnicmp(pat, "Bfile_", 6) || !strnicmp(pat, "Jfile_", 6)) { n = 2; // arg is a json file name #if 0 } else if (args->lengths[i]) { diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index 9b7145bb498..b1d4decdcdb 100644 --- a/storage/connect/json.cpp +++ b/storage/connect/json.cpp @@ -1,7 +1,7 @@ /*************** json CPP Declares Source Code File (.H) ***************/ -/* Name: json.cpp Version 1.5 */ +/* Name: json.cpp Version 1.6 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2014 - 2020 */ +/* (C) Copyright to the author Olivier BERTRAND 2014 - 2021 */ /* */ /* This file contains the JSON classes functions. */ /***********************************************************************/ @@ -55,6 +55,7 @@ char *GetExceptionDesc(PGLOBAL g, unsigned int e); char *GetJsonNull(void); int GetDefaultPrec(void); +int PrepareColist(char*); /***********************************************************************/ /* IsNum: check whether this string is all digits. */ @@ -111,6 +112,27 @@ char* NextChr(PSZ s, char sep) return p2; } // end of NextChr +/***********************************************************************/ +/* Stringified: check that this column is in the stringified list. */ +/***********************************************************************/ +bool Stringified(PCSZ strfy, char *colname) +{ + if (strfy) { + char *p, colist[512]; + int n; + + strncpy(colist, strfy, sizeof(colist) - 1); + n = PrepareColist(colist); + + for (p = colist; n && p; p += (strlen(p) + 1), n--) + if (!stricmp(p, colname)) + return true; + + } // endif strfy + + return false; +} // end of Stringified + #if 0 /***********************************************************************/ /* Allocate a VAL structure, make sure common field and Nd are zeroed. */ diff --git a/storage/connect/json.h b/storage/connect/json.h index 566cb64cc23..53fc5f65e7b 100644 --- a/storage/connect/json.h +++ b/storage/connect/json.h @@ -67,6 +67,7 @@ PJSON ParseJson(PGLOBAL g, char* s, size_t n, int* prty = NULL, bool* b = NULL); PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty); DllExport bool IsNum(PSZ s); bool IsArray(PSZ s); +bool Stringified(PCSZ strfy, char *colname); /***********************************************************************/ /* Class JDOC. The class for parsing and serializing json documents. */ diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 1f635002e7e..c1df923f0b8 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -1524,22 +1524,31 @@ static int *GetIntArgPtr(PGLOBAL g, UDF_ARGS *args, uint& n) /*********************************************************************************/ int IsJson(UDF_ARGS *args, uint i, bool b) { - int n = 0; + char *pat = args->attributes[i]; + int n = 0; + + if (*pat == '@') { + pat++; + + if (*pat == '\'' || *pat == '"') + pat++; + + } // endif pat if (i >= args->arg_count || args->arg_type[i] != STRING_RESULT) { - } else if (!strnicmp(args->attributes[i], "Json_", 5)) { + } else if (!strnicmp(pat, "Json_", 5)) { if (!args->args[i] || strchr("[{ \t\r\n", *args->args[i])) n = 1; // arg should be is a json item else n = 2; // A file name may have been returned - } else if (!strnicmp(args->attributes[i], "Jbin_", 5)) { + } else if (!strnicmp(pat, "Jbin_", 5)) { if (args->lengths[i] == sizeof(BSON)) n = 3; // arg is a binary json item else n = 2; // A file name may have been returned - } else if (!strnicmp(args->attributes[i], "Jfile_", 6)) { + } else if (!strnicmp(pat, "Jfile_", 6)) { n = 2; // arg is a json file name } else if (b) { char *sap; diff --git a/storage/connect/mongo.h b/storage/connect/mongo.h index fddc491f2d0..7e92a7dc8e9 100644 --- a/storage/connect/mongo.h +++ b/storage/connect/mongo.h @@ -82,7 +82,7 @@ protected: PSZ Wrapname; /* Java wrapper name */ PCSZ Colist; /* Options list */ PCSZ Filter; /* Filtering query */ - PCSZ Strfy; /* Stringify column */ + PCSZ Strfy; /* The stringify columns */ int Base; /* The array index base */ int Version; /* The Java driver version */ bool Pipe; /* True is Colist is a pipeline */ diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp index 7f5727a9713..3b1f1c84d1a 100644 --- a/storage/connect/tabbson.cpp +++ b/storage/connect/tabbson.cpp @@ -53,6 +53,7 @@ USETEMP UseTemp(void); bool JsonAllPath(void); int GetDefaultDepth(void); char *GetJsonNull(void); +bool Stringified(PCSZ, char*); /***********************************************************************/ /* BSONColumns: construct the result blocks containing the description */ @@ -436,7 +437,7 @@ bool BSONDISC::Find(PGLOBAL g, PBVAL jvp, PCSZ key, int j) jcol.Type = TYPE_UNKNOWN; jcol.Len = jcol.Scale = 0; jcol.Cbn = true; - } else if (j < lvl && !(strfy && !stricmp(strfy, colname))) { + } else if (j < lvl && !Stringified(strfy, colname)) { if (!fmt[bf]) strcat(fmt, colname); @@ -507,7 +508,7 @@ bool BSONDISC::Find(PGLOBAL g, PBVAL jvp, PCSZ key, int j) } // endswitch Type } else if (lvl >= 0) { - if (strfy && !stricmp(strfy, colname)) { + if (Stringified(strfy, colname)) { if (!fmt[bf]) strcat(fmt, colname); diff --git a/storage/connect/tabcmg.cpp b/storage/connect/tabcmg.cpp index 608445bb1ab..56d705f42ca 100644 --- a/storage/connect/tabcmg.cpp +++ b/storage/connect/tabcmg.cpp @@ -27,6 +27,7 @@ #include "filter.h" PQRYRES MGOColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt, bool info); +bool Stringified(PCSZ, char*); /* -------------------------- Class CMGDISC -------------------------- */ @@ -397,7 +398,7 @@ MGOCOL::MGOCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) : EXTCOL(cdp, tdbp, cprec, i, "MGO") { Tmgp = (PTDBCMG)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); - Sgfy = (Tmgp->Strfy && !stricmp(Tmgp->Strfy, Name)); + Sgfy = Stringified(Tmgp->Strfy, Name); if ((Jpath = cdp->GetFmt())) { int n = strlen(Jpath) - 1; diff --git a/storage/connect/tabcmg.h b/storage/connect/tabcmg.h index 0a29a6ce909..9effe714fdd 100644 --- a/storage/connect/tabcmg.h +++ b/storage/connect/tabcmg.h @@ -75,7 +75,7 @@ protected: CMgoConn *Cmgp; // Points to a C Mongo connection class CMGOPARM Pcg; // Parms passed to Cmgp const Item *Cnd; // The first condition - PCSZ Strfy; // The stringified column + PCSZ Strfy; // The stringified columns int Fpos; // The current row index int N; // The current Rownum int B; // Array index base diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index 7a8eedad12b..9721c62be7d 100644 --- a/storage/connect/tabjdbc.cpp +++ b/storage/connect/tabjdbc.cpp @@ -188,6 +188,9 @@ int JDBCDEF::ParseURL(PGLOBAL g, char *url, bool b) } else // host is a URL Url = PlugDup(g, server->host); + if (!Tabschema && server->db) + Tabschema = PlugDup(g, server->db); + if (!Username && server->username) Username = PlugDup(g, server->username); diff --git a/storage/connect/tabjmg.cpp b/storage/connect/tabjmg.cpp index 9271873b800..983ee39d65f 100644 --- a/storage/connect/tabjmg.cpp +++ b/storage/connect/tabjmg.cpp @@ -30,6 +30,7 @@ #define nullptr 0 PQRYRES MGOColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt, bool info); +bool Stringified(PCSZ, char*); /* -------------------------- Class JMGDISC -------------------------- */ @@ -423,15 +424,19 @@ JMGCOL::JMGCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) : EXTCOL(cdp, tdbp, cprec, i, "MGO") { Tmgp = (PTDBJMG)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp); - Sgfy = (Tmgp->Strfy && !stricmp(Tmgp->Strfy, Name)); + Sgfy = Stringified(Tmgp->Strfy, Name); if ((Jpath = cdp->GetFmt())) { - int n = strlen(Jpath) - 1; + int n = strlen(Jpath); - if (Jpath[n] == '*') { + if (n && Jpath[n - 1] == '*') { Jpath = PlugDup(g, cdp->GetFmt()); - if (Jpath[n - 1] == '.') n--; - Jpath[n] = 0; + + if (--n) { + if (Jpath[n - 1] == '.') n--; + Jpath[n] = 0; + } // endif n + Sgfy = true; } // endif Jpath diff --git a/storage/connect/tabjmg.h b/storage/connect/tabjmg.h index bc89319527a..cf7cff83b68 100644 --- a/storage/connect/tabjmg.h +++ b/storage/connect/tabjmg.h @@ -83,7 +83,7 @@ protected: PCSZ Coll_name; PCSZ Options; // The MongoDB options PCSZ Filter; // The filtering query - PCSZ Strfy; // The stringified column + PCSZ Strfy; // The stringified columns PSZ Wrapname; // Java wrapper name int Fpos; // The current row index int N; // The current Rownum diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index 2db42cc8cbf..7eff0a68c4b 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -58,6 +58,7 @@ USETEMP UseTemp(void); bool JsonAllPath(void); int GetDefaultDepth(void); char *GetJsonNull(void); +bool Stringified(PCSZ, char*); /***********************************************************************/ /* JSONColumns: construct the result blocks containing the description */ @@ -447,7 +448,7 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j) jcol.Type = TYPE_UNKNOWN; jcol.Len = jcol.Scale = 0; jcol.Cbn = true; - } else if (j < lvl && !(strfy && !stricmp(strfy, colname))) { + } else if (j < lvl && !Stringified(strfy, colname)) { if (!fmt[bf]) strcat(fmt, colname); @@ -517,7 +518,7 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j) } // endswitch Type } else if (lvl >= 0) { - if (strfy && !stricmp(strfy, colname)) { + if (Stringified(strfy, colname)) { if (!fmt[bf]) strcat(fmt, colname); diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp index 6bf2bd2b47f..c63972ec7ab 100644 --- a/storage/connect/taboccur.cpp +++ b/storage/connect/taboccur.cpp @@ -1,7 +1,7 @@ /************ TabOccur CPP Declares Source Code File (.CPP) ************/ /* Name: TABOCCUR.CPP Version 1.2 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2013 - 2017 */ +/* (C) Copyright to the author Olivier BERTRAND 2013 - 2021 */ /* */ /* OCCUR: Table that provides a view of a source table where the */ /* contain of several columns of the source table is placed in only */ @@ -52,8 +52,8 @@ /***********************************************************************/ /* Prepare and count columns in the column list. */ /***********************************************************************/ -static int PrepareColist(char *colist) - { +int PrepareColist(char *colist) +{ char *p, *pn; int n = 0; @@ -71,7 +71,7 @@ static int PrepareColist(char *colist) } // endif p return n; - } // end of PrepareColist +} // end of PrepareColist /************************************************************************/ /* OcrColumns: constructs the result blocks containing all the columns */ @@ -79,7 +79,7 @@ static int PrepareColist(char *colist) /************************************************************************/ bool OcrColumns(PGLOBAL g, PQRYRES qrp, const char *col, const char *ocr, const char *rank) - { +{ char *pn, *colist; int i, k, m, n = 0, c = 0, j = qrp->Nblin; bool rk, b = false; @@ -168,7 +168,7 @@ bool OcrColumns(PGLOBAL g, PQRYRES qrp, const char *col, /**********************************************************************/ qrp->Nblin = j; return false; - } // end of OcrColumns +} // end of OcrColumns /************************************************************************/ /* OcrSrcCols: constructs the result blocks containing all the columns */ @@ -176,7 +176,7 @@ bool OcrColumns(PGLOBAL g, PQRYRES qrp, const char *col, /************************************************************************/ bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, const char *col, const char *ocr, const char *rank) - { +{ char *pn, *colist; int i, k, m, n = 0, c = 0; bool rk, b = false; @@ -249,7 +249,7 @@ bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, const char *col, /**********************************************************************/ qrp->Nblin = i; return false; - } // end of OcrSrcCols +} // end of OcrSrcCols /* -------------- Implementation of the OCCUR classes ---------------- */ @@ -257,24 +257,24 @@ bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, const char *col, /* DefineAM: define specific AM block values from OCCUR table. */ /***********************************************************************/ bool OCCURDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) - { +{ Rcol = GetStringCatInfo(g, "RankCol", ""); Colist = GetStringCatInfo(g, "Colist", ""); Xcol = GetStringCatInfo(g, "OccurCol", Colist); return PRXDEF::DefineAM(g, am, poff); - } // end of DefineAM +} // end of DefineAM /***********************************************************************/ /* GetTable: makes a new TDB of the proper type. */ /***********************************************************************/ PTDB OCCURDEF::GetTable(PGLOBAL g, MODE) - { +{ if (Catfunc != FNC_COL) return new(g) TDBOCCUR(this); else return new(g) TDBTBC(this); - } // end of GetTable +} // end of GetTable /* ------------------------------------------------------------------- */ @@ -282,7 +282,7 @@ PTDB OCCURDEF::GetTable(PGLOBAL g, MODE) /* Implementation of the TDBOCCUR class. */ /***********************************************************************/ TDBOCCUR::TDBOCCUR(POCCURDEF tdp) : TDBPRX(tdp) - { +{ //Tdbp = NULL; // Source table (in TDBPRX) Tabname = tdp->Tablep->GetName(); // Name of source table Colist = tdp->Colist; // List of source columns @@ -294,13 +294,13 @@ TDBOCCUR::TDBOCCUR(POCCURDEF tdp) : TDBPRX(tdp) N = 0; // The current table index M = 0; // The occurence rank RowFlag = 0; // 0: Ok, 1: Same, 2: Skip - } // end of TDBOCCUR constructor +} // end of TDBOCCUR constructor /***********************************************************************/ /* Allocate OCCUR/SRC column description block. */ /***********************************************************************/ PCOL TDBOCCUR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) - { +{ PCOL colp = NULL; if (!stricmp(cdp->GetName(), Rcolumn)) { @@ -321,13 +321,13 @@ PCOL TDBOCCUR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) } // endif cprec return colp; - } // end of MakeCol +} // end of MakeCol /***********************************************************************/ /* Initializes the table. */ /***********************************************************************/ bool TDBOCCUR::InitTable(PGLOBAL g) - { +{ if (!Tdbp) // Get the table description block of this table if (!(Tdbp = GetSubTable(g, ((POCCURDEF)To_Def)->Tablep, TRUE))) @@ -338,13 +338,13 @@ bool TDBOCCUR::InitTable(PGLOBAL g) return TRUE; return FALSE; - } // end of InitTable +} // end of InitTable /***********************************************************************/ /* Allocate OCCUR column description block. */ /***********************************************************************/ bool TDBOCCUR::MakeColumnList(PGLOBAL g) - { +{ char *pn; int i; PCOL colp; @@ -371,13 +371,13 @@ bool TDBOCCUR::MakeColumnList(PGLOBAL g) } // endfor i return false; - } // end of MakeColumnList +} // end of MakeColumnList /***********************************************************************/ /* Allocate OCCUR column description block for a view. */ /***********************************************************************/ bool TDBOCCUR::ViewColumnList(PGLOBAL g) - { +{ char *pn; int i; PCOL colp, cp; @@ -412,13 +412,13 @@ bool TDBOCCUR::ViewColumnList(PGLOBAL g) } // endif Col return false; - } // end of ViewColumnList +} // end of ViewColumnList /***********************************************************************/ /* OCCUR GetMaxSize: returns the maximum number of rows in the table. */ /***********************************************************************/ int TDBOCCUR::GetMaxSize(PGLOBAL g) - { +{ if (MaxSize < 0) { if (!(Tdbp = GetSubTable(g, ((POCCURDEF)To_Def)->Tablep, TRUE))) return 0; @@ -427,22 +427,22 @@ int TDBOCCUR::GetMaxSize(PGLOBAL g) } // endif MaxSize return MaxSize; - } // end of GetMaxSize +} // end of GetMaxSize /***********************************************************************/ /* In this sample, ROWID will be the (virtual) row number, */ /* while ROWNUM will be the occurence rank in the multiple column. */ /***********************************************************************/ int TDBOCCUR::RowNumber(PGLOBAL, bool b) - { +{ return (b) ? M : N; - } // end of RowNumber +} // end of RowNumber /***********************************************************************/ /* OCCUR Access Method opening routine. */ /***********************************************************************/ bool TDBOCCUR::OpenDB(PGLOBAL g) - { +{ if (Use == USE_OPEN) { /*******************************************************************/ /* Table already open, just replace it at its beginning. */ @@ -491,13 +491,13 @@ bool TDBOCCUR::OpenDB(PGLOBAL g) Use = USE_OPEN; return ViewColumnList(g); - } // end of OpenDB +} // end of OpenDB /***********************************************************************/ /* Data Base read routine for OCCUR access method. */ /***********************************************************************/ int TDBOCCUR::ReadDB(PGLOBAL g) - { +{ int rc = RC_OK; /*********************************************************************/ @@ -518,7 +518,7 @@ int TDBOCCUR::ReadDB(PGLOBAL g) N++; return rc; - } // end of ReadDB +} // end of ReadDB // ------------------------ OCCURCOL functions ---------------------------- @@ -527,17 +527,17 @@ int TDBOCCUR::ReadDB(PGLOBAL g) /***********************************************************************/ OCCURCOL::OCCURCOL(PCOLDEF cdp, PTDBOCCUR tdbp, int n) : COLBLK(cdp, tdbp, n) - { +{ // Set additional OCCUR access method information for column. I = 0; - } // end of OCCURCOL constructor +} // end of OCCURCOL constructor /***********************************************************************/ /* ReadColumn: what this routine does is to access the columns of */ /* list, extract their value and convert it to buffer type. */ /***********************************************************************/ void OCCURCOL::ReadColumn(PGLOBAL g) - { +{ PTDBOCCUR tdbp = (PTDBOCCUR)To_Tdb; PCOL *col = tdbp->Col; @@ -559,7 +559,7 @@ void OCCURCOL::ReadColumn(PGLOBAL g) // Set the OCCUR column value from the Ith source column value Value->SetValue_pval(col[I++]->GetValue()); tdbp->RowFlag = 1; - } // end of ReadColumn +} // end of ReadColumn // ------------------------ RANKCOL functions --------------------------- @@ -569,7 +569,7 @@ void OCCURCOL::ReadColumn(PGLOBAL g) /* list, extract its name and set to it the rank column value. */ /***********************************************************************/ void RANKCOL::ReadColumn(PGLOBAL) - { +{ PTDBOCCUR tdbp = (PTDBOCCUR)To_Tdb; PCOL *col = tdbp->Col; @@ -584,4 +584,4 @@ void RANKCOL::ReadColumn(PGLOBAL) } // endelse - } // end of ReadColumn +} // end of ReadColumn From 5049887c8d425508ad9ceaba18f34a55941337c3 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 24 Jul 2021 18:24:20 +0200 Subject: [PATCH 17/18] Replace Mongo2.jar and Mongo3.jar with ne versions --- storage/connect/Mongo2.jar | Bin 623907 -> 624130 bytes storage/connect/Mongo3.jar | Bin 1705776 -> 1706057 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/storage/connect/Mongo2.jar b/storage/connect/Mongo2.jar index 9be654bd4c8e2a1a3fd159c2a69acb5acc55011c..d51cc5d234554de2544239cc40b7b84a30685c09 100644 GIT binary patch delta 34056 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 {=;Er-3$?bU0v9?M+X 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 aj;?yYo>njqg=ytxWp%S`8C_%gF!O)sA#@Y~ From fc98a6d54a7d72865f8f3e580af588bb6ac5fd57 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 24 Jul 2021 18:31:59 +0200 Subject: [PATCH 18/18] Fix compile error for centos 74 Modified taboccur.cpp --- storage/connect/taboccur.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp index c63972ec7ab..28270e77fd9 100644 --- a/storage/connect/taboccur.cpp +++ b/storage/connect/taboccur.cpp @@ -49,6 +49,8 @@ #include "tabmysql.h" #include "ha_connect.h" +int PrepareColist(char *colist); + /***********************************************************************/ /* Prepare and count columns in the column list. */ /***********************************************************************/