summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2015-04-17 20:05:41 +0200
committerOlivier Bertrand <bertrandop@gmail.com>2015-04-17 20:05:41 +0200
commiteae8318b19da168e4676fe3da5b2f8665cb4104c (patch)
tree36e1fa5fe72d8c72d2876f5c47838d7b406ff0fa
parent05b30fbcc38cdc5dcd248f9b8385a9fec65f2d96 (diff)
downloadmariadb-git-eae8318b19da168e4676fe3da5b2f8665cb4104c.tar.gz
- Fix Catalog JSON table crash when no Jpath
- Added JSON OBJECT specification for pretty != 2. - Fix NULL values not recognized for nullable JSON columns - Issue an error message when a JSON table is created without specifying LRECL if PRETTY != 2. - Make JSONColumns use a TDBJSON class. - Make JSON table using MAPFAM modified: filamap.h filamtxt.h ha_connect.cc json.result tabjson.cpp tabjson.h table.cpp - Implementing Discovery for the XML table type. modified: domdoc.cpp domdoc.h ha_connect.cc libdoc.cpp plgxml.cpp plgxml.h reldef.cpp reldef.h tabxml.cpp tabxml.h - Providing an error message when creating an ODBC table via discovery returns columns of more than one table. modified: ha_connect.cc - TableOptionStruct declaration moved from ha_connect.h to mycat.h To make it easier to use by other classes. modified: ha_connect.cc ha_connect.h mycat.cc mycat.h reldef.cpp tabmysql.cpp taboccur.cpp tabpivot.cpp tabtbl.cpp tabutil.cpp tabxcl.cpp
-rw-r--r--storage/connect/connect.cc1
-rw-r--r--storage/connect/domdoc.cpp95
-rw-r--r--storage/connect/domdoc.h19
-rw-r--r--storage/connect/filamap.h1
-rw-r--r--storage/connect/filamtxt.h1
-rw-r--r--storage/connect/ha_connect.cc41
-rw-r--r--storage/connect/ha_connect.h10
-rw-r--r--storage/connect/libdoc.cpp66
-rw-r--r--storage/connect/mycat.cc7
-rw-r--r--storage/connect/mycat.h40
-rw-r--r--storage/connect/mysql-test/connect/r/json.result18
-rw-r--r--storage/connect/plgxml.h15
-rw-r--r--storage/connect/reldef.cpp11
-rw-r--r--storage/connect/reldef.h2
-rw-r--r--storage/connect/tabjson.cpp509
-rw-r--r--storage/connect/tabjson.h40
-rw-r--r--storage/connect/table.cpp6
-rw-r--r--storage/connect/tabmysql.cpp1
-rw-r--r--storage/connect/taboccur.cpp1
-rw-r--r--storage/connect/tabpivot.cpp1
-rw-r--r--storage/connect/tabtbl.cpp1
-rw-r--r--storage/connect/tabutil.cpp1
-rw-r--r--storage/connect/tabxcl.cpp1
-rw-r--r--storage/connect/tabxml.cpp376
-rw-r--r--storage/connect/tabxml.h23
25 files changed, 894 insertions, 393 deletions
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index 1b0db6dca6b..7c32c65226d 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -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));
diff --git a/storage/connect/domdoc.cpp b/storage/connect/domdoc.cpp
index 518c806c653..9e518775c0f 100644
--- a/storage/connect/domdoc.cpp
+++ b/storage/connect/domdoc.cpp
@@ -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,15 +629,86 @@ 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. */
/******************************************************************/
bool DOMATTR::SetText(PGLOBAL g, char *txtp, int len)
diff --git a/storage/connect/domdoc.h b/storage/connect/domdoc.h
index 118541d8eb0..2cffec499e2 100644
--- a/storage/connect/domdoc.h
+++ b/storage/connect/domdoc.h
@@ -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 bool SetText(PGLOBAL g, char *txtp, int len);
+ 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;
- WCHAR *Ws;
- int Len;
+ MSXML2::IXMLDOMAttributePtr Atrp;
+ MSXML2::IXMLDOMNamedNodeMapPtr Nmp;
+ char Name[64];
+ WCHAR *Ws;
+ int Len;
+ long K;
}; // end of class DOMATTR
diff --git a/storage/connect/filamap.h b/storage/connect/filamap.h
index 1d44239e610..b9c8ad965fd 100644
--- a/storage/connect/filamap.h
+++ b/storage/connect/filamap.h
@@ -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);
diff --git a/storage/connect/filamtxt.h b/storage/connect/filamtxt.h
index 864ca66dd34..1c8ea1e3a6c 100644
--- a/storage/connect/filamtxt.h
+++ b/storage/connect/filamtxt.h
@@ -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;}
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index d310ff55980..a3f88bfe7eb 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -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;
@@ -5385,7 +5393,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
#endif // !NEW_WAY
} // endfor crp
- } else {
+ } 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;
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index c3b911710b8..611f9ba0b54 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -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 @@ public:
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)
diff --git a/storage/connect/libdoc.cpp b/storage/connect/libdoc.cpp
index e5c0ee6cfff..7d1d014c48b 100644
--- a/storage/connect/libdoc.cpp
+++ b/storage/connect/libdoc.cpp
@@ -162,10 +162,12 @@ 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 bool SetText(PGLOBAL g, char *txtp, int len);
+ virtual RCODE GetText(PGLOBAL g, char *bufp, int len);
+ virtual bool SetText(PGLOBAL g, char *txtp, int len);
protected:
// Constructor
@@ -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) {
@@ -1210,6 +1218,52 @@ XML2ATTR::XML2ATTR(PXDOC dp, xmlAttrPtr ap, xmlNodePtr 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. */
/******************************************************************/
bool XML2ATTR::SetText(PGLOBAL g, char *txtp, int len)
diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc
index a4986da4089..b15c8fa2322 100644
--- a/storage/connect/mycat.cc
+++ b/storage/connect/mycat.cc
@@ -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. */
diff --git a/storage/connect/mycat.h b/storage/connect/mycat.h
index 1aaee4ed1e8..cdbe4e5bca9 100644
--- a/storage/connect/mycat.h
+++ b/storage/connect/mycat.h
@@ -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
diff --git a/storage/connect/mysql-test/connect/r/json.result b/storage/connect/mysql-test/connect/r/json.result
index ebcad699759..fa6497e5bba 100644
--- a/storage/connect/mysql-test/connect/r/json.result
+++ b/storage/connect/mysql-test/connect/r/json.result
@@ -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 François Bernadac and Knab Construire une application XML Eyrolles Paris 1999
+9782212090819 fr applications Jean-Christophe and François 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 François 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 François 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 François 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 François 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 François 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 François 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;
diff --git a/storage/connect/plgxml.h b/storage/connect/plgxml.h
index 74a16fd4823..b8e914e0bf1 100644
--- a/storage/connect/plgxml.h
+++ b/storage/connect/plgxml.h
@@ -1,5 +1,5 @@
/******************************************************************/
-/* Dual XML implementation base classes defines. */
+/* Dual XML implementation base classes defines. */
/******************************************************************/
#if !defined(BASE_BUFFER_SIZE)
enum ElementType { // libxml2
@@ -43,7 +43,7 @@ enum NodeType { // MS DOM
NODE_NOTATION = 12};
#endif // !NODE_TYPE_LIST
-typedef class XMLDOCUMENT *PXDOC; // Document
+typedef class XMLDOCUMENT *PXDOC; // Document
typedef class XMLNODE *PXNODE; // Node (Element)
typedef class XMLNODELIST *PXLIST; // Node list
typedef class XMLATTRIBUTE *PXATTR; // Attribute
@@ -93,9 +93,9 @@ class XMLDOCUMENT : public BLOCK {
bool MakeNSlist(PGLOBAL g);
// Members
- PNS Namespaces; /* To the namespaces */
+ PNS Namespaces; /* To the namespaces */
char *Encoding; /* The document encoding */
- char *Nslist; /* Namespace list */
+ char *Nslist; /* Namespace list */
char *DefNs; /* Default namespace */
}; // end of class XMLDOCUMENT
@@ -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,10 +164,12 @@ 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 bool SetText(PGLOBAL, char *, int) = 0;
+ virtual RCODE GetText(PGLOBAL, char *, int) = 0;
+ virtual bool SetText(PGLOBAL, char *, int) = 0;
protected:
// Constructor
diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp
index c6cbedd9636..47f825e965d 100644
--- a/storage/connect/reldef.cpp
+++ b/storage/connect/reldef.cpp
@@ -1,5 +1,5 @@
/************* 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"
@@ -74,6 +73,14 @@ RELDEF::RELDEF(void)
} // 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. */
/***********************************************************************/
bool RELDEF::SetIntCatInfo(PSZ what, int n)
diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h
index 6160ea71680..13bd392b706 100644
--- a/storage/connect/reldef.h
+++ b/storage/connect/reldef.h
@@ -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);
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index af33adc69b0..4432f164cf8 100644
--- a/storage/connect/tabjson.cpp
+++ b/storage/connect/tabjson.cpp
@@ -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;
@@ -235,43 +100,49 @@ PQRYRES JSONColumns(PGLOBAL g, char *dp, const char *fn, char *objn,
strcpy(g->Message, MSG(MISSING_FNAME));
return NULL;
} else
- PlugSetPath(filename, fn, dp);
+ 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");
- return NULL;
- } // endif fgets
+ if (tjnp->OpenDB(g))
+ return NULL;
- 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
+ } // 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
+ switch (tjnp->ReadDB(g)) {
+ case RC_EF:
jsp = NULL;
-
- } else if (pretty == 1 && strlen(buf) == 1 && *buf == ']') {
- 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;
- Jmode = tdp->Jmode;
- Xcol = tdp->Xcol;
+
+ 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;
@@ -659,6 +544,34 @@ int TDBJSN::GetMaxSize(PGLOBAL g)
} // 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. */
/***********************************************************************/
bool TDBJSN::OpenDB(PGLOBAL g)
@@ -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;
@@ -752,19 +665,85 @@ int TDBJSN::ReadDB(PGLOBAL g)
} // 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 (MakeTopTree(g, Row))
+ return true;
- if (s) {
+ 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);
- return RC_FX;
- } // endif objpath
-
- } // endfor p
-
- val->SetValue(Doc);
- } else
- Top = Doc;
+ if (MakeTopTree(g, Doc))
+ return RC_FX;
+ 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. */
- /*********************************************************************/
- hFile = CreateFileMap(g, filename, &mm, MODE_READ, false);
-
- if (hFile == INVALID_HANDLE_VALUE) {
- DWORD drc = GetLastError();
-
- 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) */
+ /* Create the mapping file object in mode read. */
/*********************************************************************/
- len = mm.lenL;
- memory = (char *)mm.memory;
-
- if (!len) { // Empty file
- CloseFileHandle(hFile);
- CloseMemMap(memory, len);
+ Mode = MODE_READ;
- if (Mode == MODE_INSERT)
- return MakeNewDoc(g);
+ if (!Txfp->OpenTableFile(g)) {
+ PFBLOCK fp = Txfp->GetTo_Fb();
- } // endif len
+ if (fp) {
+ len = fp->Length;
+ memory = fp->Memory;
+ } else {
+ Mode = mode; // Restore saved Mode
+ return MakeNewDoc(g);
+ } // endif fp
- 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. */
diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h
index 20683a67971..7e9896c3b75 100644
--- a/storage/connect/tabjson.h
+++ b/storage/connect/tabjson.h
@@ -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);
@@ -71,29 +73,36 @@ class TDBJSN : public TDBDOS {
TDBJSN(TDBJSN *tdbp);
// Implementation
- virtual AMT GetAmType(void) {return TYPE_AM_JSN;}
- virtual bool SkipHeader(PGLOBAL g);
- virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBJSN(this);}
+ 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);
- virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
- virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
- virtual int RowNumber(PGLOBAL g, bool b = FALSE)
- {return (b) ? N : Fpos + 1;}
+ virtual PTDB CopyOne(PTABS t);
+ virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
+ virtual int RowNumber(PGLOBAL g, bool b = FALSE)
+ {return (b) ? N : Fpos + 1;}
// Database routines
- virtual int Cardinality(PGLOBAL g);
- virtual int GetMaxSize(PGLOBAL g);
- virtual bool OpenDB(PGLOBAL g);
- virtual bool PrepareWriting(PGLOBAL g);
- virtual int ReadDB(PGLOBAL g);
+ virtual int Cardinality(PGLOBAL g);
+ virtual int GetMaxSize(PGLOBAL g);
+ virtual bool OpenDB(PGLOBAL g);
+ virtual bool PrepareWriting(PGLOBAL g);
+ 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
diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp
index cbd5910d8c8..d163c443cd5 100644
--- a/storage/connect/table.cpp
+++ b/storage/connect/table.cpp
@@ -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
- Value->SetValue_pvblk(Crp->Kdata, Tdbp->N);
+ if (Crp->Kdata)
+ Value->SetValue_pvblk(Crp->Kdata, Tdbp->N);
+ else
+ Value->Reset();
+
} // end of ReadColumn
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index e4befc8bfde..66f275796b5 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -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"
diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp
index 5ef0ee52653..7f7b1c5d50c 100644
--- a/storage/connect/taboccur.cpp
+++ b/storage/connect/taboccur.cpp
@@ -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. */
diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp
index 4b333b2eb56..401ffa3780e 100644
--- a/storage/connect/tabpivot.cpp
+++ b/storage/connect/tabpivot.cpp
@@ -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. */
diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp
index 64a9a176cca..1ef70549751 100644
--- a/storage/connect/tabtbl.cpp
+++ b/storage/connect/tabtbl.cpp
@@ -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__)
diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp
index 6c4760e763f..1c238bcf6f2 100644
--- a/storage/connect/tabutil.cpp
+++ b/storage/connect/tabutil.cpp
@@ -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"
diff --git a/storage/connect/tabxcl.cpp b/storage/connect/tabxcl.cpp
index 454210b6e6a..dffbaf6e187 100644
--- a/storage/connect/tabxcl.cpp
+++ b/storage/connect/tabxcl.cpp
@@ -53,7 +53,6 @@
#include "xtable.h"
#include "tabmysql.h"
#include "ha_connect.h"
-#include "mycat.h"
/* -------------- Implementation of the XCOL classes ---------------- */
diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp
index 8c73907c7ee..8ea44fed2be 100644
--- a/storage/connect/tabxml.cpp
+++ b/storage/connect/tabxml.cpp
@@ -1,9 +1,9 @@
/************* 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 ---------------------------- */
diff --git a/storage/connect/tabxml.h b/storage/connect/tabxml.h
index a3dc0a2b54c..f6cfd3fb510 100644
--- a/storage/connect/tabxml.h
+++ b/storage/connect/tabxml.h
@@ -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