|
|
|
@ -163,8 +163,11 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) |
|
|
|
return NULL; |
|
|
|
|
|
|
|
tdp->Tabname = tab; |
|
|
|
tdp->Tabname = (char*)GetStringTableOption(g, topt, "Tabname", tab); |
|
|
|
tdp->Rowname = (char*)GetStringTableOption(g, topt, "Rownode", NULL); |
|
|
|
tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false); |
|
|
|
tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL); |
|
|
|
tdp->Skip = GetBooleanTableOption(g, topt, "Skipnull", false); |
|
|
|
|
|
|
|
if (!(op = GetStringTableOption(g, topt, "Xmlsup", NULL))) |
|
|
|
#if defined(__WIN__)
|
|
|
|
@ -280,7 +283,9 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) |
|
|
|
if (!vp->atp) |
|
|
|
node = vp->nl->GetItem(g, vp->k++, tdp->Usedom ? node : NULL); |
|
|
|
|
|
|
|
strncat(fmt, colname, XLEN(fmt)); |
|
|
|
if (!j) |
|
|
|
strncat(fmt, colname, XLEN(fmt)); |
|
|
|
|
|
|
|
strncat(fmt, "/", XLEN(fmt)); |
|
|
|
strncat(xcol->Name, "_", XLEN(xcol->Name)); |
|
|
|
j++; |
|
|
|
@ -302,6 +307,7 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) |
|
|
|
case RC_INFO: |
|
|
|
PushWarning(g, txmp); |
|
|
|
case RC_OK: |
|
|
|
xcol->Cbn = !strlen(buf); |
|
|
|
break; |
|
|
|
default: |
|
|
|
goto err; |
|
|
|
@ -327,9 +333,9 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) |
|
|
|
|
|
|
|
xcp->Len = MY_MAX(xcp->Len, xcol->Len); |
|
|
|
xcp->Scale = MY_MAX(xcp->Scale, xcol->Scale); |
|
|
|
xcp->Cbn |= xcol->Cbn; |
|
|
|
xcp->Cbn |= (xcol->Cbn || !xcol->Len); |
|
|
|
xcp->Found = true; |
|
|
|
} else { |
|
|
|
} else if(xcol->Len || !tdp->Skip) { |
|
|
|
// New column
|
|
|
|
xcp = new(g) XMCOL(g, xcol, fmt, i); |
|
|
|
length[0] = MY_MAX(length[0], strlen(xcol->Name)); |
|
|
|
@ -344,7 +350,8 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) |
|
|
|
n++; |
|
|
|
} // endif xcp
|
|
|
|
|
|
|
|
pxcp = xcp; |
|
|
|
if (xcp) |
|
|
|
pxcp = xcp; |
|
|
|
|
|
|
|
if (vp->atp) |
|
|
|
vp->atp = vp->atp->GetNext(g); |
|
|
|
@ -445,6 +452,7 @@ XMLDEF::XMLDEF(void) |
|
|
|
Usedom = false; |
|
|
|
Zipped = false; |
|
|
|
Mulentries = false; |
|
|
|
Skip = false; |
|
|
|
} // end of XMLDEF constructor
|
|
|
|
|
|
|
|
/***********************************************************************/ |
|
|
|
@ -814,127 +822,141 @@ bool TDBXML::Initialize(PGLOBAL g) |
|
|
|
} // endif Bufdone
|
|
|
|
|
|
|
|
#if !defined(UNIX)
|
|
|
|
if (!Root) try { |
|
|
|
if (!Root) try { |
|
|
|
#else
|
|
|
|
if (!Root) { |
|
|
|
if (!Root) { |
|
|
|
#endif
|
|
|
|
char tabpath[64], filename[_MAX_PATH]; |
|
|
|
|
|
|
|
// We used the file name relative to recorded datapath
|
|
|
|
PlugSetPath(filename, Xfile, GetPath()); |
|
|
|
|
|
|
|
// Load or re-use the table file
|
|
|
|
rc = LoadTableFile(g, filename); |
|
|
|
|
|
|
|
if (rc == RC_OK) { |
|
|
|
// Get root node
|
|
|
|
if (!(Root = Docp->GetRoot(g))) { |
|
|
|
// This should never happen as load should have failed
|
|
|
|
strcpy(g->Message, MSG(EMPTY_DOC)); |
|
|
|
goto error; |
|
|
|
} // endif Root
|
|
|
|
|
|
|
|
// If tabname is not an Xpath,
|
|
|
|
// construct one that will find it anywhere
|
|
|
|
if (!strchr(Tabname, '/')) |
|
|
|
strcat(strcpy(tabpath, "//"), Tabname); |
|
|
|
else |
|
|
|
strcpy(tabpath, Tabname); |
|
|
|
|
|
|
|
// Evaluate table xpath
|
|
|
|
if ((TabNode = Root->SelectSingleNode(g, tabpath))) { |
|
|
|
if (TabNode->GetType() != XML_ELEMENT_NODE) { |
|
|
|
sprintf(g->Message, MSG(BAD_NODE_TYPE), TabNode->GetType()); |
|
|
|
goto error; |
|
|
|
} // endif Type
|
|
|
|
|
|
|
|
} else if (Mode == MODE_INSERT && XmlDB) { |
|
|
|
// We are adding a new table to a multi-table file
|
|
|
|
|
|
|
|
// If XmlDB is not an Xpath,
|
|
|
|
// construct one that will find it anywhere
|
|
|
|
if (!strchr(XmlDB, '/')) |
|
|
|
strcat(strcpy(tabpath, "//"), XmlDB); |
|
|
|
else |
|
|
|
strcpy(tabpath, XmlDB); |
|
|
|
|
|
|
|
if (!(DBnode = Root->SelectSingleNode(g, tabpath))) { |
|
|
|
// DB node does not exist yet; we cannot create it
|
|
|
|
// because we don't know where it should be placed
|
|
|
|
sprintf(g->Message, MSG(MISSING_NODE), XmlDB, Xfile); |
|
|
|
goto error; |
|
|
|
} // endif DBnode
|
|
|
|
|
|
|
|
if (!(TabNode = DBnode->AddChildNode(g, Tabname))) { |
|
|
|
sprintf(g->Message, MSG(FAIL_ADD_NODE), Tabname); |
|
|
|
goto error; |
|
|
|
} // endif TabNode
|
|
|
|
|
|
|
|
DBnode->AddText(g, "\n"); |
|
|
|
} else |
|
|
|
TabNode = Root; // Try this ?
|
|
|
|
|
|
|
|
} else if (rc == RC_NF || rc == RC_EF) { |
|
|
|
// The XML file does not exist or is void
|
|
|
|
if (Mode == MODE_INSERT) { |
|
|
|
// New Document
|
|
|
|
char buf[64]; |
|
|
|
|
|
|
|
// Create the XML node
|
|
|
|
if (Docp->NewDoc(g, "1.0")) { |
|
|
|
strcpy(g->Message, MSG(NEW_DOC_FAILED)); |
|
|
|
goto error; |
|
|
|
} // endif NewDoc
|
|
|
|
|
|
|
|
// Now we can link the Xblock
|
|
|
|
To_Xb = Docp->LinkXblock(g, Mode, rc, filename); |
|
|
|
|
|
|
|
// Add a CONNECT comment node
|
|
|
|
strcpy(buf, " Created by the MariaDB CONNECT Storage Engine"); |
|
|
|
Docp->AddComment(g, buf); |
|
|
|
|
|
|
|
if (XmlDB) { |
|
|
|
// This is a multi-table file
|
|
|
|
DBnode = Root = Docp->NewRoot(g, XmlDB); |
|
|
|
DBnode->AddText(g, "\n"); |
|
|
|
TabNode = DBnode->AddChildNode(g, Tabname); |
|
|
|
DBnode->AddText(g, "\n"); |
|
|
|
} else |
|
|
|
TabNode = Root = Docp->NewRoot(g, Tabname); |
|
|
|
|
|
|
|
if (TabNode == NULL || Root == NULL) { |
|
|
|
strcpy(g->Message, MSG(XML_INIT_ERROR)); |
|
|
|
goto error; |
|
|
|
} else if (SetTabNode(g)) |
|
|
|
goto error; |
|
|
|
|
|
|
|
} else { |
|
|
|
sprintf(g->Message, MSG(FILE_UNFOUND), Xfile); |
|
|
|
|
|
|
|
if (Mode == MODE_READ) { |
|
|
|
PushWarning(g, this); |
|
|
|
Void = true; |
|
|
|
} // endif Mode
|
|
|
|
|
|
|
|
goto error; |
|
|
|
} // endif Mode
|
|
|
|
|
|
|
|
} else if (rc == RC_INFO) { |
|
|
|
// Loading failed
|
|
|
|
sprintf(g->Message, MSG(LOADING_FAILED), Xfile); |
|
|
|
goto error; |
|
|
|
} else // (rc == RC_FX)
|
|
|
|
goto error; |
|
|
|
|
|
|
|
// Get row node list
|
|
|
|
if (Rowname) |
|
|
|
Nlist = TabNode->SelectNodes(g, Rowname); |
|
|
|
else |
|
|
|
Nlist = TabNode->GetChildElements(g); |
|
|
|
|
|
|
|
Docp->SetNofree(true); // For libxml2
|
|
|
|
char tabpath[64], filename[_MAX_PATH]; |
|
|
|
|
|
|
|
// We used the file name relative to recorded datapath
|
|
|
|
PlugSetPath(filename, Xfile, GetPath()); |
|
|
|
|
|
|
|
// Load or re-use the table file
|
|
|
|
rc = LoadTableFile(g, filename); |
|
|
|
|
|
|
|
if (rc == RC_OK) { |
|
|
|
// Get root node
|
|
|
|
if (!(Root = Docp->GetRoot(g))) { |
|
|
|
// This should never happen as load should have failed
|
|
|
|
strcpy(g->Message, MSG(EMPTY_DOC)); |
|
|
|
goto error; |
|
|
|
} // endif Root
|
|
|
|
|
|
|
|
// If tabname is not an Xpath,
|
|
|
|
// construct one that will find it anywhere
|
|
|
|
if (!strchr(Tabname, '/')) |
|
|
|
strcat(strcpy(tabpath, "//"), Tabname); |
|
|
|
else |
|
|
|
strcpy(tabpath, Tabname); |
|
|
|
|
|
|
|
// Evaluate table xpath
|
|
|
|
if ((TabNode = Root->SelectSingleNode(g, tabpath))) { |
|
|
|
if (TabNode->GetType() != XML_ELEMENT_NODE) { |
|
|
|
sprintf(g->Message, MSG(BAD_NODE_TYPE), TabNode->GetType()); |
|
|
|
goto error; |
|
|
|
} // endif Type
|
|
|
|
|
|
|
|
} else if (Mode == MODE_INSERT && XmlDB) { |
|
|
|
// We are adding a new table to a multi-table file
|
|
|
|
|
|
|
|
// If XmlDB is not an Xpath,
|
|
|
|
// construct one that will find it anywhere
|
|
|
|
if (!strchr(XmlDB, '/')) |
|
|
|
strcat(strcpy(tabpath, "//"), XmlDB); |
|
|
|
else |
|
|
|
strcpy(tabpath, XmlDB); |
|
|
|
|
|
|
|
if (!(DBnode = Root->SelectSingleNode(g, tabpath))) { |
|
|
|
// DB node does not exist yet; we cannot create it
|
|
|
|
// because we don't know where it should be placed
|
|
|
|
sprintf(g->Message, MSG(MISSING_NODE), XmlDB, Xfile); |
|
|
|
goto error; |
|
|
|
} // endif DBnode
|
|
|
|
|
|
|
|
if (!(TabNode = DBnode->AddChildNode(g, Tabname))) { |
|
|
|
sprintf(g->Message, MSG(FAIL_ADD_NODE), Tabname); |
|
|
|
goto error; |
|
|
|
} // endif TabNode
|
|
|
|
|
|
|
|
DBnode->AddText(g, "\n"); |
|
|
|
} else { |
|
|
|
TabNode = Root; // Try this ?
|
|
|
|
Tabname = TabNode->GetName(g); |
|
|
|
} // endif's
|
|
|
|
|
|
|
|
} else if (rc == RC_NF || rc == RC_EF) { |
|
|
|
// The XML file does not exist or is void
|
|
|
|
if (Mode == MODE_INSERT) { |
|
|
|
// New Document
|
|
|
|
char buf[64]; |
|
|
|
|
|
|
|
// Create the XML node
|
|
|
|
if (Docp->NewDoc(g, "1.0")) { |
|
|
|
strcpy(g->Message, MSG(NEW_DOC_FAILED)); |
|
|
|
goto error; |
|
|
|
} // endif NewDoc
|
|
|
|
|
|
|
|
// Now we can link the Xblock
|
|
|
|
To_Xb = Docp->LinkXblock(g, Mode, rc, filename); |
|
|
|
|
|
|
|
// Add a CONNECT comment node
|
|
|
|
strcpy(buf, " Created by the MariaDB CONNECT Storage Engine"); |
|
|
|
Docp->AddComment(g, buf); |
|
|
|
|
|
|
|
if (XmlDB) { |
|
|
|
// This is a multi-table file
|
|
|
|
DBnode = Root = Docp->NewRoot(g, XmlDB); |
|
|
|
DBnode->AddText(g, "\n"); |
|
|
|
TabNode = DBnode->AddChildNode(g, Tabname); |
|
|
|
DBnode->AddText(g, "\n"); |
|
|
|
} else |
|
|
|
TabNode = Root = Docp->NewRoot(g, Tabname); |
|
|
|
|
|
|
|
if (TabNode == NULL || Root == NULL) { |
|
|
|
strcpy(g->Message, MSG(XML_INIT_ERROR)); |
|
|
|
goto error; |
|
|
|
} else if (SetTabNode(g)) |
|
|
|
goto error; |
|
|
|
|
|
|
|
} else { |
|
|
|
sprintf(g->Message, MSG(FILE_UNFOUND), Xfile); |
|
|
|
|
|
|
|
if (Mode == MODE_READ) { |
|
|
|
PushWarning(g, this); |
|
|
|
Void = true; |
|
|
|
} // endif Mode
|
|
|
|
|
|
|
|
goto error; |
|
|
|
} // endif Mode
|
|
|
|
|
|
|
|
} else if (rc == RC_INFO) { |
|
|
|
// Loading failed
|
|
|
|
sprintf(g->Message, MSG(LOADING_FAILED), Xfile); |
|
|
|
goto error; |
|
|
|
} else // (rc == RC_FX)
|
|
|
|
goto error; |
|
|
|
|
|
|
|
if (!Rowname) { |
|
|
|
for (PXNODE n = TabNode->GetChild(g); n; n = n->GetNext(g)) |
|
|
|
if (n->GetType() == XML_ELEMENT_NODE) { |
|
|
|
Rowname = n->GetName(g); |
|
|
|
break; |
|
|
|
} // endif Type
|
|
|
|
|
|
|
|
if (!Rowname) |
|
|
|
Rowname = TabNode->GetName(g); |
|
|
|
} // endif Rowname
|
|
|
|
|
|
|
|
// Get row node list
|
|
|
|
if (strcmp(Rowname, Tabname)) |
|
|
|
Nlist = TabNode->SelectNodes(g, Rowname); |
|
|
|
else |
|
|
|
Nrow = 1; |
|
|
|
|
|
|
|
|
|
|
|
Docp->SetNofree(true); // For libxml2
|
|
|
|
#if defined(__WIN__)
|
|
|
|
} catch(_com_error e) { |
|
|
|
} catch (_com_error e) { |
|
|
|
// We come here if a DOM command threw an error
|
|
|
|
char buf[128]; |
|
|
|
|
|
|
|
@ -1221,10 +1243,14 @@ int TDBXML::ReadDB(PGLOBAL g) |
|
|
|
htrc("TDBXML ReadDB: Irow=%d RowNode=%p\n", Irow, RowNode); |
|
|
|
|
|
|
|
// Get the new row node
|
|
|
|
if ((RowNode = Nlist->GetItem(g, Irow, RowNode)) == NULL) { |
|
|
|
sprintf(g->Message, MSG(MISSING_ROWNODE), Irow); |
|
|
|
return RC_FX; |
|
|
|
} // endif RowNode
|
|
|
|
if (Nlist) { |
|
|
|
if ((RowNode = Nlist->GetItem(g, Irow, RowNode)) == NULL) { |
|
|
|
sprintf(g->Message, MSG(MISSING_ROWNODE), Irow); |
|
|
|
return RC_FX; |
|
|
|
} // endif RowNode
|
|
|
|
|
|
|
|
} else |
|
|
|
RowNode = TabNode; |
|
|
|
|
|
|
|
if (Colname && Coltype == 2) |
|
|
|
Clist = RowNode->SelectNodes(g, Colname, Clist); |
|
|
|
@ -1279,6 +1305,7 @@ int TDBXML::WriteDB(PGLOBAL g) |
|
|
|
/***********************************************************************/ |
|
|
|
int TDBXML::DeleteDB(PGLOBAL g, int irc) |
|
|
|
{ |
|
|
|
// TODO: Handle null Nlist
|
|
|
|
if (irc == RC_FX) { |
|
|
|
// Delete all rows
|
|
|
|
for (Irow = 0; Irow < Nrow; Irow++) |
|
|
|
|