mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
- 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
This commit is contained in:
@@ -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));
|
||||
|
@@ -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 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
|
||||
|
@@ -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;
|
||||
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
{
|
||||
if (trace)
|
||||
htrc("GetAttribute: %s\n", name);
|
||||
xmlAttrPtr atp;
|
||||
|
||||
if (trace)
|
||||
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<70> 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<70> 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<61>ois Bernadac and Knab Construire une application XML Eyrolles Paris 1999
|
||||
9782212090819 fr applications Jean-Christophe and Fran<61>ois Bernadac and Knab Construire une application XML NULL NULL Eyrolles Paris 1999
|
||||
9782840825685 fr applications William J. Pardi XML en Action adapt<70> 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<61>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<61>ois Knab Construire une application XML NULL NULL Eyrolles Paris 1999
|
||||
9782840825685 fr applications William J. Pardi XML en Action adapt<70> 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<61>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<61>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<61>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<61>ois Knab Construire une application XML NULL NULL Eyrolles Paris 1999
|
||||
9782840825685 fr applications William J. Pardi XML en Action adapt<70> de l'anglais par James Guerin Microsoft Press Paris 1999
|
||||
9782840825685 fr applications Charles Dickens XML en Action adapt<70> de l'anglais par James Guerin Microsoft Press Paris 1999
|
||||
DROP TABLE t1;
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
@@ -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;
|
||||
|
||||
@@ -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")))
|
||||
tdp->Lrecl = lrecl;
|
||||
tdp->Ending = CRLF;
|
||||
tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp));
|
||||
tjnp->SetMode(MODE_READ);
|
||||
|
||||
if (tjnp->OpenDB(g))
|
||||
return NULL;
|
||||
|
||||
// Read first record
|
||||
for (i = 0; i <= pretty; i++)
|
||||
if (!fgets(buf, lrecl, infile)) {
|
||||
if (feof(infile)) {
|
||||
strcpy(g->Message, "Void json table");
|
||||
return NULL;
|
||||
} // endif fgets
|
||||
switch (tjnp->ReadDB(g)) {
|
||||
case RC_EF:
|
||||
strcpy(g->Message, "Void json table");
|
||||
case RC_FX:
|
||||
goto err;
|
||||
default:
|
||||
jsp = tjnp->GetRow();
|
||||
} // endswitch ReadDB
|
||||
|
||||
sprintf(g->Message, MSG(READ_ERROR), filename, strerror(0));
|
||||
return NULL;
|
||||
} // endif fgets
|
||||
|
||||
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;
|
||||
@@ -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);
|
||||
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 in mode read. */
|
||||
/*********************************************************************/
|
||||
Mode = MODE_READ;
|
||||
|
||||
/*********************************************************************/
|
||||
/* Create the mapping file object. */
|
||||
/*********************************************************************/
|
||||
hFile = CreateFileMap(g, filename, &mm, MODE_READ, false);
|
||||
if (!Txfp->OpenTableFile(g)) {
|
||||
PFBLOCK fp = Txfp->GetTo_Fb();
|
||||
|
||||
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
|
||||
if (fp) {
|
||||
len = fp->Length;
|
||||
memory = fp->Memory;
|
||||
} else {
|
||||
Mode = mode; // Restore saved Mode
|
||||
return MakeNewDoc(g);
|
||||
} // endif fp
|
||||
|
||||
} // 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)
|
||||
return MakeNewDoc(g);
|
||||
|
||||
} // 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);
|
||||
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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 ---------------- */
|
||||
|
||||
|
@@ -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 ---------------------------- */
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user