/************* tabbson C++ Program Source Code File (.CPP) *************/ /* PROGRAM NAME: tabbson Version 1.2 */ /* (C) Copyright to the author Olivier BERTRAND 2020 - 2021 */ /* This program are the BSON 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"maputil.h" #include"filamtxt.h" #include"tabdos.h" #include"tabbson.h" #include"filamap.h" #ifdefined(GZ_SUPPORT) #include"filamgz.h" #endif// GZ_SUPPORT #ifdefined(ZIP_SUPPORT) #include"filamzip.h" #endif// ZIP_SUPPORT #ifdefined(JAVA_SUPPORT) #include"jmgfam.h" #endif// JAVA_SUPPORT #ifdefined(CMGO_SUPPORT) #include"cmgfam.h" #endif// CMGO_SUPPORT #include"tabmul.h" #include"checklvl.h" #include"resource.h" #include"mycat.h"// for FNC_COL #include"m_string.h"
/***********************************************************************/ /* This should be an option. */ /***********************************************************************/ #define MAXCOL 200/* Default max column nb in result */ //#define TYPE_UNKNOWN 12 /* Must be greater than other types */
if (!(n = pjdc->GetColumns(g, db, dsn, topt))) return NULL;
skipit: if (trace(1))
htrc("BSONColumns: n=%d len=%d\n", n, length[0]);
/*********************************************************************/ /* Allocate the structures used to refer to the result set. */ /*********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
buftyp, fldtyp, length, false, false);
/*********************************************************************/ /* Now get the results into blocks. */ /*********************************************************************/ for (i = 0, jcp = pjdc->fjcp; jcp; i++, jcp = jcp->Next) { if (jcp->Type == TYPE_UNKNOWN)
jcp->Type = TYPE_STRG; // Void column
crp = qrp->Colresp; // Column Name
crp->Kdata->SetValue(jcp->Name, i);
crp = crp->Next; // Data Type
crp->Kdata->SetValue(jcp->Type, i);
crp = crp->Next; // Type Name
crp->Kdata->SetValue(GetTypeName(jcp->Type), i);
crp = crp->Next; // Precision
crp->Kdata->SetValue(jcp->Len, i);
crp = crp->Next; // Length
crp->Kdata->SetValue(jcp->Len, i);
crp = crp->Next; // Scale (precision)
crp->Kdata->SetValue(jcp->Scale, i);
crp = crp->Next; // Nullable
crp->Kdata->SetValue(jcp->Cbn ? 1 : 0, i);
crp = crp->Next; // Field format
if (crp->Kdata)
crp->Kdata->SetValue(jcp->Fmt, i);
} // endfor i
/*********************************************************************/ /* Return the result pointer. */ /*********************************************************************/ return qrp;
} // end of BSONColumns
/* -------------------------- Class BSONDISC ------------------------- */
/***********************************************************************/ /* Class used to get the columns of a JSON table. */ /***********************************************************************/
BSONDISC::BSONDISC(PGLOBAL g, uint* lg)
{
length = lg;
jcp = fjcp = pjcp = NULL;
tdp = NULL;
tjnp = NULL;
jpp = NULL;
tjsp = NULL;
jsp = NULL;
bp = NULL;
row = NULL;
sep = NULL;
strfy = NULL;
i = n = bf = ncol = lvl = sz = limit = 0;
all = false;
} // end of BSONDISC constructor
if (tdp->Fn) { // We used the file name relative to recorded datapath
PlugSetPath(filename, tdp->Fn, tdp->GetPath());
tdp->Fn = PlugDup(g, filename);
} // endif Fn
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
/***********************************************************************/ /* Parse the read line. */ /***********************************************************************/
PBVAL BTUTIL::ParseLine(PGLOBAL g, int prty, bool cma)
{
pretty = prty;
comma = cma; return ParseJson(g, Tp->To_Line, strlen(Tp->To_Line));
} // end of ParseLine
/***********************************************************************/ /* Make the top tree from the object path. */ /***********************************************************************/
PBVAL BTUTIL::MakeTopTree(PGLOBAL g, int type)
{
PBVAL top = NULL, val = NULL;
if (Tp->Objname) { if (!Tp->Row) { // Parse and allocate Objpath item(s) char *p, *objpath = PlugDup(g, Tp->Objname); char *sep = (char*)(Tp->Sep == ':' ? ":[" : ".["); int i; bool bp = false, b = false;
PBVAL objp = NULL;
PBVAL arp = NULL;
for (; objpath; objpath = p, bp = b) { if ((p = strpbrk(objpath + 1, sep))) {
b = (*p == '[');
*p++ = 0;
} // endif p
if (!bp && *objpath != '[' && !IsNum(objpath)) { // objpass is a key
objp = NewVal(TYPE_JOB);
if (!top)
top = objp;
if (val)
SetValueObj(val, objp);
val = NewVal();
SetKeyValue(objp, MOF(val), objpath);
} else { if (bp || *objpath == '[') { // Old style if (objpath[strlen(objpath) - 1] != ']') {
snprintf(g->Message, sizeof(g->Message), "Invalid Table path %s", Tp->Objname); return NULL;
} elseif (!bp)
objpath++;
} // endif bp
if (!top)
top = NewVal(TYPE_JAR);
if (val)
SetValueArr(val, arp);
val = NewVal();
i = atoi(objpath) - Tp->B;
SetArrayValue(arp, val, i);
} // endif objpath
} // endfor p
} // endif Val
Tp->Row = val; if (Tp->Row) Tp->Row->Type = type;
} else
top = Tp->Row = NewVal(type);
return top;
} // end of MakeTopTree
PSZ BTUTIL::SerialVal(PGLOBAL g, PBVAL vlp, int pretty)
{ return Serialize(g, vlp, NULL, pretty);
} // en of SerialTop
/* -------------------------- Class BCUTIL --------------------------- */
/***********************************************************************/ /* SetValue: Set a value from a BVALUE contains. */ /***********************************************************************/ void BCUTIL::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL jvp)
{ if (jvp) {
vp->SetNull(false);
if (Jb) {
vp->SetValue_psz(Serialize(g, jvp, NULL, 0));
Jb = false;
} elseswitch (jvp->Type) { case TYPE_STRG: case TYPE_INTG: case TYPE_BINT: case TYPE_DBL: case TYPE_DTM: case TYPE_FLOAT: switch (vp->GetType()) { case TYPE_STRING: case TYPE_DECIM:
vp->SetValue_psz(GetString(jvp)); break; case TYPE_INT: case TYPE_SHORT: case TYPE_TINY:
vp->SetValue(GetInteger(jvp)); break; case TYPE_BIGINT:
vp->SetValue(GetBigint(jvp)); break; case TYPE_DOUBLE:
vp->SetValue(GetDouble(jvp));
if (jvp->Type == TYPE_DBL || jvp->Type == TYPE_FLOAT)
vp->SetPrec(jvp->Nd);
break; case TYPE_DATE: if (jvp->Type == TYPE_STRG) {
PSZ dat = GetString(jvp);
if (!IsNum(dat)) { if (!((DTVAL*)vp)->IsFormatted())
((DTVAL*)vp)->SetFormat(g, "YYYY-MM-DDThh:mm:ssZ", 20, 0);
break; default:
snprintf(G->Message, sizeof(G->Message), "Unsupported column type %d", vp->GetType()); throw888;
} // endswitch Type
break; case TYPE_BOOL: if (vp->IsTypeNum())
vp->SetValue(GetInteger(jvp) ? 1 : 0); else
vp->SetValue_psz((PSZ)(GetInteger(jvp) ? "true" : "false"));
break; case TYPE_JAR: case TYPE_JOB: // SetJsonValue(g, vp, val->GetArray()->GetValue(0));
vp->SetValue_psz(GetValueText(g, jvp, NULL)); break; default:
vp->Reset();
vp->SetNull(true);
} // endswitch Type
} else {
vp->Reset();
vp->SetNull(true);
} // endif val
} // end of SetJsonValue
/***********************************************************************/ /* MakeJson: Serialize the json item and set value to it. */ /***********************************************************************/
PBVAL BCUTIL::MakeBson(PGLOBAL g, PBVAL jsp, int n)
{
PBVAL vlp, jvp = jsp;
if (n < Cp->Nod - 1) { if (jsp->Type == TYPE_JAR) { int ars = GetArraySize(jsp);
PJNODE jnp = &Cp->Nodes[n];
jvp = NewVal(TYPE_JAR);
jnp->Op = OP_EQ;
for (int i = 0; i < ars; i++) {
jnp->Rank = i;
vlp = GetRowValue(g, jsp, n);
AddArrayValue(jvp,DupVal(vlp));
} // endfor i
if (op == OP_SEP) { // Calculate average
mulval->SetValue(nv);
val[0] = vp;
val[1] = mulval;
if (vp->Compute(g, val, 2, OP_DIV))
vp->Reset();
} // endif Op
Tp->NextSame = nextsame; return vp;
} // end of CalculateArray
/***********************************************************************/ /* GetRow: Get the object containing this column. */ /***********************************************************************/
PBVAL BCUTIL::GetRow(PGLOBAL g)
{ int nod = Cp->Nod;
JNODE *nodes = Cp->Nodes;
PBVAL val = NULL;
PBVAL arp;
PBVAL nwr, row = Tp->Row;
for (int i = 0; i < nod && row; i++) { if (i < nod-1 && nodes[i+1].Op == OP_XX) break; elseswitch (row->Type) { case TYPE_JOB: if (!nodes[i].Key) // Expected Array was not there, wrap the value continue;
val = GetKeyValue(row, nodes[i].Key); break; case TYPE_JAR:
arp = row;
if (!nodes[i].Key) { if (nodes[i].Op == OP_EQ)
val = GetArrayValue(arp, nodes[i].Rank); else
val = GetArrayValue(arp, nodes[i].Rx);
} else { // Unexpected array, unwrap it as [0]
val = GetArrayValue(arp, 0);
i--;
} // endif Nodes
break; case TYPE_JVAL:
val = row; break; default:
snprintf(g->Message, sizeof(g->Message), "Invalid row JSON type %d", row->Type);
val = NULL;
} // endswitch Type
if (val) {
row = val;
} else { // Construct missing objects for (i++; row && i < nod; i++) { int type;
if (nodes[i].Op == OP_XX) break; elseif (!nodes[i].Key) // Construct intermediate array
type = TYPE_JAR; else
type = TYPE_JOB;
if (row->Type == TYPE_JOB) {
nwr = AddPair(row, nodes[i - 1].Key, type);
} elseif (row->Type == TYPE_JAR) {
AddArrayValue(row, (nwr = NewVal(type)));
} else {
safe_strcpy(g->Message, sizeof(g->Message), "Wrong type when writing new row");
nwr = NULL;
} // endif's
row = nwr;
} // endfor i
break;
} // endelse
} // endfor i
return row;
} // end of GetRow
/* -------------------------- Class BSONDEF -------------------------- */
return DOSDEF::DefineAM(g, (Uri ? "XMGO" : "DOS"), poff);
} // end of DefineAM
/***********************************************************************/ /* GetTable: makes a new Table Description Block. */ /***********************************************************************/
PTDB BSONDEF::GetTable(PGLOBAL g, MODE m)
{ if (trace(1))
htrc("BSON GetTable Pretty=%d Uri=%s\n", Pretty, SVP(Uri));
if (Catfunc == FNC_COL) returnnew(g)TDBBCL(this);
PTDBASE tdbp;
PTXF txfp = NULL;
// JSN not used for pretty=1 for insert or delete if (Pretty <= 0 || (Pretty == 1 && (m == MODE_READ || m == MODE_UPDATE))) {
USETEMP tmp = UseTemp(); bool map = Mapped && Pretty >= 0 && m != MODE_INSERT &&
!(tmp != TMP_NO && m == MODE_UPDATE) &&
!(tmp == TMP_FORCE && (m == MODE_UPDATE || m == MODE_DELETE));
if (Lrecl) { // Allocate the parse work memory
G = PlugInit(NULL, (size_t)Lrecl * (Pretty < 0 ? 3 : 5));
} else {
safe_strcpy(g->Message, sizeof(g->Message), "LRECL is not defined"); return NULL;
} // endif Lrecl
return (colp->ParseJpath(g)) ? NULL : colp;
} // end of MakeCol
/***********************************************************************/ /* InsertSpecialColumn: Put a special column ahead of the column list.*/ /***********************************************************************/
PCOL TDBBSN::InsertSpecialColumn(PCOL colp)
{ if (!colp->IsSpecial()) return NULL;
//if (Xcol && ((SPCBLK*)colp)->GetRnm()) // colp->SetKey(0); // Rownum is no more a key
colp->SetNext(Columns);
Columns = colp; return colp;
} // end of InsertSpecialColumn
/***********************************************************************/ /* JSON Cardinality: returns table size in number of rows. */ /***********************************************************************/ int TDBBSN::Cardinality(PGLOBAL g)
{ if (!g) return0; elseif (Cardinal < 0) {
Cardinal = TDBDOS::Cardinality(g);
} // endif Cardinal
return Cardinal;
} // end of Cardinality
/***********************************************************************/ /* JSON GetMaxSize: returns file size estimate in number of lines. */ /***********************************************************************/ int TDBBSN::GetMaxSize(PGLOBAL g)
{ if (MaxSize < 0)
MaxSize = TDBDOS::GetMaxSize(g) * ((Xcol) ? Limit : 1);
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/ /* JSON EstimatedLength. Returns an estimated minimum line length. */ /***********************************************************************/ int TDBBSN::EstimatedLength(void)
{ if (AvgLen <= 0) return (Lrecl ? Lrecl : 1024) / 8; // TODO: make it better else return AvgLen;
} // end of Estimated Length
/***********************************************************************/ /* OpenDB: Data Base open routine for BSN access method. */ /***********************************************************************/ bool TDBBSN::OpenDB(PGLOBAL g)
{
TUSE use = Use;
if (Use == USE_OPEN) { /*******************************************************************/ /* Table already open replace it at its beginning. ??? */ /*******************************************************************/
Fpos = -1;
NextSame = 0;
SameRow = 0;
} // endif Use
/*********************************************************************/ /* Open according to logical input/output mode required. */ /*********************************************************************/ if (TDBDOS::OpenDB(g)) returntrue;
/***********************************************************************/ /* First opening. */ /***********************************************************************/ if (Mode == MODE_INSERT) { int type;
switch (Jmode) { case MODE_OBJECT: type = TYPE_JOB; break; case MODE_ARRAY: type = TYPE_JAR; break; case MODE_VALUE: type = TYPE_JVAL; break; default:
snprintf(g->Message, sizeof(g->Message), "Invalid Jmode %d", Jmode); returntrue;
} // endswitch Jmode
Top = Bp->MakeTopTree(g, type);
Bp->MemSave();
} // endif Mode
if (Xcol)
To_Filter = NULL; // Not compatible
returnfalse;
} // end of OpenDB
/***********************************************************************/ /* SkipHeader: Physically skip first header line if applicable. */ /* This is called from TDBDOS::OpenDB and must be executed before */ /* Kindex construction if the file is accessed using an index. */ /***********************************************************************/ bool TDBBSN::SkipHeader(PGLOBAL g)
{ int len = GetFileLength(g); bool rc = false;
#ifdefined(_DEBUG) if (len < 0) returntrue; #endif// _DEBUG
if (Pretty == 1) { if (Mode == MODE_INSERT || Mode == MODE_DELETE) { // Mode Insert and delete are no more handled here
DBUG_ASSERT(false);
} elseif (len > 0) // !Insert && !Delete
rc = (Txfp->SkipRecord(g, false) == RC_FX || Txfp->RecordPos(g));
} // endif Pretty
return rc;
} // end of SkipHeader
/***********************************************************************/ /* ReadDB: Data Base read routine for JSN access method. */ /***********************************************************************/ int TDBBSN::ReadDB(PGLOBAL g)
{ int rc;
} else { // Here we get a movable Json binary tree
Bp->MemSet(((BINFAM*)Txfp)->Recsize); // Useful when updating
Row = Top = (PBVAL)To_Line;
Row = Bp->FindRow(g);
SameRow = 0;
Fpos++;
M = 1;
rc = RC_OK;
} // endif Pretty
} // endif ReadDB
return rc;
} // end of ReadDB
/***********************************************************************/ /* PrepareWriting: Prepare the line for WriteDB. */ /***********************************************************************/ bool TDBBSN::PrepareWriting(PGLOBAL g)
{ if (Pretty >= 0) {
PSZ s;
// if (!(Top = Bp->MakeTopTree(g, Row->Type))) // return true;
if ((s = Bp->SerialVal(g, Top, Pretty))) { if (Comma)
strcat(s, ",");
returnfalse;
} else returntrue;
} else
((BINFAM*)Txfp)->Recsize = ((size_t)PlugSubAlloc(Bp->G, NULL, 0)
- (size_t)To_Line); returnfalse;
} // end of PrepareWriting
/***********************************************************************/ /* WriteDB: Data Base write routine for JSON access method. */ /***********************************************************************/ int TDBBSN::WriteDB(PGLOBAL g) { int rc = TDBDOS::WriteDB(g);
Bp->SubSet();
Bp->Clear(Row); return rc;
} // end of WriteDB
/***********************************************************************/ /* Data Base close routine for JSON access method. */ /***********************************************************************/ void TDBBSN::CloseDB(PGLOBAL g)
{
TDBDOS::CloseDB(g);
Bp->G = PlugExit(Bp->G);
} // end of CloseDB
// For calculated arrays, a local Value must be used switch (jnp->Op) { case OP_NUM:
jnp->Valp = AllocateValue(g, TYPE_INT); break; case OP_ADD: case OP_MULT: case OP_SEP: if (!IsTypeChar(Buf_Type))
jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision()); else
jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2);
break; case OP_MIN: case OP_MAX:
jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision()); break; case OP_CNC: if (IsTypeChar(Buf_Type))
jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision()); else
jnp->Valp = AllocateValue(g, TYPE_STRING, 512);
break; default: break;
} // endswitch Op
if (jnp->Valp)
MulVal = AllocateValue(g, jnp->Valp);
returnfalse;
} // end of SetArrayOptions
/***********************************************************************/ /* Parse the eventual passed Jpath information. */ /* This information can be specified in the Fieldfmt column option */ /* when creating the table. It permits to indicate the position of */ /* the node corresponding to that column. */ /***********************************************************************/ bool BSONCOL::ParseJpath(PGLOBAL g)
{ char* p, * p1 = NULL, * p2 = NULL, * pbuf = NULL; int i; bool a;
if (To_Tdb->GetOrig()) { // This is an updated column, get nodes from origin for (PBSCOL colp = (PBSCOL)Tbp->GetColumns(); colp;
colp = (PBSCOL)colp->GetNext()) if (!stricmp(Name, colp->GetName())) {
Nod = colp->Nod;
Nodes = colp->Nodes;
Xpd = colp->Xpd; goto fin;
} // endif Name
// Analyze the Jpath for this column for (i = 0, p = pbuf; p && i < Nod; i++, p = (p2 ? p2 : NULL)) {
a = (p1 != NULL);
p1 = strchr(p, '[');
p2 = strchr(p, Sep);
if (!p2)
p2 = p1; elseif (p1) { if (p1 < p2)
p2 = p1; elseif (p1 == p2 + 1)
*p2++ = 0; // Old syntax .[ or :[ else
p1 = NULL;
} // endif p1
if (p2)
*p2++ = 0;
// Jpath must be explicit if (a || *p == 0 || *p == '[' || IsNum(p)) { // Analyse intermediate array processing if (SetArrayOptions(g, p, i, Nodes[i - 1].Key)) returntrue; elseif (Xpd && Tbp->Mode == MODE_DELETE) {
safe_strcpy(g->Message, sizeof(g->Message), "Cannot delete expanded columns"); returntrue;
} // endif Xpd
#ifdefined(DEVELOPMENT) if (Xpd && Value->IsNull() && !((PBDEF)Tbp->To_Def)->Accept)
htrc("Null expandable JSON value for column %s\n", Name); #endif// DEVELOPMENT
// Set null when applicable if (!Nullable)
Value->SetNull(false);
} // end of ReadColumn
/***********************************************************************/ /* WriteColumn: */ /***********************************************************************/ void BSONCOL::WriteColumn(PGLOBAL g)
{ if (Xpd && Tbp->Pretty < 2) {
safe_strcpy(g->Message, sizeof(g->Message), "Cannot write expanded column when Pretty is not 2"); throw666;
} // endif Xpd
/*********************************************************************/ /* Check whether this node must be written. */ /*********************************************************************/ if (Value != To_Val)
Value->SetValue_pval(To_Val, FALSE); // Convert the updated value
/*********************************************************************/ /* On INSERT Null values are represented by no node. */ /*********************************************************************/ if (Value->IsNull() && Tbp->Mode == MODE_INSERT) return;
PBVAL jsp, row = Cp->GetRow(g);
if (row) switch (Buf_Type) { case TYPE_STRING: case TYPE_DATE: case TYPE_INT: case TYPE_TINY: case TYPE_SHORT: case TYPE_BIGINT: case TYPE_DOUBLE: if (Buf_Type == TYPE_STRING && Nodes[Nod - 1].Op == OP_XX) { char *s = Value->GetCharValue();
// Used for update
PTDB TDBBSON::Clone(PTABS t)
{
PTDB tp;
PBSCOL cp1, cp2;
PGLOBAL g = t->G;
tp = new(g) TDBBSON(this);
for (cp1 = (PBSCOL)Columns; cp1; cp1 = (PBSCOL)cp1->GetNext()) {
cp2 = new(g) BSONCOL(cp1, tp); // Make a copy
NewPointer(t, cp1, cp2);
} // endfor cp1
return tp;
} // end of Clone
/***********************************************************************/ /* Make the document tree from the object path. */ /***********************************************************************/ int TDBBSON::MakeNewDoc(PGLOBAL g)
{ // Create a void table that will be populated
Docp = Bp->NewVal(TYPE_JAR);
if (!(Top = Bp->MakeTopTree(g, TYPE_JAR))) return RC_FX;
Docp = Row;
Done = true; return RC_OK;
} // end of MakeNewDoc
/***********************************************************************/ /* Make the document tree from a file. */ /***********************************************************************/ int TDBBSON::MakeDocument(PGLOBAL g)
{ char *p, *p1, *p2, *memory, *objpath, *key = NULL; int i = 0;
size_t len;
my_bool a;
MODE mode = Mode;
PBVAL jsp;
PBVAL objp = NULL;
PBVAL arp = NULL;
PBVAL val = NULL;
if (Done) return RC_OK;
/*********************************************************************/ /* Create the mapping file object in mode read. */ /*********************************************************************/
Mode = MODE_READ;
if (!Txfp->OpenTableFile(g)) {
PFBLOCK fp = Txfp->GetTo_Fb();
if (!a && *p && *p != '[' && !IsNum(p)) { // obj is a key if (jsp->Type != TYPE_JOB) {
safe_strcpy(g->Message, sizeof(g->Message), "Table path does not match the json file"); return RC_FX;
} // endif Type
} else { if (*p == '[') { // Old style if (p[strlen(p) - 1] != ']') {
snprintf(g->Message, sizeof(g->Message), "Invalid Table path near %s", p); return RC_FX;
} else
p++;
} // endif p
if (jsp->Type != TYPE_JAR) {
safe_strcpy(g->Message, sizeof(g->Message), "Table path does not match the json file"); return RC_FX;
} // endif Type
arp = jsp;
objp = NULL;
i = atoi(p) - B;
val = Bp->GetArrayValue(arp, i);
if (!val) {
snprintf(g->Message, sizeof(g->Message), "Cannot find array value %d", i); return RC_FX;
} // endif val
} // endif
jsp = val;
} // endfor p
} // endif objpath
if (jsp && jsp->Type == TYPE_JAR)
Docp = jsp; else { // The table is void or is just one object or one value if (objp) {
Docp = Bp->GetKeyValue(objp, key);
Docp->To_Val = Bp->MOF(Bp->DupVal(Docp));
Docp->Type = TYPE_JAR;
} elseif (arp) {
Docp = Bp->NewVal(TYPE_JAR);
Bp->AddArrayValue(Docp, jsp);
Bp->SetArrayValue(arp, Docp, i);
} else {
Top = Docp = Bp->NewVal(TYPE_JAR);
Bp->AddArrayValue(Docp, jsp);
} // endif's
} // endif jsp
Docsize = Bp->GetSize(Docp);
Done = true; return RC_OK;
} // end of MakeDocument
/***********************************************************************/ /* JSON Cardinality: returns table size in number of rows. */ /***********************************************************************/ int TDBBSON::Cardinality(PGLOBAL g)
{ if (!g) return (Xcol || Multiple) ? 0 : 1; elseif (Cardinal < 0) { if (!Multiple) { if (MakeDocument(g) == RC_OK)
Cardinal = Docsize;
} else return10;
} // endif Cardinal
return Cardinal;
} // end of Cardinality
/***********************************************************************/ /* JSON GetMaxSize: returns table size estimate in number of rows. */ /***********************************************************************/ int TDBBSON::GetMaxSize(PGLOBAL g)
{ if (MaxSize < 0)
MaxSize = Cardinality(g) * ((Xcol) ? Limit : 1);
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/ /* ResetSize: call by TDBMUL when calculating size estimate. */ /***********************************************************************/ void TDBBSON::ResetSize(void)
{
MaxSize = Cardinal = -1;
Fpos = -1;
N = 0;
Docrow = NULL;
Done = false;
} // end of ResetSize
/***********************************************************************/ /* TDBBSON is not indexable. */ /***********************************************************************/ int TDBBSON::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool)
{ if (pxdf) {
safe_strcpy(g->Message, sizeof(g->Message), "JSON not indexable when pretty = 2"); return RC_FX;
} else return RC_OK;
} // end of MakeIndex
/***********************************************************************/ /* Return the position in the table. */ /***********************************************************************/ int TDBBSON::GetRecpos(void)
{ #if0 union {
uint Rpos;
BYTE Spos[4];
};
Rpos = htonl(Fpos);
Spos[0] = (BYTE)NextSame; return Rpos; #endif// 0 return Fpos;
} // end of GetRecpos
/***********************************************************************/ /* Set the position in the table. */ /***********************************************************************/ bool TDBBSON::SetRecpos(PGLOBAL, int recpos)
{ #if0 union {
uint Rpos;
BYTE Spos[4];
};
Fpos = recpos - 1;
Docrow = NULL; returnfalse;
} // end of SetRecpos
/***********************************************************************/ /* JSON Access Method opening routine. */ /***********************************************************************/ bool TDBBSON::OpenDB(PGLOBAL g)
{ if (Use == USE_OPEN) { /*******************************************************************/ /* Table already open replace it at its beginning. */ /*******************************************************************/
Fpos = -1;
NextSame = false;
SameRow = 0;
Docrow = NULL; returnfalse;
} // endif use
/*********************************************************************/ /* OpenDB: initialize the JSON file processing. */ /*********************************************************************/ if (MakeDocument(g) != RC_OK) returntrue;
if (Mode == MODE_INSERT) switch (Jmode) { case MODE_OBJECT: Row = Bp->NewVal(TYPE_JOB); break; case MODE_ARRAY: Row = Bp->NewVal(TYPE_JAR); break; case MODE_VALUE: Row = Bp->NewVal(TYPE_JVAL); break; default:
snprintf(g->Message, sizeof(g->Message), "Invalid Jmode %d", Jmode); returntrue;
} // endswitch Jmode
if (Xcol)
To_Filter = NULL; // Imcompatible
Use = USE_OPEN; returnfalse;
} // end of OpenDB
/***********************************************************************/ /* ReadDB: Data Base read routine for JSON access method. */ /***********************************************************************/ int TDBBSON::ReadDB(PGLOBAL)
{ int rc;
/***********************************************************************/ /* WriteDB: Data Base write routine for JSON access method. */ /***********************************************************************/ int TDBBSON::WriteDB(PGLOBAL g)
{ if (Mode == MODE_INSERT) {
Bp->AddArrayValue(Docp, Row);
/***********************************************************************/ /* Data Base delete line routine for JSON access method. */ /***********************************************************************/ int TDBBSON::DeleteDB(PGLOBAL g, int irc)
{ if (irc == RC_OK) // Deleted current row
Bp->DeleteValue(Docp, Fpos); elseif (irc == RC_FX) // Delete all
Docp->To_Val = 0;
Changed = true; return RC_OK;
} // end of DeleteDB
/***********************************************************************/ /* Data Base close routine for JSON access methods. */ /***********************************************************************/ void TDBBSON::CloseDB(PGLOBAL g)
{ if (!Changed) return;
// Save the modified document char filename[_MAX_PATH];
//Docp->InitArray(g);
// We used the file name relative to recorded datapath
PlugSetPath(filename, ((PBDEF)To_Def)->Fn, GetPath());
// Serialize the modified table if (!Bp->Serialize(g, Top, filename, Pretty))
puts(g->Message);
} // end of CloseDB
/* ---------------------------TDBBCL class --------------------------- */
/***********************************************************************/ /* TDBBCL class constructor. */ /***********************************************************************/
TDBBCL::TDBBCL(PBDEF tdp) : TDBCAT(tdp) {
Topt = tdp->GetTopt();
Db = tdp->Schema;
Dsn = tdp->Uri;
} // end of TDBBCL constructor
/***********************************************************************/ /* GetResult: Get the list the JSON file columns. */ /***********************************************************************/
PQRYRES TDBBCL::GetResult(PGLOBAL g) { return BSONColumns(g, Db, Dsn, Topt, false);
} // end of GetResult
/* --------------------------- End of json --------------------------- */
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.