summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2020-10-24 10:08:07 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2020-10-24 10:08:07 +0200
commit06af03677cf5ad26b733d6250305d75412ed9201 (patch)
tree423e4ddfc890c45c57872153e305de4928f67748
parent94b493571a8ba8f30c97a5c30fc641171ca48e8a (diff)
parent671d9b6c611be423246b562878da2a5788cc327d (diff)
downloadmariadb-git-06af03677cf5ad26b733d6250305d75412ed9201.tar.gz
Merge remote-tracking branch 'connect/10.1' into 10.1
-rw-r--r--storage/connect/connect.cc1
-rw-r--r--storage/connect/filamdbf.cpp199
-rw-r--r--storage/connect/filamdbf.h2
-rw-r--r--storage/connect/filamzip.cpp282
-rw-r--r--storage/connect/filamzip.h38
-rw-r--r--storage/connect/ha_connect.cc19
-rw-r--r--storage/connect/mongo.cpp1
-rw-r--r--storage/connect/mongo.h1
-rw-r--r--storage/connect/plgxml.cpp2
-rw-r--r--storage/connect/tabcmg.cpp2
-rw-r--r--storage/connect/tabdos.cpp36
-rw-r--r--storage/connect/tabdos.h1
-rw-r--r--storage/connect/tabfix.h18
-rw-r--r--storage/connect/tabjson.cpp1
-rw-r--r--storage/connect/tabjson.h1
-rw-r--r--storage/connect/tabzip.cpp13
-rw-r--r--storage/connect/tabzip.h2
17 files changed, 511 insertions, 108 deletions
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index dfc619cf4af..2a0f2ed037f 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -355,7 +355,6 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
} // endif mode
rcop = false;
-
} catch (int n) {
if (trace(1))
htrc("Exception %d: %s\n", n, g->Message);
diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp
index c8bab2b53a4..542159fd172 100644
--- a/storage/connect/filamdbf.cpp
+++ b/storage/connect/filamdbf.cpp
@@ -49,6 +49,7 @@
#include "global.h"
#include "plgdbsem.h"
#include "filamdbf.h"
+#include "filamzip.h"
#include "tabdos.h"
#include "valblk.h"
#define NO_FUNC
@@ -139,7 +140,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
if (fread(buf, HEADLEN, 1, file) != 1) {
strcpy(g->Message, MSG(NO_READ_32));
return RC_NF;
- } // endif fread
+ } // endif fread
// Check first byte to be sure of .dbf type
if ((buf->Version & 0x03) != DBFTYPE) {
@@ -149,7 +150,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
if ((buf->Version & 0x30) == 0x30) {
strcpy(g->Message, MSG(FOXPRO_FILE));
dbc = 264; // FoxPro database container
- } // endif Version
+ } // endif Version
} else
strcpy(g->Message, MSG(DBASE_FILE));
@@ -158,12 +159,12 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
if (fseek(file, buf->Headlen() - dbc, SEEK_SET) != 0) {
sprintf(g->Message, MSG(BAD_HEADER), fn);
return RC_FX;
- } // endif fseek
+ } // endif fseek
if (fread(&endmark, 2, 1, file) != 1) {
strcpy(g->Message, MSG(BAD_HEAD_END));
return RC_FX;
- } // endif fread
+ } // endif fread
// Some files have just 1D others have 1D00 following fields
if (endmark[0] != EOH && endmark[1] != EOH) {
@@ -172,7 +173,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
if (rc == RC_OK)
return RC_FX;
- } // endif endmark
+ } // endif endmark
// Calculate here the number of fields while we have the dbc info
buf->SetFields((buf->Headlen() - dbc - 1) / 32);
@@ -180,13 +181,58 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
return rc;
} // end of dbfhead
+/****************************************************************************/
+/* dbfields: Analyze a DBF header and set the table fields number. */
+/* Parameters: */
+/* PGLOBAL g -- pointer to the CONNECT Global structure */
+/* DBFHEADER *hdrp -- pointer to _dbfheader structure */
+/* Returns: */
+/* RC_OK, RC_INFO, or RC_FX if error. */
+/****************************************************************************/
+static int dbfields(PGLOBAL g, DBFHEADER* hdrp)
+{
+ char* endmark;
+ int dbc = 2, rc = RC_OK;
+
+ *g->Message = '\0';
+
+ // Check first byte to be sure of .dbf type
+ if ((hdrp->Version & 0x03) != DBFTYPE) {
+ strcpy(g->Message, MSG(NOT_A_DBF_FILE));
+ rc = RC_INFO;
+
+ if ((hdrp->Version & 0x30) == 0x30) {
+ strcpy(g->Message, MSG(FOXPRO_FILE));
+ dbc = 264; // FoxPro database container
+ } // endif Version
+
+ } else
+ strcpy(g->Message, MSG(DBASE_FILE));
+
+ // Check last byte(s) of header
+ endmark = (char*)hdrp + hdrp->Headlen() - dbc;
+
+ // Some headers just have 1D others have 1D00 following fields
+ if (endmark[0] != EOH && endmark[1] != EOH) {
+ sprintf(g->Message, MSG(NO_0DH_HEAD), dbc);
+
+ if (rc == RC_OK)
+ return RC_FX;
+
+ } // endif endmark
+
+ // Calculate here the number of fields while we have the dbc info
+ hdrp->SetFields((hdrp->Headlen() - dbc - 1) / 32);
+ return rc;
+} // end of dbfields
+
/* -------------------------- Function DBFColumns ------------------------- */
/****************************************************************************/
/* DBFColumns: constructs the result blocks containing the description */
/* of all the columns of a DBF file that will be retrieved by #GetData. */
/****************************************************************************/
-PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
+PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, PTOS topt, bool info)
{
int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
@@ -196,10 +242,12 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
char buf[2], filename[_MAX_PATH];
int ncol = sizeof(buftyp) / sizeof(int);
int rc, type, len, field, fields;
- bool bad;
- DBFHEADER mainhead;
- DESCRIPTOR thisfield;
- FILE *infile = NULL;
+ bool bad, mul;
+ PCSZ target, pwd;
+ DBFHEADER mainhead, *hp;
+ DESCRIPTOR thisfield, *tfp;
+ FILE *infile = NULL;
+ UNZIPUTL *zutp = NULL;
PQRYRES qrp;
PCOLRES crp;
@@ -217,21 +265,55 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
/************************************************************************/
PlugSetPath(filename, fn, dp);
- if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
- return NULL;
-
- /************************************************************************/
- /* Get the first 32 bytes of the header. */
- /************************************************************************/
- if ((rc = dbfhead(g, infile, filename, &mainhead)) == RC_FX) {
- fclose(infile);
- return NULL;
- } // endif dbfhead
-
- /************************************************************************/
- /* Allocate the structures used to refer to the result set. */
- /************************************************************************/
- fields = mainhead.Fields();
+ if (topt->zipped) {
+ target = GetStringTableOption(g, topt, "Entry", NULL);
+ mul = (target && *target) ? strchr(target, '*') || strchr(target, '?')
+ : false;
+ mul = GetBooleanTableOption(g, topt, "Mulentries", mul);
+
+ if (mul) {
+ strcpy(g->Message, "Cannot find column definition for multiple entries");
+ return NULL;
+ } // endif Multiple
+
+ pwd = GetStringTableOption(g, topt, "Password", NULL);
+ zutp = new(g) UNZIPUTL(target, pwd, mul);
+
+ if (!zutp->OpenTable(g, MODE_READ, filename))
+ hp = (DBFHEADER*)zutp->memory;
+ else
+ return NULL;
+
+ /**********************************************************************/
+ /* Set the table fields number. */
+ /**********************************************************************/
+ if ((rc = dbfields(g, hp)) == RC_FX) {
+ zutp->close();
+ return NULL;
+ } // endif dbfields
+
+ tfp = (DESCRIPTOR*)hp;
+ } else {
+ if (!(infile = global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
+ return NULL;
+ else
+ hp = &mainhead;
+
+ /**********************************************************************/
+ /* Get the first 32 bytes of the header. */
+ /**********************************************************************/
+ if ((rc = dbfhead(g, infile, filename, hp)) == RC_FX) {
+ fclose(infile);
+ return NULL;
+ } // endif dbfhead
+
+ tfp = &thisfield;
+ } // endif zipped
+
+ /************************************************************************/
+ /* Get the number of the table fields. */
+ /************************************************************************/
+ fields = hp->Fields();
} else
fields = 0;
@@ -241,19 +323,21 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
if (info || !qrp) {
if (infile)
fclose(infile);
+ else if (zutp)
+ zutp->close();
return qrp;
- } // endif info
+ } // endif info
if (trace(1)) {
htrc("Structure of %s\n", filename);
htrc("headlen=%hd reclen=%hd degree=%d\n",
- mainhead.Headlen(), mainhead.Reclen(), fields);
- htrc("flags(iem)=%d,%d,%d cp=%d\n", mainhead.Incompleteflag,
- mainhead.Encryptflag, mainhead.Mdxflag, mainhead.Language);
+ hp->Headlen(), hp->Reclen(), fields);
+ htrc("flags(iem)=%d,%d,%d cp=%d\n", hp->Incompleteflag,
+ hp->Encryptflag, hp->Mdxflag, hp->Language);
htrc("%hd records, last changed %02d/%02d/%d\n",
- mainhead.Records(), mainhead.Filedate[1], mainhead.Filedate[2],
- mainhead.Filedate[0] + (mainhead.Filedate[0] <= 30) ? 2000 : 1900);
+ hp->Records(), hp->Filedate[1], hp->Filedate[2],
+ hp->Filedate[0] + (hp->Filedate[0] <= 30) ? 2000 : 1900);
htrc("Field Type Offset Len Dec Set Mdx\n");
} // endif trace
@@ -265,21 +349,24 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
for (field = 0; field < fields; field++) {
bad = FALSE;
- if (fread(&thisfield, HEADLEN, 1, infile) != 1) {
+ if (topt->zipped) {
+ tfp = (DESCRIPTOR*)((char*)tfp + HEADLEN);
+ } else if (fread(tfp, HEADLEN, 1, infile) != 1) {
sprintf(g->Message, MSG(ERR_READING_REC), field+1, fn);
goto err;
- } else
- len = thisfield.Length;
+ } // endif fread
+
+ len = tfp->Length;
if (trace(1))
htrc("%-11s %c %6ld %3d %2d %3d %3d\n",
- thisfield.Name, thisfield.Type, thisfield.Offset, len,
- thisfield.Decimals, thisfield.Setfield, thisfield.Mdxfield);
+ tfp->Name, tfp->Type, tfp->Offset, len,
+ tfp->Decimals, tfp->Setfield, tfp->Mdxfield);
/************************************************************************/
/* Now get the results into blocks. */
/************************************************************************/
- switch (thisfield.Type) {
+ switch (tfp->Type) {
case 'C': // Characters
case 'L': // Logical 'T' or 'F' or space
type = TYPE_STRING;
@@ -294,7 +381,7 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
// type = TYPE_INT;
// break;
case 'N':
- type = (thisfield.Decimals) ? TYPE_DOUBLE
+ type = (tfp->Decimals) ? TYPE_DOUBLE
: (len > 10) ? TYPE_BIGINT : TYPE_INT;
break;
case 'F': // Float
@@ -306,8 +393,8 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
break;
default:
if (!info) {
- sprintf(g->Message, MSG(BAD_DBF_TYPE), thisfield.Type
- , thisfield.Name);
+ sprintf(g->Message, MSG(BAD_DBF_TYPE), tfp->Type
+ , tfp->Name);
goto err;
} // endif info
@@ -316,27 +403,31 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
} // endswitch Type
crp = qrp->Colresp; // Column Name
- crp->Kdata->SetValue(thisfield.Name, field);
+ crp->Kdata->SetValue(tfp->Name, field);
crp = crp->Next; // Data Type
crp->Kdata->SetValue((int)type, field);
crp = crp->Next; // Type Name
if (bad) {
- buf[0] = thisfield.Type;
+ buf[0] = tfp->Type;
crp->Kdata->SetValue(buf, field);
} else
crp->Kdata->SetValue(GetTypeName(type), field);
crp = crp->Next; // Precision
- crp->Kdata->SetValue((int)thisfield.Length, field);
+ crp->Kdata->SetValue((int)tfp->Length, field);
crp = crp->Next; // Length
- crp->Kdata->SetValue((int)thisfield.Length, field);
+ crp->Kdata->SetValue((int)tfp->Length, field);
crp = crp->Next; // Scale (precision)
- crp->Kdata->SetValue((int)thisfield.Decimals, field);
+ crp->Kdata->SetValue((int)tfp->Decimals, field);
} // endfor field
qrp->Nblin = field;
- fclose(infile);
+
+ if (infile)
+ fclose(infile);
+ else if (zutp)
+ zutp->close();
#if 0
if (info) {
@@ -347,9 +438,9 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
sprintf(buf,
"Ver=%02x ncol=%hu nlin=%u lrecl=%hu headlen=%hu date=%02d/%02d/%02d",
- mainhead.Version, fields, mainhead.Records, mainhead.Reclen,
- mainhead.Headlen, mainhead.Filedate[0], mainhead.Filedate[1],
- mainhead.Filedate[2]);
+ hp->Version, fields, hp->Records, hp->Reclen,
+ hp->Headlen, hp->Filedate[0], hp->Filedate[1],
+ hp->Filedate[2]);
strcat(g->Message, buf);
} // endif info
@@ -360,9 +451,13 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
/**************************************************************************/
return qrp;
- err:
- fclose(infile);
- return NULL;
+err:
+ if (infile)
+ fclose(infile);
+ else if (zutp)
+ zutp->close();
+
+ return NULL;
} // end of DBFColumns
/* ---------------------------- Class DBFBASE ----------------------------- */
diff --git a/storage/connect/filamdbf.h b/storage/connect/filamdbf.h
index 640fc349b4c..dfe5cb5cfc4 100644
--- a/storage/connect/filamdbf.h
+++ b/storage/connect/filamdbf.h
@@ -19,7 +19,7 @@ typedef class DBMFAM *PDBMFAM;
/****************************************************************************/
/* Functions used externally. */
/****************************************************************************/
-PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info);
+PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, PTOS tiop, bool info);
/****************************************************************************/
/* This is the base class for dBASE file access methods. */
diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp
index e76dc496246..eeb23e1f053 100644
--- a/storage/connect/filamzip.cpp
+++ b/storage/connect/filamzip.cpp
@@ -1,11 +1,11 @@
/*********** File AM Zip C++ Program Source Code File (.CPP) ***********/
/* PROGRAM NAME: FILAMZIP */
/* ------------- */
-/* Version 1.3 */
+/* Version 1.4 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2016-2017 */
+/* (C) Copyright to the author Olivier BERTRAND 2016-2020 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -45,6 +45,62 @@
#define WRITEBUFFERSIZE (16384)
+/****************************************************************************/
+/* Definitions used for DBF tables. */
+/****************************************************************************/
+#define HEADLEN 32 /* sizeof ( mainhead or thisfield ) */
+//efine MEMOLEN 10 /* length of memo field in .dbf */
+#define DBFTYPE 3 /* value of bits 0 and 1 if .dbf */
+#define EOH 0x0D /* end-of-header marker in .dbf file */
+
+/****************************************************************************/
+/* First 32 bytes of a DBF table. */
+/* Note: some reserved fields are used here to store info (Fields) */
+/****************************************************************************/
+typedef struct _dbfheader {
+ uchar Version; /* Version information flags */
+ char Filedate[3]; /* date, YYMMDD, binary. YY=year-1900 */
+private:
+ /* The following four members are stored in little-endian format on disk */
+ char m_RecordsBuf[4]; /* records in the file */
+ char m_HeadlenBuf[2]; /* bytes in the header */
+ char m_ReclenBuf[2]; /* bytes in a record */
+ char m_FieldsBuf[2]; /* Reserved but used to store fields */
+public:
+ char Incompleteflag; /* 01 if incomplete, else 00 */
+ char Encryptflag; /* 01 if encrypted, else 00 */
+ char Reserved2[12]; /* for LAN use */
+ char Mdxflag; /* 01 if production .mdx, else 00 */
+ char Language; /* Codepage */
+ char Reserved3[2];
+
+ uint Records(void) const { return uint4korr(m_RecordsBuf); }
+ ushort Headlen(void) const { return uint2korr(m_HeadlenBuf); }
+ ushort Reclen(void) const { return uint2korr(m_ReclenBuf); }
+ ushort Fields(void) const { return uint2korr(m_FieldsBuf); }
+
+ void SetHeadlen(ushort num) { int2store(m_HeadlenBuf, num); }
+ void SetReclen(ushort num) { int2store(m_ReclenBuf, num); }
+ void SetFields(ushort num) { int2store(m_FieldsBuf, num); }
+} DBFHEADER;
+
+/****************************************************************************/
+/* Column field descriptor of a .dbf file. */
+/****************************************************************************/
+typedef struct _descriptor {
+ char Name[11]; /* field name, in capitals, null filled*/
+ char Type; /* field type, C, D, F, L, M or N */
+ uint Offset; /* used in memvars, not in files. */
+ uchar Length; /* field length */
+ uchar Decimals; /* number of decimal places */
+ short Reserved4;
+ char Workarea; /* ??? */
+ char Reserved5[2];
+ char Setfield; /* ??? */
+ char Reserved6[7];
+ char Mdxfield; /* 01 if tag field in production .mdx */
+} DESCRIPTOR;
+
bool ZipLoadFile(PGLOBAL g, PCSZ zfn, PCSZ fn, PCSZ entry, bool append, bool mul);
/***********************************************************************/
@@ -214,10 +270,21 @@ bool ZipLoadFile(PGLOBAL g, PCSZ zfn, PCSZ fn, PCSZ entry, bool append, bool mul
buf = (char*)PlugSubAlloc(g, NULL, WRITEBUFFERSIZE);
- if (mul)
- err = ZipFiles(g, zutp, fn, buf);
- else
- err = ZipFile(g, zutp, fn, entry, buf);
+ if (!mul) {
+ PCSZ entp;
+
+ if (!entry) { // entry defaults to the file name
+ char* p = strrchr((char*)fn, '/');
+#if defined(__WIN__)
+ if (!p) p = strrchr((char*)fn, '\\');
+#endif // __WIN__
+ entp = (p) ? p + 1 : entry;
+ } else
+ entp = entry;
+
+ err = ZipFile(g, zutp, fn, entp, buf);
+ } else
+ err = ZipFiles(g, zutp, fn, buf);
zutp->close();
return err;
@@ -232,6 +299,7 @@ ZIPUTIL::ZIPUTIL(PCSZ tgt)
{
zipfile = NULL;
target = tgt;
+ pwd = NULL;
fp = NULL;
entryopen = false;
} // end of ZIPUTIL standard constructor
@@ -241,6 +309,7 @@ ZIPUTIL::ZIPUTIL(ZIPUTIL *zutp)
{
zipfile = zutp->zipfile;
target = zutp->target;
+ pwd = zutp->pwd;
fp = zutp->fp;
entryopen = zutp->entryopen;
} // end of UNZIPUTL copy constructor
@@ -385,11 +454,11 @@ void ZIPUTIL::closeEntry()
/***********************************************************************/
/* Constructors. */
/***********************************************************************/
-UNZIPUTL::UNZIPUTL(PCSZ tgt, bool mul)
+UNZIPUTL::UNZIPUTL(PCSZ tgt, PCSZ pw, bool mul)
{
zipfile = NULL;
target = tgt;
- pwd = NULL;
+ pwd = pw;
fp = NULL;
memory = NULL;
size = 0;
@@ -959,7 +1028,7 @@ int UZXFAM::Cardinality(PGLOBAL g)
} // end of Cardinality
/***********************************************************************/
-/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
+/* OpenTableFile: Open a FIX/UNIX table file from a ZIP file. */
/***********************************************************************/
bool UZXFAM::OpenTableFile(PGLOBAL g)
{
@@ -1015,6 +1084,197 @@ int UZXFAM::GetNext(PGLOBAL g)
return RC_OK;
} // end of GetNext
+/* -------------------------- class UZDFAM --------------------------- */
+
+/***********************************************************************/
+/* Constructors. */
+/***********************************************************************/
+UZDFAM::UZDFAM(PDOSDEF tdp) : DBMFAM(tdp)
+{
+ zutp = NULL;
+ tdfp = tdp;
+ //target = tdp->GetEntry();
+ //mul = tdp->GetMul();
+ //Lrecl = tdp->GetLrecl();
+} // end of UZXFAM standard constructor
+
+UZDFAM::UZDFAM(PUZDFAM txfp) : DBMFAM(txfp)
+{
+ zutp = txfp->zutp;
+ tdfp = txfp->tdfp;
+ //target = txfp->target;
+ //mul = txfp->mul;
+ //Lrecl = txfp->Lrecl;
+} // end of UZXFAM copy constructor
+
+#if 0
+/****************************************************************************/
+/* dbfhead: Routine to analyze a DBF header. */
+/* Parameters: */
+/* PGLOBAL g -- pointer to the CONNECT Global structure */
+/* DBFHEADER *hdrp -- pointer to _dbfheader structure */
+/* Returns: */
+/* RC_OK, RC_NF, RC_INFO, or RC_FX if error. */
+/* Side effects: */
+/* Set the fields number in the header. */
+/****************************************************************************/
+int UZDFAM::dbfhead(PGLOBAL g, void* buf)
+{
+ char *endmark;
+ int dbc = 2, rc = RC_OK;
+ DBFHEADER* hdrp = (DBFHEADER*)buf;
+
+ *g->Message = '\0';
+
+ // Check first byte to be sure of .dbf type
+ if ((hdrp->Version & 0x03) != DBFTYPE) {
+ strcpy(g->Message, MSG(NOT_A_DBF_FILE));
+ rc = RC_INFO;
+
+ if ((hdrp->Version & 0x30) == 0x30) {
+ strcpy(g->Message, MSG(FOXPRO_FILE));
+ dbc = 264; // FoxPro database container
+ } // endif Version
+
+ } else
+ strcpy(g->Message, MSG(DBASE_FILE));
+
+ // Check last byte(s) of header
+ endmark = (char*)hdrp + hdrp->Headlen() - dbc;
+
+ // Some headers just have 1D others have 1D00 following fields
+ if (endmark[0] != EOH && endmark[1] != EOH) {
+ sprintf(g->Message, MSG(NO_0DH_HEAD), dbc);
+
+ if (rc == RC_OK)
+ return RC_FX;
+
+ } // endif endmark
+
+ // Calculate here the number of fields while we have the dbc info
+ hdrp->SetFields((hdrp->Headlen() - dbc - 1) / 32);
+ return rc;
+} // end of dbfhead
+
+/****************************************************************************/
+/* ScanHeader: scan the DBF file header for number of records, record size,*/
+/* and header length. Set Records, check that Reclen is equal to lrecl and */
+/* return the header length or 0 in case of error. */
+/****************************************************************************/
+int UZDFAM::ScanHeader(PGLOBAL g, int* rln)
+{
+ int rc;
+ DBFHEADER header;
+
+ /************************************************************************/
+ /* Get the first 32 bytes of the header. */
+ /************************************************************************/
+ rc = dbfhead(g, &header);
+
+ if (rc == RC_FX)
+ return -1;
+
+ *rln = (int)header.Reclen();
+ Records = (int)header.Records();
+ return (int)header.Headlen();
+} // end of ScanHeader
+#endif // 0
+
+/***********************************************************************/
+/* ZIP GetFileLength: returns file size in number of bytes. */
+/***********************************************************************/
+int UZDFAM::GetFileLength(PGLOBAL g)
+{
+ int len;
+
+ if (!zutp && OpenTableFile(g))
+ return 0;
+
+ if (zutp->entryopen)
+ len = zutp->size;
+ else
+ len = 0;
+
+ return len;
+} // end of GetFileLength
+
+/***********************************************************************/
+/* ZIP Cardinality: return the number of rows if possible. */
+/***********************************************************************/
+int UZDFAM::Cardinality(PGLOBAL g)
+{
+ if (!g)
+ return 1;
+
+ int card = -1;
+ int len = GetFileLength(g);
+
+ card = Records;
+
+ // Set number of blocks for later use
+ Block = (card > 0) ? (card + Nrec - 1) / Nrec : 0;
+ return card;
+} // end of Cardinality
+
+/***********************************************************************/
+/* OpenTableFile: Open a DBF table file from a ZIP file. */
+/***********************************************************************/
+bool UZDFAM::OpenTableFile(PGLOBAL g)
+{
+ // May have been already opened in GetFileLength
+ if (!zutp || !zutp->zipfile) {
+ char filename[_MAX_PATH];
+ MODE mode = Tdbp->GetMode();
+
+ /*********************************************************************/
+ /* Allocate the ZIP utility class. */
+ /*********************************************************************/
+ if (!zutp)
+ zutp = new(g)UNZIPUTL(tdfp);
+
+ // 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;
+ Top = Memory + zutp->size;
+ To_Fb = zutp->fp; // Useful when closing
+ return AllocateBuffer(g);
+ } else
+ return true;
+
+ } else
+ Reset();
+
+ return false;
+} // end of OpenTableFile
+
+/***********************************************************************/
+/* GetNext: go to next entry. */
+/***********************************************************************/
+int UZDFAM::GetNext(PGLOBAL g)
+{
+ int rc = zutp->nextEntry(g);
+
+ if (rc != RC_OK)
+ return rc;
+
+ int len = zutp->size;
+
+#if 0
+ if (len % Lrecl) {
+ sprintf(g->Message, MSG(NOT_FIXED_LEN), zutp->fn, len, Lrecl);
+ return RC_FX;
+ } // endif size
+#endif // 0
+
+ Memory = zutp->memory;
+ Top = Memory + len;
+ Rewind();
+ return RC_OK;
+} // end of GetNext
+
/* -------------------------- class ZIPFAM --------------------------- */
/***********************************************************************/
@@ -1045,7 +1305,7 @@ bool ZIPFAM::OpenTableFile(PGLOBAL g)
strcpy(g->Message, "No insert into existing zip file");
return true;
} else if (append && len > 0) {
- UNZIPUTL *zutp = new(g) UNZIPUTL(target, false);
+ UNZIPUTL *zutp = new(g) UNZIPUTL(target, NULL, false);
if (!zutp->IsInsertOk(g, filename)) {
strcpy(g->Message, "No insert into existing entry");
@@ -1129,7 +1389,7 @@ bool ZPXFAM::OpenTableFile(PGLOBAL g)
strcpy(g->Message, "No insert into existing zip file");
return true;
} else if (append && len > 0) {
- UNZIPUTL *zutp = new(g) UNZIPUTL(target, false);
+ UNZIPUTL *zutp = new(g) UNZIPUTL(target, NULL, false);
if (!zutp->IsInsertOk(g, filename)) {
strcpy(g->Message, "No insert into existing entry");
diff --git a/storage/connect/filamzip.h b/storage/connect/filamzip.h
index be17d954728..7ff1fb0a543 100644
--- a/storage/connect/filamzip.h
+++ b/storage/connect/filamzip.h
@@ -1,7 +1,7 @@
/************** filamzip H Declares Source Code File (.H) **************/
-/* Name: filamzip.h Version 1.2 */
+/* Name: filamzip.h Version 1.3 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2016-2017 */
+/* (C) Copyright to the author Olivier BERTRAND 2016-2020 */
/* */
/* This file contains the ZIP file access method classes declares. */
/***********************************************************************/
@@ -11,6 +11,7 @@
#include "block.h"
#include "filamap.h"
#include "filamfix.h"
+#include "filamdbf.h"
#include "zip.h"
#include "unzip.h"
@@ -18,6 +19,7 @@
typedef class UNZFAM *PUNZFAM;
typedef class UZXFAM *PUZXFAM;
+typedef class UZDFAM* PUZDFAM;
typedef class ZIPFAM *PZIPFAM;
typedef class ZPXFAM *PZPXFAM;
@@ -53,7 +55,7 @@ class DllExport ZIPUTIL : public BLOCK {
class DllExport UNZIPUTL : public BLOCK {
public:
// Constructor
- UNZIPUTL(PCSZ tgt, bool mul);
+ UNZIPUTL(PCSZ tgt, PCSZ pw, bool mul);
UNZIPUTL(PDOSDEF tdp);
// Implementation
@@ -144,6 +146,36 @@ class DllExport UZXFAM : public MPXFAM {
}; // end of UZXFAM
/***********************************************************************/
+/* This is the fixed unzip file access method. */
+/***********************************************************************/
+class DllExport UZDFAM : public DBMFAM {
+ //friend class UNZFAM;
+public:
+ // Constructors
+ UZDFAM(PDOSDEF tdp);
+ UZDFAM(PUZDFAM txfp);
+
+ // Implementation
+ virtual AMT GetAmType(void) { return TYPE_AM_ZIP; }
+ virtual PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)UZDFAM(this); }
+
+ // Methods
+ 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:
+ int dbfhead(PGLOBAL g, void* buf);
+ int ScanHeader(PGLOBAL g, int* rln);
+
+ // Members
+ UNZIPUTL* zutp;
+ PDOSDEF tdfp;
+}; // end of UZDFAM
+
+/***********************************************************************/
/* This is the zip file access method. */
/***********************************************************************/
class DllExport ZIPFAM : public DOSFAM {
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index a111082e786..bb56d6cd655 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -4507,12 +4507,12 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
case TAB_DIR:
case TAB_ZIP:
case TAB_OEM:
- if (table && table->pos_in_table_list) // if SELECT
- {
- //Switch_to_definer_security_ctx backup_ctx(thd, table->pos_in_table_list);
+ if (table && table->pos_in_table_list) { // if SELECT
+#if MYSQL_VERSION_ID > 100200
+ Switch_to_definer_security_ctx backup_ctx(thd, table->pos_in_table_list);
+#endif // VERSION_ID > 100200
return check_global_access(thd, FILE_ACL);
- }
- else
+ } else
return check_global_access(thd, FILE_ACL);
case TAB_ODBC:
case TAB_JDBC:
@@ -4528,7 +4528,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
case TAB_VIR:
// This is temporary until a solution is found
return false;
- } // endswitch type
+ } // endswitch type
my_printf_error(ER_UNKNOWN_ERROR, "check_privileges failed", MYF(0));
return true;
@@ -5882,7 +5882,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
} else switch (ttp) {
case TAB_DBF:
- qrp= DBFColumns(g, dpath, fn, fnc == FNC_COL);
+ qrp= DBFColumns(g, dpath, fn, topt, fnc == FNC_COL);
break;
#if defined(ODBC_SUPPORT)
case TAB_ODBC:
@@ -6733,11 +6733,6 @@ int ha_connect::create(const char *name, TABLE *table_arg,
PCSZ m= GetListOption(g, "Mulentries", options->oplist, "NO");
bool mul= *m == '1' || *m == 'Y' || *m == 'y' || !stricmp(m, "ON");
- if (!entry && !mul) {
- my_message(ER_UNKNOWN_ERROR, "Missing entry name", MYF(0));
- DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
- } // endif entry
-
strcat(strcat(strcpy(dbpath, "./"), table->s->db.str), "/");
PlugSetPath(zbuf, options->filename, dbpath);
PlugSetPath(buf, fn, dbpath);
diff --git a/storage/connect/mongo.cpp b/storage/connect/mongo.cpp
index 53e2bf377c4..bd3d3b893c1 100644
--- a/storage/connect/mongo.cpp
+++ b/storage/connect/mongo.cpp
@@ -380,7 +380,6 @@ MGODEF::MGODEF(void)
Uri = NULL;
Colist = NULL;
Filter = NULL;
- Level = 0;
Base = 0;
Version = 0;
Pipe = false;
diff --git a/storage/connect/mongo.h b/storage/connect/mongo.h
index 97c391a217f..dcefac372c0 100644
--- a/storage/connect/mongo.h
+++ b/storage/connect/mongo.h
@@ -82,7 +82,6 @@ protected:
PSZ Wrapname; /* Java wrapper name */
PCSZ Colist; /* Options list */
PCSZ Filter; /* Filtering query */
- int Level; /* Used for catalog table */
int Base; /* The array index base */
int Version; /* The Java driver version */
bool Pipe; /* True is Colist is a pipeline */
diff --git a/storage/connect/plgxml.cpp b/storage/connect/plgxml.cpp
index f3d3a010266..8c5cc261899 100644
--- a/storage/connect/plgxml.cpp
+++ b/storage/connect/plgxml.cpp
@@ -49,7 +49,7 @@ bool XMLDOCUMENT::InitZip(PGLOBAL g, PCSZ entry)
{
#if defined(ZIP_SUPPORT)
bool mul = (entry) ? strchr(entry, '*') || strchr(entry, '?') : false;
- zip = new(g) UNZIPUTL(entry, mul);
+ zip = new(g) UNZIPUTL(entry, NULL, mul);
return zip == NULL;
#else // !ZIP_SUPPORT
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
diff --git a/storage/connect/tabcmg.cpp b/storage/connect/tabcmg.cpp
index b9b7f6e4b60..f2ff721627c 100644
--- a/storage/connect/tabcmg.cpp
+++ b/storage/connect/tabcmg.cpp
@@ -26,6 +26,8 @@
#include "tabmul.h"
#include "filter.h"
+PQRYRES MGOColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt, bool info);
+
/* -------------------------- Class CMGDISC -------------------------- */
/***********************************************************************/
diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp
index 8efe2aad702..b3147bb7357 100644
--- a/storage/connect/tabdos.cpp
+++ b/storage/connect/tabdos.cpp
@@ -1,11 +1,11 @@
/************* TabDos C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABDOS */
/* ------------- */
-/* Version 4.9.4 */
+/* Version 4.9.5 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2019 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2020 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -359,7 +359,26 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode)
/* Allocate table and file processing class of the proper type. */
/* Column blocks will be allocated only when needed. */
/*********************************************************************/
- if (Zipped) {
+ if (Recfm == RECFM_DBF) {
+ if (Catfunc == FNC_NO) {
+ if (Zipped) {
+ if (mode == MODE_READ || mode == MODE_ANY || mode == MODE_ALTER) {
+ txfp = new(g) UZDFAM(this);
+ } else {
+ strcpy(g->Message, "Zipped DBF tables are read only");
+ return NULL;
+ } // endif's mode
+
+ } else if (map)
+ txfp = new(g) DBMFAM(this);
+ else
+ txfp = new(g) DBFFAM(this);
+
+ tdbp = new(g) TDBFIX(this, txfp);
+ } else
+ tdbp = new(g) TDBDCL(this); // Catfunc should be 'C'
+
+ } else if (Zipped) {
#if defined(ZIP_SUPPORT)
if (Recfm == RECFM_VAR) {
if (mode == MODE_READ || mode == MODE_ANY || mode == MODE_ALTER) {
@@ -389,17 +408,6 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode)
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
return NULL;
#endif // !ZIP_SUPPORT
- } else if (Recfm == RECFM_DBF) {
- if (Catfunc == FNC_NO) {
- if (map)
- txfp = new(g) DBMFAM(this);
- else
- txfp = new(g) DBFFAM(this);
-
- tdbp = new(g) TDBFIX(this, txfp);
- } else // Catfunc should be 'C'
- tdbp = new(g) TDBDCL(this);
-
} else if (Recfm != RECFM_VAR && Compressed < 2) {
if (Huge)
txfp = new(g) BGXFAM(this);
diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h
index 207a1277fce..80dfe63845d 100644
--- a/storage/connect/tabdos.h
+++ b/storage/connect/tabdos.h
@@ -30,6 +30,7 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
friend class DBFBASE;
friend class UNZIPUTL;
friend class JSONCOL;
+ friend class TDBDCL;
public:
// Constructor
DOSDEF(void);
diff --git a/storage/connect/tabfix.h b/storage/connect/tabfix.h
index 53c0af1c422..5f859a2bffe 100644
--- a/storage/connect/tabfix.h
+++ b/storage/connect/tabfix.h
@@ -98,18 +98,20 @@ class DllExport BINCOL : public DOSCOL {
/* This is the class declaration for the DBF columns catalog table. */
/***********************************************************************/
class TDBDCL : public TDBCAT {
- public:
- // Constructor
- TDBDCL(PDOSDEF tdp) : TDBCAT(tdp) {Fn = tdp->GetFn();}
+public:
+ // Constructor
+ TDBDCL(PDOSDEF tdp) : TDBCAT(tdp)
+ {Fn = tdp->GetFn(); Topt = tdp->GetTopt();}
- protected:
+protected:
// Specific routines
- virtual PQRYRES GetResult(PGLOBAL g)
- {return DBFColumns(g, ((PTABDEF)To_Def)->GetPath(), Fn, false);}
+ virtual PQRYRES GetResult(PGLOBAL g)
+ {return DBFColumns(g, ((PTABDEF)To_Def)->GetPath(), Fn, Topt, false);}
- // Members
+ // Members
PCSZ Fn; // The DBF file (path) name
- }; // end of class TDBOCL
+ PTOS Topt;
+}; // end of class TDBOCL
#endif // __TABFIX__
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index 7e8d6c8d9f0..3b0d458a7a6 100644
--- a/storage/connect/tabjson.cpp
+++ b/storage/connect/tabjson.cpp
@@ -739,6 +739,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
/***********************************************************************/
TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
{
+ G = NULL;
Top = NULL;
Row = NULL;
Val = NULL;
diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h
index 8721a2a5ab7..8c3f1013919 100644
--- a/storage/connect/tabjson.h
+++ b/storage/connect/tabjson.h
@@ -104,7 +104,6 @@ public:
PCSZ Xcol; /* Name of expandable column */
int Limit; /* Limit of multiple values */
int Pretty; /* Depends on file structure */
- int Level; /* Used for catalog table */
int Base; /* The array index base */
bool Strict; /* Strict syntax checking */
char Sep; /* The Jpath separator */
diff --git a/storage/connect/tabzip.cpp b/storage/connect/tabzip.cpp
index c026744dba8..d9c13e2a58a 100644
--- a/storage/connect/tabzip.cpp
+++ b/storage/connect/tabzip.cpp
@@ -23,6 +23,7 @@
#include "filamzip.h"
#include "resource.h" // for IDS_COLUMNS
#include "tabdos.h"
+#include "tabmul.h"
#include "tabzip.h"
/* -------------------------- Class ZIPDEF --------------------------- */
@@ -41,7 +42,14 @@ bool ZIPDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
PTDB ZIPDEF::GetTable(PGLOBAL g, MODE m)
{
- return new(g) TDBZIP(this);
+ PTDB tdbp = NULL;
+
+ tdbp = new(g) TDBZIP(this);
+
+ if (Multiple)
+ tdbp = new(g) TDBMUL(tdbp);
+
+ return tdbp;
} // end of GetTable
/* ------------------------------------------------------------------- */
@@ -108,7 +116,7 @@ int TDBZIP::Cardinality(PGLOBAL g)
Cardinal = (err == UNZ_OK) ? (int)ginfo.number_entry : 0;
} else
- Cardinal = 0;
+ Cardinal = 10; // Dummy for multiple tables
} // endif Cardinal
@@ -187,6 +195,7 @@ int TDBZIP::DeleteDB(PGLOBAL g, int irc)
void TDBZIP::CloseDB(PGLOBAL g)
{
close();
+ nexterr = UNZ_OK; // For multiple tables
Use = USE_READY; // Just to be clean
} // end of CloseDB
diff --git a/storage/connect/tabzip.h b/storage/connect/tabzip.h
index 32b15281f81..d36e4dc01d0 100644
--- a/storage/connect/tabzip.h
+++ b/storage/connect/tabzip.h
@@ -48,6 +48,8 @@ public:
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_ZIP;}
+ virtual PCSZ GetFile(PGLOBAL) {return zfn;}
+ virtual void SetFile(PGLOBAL, PCSZ fn) {zfn = fn;}
// Methods
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);