Commit b3f9838f authored by Olivier Bertrand's avatar Olivier Bertrand

Update 10.1 with changes from 10.0

parent 48a77e61
......@@ -42,7 +42,6 @@
#include "tabcol.h"
#include "catalog.h"
#include "ha_connect.h"
#include "mycat.h"
#define my_strupr(p) my_caseup_str(default_charset_info, (p));
#define my_strlwr(p) my_casedn_str(default_charset_info, (p));
......
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level='asInvoker' uiAccess='false' />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
La ressource de manifeste a ‚t‚ mise … jour pour la derniŠre fois … 15:13:07,47 le 21/03/2015
......@@ -275,7 +275,7 @@ PXNODE DOMNODE::GetNext(PGLOBAL g)
{
if (Nodep->nextSibling == NULL)
Next = NULL;
else if (!Next)
else // if (!Next)
Next = new(g) DOMNODE(Doc, Nodep->nextSibling);
return Next;
......@@ -288,7 +288,7 @@ PXNODE DOMNODE::GetChild(PGLOBAL g)
{
if (Nodep->firstChild == NULL)
Children = NULL;
else if (!Children)
else // if (!Children)
Children = new(g) DOMNODE(Doc, Nodep->firstChild);
return Children;
......@@ -441,15 +441,27 @@ PXNODE DOMNODE::SelectSingleNode(PGLOBAL g, char *xp, PXNODE np)
/******************************************************************/
PXATTR DOMNODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap)
{
MSXML2::IXMLDOMElementPtr ep = Nodep;
MSXML2::IXMLDOMAttributePtr atp = ep->getAttributeNode(name);
MSXML2::IXMLDOMElementPtr ep;
MSXML2::IXMLDOMNamedNodeMapPtr nmp;
MSXML2::IXMLDOMAttributePtr atp;
if (name) {
ep = Nodep;
atp = ep->getAttributeNode(name);
nmp = NULL;
} else {
nmp = Nodep->Getattributes();
atp = nmp->Getitem(0);
} // endif name
if (atp) {
if (ap) {
((PDOMATTR)ap)->Atrp = atp;
((PDOMATTR)ap)->Nmp = nmp;
((PDOMATTR)ap)->K = 0;
return ap;
} else
return new(g) DOMATTR(Doc, atp);
return new(g) DOMATTR(Doc, atp, nmp);
} else
return NULL;
......@@ -617,14 +629,85 @@ bool DOMNODELIST::DropItem(PGLOBAL g, int n)
/******************************************************************/
/* DOMATTR constructor. */
/******************************************************************/
DOMATTR::DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap)
DOMATTR::DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap,
MSXML2::IXMLDOMNamedNodeMapPtr nmp)
: XMLATTRIBUTE(dp)
{
Atrp = ap;
Nmp = nmp;
Ws = NULL;
Len = 0;
K = 0;
} // end of DOMATTR constructor
/******************************************************************/
/* Return the attribute name. */
/******************************************************************/
char *DOMATTR::GetName(PGLOBAL g)
{
if (!WideCharToMultiByte(CP_ACP, 0, Atrp->nodeName, -1,
Name, sizeof(Name), NULL, NULL)) {
strcpy(g->Message, MSG(NAME_CONV_ERR));
return NULL;
} // endif
return Name;
} // end of GetName
/******************************************************************/
/* Return the next attribute node. */
/* This funtion is implemented as needed by XMLColumns. */
/******************************************************************/
PXATTR DOMATTR::GetNext(PGLOBAL g)
{
if (!Nmp)
return NULL;
if (++K >= Nmp->Getlength()) {
Nmp->reset();
Nmp = NULL;
K = 0;
return NULL;
} // endif K
Atrp = Nmp->Getitem(K);
return this;
} // end of GetNext
/******************************************************************/
/* Return the content of a node and subnodes. */
/******************************************************************/
RCODE DOMATTR::GetText(PGLOBAL g, char *buf, int len)
{
RCODE rc = RC_OK;
if (!WideCharToMultiByte(CP_UTF8, 0, Atrp->text, -1,
buf, len, NULL, NULL)) {
DWORD lsr = GetLastError();
switch (lsr) {
case 0:
case ERROR_INSUFFICIENT_BUFFER: // 122L
sprintf(g->Message, "Truncated %s content", GetName(g));
rc = RC_INFO;
break;
case ERROR_NO_UNICODE_TRANSLATION: // 1113L
sprintf(g->Message, "Invalid character(s) in %s content",
GetName(g));
rc = RC_INFO;
break;
default:
sprintf(g->Message, "System error getting %s content",
GetName(g));
rc = RC_FX;
break;
} // endswitch
} // endif
return rc;
} // end of GetText
/******************************************************************/
/* Set the text content of an attribute. */
/******************************************************************/
......
......@@ -122,15 +122,24 @@ class DOMATTR : public XMLATTRIBUTE {
friend class DOMDOC;
friend class DOMNODE;
public:
// Properties
virtual char *GetName(PGLOBAL g);
virtual PXATTR GetNext(PGLOBAL);
// Methods
virtual RCODE GetText(PGLOBAL g, char *bufp, int len);
virtual bool SetText(PGLOBAL g, char *txtp, int len);
protected:
// Constructor
DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap);
DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap,
MSXML2::IXMLDOMNamedNodeMapPtr nmp = NULL);
// Members
MSXML2::IXMLDOMAttributePtr Atrp;
MSXML2::IXMLDOMNamedNodeMapPtr Nmp;
char Name[64];
WCHAR *Ws;
int Len;
long K;
}; // end of class DOMATTR
......@@ -17,6 +17,7 @@ typedef class MAPFAM *PMAPFAM;
/* This is the variable file access method using file mapping. */
/***********************************************************************/
class DllExport MAPFAM : public TXTFAM {
friend class TDBJSON;
public:
// Constructor
MAPFAM(PDOSDEF tdp);
......
......@@ -42,6 +42,7 @@ class DllExport TXTFAM : public BLOCK {
virtual PTXF Duplicate(PGLOBAL g) = 0;
virtual bool GetUseTemp(void) {return false;}
virtual int GetDelRows(void) {return DelRows;}
PFBLOCK GetTo_Fb(void) {return To_Fb;}
int GetCurBlk(void) {return CurBlk;}
void SetTdbp(PTDBDOS tdbp) {Tdbp = tdbp;}
int GetBlock(void) {return Block;}
......
......@@ -145,7 +145,6 @@
#include "connect.h"
#include "user_connect.h"
#include "ha_connect.h"
#include "mycat.h"
#include "myutil.h"
#include "preparse.h"
#include "inihandl.h"
......@@ -169,7 +168,7 @@
#define JSONMAX 10 // JSON Default max grp size
extern "C" {
char version[]= "Version 1.03.0006 March 16, 2015";
char version[]= "Version 1.03.0006 April 12, 2015";
#if defined(WIN32)
char compver[]= "Version 1.03.0006 " __DATE__ " " __TIME__;
......@@ -211,6 +210,7 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, 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);
PQRYRES XMLColumns(PGLOBAL g, char *dp, char *tab, PTOS topt, bool info);
void PushWarning(PGLOBAL g, THD *thd, int level);
bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
const char *db, char *tab, const char *src, int port);
......@@ -5228,6 +5228,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
strcpy(g->Message, "Missing OEM module or subtype");
break;
#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT)
case TAB_XML:
#endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT
case TAB_JSON:
if (!fn)
sprintf(g->Message, "Missing %s file name", topt->type);
......@@ -5348,6 +5351,11 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
case TAB_JSON:
qrp= JSONColumns(g, (char*)db, fn, objn, pty, lrecl, lvl, fnc == FNC_COL);
break;
#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT)
case TAB_XML:
qrp= XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL);
break;
#endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT
case TAB_OEM:
qrp= OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL);
break;
......@@ -5386,6 +5394,8 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endfor crp
} else {
char *schem= NULL;
// Not a catalog table
if (!qrp->Nblin) {
if (tab)
......@@ -5469,6 +5479,19 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
key= crp->Kdata->GetCharValue(i);
break;
case FLD_SCHEM:
#if defined(ODBC_SUPPORT)
if (ttp == TAB_ODBC && crp->Kdata) {
if (schem && stricmp(schem, crp->Kdata->GetCharValue(i))) {
sprintf(g->Message,
"Several %s tables found, specify DBNAME", tab);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
goto err;
} else if (!schem)
schem= crp->Kdata->GetCharValue(i);
} // endif ttp
#endif // ODBC_SUPPORT
default:
break; // Ignore
} // endswitch Fld
......@@ -5790,6 +5813,18 @@ int ha_connect::create(const char *name, TABLE *table_arg,
} // endif type
if (type == TAB_JSON) {
int pretty= atoi(GetListOption(g, "Pretty", options->oplist, "2"));
if (!options->lrecl && pretty != 2) {
sprintf(g->Message, "LRECL must be specified for pretty=%d", pretty);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
rc= HA_ERR_INTERNAL_ERROR;
DBUG_RETURN(rc);
} // endif lrecl
} // endif type
// Check column types
for (field= table_arg->field; *field; field++) {
fp= *field;
......
......@@ -26,6 +26,11 @@
#pragma interface /* gcc class implementation */
#endif
/****************************************************************************/
/* mycat.h contains the TOS, PTOS, ha_table_option_struct declarations. */
/****************************************************************************/
#include "mycat.h"
static char *strz(PGLOBAL g, LEX_STRING &ls);
/****************************************************************************/
......@@ -68,7 +73,6 @@ class XCHK : public BLOCK {
typedef class XCHK *PCHK;
typedef class user_connect *PCONNECT;
typedef struct ha_table_option_struct TOS, *PTOS;
typedef struct ha_field_option_struct FOS, *PFOS;
typedef struct ha_index_option_struct XOS, *PXOS;
......@@ -80,6 +84,9 @@ extern handlerton *connect_hton;
These can be specified in the CREATE TABLE:
CREATE TABLE ( ... ) {...here...}
*/
#if 0 // moved to mycat.h
typedef struct ha_table_option_struct TOS, *PTOS;
struct ha_table_option_struct {
const char *type;
const char *filename;
......@@ -111,6 +118,7 @@ struct ha_table_option_struct {
bool readonly;
bool sepindex;
};
#endif // 0
/**
structure for CREATE TABLE options (field options)
......
......@@ -162,9 +162,11 @@ class XML2ATTR : public XMLATTRIBUTE {
friend class XML2NODE;
public:
// Properties
//virtual char *GetText(void);
virtual char *GetName(PGLOBAL g) {return (char*)Atrp->name;}
virtual PXATTR GetNext(PGLOBAL g);
// Methods
virtual RCODE GetText(PGLOBAL g, char *bufp, int len);
virtual bool SetText(PGLOBAL g, char *txtp, int len);
protected:
......@@ -812,7 +814,7 @@ PXNODE XML2NODE::GetNext(PGLOBAL g)
if (!Nodep->next)
Next = NULL;
else if (!Next)
else // if (!Next)
Next = new(g) XML2NODE(Doc, Nodep->next);
return Next;
......@@ -828,7 +830,7 @@ PXNODE XML2NODE::GetChild(PGLOBAL g)
if (!Nodep->children)
Children = NULL;
else if (!Children)
else // if (!Children)
Children = new(g) XML2NODE(Doc, Nodep->children);
return Children;
......@@ -978,10 +980,16 @@ PXNODE XML2NODE::SelectSingleNode(PGLOBAL g, char *xp, PXNODE np)
/******************************************************************/
PXATTR XML2NODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap)
{
xmlAttrPtr atp;
if (trace)
htrc("GetAttribute: %s\n", name);
htrc("GetAttribute: %s\n", SVP(name));
if (name)
atp = xmlHasProp(Nodep, BAD_CAST name);
else
atp = Nodep->properties;
xmlAttrPtr atp = xmlHasProp(Nodep, BAD_CAST name);
if (atp) {
if (ap) {
......@@ -1209,6 +1217,52 @@ XML2ATTR::XML2ATTR(PXDOC dp, xmlAttrPtr ap, xmlNodePtr np)
Parent = np;
} // end of XML2ATTR constructor
/******************************************************************/
/* Return the next sibling of the attribute. */
/******************************************************************/
PXATTR XML2ATTR::GetNext(PGLOBAL g)
{
if (trace)
htrc("Attr GetNext\n");
if (!Atrp->next)
return NULL;
else
return new(g) XML2ATTR(Doc, Atrp->next, Atrp->parent);
} // end of GetNext
/******************************************************************/
/* Return the text of an attribute. */
/******************************************************************/
RCODE XML2ATTR::GetText(PGLOBAL g, char *buf, int len)
{
RCODE rc = RC_OK;
xmlChar *txt;
if (trace)
htrc("GetText\n");
if ((txt = xmlGetProp(Atrp->parent, Atrp->name))) {
// Copy the text to the buffer
if (strlen((char*)txt) >= (unsigned)len) {
memcpy(buf, txt, len - 1);
buf[len - 1] = 0;
sprintf(g->Message, "Truncated %s content", Atrp->name);
rc = RC_INFO;
} else
strcpy(buf, (const char*)txt);
xmlFree(txt);
} else
*buf = '\0';
if (trace)
htrc("GetText: %s\n", buf);
return rc;
} // end of GetText
/******************************************************************/
/* Set the content of an attribute. */
/******************************************************************/
......
......@@ -74,9 +74,6 @@
#include "tabxcl.h"
#include "tabtbl.h"
#include "taboccur.h"
#if defined(XML_SUPPORT)
#include "tabxml.h"
#endif // XML_SUPPORT
#include "tabmul.h"
#include "tabmysql.h"
#if defined(ODBC_SUPPORT)
......@@ -89,7 +86,9 @@
#include "tabvir.h"
#include "tabjson.h"
#include "ha_connect.h"
#include "mycat.h"
#if defined(XML_SUPPORT)
#include "tabxml.h"
#endif // XML_SUPPORT
/***********************************************************************/
/* Extern static variables. */
......
......@@ -24,6 +24,46 @@
#include "block.h"
#include "catalog.h"
typedef struct ha_table_option_struct TOS, *PTOS;
/**
structure for CREATE TABLE options (table options)
These can be specified in the CREATE TABLE:
CREATE TABLE ( ... ) {...here...}
*/
struct ha_table_option_struct {
const char *type;
const char *filename;
const char *optname;
const char *tabname;
const char *tablist;
const char *dbname;
const char *separator;
//const char *connect;
const char *qchar;
const char *module;
const char *subtype;
const char *catfunc;
const char *srcdef;
const char *colist;
const char *oplist;
const char *data_charset;
ulonglong lrecl;
ulonglong elements;
//ulonglong estimate;
ulonglong multiple;
ulonglong header;
ulonglong quoted;
ulonglong ending;
ulonglong compressed;
bool mapped;
bool huge;
bool split;
bool readonly;
bool sepindex;
};
// Possible value for catalog functions
#define FNC_NO (1 << 0) // Not a catalog table
#define FNC_COL (1 << 1) // Column catalog function
......
......@@ -15,7 +15,7 @@ DATEPUB int(4)
) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN LANG SUBJECT AUTHOR TITLE TRANSLATION TRANSLATOR PUBLISHER DATEPUB
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapt de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
#
......@@ -37,7 +37,7 @@ Year int(4) FIELD_FORMAT='DATEPUB'
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN Language Subject Authors Title Translation Translator Publisher Location Year
9782212090819 fr applications 2 Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications 2 Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications 1 XML en Action adapt de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
#
......@@ -60,7 +60,7 @@ Year int(4) FIELD_FORMAT='DATEPUB'
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
9782212090819 fr applications Jean-Christophe and Franois Bernadac and Knab Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Jean-Christophe and Franois Bernadac and Knab Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapt de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
#
......@@ -83,14 +83,14 @@ Year int(4) FIELD_FORMAT='DATEPUB'
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Franois Knab Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML NULL NULL Eyrolles Paris 1999
9782212090819 fr applications Franois Knab Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapt de l'anglais par James Guerin Microsoft Press Paris 1999
UPDATE t1 SET AuthorFN = 'Philippe' WHERE AuthorLN = 'Knab';
SELECT * FROM t1 WHERE ISBN = '9782212090819';
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Franois Knab Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Philippe Bernadac Construire une application XML NULL NULL Eyrolles Paris 1999
9782212090819 fr applications Franois Knab Construire une application XML NULL NULL Eyrolles Paris 1999
#
# To add an author a new table must be created
#
......@@ -104,8 +104,8 @@ William J. Pardi
INSERT INTO t2 VALUES('Charles','Dickens');
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Franois Knab Construire une application XML Eyrolles Paris 1999
9782212090819 fr applications Philippe Bernadac Construire une application XML NULL NULL Eyrolles Paris 1999
9782212090819 fr applications Franois Knab Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapt de l'anglais par James Guerin Microsoft Press Paris 1999
9782840825685 fr applications Charles Dickens XML en Action adapt de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
......
......@@ -109,6 +109,7 @@ class XMLNODE : public BLOCK {
virtual int GetType(void) = 0;
virtual PXNODE GetNext(PGLOBAL) = 0;
virtual PXNODE GetChild(PGLOBAL) = 0;
virtual int GetLen(void) {return Len;}
// Methods
virtual RCODE GetContent(PGLOBAL, char *, int) = 0;
......@@ -163,9 +164,11 @@ class XMLNODELIST : public BLOCK {
class XMLATTRIBUTE : public BLOCK {
public:
// Properties
//virtual char *GetText(void) = 0;
virtual char *GetName(PGLOBAL) = 0;
virtual PXATTR GetNext(PGLOBAL) = 0;
// Methods
virtual RCODE GetText(PGLOBAL, char *, int) = 0;
virtual bool SetText(PGLOBAL, char *, int) = 0;
protected:
......
/************* RelDef CPP Program Source Code File (.CPP) **************/
/* PROGRAM NAME: REFDEF */
/* PROGRAM NAME: RELDEF */
/* ------------- */
/* Version 1.4 */
/* */
......@@ -35,7 +35,6 @@
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
#include "mycat.h"
#include "reldef.h"
#include "colblk.h"
#include "filamap.h"
......@@ -73,6 +72,14 @@ RELDEF::RELDEF(void)
Hc = NULL;
} // end of RELDEF constructor
/***********************************************************************/
/* This function return a pointer to the Table Option Struct. */
/***********************************************************************/
PTOS RELDEF::GetTopt(void)
{
return Hc->GetTableOptionStruct();
} // end of GetTopt
/***********************************************************************/
/* This function sets an integer table information. */
/***********************************************************************/
......
......@@ -12,6 +12,7 @@
#include "block.h"
#include "catalog.h"
#include "my_sys.h"
#include "mycat.h"
typedef class INDEXDEF *PIXDEF;
typedef class ha_connect *PHC;
......@@ -40,6 +41,7 @@ class DllExport RELDEF : public BLOCK { // Relation definition block
void SetCat(PCATLG cat) { Cat=cat; }
// Methods
PTOS GetTopt(void);
bool GetBoolCatInfo(PSZ what, bool bdef);
bool SetIntCatInfo(PSZ what, int ival);
bool Partitioned(void);
......
......@@ -19,7 +19,6 @@
#include "global.h"
#include "plgdbsem.h"
//#include "xtable.h"
//#include "mycat.h" // for FNC_COL
#include "maputil.h"
#include "filamtxt.h"
#include "tabdos.h"
......@@ -32,7 +31,7 @@
#include "tabmul.h"
#include "checklvl.h"
#include "resource.h"
#include "mycat.h"
#include "mycat.h" // for FNC_COL
/***********************************************************************/
/* This should be an option. */
......@@ -45,140 +44,6 @@
/***********************************************************************/
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;
......@@ -202,11 +67,9 @@ PQRYRES JSONColumns(PGLOBAL g, char *dp, const char *fn, char *objn,
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;
char filename[_MAX_PATH], colname[65], fmt[129];
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;
......@@ -214,7 +77,9 @@ PQRYRES JSONColumns(PGLOBAL g, char *dp, const char *fn, char *objn,
PJSON jsp;
PJVAL jvp;
PJOB row;
PJAR doc;
PJDEF tdp;
TDBJSN *tjnp;
PJTDB tjsp;
PQRYRES qrp;
PCOLRES crp;
......@@ -237,41 +102,47 @@ PQRYRES JSONColumns(PGLOBAL g, char *dp, const char *fn, char *objn,
} else
PlugSetPath(filename, fn, dp);
tdp = new(g) JSONDEF;
tdp->Database = dp;
tdp->Fn = filename;
tdp->Objname = objn;
tdp->Pretty = pretty;
if (pretty == 2) {
if (!MakeJsonTree(g, filename, objn, pretty, doc, drc))
tjsp = new(g) TDBJSON(tdp, new(g) MAPFAM(tdp));
if (tjsp->MakeDocument(g))
return NULL;
jsp = (doc) ? doc->GetValue(0) : NULL;
jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->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
} // endif lrecl
if (!(infile = global_fopen(g, MSGID_CANNOT_OPEN, filename, "r")))
return NULL;
tdp->Lrecl = lrecl;
tdp->Ending = CRLF;
tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp));
tjnp->SetMode(MODE_READ);
// Read first record
for (i = 0; i <= pretty; i++)
if (!fgets(buf, lrecl, infile)) {
if (feof(infile)) {
strcpy(g->Message, "Void json table");
if (tjnp->OpenDB(g))
return NULL;
} // endif fgets
sprintf(g->Message, MSG(READ_ERROR), filename, strerror(0));
return NULL;
} // endif fgets
switch (tjnp->ReadDB(g)) {
case RC_EF:
strcpy(g->Message, "Void json table");
case RC_FX:
goto err;
default:
jsp = tjnp->GetRow();
} // endswitch ReadDB
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;
goto err;
} // endif row
jcol.Next = NULL;
......@@ -394,20 +265,18 @@ PQRYRES JSONColumns(PGLOBAL g, char *dp, const char *fn, char *objn,
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 == ']') {
switch (tjnp->ReadDB(g)) {
case RC_EF:
jsp = NULL;
} else
jsp = ParseJson(g, buf, strlen(buf), pretty, NULL);
break;
case RC_FX:
goto err;
default:
jsp = tjnp->GetRow();
} // endswitch ReadDB
} else
jsp = doc->GetValue(i);
jsp = tjsp->GetDoc()->GetValue(i);
if (!(row = (jsp) ? jsp->GetObject() : NULL))
break;
......@@ -415,7 +284,7 @@ PQRYRES JSONColumns(PGLOBAL g, char *dp, const char *fn, char *objn,
} // endor i
if (pretty != 2)
fclose(infile);
tjnp->CloseDB(g);
skipit:
if (trace)
......@@ -471,7 +340,7 @@ PQRYRES JSONColumns(PGLOBAL g, char *dp, const char *fn, char *objn,
err:
if (pretty != 2)
fclose(infile);
tjnp->CloseDB(g);
return NULL;
} // end of JSONColumns
......@@ -487,6 +356,7 @@ JSONDEF::JSONDEF(void)
Limit = 1;
Level = 0;
ReadMode = 0;
Strict = false;
} // end of JSONDEF constructor
/***********************************************************************/
......@@ -540,7 +410,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
// Txfp must be set for TDBDOS
tdbp = new(g) TDBJSN(this, txfp);
} else {
txfp = new(g) DOSFAM(this);
txfp = new(g) MAPFAM(this);
tdbp = new(g) TDBJSON(this, txfp);
} // endif Pretty
......@@ -557,30 +427,45 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
/***********************************************************************/
TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
{
Top = NULL;
Row = NULL;
Val = NULL;
Colp = NULL;
if (tdp) {
Jmode = tdp->Jmode;
Objname = tdp->Objname;
Xcol = tdp->Xcol;
Limit = tdp->Limit;
Pretty = tdp->Pretty;
Strict = tdp->Strict;
} else {
Jmode = MODE_OBJECT;
Objname = NULL;
Xcol = NULL;
Limit = 1;
Pretty = 0;
Strict = false;
} // endif tdp
Fpos = -1;
//Spos = 0;
N = 0;
Limit = tdp->Limit;
NextSame = 0;
SameRow = 0;
Xval = -1;
Pretty = tdp->Pretty;
Strict = tdp->Strict;
Comma = false;
} // end of TDBJSN standard constructor
TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
{
Top = tdbp->Top;
Row = tdbp->Row;
Val = tdbp->Val;
Colp = tdbp->Colp;
Jmode = tdbp->Jmode;
Objname = tdbp->Objname;
Xcol = tdbp->Xcol;
Fpos = tdbp->Fpos;
//Spos = tdbp->Spos;
N = tdbp->N;
Limit = tdbp->Limit;
NextSame = tdbp->NextSame;
......@@ -658,6 +543,34 @@ int TDBJSN::GetMaxSize(PGLOBAL g)
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/
/* Find the row in the tree structure. */
/***********************************************************************/
PJSON TDBJSN::FindRow(PGLOBAL g)
{
char *p, *objpath;
PJSON jsp = Row;
PJVAL val = NULL;
for (objpath = PlugDup(g, Objname); jsp && objpath; objpath = p) {
if ((p = strchr(objpath, ':')))
*p++ = 0;
if (*objpath != '[') { // objpass is a key
val = (jsp->GetType() == TYPE_JOB) ?
jsp->GetObject()->GetValue(objpath) : NULL;
} else if (objpath[strlen(objpath)-1] == ']') {
val = (jsp->GetType() == TYPE_JAR) ?
jsp->GetArray()->GetValue(atoi(objpath+1) - 1) : NULL;
} else
val = NULL;
jsp = (val) ? val->GetJson() : NULL;
} // endfor objpath
return jsp;
} // end of FindRow
/***********************************************************************/
/* OpenDB: Data Base open routine for JSN access method. */
/***********************************************************************/
......@@ -668,7 +581,6 @@ bool TDBJSN::OpenDB(PGLOBAL g)
/* Table already open replace it at its beginning. */
/*******************************************************************/
Fpos= -1;
// Spos = 0;
NextSame = 0;
SameRow = 0;
} else {
......@@ -743,6 +655,7 @@ int TDBJSN::ReadDB(PGLOBAL g)
strlen(To_Line), Pretty, &Comma))) {
rc = (Pretty == 1 && !strcmp(To_Line, "]")) ? RC_EF : RC_FX;
} else {
Row = FindRow(g);
SameRow = 0;
Fpos++;
rc = RC_OK;
......@@ -751,20 +664,86 @@ int TDBJSN::ReadDB(PGLOBAL g)
return rc;
} // end of ReadDB
/***********************************************************************/
/* Make the top tree from the object path. */
/***********************************************************************/
int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
{
if (Objname) {
if (!Val) {
// Parse and allocate Objname item(s)
char *p;
char *objpath = PlugDup(g, Objname);
int i;
PJOB objp;
PJAR arp;
PJVAL val = NULL;
Top = NULL;
for (; objpath; objpath = p) {
if ((p = strchr(objpath, ':')))
*p++ = 0;
if (*objpath != '[') {
objp = new(g) JOBJECT;
if (!Top)
Top = objp;
if (val)
val->SetValue(objp);
val = new(g) JVALUE;
objp->SetValue(g, val, objpath);
} else if (objpath[strlen(objpath)-1] == ']') {
arp = new(g) JARRAY;
if (!Top)
Top = arp;
if (val)
val->SetValue(arp);
val = new(g) JVALUE;
i = atoi(objpath+1) - 1;
arp->SetValue(g, val, i);
arp->InitArray(g);
} else {
sprintf(g->Message, "Invalid Table path %s", Objname);
return RC_FX;
} // endif objpath
} // endfor p
Val = val;
} // endif Val
Val->SetValue(jsp);
} else
Top = jsp;
return RC_OK;
} // end of MakeTopTree
/***********************************************************************/
/* PrepareWriting: Prepare the line for WriteDB. */
/***********************************************************************/
bool TDBJSN::PrepareWriting(PGLOBAL g)
{
PSZ s = Serialize(g, Row, NULL, Pretty);
PSZ s;
if (s) {
if (MakeTopTree(g, Row))
return true;
if ((s = Serialize(g, Top, NULL, Pretty))) {
if (Comma)
strcat(s, ",");
if ((signed)strlen(s) > Lrecl) {
sprintf(g->Message, "Line would be truncated (lrecl=%d)", Lrecl);
return true;
strncpy(To_Line, s, Lrecl);
sprintf(g->Message, "Line truncated (lrecl=%d)", Lrecl);
return PushWarning(g, this);
} else
strcpy(To_Line, s);
......@@ -1083,6 +1062,10 @@ void JSONCOL::ReadColumn(PGLOBAL g)
if (!Tjp->SameRow || Xnod >= Tjp->SameRow)
Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0));
// Set null when applicable
if (Nullable)
Value->SetNull(Value->IsZero());
} // end of ReadColumn
/***********************************************************************/
......@@ -1272,7 +1255,7 @@ PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n)
/***********************************************************************/
PJSON JSONCOL::GetRow(PGLOBAL g)
{
PJVAL val;
PJVAL val = NULL;
PJAR arp;
PJSON nwr, row = Tjp->Row;
......@@ -1438,18 +1421,14 @@ void JSONCOL::WriteColumn(PGLOBAL g)
/***********************************************************************/
TDBJSON::TDBJSON(PJDEF tdp, PTXF txfp) : TDBJSN(tdp, txfp)
{
Top = NULL;
Doc = NULL;
Objname = tdp->Objname;
Multiple = tdp->Multiple;
Done = Changed = false;
} // end of TDBJSON standard constructor
TDBJSON::TDBJSON(PJTDB tdbp) : TDBJSN(tdbp)
{
Top = tdbp->Top;
Doc = tdbp->Doc;
Objname = tdbp->Objname;
Multiple = tdbp->Multiple;
Done = tdbp->Done;
Changed = tdbp->Changed;
......@@ -1473,64 +1452,17 @@ PTDB TDBJSON::CopyOne(PTABS t)
} // end of CopyOne
/***********************************************************************/
/* Make the document tree from a file. */
/* Make the document tree from the object path. */
/***********************************************************************/
int TDBJSON::MakeNewDoc(PGLOBAL g)
{
// Create a void table that will be populated
Doc = new(g) JARRAY;
if (Objname) {
// Parse and allocate Objname item(s)
char *p;
char *objpath = (char*)PlugSubAlloc(g, NULL, strlen(Objname)+1);
int i;
PJOB objp;
PJAR arp;
PJVAL val = NULL;
strcpy(objpath, Objname);
Top = NULL;
for (; objpath; objpath = p) {
if ((p = strchr(objpath, ':')))
*p++ = 0;
if (*objpath != '[') {
objp = new(g) JOBJECT;
if (!Top)
Top = objp;
if (val)
val->SetValue(objp);
val = new(g) JVALUE;
objp->SetValue(g, val, objpath);
} else if (objpath[strlen(objpath)-1] == ']') {
arp = new(g) JARRAY;
if (!Top)
Top = arp;
if (val)
val->SetValue(arp);
val = new(g) JVALUE;
i = atoi(objpath+1) - 1;
arp->SetValue(g, val, i);
arp->InitArray(g);
} else {
sprintf(g->Message, "Invalid Table path %s", Objname);
if (MakeTopTree(g, Doc))
return RC_FX;
} // endif objpath
} // endfor p
val->SetValue(Doc);
} else
Top = Doc;
Done = true;
return RC_OK;
} // end of MakeNewDoc
......@@ -1539,36 +1471,9 @@ int TDBJSON::MakeNewDoc(PGLOBAL g)
/***********************************************************************/
int TDBJSON::MakeDocument(PGLOBAL g)
{
char filename[_MAX_PATH];
int rc = RC_OK;
DWORD drc;
if (Done)
return RC_OK;
// Now open the JSON file
PlugSetPath(filename, Txfp->To_File, GetPath());
/*********************************************************************/
/* Get top of the parsed tree and the inside table document. */
/*********************************************************************/
if (!(Top = MakeJsonTree(g, filename, Objname, Pretty, Doc, drc)))
rc = (drc == ENOENT && Mode == MODE_INSERT) ? MakeNewDoc(g) : RC_FX;
Done = (rc == RC_OK);
return rc;
} // end of MakeDocument
#if 0
/***********************************************************************/
/* Make the document tree from a file. */
/***********************************************************************/
int TDBJSON::MakeDocument(PGLOBAL g)
{
char *p, *memory, *objpath, *key, filename[_MAX_PATH];
char *p, *memory, *objpath, *key;
int len, i = 0;
HANDLE hFile;
MEMMAP mm;
MODE mode = Mode;
PJSON jsp;
PJOB objp = NULL;
PJAR arp = NULL;
......@@ -1576,61 +1481,33 @@ int TDBJSON::MakeDocument(PGLOBAL g)
if (Done)
return RC_OK;
else
Done = true;
// Now open the JSON file
PlugSetPath(filename, Txfp->To_File, GetPath());
/*********************************************************************/
/* Create the mapping file object. */
/* Create the mapping file object in mode read. */
/*********************************************************************/
hFile = CreateFileMap(g, filename, &mm, MODE_READ, false);
Mode = MODE_READ;
if (hFile == INVALID_HANDLE_VALUE) {
DWORD drc = GetLastError();
if (!Txfp->OpenTableFile(g)) {
PFBLOCK fp = Txfp->GetTo_Fb();
if (drc != ENOENT || Mode != MODE_INSERT) {
if (!(*g->Message))
sprintf(g->Message, MSG(OPEN_MODE_ERROR),
"map", (int)drc, filename);
return RC_FX;
} else
return MakeNewDoc(g);
} // 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);
if (Mode == MODE_INSERT)
if (fp) {
len = fp->Length;
memory = fp->Memory;
} else {
Mode = mode; // Restore saved Mode
return MakeNewDoc(g);
} // endif fp
} // endif len
if (!memory) {
CloseFileHandle(hFile);
sprintf(g->Message, MSG(MAP_VIEW_ERROR), filename, GetLastError());
} else
return RC_FX;
} // endif Memory
CloseFileHandle(hFile); // Not used anymore
hFile = INVALID_HANDLE_VALUE; // For Fblock
/*********************************************************************/
/* Parse the json file and allocate its tree structure. */
/*********************************************************************/
g->Message[0] = 0;
jsp = Top = ParseJson(g, memory, len, Pretty);
CloseMemMap(memory, len);
Txfp->CloseTableFile(g, false);
Mode = mode; // Restore saved Mode
if (!jsp && g->Message[0])
return RC_FX;
......@@ -1707,9 +1584,9 @@ int TDBJSON::MakeDocument(PGLOBAL g)
} // endif jsp
Done = true;
return RC_OK;
} // end of MakeDocument
#endif // 0
/***********************************************************************/
/* JSON Cardinality: returns table size in number of rows. */
......
......@@ -35,6 +35,8 @@ class JSONDEF : public DOSDEF { /* Table description */
friend class TDBJSON;
friend class TDBJSN;
friend class TDBJCL;
friend PQRYRES JSONColumns(PGLOBAL, char *, const char *, char *,
int, int, int, bool);
public:
// Constructor
JSONDEF(void);
......@@ -74,6 +76,7 @@ class TDBJSN : public TDBDOS {
virtual AMT GetAmType(void) {return TYPE_AM_JSN;}
virtual bool SkipHeader(PGLOBAL g);
virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBJSN(this);}
PJSON GetRow(void) {return Row;}
// Methods
virtual PTDB CopyOne(PTABS t);
......@@ -90,10 +93,16 @@ class TDBJSN : public TDBDOS {
virtual int ReadDB(PGLOBAL g);
protected:
PJSON FindRow(PGLOBAL g);
int MakeTopTree(PGLOBAL g, PJSON jsp);
// Members
PJSON Top; // The top JSON tree
PJSON Row; // The current row
PJSON Val; // The value of the current row
PJCOL Colp; // The multiple column
JMODE Jmode; // MODE_OBJECT by default
char *Objname; // The table object name
char *Xcol; // Name of expandable column
int Fpos; // The current row index
//int Spos; // DELETE start index
......@@ -168,6 +177,7 @@ class TDBJSON : public TDBJSN {
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_JSON;}
virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBJSON(this);}
PJAR GetDoc(void) {return Doc;}
// Methods
virtual PTDB CopyOne(PTABS t);
......@@ -185,18 +195,16 @@ class TDBJSON : public TDBJSN {
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
int MakeDocument(PGLOBAL g);
// Optimization routines
virtual int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add);
protected:
int MakeNewDoc(PGLOBAL g);
int MakeDocument(PGLOBAL g);
// Members
PJSON Top; // The file JSON tree
PJAR Doc; // The document array
char *Objname; // The table object name
int Multiple; // 0: No 1: DIR 2: Section 3: filelist
bool Done; // True when document parsing is done
bool Changed; // After Update, Insert or Delete
......
......@@ -587,6 +587,10 @@ CATCOL::CATCOL(PCOLDEF cdp, PTDB tdbp, int n)
void CATCOL::ReadColumn(PGLOBAL g)
{
// Get the value of the Name or Description property
if (Crp->Kdata)
Value->SetValue_pvblk(Crp->Kdata, Tdbp->N);
else
Value->Reset();
} // end of ReadColumn
......@@ -56,7 +56,6 @@
#include "xtable.h"
#include "tabcol.h"
#include "colblk.h"
#include "mycat.h"
#include "reldef.h"
#include "tabmysql.h"
#include "valblk.h"
......
......@@ -47,7 +47,6 @@
#include "xtable.h"
#include "tabmysql.h"
#include "ha_connect.h"
#include "mycat.h"
/***********************************************************************/
/* Prepare and count columns in the column list. */
......
......@@ -49,7 +49,6 @@
#include "tabpivot.h"
#include "valblk.h"
#include "ha_connect.h"
#include "mycat.h" // For GetHandler
/***********************************************************************/
/* Make the Pivot table column list. */
......
......@@ -72,7 +72,6 @@
#include "tabtbl.h"
#include "tabmysql.h"
#include "ha_connect.h"
#include "mycat.h" // For GetHandler
#if defined(WIN32)
#if defined(__BORLANDC__)
......
......@@ -43,7 +43,6 @@
#include "plgdbsem.h"
#include "plgcnx.h" // For DB types
#include "myutil.h"
#include "mycat.h"
#include "valblk.h"
#include "resource.h"
#include "reldef.h"
......
......@@ -53,7 +53,6 @@
#include "xtable.h"
#include "tabmysql.h"
#include "ha_connect.h"
#include "mycat.h"
/* -------------- Implementation of the XCOL classes ---------------- */
......
/************* Tabxml C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABXML */
/* ------------- */
/* Version 2.7 */
/* Version 2.8 */
/* */
/* Author Olivier BERTRAND 2007 - 2014 */
/* Author Olivier BERTRAND 2007 - 2015 */
/* */
/* This program are the XML tables classes using MS-DOM or libxml2. */
/***********************************************************************/
......@@ -29,6 +29,7 @@
#include "osutil.h"
#define _O_RDONLY O_RDONLY
#endif // !WIN32
#include "resource.h" // for IDS_COLUMNS
#define INCLUDE_TDBXML
#define NODE_TYPE_LIST
......@@ -44,6 +45,7 @@
#include "reldef.h"
#include "xtable.h"
#include "colblk.h"
#include "mycat.h"
#include "xindex.h"
#include "plgxml.h"
#include "tabxml.h"
......@@ -57,6 +59,336 @@ extern "C" char version[];
#define XMLSUP "libxml2"
#endif // !WIN32
#define TYPE_UNKNOWN 12 /* Must be greater than other types */
/***********************************************************************/
/* Class and structure used by XMLColumns. */
/***********************************************************************/
typedef class XMCOL *PXCL;
class XMCOL : public BLOCK {
public:
// Constructors
XMCOL(void) {Next = NULL;
Name[0] = 0;
Fmt = NULL;
Type = 1;
Len = Scale = 0;
Cbn = false;
Found = true;}
XMCOL(PGLOBAL g, PXCL xp, char *fmt, int i) {
Next = NULL;
strcpy(Name, xp->Name);
Fmt = (*fmt) ? PlugDup(g, fmt) : NULL;
Type = xp->Type;
Len = xp->Len;
Scale = xp->Scale;
Cbn = (xp->Cbn || i > 1);
Found = true;}
// Members
PXCL Next;
char Name[64];
char *Fmt;
int Type;
int Len;
int Scale;
bool Cbn;
bool Found;
}; // end of class XMCOL
typedef struct LVL {
PXNODE pn;
PXLIST nl;
PXATTR atp;
bool b;
long k;
int m, n;
} *PLVL;
/***********************************************************************/
/* XMLColumns: construct the result blocks containing the description */
/* of all the columns of a table contained inside an XML file. */
/***********************************************************************/
PQRYRES XMLColumns(PGLOBAL g, char *dp, char *tab, PTOS topt, 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 *op, colname[65], fmt[129], buf[512];
int i, j, lvl, rc, n = 0;
int ncol = sizeof(buftyp) / sizeof(int);
bool ok = true;
PXCL xcol, xcp, fxcp = NULL, pxcp = NULL;
PLVL *lvlp, vp;
PXNODE node = NULL;
PXMLDEF tdp;
PTDBXML txmp;
PQRYRES qrp;
PCOLRES crp;
if (info) {
length[0] = 128;
length[7] = 256;
goto skipit;
} // endif info
/*********************************************************************/
/* Open the input file. */
/*********************************************************************/
if (!topt->filename) {
strcpy(g->Message, MSG(MISSING_FNAME));
return NULL;
} else
lvl = atoi(GetListOption(g, "Level", topt->oplist, "0"));
if (trace)
htrc("File %s lvl=%d\n", topt->filename, lvl);
tdp = new(g) XMLDEF;
tdp->Database = dp;
tdp->Fn = (char*)topt->filename;
tdp->Tabname = tab;
if (!(op = GetListOption(g, "Xmlsup", topt->oplist, NULL)))
#if defined(WIN32)
tdp->Usedom = true;
#else // !WIN32
tdp->Usedom = false;
#endif // !WIN32
else
tdp->Usedom = (toupper(*op) == 'M' || toupper(*op) == 'D');
txmp = new(g) TDBXML(tdp);
if (txmp->Initialize(g))
return NULL;
xcol = new(g) XMCOL;
colname[64] = 0;
fmt[128] = 0;
lvlp = (PLVL*)PlugSubAlloc(g, NULL, sizeof(PLVL) * (lvl + 1));
for (j = 0; j <= lvl; j++)
lvlp[j] = (PLVL)PlugSubAlloc(g, NULL, sizeof(LVL));
/*********************************************************************/
/* Analyse the XML tree and define columns. */
/*********************************************************************/
for (i = 1; ; i++) {
// Get next row
switch (txmp->ReadDB(g)) {
case RC_EF:
vp = NULL;
break;
case RC_FX:
goto err;
default:
vp = lvlp[0];
vp->pn = txmp->RowNode;
vp->atp = vp->pn->GetAttribute(g, NULL);
vp->nl = vp->pn->GetChildElements(g);
vp->b = true;
vp->k = 0;
vp->m = vp->n = 0;
j = 0;
} // endswitch ReadDB
if (!vp)
break;
while (true) {
if (!vp->atp &&
!(node = (vp->nl) ? vp->nl->GetItem(g, vp->k++, node) : NULL))
if (j) {
vp = lvlp[--j];
if (!tdp->Usedom) // nl was destroyed
vp->nl = vp->pn->GetChildElements(g);
if (!lvlp[j+1]->b) {
vp->k--;
ok = false;
} // endif b
continue;
} else
break;
xcol->Name[vp->n] = 0;
fmt[vp->m] = 0;
more:
if (vp->atp) {
strncpy(colname, vp->atp->GetName(g), sizeof(colname));
strncat(xcol->Name, colname, 64);
rc = vp->atp->GetText(g, buf, sizeof(buf));
strncat(fmt, "@", sizeof(fmt));
if (j)
strncat(fmt, colname, sizeof(fmt));
} else {
if (tdp->Usedom && node->GetType() != 1)
continue;
strncpy(colname, node->GetName(g), sizeof(colname));
strncat(xcol->Name, colname, 64);
if (j)
strncat(fmt, colname, sizeof(fmt));
if (j < lvl && ok) {
vp = lvlp[j+1];
vp->k = 0;
vp->atp = node->GetAttribute(g, NULL);
vp->nl = node->GetChildElements(g);
if (tdp->Usedom && vp->nl->GetLength() == 1) {
node = vp->nl->GetItem(g, 0, node);
vp->b = (node->GetType() == 1); // Must be ab element
} else
vp->b = (vp->nl && vp->nl->GetLength());
if (vp->atp || vp->b) {
if (!vp->atp)
node = vp->nl->GetItem(g, vp->k++, node);
strncat(strncat(fmt, colname, 125), "/", 125);
strncat(xcol->Name, "_", 64);
j++;
vp->n = (int)strlen(xcol->Name);
vp->m = (int)strlen(fmt);
goto more;
} else {
vp = lvlp[j];
if (!tdp->Usedom) // nl was destroyed
vp->nl = vp->pn->GetChildElements(g);
} // endif vp
} else
ok = true;
rc = node->GetContent(g, buf, sizeof(buf));
} // endif atp;
xcol->Len = strlen(buf);
// Check whether this column was already found
for (xcp = fxcp; xcp; xcp = xcp->Next)
if (!strcmp(xcol->Name, xcp->Name))
break;
if (xcp) {
if (xcp->Type != xcol->Type)
xcp->Type = TYPE_STRING;
if (*fmt && (!xcp->Fmt || strlen(xcp->Fmt) < strlen(fmt))) {
xcp->Fmt = PlugDup(g, fmt);
length[7] = MY_MAX(length[7], strlen(fmt));
} // endif *fmt
xcp->Len = MY_MAX(xcp->Len, xcol->Len);
xcp->Scale = MY_MAX(xcp->Scale, xcol->Scale);
xcp->Cbn |= xcol->Cbn;
xcp->Found = true;
} else {
// New column
xcp = new(g) XMCOL(g, xcol, fmt, i);
length[0] = MY_MAX(length[0], strlen(xcol->Name));
length[7] = MY_MAX(length[7], strlen(fmt));
if (pxcp) {
xcp->Next = pxcp->Next;
pxcp->Next = xcp;
} else
fxcp = xcp;
n++;
} // endif xcp
pxcp = xcp;
// for (j = lvl - 1; j >= 0; j--)
// if (jrp[j] && (jrp[j] = jrp[j]->GetNext()))
// goto more;
if (vp->atp)
vp->atp = vp->atp->GetNext(g);
} // endwhile
// Missing column can be null
for (xcp = fxcp; xcp; xcp = xcp->Next) {
xcp->Cbn |= !xcp->Found;
xcp->Found = false;
} // endfor xcp
} // endor i
txmp->CloseDB(g);
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 = "Xpath";
if (info || !qrp)
return qrp;
qrp->Nblin = n;
/*********************************************************************/
/* Now get the results into blocks. */
/*********************************************************************/
for (i = 0, xcp = fxcp; xcp; i++, xcp = xcp->Next) {
if (xcp->Type == TYPE_UNKNOWN) // Void column
xcp->Type = TYPE_STRING;
crp = qrp->Colresp; // Column Name
crp->Kdata->SetValue(xcp->Name, i);
crp = crp->Next; // Data Type
crp->Kdata->SetValue(xcp->Type, i);
crp = crp->Next; // Type Name
crp->Kdata->SetValue(GetTypeName(xcp->Type), i);
crp = crp->Next; // Precision
crp->Kdata->SetValue(xcp->Len, i);
crp = crp->Next; // Length
crp->Kdata->SetValue(xcp->Len, i);
crp = crp->Next; // Scale (precision)
crp->Kdata->SetValue(xcp->Scale, i);
crp = crp->Next; // Nullable
crp->Kdata->SetValue(xcp->Cbn ? 1 : 0, i);
crp = crp->Next; // Field format
if (crp->Kdata)
crp->Kdata->SetValue(xcp->Fmt, i);
} // endfor i
/*********************************************************************/
/* Return the result pointer. */
/*********************************************************************/
return qrp;
err:
txmp->CloseDB(g);
return NULL;
} // end of XMLColumns
/* -------------- Implementation of the XMLDEF class ---------------- */
/***********************************************************************/
......@@ -176,6 +508,9 @@ bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
PTDB XMLDEF::GetTable(PGLOBAL g, MODE m)
{
if (Catfunc == FNC_COL)
return new(g) TDBXCT(this);
PTDBASE tdbp = new(g) TDBXML(this);
if (Multiple)
......@@ -229,14 +564,14 @@ TDBXML::TDBXML(PXMLDEF tdp) : TDBASE(tdp)
Xfile = tdp->Fn;
Enc = tdp->Encoding;
Tabname = tdp->Tabname;
Rowname = (*tdp->Rowname) ? tdp->Rowname : NULL;
Colname = (*tdp->Colname) ? tdp->Colname : NULL;
Mulnode = (*tdp->Mulnode) ? tdp->Mulnode : NULL;
XmlDB = (*tdp->XmlDB) ? tdp->XmlDB : NULL;
Nslist = (*tdp->Nslist) ? tdp->Nslist : NULL;
DefNs = (*tdp->DefNs) ? tdp->DefNs : NULL;
Attrib = (*tdp->Attrib) ? tdp->Attrib : NULL;
Hdattr = (*tdp->Hdattr) ? tdp->Hdattr : NULL;
Rowname = (tdp->Rowname && *tdp->Rowname) ? tdp->Rowname : NULL;
Colname = (tdp->Colname && *tdp->Colname) ? tdp->Colname : NULL;
Mulnode = (tdp->Mulnode && *tdp->Mulnode) ? tdp->Mulnode : NULL;
XmlDB = (tdp->XmlDB && *tdp->XmlDB) ? tdp->XmlDB : NULL;
Nslist = (tdp->Nslist && *tdp->Nslist) ? tdp->Nslist : NULL;
DefNs = (tdp->DefNs && *tdp->DefNs) ? tdp->DefNs : NULL;
Attrib = (tdp->Attrib && *tdp->Attrib) ? tdp->Attrib : NULL;
Hdattr = (tdp->Hdattr && *tdp->Hdattr) ? tdp->Hdattr : NULL;
Coltype = tdp->Coltype;
Limit = tdp->Limit;
Xpand = tdp->Xpand;
......@@ -771,7 +1106,6 @@ bool TDBXML::OpenDB(PGLOBAL g)
NewRow = (Mode == MODE_INSERT);
Nsub = 0;
Use = USE_OPEN; // Do it now in case we are recursively called
return false;
} // end of OpenDB
......@@ -1847,4 +2181,24 @@ void XPOSCOL::WriteColumn(PGLOBAL g)
} // end of WriteColumn
/* ---------------------------TDBXCT class --------------------------- */
/***********************************************************************/
/* TDBXCT class constructor. */
/***********************************************************************/
TDBXCT::TDBXCT(PXMLDEF tdp) : TDBCAT(tdp)
{
Topt = tdp->GetTopt();
Dp = tdp->GetPath();
Tabn = tdp->Tabname;
} // end of TDBXCT constructor
/***********************************************************************/
/* GetResult: Get the list the JSON file columns. */
/***********************************************************************/
PQRYRES TDBXCT::GetResult(PGLOBAL g)
{
return XMLColumns(g, Dp, Tabn, Topt, false);
} // end of GetResult
/* ------------------------ End of Tabxml ---------------------------- */
......@@ -16,6 +16,8 @@ typedef class XMLCOL *PXMLCOL;
/***********************************************************************/
class DllExport XMLDEF : public TABDEF { /* Logical table description */
friend class TDBXML;
friend class TDBXCT;
friend PQRYRES XMLColumns(PGLOBAL, char*, char*, PTOS, bool);
public:
// Constructor
XMLDEF(void);
......@@ -55,6 +57,7 @@ class DllExport TDBXML : public TDBASE {
friend class XMLCOL;
friend class XMULCOL;
friend class XPOSCOL;
friend PQRYRES XMLColumns(PGLOBAL, char*, char*, PTOS, bool);
public:
// Constructor
TDBXML(PXMLDEF tdp);
......@@ -237,4 +240,24 @@ class XPOSCOL : public XMLCOLX {
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
}; // end of class XPOSCOL
/***********************************************************************/
/* This is the class declaration for the XML catalog table. */
/***********************************************************************/
class TDBXCT : public TDBCAT {
public:
// Constructor
TDBXCT(PXMLDEF tdp);
protected:
// Specific routines
virtual PQRYRES GetResult(PGLOBAL g);
// Members
PTOS Topt;
char *Dp;
//const char *Fn;
char *Tabn;
}; // end of class TDBXCT
#endif // INCLUDE_TDBXML
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