diff options
Diffstat (limited to 'storage/connect/tabcmg.cpp')
-rw-r--r-- | storage/connect/tabcmg.cpp | 506 |
1 files changed, 506 insertions, 0 deletions
diff --git a/storage/connect/tabcmg.cpp b/storage/connect/tabcmg.cpp new file mode 100644 index 00000000..56d705f4 --- /dev/null +++ b/storage/connect/tabcmg.cpp @@ -0,0 +1,506 @@ +/************** tabcmg C++ Program Source Code File (.CPP) *************/ +/* 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. */ +/***********************************************************************/ + +/***********************************************************************/ +/* Include relevant sections of the MariaDB header file. */ +/***********************************************************************/ +#include <my_global.h> + +/***********************************************************************/ +/* Include application header files: */ +/* global.h is header containing all global declarations. */ +/* plgdbsem.h is header containing the DB application declarations. */ +/* tdbdos.h is header containing the TDBDOS declarations. */ +/* json.h is header containing the JSON classes declarations. */ +/***********************************************************************/ +#include "global.h" +#include "plgdbsem.h" +#include "xtable.h" +#include "maputil.h" +#include "filamtxt.h" +#include "tabext.h" +#include "tabcmg.h" +#include "tabmul.h" +#include "filter.h" + +PQRYRES MGOColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt, bool info); +bool Stringified(PCSZ, char*); + +/* -------------------------- Class CMGDISC -------------------------- */ + +/***********************************************************************/ +/* Get document. */ +/***********************************************************************/ +void CMGDISC::GetDoc(void) +{ + doc = ((TDBCMG*)tmgp)->Cmgp->Document; +} // end of GetDoc + +/***********************************************************************/ +/* Analyse passed document. */ +/***********************************************************************/ +//bool CMGDISC::Find(PGLOBAL g, int i, int k, bool b) +bool CMGDISC::Find(PGLOBAL g) +{ + return FindInDoc(g, &iter, doc, NULL, NULL, 0, false); +} // end of Find + +/***********************************************************************/ +/* Analyse passed document. */ +/***********************************************************************/ +bool CMGDISC::FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc, + char *pcn, char *pfmt, int k, bool b) +{ + if (!doc || bson_iter_init(iter, doc)) { + const char *key; + char colname[65]; + char fmt[129]; + bool newcol; + size_t n; + + while (bson_iter_next(iter)) { + key = bson_iter_key(iter); + newcol = true; + + if (pcn) { + n = sizeof(colname) - 1; + strncpy(colname, pcn, n); + colname[n] = 0; + n -= strlen(colname); + strncat(strncat(colname, "_", n), key, n - 1); + } else + strcpy(colname, key); + + if (pfmt) { + n = sizeof(fmt) - 1; + strncpy(fmt, pfmt, n); + fmt[n] = 0; + n -= strlen(fmt); + strncat(strncat(fmt, ".", n), key, n - 1); + } else + strcpy(fmt, key); + + bcol.Cbn = false; + + switch (bson_iter_type(iter)) { + case BSON_TYPE_UTF8: + bcol.Type = TYPE_STRING; + 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)) + 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 + + break; + } // endswitch iter + + if (newcol) + AddColumn(g, colname, fmt, k); + + if (b) + break; // Test only first element of arrays + + } // endwhile iter + + } // endif doc + + return false; +} // end of FindInDoc + +/* --------------------------- Class TDBCMG -------------------------- */ + +/***********************************************************************/ +/* Implementation of the TDBCMG class. */ +/***********************************************************************/ +TDBCMG::TDBCMG(MGODEF *tdp) : TDBEXT(tdp) +{ + Cmgp = NULL; + Cnd = NULL; + Pcg.Tdbp = this; + + if (tdp) { + Pcg.Uristr = tdp->Uri; + Pcg.Db_name = tdp->Tabschema; + 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; + Strfy = tdp->Strfy; + } else { + Pcg.Uristr = NULL; + Pcg.Db_name = NULL; + Pcg.Coll_name = NULL; + Pcg.Options = NULL; + Pcg.Filter = NULL; + Pcg.Line = NULL; + Pcg.Pipe = false; + Strfy = NULL; + B = 0; + } // endif tdp + + Fpos = -1; + N = 0; + Done = false; +} // end of TDBCMG standard constructor + +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; + Done = tdbp->Done; +} // end of TDBCMG copy constructor + +// Used for update +PTDB TDBCMG::Clone(PTABS t) +{ + PTDB tp; + PMGOCOL cp1, cp2; + PGLOBAL g = t->G; + + tp = new(g) TDBCMG(this); + + for (cp1 = (PMGOCOL)Columns; cp1; cp1 = (PMGOCOL)cp1->GetNext()) + if (!cp1->IsSpecial()) { + cp2 = new(g) MGOCOL(cp1, tp); // Make a copy + NewPointer(t, cp1, cp2); + } // endif cp1 + + return tp; +} // end of Clone + +/***********************************************************************/ +/* Allocate JSN column description block. */ +/***********************************************************************/ +PCOL TDBCMG::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) +{ + PMGOCOL colp = new(g) MGOCOL(g, cdp, this, cprec, n); + + return colp; +} // end of MakeCol + +/***********************************************************************/ +/* InsertSpecialColumn: Put a special column ahead of the column list.*/ +/***********************************************************************/ +PCOL TDBCMG::InsertSpecialColumn(PCOL colp) +{ + if (!colp->IsSpecial()) + return NULL; + + colp->SetNext(Columns); + Columns = colp; + return colp; +} // end of InsertSpecialColumn + +/***********************************************************************/ +/* Init: initialize MongoDB processing. */ +/***********************************************************************/ +bool TDBCMG::Init(PGLOBAL g) +{ + if (Done) + return false; + + /*********************************************************************/ + /* Open an C connection for this table. */ + /*********************************************************************/ + if (!Cmgp) + Cmgp = new(g) CMgoConn(g, &Pcg); + else if (Cmgp->IsConnected()) + Cmgp->Close(); + + if (Cmgp->Connect(g)) + return true; + + Done = true; + return false; +} // end of Init + +/***********************************************************************/ +/* MONGO Cardinality: returns table size in number of rows. */ +/***********************************************************************/ +int TDBCMG::Cardinality(PGLOBAL g) +{ + if (!g) + return 1; + else if (Cardinal < 0) + Cardinal = (!Init(g)) ? Cmgp->CollSize(g) : 0; + + return Cardinal; +} // end of Cardinality + +/***********************************************************************/ +/* MONGO GetMaxSize: returns collection size estimate. */ +/***********************************************************************/ +int TDBCMG::GetMaxSize(PGLOBAL g) +{ + if (MaxSize < 0) + MaxSize = Cardinality(g); + + return MaxSize; +} // end of GetMaxSize + +/***********************************************************************/ +/* OpenDB: Data Base open routine for MONGO access method. */ +/***********************************************************************/ +bool TDBCMG::OpenDB(PGLOBAL g) +{ + if (Use == USE_OPEN) { + /*******************************************************************/ + /* Table already open replace it at its beginning. */ + /*******************************************************************/ + Cmgp->Rewind(); + Fpos = -1; + return false; + } // endif Use + + /*********************************************************************/ + /* First opening. */ + /*********************************************************************/ + if (Pcg.Pipe && Mode != MODE_READ) { + strcpy(g->Message, "Pipeline tables are read only"); + return true; + } // endif Pipe + + Use = USE_OPEN; // Do it now in case we are recursively called + + if (Init(g)) + return true; + + if (Mode == MODE_DELETE && !Next) + // Delete all documents + return Cmgp->DocDelete(g); + else if (Mode == MODE_INSERT) + Cmgp->MakeColumnGroups(g); + + return false; +} // end of OpenDB + +/***********************************************************************/ +/* Data Base indexed read routine for ODBC access method. */ +/***********************************************************************/ +bool TDBCMG::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr) +{ + strcpy(g->Message, "MONGO tables are not indexable"); + return true; +} // end of ReadKey + +/***********************************************************************/ +/* ReadDB: Get next document from a collection. */ +/***********************************************************************/ +int TDBCMG::ReadDB(PGLOBAL g) +{ + return Cmgp->ReadNext(g); +} // end of ReadDB + +/***********************************************************************/ +/* WriteDB: Data Base write routine for MGO access method. */ +/***********************************************************************/ +int TDBCMG::WriteDB(PGLOBAL g) +{ + return Cmgp->Write(g); +} // end of WriteDB + +/***********************************************************************/ +/* Data Base delete line routine for MGO access method. */ +/***********************************************************************/ +int TDBCMG::DeleteDB(PGLOBAL g, int irc) +{ + return (irc == RC_OK) ? WriteDB(g) : RC_OK; +} // end of DeleteDB + +/***********************************************************************/ +/* Table close routine for MONGO tables. */ +/***********************************************************************/ +void TDBCMG::CloseDB(PGLOBAL g) +{ + Cmgp->Close(); + Done = false; +} // end of CloseDB + +/* ----------------------------- MGOCOL ------------------------------ */ + +/***********************************************************************/ +/* MGOCOL public constructor. */ +/***********************************************************************/ +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 = Stringified(Tmgp->Strfy, Name); + + 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 + +/***********************************************************************/ +/* MGOCOL constructor used for copying columns. */ +/* tdbp is the pointer to the new table descriptor. */ +/***********************************************************************/ +MGOCOL::MGOCOL(MGOCOL *col1, PTDB tdbp) : EXTCOL(col1, tdbp) +{ + Tmgp = col1->Tmgp; + Jpath = col1->Jpath; + Sgfy = col1->Sgfy; +} // end of MGOCOL copy constructor + +/***********************************************************************/ +/* Get path when proj is false or projection path when proj is true. */ +/***********************************************************************/ +PSZ MGOCOL::GetJpath(PGLOBAL g, bool proj) +{ + if (Jpath) { + if (proj) { + char *p1, *p2, *projpath = PlugDup(g, Jpath); + int i = 0; + + for (p1 = p2 = projpath; *p1; p1++) + if (*p1 == '.') { + if (!i) + *p2++ = *p1; + + i = 1; + } else if (i) { + if (!isdigit(*p1)) { + *p2++ = *p1; + i = 0; + } // endif p1 + + } else + *p2++ = *p1; + + if (*(p2 - 1) == '.') + p2--; + + *p2 = 0; + return projpath; + } else + return Jpath; + + } else + return Name; + +} // end of GetJpath + +/***********************************************************************/ +/* ReadColumn: */ +/***********************************************************************/ +void MGOCOL::ReadColumn(PGLOBAL g) +{ + Tmgp->Cmgp->GetColumnValue(g, this); +} // end of ReadColumn + +/***********************************************************************/ +/* WriteColumn: */ +/***********************************************************************/ +void MGOCOL::WriteColumn(PGLOBAL g) +{ + // Check whether this node must be written + if (Value != To_Val) + Value->SetValue_pval(To_Val, FALSE); // Convert the updated value + +} // end of WriteColumn + +/* ---------------------------TDBGOL class --------------------------- */ + +/***********************************************************************/ +/* TDBGOL class constructor. */ +/***********************************************************************/ +TDBGOL::TDBGOL(PMGODEF tdp) : TDBCAT(tdp) +{ + Topt = tdp->GetTopt(); + Uri = tdp->Uri; + Db = tdp->GetTabschema(); +} // end of TDBJCL constructor + +/***********************************************************************/ +/* GetResult: Get the list the JSON file columns. */ +/***********************************************************************/ +PQRYRES TDBGOL::GetResult(PGLOBAL g) +{ + return MGOColumns(g, Db, Uri, Topt, false); +} // end of GetResult + +/* -------------------------- End of mongo --------------------------- */ |