summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2016-12-23 14:23:46 +0100
committerOlivier Bertrand <bertrandop@gmail.com>2016-12-23 14:23:46 +0100
commit5c0c623577c7d1fe183bb8903d26eaf52a89b88b (patch)
tree34541e487d14ebad413edb47049e967890e34f1e
parentb3d2ac3492c50ffab716e626d745727162a28343 (diff)
downloadmariadb-git-5c0c623577c7d1fe183bb8903d26eaf52a89b88b.tar.gz
Fix some XML table type bugs:
- in DOMNODELIST::DropItem if (Listp == NULL || Listp->length <= n) return true; is wrong, should be: if (Listp == NULL || Listp->length < n) return true; - Crash in discovery with libxml2 in XMLColumns because: if (!tdp->Usedom) // nl was destroyed vp->nl = vp->pn->GetChildElements(g); is executed with vp->pn uninitialized. Fixed by adding: vp->pn = node; line 264. -In discovery with libxml2 some columns are not found. Because list was not recovered properly, nodes being modified and not reallocated. Fixed lines 214 and 277. modified: storage/connect/domdoc.cpp modified: storage/connect/tabxml.cpp Add support for zipped table files modified: storage/connect/domdoc.cpp modified: storage/connect/domdoc.h modified: storage/connect/filamap.cpp modified: storage/connect/filamap.h modified: storage/connect/filamzip.cpp modified: storage/connect/filamzip.h modified: storage/connect/ha_connect.cc modified: storage/connect/libdoc.cpp modified: storage/connect/plgdbutl.cpp modified: storage/connect/plgxml.cpp modified: storage/connect/plgxml.h modified: storage/connect/tabdos.cpp modified: storage/connect/tabdos.h modified: storage/connect/tabfmt.cpp modified: storage/connect/tabjson.cpp modified: storage/connect/tabxml.cpp
-rw-r--r--storage/connect/domdoc.cpp40
-rw-r--r--storage/connect/domdoc.h4
-rw-r--r--storage/connect/filamap.cpp49
-rw-r--r--storage/connect/filamap.h3
-rw-r--r--storage/connect/filamzip.cpp426
-rw-r--r--storage/connect/filamzip.h86
-rw-r--r--storage/connect/ha_connect.cc6
-rw-r--r--storage/connect/libdoc.cpp30
-rw-r--r--storage/connect/plgdbutl.cpp2
-rw-r--r--storage/connect/plgxml.cpp55
-rw-r--r--storage/connect/plgxml.h16
-rw-r--r--storage/connect/tabdos.cpp34
-rw-r--r--storage/connect/tabdos.h13
-rw-r--r--storage/connect/tabfmt.cpp11
-rw-r--r--storage/connect/tabjson.cpp33
-rw-r--r--storage/connect/tabxml.cpp56
-rw-r--r--storage/connect/tabxml.h18
17 files changed, 604 insertions, 278 deletions
diff --git a/storage/connect/domdoc.cpp b/storage/connect/domdoc.cpp
index 64a0a172956..eb9660b439d 100644
--- a/storage/connect/domdoc.cpp
+++ b/storage/connect/domdoc.cpp
@@ -89,30 +89,43 @@ DOMDOC::DOMDOC(char *nsl, char *nsdf, char *enc, PFBLOCK fp)
/******************************************************************/
/* Initialize XML parser and check library compatibility. */
/******************************************************************/
-bool DOMDOC::Initialize(PGLOBAL g)
- {
- if (TestHr(g, CoInitialize(NULL)))
+bool DOMDOC::Initialize(PGLOBAL g, char *entry, bool zipped)
+{
+ if (zipped && InitZip(g, entry))
+ return true;
+
+ if (TestHr(g, CoInitialize(NULL)))
return true;
if (TestHr(g, Docp.CreateInstance("msxml2.domdocument")))
return true;
return MakeNSlist(g);
- } // end of Initialize
+} // end of Initialize
/******************************************************************/
/* Parse the XML file and construct node tree in memory. */
/******************************************************************/
-bool DOMDOC::ParseFile(char *fn)
- {
- // Load the document
+bool DOMDOC::ParseFile(PGLOBAL g, char *fn)
+{
+ bool b;
+
Docp->async = false;
- if (!(bool)Docp->load((_bstr_t)fn))
+ if (zip) {
+ // Parse an in memory document
+ char *xdoc = GetMemDoc(g, fn);
+
+ b = (xdoc) ? (bool)Docp->loadXML((_bstr_t)xdoc) : false;
+ } else
+ // Load the document
+ b = (bool)Docp->load((_bstr_t)fn);
+
+ if (!b)
return true;
return false;
- } // end of ParseFile
+} // end of ParseFile
/******************************************************************/
/* Create or reuse an Xblock for this document. */
@@ -239,6 +252,7 @@ int DOMDOC::DumpDoc(PGLOBAL g, char *ofn)
void DOMDOC::CloseDoc(PGLOBAL g, PFBLOCK xp)
{
CloseXMLFile(g, xp, false);
+ CloseZip();
} // end of Close
/* ----------------------- class DOMNODE ------------------------ */
@@ -616,13 +630,13 @@ PXNODE DOMNODELIST::GetItem(PGLOBAL g, int n, PXNODE np)
/* Reset the pointer on the deleted item. */
/******************************************************************/
bool DOMNODELIST::DropItem(PGLOBAL g, int n)
- {
- if (Listp == NULL || Listp->length <= n)
- return true;
+{
+ if (Listp == NULL || Listp->length < n)
+ return true;
//Listp->item[n] = NULL; La propriété n'a pas de méthode 'set'
return false;
- } // end of DeleteItem
+} // end of DeleteItem
/* ----------------------- class DOMATTR ------------------------ */
diff --git a/storage/connect/domdoc.h b/storage/connect/domdoc.h
index 2cffec499e2..cfec98a9422 100644
--- a/storage/connect/domdoc.h
+++ b/storage/connect/domdoc.h
@@ -37,8 +37,8 @@ class DOMDOC : public XMLDOCUMENT {
virtual void SetNofree(bool b) {} // Only libxml2
// Methods
- virtual bool Initialize(PGLOBAL g);
- virtual bool ParseFile(char *fn);
+ virtual bool Initialize(PGLOBAL g, char *entry, bool zipped);
+ virtual bool ParseFile(PGLOBAL g, char *fn);
virtual bool NewDoc(PGLOBAL g, char *ver);
virtual void AddComment(PGLOBAL g, char *com);
virtual PXNODE GetRoot(PGLOBAL g);
diff --git a/storage/connect/filamap.cpp b/storage/connect/filamap.cpp
index 3c5b3ae7592..94c562a9981 100644
--- a/storage/connect/filamap.cpp
+++ b/storage/connect/filamap.cpp
@@ -319,11 +319,13 @@ int MAPFAM::SkipRecord(PGLOBAL g, bool header)
/***********************************************************************/
int MAPFAM::ReadBuffer(PGLOBAL g)
{
- int len;
+ int rc, len;
// Are we at the end of the memory
- if (Mempos >= Top)
- return RC_EF;
+ if (Mempos >= Top)
+ if ((rc = GetNext(g)) != RC_OK)
+ return rc;
+
if (!Placed) {
/*******************************************************************/
@@ -341,8 +343,10 @@ int MAPFAM::ReadBuffer(PGLOBAL g)
/*******************************************************************/
switch (Tdbp->TestBlock(g)) {
case RC_EF:
- return RC_EF;
- case RC_NF:
+ if ((rc = GetNext(g)) != RC_OK)
+ return rc;
+
+ case RC_NF:
// Skip this record
if ((rc = SkipRecord(g, false)) != RC_OK)
return rc;
@@ -569,7 +573,7 @@ int MBKFAM::GetRowID(void)
/***********************************************************************/
int MBKFAM::ReadBuffer(PGLOBAL g)
{
- int len;
+ int rc, len;
/*********************************************************************/
/* Sequential block reading when Placed is not true. */
@@ -577,8 +581,10 @@ int MBKFAM::ReadBuffer(PGLOBAL g)
if (Placed) {
Placed = false;
} else if (Mempos >= Top) { // Are we at the end of the memory
- return RC_EF;
- } else if (++CurNum < Nrec) {
+ if ((rc = GetNext(g)) != RC_OK)
+ return rc;
+
+ } else if (++CurNum < Nrec) {
Fpos = Mempos;
} else {
/*******************************************************************/
@@ -588,7 +594,8 @@ int MBKFAM::ReadBuffer(PGLOBAL g)
next:
if (++CurBlk >= Block)
- return RC_EF;
+ if ((rc = GetNext(g)) != RC_OK)
+ return rc;
/*******************************************************************/
/* Before reading a new block, check whether block optimization */
@@ -596,8 +603,11 @@ int MBKFAM::ReadBuffer(PGLOBAL g)
/*******************************************************************/
switch (Tdbp->TestBlock(g)) {
case RC_EF:
- return RC_EF;
- case RC_NF:
+ if ((rc = GetNext(g)) != RC_OK)
+ return rc;
+
+ break;
+ case RC_NF:
goto next;
} // endswitch rc
@@ -697,14 +707,18 @@ int MPXFAM::InitDelete(PGLOBAL, int fpos, int)
/***********************************************************************/
int MPXFAM::ReadBuffer(PGLOBAL g)
{
+ int rc;
+
/*********************************************************************/
/* Sequential block reading when Placed is not true. */
/*********************************************************************/
if (Placed) {
Placed = false;
} else if (Mempos >= Top) { // Are we at the end of the memory
- return RC_EF;
- } else if (++CurNum < Nrec) {
+ if ((rc = GetNext(g)) != RC_OK)
+ return rc;
+
+ } else if (++CurNum < Nrec) {
Fpos = Mempos;
} else {
/*******************************************************************/
@@ -714,7 +728,7 @@ int MPXFAM::ReadBuffer(PGLOBAL g)
next:
if (++CurBlk >= Block)
- return RC_EF;
+ return GetNext(g);
/*******************************************************************/
/* Before reading a new block, check whether block optimization */
@@ -722,8 +736,11 @@ int MPXFAM::ReadBuffer(PGLOBAL g)
/*******************************************************************/
switch (Tdbp->TestBlock(g)) {
case RC_EF:
- return RC_EF;
- case RC_NF:
+ if ((rc = GetNext(g)) != RC_OK)
+ return rc;
+
+ break;
+ case RC_NF:
goto next;
} // endswitch rc
diff --git a/storage/connect/filamap.h b/storage/connect/filamap.h
index b9c8ad965fd..774eb8b91b3 100644
--- a/storage/connect/filamap.h
+++ b/storage/connect/filamap.h
@@ -41,7 +41,8 @@ class DllExport MAPFAM : public TXTFAM {
virtual int SkipRecord(PGLOBAL g, bool header);
virtual bool OpenTableFile(PGLOBAL g);
virtual bool DeferReading(void) {return false;}
- virtual int ReadBuffer(PGLOBAL g);
+ virtual int GetNext(PGLOBAL g) {return RC_EF;}
+ virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g, bool abort);
diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp
index 8386e5be481..65013e170e4 100644
--- a/storage/connect/filamzip.cpp
+++ b/storage/connect/filamzip.cpp
@@ -40,19 +40,21 @@
//#include "tabzip.h"
#include "filamzip.h"
-/* -------------------------- class ZIPFAM --------------------------- */
+/* -------------------------- class ZIPUTIL -------------------------- */
/***********************************************************************/
/* Constructors. */
/***********************************************************************/
-ZIPFAM::ZIPFAM(PDOSDEF tdp) : MAPFAM(tdp)
+ZIPUTIL::ZIPUTIL(PSZ tgt, bool mul)
{
zipfile = NULL;
-//zfn = tdp->Fn;
- target = tdp->Entry;
-//*fn = 0;
+ target = tgt;
+ fp = NULL;
+ memory = NULL;
+ size = 0;
entryopen = false;
- multiple = (target && !(strchr(target, '*') || strchr(target, '?'))) ? 0 : 1;
+ multiple = mul;
+ memset(fn, 0, sizeof(fn));
// Init the case mapping table.
#if defined(__WIN__)
@@ -60,29 +62,30 @@ ZIPFAM::ZIPFAM(PDOSDEF tdp) : MAPFAM(tdp)
#else
for (int i = 0; i < 256; ++i) mapCaseTable[i] = i;
#endif
-} // end of ZIPFAM standard constructor
+} // end of ZIPUTIL standard constructor
-ZIPFAM::ZIPFAM(PZIPFAM txfp) : MAPFAM(txfp)
+#if 0
+ZIPUTIL::ZIPUTIL(PZIPUTIL zutp)
{
- zipfile = txfp->zipfile;
-//zfn = txfp->zfn;
- target = txfp->target;
-//strcpy(fn, txfp->fn);
- finfo = txfp->finfo;
- entryopen = txfp->entryopen;
- multiple = txfp->multiple;
- for (int i = 0; i < 256; ++i) mapCaseTable[i] = txfp->mapCaseTable[i];
-} // end of ZIPFAM copy constructor
+ zipfile = zutp->zipfile;
+ target = zutp->target;
+ fp = zutp->fp;
+ finfo = zutp->finfo;
+ entryopen = zutp->entryopen;
+ multiple = zutp->multiple;
+ for (int i = 0; i < 256; ++i) mapCaseTable[i] = zutp->mapCaseTable[i];
+} // end of ZIPUTIL copy constructor
+#endif // 0
/***********************************************************************/
/* This code is the copyright property of Alessandro Felice Cantatore. */
/* http://xoomer.virgilio.it/acantato/dev/wildcard/wildmatch.html */
/***********************************************************************/
-bool ZIPFAM::WildMatch(PSZ pat, PSZ str) {
+bool ZIPUTIL::WildMatch(PSZ pat, PSZ str) {
PSZ s, p;
bool star = FALSE;
- loopStart:
+loopStart:
for (s = str, p = pat; *s; ++s, ++p) {
switch (*p) {
case '?':
@@ -102,31 +105,18 @@ bool ZIPFAM::WildMatch(PSZ pat, PSZ str) {
if (*p == '*') ++p;
return (!*p);
- starCheck:
+starCheck:
if (!star) return FALSE;
str++;
goto loopStart;
} // end of WildMatch
/***********************************************************************/
-/* ZIP GetFileLength: returns file size in number of bytes. */
-/***********************************************************************/
-int ZIPFAM::GetFileLength(PGLOBAL g)
-{
- int len = (entryopen) ? Top - Memory : 100; // not 0 to avoid ASSERT
-
- if (trace)
- htrc("Zipped file length=%d\n", len);
-
- return len;
-} // end of GetFileLength
-
-/***********************************************************************/
/* open a zip file. */
/* param: filename path and the filename of the zip file to open. */
/* return: true if open, false otherwise. */
/***********************************************************************/
-bool ZIPFAM::open(PGLOBAL g, const char *filename)
+bool ZIPUTIL::open(PGLOBAL g, char *filename)
{
if (!zipfile && !(zipfile = unzOpen64(filename)))
sprintf(g->Message, "Zipfile open error on %s", filename);
@@ -137,7 +127,7 @@ bool ZIPFAM::open(PGLOBAL g, const char *filename)
/***********************************************************************/
/* Close the zip file. */
/***********************************************************************/
-void ZIPFAM::close()
+void ZIPUTIL::close()
{
if (zipfile) {
closeEntry();
@@ -150,10 +140,9 @@ void ZIPFAM::close()
/***********************************************************************/
/* Find next entry matching target pattern. */
/***********************************************************************/
-int ZIPFAM::findEntry(PGLOBAL g, bool next)
+int ZIPUTIL::findEntry(PGLOBAL g, bool next)
{
int rc;
- char fn[FILENAME_MAX]; // The current entry file name
do {
if (next) {
@@ -188,37 +177,53 @@ int ZIPFAM::findEntry(PGLOBAL g, bool next)
strcpy(g->Message, "FindNext logical error");
return RC_FX;
-} // end of FindNext
+} // end of FindEntry
+
/***********************************************************************/
-/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
+/* Get the next used entry. */
/***********************************************************************/
-bool ZIPFAM::OpenTableFile(PGLOBAL g)
+int ZIPUTIL::nextEntry(PGLOBAL g)
{
- char filename[_MAX_PATH];
- MODE mode = Tdbp->GetMode();
- PFBLOCK fp;
- PDBUSER dbuserp = (PDBUSER)g->Activityp->Aptr;
+ if (multiple) {
+ int rc;
+
+ closeEntry();
+
+ if ((rc = findEntry(g, true)) != RC_OK)
+ return rc;
+
+ if (openEntry(g))
+ return RC_FX;
+ return RC_OK;
+ } else
+ return RC_EF;
+
+} // end of nextEntry
+
+
+/***********************************************************************/
+/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
+/***********************************************************************/
+bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, char *fn)
+{
/*********************************************************************/
/* The file will be decompressed into virtual memory. */
/*********************************************************************/
- if (mode == MODE_READ) {
- // We used the file name relative to recorded datapath
- PlugSetPath(filename, To_File, Tdbp->GetPath());
-
- bool b = open(g, filename);
+ if (mode == MODE_READ || mode == MODE_ANY) {
+ bool b = open(g, fn);
if (!b) {
int rc;
-
+
if (target && *target) {
if (!multiple) {
rc = unzLocateFile(zipfile, target, 0);
if (rc == UNZ_END_OF_LIST_OF_FILE) {
- sprintf(g->Message, "Target file %s not in %s", target, filename);
- return false;
+ sprintf(g->Message, "Target file %s not in %s", target, fn);
+ return true;
} else if (rc != UNZ_OK) {
sprintf(g->Message, "unzLocateFile rc=%d", rc);
return true;
@@ -227,9 +232,9 @@ bool ZIPFAM::OpenTableFile(PGLOBAL g)
} else {
if ((rc = findEntry(g, false)) == RC_FX)
return true;
- else if (rc == RC_NF) {
- sprintf(g->Message, "No match of %s in %s", target, filename);
- return false;
+ else if (rc == RC_EF) {
+ sprintf(g->Message, "No match of %s in %s", target, fn);
+ return true;
} // endif rc
} // endif multiple
@@ -239,25 +244,26 @@ bool ZIPFAM::OpenTableFile(PGLOBAL g)
if (openEntry(g))
return true;
- if (Top > Memory) {
+ if (size > 0) {
/*******************************************************************/
/* Link a Fblock. This make possible to automatically close it */
/* in case of error g->jump. */
/*******************************************************************/
+ PDBUSER dbuserp = (PDBUSER)g->Activityp->Aptr;
+
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
fp->Type = TYPE_FB_ZIP;
- fp->Fname = PlugDup(g, filename);
+ fp->Fname = PlugDup(g, fn);
fp->Next = dbuserp->Openlist;
dbuserp->Openlist = fp;
fp->Count = 1;
- fp->Length = Top - Memory;
- fp->Memory = Memory;
+ fp->Length = size;
+ fp->Memory = memory;
fp->Mode = mode;
fp->File = this;
fp->Handle = NULL;
} // endif fp
- To_Fb = fp; // Useful when closing
} else
return true;
@@ -267,65 +273,161 @@ bool ZIPFAM::OpenTableFile(PGLOBAL g)
} // endif mode
return false;
- } // end of OpenTableFile
+} // end of OpenTableFile
/***********************************************************************/
/* Open target in zip file. */
/***********************************************************************/
-bool ZIPFAM::openEntry(PGLOBAL g)
+bool ZIPUTIL::openEntry(PGLOBAL g)
{
- int rc;
- uint size;
+ int rc;
- rc = unzGetCurrentFileInfo(zipfile, &finfo, 0, 0, 0, 0, 0, 0);
+ rc = unzGetCurrentFileInfo(zipfile, &finfo, fn, sizeof(fn),
+ NULL, 0, NULL, 0);
if (rc != UNZ_OK) {
sprintf(g->Message, "unzGetCurrentFileInfo64 rc=%d", rc);
return true;
} else if ((rc = unzOpenCurrentFile(zipfile)) != UNZ_OK) {
- sprintf(g->Message, "unzOpenCurrentFile rc=%d", rc);
+ sprintf(g->Message, "unzOpen fn=%s rc=%d", fn, rc);
return true;
} // endif rc
size = finfo.uncompressed_size;
- Memory = new char[size];
+ memory = new char[size + 1];
- if ((rc = unzReadCurrentFile(zipfile, Memory, size)) < 0) {
+ if ((rc = unzReadCurrentFile(zipfile, memory, size)) < 0) {
sprintf(g->Message, "unzReadCurrentFile rc = ", rc);
unzCloseCurrentFile(zipfile);
- free(Memory);
+ free(memory);
+ memory = NULL;
entryopen = false;
} else {
- // The pseudo "buffer" is here the entire real buffer
- Fpos = Mempos = Memory;
- Top = Memory + size;
-
- if (trace)
- htrc("Memory=%p size=%ud Top=%p\n", Memory, size, Top);
-
+ memory[size] = 0; // Required by some table types (XML)
entryopen = true;
} // endif rc
+ if (trace)
+ htrc("Openning entry%s %s\n", fn, (entryopen) ? "oked" : "failed");
+
return !entryopen;
} // end of openEntry
/***********************************************************************/
/* Close the zip file. */
/***********************************************************************/
-void ZIPFAM::closeEntry()
+void ZIPUTIL::closeEntry()
{
if (entryopen) {
unzCloseCurrentFile(zipfile);
entryopen = false;
} // endif entryopen
- if (Memory) {
- free(Memory);
- Memory = NULL;
- } // endif Memory
+ if (memory) {
+ free(memory);
+ memory = NULL;
+ } // endif memory
} // end of closeEntry
+/* -------------------------- class ZIPFAM --------------------------- */
+
+/***********************************************************************/
+/* Constructors. */
+/***********************************************************************/
+ZIPFAM::ZIPFAM(PDOSDEF tdp) : MAPFAM(tdp)
+{
+ zutp = NULL;
+ target = tdp->GetEntry();
+ mul = tdp->GetMul();
+} // end of ZIPFAM standard constructor
+
+ZIPFAM::ZIPFAM(PZIPFAM txfp) : MAPFAM(txfp)
+{
+ zutp = txfp->zutp;
+ target = txfp->target;
+ mul = txfp->mul;
+} // end of ZIPFAM copy constructor
+
+ZIPFAM::ZIPFAM(PDOSDEF tdp, PZPXFAM txfp) : MAPFAM(tdp)
+{
+ zutp = txfp->zutp;
+ target = txfp->target;
+ mul = txfp->mul;
+} // end of ZIPFAM constructor used in ResetTableOpt
+
+/***********************************************************************/
+/* ZIP GetFileLength: returns file size in number of bytes. */
+/***********************************************************************/
+int ZIPFAM::GetFileLength(PGLOBAL g)
+{
+ int len = (zutp && zutp->entryopen) ? Top - Memory
+ : TXTFAM::GetFileLength(g) * 3;
+
+ if (trace)
+ htrc("Zipped file length=%d\n", len);
+
+ return len;
+} // end of GetFileLength
+
+/***********************************************************************/
+/* ZIP Cardinality: return the number of rows if possible. */
+/***********************************************************************/
+int ZIPFAM::Cardinality(PGLOBAL g)
+{
+ if (!g)
+ return 1;
+
+ int card = -1;
+ int len = GetFileLength(g);
+
+ card = (len / (int)Lrecl) * 2; // Estimated ???
+ return card;
+} // end of Cardinality
+
+/***********************************************************************/
+/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
+/***********************************************************************/
+bool ZIPFAM::OpenTableFile(PGLOBAL g)
+{
+ char filename[_MAX_PATH];
+ MODE mode = Tdbp->GetMode();
+
+ /*********************************************************************/
+ /* Allocate the ZIP utility class. */
+ /*********************************************************************/
+ zutp = new(g) ZIPUTIL(target, mul);
+
+ // We used the file name relative to recorded datapath
+ PlugSetPath(filename, To_File, Tdbp->GetPath());
+
+ if (!zutp->OpenTable(g, mode, filename)) {
+ // The pseudo "buffer" is here the entire real buffer
+ Fpos = Mempos = Memory = zutp->memory;
+ Top = Memory + zutp->size;
+ To_Fb = zutp->fp; // Useful when closing
+ } else
+ return true;
+
+ return false;
+ } // end of OpenTableFile
+
+/***********************************************************************/
+/* GetNext: go to next entry. */
+/***********************************************************************/
+int ZIPFAM::GetNext(PGLOBAL g)
+{
+ int rc = zutp->nextEntry(g);
+
+ if (rc != RC_OK)
+ return rc;
+
+ Mempos = Memory = zutp->memory;
+ Top = Memory + zutp->size;
+ return RC_OK;
+} // end of GetNext
+
+#if 0
/***********************************************************************/
/* ReadBuffer: Read one line for a ZIP file. */
/***********************************************************************/
@@ -335,19 +437,12 @@ int ZIPFAM::ReadBuffer(PGLOBAL g)
// Are we at the end of the memory
if (Mempos >= Top) {
- if (multiple) {
- closeEntry();
-
- if ((rc = findEntry(g, true)) != RC_OK)
- return rc;
-
- if (openEntry(g))
- return RC_FX;
+ if ((rc = zutp->nextEntry(g)) != RC_OK)
+ return rc;
- } else
- return RC_EF;
-
- } // endif Mempos
+ Mempos = Memory = zutp->memory;
+ Top = Memory + zutp->size;
+ } // endif Mempos
#if 0
if (!Placed) {
@@ -399,7 +494,6 @@ int ZIPFAM::ReadBuffer(PGLOBAL g)
return RC_OK;
} // end of ReadBuffer
-#if 0
/***********************************************************************/
/* Table file close routine for MAP access method. */
/***********************************************************************/
@@ -414,89 +508,115 @@ void ZIPFAM::CloseTableFile(PGLOBAL g, bool)
/***********************************************************************/
/* Constructors. */
/***********************************************************************/
-ZPXFAM::ZPXFAM(PDOSDEF tdp) : ZIPFAM(tdp)
+ZPXFAM::ZPXFAM(PDOSDEF tdp) : MPXFAM(tdp)
{
- Lrecl = tdp->GetLrecl();
+ zutp = NULL;
+ target = tdp->GetEntry();
+ mul = tdp->GetMul();
+ //Lrecl = tdp->GetLrecl();
} // end of ZPXFAM standard constructor
-ZPXFAM::ZPXFAM(PZPXFAM txfp) : ZIPFAM(txfp)
+ZPXFAM::ZPXFAM(PZPXFAM txfp) : MPXFAM(txfp)
{
- Lrecl = txfp->Lrecl;
+ zutp = txfp->zutp;
+ target = txfp->target;
+ mul = txfp->mul;
+//Lrecl = txfp->Lrecl;
} // end of ZPXFAM copy constructor
/***********************************************************************/
-/* ReadBuffer: Read one line for a fixed ZIP file. */
+/* ZIP GetFileLength: returns file size in number of bytes. */
/***********************************************************************/
-int ZPXFAM::ReadBuffer(PGLOBAL g)
+int ZPXFAM::GetFileLength(PGLOBAL g)
{
- int rc, len;
+ int len;
- // Are we at the end of the memory
- if (Mempos >= Top) {
- if (multiple) {
- closeEntry();
+ if (!zutp && OpenTableFile(g))
+ return 0;
- if ((rc = findEntry(g, true)) != RC_OK)
- return rc;
+ if (zutp->entryopen)
+ len = zutp->size;
+ else
+ len = 0;
- if (openEntry(g))
- return RC_FX;
+ return len;
+} // end of GetFileLength
- } else
- return RC_EF;
+/***********************************************************************/
+/* ZIP Cardinality: return the number of rows if possible. */
+/***********************************************************************/
+int ZPXFAM::Cardinality(PGLOBAL g)
+{
+ if (!g)
+ return 1;
- } // endif Mempos
+ int card = -1;
+ int len = GetFileLength(g);
-#if 0
- if (!Placed) {
- /*******************************************************************/
- /* Record file position in case of UPDATE or DELETE. */
- /*******************************************************************/
- int rc;
+ if (!(len % Lrecl))
+ card = len / (int)Lrecl; // Fixed length file
+ else
+ sprintf(g->Message, MSG(NOT_FIXED_LEN), zutp->fn, len, Lrecl);
- next:
- Fpos = Mempos;
- CurBlk = (int)Rows++;
+ // Set number of blocks for later use
+ Block = (card > 0) ? (card + Nrec - 1) / Nrec : 0;
+ return card;
+} // end of Cardinality
- /*******************************************************************/
- /* Check whether optimization on ROWID */
- /* can be done, as well as for join as for local filtering. */
- /*******************************************************************/
- switch (Tdbp->TestBlock(g)) {
- case RC_EF:
- return RC_EF;
- case RC_NF:
- // Skip this record
- if ((rc = SkipRecord(g, false)) != RC_OK)
- return rc;
+/***********************************************************************/
+/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
+/***********************************************************************/
+bool ZPXFAM::OpenTableFile(PGLOBAL g)
+{
+ // May have been already opened in GetFileLength
+ if (!zutp || !zutp->zipfile) {
+ char filename[_MAX_PATH];
+ MODE mode = Tdbp->GetMode();
- goto next;
- } // endswitch rc
+ /*********************************************************************/
+ /* Allocate the ZIP utility class. */
+ /*********************************************************************/
+ if (!zutp)
+ zutp = new(g)ZIPUTIL(target, mul);
+
+ // We used the file name relative to recorded datapath
+ PlugSetPath(filename, To_File, Tdbp->GetPath());
+
+ if (!zutp->OpenTable(g, mode, filename)) {
+ // The pseudo "buffer" is here the entire real buffer
+ Memory = zutp->memory;
+ Fpos = Mempos = Memory + Headlen;
+ Top = Memory + zutp->size;
+ To_Fb = zutp->fp; // Useful when closing
+ } else
+ return true;
} else
- Placed = false;
-#else
- // Perhaps unuseful
- Fpos = Mempos;
- CurBlk = (int)Rows++;
- Placed = false;
-#endif
+ Reset();
- // Immediately calculate next position (Used by DeleteDB)
- Mempos += Lrecl;
+ return false;
+} // end of OpenTableFile
- // Set caller line buffer
- len = Lrecl;
+/***********************************************************************/
+/* GetNext: go to next entry. */
+/***********************************************************************/
+int ZPXFAM::GetNext(PGLOBAL g)
+{
+ int rc = zutp->nextEntry(g);
- // Don't rely on ENDING setting
- if (len > 0 && *(Mempos - 1) == '\n')
- len--; // Line ends by LF
+ if (rc != RC_OK)
+ return rc;
- if (len > 0 && *(Mempos - 2) == '\r')
- len--; // Line ends by CRLF
+ int len = zutp->size;
- memcpy(Tdbp->GetLine(), Fpos, len);
- Tdbp->GetLine()[len] = '\0';
+ if (len % Lrecl) {
+ sprintf(g->Message, MSG(NOT_FIXED_LEN), zutp->fn, len, Lrecl);
+ return RC_FX;
+ } // endif size
+
+ Memory = zutp->memory;
+ Top = Memory + len;
+ Rewind();
return RC_OK;
-} // end of ReadBuffer
+} // end of GetNext
diff --git a/storage/connect/filamzip.h b/storage/connect/filamzip.h
index c3c04b2b3bb..9312fb2f70e 100644
--- a/storage/connect/filamzip.h
+++ b/storage/connect/filamzip.h
@@ -18,66 +18,100 @@ typedef class ZIPFAM *PZIPFAM;
typedef class ZPXFAM *PZPXFAM;
/***********************************************************************/
+/* This is the ZIP utility fonctions class. */
+/***********************************************************************/
+class DllExport ZIPUTIL : public BLOCK {
+public:
+ // Constructor
+ ZIPUTIL(PSZ tgt, bool mul);
+//ZIPUTIL(ZIPUTIL *zutp);
+
+ // Implementation
+//PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)ZIPFAM(this); }
+
+ // Methods
+ virtual bool OpenTable(PGLOBAL g, MODE mode, char *fn);
+ bool open(PGLOBAL g, char *fn);
+ bool openEntry(PGLOBAL g);
+ void close(void);
+ void closeEntry(void);
+ bool WildMatch(PSZ pat, PSZ str);
+ int findEntry(PGLOBAL g, bool next);
+ int nextEntry(PGLOBAL g);
+
+ // Members
+ unzFile zipfile; // The ZIP container file
+ PSZ target; // The target file name
+ unz_file_info finfo; // The current file info
+ PFBLOCK fp;
+ char *memory;
+ uint size;
+ int multiple; // Multiple targets
+ bool entryopen; // True when open current entry
+ char fn[FILENAME_MAX]; // The current entry file name
+ char mapCaseTable[256];
+}; // end of ZIPFAM
+
+/***********************************************************************/
/* This is the ZIP file access method. */
/***********************************************************************/
class DllExport ZIPFAM : public MAPFAM {
+ friend class ZPXFAM;
public:
- // Constructor
+ // Constructors
ZIPFAM(PDOSDEF tdp);
ZIPFAM(PZIPFAM txfp);
+ ZIPFAM(PDOSDEF tdp, PZPXFAM txfp);
// Implementation
- virtual AMT GetAmType(void) {return TYPE_AM_ZIP;}
- virtual PTXF Duplicate(PGLOBAL g) {return (PTXF) new(g) ZIPFAM(this);}
+ virtual AMT GetAmType(void) { return TYPE_AM_ZIP; }
+ virtual PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)ZIPFAM(this); }
// Methods
+ virtual int Cardinality(PGLOBAL g);
virtual int GetFileLength(PGLOBAL g);
- virtual int Cardinality(PGLOBAL g) {return (g) ? 10 : 1;}
//virtual int MaxBlkSize(PGLOBAL g, int s) {return s;}
virtual bool OpenTableFile(PGLOBAL g);
- virtual bool DeferReading(void) {return false;}
- virtual int ReadBuffer(PGLOBAL g);
+ virtual bool DeferReading(void) { return false; }
+ virtual int GetNext(PGLOBAL g);
+//virtual int ReadBuffer(PGLOBAL g);
//virtual int WriteBuffer(PGLOBAL g);
//virtual int DeleteRecords(PGLOBAL g, int irc);
//virtual void CloseTableFile(PGLOBAL g, bool abort);
- void close(void);
protected:
- bool open(PGLOBAL g, const char *filename);
- bool openEntry(PGLOBAL g);
- void closeEntry(void);
- bool WildMatch(PSZ pat, PSZ str);
- int findEntry(PGLOBAL g, bool next);
-
// Members
- unzFile zipfile; // The ZIP container file
-//PSZ zfn; // The ZIP file name
- PSZ target; // The target file name
- unz_file_info finfo; // The current file info
-//char fn[FILENAME_MAX]; // The current file name
- bool entryopen; // True when open current entry
- int multiple; // Multiple targets
- char mapCaseTable[256];
+ ZIPUTIL *zutp;
+ PSZ target;
+ bool mul;
}; // end of ZIPFAM
/***********************************************************************/
/* This is the fixed ZIP file access method. */
/***********************************************************************/
-class DllExport ZPXFAM : public ZIPFAM {
+class DllExport ZPXFAM : public MPXFAM {
+ friend class ZIPFAM;
public:
- // Constructor
+ // Constructors
ZPXFAM(PDOSDEF tdp);
ZPXFAM(PZPXFAM txfp);
// Implementation
- virtual PTXF Duplicate(PGLOBAL g) {return (PTXF) new(g) ZPXFAM(this);}
+ virtual AMT GetAmType(void) { return TYPE_AM_ZIP; }
+ virtual PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)ZPXFAM(this); }
// Methods
- virtual int ReadBuffer(PGLOBAL g);
+ virtual int GetFileLength(PGLOBAL g);
+ virtual int Cardinality(PGLOBAL g);
+ virtual bool OpenTableFile(PGLOBAL g);
+ virtual int GetNext(PGLOBAL g);
+//virtual int ReadBuffer(PGLOBAL g);
protected:
// Members
- int Lrecl;
+ ZIPUTIL *zutp;
+ PSZ target;
+ bool mul;
}; // end of ZPXFAM
#endif // __FILAMZIP_H
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 45ca546ad4e..6590902bcd4 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -1242,8 +1242,10 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
if (opval && (!stricmp(opname, "connect")
|| !stricmp(opname, "tabname")
- || !stricmp(opname, "filename")))
- opval = GetRealString(opval);
+ || !stricmp(opname, "filename")
+ || !stricmp(opname, "optname")
+ || !stricmp(opname, "entry")))
+ opval = GetRealString(opval);
if (!opval) {
if (sdef && !strcmp(sdef, "*")) {
diff --git a/storage/connect/libdoc.cpp b/storage/connect/libdoc.cpp
index c2882fc0d7c..2470d37c353 100644
--- a/storage/connect/libdoc.cpp
+++ b/storage/connect/libdoc.cpp
@@ -1,6 +1,6 @@
/******************************************************************/
/* Implementation of XML document processing using libxml2 */
-/* Author: Olivier Bertrand 2007-2015 */
+/* Author: Olivier Bertrand 2007-2016 */
/******************************************************************/
#include "my_global.h"
#include <string.h>
@@ -68,8 +68,8 @@ class LIBXMLDOC : public XMLDOCUMENT {
virtual void SetNofree(bool b) {Nofreelist = b;}
// Methods
- virtual bool Initialize(PGLOBAL g);
- virtual bool ParseFile(char *fn);
+ virtual bool Initialize(PGLOBAL g, char *entry, bool zipped);
+ virtual bool ParseFile(PGLOBAL g, char *fn);
virtual bool NewDoc(PGLOBAL g, char *ver);
virtual void AddComment(PGLOBAL g, char *com);
virtual PXNODE GetRoot(PGLOBAL g);
@@ -373,22 +373,33 @@ LIBXMLDOC::LIBXMLDOC(char *nsl, char *nsdf, char *enc, PFBLOCK fp)
/******************************************************************/
/* Initialize XML parser and check library compatibility. */
/******************************************************************/
-bool LIBXMLDOC::Initialize(PGLOBAL g)
- {
+bool LIBXMLDOC::Initialize(PGLOBAL g, char *entry, bool zipped)
+{
+ if (zipped && InitZip(g, entry))
+ return true;
+
int n = xmlKeepBlanksDefault(1);
return MakeNSlist(g);
- } // end of Initialize
+} // end of Initialize
/******************************************************************/
/* Parse the XML file and construct node tree in memory. */
/******************************************************************/
-bool LIBXMLDOC::ParseFile(char *fn)
+bool LIBXMLDOC::ParseFile(PGLOBAL g, char *fn)
{
if (trace)
htrc("ParseFile\n");
- if ((Docp = xmlParseFile(fn))) {
- if (Docp->encoding)
+ if (zip) {
+ // Parse an in memory document
+ char *xdoc = GetMemDoc(g, fn);
+
+ Docp = (xdoc) ? xmlParseDoc((const xmlChar *)xdoc) : NULL;
+ } else
+ Docp = xmlParseFile(fn);
+
+ if (Docp) {
+ if (Docp->encoding)
Encoding = (char*)Docp->encoding;
return false;
@@ -609,6 +620,7 @@ void LIBXMLDOC::CloseDoc(PGLOBAL g, PFBLOCK xp)
} // endif xp
CloseXML2File(g, xp, false);
+ CloseZip();
} // end of Close
/******************************************************************/
diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp
index 31c040c6957..83975c6d8fa 100644
--- a/storage/connect/plgdbutl.cpp
+++ b/storage/connect/plgdbutl.cpp
@@ -939,7 +939,7 @@ int PlugCloseFile(PGLOBAL g __attribute__((unused)), PFBLOCK fp, bool all)
#endif // LIBXML2_SUPPORT
#ifdef ZIP_SUPPORT
case TYPE_FB_ZIP:
- ((PZIPFAM)fp->File)->close();
+ ((ZIPUTIL*)fp->File)->close();
fp->Memory = NULL;
fp->Mode = MODE_ANY;
fp->Count = 0;
diff --git a/storage/connect/plgxml.cpp b/storage/connect/plgxml.cpp
index 3061a6d697e..71b72621b06 100644
--- a/storage/connect/plgxml.cpp
+++ b/storage/connect/plgxml.cpp
@@ -30,19 +30,51 @@ PXDOC GetLibxmlDoc(PGLOBAL g, char *nsl, char *nsdf,
/* XMLDOCUMENT constructor. */
/******************************************************************/
XMLDOCUMENT::XMLDOCUMENT(char *nsl, char *nsdf, char *enc)
- {
- Namespaces = NULL;
+{
+#if defined(ZIP_SUPPORT)
+ zip = NULL;
+#else // !ZIP_SUPPORT
+ zip = false;
+#endif // !ZIP_SUPPORT
+ Namespaces = NULL;
Encoding = enc;
Nslist = nsl;
DefNs = nsdf;
- } // end of XMLDOCUMENT constructor
+} // end of XMLDOCUMENT constructor
+
+/******************************************************************/
+/* Initialize zipped file processing. */
+/******************************************************************/
+bool XMLDOCUMENT::InitZip(PGLOBAL g, char *entry)
+{
+#if defined(ZIP_SUPPORT)
+ bool mul = (entry) ? strchr(entry, '*') || strchr(entry, '?') : false;
+ zip = new(g) ZIPUTIL(entry, mul);
+ return zip == NULL;
+#else // !ZIP_SUPPORT
+ sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
+ return true;
+#endif // !ZIP_SUPPORT
+} // end of InitZip
+
+/******************************************************************/
+/* Make the namespace structure list. */
+/******************************************************************/
+char* XMLDOCUMENT::GetMemDoc(PGLOBAL g, char *fn)
+{
+#if defined(ZIP_SUPPORT)
+ return (zip->OpenTable(g, MODE_ANY, fn)) ? NULL : zip->memory;
+#else // !ZIP_SUPPORT
+ return NULL;
+#endif // !ZIP_SUPPORT
+} // end of GetMemDoc
/******************************************************************/
/* Make the namespace structure list. */
/******************************************************************/
bool XMLDOCUMENT::MakeNSlist(PGLOBAL g)
- {
- char *prefix, *href, *next = Nslist;
+{
+ char *prefix, *href, *next = Nslist;
PNS nsp, *ppns = &Namespaces;
while (next) {
@@ -84,6 +116,19 @@ bool XMLDOCUMENT::MakeNSlist(PGLOBAL g)
} // end of MakeNSlist
/******************************************************************/
+/* Close ZIP file. */
+/******************************************************************/
+void XMLDOCUMENT::CloseZip(void)
+{
+#if defined(ZIP_SUPPORT)
+ if (zip) {
+ zip->close();
+ zip = NULL;
+ } // endif zip
+#endif // ZIP_SUPPORT
+} // end of CloseZip
+
+/******************************************************************/
/* XMLNODE constructor. */
/******************************************************************/
XMLNODE::XMLNODE(PXDOC dp)
diff --git a/storage/connect/plgxml.h b/storage/connect/plgxml.h
index b8e914e0bf1..db7dfa6bda5 100644
--- a/storage/connect/plgxml.h
+++ b/storage/connect/plgxml.h
@@ -1,3 +1,7 @@
+#if defined(ZIP_SUPPORT)
+#include "filamzip.h"
+#endif // ZIP_SUPPORT
+
/******************************************************************/
/* Dual XML implementation base classes defines. */
/******************************************************************/
@@ -72,8 +76,8 @@ class XMLDOCUMENT : public BLOCK {
virtual void SetNofree(bool b) = 0;
// Methods
- virtual bool Initialize(PGLOBAL) = 0;
- virtual bool ParseFile(char *) = 0;
+ virtual bool Initialize(PGLOBAL, char *, bool) = 0;
+ virtual bool ParseFile(PGLOBAL, char *) = 0;
virtual bool NewDoc(PGLOBAL, char *) = 0;
virtual void AddComment(PGLOBAL, char *) = 0;
virtual PXNODE GetRoot(PGLOBAL) = 0;
@@ -91,8 +95,16 @@ class XMLDOCUMENT : public BLOCK {
// Utility
bool MakeNSlist(PGLOBAL g);
+ bool InitZip(PGLOBAL g, char *entry);
+ char *GetMemDoc(PGLOBAL g, char *fn);
+ void CloseZip(void);
// Members
+#if defined(ZIP_SUPPORT)
+ ZIPUTIL *zip; /* Used for zipped file */
+#else // !ZIP_SUPPORT
+ bool zip; /* Always false */
+#endif // !ZIP_SUPPORT
PNS Namespaces; /* To the namespaces */
char *Encoding; /* The document encoding */
char *Nslist; /* Namespace list */
diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp
index f47e66b014b..16cc6c33b44 100644
--- a/storage/connect/tabdos.cpp
+++ b/storage/connect/tabdos.cpp
@@ -101,6 +101,7 @@ DOSDEF::DOSDEF(void)
Recfm = RECFM_VAR;
Mapped = false;
Zipped = false;
+ Mulentries = false;
Padded = false;
Huge = false;
Accept = false;
@@ -131,12 +132,13 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
: (am && (*am == 'B' || *am == 'b')) ? "B"
: (am && !stricmp(am, "DBF")) ? "D" : "V";
- if (*dfm != 'D')
- Zipped = GetBoolCatInfo("Zipped", false);
+ if ((Zipped = GetBoolCatInfo("Zipped", false)))
+ Mulentries = ((Entry = GetStringCatInfo(g, "Entry", NULL)))
+ ? strchr(Entry, '*') || strchr(Entry, '?')
+ : GetBoolCatInfo("Mulentries", false);
Desc = Fn = GetStringCatInfo(g, "Filename", NULL);
Ofn = GetStringCatInfo(g, "Optname", Fn);
- Entry = GetStringCatInfo(g, "Entry", NULL);
GetCharCatInfo("Recfm", (PSZ)dfm, buf, sizeof(buf));
Recfm = (toupper(*buf) == 'F') ? RECFM_FIX :
(toupper(*buf) == 'B') ? RECFM_BIN :
@@ -344,14 +346,16 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode)
/*********************************************************************/
if (Zipped) {
#if defined(ZIP_SUPPORT)
- if (Recfm == RECFM_VAR)
- txfp = new(g) ZIPFAM(this);
- else
- txfp = new(g) ZPXFAM(this);
+ if (Recfm == RECFM_VAR) {
+ txfp = new(g)ZIPFAM(this);
+ tdbp = new(g)TDBDOS(this, txfp);
+ } else {
+ txfp = new(g)ZPXFAM(this);
+ tdbp = new(g)TDBFIX(this, txfp);
+ } // endif Recfm
- tdbp = new(g) TDBDOS(this, txfp);
#else // !ZIP_SUPPORT
- strcpy(g->Message, "ZIP not supported");
+ sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
return NULL;
#endif // !ZIP_SUPPORT
} else if (Recfm == RECFM_DBF) {
@@ -559,7 +563,7 @@ int TDBDOS::ResetTableOpt(PGLOBAL g, bool dop, bool dox)
Txfp->Reset();
((PZLBFAM)Txfp)->SetOptimized(false);
#endif // GZ_SUPPORT
- } else if (Txfp->GetAmType() == TYPE_AM_BLK)
+ } else if (Txfp->GetAmType() == TYPE_AM_BLK)
Txfp = new(g) DOSFAM((PDOSDEF)To_Def);
Txfp->SetTdbp(this);
@@ -630,7 +634,12 @@ int TDBDOS::MakeBlockValues(PGLOBAL g)
defp->SetOptimized(0);
// Estimate the number of needed blocks
- block = (int)((MaxSize + (int)nrec - 1) / (int)nrec);
+ if ((block = (int)((MaxSize + (int)nrec - 1) / (int)nrec)) < 2) {
+ // This may be wrong to do in some cases
+ defp->RemoveOptValues(g);
+ strcpy(g->Message, MSG(TABLE_NOT_OPT));
+ return RC_INFO; // Not to be optimized
+ } // endif block
// We have to use local variables because Txfp->CurBlk is set
// to Rows+1 by unblocked variable length table access methods.
@@ -973,13 +982,14 @@ bool TDBDOS::GetBlockValues(PGLOBAL g)
PCOLDEF cdp;
PDOSDEF defp = (PDOSDEF)To_Def;
PCATLG cat = defp->GetCat();
+ PDBUSER dup = PlgGetUser(g);
#if 0
if (Mode == MODE_INSERT && Txfp->GetAmType() == TYPE_AM_DOS)
return false;
#endif // __WIN__
- if (defp->Optimized)
+ if (defp->Optimized || !(dup->Check & CHK_OPT))
return false; // Already done or to be redone
if (Ftype == RECFM_VAR || defp->Compressed == 2) {
diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h
index 623adcfed0d..4c8eb438a26 100644
--- a/storage/connect/tabdos.h
+++ b/storage/connect/tabdos.h
@@ -28,7 +28,7 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
friend class TDBFIX;
friend class TXTFAM;
friend class DBFBASE;
- friend class ZIPFAM;
+ friend class ZIPUTIL;
public:
// Constructor
DOSDEF(void);
@@ -41,7 +41,9 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
virtual bool IsHuge(void) {return Huge;}
PSZ GetFn(void) {return Fn;}
PSZ GetOfn(void) {return Ofn;}
- void SetBlock(int block) {Block = block;}
+ PSZ GetEntry(void) {return Entry;}
+ bool GetMul(void) {return Mulentries;}
+ void SetBlock(int block) {Block = block;}
int GetBlock(void) {return Block;}
int GetLast(void) {return Last;}
void SetLast(int last) {Last = last;}
@@ -58,9 +60,9 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
int *GetTo_Pos(void) {return To_Pos;}
// Methods
- virtual int Indexable(void)
- {return (!Multiple && !Zipped && Compressed != 1) ? 1 : 0;}
- virtual bool DeleteIndexFile(PGLOBAL g, PIXDEF pxdf);
+ virtual int Indexable(void)
+ {return (!Multiple && !Mulentries && Compressed != 1) ? 1 : 0;}
+ virtual bool DeleteIndexFile(PGLOBAL g, PIXDEF pxdf);
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode);
bool InvalidateIndex(PGLOBAL g);
@@ -78,6 +80,7 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
RECFM Recfm; /* 0:VAR, 1:FIX, 2:BIN, 3:VCT, 6:DBF */
bool Mapped; /* 0: disk file, 1: memory mapped file */
bool Zipped; /* true for zipped table file */
+ bool Mulentries; /* true for multiple entries */
bool Padded; /* true for padded table file */
bool Huge; /* true for files larger than 2GB */
bool Accept; /* true if wrong lines are accepted */
diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp
index 2c4d605e66c..b24375443f6 100644
--- a/storage/connect/tabfmt.cpp
+++ b/storage/connect/tabfmt.cpp
@@ -177,9 +177,14 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info)
htrc("File %s Sep=%c Qot=%c Header=%d maxerr=%d\n",
SVP(tdp->Fn), tdp->Sep, tdp->Qot, tdp->Header, tdp->Maxerr);
- if (tdp->Zipped)
- tdbp = new(g) TDBCSV(tdp, new(g) ZIPFAM(tdp));
- else
+ if (tdp->Zipped) {
+#if defined(ZIP_SUPPORT)
+ tdbp = new(g)TDBCSV(tdp, new(g)ZIPFAM(tdp));
+#else // !ZIP_SUPPORT
+ sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
+ return NULL;
+#endif // !ZIP_SUPPORT
+ } else
tdbp = new(g) TDBCSV(tdp, new(g) DOSFAM(tdp));
tdbp->SetMode(MODE_READ);
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index eff95445a3a..1b9ce8b64c9 100644
--- a/storage/connect/tabjson.cpp
+++ b/storage/connect/tabjson.cpp
@@ -127,9 +127,14 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info)
tdp->Fn, tdp->Objname, tdp->Pretty, lvl);
if (tdp->Pretty == 2) {
- if (tdp->Zipped)
- tjsp = new(g) TDBJSON(tdp, new(g) ZIPFAM(tdp));
- else
+ if (tdp->Zipped) {
+#if defined(ZIP_SUPPORT)
+ tjsp = new(g) TDBJSON(tdp, new(g) ZIPFAM(tdp));
+#else // !ZIP_SUPPORT
+ sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
+ return NULL;
+#endif // !ZIP_SUPPORT
+ } else
tjsp = new(g) TDBJSON(tdp, new(g) MAPFAM(tdp));
if (tjsp->MakeDocument(g))
@@ -144,9 +149,14 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info)
tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF);
- if (tdp->Zipped)
- tjnp = new(g) TDBJSN(tdp, new(g) ZIPFAM(tdp));
- else
+ if (tdp->Zipped) {
+#if defined(ZIP_SUPPORT)
+ tjnp = new(g)TDBJSN(tdp, new(g)ZIPFAM(tdp));
+#else // !ZIP_SUPPORT
+ sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
+ return NULL;
+#endif // !ZIP_SUPPORT
+ } else
tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp));
tjnp->SetMode(MODE_READ);
@@ -467,9 +477,14 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
((TDBJSN*)tdbp)->G = g;
#endif
} else {
- if (Zipped)
- txfp = new(g) ZIPFAM(this);
- else
+ if (Zipped) {
+#if defined(ZIP_SUPPORT)
+ txfp = new(g)ZIPFAM(this);
+#else // !ZIP_SUPPORT
+ sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
+ return NULL;
+#endif // !ZIP_SUPPORT
+ } else
txfp = new(g) MAPFAM(this);
tdbp = new(g) TDBJSON(this, txfp);
diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp
index 1993b07eb7a..3b8229fcf51 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.8 */
+/* Version 2.9 */
/* */
-/* Author Olivier BERTRAND 2007 - 2015 */
+/* Author Olivier BERTRAND 2007 - 2016 */
/* */
/* This program are the XML tables classes using MS-DOM or libxml2. */
/***********************************************************************/
@@ -159,6 +159,8 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
tdp->Fn = fn;
tdp->Database = SetPath(g, db);
tdp->Tabname = tab;
+ tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false);
+ tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL);
if (!(op = GetStringTableOption(g, topt, "Xmlsup", NULL)))
#if defined(__WIN__)
@@ -209,7 +211,8 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
while (true) {
if (!vp->atp &&
- !(node = (vp->nl) ? vp->nl->GetItem(g, vp->k++, node) : NULL))
+ !(node = (vp->nl) ? vp->nl->GetItem(g, vp->k++, tdp->Usedom ? node : NULL)
+ : NULL))
if (j) {
vp = lvlp[--j];
@@ -259,7 +262,8 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
if (j < lvl && ok) {
vp = lvlp[j+1];
vp->k = 0;
- vp->atp = node->GetAttribute(g, NULL);
+ vp->pn = node;
+ vp->atp = node->GetAttribute(g, NULL);
vp->nl = node->GetChildElements(g);
if (tdp->Usedom && vp->nl->GetLength() == 1) {
@@ -270,7 +274,7 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
if (vp->atp || vp->b) {
if (!vp->atp)
- node = vp->nl->GetItem(g, vp->k++, node);
+ node = vp->nl->GetItem(g, vp->k++, tdp->Usedom ? node : NULL);
strncat(fmt, colname, XLEN(fmt));
strncat(fmt, "/", XLEN(fmt));
@@ -429,11 +433,14 @@ XMLDEF::XMLDEF(void)
DefNs = NULL;
Attrib = NULL;
Hdattr = NULL;
+ Entry = NULL;
Coltype = 1;
Limit = 0;
Header = 0;
Xpand = false;
Usedom = false;
+ Zipped = false;
+ Mulentries = false;
} // end of XMLDEF constructor
/***********************************************************************/
@@ -512,7 +519,14 @@ bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
// Get eventual table node attribute
Attrib = GetStringCatInfo(g, "Attribute", NULL);
Hdattr = GetStringCatInfo(g, "HeadAttr", NULL);
- return false;
+
+ // Specific for zipped files
+ if ((Zipped = GetBoolCatInfo("Zipped", false)))
+ Mulentries = ((Entry = GetStringCatInfo(g, "Entry", NULL)))
+ ? strchr(Entry, '*') || strchr(Entry, '?')
+ : GetBoolCatInfo("Mulentries", false);
+
+ return false;
} // end of DefineAM
/***********************************************************************/
@@ -552,6 +566,7 @@ TDBXML::TDBXML(PXMLDEF tdp) : TDBASE(tdp)
Xfile = tdp->Fn;
Enc = tdp->Encoding;
Tabname = tdp->Tabname;
+#if 0 // why all these?
Rowname = (tdp->Rowname) ? tdp->Rowname : NULL;
Colname = (tdp->Colname) ? tdp->Colname : NULL;
Mulnode = (tdp->Mulnode) ? tdp->Mulnode : NULL;
@@ -560,10 +575,22 @@ TDBXML::TDBXML(PXMLDEF tdp) : TDBASE(tdp)
DefNs = (tdp->DefNs) ? tdp->DefNs : NULL;
Attrib = (tdp->Attrib) ? tdp->Attrib : NULL;
Hdattr = (tdp->Hdattr) ? tdp->Hdattr : NULL;
- Coltype = tdp->Coltype;
+#endif // 0
+ Rowname = tdp->Rowname;
+ Colname = tdp->Colname;
+ Mulnode = tdp->Mulnode;
+ XmlDB = tdp->XmlDB;
+ Nslist = tdp->Nslist;
+ DefNs = tdp->DefNs;
+ Attrib = tdp->Attrib;
+ Hdattr = tdp->Hdattr;
+ Entry = tdp->Entry;
+ Coltype = tdp->Coltype;
Limit = tdp->Limit;
Xpand = tdp->Xpand;
- Changed = false;
+ Zipped = tdp->Zipped;
+ Mulentries = tdp->Mulentries;
+ Changed = false;
Checked = false;
NextSame = false;
NewRow = false;
@@ -605,10 +632,13 @@ TDBXML::TDBXML(PTDBXML tdbp) : TDBASE(tdbp)
DefNs = tdbp->DefNs;
Attrib = tdbp->Attrib;
Hdattr = tdbp->Hdattr;
- Coltype = tdbp->Coltype;
+ Entry = tdbp->Entry;
+ Coltype = tdbp->Coltype;
Limit = tdbp->Limit;
Xpand = tdbp->Xpand;
- Changed = tdbp->Changed;
+ Zipped = tdbp->Zipped;
+ Mulentries = tdbp->Mulentries;
+ Changed = tdbp->Changed;
Checked = tdbp->Checked;
NextSame = tdbp->NextSame;
NewRow = tdbp->NewRow;
@@ -686,7 +716,7 @@ int TDBXML::LoadTableFile(PGLOBAL g, char *filename)
/*********************************************************************/
/* Firstly we check whether this file have been already loaded. */
/*********************************************************************/
- if (Mode == MODE_READ || Mode == MODE_ANY)
+ if ((Mode == MODE_READ || Mode == MODE_ANY) && !Zipped)
for (fp = dup->Openlist; fp; fp = fp->Next)
if (fp->Type == type && fp->Length && fp->Count)
if (!stricmp(fp->Fname, filename))
@@ -708,7 +738,7 @@ int TDBXML::LoadTableFile(PGLOBAL g, char *filename)
return RC_FX;
// Initialize the implementation
- if (Docp->Initialize(g)) {
+ if (Docp->Initialize(g, Entry, Zipped)) {
sprintf(g->Message, MSG(INIT_FAILED), (Usedom) ? "DOM" : "libxml2");
return RC_FX;
} // endif init
@@ -717,7 +747,7 @@ int TDBXML::LoadTableFile(PGLOBAL g, char *filename)
htrc("TDBXML: parsing %s rc=%d\n", filename, rc);
// Parse the XML file
- if (Docp->ParseFile(filename)) {
+ if (Docp->ParseFile(g, filename)) {
// Does the file exist?
int h= global_open(g, MSGID_NONE, filename, _O_RDONLY);
diff --git a/storage/connect/tabxml.h b/storage/connect/tabxml.h
index 7ba3166881d..6c586d79dec 100644
--- a/storage/connect/tabxml.h
+++ b/storage/connect/tabxml.h
@@ -1,7 +1,7 @@
/*************** Tabxml H Declares Source Code File (.H) ***************/
-/* Name: TABXML.H Version 1.6 */
+/* Name: TABXML.H Version 1.7 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2007-2015 */
+/* (C) Copyright to the author Olivier BERTRAND 2007-2016 */
/* */
/* This file contains the XML table classes declares. */
/***********************************************************************/
@@ -42,12 +42,15 @@ class DllExport XMLDEF : public TABDEF { /* Logical table description */
char *DefNs; /* Dummy name of default namespace */
char *Attrib; /* Table node attributes */
char *Hdattr; /* Header node attributes */
- int Coltype; /* Default column type */
+ char *Entry; /* Zip entry name or pattern */
+ int Coltype; /* Default column type */
int Limit; /* Limit of multiple values */
int Header; /* n first rows are header rows */
bool Xpand; /* Put multiple tags in several rows */
bool Usedom; /* True: DOM, False: libxml2 */
- }; // end of XMLDEF
+ bool Zipped; /* True: Zipped XML file(s) */
+ bool Mulentries; /* True: multiple entries in zip file*/
+}; // end of XMLDEF
#if defined(INCLUDE_TDBXML)
/***********************************************************************/
@@ -122,7 +125,9 @@ class DllExport TDBXML : public TDBASE {
bool Bufdone; // True when column buffers allocated
bool Nodedone; // True when column nodes allocated
bool Void; // True if the file does not exist
- char *Xfile; // The XML file
+ bool Zipped; // True if Zipped XML file(s)
+ bool Mulentries; // True if multiple entries in zip file
+ char *Xfile; // The XML file
char *Enc; // New XML table file encoding
char *Tabname; // Name of Table node
char *Rowname; // Name of first level nodes
@@ -133,7 +138,8 @@ class DllExport TDBXML : public TDBASE {
char *DefNs; // Dummy name of default namespace
char *Attrib; // Table node attribut(s)
char *Hdattr; // Header node attribut(s)
- int Coltype; // Default column type
+ char *Entry; // Zip entry name or pattern
+ int Coltype; // Default column type
int Limit; // Limit of multiple values
int Header; // n first rows are header rows
int Multiple; // If multiple files