Commit 2bb42803 authored by Olivier Bertrand's avatar Olivier Bertrand

This commit includes changes done in a previous (deleted) branch plus new ones.

From the previous branch:
commit eda4928ff122a0845baf5ade83b4aa29244a3a89
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Mon Mar 9 22:34:56 2015 +0100

- Add discovery to JSON tables
  When columns are not defined, CONNECT analyses the json file to find column definitions.
  This wors only on table that are an array of objects. Pair keys are used to generate the
  column names and pair values are used for its definition. When the LEVEL option is defined
  as a not null integer, the eventual JPATH is scanned up to the LEVEL value.

From the current one:
- Fix MDEV-7521 when column names are utf8 encoded (not a general multi-charset fix)

- Adds more to JSON discovery processing and UDF's

- Use PlugDup everywhere it replaces PlugSubAlloc + strcpy.
parent 57aaccef
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */ /* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -207,8 +207,7 @@ bool MAPFAM::OpenTableFile(PGLOBAL g) ...@@ -207,8 +207,7 @@ bool MAPFAM::OpenTableFile(PGLOBAL g)
/*******************************************************************/ /*******************************************************************/
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK)); fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
fp->Type = TYPE_FB_MAP; fp->Type = TYPE_FB_MAP;
fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1); fp->Fname = PlugDup(g, filename);
strcpy((char*)fp->Fname, filename);
fp->Next = dbuserp->Openlist; fp->Next = dbuserp->Openlist;
dbuserp->Openlist = fp; dbuserp->Openlist = fp;
fp->Count = 1; fp->Count = 1;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */ /* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -289,8 +289,7 @@ bool TXTFAM::AddListValue(PGLOBAL g, int type, void *val, PPARM *top) ...@@ -289,8 +289,7 @@ bool TXTFAM::AddListValue(PGLOBAL g, int type, void *val, PPARM *top)
pp->Intval = *(int*)val; pp->Intval = *(int*)val;
break; break;
// case TYPE_STRING: // case TYPE_STRING:
// pp->Value = PlugSubAlloc(g, NULL, strlen((char*)val) + 1); // pp->Value = PlugDup(g, (char*)val);
// strcpy((char*)pp->Value, (char*)val);
// break; // break;
case TYPE_PCHAR: case TYPE_PCHAR:
pp->Value = val; pp->Value = val;
...@@ -325,8 +324,7 @@ int TXTFAM::StoreValues(PGLOBAL g, bool upd) ...@@ -325,8 +324,7 @@ int TXTFAM::StoreValues(PGLOBAL g, bool upd)
if (Tdbp->PrepareWriting(g)) if (Tdbp->PrepareWriting(g))
return RC_FX; return RC_FX;
buf = (char*)PlugSubAlloc(g, NULL, strlen(Tdbp->GetLine()) + 1); buf = PlugDup(g, Tdbp->GetLine());
strcpy(buf, Tdbp->GetLine());
rc = AddListValue(g, TYPE_PCHAR, buf, &To_Upd); rc = AddListValue(g, TYPE_PCHAR, buf, &To_Upd);
} // endif upd } // endif upd
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */ /* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -1451,8 +1451,7 @@ bool VCMFAM::OpenTableFile(PGLOBAL g) ...@@ -1451,8 +1451,7 @@ bool VCMFAM::OpenTableFile(PGLOBAL g)
/*******************************************************************/ /*******************************************************************/
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK)); fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
fp->Type = TYPE_FB_MAP; fp->Type = TYPE_FB_MAP;
fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1); fp->Fname = PlugDup(g, filename);
strcpy((char*)fp->Fname, filename);
fp->Next = dbuserp->Openlist; fp->Next = dbuserp->Openlist;
dbuserp->Openlist = fp; dbuserp->Openlist = fp;
fp->Count = 1; fp->Count = 1;
...@@ -2844,8 +2843,7 @@ bool VMPFAM::MapColumnFile(PGLOBAL g, MODE mode, int i) ...@@ -2844,8 +2843,7 @@ bool VMPFAM::MapColumnFile(PGLOBAL g, MODE mode, int i)
/*******************************************************************/ /*******************************************************************/
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK)); fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
fp->Type = TYPE_FB_MAP; fp->Type = TYPE_FB_MAP;
fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1); fp->Fname = PlugDup(g, filename);
strcpy((char*)fp->Fname, filename);
fp->Next = dup->Openlist; fp->Next = dup->Openlist;
dup->Openlist = fp; dup->Openlist = fp;
fp->Count = 1; fp->Count = 1;
......
...@@ -171,7 +171,7 @@ ...@@ -171,7 +171,7 @@
#define JSONMAX 10 // JSON Default max grp size #define JSONMAX 10 // JSON Default max grp size
extern "C" { extern "C" {
char version[]= "Version 1.03.0006 February 06, 2015"; char version[]= "Version 1.03.0006 March 16, 2015";
#if defined(WIN32) #if defined(WIN32)
char compver[]= "Version 1.03.0006 " __DATE__ " " __TIME__; char compver[]= "Version 1.03.0006 " __DATE__ " " __TIME__;
...@@ -211,6 +211,8 @@ extern "C" { ...@@ -211,6 +211,8 @@ extern "C" {
/***********************************************************************/ /***********************************************************************/
PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
PQRYRES VirColumns(PGLOBAL g, char *tab, char *db, bool info); PQRYRES VirColumns(PGLOBAL g, char *tab, char *db, bool info);
PQRYRES JSONColumns(PGLOBAL g, char *dp, const char *fn, char *objn,
int pretty, int lvl, int mxr, bool info);
void PushWarning(PGLOBAL g, THD *thd, int level); void PushWarning(PGLOBAL g, THD *thd, int level);
bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host, bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
const char *db, char *tab, const char *src, int port); const char *db, char *tab, const char *src, int port);
...@@ -1020,8 +1022,7 @@ char *GetListOption(PGLOBAL g, const char *opname, ...@@ -1020,8 +1022,7 @@ char *GetListOption(PGLOBAL g, const char *opname,
} // endif pv } // endif pv
if (!stricmp(opname, key)) { if (!stricmp(opname, key)) {
opval= (char*)PlugSubAlloc(g, NULL, strlen(val) + 1); opval= PlugDup(g, val);
strcpy(opval, val);
break; break;
} else if (!pn) } else if (!pn)
break; break;
...@@ -1506,8 +1507,7 @@ PIXDEF ha_connect::GetIndexInfo(TABLE_SHARE *s) ...@@ -1506,8 +1507,7 @@ PIXDEF ha_connect::GetIndexInfo(TABLE_SHARE *s)
// Now get index information // Now get index information
pn= (char*)s->keynames.type_names[n]; pn= (char*)s->keynames.type_names[n];
name= (char*)PlugSubAlloc(g, NULL, strlen(pn) + 1); name= PlugDup(g, pn);
strcpy(name, pn); // This is probably unuseful
unique= (kp.flags & 1) != 0; unique= (kp.flags & 1) != 0;
pkp= NULL; pkp= NULL;
...@@ -1517,8 +1517,7 @@ PIXDEF ha_connect::GetIndexInfo(TABLE_SHARE *s) ...@@ -1517,8 +1517,7 @@ PIXDEF ha_connect::GetIndexInfo(TABLE_SHARE *s)
// Get the the key parts info // Get the the key parts info
for (int k= 0; (unsigned)k < kp.user_defined_key_parts; k++) { for (int k= 0; (unsigned)k < kp.user_defined_key_parts; k++) {
pn= (char*)kp.key_part[k].field->field_name; pn= (char*)kp.key_part[k].field->field_name;
name= (char*)PlugSubAlloc(g, NULL, strlen(pn) + 1); name= PlugDup(g, pn);
strcpy(name, pn); // This is probably unuseful
// Allocate the key part description block // Allocate the key part description block
kpp= new(g) KPARTDEF(name, k + 1); kpp= new(g) KPARTDEF(name, k + 1);
...@@ -4738,9 +4737,9 @@ static char *encode(PGLOBAL g, const char *cnm) ...@@ -4738,9 +4737,9 @@ static char *encode(PGLOBAL g, const char *cnm)
@return @return
Return 0 if ok Return 0 if ok
*/ */
static bool add_field(String *sql, const char *field_name, int typ, static bool add_field(String *sql, const char *field_name, int typ, int len,
int len, int dec, char *key, uint tm, const char *rem, int dec, char *key, uint tm, const char *rem, char *dft,
char *dft, char *xtra, int flag, bool dbf, char v) char *xtra, char *fmt, int flag, bool dbf, char v)
{ {
char var = (len > 255) ? 'V' : v; char var = (len > 255) ? 'V' : v;
bool q, error= false; bool q, error= false;
...@@ -4809,6 +4808,12 @@ static bool add_field(String *sql, const char *field_name, int typ, ...@@ -4809,6 +4808,12 @@ static bool add_field(String *sql, const char *field_name, int typ,
error|= sql->append("'"); error|= sql->append("'");
} // endif rem } // endif rem
if (fmt && *fmt) {
error|= sql->append(" FIELD_FORMAT='");
error|= sql->append_for_single_quote(fmt, strlen(fmt));
error|= sql->append("'");
} // endif flag
if (flag) { if (flag) {
error|= sql->append(" FLAG="); error|= sql->append(" FLAG=");
error|= sql->append_ulonglong(flag); error|= sql->append_ulonglong(flag);
...@@ -4952,12 +4957,12 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -4952,12 +4957,12 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
const char *fncn= "?"; const char *fncn= "?";
const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src; const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src;
const char *col, *ocl, *rnk, *pic, *fcl, *skc; const char *col, *ocl, *rnk, *pic, *fcl, *skc;
char *tab, *dsn, *shm, *dpath; char *tab, *dsn, *shm, *dpath, *objn;
#if defined(WIN32) #if defined(WIN32)
char *nsp= NULL, *cls= NULL; char *nsp= NULL, *cls= NULL;
#endif // WIN32 #endif // WIN32
int port= 0, hdr= 0, mxr __attribute__((unused))= 0, mxe= 0, rc= 0; int port= 0, hdr= 0, mxr __attribute__((unused))= 0, mxe= 0, rc= 0;
int cop __attribute__((unused)) = 0; int cop __attribute__((unused))= 0, pty= 2, lrecl= 0, lvl= 0;
#if defined(ODBC_SUPPORT) #if defined(ODBC_SUPPORT)
POPARM sop = NULL; POPARM sop = NULL;
char *ucnc = NULL; char *ucnc = NULL;
...@@ -4987,7 +4992,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -4987,7 +4992,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if (!g) if (!g)
return HA_ERR_INTERNAL_ERROR; return HA_ERR_INTERNAL_ERROR;
user= host= pwd= tbl= src= col= ocl= pic= fcl= skc= rnk= dsn= NULL; user= host= pwd= tbl= src= col= ocl= pic= fcl= skc= rnk= dsn= objn= NULL;
// Get the useful create options // Get the useful create options
ttp= GetTypeID(topt->type); ttp= GetTypeID(topt->type);
...@@ -5003,6 +5008,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -5003,6 +5008,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
hdr= (int)topt->header; hdr= (int)topt->header;
tbl= topt->tablist; tbl= topt->tablist;
col= topt->colist; col= topt->colist;
lrecl= (int)topt->lrecl;
if (topt->oplist) { if (topt->oplist) {
host= GetListOption(g, "host", topt->oplist, "localhost"); host= GetListOption(g, "host", topt->oplist, "localhost");
...@@ -5017,6 +5023,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -5017,6 +5023,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
skc= GetListOption(g, "skipcol", topt->oplist, NULL); skc= GetListOption(g, "skipcol", topt->oplist, NULL);
rnk= GetListOption(g, "rankcol", topt->oplist, NULL); rnk= GetListOption(g, "rankcol", topt->oplist, NULL);
pwd= GetListOption(g, "password", topt->oplist); pwd= GetListOption(g, "password", topt->oplist);
objn= GetListOption(g, "Object", topt->oplist, NULL);
#if defined(WIN32) #if defined(WIN32)
nsp= GetListOption(g, "namespace", topt->oplist); nsp= GetListOption(g, "namespace", topt->oplist);
cls= GetListOption(g, "class", topt->oplist); cls= GetListOption(g, "class", topt->oplist);
...@@ -5034,6 +5041,8 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -5034,6 +5041,8 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
#if defined(PROMPT_OK) #if defined(PROMPT_OK)
cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0")); cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0"));
#endif // PROMPT_OK #endif // PROMPT_OK
pty= atoi(GetListOption(g,"Pretty", topt->oplist, "2"));
lvl= atoi(GetListOption(g,"Level", topt->oplist, "0"));
} else { } else {
host= "localhost"; host= "localhost";
user= (ttp == TAB_ODBC ? NULL : "root"); user= (ttp == TAB_ODBC ? NULL : "root");
...@@ -5077,8 +5086,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -5077,8 +5086,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
goto err; goto err;
} // endif tbl } // endif tbl
tab= (char*)PlugSubAlloc(g, NULL, strlen(tbl) + 1); tab= PlugDup(g, tbl);
strcpy(tab, tbl);
if ((p= strchr(tab, ','))) if ((p= strchr(tab, ',')))
*p= 0; *p= 0;
...@@ -5204,6 +5212,13 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -5204,6 +5212,13 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
else else
strcpy(g->Message, "Missing OEM module or subtype"); strcpy(g->Message, "Missing OEM module or subtype");
break;
case TAB_JSON:
if (!fn)
sprintf(g->Message, "Missing %s file name", topt->type);
else
ok= true;
break; break;
case TAB_VIR: case TAB_VIR:
ok= true; ok= true;
...@@ -5226,7 +5241,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -5226,7 +5241,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endif src } // endif src
if (ok) { if (ok) {
char *cnm, *rem, *dft, *xtra, *key; char *cnm, *rem, *dft, *xtra, *key, *fmt;
int i, len, prec, dec, typ, flg; int i, len, prec, dec, typ, flg;
// if (cat) // if (cat)
...@@ -5315,6 +5330,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -5315,6 +5330,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
case TAB_VIR: case TAB_VIR:
qrp= VirColumns(g, tab, (char*)db, fnc == FNC_COL); qrp= VirColumns(g, tab, (char*)db, fnc == FNC_COL);
break; break;
case TAB_JSON:
qrp= JSONColumns(g, (char*)db, fn, objn, pty, lrecl, lvl, fnc == FNC_COL);
break;
case TAB_OEM: case TAB_OEM:
qrp= OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL); qrp= OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL);
break; break;
...@@ -5331,7 +5349,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -5331,7 +5349,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if (fnc != FNC_NO || src || ttp == TAB_PIVOT) { if (fnc != FNC_NO || src || ttp == TAB_PIVOT) {
// Catalog like table // Catalog like table
for (crp= qrp->Colresp; !rc && crp; crp= crp->Next) { for (crp= qrp->Colresp; !rc && crp; crp= crp->Next) {
cnm= encode(g, crp->Name); cnm= (ttp == TAB_PIVOT) ? crp->Name : encode(g, crp->Name);
typ= crp->Type; typ= crp->Type;
len= crp->Length; len= crp->Length;
dec= crp->Prec; dec= crp->Prec;
...@@ -5347,7 +5365,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -5347,7 +5365,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
NOT_NULL_FLAG, "", flg, dbf, v); NOT_NULL_FLAG, "", flg, dbf, v);
#else // !NEW_WAY #else // !NEW_WAY
if (add_field(&sql, cnm, typ, len, dec, NULL, NOT_NULL_FLAG, if (add_field(&sql, cnm, typ, len, dec, NULL, NOT_NULL_FLAG,
NULL, NULL, NULL, flg, dbf, v)) NULL, NULL, NULL, NULL, flg, dbf, v))
rc= HA_ERR_OUT_OF_MEM; rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY #endif // !NEW_WAY
} // endfor crp } // endfor crp
...@@ -5368,7 +5386,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -5368,7 +5386,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
typ= len= prec= dec= 0; typ= len= prec= dec= 0;
tm= NOT_NULL_FLAG; tm= NOT_NULL_FLAG;
cnm= (char*)"noname"; cnm= (char*)"noname";
dft= xtra= key= NULL; dft= xtra= key= fmt= NULL;
v= ' '; v= ' ';
#if defined(NEW_WAY) #if defined(NEW_WAY)
rem= ""; rem= "";
...@@ -5407,6 +5425,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -5407,6 +5425,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if (crp->Kdata->GetIntValue(i)) if (crp->Kdata->GetIntValue(i))
tm= 0; // Nullable tm= 0; // Nullable
break;
case FLD_FORMAT:
fmt= (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL;
break; break;
case FLD_REM: case FLD_REM:
rem= crp->Kdata->GetCharValue(i); rem= crp->Kdata->GetCharValue(i);
...@@ -5485,7 +5506,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -5485,7 +5506,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
tm, rem, 0, dbf, v); tm, rem, 0, dbf, v);
#else // !NEW_WAY #else // !NEW_WAY
if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra, if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra,
0, dbf, v)) fmt, 0, dbf, v))
rc= HA_ERR_OUT_OF_MEM; rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY #endif // !NEW_WAY
} // endfor i } // endfor i
...@@ -6545,7 +6566,7 @@ maria_declare_plugin(connect) ...@@ -6545,7 +6566,7 @@ maria_declare_plugin(connect)
0x0103, /* version number (1.03) */ 0x0103, /* version number (1.03) */
NULL, /* status variables */ NULL, /* status variables */
connect_system_variables, /* system variables */ connect_system_variables, /* system variables */
"1.03.0005", /* string version */ "1.03.0006", /* string version */
MariaDB_PLUGIN_MATURITY_BETA /* maturity */ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
} }
maria_declare_plugin_end; maria_declare_plugin_end;
/* Copyright (C) Olivier Bertrand 2004 - 2014 /* Copyright (C) Olivier Bertrand 2004 - 2015
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -56,11 +56,7 @@ public: ...@@ -56,11 +56,7 @@ public:
oldopn= newopn= NULL; oldopn= newopn= NULL;
oldpix= newpix= NULL;} oldpix= newpix= NULL;}
inline char *SetName(PGLOBAL g, char *name) { inline char *SetName(PGLOBAL g, char *name) {return PlugDup(g, name);}
char *nm= NULL;
if (name) {nm= (char*)PlugSubAlloc(g, NULL, strlen(name) + 1);
strcpy(nm, name);}
return nm;}
bool oldsep; // Sepindex before create/alter bool oldsep; // Sepindex before create/alter
bool newsep; // Sepindex after create/alter bool newsep; // Sepindex after create/alter
......
/*************** json CPP Declares Source Code File (.H) ***************/ /*************** json CPP Declares Source Code File (.H) ***************/
/* Name: json.cpp Version 1.0 */ /* Name: json.cpp Version 1.1 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */ /* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* */ /* */
...@@ -1157,6 +1157,6 @@ void JVALUE::SetString(PGLOBAL g, PSZ s) ...@@ -1157,6 +1157,6 @@ void JVALUE::SetString(PGLOBAL g, PSZ s)
/***********************************************************************/ /***********************************************************************/
bool JVALUE::IsNull(void) bool JVALUE::IsNull(void)
{ {
return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsNull() : true; return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsZero() : true;
} // end of IsNull } // end of IsNull
/**************** json H Declares Source Code File (.H) ****************/ /**************** json H Declares Source Code File (.H) ****************/
/* Name: json.h Version 1.0 */ /* Name: json.h Version 1.1 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */ /* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* */ /* */
/* This file contains the JSON classes declares. */ /* This file contains the JSON classes declares. */
/***********************************************************************/ /***********************************************************************/
#include "value.h" #include "value.h"
#if defined(_DEBUG) #if defined(_DEBUG)
#define X assert(false); #define X assert(false);
#else #else
#define X #define X
#endif #endif
enum JTYP {TYPE_STRG = 1, enum JTYP {TYPE_STRG = 1,
TYPE_DBL = 2, TYPE_DBL = 2,
TYPE_BOOL = 4, TYPE_BOOL = 4,
TYPE_INTG = 7, TYPE_INTG = 7,
TYPE_JSON = 12, TYPE_JSON = 12,
TYPE_JAR, TYPE_JAR,
TYPE_JOB, TYPE_JOB,
TYPE_JVAL}; TYPE_JVAL};
class JOUT; class JOUT;
class JSON; class JSON;
class JMAP; class JMAP;
class JVALUE; class JVALUE;
class JOBJECT; class JOBJECT;
class JARRAY; class JARRAY;
typedef class JPAIR *PJPR; typedef class JPAIR *PJPR;
typedef class JSON *PJSON; typedef class JSON *PJSON;
typedef class JVALUE *PJVAL; typedef class JVALUE *PJVAL;
typedef class JOBJECT *PJOB; typedef class JOBJECT *PJOB;
typedef class JARRAY *PJAR; typedef class JARRAY *PJAR;
typedef struct { typedef struct {
char *str; char *str;
int len; int len;
} STRG, *PSG; } STRG, *PSG;
PJSON ParseJson(PGLOBAL g, char *s, int n, int prty, bool *b = NULL); PJSON ParseJson(PGLOBAL g, char *s, int n, int prty, bool *b = NULL);
PJAR ParseArray(PGLOBAL g, int& i, STRG& src); PJAR ParseArray(PGLOBAL g, int& i, STRG& src);
PJOB ParseObject(PGLOBAL g, int& i, STRG& src); PJOB ParseObject(PGLOBAL g, int& i, STRG& src);
PJVAL ParseValue(PGLOBAL g, int& i, STRG& src); PJVAL ParseValue(PGLOBAL g, int& i, STRG& src);
char *ParseString(PGLOBAL g, int& i, STRG& src); char *ParseString(PGLOBAL g, int& i, STRG& src);
PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src); PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src);
PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty); PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty);
bool SerializeArray(JOUT *js, PJAR jarp, bool b); bool SerializeArray(JOUT *js, PJAR jarp, bool b);
bool SerializeObject(JOUT *js, PJOB jobp); bool SerializeObject(JOUT *js, PJOB jobp);
bool SerializeValue(JOUT *js, PJVAL jvp); bool SerializeValue(JOUT *js, PJVAL jvp);
/***********************************************************************/ /***********************************************************************/
/* Class JOUT. Used by Serialize. */ /* Class JOUT. Used by Serialize. */
/***********************************************************************/ /***********************************************************************/
class JOUT : public BLOCK { class JOUT : public BLOCK {
public: public:
JOUT(PGLOBAL gp) : BLOCK() {g = gp;} JOUT(PGLOBAL gp) : BLOCK() {g = gp;}
virtual bool WriteStr(const char *s) = 0; virtual bool WriteStr(const char *s) = 0;
virtual bool WriteChr(const char c) = 0; virtual bool WriteChr(const char c) = 0;
virtual bool Escape(const char *s) = 0; virtual bool Escape(const char *s) = 0;
// Member // Member
PGLOBAL g; PGLOBAL g;
}; // end of class JOUT }; // end of class JOUT
/***********************************************************************/ /***********************************************************************/
/* Class JOUTSTR. Used to Serialize to a string. */ /* Class JOUTSTR. Used to Serialize to a string. */
/***********************************************************************/ /***********************************************************************/
class JOUTSTR : public JOUT { class JOUTSTR : public JOUT {
public: public:
JOUTSTR(PGLOBAL g); JOUTSTR(PGLOBAL g);
virtual bool WriteStr(const char *s); virtual bool WriteStr(const char *s);
virtual bool WriteChr(const char c); virtual bool WriteChr(const char c);
virtual bool Escape(const char *s); virtual bool Escape(const char *s);
// Member // Member
char *Strp; // The serialized string char *Strp; // The serialized string
size_t N; // Position of next char size_t N; // Position of next char
size_t Max; // String max size size_t Max; // String max size
}; // end of class JOUTSTR }; // end of class JOUTSTR
/***********************************************************************/ /***********************************************************************/
/* Class JOUTFILE. Used to Serialize to a file. */ /* Class JOUTFILE. Used to Serialize to a file. */
/***********************************************************************/ /***********************************************************************/
class JOUTFILE : public JOUT { class JOUTFILE : public JOUT {
public: public:
JOUTFILE(PGLOBAL g, FILE *str) : JOUT(g) {Stream = str;} JOUTFILE(PGLOBAL g, FILE *str) : JOUT(g) {Stream = str;}
virtual bool WriteStr(const char *s); virtual bool WriteStr(const char *s);
virtual bool WriteChr(const char c); virtual bool WriteChr(const char c);
virtual bool Escape(const char *s); virtual bool Escape(const char *s);
// Member // Member
FILE *Stream; FILE *Stream;
}; // end of class JOUTFILE }; // end of class JOUTFILE
/***********************************************************************/ /***********************************************************************/
/* Class JOUTPRT. Used to Serialize to a pretty file. */ /* Class JOUTPRT. Used to Serialize to a pretty file. */
/***********************************************************************/ /***********************************************************************/
class JOUTPRT : public JOUTFILE { class JOUTPRT : public JOUTFILE {
public: public:
JOUTPRT(PGLOBAL g, FILE *str) : JOUTFILE(g, str) {M = 0; B = false;} JOUTPRT(PGLOBAL g, FILE *str) : JOUTFILE(g, str) {M = 0; B = false;}
virtual bool WriteStr(const char *s); virtual bool WriteStr(const char *s);
virtual bool WriteChr(const char c); virtual bool WriteChr(const char c);
// Member // Member
int M; int M;
bool B; bool B;
}; // end of class JOUTPRT }; // end of class JOUTPRT
/***********************************************************************/ /***********************************************************************/
/* Class PAIR. The pairs of a json Object. */ /* Class PAIR. The pairs of a json Object. */
/***********************************************************************/ /***********************************************************************/
class JPAIR : public BLOCK { class JPAIR : public BLOCK {
friend class JOBJECT; friend class JOBJECT;
friend PJOB ParseObject(PGLOBAL, int&, STRG&); friend PJOB ParseObject(PGLOBAL, int&, STRG&);
friend bool SerializeObject(JOUT *, PJOB); friend bool SerializeObject(JOUT *, PJOB);
public: public:
JPAIR(PSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;} JPAIR(PSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;}
protected: inline PSZ GetKey(void) {return Key;}
PSZ Key; // This pair key name inline PJVAL GetVal(void) {return Val;}
PJVAL Val; // To the value of the pair inline PJPR GetNext(void) {return Next;}
PJPR Next; // To the next pair
}; // end of class JPAIR protected:
PSZ Key; // This pair key name
/***********************************************************************/ PJVAL Val; // To the value of the pair
/* Class JSON. The base class for all other json classes. */ PJPR Next; // To the next pair
/***********************************************************************/ }; // end of class JPAIR
class JSON : public BLOCK {
public: /***********************************************************************/
JSON(void) {Size = 0;} /* Class JSON. The base class for all other json classes. */
/***********************************************************************/
int size(void) {return Size;} class JSON : public BLOCK {
virtual void Clear(void) {Size = 0;} public:
virtual JTYP GetType(void) {return TYPE_JSON;} JSON(void) {Size = 0;}
virtual JTYP GetValType(void) {X return TYPE_JSON;}
virtual void InitArray(PGLOBAL g) {X} int size(void) {return Size;}
virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL) {X return NULL;} virtual void Clear(void) {Size = 0;}
virtual PJPR AddPair(PGLOBAL g, PSZ key) {X return NULL;} virtual JTYP GetType(void) {return TYPE_JSON;}
virtual PJVAL GetValue(const char *key) {X return NULL;} virtual JTYP GetValType(void) {X return TYPE_JSON;}
virtual PJOB GetObject(void) {X return NULL;} virtual void InitArray(PGLOBAL g) {X}
virtual PJAR GetArray(void) {X return NULL;} virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL) {X return NULL;}
virtual PJVAL GetValue(int i) {X return NULL;} virtual PJPR AddPair(PGLOBAL g, PSZ key) {X return NULL;}
virtual PVAL GetValue(void) {X return NULL;} virtual PJVAL GetValue(const char *key) {X return NULL;}
virtual PJSON GetJson(void) {X return NULL;} virtual PJOB GetObject(void) {return NULL;}
virtual int GetInteger(void) {X return 0;} virtual PJAR GetArray(void) {return NULL;}
virtual double GetFloat() {X return 0.0;} virtual PJVAL GetValue(int i) {X return NULL;}
virtual PSZ GetString() {X return NULL;} virtual PVAL GetValue(void) {X return NULL;}
virtual PSZ GetText(PGLOBAL g, PSZ text) {X return NULL;} virtual PJSON GetJson(void) {X return NULL;}
virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i) {X return true;} virtual PJPR GetFirst(void) {X return NULL;}
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X} virtual int GetInteger(void) {X return 0;}
virtual void SetValue(PVAL valp) {X} virtual double GetFloat() {X return 0.0;}
virtual void SetValue(PJSON jsp) {X} virtual PSZ GetString() {X return NULL;}
virtual void SetString(PGLOBAL g, PSZ s) {X} virtual PSZ GetText(PGLOBAL g, PSZ text) {X return NULL;}
virtual void SetInteger(PGLOBAL g, int n) {X} virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i) {X return true;}
virtual void SetFloat(PGLOBAL g, double f) {X} virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X}
virtual bool DeleteValue(int i) {X return true;} virtual void SetValue(PVAL valp) {X}
virtual bool IsNull(void) {X return true;} virtual void SetValue(PJSON jsp) {X}
virtual void SetString(PGLOBAL g, PSZ s) {X}
protected: virtual void SetInteger(PGLOBAL g, int n) {X}
int Size; virtual void SetFloat(PGLOBAL g, double f) {X}
}; // end of class JSON virtual bool DeleteValue(int i) {X return true;}
virtual bool IsNull(void) {X return true;}
/***********************************************************************/
/* Class JOBJECT: contains a list of value pairs. */ protected:
/***********************************************************************/ int Size;
class JOBJECT : public JSON { }; // end of class JSON
friend PJOB ParseObject(PGLOBAL, int&, STRG&);
friend bool SerializeObject(JOUT *, PJOB); /***********************************************************************/
public: /* Class JOBJECT: contains a list of value pairs. */
JOBJECT(void) : JSON() {First = Last = NULL;} /***********************************************************************/
class JOBJECT : public JSON {
using JSON::GetValue; friend PJOB ParseObject(PGLOBAL, int&, STRG&);
using JSON::SetValue; friend bool SerializeObject(JOUT *, PJOB);
virtual void Clear(void) {First = Last = NULL; Size = 0;} public:
virtual JTYP GetType(void) {return TYPE_JOB;} JOBJECT(void) : JSON() {First = Last = NULL;}
virtual PJPR AddPair(PGLOBAL g, PSZ key);
virtual PJOB GetObject(void) {return this;} using JSON::GetValue;
virtual PJVAL GetValue(const char* key); using JSON::SetValue;
virtual PSZ GetText(PGLOBAL g, PSZ text); virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key); virtual JTYP GetType(void) {return TYPE_JOB;}
virtual bool IsNull(void); virtual PJPR GetFirst(void) {return First;}
virtual PJPR AddPair(PGLOBAL g, PSZ key);
protected: virtual PJOB GetObject(void) {return this;}
PJPR First; virtual PJVAL GetValue(const char* key);
PJPR Last; virtual PSZ GetText(PGLOBAL g, PSZ text);
}; // end of class JOBJECT virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key);
virtual bool IsNull(void);
/***********************************************************************/
/* Class JARRAY. */ protected:
/***********************************************************************/ PJPR First;
class JARRAY : public JSON { PJPR Last;
friend PJAR ParseArray(PGLOBAL, int&, STRG&); }; // end of class JOBJECT
public:
JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;} /***********************************************************************/
/* Class JARRAY. */
using JSON::GetValue; /***********************************************************************/
using JSON::SetValue; class JARRAY : public JSON {
virtual void Clear(void) {First = Last = NULL; Size = 0;} friend PJAR ParseArray(PGLOBAL, int&, STRG&);
virtual JTYP GetType(void) {return TYPE_JAR;} public:
virtual PJAR GetArray(void) {return this;} JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;}
virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL);
virtual void InitArray(PGLOBAL g); using JSON::GetValue;
virtual PJVAL GetValue(int i); using JSON::SetValue;
virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i); virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual bool DeleteValue(int n); virtual JTYP GetType(void) {return TYPE_JAR;}
virtual bool IsNull(void); virtual PJAR GetArray(void) {return this;}
virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL);
protected: virtual void InitArray(PGLOBAL g);
// Members virtual PJVAL GetValue(int i);
int Alloc; // The Mvals allocated size virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i);
PJVAL First; // Used when constructing virtual bool DeleteValue(int n);
PJVAL Last; // Last constructed value virtual bool IsNull(void);
PJVAL *Mvals; // Allocated when finished
}; // end of class JARRAY protected:
// Members
/***********************************************************************/ int Alloc; // The Mvals allocated size
/* Class JVALUE. */ PJVAL First; // Used when constructing
/***********************************************************************/ PJVAL Last; // Last constructed value
class JVALUE : public JSON { PJVAL *Mvals; // Allocated when finished
friend class JARRAY; }; // end of class JARRAY
friend PJVAL ParseValue(PGLOBAL, int&, STRG&);
friend bool SerializeValue(JOUT *, PJVAL); /***********************************************************************/
public: /* Class JVALUE. */
JVALUE(void) : JSON() /***********************************************************************/
{Jsp = NULL; Value = NULL; Next = NULL; Del = false;} class JVALUE : public JSON {
JVALUE(PJSON jsp) : JSON() friend class JARRAY;
{Jsp = jsp; Value = NULL; Next = NULL; Del = false;} friend PJVAL ParseValue(PGLOBAL, int&, STRG&);
JVALUE(PGLOBAL g, PVAL valp); friend bool SerializeValue(JOUT *, PJVAL);
public:
using JSON::GetValue; JVALUE(void) : JSON()
using JSON::SetValue; {Jsp = NULL; Value = NULL; Next = NULL; Del = false;}
virtual void Clear(void) JVALUE(PJSON jsp) : JSON()
{Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;} {Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
virtual JTYP GetType(void) {return TYPE_JVAL;} JVALUE(PGLOBAL g, PVAL valp);
virtual JTYP GetValType(void);
virtual PJOB GetObject(void); using JSON::GetValue;
virtual PJAR GetArray(void); using JSON::SetValue;
virtual PVAL GetValue(void) {return Value;} virtual void Clear(void)
virtual PJSON GetJson(void) {return (Jsp ? Jsp : this);} {Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;}
virtual int GetInteger(void); virtual JTYP GetType(void) {return TYPE_JVAL;}
virtual double GetFloat(void); virtual JTYP GetValType(void);
virtual PSZ GetString(void); virtual PJOB GetObject(void);
virtual PSZ GetText(PGLOBAL g, PSZ text); virtual PJAR GetArray(void);
virtual void SetValue(PVAL valp) {Value = valp;} virtual PVAL GetValue(void) {return Value;}
virtual void SetValue(PJSON jsp) {Jsp = jsp;} virtual PJSON GetJson(void) {return (Jsp ? Jsp : this);}
virtual void SetString(PGLOBAL g, PSZ s); virtual int GetInteger(void);
virtual void SetInteger(PGLOBAL g, int n); virtual double GetFloat(void);
virtual void SetFloat(PGLOBAL g, double f); virtual PSZ GetString(void);
virtual bool IsNull(void); virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual void SetValue(PVAL valp) {Value = valp;}
protected: virtual void SetValue(PJSON jsp) {Jsp = jsp;}
PJSON Jsp; // To the json value virtual void SetString(PGLOBAL g, PSZ s);
PVAL Value; // The numeric value virtual void SetInteger(PGLOBAL g, int n);
PJVAL Next; // Next value in array virtual void SetFloat(PGLOBAL g, double f);
bool Del; // True when deleted virtual bool IsNull(void);
}; // end of class JVALUE
protected:
PJSON Jsp; // To the json value
PVAL Value; // The numeric value
PJVAL Next; // Next value in array
bool Del; // True when deleted
}; // end of class JVALUE
/******************************************************************/ /******************************************************************/
/* Implementation of XML document processing using libxml2 */ /* Implementation of XML document processing using libxml2 */
/* Author: Olivier Bertrand 2007-2013 */ /* Author: Olivier Bertrand 2007-2015 */
/******************************************************************/ /******************************************************************/
#include "my_global.h" #include "my_global.h"
#include <string.h> #include <string.h>
...@@ -408,8 +408,7 @@ PFBLOCK LIBXMLDOC::LinkXblock(PGLOBAL g, MODE m, int rc, char *fn) ...@@ -408,8 +408,7 @@ PFBLOCK LIBXMLDOC::LinkXblock(PGLOBAL g, MODE m, int rc, char *fn)
xp->Next = (PX2BLOCK)dup->Openlist; xp->Next = (PX2BLOCK)dup->Openlist;
dup->Openlist = (PFBLOCK)xp; dup->Openlist = (PFBLOCK)xp;
xp->Type = TYPE_FB_XML2; xp->Type = TYPE_FB_XML2;
xp->Fname = (LPCSTR)PlugSubAlloc(g, NULL, strlen(fn) + 1); xp->Fname = (LPCSTR)PlugDup(g, fn);
strcpy((char*)xp->Fname, fn);
xp->Count = 1; xp->Count = 1;
xp->Length = (m == MODE_READ) ? 1 : 0; xp->Length = (m == MODE_READ) ? 1 : 0;
xp->Retcode = rc; xp->Retcode = rc;
......
/************ Odbconn C++ Functions Source Code File (.CPP) ************/ /************ Odbconn C++ Functions Source Code File (.CPP) ************/
/* Name: ODBCONN.CPP Version 2.1 */ /* Name: ODBCONN.CPP Version 2.2 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */ /* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
/* */ /* */
...@@ -867,8 +867,7 @@ bool DBX::BuildErrorMessage(ODBConn* pdb, HSTMT hstmt) ...@@ -867,8 +867,7 @@ bool DBX::BuildErrorMessage(ODBConn* pdb, HSTMT hstmt)
for (int i = 0; i < MAX_NUM_OF_MSG for (int i = 0; i < MAX_NUM_OF_MSG
&& (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) && (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
&& strcmp((char*)state, "00000"); i++) { && strcmp((char*)state, "00000"); i++) {
m_ErrMsg[i] = (PSZ)PlugSubAlloc(g, NULL, strlen((char*)msg) + 1); m_ErrMsg[i] = (PSZ)PlugDup(g, (char*)msg);
strcpy(m_ErrMsg[i], (char*)msg);
if (trace) if (trace)
htrc("%s: %s, Native=%d\n", state, msg, native); htrc("%s: %s, Native=%d\n", state, msg, native);
...@@ -882,8 +881,7 @@ bool DBX::BuildErrorMessage(ODBConn* pdb, HSTMT hstmt) ...@@ -882,8 +881,7 @@ bool DBX::BuildErrorMessage(ODBConn* pdb, HSTMT hstmt)
} else { } else {
snprintf((char*)msg, SQL_MAX_MESSAGE_LENGTH + 1, "%s: %s", m_Msg, snprintf((char*)msg, SQL_MAX_MESSAGE_LENGTH + 1, "%s: %s", m_Msg,
MSG(BAD_HANDLE_VAL)); MSG(BAD_HANDLE_VAL));
m_ErrMsg[0] = (PSZ)PlugSubAlloc(g, NULL, strlen((char*)msg) + 1); m_ErrMsg[0] = (PSZ)PlugDup(g, (char*)msg);
strcpy(m_ErrMsg[0], (char*)msg);
if (trace) if (trace)
htrc("%s: rc=%hd\n", SVP(m_ErrMsg[0]), m_RC); htrc("%s: rc=%hd\n", SVP(m_ErrMsg[0]), m_RC);
...@@ -1012,8 +1010,7 @@ PSZ ODBConn::GetStringInfo(ushort infotype) ...@@ -1012,8 +1010,7 @@ PSZ ODBConn::GetStringInfo(ushort infotype)
// *buffer = '\0'; // *buffer = '\0';
} // endif rc } // endif rc
p = (char *)PlugSubAlloc(m_G, NULL, strlen(buffer) + 1); p = PlugDup(m_G, buffer);
strcpy(p, buffer);
return p; return p;
} // end of GetStringInfo } // end of GetStringInfo
......
/************** PlgDBSem H Declares Source Code File (.H) **************/ /************** PlgDBSem H Declares Source Code File (.H) **************/
/* Name: PLGDBSEM.H Version 3.6 */ /* Name: PLGDBSEM.H Version 3.6 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */ /* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
/* */ /* */
/* This file contains the PlugDB++ application type definitions. */ /* This file contains the PlugDB++ application type definitions. */
/***********************************************************************/ /***********************************************************************/
...@@ -504,9 +504,10 @@ enum XFLD {FLD_NO = 0, /* Not a field definition item */ ...@@ -504,9 +504,10 @@ enum XFLD {FLD_NO = 0, /* Not a field definition item */
FLD_EXTRA = 13, /* Field extra info */ FLD_EXTRA = 13, /* Field extra info */
FLD_PRIV = 14, /* Field priviledges */ FLD_PRIV = 14, /* Field priviledges */
FLD_DATEFMT = 15, /* Field date format */ FLD_DATEFMT = 15, /* Field date format */
FLD_CAT = 16, /* Table catalog */ FLD_FORMAT = 16, /* Field format */
FLD_SCHEM = 17, /* Table schema */ FLD_CAT = 17, /* Table catalog */
FLD_TABNAME = 18}; /* Column Table name */ FLD_SCHEM = 18, /* Table schema */
FLD_TABNAME = 19}; /* Column Table name */
/***********************************************************************/ /***********************************************************************/
/* Result of last SQL noconv query. */ /* Result of last SQL noconv query. */
...@@ -584,6 +585,7 @@ DllExport PCATLG PlgGetCatalog(PGLOBAL g, bool jump = true); ...@@ -584,6 +585,7 @@ DllExport PCATLG PlgGetCatalog(PGLOBAL g, bool jump = true);
DllExport bool PlgSetXdbPath(PGLOBAL g, PSZ, PSZ, char *, int, char *, int); DllExport bool PlgSetXdbPath(PGLOBAL g, PSZ, PSZ, char *, int, char *, int);
DllExport void PlgDBfree(MBLOCK&); DllExport void PlgDBfree(MBLOCK&);
DllExport void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size); DllExport void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size);
DllExport char *PlgDBDup(PGLOBAL g, const char *str);
DllExport void *PlgDBalloc(PGLOBAL, void *, MBLOCK&); DllExport void *PlgDBalloc(PGLOBAL, void *, MBLOCK&);
DllExport void *PlgDBrealloc(PGLOBAL, void *, MBLOCK&, size_t); DllExport void *PlgDBrealloc(PGLOBAL, void *, MBLOCK&, size_t);
DllExport void NewPointer(PTABS, void *, void *); DllExport void NewPointer(PTABS, void *, void *);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */ /* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -294,8 +294,7 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids, ...@@ -294,8 +294,7 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
#else // !XMSG #else // !XMSG
GetRcString(ids + crp->Ncol, cname, sizeof(cname)); GetRcString(ids + crp->Ncol, cname, sizeof(cname));
#endif // !XMSG #endif // !XMSG
crp->Name = (PSZ)PlugSubAlloc(g, NULL, strlen(cname) + 1); crp->Name = (PSZ)PlugDup(g, cname);
strcpy(crp->Name, cname);
} else } else
crp->Name = NULL; // Will be set by caller crp->Name = NULL; // Will be set by caller
...@@ -853,8 +852,7 @@ FILE *PlugOpenFile(PGLOBAL g, LPCSTR fname, LPCSTR ftype) ...@@ -853,8 +852,7 @@ FILE *PlugOpenFile(PGLOBAL g, LPCSTR fname, LPCSTR ftype)
htrc(" fp=%p\n", fp); htrc(" fp=%p\n", fp);
// fname may be in volatile memory such as stack // fname may be in volatile memory such as stack
fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(fname) + 1); fp->Fname = PlugDup(g, fname);
strcpy((char*)fp->Fname, fname);
fp->Count = 1; fp->Count = 1;
fp->Type = TYPE_FB_FILE; fp->Type = TYPE_FB_FILE;
fp->File = fop; fp->File = fop;
...@@ -1400,6 +1398,23 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size) ...@@ -1400,6 +1398,23 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size)
return (memp); return (memp);
} // end of PlgDBSubAlloc } // end of PlgDBSubAlloc
/***********************************************************************/
/* Program for sub-allocating and copying a string in a storage area. */
/***********************************************************************/
char *PlgDBDup(PGLOBAL g, const char *str)
{
if (str) {
char *sm = (char*)PlgDBSubAlloc(g, NULL, strlen(str) + 1);
if (sm)
strcpy(sm, str);
return sm;
} else
return NULL;
} // end of PlgDBDup
/***********************************************************************/ /***********************************************************************/
/* PUTOUT: Plug DB object typing routine. */ /* PUTOUT: Plug DB object typing routine. */
/***********************************************************************/ /***********************************************************************/
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 1993-2014 */ /* (C) Copyright to the author Olivier BERTRAND 1993-2015 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -228,7 +228,6 @@ BOOL PlugIsAbsolutePath(LPCSTR path) ...@@ -228,7 +228,6 @@ BOOL PlugIsAbsolutePath(LPCSTR path)
#endif #endif
} }
/***********************************************************************/ /***********************************************************************/
/* Set the full path of a file relatively to a given path. */ /* Set the full path of a file relatively to a given path. */
/* Note: this routine is not really implemented for Unix. */ /* Note: this routine is not really implemented for Unix. */
...@@ -385,8 +384,7 @@ char *PlugReadMessage(PGLOBAL g, int mid, char *m) ...@@ -385,8 +384,7 @@ char *PlugReadMessage(PGLOBAL g, int mid, char *m)
err: err:
if (g) { if (g) {
// Called by STEP // Called by STEP
msg = (char *)PlugSubAlloc(g, NULL, strlen(stmsg) + 1); msg = PlugDup(g, stmsg);
strcpy(msg, stmsg);
} else // Called by MSG or PlgGetErrorMsg } else // Called by MSG or PlgGetErrorMsg
msg = stmsg; msg = stmsg;
...@@ -421,8 +419,7 @@ char *PlugGetMessage(PGLOBAL g, int mid) ...@@ -421,8 +419,7 @@ char *PlugGetMessage(PGLOBAL g, int mid)
if (g) { if (g) {
// Called by STEP // Called by STEP
msg = (char *)PlugSubAlloc(g, NULL, strlen(stmsg) + 1); msg = PlugDup(g, stmsg);
strcpy(msg, stmsg);
} else // Called by MSG or PlgGetErrorMsg } else // Called by MSG or PlgGetErrorMsg
msg = stmsg; msg = stmsg;
...@@ -536,6 +533,22 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size) ...@@ -536,6 +533,22 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
return (memp); return (memp);
} /* end of PlugSubAlloc */ } /* end of PlugSubAlloc */
/***********************************************************************/
/* Program for sub-allocating and copying a string in a storage area. */
/***********************************************************************/
char *PlugDup(PGLOBAL g, const char *str)
{
if (str) {
char *sm = (char*)PlugSubAlloc(g, NULL, strlen(str) + 1);
strcpy(sm, str);
return sm;
} else
return NULL;
} // end of PlugDup
#if 0
/***********************************************************************/ /***********************************************************************/
/* This routine suballocate a copy of the passed string. */ /* This routine suballocate a copy of the passed string. */
/***********************************************************************/ /***********************************************************************/
...@@ -552,6 +565,7 @@ char *PlugDup(PGLOBAL g, const char *str) ...@@ -552,6 +565,7 @@ char *PlugDup(PGLOBAL g, const char *str)
return(buf); return(buf);
} /* end of PlugDup */ } /* end of PlugDup */
#endif // 0
/***********************************************************************/ /***********************************************************************/
/* This routine makes a pointer from an offset to a memory pointer. */ /* This routine makes a pointer from an offset to a memory pointer. */
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2004-2014 */ /* (C) Copyright to the author Olivier BERTRAND 2004-2015 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -153,10 +153,9 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef) ...@@ -153,10 +153,9 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef)
if (s) { if (s) {
if (!Hc->IsPartitioned() || if (!Hc->IsPartitioned() ||
(stricmp(what, "filename") && stricmp(what, "tabname") (stricmp(what, "filename") && stricmp(what, "tabname")
&& stricmp(what, "connect"))) { && stricmp(what, "connect")))
sval= (char*)PlugSubAlloc(g, NULL, strlen(s) + 1); sval= PlugDup(g, s);
strcpy(sval, s); else
} else
sval= s; sval= s;
} else if (!stricmp(what, "filename")) { } else if (!stricmp(what, "filename")) {
...@@ -213,8 +212,7 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am) ...@@ -213,8 +212,7 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am)
{ {
int poff = 0; int poff = 0;
Name = (PSZ)PlugSubAlloc(g, NULL, strlen(name) + 1); Name = (PSZ)PlugDup(g, name);
strcpy(Name, name);
Cat = cat; Cat = cat;
Hc = ((MYCAT*)cat)->GetHandler(); Hc = ((MYCAT*)cat)->GetHandler();
Catfunc = GetFuncID(GetStringCatInfo(g, "Catfunc", NULL)); Catfunc = GetFuncID(GetStringCatInfo(g, "Catfunc", NULL));
...@@ -712,8 +710,7 @@ COLDEF::COLDEF(void) : COLCRT() ...@@ -712,8 +710,7 @@ COLDEF::COLDEF(void) : COLCRT()
/***********************************************************************/ /***********************************************************************/
int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff) int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
{ {
Name = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Name) + 1); Name = (PSZ)PlugDup(g, cfp->Name);
strcpy(Name, cfp->Name);
if (!(cfp->Flags & U_SPECIAL)) { if (!(cfp->Flags & U_SPECIAL)) {
Poff = poff; Poff = poff;
...@@ -735,22 +732,16 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff) ...@@ -735,22 +732,16 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
Key = cfp->Key; Key = cfp->Key;
Freq = cfp->Freq; Freq = cfp->Freq;
if (cfp->Remark && *cfp->Remark) { if (cfp->Remark && *cfp->Remark)
Desc = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Remark) + 1); Desc = (PSZ)PlugDup(g, cfp->Remark);
strcpy(Desc, cfp->Remark);
} // endif Remark
if (cfp->Datefmt) { if (cfp->Datefmt)
Decode = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Datefmt) + 1); Decode = (PSZ)PlugDup(g, cfp->Datefmt);
strcpy(Decode, cfp->Datefmt);
} // endif Datefmt
} // endif special } // endif special
if (cfp->Fieldfmt) { if (cfp->Fieldfmt)
Fmt = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Fieldfmt) + 1); Fmt = (PSZ)PlugDup(g, cfp->Fieldfmt);
strcpy(Fmt, cfp->Fieldfmt);
} // endif Fieldfmt
Flags = cfp->Flags; Flags = cfp->Flags;
return (Flags & (U_VIRTUAL|U_SPECIAL)) ? 0 : Long; return (Flags & (U_VIRTUAL|U_SPECIAL)) ? 0 : Long;
......
/************* tabjson C++ Program Source Code File (.CPP) *************/ /************* tabjson C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: tabjson Version 1.0 */ /* PROGRAM NAME: tabjson Version 1.1 */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */ /* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* This program are the JSON class DB execution routines. */ /* This program are the JSON class DB execution routines. */
/***********************************************************************/ /***********************************************************************/
...@@ -31,12 +31,451 @@ ...@@ -31,12 +31,451 @@
#endif // ZIP_SUPPORT #endif // ZIP_SUPPORT
#include "tabmul.h" #include "tabmul.h"
#include "checklvl.h" #include "checklvl.h"
#include "resource.h"
#include "mycat.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 */
/***********************************************************************/ /***********************************************************************/
/* External function. */ /* External function. */
/***********************************************************************/ /***********************************************************************/
USETEMP UseTemp(void); USETEMP UseTemp(void);
/***********************************************************************/
/* Make the document tree from a file. */
/***********************************************************************/
PJSON MakeJsonTree(PGLOBAL g, char *fn, char *objn, int pty,
PJAR& doc, DWORD& drc)
{
char *p, *memory, *objpath, *key;
int len, i = 0;
HANDLE hFile;
MEMMAP mm;
PJSON jsp, top;
PJOB objp = NULL;
PJAR arp = NULL;
PJVAL val = NULL;
/*********************************************************************/
/* Create the mapping file object. */
/*********************************************************************/
hFile = CreateFileMap(g, fn, &mm, MODE_READ, false);
if (hFile == INVALID_HANDLE_VALUE) {
drc = GetLastError();
if (!*g->Message)
sprintf(g->Message, MSG(OPEN_MODE_ERROR), "map", (int)drc, fn);
return NULL;
} // endif hFile
/*********************************************************************/
/* Get the file size (assuming file is smaller than 4 GB) */
/*********************************************************************/
len = mm.lenL;
memory = (char *)mm.memory;
if (!len) { // Empty file
CloseFileHandle(hFile);
CloseMemMap(memory, len);
drc = ENOENT;
return NULL;
} else if (!memory) {
sprintf(g->Message, MSG(MAP_VIEW_ERROR), fn, drc);
CloseFileHandle(hFile);
return NULL;
} // endif Memory
CloseFileHandle(hFile); // Not used anymore
/*********************************************************************/
/* Parse the json file and allocate its tree structure. */
/*********************************************************************/
g->Message[0] = 0;
jsp = top = ParseJson(g, memory, len, pty);
CloseMemMap(memory, len);
drc = EBADF;
if (!jsp && g->Message[0])
return NULL;
objpath = PlugDup(g, objn); // NULL if !objn
/*********************************************************************/
/* Find the table in the tree structure. */
/*********************************************************************/
for (doc = NULL; jsp && objpath; objpath = p) {
if ((p = strchr(objpath, ':')))
*p++ = 0;
if (*objpath != '[') { // objpass is a key
if (jsp->GetType() != TYPE_JOB) {
strcpy(g->Message, "Table path does no match json file");
return NULL;
} // endif Type
key = objpath;
objp = jsp->GetObject();
arp = NULL;
val = objp->GetValue(key);
if (!val || !(jsp = val->GetJson())) {
sprintf(g->Message, "Cannot find object key %s", key);
return NULL;
} // endif val
} else if (objpath[strlen(objpath)-1] == ']') {
if (jsp->GetType() != TYPE_JAR) {
strcpy(g->Message, "Table path does no match json file");
return NULL;
} // endif Type
arp = jsp->GetArray();
objp = NULL;
i = atoi(objpath+1) - 1;
val = arp->GetValue(i);
if (!val) {
sprintf(g->Message, "Cannot find array value %d", i);
return NULL;
} // endif val
} else {
sprintf(g->Message, "Invalid Table path %s", objn);
return NULL;
} // endif objpath
jsp = val->GetJson();
} // endfor objpath
if (jsp && jsp->GetType() == TYPE_JAR)
doc = jsp->GetArray();
else {
// The table is void or is just one object or one value
doc = new(g) JARRAY;
if (val) {
doc->AddValue(g, val);
doc->InitArray(g);
} else if (jsp) {
doc->AddValue(g, new(g) JVALUE(jsp));
doc->InitArray(g);
} // endif val
if (objp)
objp->SetValue(g, new(g) JVALUE(doc), key);
else if (arp)
arp->SetValue(g, new(g) JVALUE(doc), i);
else
top = doc;
} // endif jsp
return top;
} // end of MakeJsonTree
typedef struct _jncol {
struct _jncol *Next;
char *Name;
char *Fmt;
int Type;
int Len;
int Scale;
bool Cbn;
bool Found;
} JCOL, *PJCL;
/***********************************************************************/
/* JSONColumns: construct the result blocks containing the description */
/* of all the columns of a table contained inside a JSON file. */
/***********************************************************************/
PQRYRES JSONColumns(PGLOBAL g, char *dp, const char *fn, char *objn,
int pretty, int lrecl, int lvl, bool info)
{
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT};
static unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0};
char filename[_MAX_PATH], colname[65], fmt[129], *buf;
int i, j, n = 0;
int ncol = sizeof(buftyp) / sizeof(int);
FILE *infile;
DWORD drc;
PVAL valp;
JCOL jcol;
PJCL jcp, fjcp = NULL, pjcp = NULL;
PJPR *jrp, jpp;
PJSON jsp;
PJVAL jvp;
PJOB row;
PJAR doc;
PQRYRES qrp;
PCOLRES crp;
if (info) {
length[0] = 128;
length[7] = 256;
goto skipit;
} // endif info
if (trace)
htrc("File %s pretty=%d lvl=%d lrecl=%d\n",
SVP(fn), pretty, lvl, lrecl);
/*********************************************************************/
/* Open the input file. */
/*********************************************************************/
if (!fn) {
strcpy(g->Message, MSG(MISSING_FNAME));
return NULL;
} else
PlugSetPath(filename, fn, dp);
if (pretty == 2) {
if (!MakeJsonTree(g, filename, objn, pretty, doc, drc))
return NULL;
jsp = (doc) ? doc->GetValue(0) : NULL;
} else {
if (!lrecl) {
sprintf(g->Message, "LRECL must be specified for pretty=%d", pretty);
return NULL;
} else if (!(buf = (char*)PlugSubAlloc(g, NULL, lrecl))) {
sprintf(g->Message, "Alloc error, lrecl=%d", lrecl);
return NULL;
} // endif buf
if (!(infile = global_fopen(g, MSGID_CANNOT_OPEN, filename, "r")))
return NULL;
// Read first record
for (i = 0; i <= pretty; i++)
if (!fgets(buf, lrecl, infile)) {
if (feof(infile)) {
strcpy(g->Message, "Void json table");
return NULL;
} // endif fgets
sprintf(g->Message, MSG(READ_ERROR), filename, strerror(0));
return NULL;
} // endif fgets
jsp = ParseJson(g, buf, strlen(buf), pretty, NULL);
} // endif pretty
if (!(row = (jsp) ? jsp->GetObject() : NULL)) {
strcpy(g->Message, "Can only retrieve columns from object rows");
return NULL;
} // endif row
jcol.Next = NULL;
jcol.Found = true;
colname[64] = 0;
fmt[128] = 0;
jrp = (PJPR*)PlugSubAlloc(g, NULL, sizeof(PJPR) * lvl);
/*********************************************************************/
/* Analyse the JSON tree and define columns. */
/*********************************************************************/
for (i = 1; ; i++) {
for (jpp = row->GetFirst(); jpp; jpp = jpp->GetNext()) {
for (j = 0; j < lvl; j++)
jrp[j] = NULL;
more:
strncpy(colname, jpp->GetKey(), 64);
*fmt = 0;
j = 0;
jvp = jpp->GetVal();
retry:
if ((valp = jvp ? jvp->GetValue() : NULL)) {
jcol.Type = valp->GetType();
jcol.Len = valp->GetValLen();
jcol.Scale = valp->GetValPrec();
jcol.Cbn = valp->IsNull();
} else if (!jvp || jvp->IsNull()) {
jcol.Type = TYPE_UNKNOWN;
jcol.Len = jcol.Scale = 0;
jcol.Cbn = true;
} else if (j < lvl) {
if (!*fmt)
strcpy(fmt, colname);
jsp = jvp->GetJson();
switch (jsp->GetType()) {
case TYPE_JOB:
if (!jrp[j])
jrp[j] = jsp->GetFirst();
strncat(strncat(fmt, ":", 128), jrp[j]->GetKey(), 128);
strncat(strncat(colname, "_", 64), jrp[j]->GetKey(), 64);
jvp = jrp[j]->GetVal();
j++;
break;
case TYPE_JAR:
strncat(fmt, ":", 128);
jvp = jsp->GetValue(0);
break;
default:
sprintf(g->Message, "Logical error after %s", fmt);
goto err;
} // endswitch jsp
goto retry;
} else {
jcol.Type = TYPE_STRING;
jcol.Len = 256;
jcol.Scale = 0;
jcol.Cbn = true;
} // endif's
// Check whether this column was already found
for (jcp = fjcp; jcp; jcp = jcp->Next)
if (!strcmp(colname, jcp->Name))
break;
if (jcp) {
if (jcp->Type != jcol.Type)
jcp->Type = TYPE_STRING;
if (*fmt && (!jcp->Fmt || strlen(jcp->Fmt) < strlen(fmt))) {
jcp->Fmt = PlugDup(g, fmt);
length[7] = MY_MAX(length[7], strlen(fmt));
} // endif *fmt
jcp->Len = MY_MAX(jcp->Len, jcol.Len);
jcp->Scale = MY_MAX(jcp->Scale, jcol.Scale);
jcp->Cbn |= jcol.Cbn;
jcp->Found = true;
} else {
// New column
jcp = (PJCL)PlugSubAlloc(g, NULL, sizeof(JCOL));
*jcp = jcol;
jcp->Cbn |= (i > 1);
jcp->Name = PlugDup(g, colname);
length[0] = MY_MAX(length[0], strlen(colname));
if (*fmt) {
jcp->Fmt = PlugDup(g, fmt);
length[7] = MY_MAX(length[7], strlen(fmt));
} else
jcp->Fmt = NULL;
if (pjcp) {
jcp->Next = pjcp->Next;
pjcp->Next = jcp;
} else
fjcp = jcp;
n++;
} // endif jcp
pjcp = jcp;
for (j = lvl - 1; j >= 0; j--)
if (jrp[j] && (jrp[j] = jrp[j]->GetNext()))
goto more;
} // endfor jpp
// Missing column can be null
for (jcp = fjcp; jcp; jcp = jcp->Next) {
jcp->Cbn |= !jcp->Found;
jcp->Found = false;
} // endfor jcp
if (pretty != 2) {
// Read next record
if (!fgets(buf, lrecl, infile)) {
if (!feof(infile)) {
sprintf(g->Message, MSG(READ_ERROR), filename, strerror(0));
return NULL;
} else
jsp = NULL;
} else if (pretty == 1 && strlen(buf) == 1 && *buf == ']') {
jsp = NULL;
} else
jsp = ParseJson(g, buf, strlen(buf), pretty, NULL);
} else
jsp = doc->GetValue(i);
if (!(row = (jsp) ? jsp->GetObject() : NULL))
break;
} // endor i
if (pretty != 2)
fclose(infile);
skipit:
if (trace)
htrc("CSVColumns: 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);
crp = qrp->Colresp->Next->Next->Next->Next->Next->Next;
crp->Name = "Nullable";
crp->Next->Name = "Jpath";
if (info || !qrp)
return qrp;
qrp->Nblin = n;
/*********************************************************************/
/* Now get the results into blocks. */
/*********************************************************************/
for (i = 0, jcp = fjcp; jcp; i++, jcp = jcp->Next) {
if (jcp->Type == TYPE_UNKNOWN) // Void column
jcp->Type = TYPE_STRING;
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;
err:
if (pretty != 2)
fclose(infile);
return NULL;
} // end of JSONColumns
/* -------------------------- Class JSONDEF -------------------------- */ /* -------------------------- Class JSONDEF -------------------------- */
JSONDEF::JSONDEF(void) JSONDEF::JSONDEF(void)
...@@ -44,7 +483,9 @@ JSONDEF::JSONDEF(void) ...@@ -44,7 +483,9 @@ JSONDEF::JSONDEF(void)
Jmode = MODE_OBJECT; Jmode = MODE_OBJECT;
Objname = NULL; Objname = NULL;
Xcol = NULL; Xcol = NULL;
Pretty = 2;
Limit = 1; Limit = 1;
Level = 0;
ReadMode = 0; ReadMode = 0;
} // end of JSONDEF constructor } // end of JSONDEF constructor
...@@ -57,6 +498,7 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -57,6 +498,7 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Objname = GetStringCatInfo(g, "Object", NULL); Objname = GetStringCatInfo(g, "Object", NULL);
Xcol = GetStringCatInfo(g, "Expand", NULL); Xcol = GetStringCatInfo(g, "Expand", NULL);
Pretty = GetIntCatInfo("Pretty", 2); Pretty = GetIntCatInfo("Pretty", 2);
Level = GetIntCatInfo("Level", 0);
Limit = GetIntCatInfo("Limit", 10); Limit = GetIntCatInfo("Limit", 10);
return DOSDEF::DefineAM(g, "DOS", poff); return DOSDEF::DefineAM(g, "DOS", poff);
} // end of DefineAM } // end of DefineAM
...@@ -66,6 +508,9 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -66,6 +508,9 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/ /***********************************************************************/
PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
{ {
if (Catfunc == FNC_COL)
return new(g)TDBJCL(this);
PTDBASE tdbp; PTDBASE tdbp;
PTXF txfp = NULL; PTXF txfp = NULL;
...@@ -403,7 +848,7 @@ bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b) ...@@ -403,7 +848,7 @@ bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b)
bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
{ {
int n = (int)strlen(p); int n = (int)strlen(p);
bool dg = true; bool dg = true, b = false;
PJNODE jnp = &Nodes[i]; PJNODE jnp = &Nodes[i];
if (*p) { if (*p) {
...@@ -417,7 +862,8 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) ...@@ -417,7 +862,8 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
return true; return true;
} // endif p } // endif p
} // endif *p } else
b = true;
// To check whether a numeric Rank was specified // To check whether a numeric Rank was specified
for (int k = 0; dg && p[k]; k++) for (int k = 0; dg && p[k]; k++)
...@@ -427,13 +873,19 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) ...@@ -427,13 +873,19 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
// Default specifications // Default specifications
if (CheckExpand(g, i, nm, false)) if (CheckExpand(g, i, nm, false))
return true; return true;
else if (jnp->Op != OP_EXP) else if (jnp->Op != OP_EXP) {
if (!Value->IsTypeNum()) { if (b) {
// Return 1st value
jnp->Rank = 1;
jnp->Op = OP_EQ;
} else if (!Value->IsTypeNum()) {
jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING); jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING);
jnp->Op = OP_CNC; jnp->Op = OP_CNC;
} else } else
jnp->Op = OP_ADD; jnp->Op = OP_ADD;
} // endif OP
} else if (dg) { } else if (dg) {
if (atoi(p) > 0) { if (atoi(p) > 0) {
// Return nth value // Return nth value
...@@ -537,8 +989,7 @@ bool JSONCOL::ParseJpath(PGLOBAL g) ...@@ -537,8 +989,7 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
else if (!Jpath) else if (!Jpath)
Jpath = Name; Jpath = Name;
pbuf = (char*)PlugSubAlloc(g, NULL, strlen(Jpath) + 1); pbuf = PlugDup(g, Jpath);
strcpy(pbuf, Jpath);
// The Jpath must be analyzed // The Jpath must be analyzed
for (i = 0, p = pbuf; (p = strchr(p, ':')); i++, p++) for (i = 0, p = pbuf; (p = strchr(p, ':')); i++, p++)
...@@ -1083,6 +1534,38 @@ int TDBJSON::MakeNewDoc(PGLOBAL g) ...@@ -1083,6 +1534,38 @@ int TDBJSON::MakeNewDoc(PGLOBAL g)
return RC_OK; return RC_OK;
} // end of MakeNewDoc } // end of MakeNewDoc
/***********************************************************************/
/* Make the document tree from a file. */
/***********************************************************************/
int TDBJSON::MakeDocument(PGLOBAL g)
{
char filename[_MAX_PATH];
DWORD drc;
if (Done)
return RC_OK;
else
Done = true;
// Now open the JSON file
PlugSetPath(filename, Txfp->To_File, GetPath());
/*********************************************************************/
/* Get top of the parsed tree and the inside table document. */
/*********************************************************************/
Top = MakeJsonTree(g, filename, Objname, Pretty, Doc, drc);
if (!Top) {
if (drc != ENOENT || Mode != MODE_INSERT)
return RC_FX;
return MakeNewDoc(g);
} // endif !Top
return RC_OK;
} // end of MakeDocument
#if 0
/***********************************************************************/ /***********************************************************************/
/* Make the document tree from a file. */ /* Make the document tree from a file. */
/***********************************************************************/ /***********************************************************************/
...@@ -1158,11 +1641,7 @@ int TDBJSON::MakeDocument(PGLOBAL g) ...@@ -1158,11 +1641,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
if (!jsp && g->Message[0]) if (!jsp && g->Message[0])
return RC_FX; return RC_FX;
if (Objname) { objpath = PlugDup(g, Objname);
objpath = (char*)PlugSubAlloc(g, NULL, strlen(Objname) + 1);
strcpy(objpath, Objname);
} else
objpath = NULL;
/*********************************************************************/ /*********************************************************************/
/* Find the table in the tree structure. */ /* Find the table in the tree structure. */
...@@ -1236,6 +1715,7 @@ int TDBJSON::MakeDocument(PGLOBAL g) ...@@ -1236,6 +1715,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
return RC_OK; return RC_OK;
} // end of MakeDocument } // end of MakeDocument
#endif // 0
/***********************************************************************/ /***********************************************************************/
/* JSON Cardinality: returns table size in number of rows. */ /* JSON Cardinality: returns table size in number of rows. */
...@@ -1484,4 +1964,27 @@ void TDBJSON::CloseDB(PGLOBAL g) ...@@ -1484,4 +1964,27 @@ void TDBJSON::CloseDB(PGLOBAL g)
} // end of CloseDB } // end of CloseDB
/* -------------------------- End of json --------------------------- */ /* ---------------------------TDBJCL class --------------------------- */
/***********************************************************************/
/* TDBJCL class constructor. */
/***********************************************************************/
TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp)
{
Fn = tdp->GetFn();
Objn = tdp->Objname;
Pretty = tdp->Pretty;
Lrecl = tdp->Lrecl;
lvl = tdp->Level;
} // end of TDBJCL constructor
/***********************************************************************/
/* GetResult: Get the list the JSON file columns. */
/***********************************************************************/
PQRYRES TDBJCL::GetResult(PGLOBAL g)
{
return JSONColumns(g, ((PTABDEF)To_Def)->GetPath(), Fn, Objn,
Pretty, Lrecl, lvl, false);
} // end of GetResult
/* --------------------------- End of json --------------------------- */
/*************** tabjson H Declares Source Code File (.H) **************/ /*************** tabjson H Declares Source Code File (.H) **************/
/* Name: tabjson.h Version 1.0 */ /* Name: tabjson.h Version 1.1 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */ /* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* */ /* */
...@@ -34,6 +34,7 @@ typedef struct _jnode { ...@@ -34,6 +34,7 @@ typedef struct _jnode {
class JSONDEF : public DOSDEF { /* Table description */ class JSONDEF : public DOSDEF { /* Table description */
friend class TDBJSON; friend class TDBJSON;
friend class TDBJSN; friend class TDBJSN;
friend class TDBJCL;
public: public:
// Constructor // Constructor
JSONDEF(void); JSONDEF(void);
...@@ -52,6 +53,7 @@ class JSONDEF : public DOSDEF { /* Table description */ ...@@ -52,6 +53,7 @@ class JSONDEF : public DOSDEF { /* Table description */
char *Xcol; /* Name of expandable column */ char *Xcol; /* Name of expandable column */
int Limit; /* Limit of multiple values */ int Limit; /* Limit of multiple values */
int Pretty; /* Depends on file structure */ int Pretty; /* Depends on file structure */
int Level; /* Used for catalog table */
bool Strict; /* Strict syntax checking */ bool Strict; /* Strict syntax checking */
}; // end of JSONDEF }; // end of JSONDEF
...@@ -199,3 +201,25 @@ class TDBJSON : public TDBJSN { ...@@ -199,3 +201,25 @@ class TDBJSON : public TDBJSN {
bool Done; // True when document parsing is done bool Done; // True when document parsing is done
bool Changed; // After Update, Insert or Delete bool Changed; // After Update, Insert or Delete
}; // end of class TDBJSON }; // end of class TDBJSON
/***********************************************************************/
/* This is the class declaration for the JSON catalog table. */
/***********************************************************************/
class TDBJCL : public TDBCAT {
public:
// Constructor
TDBJCL(PJDEF tdp);
protected:
// Specific routines
virtual PQRYRES GetResult(PGLOBAL g);
// Members
//char *Dp;
const char *Fn;
char *Objn;
int Pretty;
int Lrecl;
int lvl;
}; // end of class TDBJCL
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to PlugDB Software Development 2003 - 2012 */ /* (C) Copyright to PlugDB Software Development 2003 - 2015 */
/* Author: Olivier BERTRAND */ /* Author: Olivier BERTRAND */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
...@@ -172,8 +172,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g) ...@@ -172,8 +172,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
while (n < PFNZ) { while (n < PFNZ) {
strcat(strcat(strcpy(filename, drive), direc), FileData.cFileName); strcat(strcat(strcpy(filename, drive), direc), FileData.cFileName);
pfn[n] = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1); pfn[n++] = PlugDup(g, filename);
strcpy(pfn[n++], filename);
if (!FindNextFile(hSearch, &FileData)) { if (!FindNextFile(hSearch, &FileData)) {
rc = GetLastError(); rc = GetLastError();
...@@ -239,8 +238,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g) ...@@ -239,8 +238,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
continue; // Not a match continue; // Not a match
strcat(strcpy(filename, direc), entry->d_name); strcat(strcpy(filename, direc), entry->d_name);
pfn[n] = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1); pfn[n] = PlugDup(g, filename);
strcpy(pfn[n++], filename);
if (trace) if (trace)
htrc("Adding pfn[%d] %s\n", n, filename); htrc("Adding pfn[%d] %s\n", n, filename);
...@@ -292,8 +290,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g) ...@@ -292,8 +290,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
*(++p) = '\0'; *(++p) = '\0';
// Suballocate the file name // Suballocate the file name
pfn[n] = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1); pfn[n++] = PlugDup(g, filename);
strcpy(pfn[n++], filename);
} // endfor n } // endfor n
} // endif Mul } // endif Mul
......
/************ TabOccur CPP Declares Source Code File (.CPP) ************/ /************ TabOccur CPP Declares Source Code File (.CPP) ************/
/* Name: TABOCCUR.CPP Version 1.1 */ /* Name: TABOCCUR.CPP Version 1.1 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2013 */ /* (C) Copyright to the author Olivier BERTRAND 2013 - 2015 */
/* */ /* */
/* OCCUR: Table that provides a view of a source table where the */ /* OCCUR: Table that provides a view of a source table where the */
/* contain of several columns of the source table is placed in only */ /* contain of several columns of the source table is placed in only */
...@@ -93,8 +93,7 @@ bool OcrColumns(PGLOBAL g, PQRYRES qrp, const char *col, ...@@ -93,8 +93,7 @@ bool OcrColumns(PGLOBAL g, PQRYRES qrp, const char *col,
} // endif col } // endif col
// Prepare the column list // Prepare the column list
colist = (char*)PlugSubAlloc(g, NULL, strlen(col) + 1); colist = PlugDup(g, col);
strcpy(colist, col);
m = PrepareColist(colist); m = PrepareColist(colist);
if ((rk = (rank && *rank))) { if ((rk = (rank && *rank))) {
...@@ -191,8 +190,7 @@ bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, const char *col, ...@@ -191,8 +190,7 @@ bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, const char *col,
} // endif col } // endif col
// Prepare the column list // Prepare the column list
colist = (char*)PlugSubAlloc(g, NULL, strlen(col) + 1); colist = PlugDup(g, col);
strcpy(colist, col);
m = PrepareColist(colist); m = PrepareColist(colist);
if ((rk = (rank && *rank))) if ((rk = (rank && *rank)))
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */ /* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -150,11 +150,18 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) ...@@ -150,11 +150,18 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
query = Tabsrc; query = Tabsrc;
// Open a MySQL connection for this table // Open a MySQL connection for this table
if (Myc.Open(g, Host, Database, User, Pwd, Port)) if (!Myc.Open(g, Host, Database, User, Pwd, Port)) {
return NULL;
else
b = true; b = true;
// Returned values must be in their original character set
if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX)
goto err;
else
Myc.FreeResult();
} else
return NULL;
// Send the source command to MySQL // Send the source command to MySQL
if (Myc.ExecSQL(g, query, &w) == RC_FX) if (Myc.ExecSQL(g, query, &w) == RC_FX)
goto err; goto err;
...@@ -241,6 +248,10 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) ...@@ -241,6 +248,10 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
} else { } else {
// The query was limited, we must get pivot column values // The query was limited, we must get pivot column values
// Returned values must be in their original character set
// if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX)
// goto err;
query = (char*)PlugSubAlloc(g, NULL, 0); query = (char*)PlugSubAlloc(g, NULL, 0);
sprintf(query, "SELECT DISTINCT `%s` FROM `%s`", Picol, Tabname); sprintf(query, "SELECT DISTINCT `%s` FROM `%s`", Picol, Tabname);
PlugSubAlloc(g, NULL, strlen(query) + 1); PlugSubAlloc(g, NULL, strlen(query) + 1);
...@@ -284,8 +295,7 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) ...@@ -284,8 +295,7 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
valp->SetValue_pvblk(Rblkp, i); valp->SetValue_pvblk(Rblkp, i);
colname = valp->GetCharString(buf); colname = valp->GetCharString(buf);
crp->Name = (char*)PlugSubAlloc(g, NULL, strlen(colname) + 1); crp->Name = PlugDup(g, colname);
strcpy(crp->Name, colname);
crp->Flag = 1; crp->Flag = 1;
// Add this column // Add this column
......
/************ Valblk C++ Functions Source Code File (.CPP) *************/ /************ Valblk C++ Functions Source Code File (.CPP) *************/
/* Name: VALBLK.CPP Version 2.1 */ /* Name: VALBLK.CPP Version 2.1 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */ /* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */ /* */
/* This file contains the VALBLK and derived classes functions. */ /* This file contains the VALBLK and derived classes functions. */
/* Second family is VALBLK, representing simple suballocated arrays */ /* Second family is VALBLK, representing simple suballocated arrays */
...@@ -1155,10 +1155,9 @@ void STRBLK::SetValue(PVAL valp, int n) ...@@ -1155,10 +1155,9 @@ void STRBLK::SetValue(PVAL valp, int n)
void STRBLK::SetValue(PSZ p, int n) void STRBLK::SetValue(PSZ p, int n)
{ {
if (p) { if (p) {
if (!Sorted || !n || !Strp[n-1] || strcmp(p, Strp[n-1])) { if (!Sorted || !n || !Strp[n-1] || strcmp(p, Strp[n-1]))
Strp[n] = (PSZ)PlugSubAlloc(Global, NULL, strlen(p) + 1); Strp[n] = (PSZ)PlugDup(Global, p);
strcpy(Strp[n], p); else
} else
Strp[n] = Strp[n-1]; Strp[n] = Strp[n-1];
} else } else
......
/**************** Table H Declares Source Code File (.H) ***************/ /**************** Table H Declares Source Code File (.H) ***************/
/* Name: TABLE.H Version 2.3 */ /* Name: TABLE.H Version 2.3 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 1999-2014 */ /* (C) Copyright to the author Olivier BERTRAND 1999-2015 */
/* */ /* */
/* This file contains the TBX, OPJOIN and TDB class definitions. */ /* This file contains the TBX, OPJOIN and TDB class definitions. */
/***********************************************************************/ /***********************************************************************/
...@@ -24,9 +24,7 @@ typedef class CMD *PCMD; ...@@ -24,9 +24,7 @@ typedef class CMD *PCMD;
class CMD : public BLOCK { class CMD : public BLOCK {
public: public:
// Constructor // Constructor
CMD(PGLOBAL g, char *cmd) { CMD(PGLOBAL g, char *cmd) {Cmd = PlugDup(g, cmd); Next = NULL;}
Cmd = (char*)PlugSubAlloc(g, NULL, strlen(cmd) + 1);
strcpy(Cmd, cmd); Next = NULL; }
// Members // Members
PCMD Next; PCMD Next;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment