diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2017-01-17 19:39:49 +0100 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2017-01-17 19:39:49 +0100 |
commit | 82913b0e909a3b8f10138f7f7cc759301f4c2026 (patch) | |
tree | 16aee581e5484379ce433bb91c5638ab75e31a0d /storage/connect | |
parent | 43147681503299ccdf31e23e84dd39aeff52b2df (diff) | |
download | mariadb-git-82913b0e909a3b8f10138f7f7cc759301f4c2026.tar.gz |
Commit changes made for version 10.1
Diffstat (limited to 'storage/connect')
30 files changed, 1740 insertions, 185 deletions
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index 460d47bcf62..b57dcf1fb16 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -157,23 +157,22 @@ bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname) /* Returns valid: true if this is a table info. */ /***********************************************************************/ bool CntInfo(PGLOBAL g, PTDB tp, PXF info) - { - bool b; - PTDBDOS tdbp= (PTDBDOS)tp; +{ + if (tp) { + bool b = ((PTDBASE)tp)->GetFtype() == RECFM_NAF; + PTDBDOS tdbp = b ? NULL : (PTDBDOS)tp; - if (tdbp) { - b= tdbp->GetFtype() != RECFM_NAF; - info->data_file_length= (b) ? (ulonglong)tdbp->GetFileLength(g) : 0; + info->data_file_length = (b) ? 0 : (ulonglong)tdbp->GetFileLength(g); - if (!b || info->data_file_length) - info->records= (unsigned)tdbp->Cardinality(g); -// info->records= (unsigned)tdbp->GetMaxSize(g); + if (b || info->data_file_length) + info->records= (unsigned)tp->Cardinality(g); +// info->records= (unsigned)tp->GetMaxSize(g); else info->records= 0; // info->mean_rec_length= tdbp->GetLrecl(); info->mean_rec_length= 0; - info->data_file_name= (b) ? tdbp->GetFile(g) : NULL; + info->data_file_name= (b) ? NULL : tdbp->GetFile(g); return true; } else { info->data_file_length= 0; @@ -183,7 +182,7 @@ bool CntInfo(PGLOBAL g, PTDB tp, PXF info) return false; } // endif tdbp - } // end of CntInfo +} // end of CntInfo /***********************************************************************/ /* GetTDB: Get the table description block of a CONNECT table. */ diff --git a/storage/connect/domdoc.cpp b/storage/connect/domdoc.cpp index eb9660b439d..1622ec16c68 100644 --- a/storage/connect/domdoc.cpp +++ b/storage/connect/domdoc.cpp @@ -116,7 +116,9 @@ bool DOMDOC::ParseFile(PGLOBAL g, char *fn) // Parse an in memory document char *xdoc = GetMemDoc(g, fn); - b = (xdoc) ? (bool)Docp->loadXML((_bstr_t)xdoc) : false; + // This is not equivalent to load for UTF8 characters + // It is why get node content is not the same + b = (xdoc) ? (bool)Docp->loadXML((_bstr_t)xdoc) : false; } else // Load the document b = (bool)Docp->load((_bstr_t)fn); @@ -266,6 +268,7 @@ DOMNODE::DOMNODE(PXDOC dp, MSXML2::IXMLDOMNodePtr np) : XMLNODE(dp) Nodep = np; Ws = NULL; Len = 0; + Zip = (bool)dp->zip; } // end of DOMNODE constructor /******************************************************************/ @@ -316,8 +319,10 @@ RCODE DOMNODE::GetContent(PGLOBAL g, char *buf, int len) RCODE rc = RC_OK; // Nodep can be null for a missing HTML table column - if (Nodep) { - if (!WideCharToMultiByte(CP_UTF8, 0, Nodep->text, -1, + if (Nodep) { + if (Zip) { + strcpy(buf, Nodep->text); + } else if (!WideCharToMultiByte(CP_UTF8, 0, Nodep->text, -1, buf, len, NULL, NULL)) { DWORD lsr = GetLastError(); diff --git a/storage/connect/domdoc.h b/storage/connect/domdoc.h index cfec98a9422..7f269002d59 100644 --- a/storage/connect/domdoc.h +++ b/storage/connect/domdoc.h @@ -93,6 +93,7 @@ class DOMNODE : public XMLNODE { char Name[64]; WCHAR *Ws; int Len; + bool Zip; }; // end of class DOMNODE /******************************************************************/ diff --git a/storage/connect/filamap.cpp b/storage/connect/filamap.cpp index 94c562a9981..8fffaca3d06 100644 --- a/storage/connect/filamap.cpp +++ b/storage/connect/filamap.cpp @@ -5,7 +5,7 @@ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */ +/* (C) Copyright to the author Olivier BERTRAND 2005-2017 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -45,6 +45,7 @@ #include "maputil.h" #include "filamap.h" #include "tabdos.h" +#include "tabfmt.h" /* --------------------------- Class MAPFAM -------------------------- */ @@ -322,17 +323,20 @@ int MAPFAM::ReadBuffer(PGLOBAL g) int rc, len; // Are we at the end of the memory - if (Mempos >= Top) + if (Mempos >= Top) { if ((rc = GetNext(g)) != RC_OK) return rc; + else if (Tdbp->GetAmType() == TYPE_AM_CSV && ((PTDBCSV)Tdbp)->Header) + if ((rc = SkipRecord(g, true)) != RC_OK) + return rc; + + } // endif Mempos if (!Placed) { /*******************************************************************/ /* Record file position in case of UPDATE or DELETE. */ /*******************************************************************/ - int rc; - next: Fpos = Mempos; CurBlk = (int)Rows++; diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index a4557facbd8..8b9d436d626 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -281,15 +281,25 @@ PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info) /************************************************************************/ switch (thisfield.Type) { case 'C': // Characters - case 'L': // Logical 'T' or 'F' - type = TYPE_STRING; + case 'L': // Logical 'T' or 'F' or space + type = TYPE_STRING; + break; + case 'M': // Memo a .DBT block number + case 'B': // Binary a .DBT block number + case 'G': // Ole a .DBT block number + type = TYPE_STRING; break; + //case 'I': // Long + //case '+': // Autoincrement + // type = TYPE_INT; + // break; case 'N': type = (thisfield.Decimals) ? TYPE_DOUBLE : (len > 10) ? TYPE_BIGINT : TYPE_INT; break; - case 'F': - type = TYPE_DOUBLE; + case 'F': // Float + //case 'O': // Double + type = TYPE_DOUBLE; break; case 'D': type = TYPE_DATE; // Is this correct ??? @@ -441,6 +451,7 @@ int DBFFAM::Cardinality(PGLOBAL g) if (Accept) { Lrecl = rln; + Blksize = Nrec * rln; PushWarning(g, Tdbp); } else return -1; diff --git a/storage/connect/filamgz.cpp b/storage/connect/filamgz.cpp index 07242ea633c..dc6f277ee27 100644 --- a/storage/connect/filamgz.cpp +++ b/storage/connect/filamgz.cpp @@ -724,20 +724,20 @@ void ZBKFAM::Rewind(void) /***********************************************************************/ /* Constructors. */ /***********************************************************************/ -ZIXFAM::ZIXFAM(PDOSDEF tdp) : ZBKFAM(tdp) +GZXFAM::GZXFAM(PDOSDEF tdp) : ZBKFAM(tdp) { //Block = tdp->GetBlock(); //Last = tdp->GetLast(); Nrec = (tdp->GetElemt()) ? tdp->GetElemt() : DOS_BUFF_LEN; Blksize = Nrec * Lrecl; - } // end of ZIXFAM standard constructor + } // end of GZXFAM standard constructor /***********************************************************************/ /* ZIX Cardinality: returns table cardinality in number of rows. */ /* This function can be called with a null argument to test the */ /* availability of Cardinality implementation (1 yes, 0 no). */ /***********************************************************************/ -int ZIXFAM::Cardinality(PGLOBAL g) +int GZXFAM::Cardinality(PGLOBAL g) { if (Last) return (g) ? (int)((Block - 1) * Nrec + Last) : 1; @@ -750,7 +750,7 @@ int ZIXFAM::Cardinality(PGLOBAL g) /* Allocate the line buffer. For mode Delete a bigger buffer has to */ /* be allocated because is it also used to move lines into the file. */ /***********************************************************************/ -bool ZIXFAM::AllocateBuffer(PGLOBAL g) +bool GZXFAM::AllocateBuffer(PGLOBAL g) { Buflen = Blksize; To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen); @@ -788,7 +788,7 @@ bool ZIXFAM::AllocateBuffer(PGLOBAL g) /***********************************************************************/ /* ReadBuffer: Read one line from a compressed text file. */ /***********************************************************************/ -int ZIXFAM::ReadBuffer(PGLOBAL g) +int GZXFAM::ReadBuffer(PGLOBAL g) { int n, rc = RC_OK; @@ -850,7 +850,7 @@ int ZIXFAM::ReadBuffer(PGLOBAL g) /* WriteDB: Data Base write routine for ZDOS access method. */ /* Update is not possible without using a temporary file (NIY). */ /***********************************************************************/ -int ZIXFAM::WriteBuffer(PGLOBAL g) +int GZXFAM::WriteBuffer(PGLOBAL g) { /*********************************************************************/ /* In Insert mode, blocs are added sequentialy to the file end. */ diff --git a/storage/connect/filamgz.h b/storage/connect/filamgz.h index d667fdddcc2..7a00c0d4bc7 100644 --- a/storage/connect/filamgz.h +++ b/storage/connect/filamgz.h @@ -12,7 +12,7 @@ typedef class GZFAM *PGZFAM; typedef class ZBKFAM *PZBKFAM; -typedef class ZIXFAM *PZIXFAM; +typedef class GZXFAM *PZIXFAM; typedef class ZLBFAM *PZLBFAM; /***********************************************************************/ @@ -101,16 +101,16 @@ class DllExport ZBKFAM : public GZFAM { /* length files compressed using the gzip library functions. */ /* The file is always accessed by block. */ /***********************************************************************/ -class DllExport ZIXFAM : public ZBKFAM { +class DllExport GZXFAM : public ZBKFAM { public: // Constructor - ZIXFAM(PDOSDEF tdp); - ZIXFAM(PZIXFAM txfp) : ZBKFAM(txfp) {} + GZXFAM(PDOSDEF tdp); + GZXFAM(PZIXFAM txfp) : ZBKFAM(txfp) {} // Implementation virtual int GetNextPos(void) {return 0;} virtual PTXF Duplicate(PGLOBAL g) - {return (PTXF)new(g) ZIXFAM(this);} + {return (PTXF)new(g) GZXFAM(this);} // Methods virtual int Cardinality(PGLOBAL g); @@ -120,7 +120,7 @@ class DllExport ZIXFAM : public ZBKFAM { protected: // No additional Members - }; // end of class ZIXFAM + }; // end of class GZXFAM /***********************************************************************/ /* This is the DOS/UNIX Access Method class declaration for PlugDB */ diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp index 65013e170e4..9abb2602b56 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.0 */ +/* Version 1.1 */ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2016 */ +/* (C) Copyright to the author Olivier BERTRAND 2016-2017 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -19,13 +19,16 @@ #include "my_global.h" #if !defined(__WIN__) #if defined(UNIX) +#include <fnmatch.h> #include <errno.h> +#include <dirent.h> #include <unistd.h> #else // !UNIX #include <io.h> #endif // !UNIX #include <fcntl.h> #endif // !__WIN__ +#include <time.h> /***********************************************************************/ /* Include application header files: */ @@ -40,12 +43,346 @@ //#include "tabzip.h" #include "filamzip.h" +#define WRITEBUFFERSIZE (16384) + +bool ZipLoadFile(PGLOBAL g, char *zfn, char *fn, char *entry, bool append, bool mul); + +/***********************************************************************/ +/* Compress a file in zip when creating a table. */ +/***********************************************************************/ +static bool ZipFile(PGLOBAL g, ZIPUTIL *zutp, char *fn, char *entry, char *buf) +{ + int rc = RC_OK, size_read, size_buf = WRITEBUFFERSIZE; + FILE *fin; + + if (zutp->addEntry(g, entry)) + return true; + else if (!(fin = fopen(fn, "rb"))) { + sprintf(g->Message, "error in opening %s for reading", fn); + return true; + } // endif fin + + do { + size_read = (int)fread(buf, 1, size_buf, fin); + + if (size_read < size_buf && feof(fin) == 0) { + sprintf(g->Message, "error in reading %s", fn); + rc = RC_FX; + } // endif size_read + + if (size_read > 0) { + rc = zutp->writeEntry(g, buf, size_read); + + if (rc == RC_FX) + sprintf(g->Message, "error in writing %s in the zipfile", fn); + + } // endif size_read + + } while (rc == RC_OK && size_read > 0); + + fclose(fin); + zutp->closeEntry(); + return rc != RC_OK; +} // end of ZipFile + +/***********************************************************************/ +/* Find and Compress several files in zip when creating a table. */ +/***********************************************************************/ +static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, char *pat, char *buf) +{ + char filename[_MAX_PATH]; + int rc; + + /*********************************************************************/ + /* pat is a multiple file name with wildcard characters */ + /*********************************************************************/ + strcpy(filename, pat); + +#if defined(__WIN__) + char drive[_MAX_DRIVE], direc[_MAX_DIR]; + WIN32_FIND_DATA FileData; + HANDLE hSearch; + + _splitpath(filename, drive, direc, NULL, NULL); + + // Start searching files in the target directory. + hSearch = FindFirstFile(filename, &FileData); + + if (hSearch == INVALID_HANDLE_VALUE) { + rc = GetLastError(); + + if (rc != ERROR_FILE_NOT_FOUND) { + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), 0, (LPTSTR)&filename, sizeof(filename), NULL); + sprintf(g->Message, MSG(BAD_FILE_HANDLE), filename); + return true; + } else { + strcpy(g->Message, "Cannot find any file to load"); + return true; + } // endif rc + + } // endif hSearch + + while (true) { + if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + strcat(strcat(strcpy(filename, drive), direc), FileData.cFileName); + + if (ZipFile(g, zutp, filename, FileData.cFileName, buf)) { + FindClose(hSearch); + return true; + } // endif ZipFile + + } // endif dwFileAttributes + + if (!FindNextFile(hSearch, &FileData)) { + rc = GetLastError(); + + if (rc != ERROR_NO_MORE_FILES) { + sprintf(g->Message, MSG(NEXT_FILE_ERROR), rc); + FindClose(hSearch); + return true; + } // endif rc + + break; + } // endif FindNextFile + + } // endwhile n + + // Close the search handle. + if (!FindClose(hSearch)) { + strcpy(g->Message, MSG(SRCH_CLOSE_ERR)); + return true; + } // endif FindClose + +#else // !__WIN__ + struct stat fileinfo; + char fn[FN_REFLEN], direc[FN_REFLEN], pattern[FN_HEADLEN], ftype[FN_EXTLEN]; + DIR *dir; + struct dirent *entry; + + _splitpath(filename, NULL, direc, pattern, ftype); + strcat(pattern, ftype); + + // Start searching files in the target directory. + if (!(dir = opendir(direc))) { + sprintf(g->Message, MSG(BAD_DIRECTORY), direc, strerror(errno)); + return true; + } // endif dir + + while ((entry = readdir(dir))) { + strcat(strcpy(fn, direc), entry->d_name); + + if (lstat(fn, &fileinfo) < 0) { + sprintf(g->Message, "%s: %s", fn, strerror(errno)); + return true; + } else if (!S_ISREG(fileinfo.st_mode)) + continue; // Not a regular file (should test for links) + + /*******************************************************************/ + /* Test whether the file name matches the table name filter. */ + /*******************************************************************/ + if (fnmatch(pattern, entry->d_name, 0)) + continue; // Not a match + + strcat(strcpy(filename, direc), entry->d_name); + + if (ZipFile(g, zutp, filename, entry->d_name, buf)) { + closedir(dir); + return true; + } // endif ZipFile + + } // endwhile readdir + + // Close the dir handle. + closedir(dir); +#endif // !__WIN__ + + return false; +} // end of ZipFiles + +/***********************************************************************/ +/* Load and Compress a file in zip when creating a table. */ +/***********************************************************************/ +bool ZipLoadFile(PGLOBAL g, char *zfn, char *fn, char *entry, bool append, bool mul) +{ + char *buf; + bool err; + ZIPUTIL *zutp = new(g) ZIPUTIL(NULL); + + if (zutp->open(g, zfn, append)) + return true; + + buf = (char*)PlugSubAlloc(g, NULL, WRITEBUFFERSIZE); + + if (mul) + err = ZipFiles(g, zutp, fn, buf); + else + err = ZipFile(g, zutp, fn, entry, buf); + + zutp->close(); + return err; +} // end of ZipLoadFile + /* -------------------------- class ZIPUTIL -------------------------- */ /***********************************************************************/ /* Constructors. */ /***********************************************************************/ -ZIPUTIL::ZIPUTIL(PSZ tgt, bool mul) +ZIPUTIL::ZIPUTIL(PSZ tgt) +{ + zipfile = NULL; + target = tgt; + fp = NULL; + entryopen = false; +} // end of ZIPUTIL standard constructor + +#if 0 +ZIPUTIL::ZIPUTIL(ZIPUTIL *zutp) +{ + zipfile = zutp->zipfile; + target = zutp->target; + fp = zutp->fp; + entryopen = zutp->entryopen; +} // end of UNZIPUTL copy constructor +#endif // 0 + +/***********************************************************************/ +/* Fill the zip time structure */ +/* param: tmZip time structure to be filled */ +/***********************************************************************/ +void ZIPUTIL::getTime(tm_zip& tmZip) +{ + time_t rawtime; + time(&rawtime); + struct tm *timeinfo = localtime(&rawtime); + tmZip.tm_sec = timeinfo->tm_sec; + tmZip.tm_min = timeinfo->tm_min; + tmZip.tm_hour = timeinfo->tm_hour; + tmZip.tm_mday = timeinfo->tm_mday; + tmZip.tm_mon = timeinfo->tm_mon; + tmZip.tm_year = timeinfo->tm_year; +} // end of getTime + +/***********************************************************************/ +/* open a zip file for deflate. */ +/* param: filename path and the filename of the zip file to open. */ +/* append: set true to append the zip file */ +/* return: true if open, false otherwise. */ +/***********************************************************************/ +bool ZIPUTIL::open(PGLOBAL g, char *filename, bool append) +{ + if (!zipfile && !(zipfile = zipOpen64(filename, + append ? APPEND_STATUS_ADDINZIP + : APPEND_STATUS_CREATE))) + sprintf(g->Message, "Zipfile open error on %s", filename); + + return (zipfile == NULL); +} // end of open + +/***********************************************************************/ +/* Close the zip file. */ +/***********************************************************************/ +void ZIPUTIL::close() +{ + if (zipfile) { + closeEntry(); + zipClose(zipfile, 0); + zipfile = NULL; + } // endif zipfile + +} // end of close + +/***********************************************************************/ +/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */ +/***********************************************************************/ +bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, char *fn, bool append) +{ + /*********************************************************************/ + /* The file will be compressed. */ + /*********************************************************************/ + if (mode == MODE_INSERT) { + bool b = open(g, fn, append); + + if (!b) { + if (addEntry(g, target)) + return true; + + /*****************************************************************/ + /* 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, fn); + fp->Next = dbuserp->Openlist; + dbuserp->Openlist = fp; + fp->Count = 1; + fp->Length = 0; + fp->Memory = NULL; + fp->Mode = mode; + fp->File = this; + fp->Handle = 0; + } else + return true; + + } else { + strcpy(g->Message, "Only INSERT mode supported for ZIPPING files"); + return true; + } // endif mode + + return false; +} // end of OpenTableFile + +/***********************************************************************/ +/* Add target in zip file. */ +/***********************************************************************/ +bool ZIPUTIL::addEntry(PGLOBAL g, char *entry) +{ + //?? we dont need the stinking time + zip_fileinfo zi = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + getTime(zi.tmz_date); + target = entry; + + int err = zipOpenNewFileInZip(zipfile, target, &zi, + NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION); + + return !(entryopen = (err == ZIP_OK)); +} // end of addEntry + +/***********************************************************************/ +/* writeEntry: Deflate the buffer to the zip file. */ +/***********************************************************************/ +int ZIPUTIL::writeEntry(PGLOBAL g, char *buf, int len) +{ + if (zipWriteInFileInZip(zipfile, buf, len) < 0) { + sprintf(g->Message, "Error writing %s in the zipfile", target); + return RC_FX; + } // endif zipWriteInFileInZip + + return RC_OK; +} // end of writeEntry + +/***********************************************************************/ +/* Close the zip file. */ +/***********************************************************************/ +void ZIPUTIL::closeEntry() +{ + if (entryopen) { + zipCloseFileInZip(zipfile); + entryopen = false; + } // endif entryopen + +} // end of closeEntry + +/* ------------------------- class UNZIPUTL -------------------------- */ + +/***********************************************************************/ +/* Constructors. */ +/***********************************************************************/ +UNZIPUTL::UNZIPUTL(PSZ tgt, bool mul) { zipfile = NULL; target = tgt; @@ -62,10 +399,10 @@ ZIPUTIL::ZIPUTIL(PSZ tgt, bool mul) #else for (int i = 0; i < 256; ++i) mapCaseTable[i] = i; #endif -} // end of ZIPUTIL standard constructor +} // end of UNZIPUTL standard constructor #if 0 -ZIPUTIL::ZIPUTIL(PZIPUTIL zutp) +UNZIPUTL::UNZIPUTL(PZIPUTIL zutp) { zipfile = zutp->zipfile; target = zutp->target; @@ -74,14 +411,14 @@ ZIPUTIL::ZIPUTIL(PZIPUTIL zutp) entryopen = zutp->entryopen; multiple = zutp->multiple; for (int i = 0; i < 256; ++i) mapCaseTable[i] = zutp->mapCaseTable[i]; -} // end of ZIPUTIL copy constructor +} // end of UNZIPUTL copy constructor #endif // 0 /***********************************************************************/ /* This code is the copyright property of Alessandro Felice Cantatore. */ /* http://xoomer.virgilio.it/acantato/dev/wildcard/wildmatch.html */ /***********************************************************************/ -bool ZIPUTIL::WildMatch(PSZ pat, PSZ str) { +bool UNZIPUTL::WildMatch(PSZ pat, PSZ str) { PSZ s, p; bool star = FALSE; @@ -97,7 +434,7 @@ loopStart: if (!*++pat) return TRUE; goto loopStart; default: - if (mapCaseTable[*s] != mapCaseTable[*p]) + if (mapCaseTable[(uint)*s] != mapCaseTable[(uint)*p]) goto starCheck; break; } /* endswitch */ @@ -116,7 +453,7 @@ starCheck: /* param: filename path and the filename of the zip file to open. */ /* return: true if open, false otherwise. */ /***********************************************************************/ -bool ZIPUTIL::open(PGLOBAL g, char *filename) +bool UNZIPUTL::open(PGLOBAL g, char *filename) { if (!zipfile && !(zipfile = unzOpen64(filename))) sprintf(g->Message, "Zipfile open error on %s", filename); @@ -127,7 +464,7 @@ bool ZIPUTIL::open(PGLOBAL g, char *filename) /***********************************************************************/ /* Close the zip file. */ /***********************************************************************/ -void ZIPUTIL::close() +void UNZIPUTL::close() { if (zipfile) { closeEntry(); @@ -140,7 +477,7 @@ void ZIPUTIL::close() /***********************************************************************/ /* Find next entry matching target pattern. */ /***********************************************************************/ -int ZIPUTIL::findEntry(PGLOBAL g, bool next) +int UNZIPUTL::findEntry(PGLOBAL g, bool next) { int rc; @@ -151,7 +488,7 @@ int ZIPUTIL::findEntry(PGLOBAL g, bool next) if (rc == UNZ_END_OF_LIST_OF_FILE) return RC_EF; else if (rc != UNZ_OK) { - sprintf(g->Message, "unzGoToNextFile rc = ", rc); + sprintf(g->Message, "unzGoToNextFile rc = %d", rc); return RC_FX; } // endif rc @@ -183,7 +520,7 @@ int ZIPUTIL::findEntry(PGLOBAL g, bool next) /***********************************************************************/ /* Get the next used entry. */ /***********************************************************************/ -int ZIPUTIL::nextEntry(PGLOBAL g) +int UNZIPUTL::nextEntry(PGLOBAL g) { if (multiple) { int rc; @@ -206,7 +543,7 @@ int ZIPUTIL::nextEntry(PGLOBAL g) /***********************************************************************/ /* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */ /***********************************************************************/ -bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, char *fn) +bool UNZIPUTL::OpenTable(PGLOBAL g, MODE mode, char *fn) { /*********************************************************************/ /* The file will be decompressed into virtual memory. */ @@ -261,14 +598,14 @@ bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, char *fn) fp->Memory = memory; fp->Mode = mode; fp->File = this; - fp->Handle = NULL; + fp->Handle = 0; } // endif fp } else return true; } else { - strcpy(g->Message, "Only READ mode supported for ZIP files"); + strcpy(g->Message, "Only READ mode supported for ZIPPED tables"); return true; } // endif mode @@ -278,7 +615,7 @@ bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, char *fn) /***********************************************************************/ /* Open target in zip file. */ /***********************************************************************/ -bool ZIPUTIL::openEntry(PGLOBAL g) +bool UNZIPUTL::openEntry(PGLOBAL g) { int rc; @@ -297,7 +634,7 @@ bool ZIPUTIL::openEntry(PGLOBAL g) memory = new char[size + 1]; if ((rc = unzReadCurrentFile(zipfile, memory, size)) < 0) { - sprintf(g->Message, "unzReadCurrentFile rc = ", rc); + sprintf(g->Message, "unzReadCurrentFile rc = %d", rc); unzCloseCurrentFile(zipfile); free(memory); memory = NULL; @@ -316,7 +653,7 @@ bool ZIPUTIL::openEntry(PGLOBAL g) /***********************************************************************/ /* Close the zip file. */ /***********************************************************************/ -void ZIPUTIL::closeEntry() +void UNZIPUTL::closeEntry() { if (entryopen) { unzCloseCurrentFile(zipfile); @@ -330,36 +667,29 @@ void ZIPUTIL::closeEntry() } // end of closeEntry -/* -------------------------- class ZIPFAM --------------------------- */ +/* -------------------------- class UNZFAM --------------------------- */ /***********************************************************************/ /* Constructors. */ /***********************************************************************/ -ZIPFAM::ZIPFAM(PDOSDEF tdp) : MAPFAM(tdp) +UNZFAM::UNZFAM(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 +} // end of UNZFAM standard constructor -ZIPFAM::ZIPFAM(PDOSDEF tdp, PZPXFAM txfp) : MAPFAM(tdp) +UNZFAM::UNZFAM(PUNZFAM txfp) : MAPFAM(txfp) { zutp = txfp->zutp; target = txfp->target; mul = txfp->mul; -} // end of ZIPFAM constructor used in ResetTableOpt +} // end of UNZFAM copy constructor /***********************************************************************/ /* ZIP GetFileLength: returns file size in number of bytes. */ /***********************************************************************/ -int ZIPFAM::GetFileLength(PGLOBAL g) +int UNZFAM::GetFileLength(PGLOBAL g) { int len = (zutp && zutp->entryopen) ? Top - Memory : TXTFAM::GetFileLength(g) * 3; @@ -373,7 +703,7 @@ int ZIPFAM::GetFileLength(PGLOBAL g) /***********************************************************************/ /* ZIP Cardinality: return the number of rows if possible. */ /***********************************************************************/ -int ZIPFAM::Cardinality(PGLOBAL g) +int UNZFAM::Cardinality(PGLOBAL g) { if (!g) return 1; @@ -388,7 +718,7 @@ int ZIPFAM::Cardinality(PGLOBAL g) /***********************************************************************/ /* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */ /***********************************************************************/ -bool ZIPFAM::OpenTableFile(PGLOBAL g) +bool UNZFAM::OpenTableFile(PGLOBAL g) { char filename[_MAX_PATH]; MODE mode = Tdbp->GetMode(); @@ -396,7 +726,7 @@ bool ZIPFAM::OpenTableFile(PGLOBAL g) /*********************************************************************/ /* Allocate the ZIP utility class. */ /*********************************************************************/ - zutp = new(g) ZIPUTIL(target, mul); + zutp = new(g) UNZIPUTL(target, mul); // We used the file name relative to recorded datapath PlugSetPath(filename, To_File, Tdbp->GetPath()); @@ -415,7 +745,7 @@ bool ZIPFAM::OpenTableFile(PGLOBAL g) /***********************************************************************/ /* GetNext: go to next entry. */ /***********************************************************************/ -int ZIPFAM::GetNext(PGLOBAL g) +int UNZFAM::GetNext(PGLOBAL g) { int rc = zutp->nextEntry(g); @@ -431,7 +761,7 @@ int ZIPFAM::GetNext(PGLOBAL g) /***********************************************************************/ /* ReadBuffer: Read one line for a ZIP file. */ /***********************************************************************/ -int ZIPFAM::ReadBuffer(PGLOBAL g) +int UNZFAM::ReadBuffer(PGLOBAL g) { int rc, len; @@ -497,37 +827,37 @@ int ZIPFAM::ReadBuffer(PGLOBAL g) /***********************************************************************/ /* Table file close routine for MAP access method. */ /***********************************************************************/ -void ZIPFAM::CloseTableFile(PGLOBAL g, bool) +void UNZFAM::CloseTableFile(PGLOBAL g, bool) { close(); } // end of CloseTableFile #endif // 0 -/* -------------------------- class ZPXFAM --------------------------- */ +/* -------------------------- class UZXFAM --------------------------- */ /***********************************************************************/ /* Constructors. */ /***********************************************************************/ -ZPXFAM::ZPXFAM(PDOSDEF tdp) : MPXFAM(tdp) +UZXFAM::UZXFAM(PDOSDEF tdp) : MPXFAM(tdp) { zutp = NULL; target = tdp->GetEntry(); mul = tdp->GetMul(); //Lrecl = tdp->GetLrecl(); -} // end of ZPXFAM standard constructor +} // end of UZXFAM standard constructor -ZPXFAM::ZPXFAM(PZPXFAM txfp) : MPXFAM(txfp) +UZXFAM::UZXFAM(PUZXFAM txfp) : MPXFAM(txfp) { zutp = txfp->zutp; target = txfp->target; mul = txfp->mul; //Lrecl = txfp->Lrecl; -} // end of ZPXFAM copy constructor +} // end of UZXFAM copy constructor /***********************************************************************/ /* ZIP GetFileLength: returns file size in number of bytes. */ /***********************************************************************/ -int ZPXFAM::GetFileLength(PGLOBAL g) +int UZXFAM::GetFileLength(PGLOBAL g) { int len; @@ -545,7 +875,7 @@ int ZPXFAM::GetFileLength(PGLOBAL g) /***********************************************************************/ /* ZIP Cardinality: return the number of rows if possible. */ /***********************************************************************/ -int ZPXFAM::Cardinality(PGLOBAL g) +int UZXFAM::Cardinality(PGLOBAL g) { if (!g) return 1; @@ -566,7 +896,7 @@ int ZPXFAM::Cardinality(PGLOBAL g) /***********************************************************************/ /* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */ /***********************************************************************/ -bool ZPXFAM::OpenTableFile(PGLOBAL g) +bool UZXFAM::OpenTableFile(PGLOBAL g) { // May have been already opened in GetFileLength if (!zutp || !zutp->zipfile) { @@ -577,7 +907,7 @@ bool ZPXFAM::OpenTableFile(PGLOBAL g) /* Allocate the ZIP utility class. */ /*********************************************************************/ if (!zutp) - zutp = new(g)ZIPUTIL(target, mul); + zutp = new(g)UNZIPUTL(target, mul); // We used the file name relative to recorded datapath PlugSetPath(filename, To_File, Tdbp->GetPath()); @@ -600,7 +930,7 @@ bool ZPXFAM::OpenTableFile(PGLOBAL g) /***********************************************************************/ /* GetNext: go to next entry. */ /***********************************************************************/ -int ZPXFAM::GetNext(PGLOBAL g) +int UZXFAM::GetNext(PGLOBAL g) { int rc = zutp->nextEntry(g); @@ -620,3 +950,146 @@ int ZPXFAM::GetNext(PGLOBAL g) return RC_OK; } // end of GetNext +/* -------------------------- class ZIPFAM --------------------------- */ + +/***********************************************************************/ +/* Constructor. */ +/***********************************************************************/ +ZIPFAM::ZIPFAM(PDOSDEF tdp) : DOSFAM(tdp) +{ + zutp = NULL; + target = tdp->GetEntry(); + append = tdp->GetAppend(); +} // end of ZIPFAM standard constructor + +/***********************************************************************/ +/* 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); + + // We used the file name relative to recorded datapath + PlugSetPath(filename, To_File, Tdbp->GetPath()); + + if (!zutp->OpenTable(g, mode, filename, append)) { + To_Fb = zutp->fp; // Useful when closing + } else + return true; + + return AllocateBuffer(g); +} // end of OpenTableFile + +/***********************************************************************/ +/* ReadBuffer: Read one line for a ZIP file. */ +/***********************************************************************/ +int ZIPFAM::ReadBuffer(PGLOBAL g) +{ + strcpy(g->Message, "ReadBuffer should not been called when zipping"); + return RC_FX; +} // end of ReadBuffer + +/***********************************************************************/ +/* WriteBuffer: Deflate the buffer to the zip file. */ +/***********************************************************************/ +int ZIPFAM::WriteBuffer(PGLOBAL g) +{ + int len; + + // Prepare to write the new line + strcat(strcpy(To_Buf, Tdbp->GetLine()), (Bin) ? CrLf : "\n"); + len = strchr(To_Buf, '\n') - To_Buf + 1; + return zutp->writeEntry(g, To_Buf, len); +} // end of WriteBuffer + +/***********************************************************************/ +/* Table file close routine for ZIP access method. */ +/***********************************************************************/ +void ZIPFAM::CloseTableFile(PGLOBAL g, bool) +{ + To_Fb->Count = 0; + zutp->close(); +} // end of CloseTableFile + +/* -------------------------- class ZPXFAM --------------------------- */ + +/***********************************************************************/ +/* Constructor. */ +/***********************************************************************/ +ZPXFAM::ZPXFAM(PDOSDEF tdp) : FIXFAM(tdp) +{ + zutp = NULL; + target = tdp->GetEntry(); + append = tdp->GetAppend(); + //Lrecl = tdp->GetLrecl(); +} // end of UZXFAM standard constructor + +/***********************************************************************/ +/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */ +/***********************************************************************/ +bool ZPXFAM::OpenTableFile(PGLOBAL g) +{ + char filename[_MAX_PATH]; + MODE mode = Tdbp->GetMode(); + + /*********************************************************************/ + /* Allocate the ZIP utility class. */ + /*********************************************************************/ + zutp = new(g) ZIPUTIL(target); + + // We used the file name relative to recorded datapath + PlugSetPath(filename, To_File, Tdbp->GetPath()); + + if (!zutp->OpenTable(g, mode, filename, append)) { + To_Fb = zutp->fp; // Useful when closing + } else + return true; + + return AllocateBuffer(g); +} // end of OpenTableFile + +/***********************************************************************/ +/* WriteBuffer: Deflate the buffer to the zip file. */ +/***********************************************************************/ +int ZPXFAM::WriteBuffer(PGLOBAL g) +{ + /*********************************************************************/ + /* In Insert mode, we write only full blocks. */ + /*********************************************************************/ + if (++CurNum != Rbuf) { + Tdbp->IncLine(Lrecl); // Used by DOSCOL functions + return RC_OK; + } // endif CurNum + + // Now start the compress process. + if (zutp->writeEntry(g, To_Buf, Lrecl * Rbuf) != RC_OK) { + Closing = true; + return RC_FX; + } // endif writeEntry + + CurBlk++; + CurNum = 0; + Tdbp->SetLine(To_Buf); + return RC_OK; +} // end of WriteBuffer + +/***********************************************************************/ +/* Table file close routine for ZIP access method. */ +/***********************************************************************/ +void ZPXFAM::CloseTableFile(PGLOBAL g, bool) +{ + if (CurNum && !Closing) { + // Some more inserted lines remain to be written + Rbuf = CurNum--; + WriteBuffer(g); + } // endif Curnum + + To_Fb->Count = 0; + zutp->close(); +} // end of CloseTableFile diff --git a/storage/connect/filamzip.h b/storage/connect/filamzip.h index 9312fb2f70e..3160703bd20 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.0 */ +/* Name: filamzip.h Version 1.1 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2016 */ +/* (C) Copyright to the author Olivier BERTRAND 2016-2017 */ /* */ /* This file contains the ZIP file access method classes declares. */ /***********************************************************************/ @@ -10,10 +10,14 @@ #include "block.h" #include "filamap.h" +#include "filamfix.h" +#include "zip.h" #include "unzip.h" #define DLLEXPORT extern "C" +typedef class UNZFAM *PUNZFAM; +typedef class UZXFAM *PUZXFAM; typedef class ZIPFAM *PZIPFAM; typedef class ZPXFAM *PZPXFAM; @@ -21,16 +25,50 @@ typedef class ZPXFAM *PZPXFAM; /* This is the ZIP utility fonctions class. */ /***********************************************************************/ class DllExport ZIPUTIL : public BLOCK { -public: + public: // Constructor - ZIPUTIL(PSZ tgt, bool mul); -//ZIPUTIL(ZIPUTIL *zutp); + ZIPUTIL(PSZ tgt); + //ZIPUTIL(ZIPUTIL *zutp); // Implementation -//PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)ZIPFAM(this); } + //PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)UNZFAM(this); } // Methods - virtual bool OpenTable(PGLOBAL g, MODE mode, char *fn); + bool OpenTable(PGLOBAL g, MODE mode, char *fn, bool append); + bool open(PGLOBAL g, char *fn, bool append); + bool addEntry(PGLOBAL g, char *entry); + void close(void); + void closeEntry(void); + int writeEntry(PGLOBAL g, char *buf, int len); + void getTime(tm_zip& tmZip); + + // Members + zipFile 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 ZIPUTIL + +/***********************************************************************/ +/* This is the unZIP utility fonctions class. */ +/***********************************************************************/ +class DllExport UNZIPUTL : public BLOCK { + public: + // Constructor + UNZIPUTL(PSZ tgt, bool mul); +//UNZIPUTL(UNZIPUTL *zutp); + + // Implementation +//PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)UNZFAM(this); } + + // Methods + bool OpenTable(PGLOBAL g, MODE mode, char *fn); bool open(PGLOBAL g, char *fn); bool openEntry(PGLOBAL g); void close(void); @@ -50,68 +88,120 @@ public: bool entryopen; // True when open current entry char fn[FILENAME_MAX]; // The current entry file name char mapCaseTable[256]; -}; // end of ZIPFAM +}; // end of UNZIPUTL /***********************************************************************/ -/* This is the ZIP file access method. */ +/* This is the unzip file access method. */ /***********************************************************************/ -class DllExport ZIPFAM : public MAPFAM { - friend class ZPXFAM; -public: +class DllExport UNZFAM : public MAPFAM { +//friend class UZXFAM; + public: // Constructors - ZIPFAM(PDOSDEF tdp); - ZIPFAM(PZIPFAM txfp); - ZIPFAM(PDOSDEF tdp, PZPXFAM txfp); + UNZFAM(PDOSDEF tdp); + UNZFAM(PUNZFAM 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) UNZFAM(this);} // Methods virtual int Cardinality(PGLOBAL g); virtual int GetFileLength(PGLOBAL g); -//virtual int MaxBlkSize(PGLOBAL g, int s) {return s;} + //virtual int MaxBlkSize(PGLOBAL g, int s) {return s;} virtual bool OpenTableFile(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); + //virtual int ReadBuffer(PGLOBAL g); + //virtual int WriteBuffer(PGLOBAL g); + //virtual int DeleteRecords(PGLOBAL g, int irc); + //virtual void CloseTableFile(PGLOBAL g, bool abort); -protected: + protected: // Members - ZIPUTIL *zutp; - PSZ target; - bool mul; -}; // end of ZIPFAM + UNZIPUTL *zutp; + PSZ target; + bool mul; +}; // end of UNZFAM /***********************************************************************/ -/* This is the fixed ZIP file access method. */ +/* This is the fixed unzip file access method. */ /***********************************************************************/ -class DllExport ZPXFAM : public MPXFAM { - friend class ZIPFAM; -public: +class DllExport UZXFAM : public MPXFAM { +//friend class UNZFAM; + public: // Constructors - ZPXFAM(PDOSDEF tdp); - ZPXFAM(PZPXFAM txfp); + UZXFAM(PDOSDEF tdp); + UZXFAM(PUZXFAM txfp); // Implementation virtual AMT GetAmType(void) { return TYPE_AM_ZIP; } - virtual PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)ZPXFAM(this); } + virtual PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)UZXFAM(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); + //virtual int ReadBuffer(PGLOBAL g); + + protected: + // Members + UNZIPUTL *zutp; + PSZ target; + bool mul; +}; // end of UZXFAM + +/***********************************************************************/ +/* This is the zip file access method. */ +/***********************************************************************/ +class DllExport ZIPFAM : public DOSFAM { + public: + // Constructors + ZIPFAM(PDOSDEF tdp); + + // Implementation + virtual AMT GetAmType(void) {return TYPE_AM_ZIP;} + + // Methods + virtual int Cardinality(PGLOBAL g) {return 0;} + virtual int GetFileLength(PGLOBAL g) {return g ? 0 : 1;} + //virtual int MaxBlkSize(PGLOBAL g, int s) {return s;} + virtual bool OpenTableFile(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); + + protected: + // Members + ZIPUTIL *zutp; + PSZ target; + bool append; +}; // end of ZIPFAM + +/***********************************************************************/ +/* This is the fixed zip file access method. */ +/***********************************************************************/ +class DllExport ZPXFAM : public FIXFAM { + public: + // Constructors + ZPXFAM(PDOSDEF tdp); + + // Implementation + virtual AMT GetAmType(void) {return TYPE_AM_ZIP;} + + // Methods + virtual int Cardinality(PGLOBAL g) {return 0;} + virtual int GetFileLength(PGLOBAL g) {return g ? 0 : 1;} + virtual bool OpenTableFile(PGLOBAL g); + virtual int WriteBuffer(PGLOBAL g); + virtual void CloseTableFile(PGLOBAL g, bool abort); -protected: + protected: // Members ZIPUTIL *zutp; PSZ target; - bool mul; + bool append; }; // end of ZPXFAM #endif // __FILAMZIP_H diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 33f02d8338c..9b1689f6dd5 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -1,4 +1,4 @@ -/* Copyright (C) Olivier Bertrand 2004 - 2016 +/* Copyright (C) Olivier Bertrand 2004 - 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -171,9 +171,9 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.05.0001 December 13, 2016"; + char version[]= "Version 1.05.0002 January 08, 2017"; #if defined(__WIN__) - char compver[]= "Version 1.05.0001 " __DATE__ " " __TIME__; + char compver[]= "Version 1.05.0002 " __DATE__ " " __TIME__; char slash= '\\'; #else // !__WIN__ char slash= '/'; @@ -214,6 +214,7 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v); void PushWarning(PGLOBAL g, THD *thd, int level); bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host, const char *db, char *tab, const char *src, int port); +bool ZipLoadFile(PGLOBAL, char*, char*, char*, bool, bool); bool ExactInfo(void); USETEMP UseTemp(void); int GetConvSize(void); @@ -5173,7 +5174,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, TABLE_SHARE *table_s, HA_CREATE_INFO *create_info) { - char v=0, spc= ',', qch= 0; + char v=0; const char *fncn= "?"; const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src; const char *col, *ocl, *rnk, *pic, *fcl, *skc, *zfn; @@ -5225,8 +5226,6 @@ static int connect_assisted_discovery(handlerton *, THD* thd, fncn= topt->catfunc; fnc= GetFuncID(fncn); sep= topt->separator; - spc= (!sep) ? ',' : *sep; - qch= topt->qchar ? *topt->qchar : (signed)topt->quoted >= 0 ? '"' : 0; mul = (int)topt->multiple; tbl= topt->tablist; col= topt->colist; @@ -6267,21 +6266,26 @@ int ha_connect::create(const char *name, TABLE *table_arg, // Check for incompatible options if (options->sepindex) { my_message(ER_UNKNOWN_ERROR, - "SEPINDEX is incompatible with unspecified file name", - MYF(0)); + "SEPINDEX is incompatible with unspecified file name", MYF(0)); DBUG_RETURN(HA_ERR_UNSUPPORTED); - } else if (GetTypeID(options->type) == TAB_VEC) - if (!table->s->max_rows || options->split) { - my_printf_error(ER_UNKNOWN_ERROR, - "%s tables whose file name is unspecified cannot be split", - MYF(0), options->type); - DBUG_RETURN(HA_ERR_UNSUPPORTED); - } else if (options->header == 2) { - my_printf_error(ER_UNKNOWN_ERROR, - "header=2 is not allowed for %s tables whose file name is unspecified", - MYF(0), options->type); - DBUG_RETURN(HA_ERR_UNSUPPORTED); - } // endif's + } else if (GetTypeID(options->type) == TAB_VEC) { + if (!table->s->max_rows || options->split) { + my_printf_error(ER_UNKNOWN_ERROR, + "%s tables whose file name is unspecified cannot be split", + MYF(0), options->type); + DBUG_RETURN(HA_ERR_UNSUPPORTED); + } else if (options->header == 2) { + my_printf_error(ER_UNKNOWN_ERROR, + "header=2 is not allowed for %s tables whose file name is unspecified", + MYF(0), options->type); + DBUG_RETURN(HA_ERR_UNSUPPORTED); + } // endif's + + } else if (options->zipped) { + my_message(ER_UNKNOWN_ERROR, + "ZIPPED is incompatible with unspecified file name", MYF(0)); + DBUG_RETURN(HA_ERR_UNSUPPORTED); + } // endif's options // Fold type to lower case for (int i= 0; i < 12; i++) @@ -6334,6 +6338,36 @@ int ha_connect::create(const char *name, TABLE *table_arg, if (trace) htrc("xchk=%p createas=%d\n", g->Xchk, g->Createas); + if (options->zipped) { + // Check whether the zip entry must be made from a file + char *fn = GetListOption(g, "Load", options->oplist, NULL); + + if (fn) { + char zbuf[_MAX_PATH], buf[_MAX_PATH], dbpath[_MAX_PATH]; + char *entry = GetListOption(g, "Entry", options->oplist, NULL); + char *a = GetListOption(g, "Append", options->oplist, "NO"); + bool append = *a == '1' || *a == 'Y' || *a == 'y' || !stricmp(a, "ON"); + char *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); + + if (ZipLoadFile(g, zbuf, buf, entry, append, mul)) { + my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); + } // endif LoadFile + + } // endif fn + + } // endif zipped + // To check whether indexes have to be made or remade if (!g->Xchk) { PIXDEF xdp; diff --git a/storage/connect/mysql-test/connect/r/xml_zip.result b/storage/connect/mysql-test/connect/r/xml_zip.result new file mode 100644 index 00000000000..f176149c53f --- /dev/null +++ b/storage/connect/mysql-test/connect/r/xml_zip.result @@ -0,0 +1,98 @@ +Warnings: +Warning 1105 No file name. Table will use t1.xml +# +# Testing zipped XML tables +# +CREATE TABLE t1 ( +ISBN CHAR(13) NOT NULL FIELD_FORMAT='@', +LANG CHAR(2) NOT NULL FIELD_FORMAT='@', +SUBJECT CHAR(12) NOT NULL FIELD_FORMAT='@', +AUTHOR_FIRSTNAME CHAR(15) NOT NULL FIELD_FORMAT='AUTHOR/FIRSTNAME', +AUTHOR_LASTNAME CHAR(8) NOT NULL FIELD_FORMAT='AUTHOR/LASTNAME', +TRANSLATOR_PREFIX CHAR(24) DEFAULT NULL FIELD_FORMAT='TRANSLATOR/@PREFIX', +TRANSLATOR_FIRSTNAME CHAR(6) DEFAULT NULL FIELD_FORMAT='TRANSLATOR/FIRSTNAME', +TRANSLATOR_LASTNAME CHAR(6) DEFAULT NULL FIELD_FORMAT='TRANSLATOR/LASTNAME', +TITLE CHAR(30) NOT NULL, +PUBLISHER_NAME CHAR(15) NOT NULL FIELD_FORMAT='PUBLISHER/NAME', +PUBLISHER_PLACE CHAR(5) NOT NULL FIELD_FORMAT='PUBLISHER/PLACE', +DATEPUB CHAR(4) NOT NULL +) ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='xsample2.zip' ZIPPED=YES +OPTION_LIST='entry=xsample2.xml,load=xsample2.xml,rownode=BOOK,xmlsup=libxml2,expand=1,mulnode=AUTHOR'; +SELECT * FROM t1; +ISBN 9782212090819 +LANG fr +SUBJECT applications +AUTHOR_FIRSTNAME Jean-Christophe +AUTHOR_LASTNAME Bernadac +TRANSLATOR_PREFIX NULL +TRANSLATOR_FIRSTNAME NULL +TRANSLATOR_LASTNAME NULL +TITLE Construire une application XML +PUBLISHER_NAME Eyrolles +PUBLISHER_PLACE Paris +DATEPUB 1999 +ISBN 9782212090819 +LANG fr +SUBJECT applications +AUTHOR_FIRSTNAME François +AUTHOR_LASTNAME Knab +TRANSLATOR_PREFIX NULL +TRANSLATOR_FIRSTNAME NULL +TRANSLATOR_LASTNAME NULL +TITLE Construire une application XML +PUBLISHER_NAME Eyrolles +PUBLISHER_PLACE Paris +DATEPUB 1999 +ISBN 9782840825685 +LANG fr +SUBJECT applications +AUTHOR_FIRSTNAME William J. +AUTHOR_LASTNAME Pardi +TRANSLATOR_PREFIX adapté de l'anglais par +TRANSLATOR_FIRSTNAME James +TRANSLATOR_LASTNAME Guerin +TITLE XML en Action +PUBLISHER_NAME Microsoft Press +PUBLISHER_PLACE Paris +DATEPUB 1999 +ISBN 9782212090529 +LANG fr +SUBJECT général +AUTHOR_FIRSTNAME Alain +AUTHOR_LASTNAME Michard +TRANSLATOR_PREFIX NULL +TRANSLATOR_FIRSTNAME NULL +TRANSLATOR_LASTNAME NULL +TITLE XML, Langage et Applications +PUBLISHER_NAME Eyrolles +PUBLISHER_PLACE Paris +DATEPUB 2003 +CREATE TABLE t2 +ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='xsample2.zip' ZIPPED=YES +OPTION_LIST='xmlsup=libxml2'; +SELECT * FROM t2; +ISBN 9782212090819 +LANG fr +SUBJECT applications +AUTHOR Jean-Christophe Bernadac +TRANSLATOR NULL +TITLE Construire une application XML +PUBLISHER Eyrolles Paris +DATEPUB 1999 +ISBN 9782840825685 +LANG fr +SUBJECT applications +AUTHOR William J. Pardi +TRANSLATOR James Guerin +TITLE XML en Action +PUBLISHER Microsoft Press Paris +DATEPUB 1999 +ISBN 9782212090529 +LANG fr +SUBJECT général +AUTHOR Alain Michard +TRANSLATOR NULL +TITLE XML, Langage et Applications +PUBLISHER Eyrolles Paris +DATEPUB 2003 +DROP TABLE t1,t2; diff --git a/storage/connect/mysql-test/connect/r/zip.result b/storage/connect/mysql-test/connect/r/zip.result new file mode 100644 index 00000000000..c03b27bd428 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/zip.result @@ -0,0 +1,240 @@ +# +# Testing zipped DOS tables +# +CREATE TABLE t1 ( +digit INT(3) NOT NULL, +letter CHAR(16) NOT NULL) +ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='newdos.zip' +OPTION_LIST='ENTRY=new1.dos' ZIPPED=1; +INSERT INTO t1 VALUES(1,'One'),(2,'Two'),(3,'Three'),(4,'Four'),(5,'Five'),(6,'Six'),(7,'Seven'),(8,'Eight'),(9,'Nine'),(10,'Ten'); +SELECT * FROM t1; +digit letter +1 One +2 Two +3 Three +4 Four +5 Five +6 Six +7 Seven +8 Eight +9 Nine +10 Ten +CREATE TABLE t2 ( +digit INT(3) NOT NULL, +letter CHAR(16) NOT NULL) +ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='newdos.zip' +OPTION_LIST='ENTRY=new2.dos,APPEND=1' ZIPPED=1; +INSERT INTO t2 VALUES(11,'Eleven'),(12,'Twelve'),(13,'Thirteen'),(14,'Fourteen'),(15,'Fiften'),(16,'Sixteen'),(17,'Seventeen'),(18,'Eighteen'),(19,'Nineteen'),(20,'Twenty'); +SELECT * FROM t2; +digit letter +11 Eleven +12 Twelve +13 Thirteen +14 Fourteen +15 Fiften +16 Sixteen +17 Seventeen +18 Eighteen +19 Nineteen +20 Twenty +CREATE TABLE t3 ( +digit INT(3) NOT NULL, +letter CHAR(16) NOT NULL) +ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='newdos.zip' +OPTION_LIST='MULENTRIES=1' ZIPPED=1; +SELECT * FROM t3; +digit letter +1 One +2 Two +3 Three +4 Four +5 Five +6 Six +7 Seven +8 Eight +9 Nine +10 Ten +11 Eleven +12 Twelve +13 Thirteen +14 Fourteen +15 Fiften +16 Sixteen +17 Seventeen +18 Eighteen +19 Nineteen +20 Twenty +CREATE TABLE t4 ( +fn VARCHAR(256)NOT NULL, +cmpsize BIGINT NOT NULL FLAG=1, +uncsize BIGINT NOT NULL FLAG=2, +method INT NOT NULL FLAG=3) +ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='newdos.zip'; +SELECT * FROM t4; +fn cmpsize uncsize method +new1.dos 67 79 8 +new2.dos 77 112 8 +DROP TABLE t1,t2,t3,t4; +# +# Testing zipped CSV tables +# +CREATE TABLE t1 ( +digit INT(3) NOT NULL, +letter CHAR(16) NOT NULL) +ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='newcsv.zip' +OPTION_LIST='ENTRY=new1.csv' HEADER=1 ZIPPED=1; +INSERT INTO t1 VALUES(1,'One'),(2,'Two'),(3,'Three'),(4,'Four'),(5,'Five'),(6,'Six'),(7,'Seven'),(8,'Eight'),(9,'Nine'),(10,'Ten'); +SELECT * FROM t1; +digit letter +1 One +2 Two +3 Three +4 Four +5 Five +6 Six +7 Seven +8 Eight +9 Nine +10 Ten +CREATE TABLE td1 +ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='newcsv.zip' +OPTION_LIST='ENTRY=new1.csv' HEADER=1 ZIPPED=1; +SELECT * FROM td1; +digit letter +1 One +2 Two +3 Three +4 Four +5 Five +6 Six +7 Seven +8 Eight +9 Nine +10 Ten +DROP TABLE td1; +CREATE TABLE t2 ( +digit INT(3) NOT NULL, +letter CHAR(16) NOT NULL) +ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='newcsv.zip' +OPTION_LIST='ENTRY=new2.csv,APPEND=1' HEADER=1 ZIPPED=1; +INSERT INTO t2 VALUES(11,'Eleven'),(12,'Twelve'),(13,'Thirteen'),(14,'Fourteen'),(15,'Fiften'),(16,'Sixteen'),(17,'Seventeen'),(18,'Eighteen'),(19,'Nineteen'),(20,'Twenty'); +SELECT * FROM t2; +digit letter +11 Eleven +12 Twelve +13 Thirteen +14 Fourteen +15 Fiften +16 Sixteen +17 Seventeen +18 Eighteen +19 Nineteen +20 Twenty +CREATE TABLE t3 +ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='newcsv.zip' +OPTION_LIST='MULENTRIES=1' HEADER=1 ZIPPED=1; +SELECT * FROM t3; +digit letter +1 One +2 Two +3 Three +4 Four +5 Five +6 Six +7 Seven +8 Eight +9 Nine +10 Ten +11 Eleven +12 Twelve +13 Thirteen +14 Fourteen +15 Fiften +16 Sixteen +17 Seventeen +18 Eighteen +19 Nineteen +20 Twenty +CREATE TABLE t4 ( +fn VARCHAR(256)NOT NULL, +cmpsize BIGINT NOT NULL FLAG=1, +uncsize BIGINT NOT NULL FLAG=2, +method INT NOT NULL FLAG=3) +ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='newcsv.zip'; +SELECT * FROM t4; +fn cmpsize uncsize method +new1.csv 79 83 8 +new2.csv 94 125 8 +DROP TABLE t1,t2,t3,t4; +# +# Testing zipped JSON tables +# +CREATE TABLE t1 ( +_id INT(2) NOT NULL, +name_first CHAR(9) NOT NULL FIELD_FORMAT='name:first', +name_aka CHAR(4) DEFAULT NULL FIELD_FORMAT='name:aka', +name_last CHAR(10) NOT NULL FIELD_FORMAT='name:last', +title CHAR(12) DEFAULT NULL, +birth CHAR(20) DEFAULT NULL, +death CHAR(20) DEFAULT NULL, +contribs CHAR(7) NOT NULL FIELD_FORMAT='contribs:', +awards_award CHAR(42) DEFAULT NULL FIELD_FORMAT='awards::award', +awards_year CHAR(4) DEFAULT NULL FIELD_FORMAT='awards::year', +awards_by CHAR(38) DEFAULT NULL FIELD_FORMAT='awards::by' +) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='bios.zip' OPTION_LIST='ENTRY=bios.json,LOAD=bios.json' ZIPPED=YES; +SELECT * FROM t1; +_id name_first name_aka name_last title birth death contribs awards_award awards_year awards_by +1 John NULL Backus NULL 1924-12-03T05:00:00Z 2007-03-17T04:00:00Z Fortran W.W. McDowell Award 1967 IEEE Computer Society +2 John NULL McCarthy NULL 1927-09-04T04:00:00Z 2011-12-24T05:00:00Z Lisp Turing Award 1971 ACM +3 Grace NULL Hopper Rear Admiral 1906-12-09T05:00:00Z 1992-01-01T05:00:00Z UNIVAC Computer Sciences Man of the Year 1969 Data Processing Management Association +4 Kristen NULL Nygaard NULL 1926-08-27T04:00:00Z 2002-08-10T04:00:00Z OOP Rosing Prize 1999 Norwegian Data Association +5 Ole-Johan NULL Dahl NULL 1931-10-12T04:00:00Z 2002-06-29T04:00:00Z OOP Rosing Prize 1999 Norwegian Data Association +6 Guido NULL van Rossum NULL 1956-01-31T05:00:00Z NULL Python Award for the Advancement of Free Software 2001 Free Software Foundation +7 Dennis NULL Ritchie NULL 1941-09-09T04:00:00Z 2011-10-12T04:00:00Z UNIX Turing Award 1983 ACM +8 Yukihiro Matz Matsumoto NULL 1965-04-14T04:00:00Z NULL Ruby Award for the Advancement of Free Software 2011 Free Software Foundation +9 James NULL Gosling NULL 1955-05-19T04:00:00Z NULL Java The Economist Innovation Award 2002 The Economist +10 Martin NULL Odersky NULL NULL NULL Scala NULL NULL NULL +CREATE TABLE t2 +ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='bios.zip' ZIPPED=1 +OPTION_LIST='LEVEL=5'; +SELECT * FROM t2; +_id name_first name_aka name_last title birth death contribs awards_award awards_year awards_by +1 John NULL Backus NULL 1924-12-03T05:00:00Z 2007-03-17T04:00:00Z Fortran W.W. McDowell Award 1967 IEEE Computer Society +2 John NULL McCarthy NULL 1927-09-04T04:00:00Z 2011-12-24T05:00:00Z Lisp Turing Award 1971 ACM +3 Grace NULL Hopper Rear Admiral 1906-12-09T05:00:00Z 1992-01-01T05:00:00Z UNIVAC Computer Sciences Man of the Year 1969 Data Processing Management Association +4 Kristen NULL Nygaard NULL 1926-08-27T04:00:00Z 2002-08-10T04:00:00Z OOP Rosing Prize 1999 Norwegian Data Association +5 Ole-Johan NULL Dahl NULL 1931-10-12T04:00:00Z 2002-06-29T04:00:00Z OOP Rosing Prize 1999 Norwegian Data Association +6 Guido NULL van Rossum NULL 1956-01-31T05:00:00Z NULL Python Award for the Advancement of Free Software 2001 Free Software Foundation +7 Dennis NULL Ritchie NULL 1941-09-09T04:00:00Z 2011-10-12T04:00:00Z UNIX Turing Award 1983 ACM +8 Yukihiro Matz Matsumoto NULL 1965-04-14T04:00:00Z NULL Ruby Award for the Advancement of Free Software 2011 Free Software Foundation +9 James NULL Gosling NULL 1955-05-19T04:00:00Z NULL Java The Economist Innovation Award 2002 The Economist +10 Martin NULL Odersky NULL NULL NULL Scala NULL NULL NULL +CREATE TABLE t3 ( +_id INT(2) NOT NULL, +firstname CHAR(9) NOT NULL FIELD_FORMAT='name:first', +aka CHAR(4) DEFAULT NULL FIELD_FORMAT='name:aka', +lastname CHAR(10) NOT NULL FIELD_FORMAT='name:last', +title CHAR(12) DEFAULT NULL, +birth date DEFAULT NULL date_format="YYYY-DD-MM'T'hh:mm:ss'Z'", +death date DEFAULT NULL date_format="YYYY-DD-MM'T'hh:mm:ss'Z'", +contribs CHAR(64) NOT NULL FIELD_FORMAT='contribs:[", "]', +award CHAR(42) DEFAULT NULL FIELD_FORMAT='awards:[x]:award', +year CHAR(4) DEFAULT NULL FIELD_FORMAT='awards:[x]:year', +`by` CHAR(38) DEFAULT NULL FIELD_FORMAT='awards:[x]:by' +) ENGINE=CONNECT TABLE_TYPE='json' FILE_NAME='bios.zip' ZIPPED=YES; +SELECT * FROM t3 WHERE _id = 1; +_id firstname aka lastname title birth death contribs award year by +1 John NULL Backus NULL 1924-03-12 2008-05-03 Fortran, ALGOL, Backus-Naur Form, FP W.W. McDowell Award 1967 IEEE Computer Society +1 John NULL Backus NULL 1924-03-12 2008-05-03 Fortran, ALGOL, Backus-Naur Form, FP National Medal of Science 1975 National Science Foundation +1 John NULL Backus NULL 1924-03-12 2008-05-03 Fortran, ALGOL, Backus-Naur Form, FP Turing Award 1977 ACM +1 John NULL Backus NULL 1924-03-12 2008-05-03 Fortran, ALGOL, Backus-Naur Form, FP Draper Prize 1993 National Academy of Engineering +CREATE TABLE t4 ( +fn VARCHAR(256)NOT NULL, +cmpsize BIGINT NOT NULL FLAG=1, +uncsize BIGINT NOT NULL FLAG=2, +method INT NOT NULL FLAG=3) +ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='bios.zip'; +SELECT * FROM t4; +fn cmpsize uncsize method +bios.json 1096 6848 8 +DROP TABLE t1,t2,t3,t4; diff --git a/storage/connect/mysql-test/connect/std_data/bios.json b/storage/connect/mysql-test/connect/std_data/bios.json new file mode 100644 index 00000000000..85e4ecb933f --- /dev/null +++ b/storage/connect/mysql-test/connect/std_data/bios.json @@ -0,0 +1,273 @@ +[ + { + "_id" : 1, + "name" : { + "first" : "John", + "last" : "Backus" + }, + "birth" : "1924-12-03T05:00:00Z", + "death" : "2007-03-17T04:00:00Z", + "contribs" : [ + "Fortran", + "ALGOL", + "Backus-Naur Form", + "FP" + ], + "awards" : [ + { + "award" : "W.W. McDowell Award", + "year" : 1967, + "by" : "IEEE Computer Society" + }, + { + "award" : "National Medal of Science", + "year" : 1975, + "by" : "National Science Foundation" + }, + { + "award" : "Turing Award", + "year" : 1977, + "by" : "ACM" + }, + { + "award" : "Draper Prize", + "year" : 1993, + "by" : "National Academy of Engineering" + } + ] + }, + { + "_id" : 2, + "name" : { + "first" : "John", + "last" : "McCarthy" + }, + "birth" : "1927-09-04T04:00:00Z", + "death" : "2011-12-24T05:00:00Z", + "contribs" : [ + "Lisp", + "Artificial Intelligence", + "ALGOL" + ], + "awards" : [ + { + "award" : "Turing Award", + "year" : 1971, + "by" : "ACM" + }, + { + "award" : "Kyoto Prize", + "year" : 1988, + "by" : "Inamori Foundation" + }, + { + "award" : "National Medal of Science", + "year" : 1990, + "by" : "National Science Foundation" + } + ] + }, + { + "_id" : 3, + "name" : { + "first" : "Grace", + "last" : "Hopper" + }, + "title" : "Rear Admiral", + "birth" : "1906-12-09T05:00:00Z", + "death" : "1992-01-01T05:00:00Z", + "contribs" : [ + "UNIVAC", + "compiler", + "FLOW-MATIC", + "COBOL" + ], + "awards" : [ + { + "award" : "Computer Sciences Man of the Year", + "year" : 1969, + "by" : "Data Processing Management Association" + }, + { + "award" : "Distinguished Fellow", + "year" : 1973, + "by" : " British Computer Society" + }, + { + "award" : "W. W. McDowell Award", + "year" : 1976, + "by" : "IEEE Computer Society" + }, + { + "award" : "National Medal of Technology", + "year" : 1991, + "by" : "United States" + } + ] + }, + { + "_id" : 4, + "name" : { + "first" : "Kristen", + "last" : "Nygaard" + }, + "birth" : "1926-08-27T04:00:00Z", + "death" : "2002-08-10T04:00:00Z", + "contribs" : [ + "OOP", + "Simula" + ], + "awards" : [ + { + "award" : "Rosing Prize", + "year" : 1999, + "by" : "Norwegian Data Association" + }, + { + "award" : "Turing Award", + "year" : 2001, + "by" : "ACM" + }, + { + "award" : "IEEE John von Neumann Medal", + "year" : 2001, + "by" : "IEEE" + } + ] + }, + { + "_id" : 5, + "name" : { + "first" : "Ole-Johan", + "last" : "Dahl" + }, + "birth" : "1931-10-12T04:00:00Z", + "death" : "2002-06-29T04:00:00Z", + "contribs" : [ + "OOP", + "Simula" + ], + "awards" : [ + { + "award" : "Rosing Prize", + "year" : 1999, + "by" : "Norwegian Data Association" + }, + { + "award" : "Turing Award", + "year" : 2001, + "by" : "ACM" + }, + { + "award" : "IEEE John von Neumann Medal", + "year" : 2001, + "by" : "IEEE" + } + ] + }, + { + "_id" : 6, + "name" : { + "first" : "Guido", + "last" : "van Rossum" + }, + "birth" : "1956-01-31T05:00:00Z", + "contribs" : [ + "Python" + ], + "awards" : [ + { + "award" : "Award for the Advancement of Free Software", + "year" : 2001, + "by" : "Free Software Foundation" + }, + { + "award" : "NLUUG Award", + "year" : 2003, + "by" : "NLUUG" + } + ] + }, + { + "_id" : 7, + "name" : { + "first" : "Dennis", + "last" : "Ritchie" + }, + "birth" : "1941-09-09T04:00:00Z", + "death" : "2011-10-12T04:00:00Z", + "contribs" : [ + "UNIX", + "C" + ], + "awards" : [ + { + "award" : "Turing Award", + "year" : 1983, + "by" : "ACM" + }, + { + "award" : "National Medal of Technology", + "year" : 1998, + "by" : "United States" + }, + { + "award" : "Japan Prize", + "year" : 2011, + "by" : "The Japan Prize Foundation" + } + ] + }, + { + "_id" : 8, + "name" : { + "first" : "Yukihiro", + "aka" : "Matz", + "last" : "Matsumoto" + }, + "birth" : "1965-04-14T04:00:00Z", + "contribs" : [ + "Ruby" + ], + "awards" : [ + { + "award" : "Award for the Advancement of Free Software", + "year" : "2011", + "by" : "Free Software Foundation" + } + ] + }, + { + "_id" : 9, + "name" : { + "first" : "James", + "last" : "Gosling" + }, + "birth" : "1955-05-19T04:00:00Z", + "contribs" : [ + "Java" + ], + "awards" : [ + { + "award" : "The Economist Innovation Award", + "year" : 2002, + "by" : "The Economist" + }, + { + "award" : "Officer of the Order of Canada", + "year" : 2007, + "by" : "Canada" + } + ] + }, + { + "_id" : 10, + "name" : { + "first" : "Martin", + "last" : "Odersky" + }, + "contribs" : [ + "Scala" + ] + } +] diff --git a/storage/connect/mysql-test/connect/std_data/xsample2.xml b/storage/connect/mysql-test/connect/std_data/xsample2.xml new file mode 100644 index 00000000000..35295844370 --- /dev/null +++ b/storage/connect/mysql-test/connect/std_data/xsample2.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<BIBLIO SUBJECT="XML"> + <BOOK ISBN="9782212090819" LANG="fr" SUBJECT="applications"> + <AUTHOR> + <FIRSTNAME>Jean-Christophe</FIRSTNAME> + <LASTNAME>Bernadac</LASTNAME> + </AUTHOR> + <AUTHOR> + <FIRSTNAME>François</FIRSTNAME> + <LASTNAME>Knab</LASTNAME> + </AUTHOR> + <TITLE>Construire une application XML</TITLE> + <PUBLISHER> + <NAME>Eyrolles</NAME> + <PLACE>Paris</PLACE> + </PUBLISHER> + <DATEPUB>1999</DATEPUB> + </BOOK> + <BOOK ISBN="9782840825685" LANG="fr" SUBJECT="applications"> + <AUTHOR> + <FIRSTNAME>William J.</FIRSTNAME> + <LASTNAME>Pardi</LASTNAME> + </AUTHOR> + <TRANSLATOR PREFIX="adapté de l'anglais par"> + <FIRSTNAME>James</FIRSTNAME> + <LASTNAME>Guerin</LASTNAME> + </TRANSLATOR> + <TITLE>XML en Action</TITLE> + <PUBLISHER> + <NAME>Microsoft Press</NAME> + <PLACE>Paris</PLACE> + </PUBLISHER> + <DATEPUB>1999</DATEPUB> + </BOOK> + <BOOK ISBN="9782212090529" LANG="fr" SUBJECT="général"> + <AUTHOR> + <FIRSTNAME>Alain</FIRSTNAME> + <LASTNAME>Michard</LASTNAME> + </AUTHOR> + <TITLE>XML, Langage et Applications</TITLE> + <PUBLISHER> + <NAME>Eyrolles</NAME> + <PLACE>Paris</PLACE> + </PUBLISHER> + <DATEPUB>2003</DATEPUB> + </BOOK> +</BIBLIO> diff --git a/storage/connect/mysql-test/connect/t/have_zip.inc b/storage/connect/mysql-test/connect/t/have_zip.inc new file mode 100644 index 00000000000..d1283fc1d38 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/have_zip.inc @@ -0,0 +1,19 @@ +--disable_query_log +--error 0,ER_UNKNOWN_ERROR +CREATE TABLE t1 (a CHAR(10)) ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='test.zip'; +if ($mysql_errno) +{ + Skip No ZIP support; +} +#if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES +# WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1' +# AND ENGINE='CONNECT' +# AND CREATE_OPTIONS LIKE '%`table_type`=ZIP%' +# AND CREATE OPTIONS LIKE "%`file_name`='test.zip'%"`) +#{ +# DROP TABLE IF EXISTS t1; +# Skip Need ZIP support; +#} +DROP TABLE t1; +--enable_query_log + diff --git a/storage/connect/mysql-test/connect/t/xml_zip.test b/storage/connect/mysql-test/connect/t/xml_zip.test new file mode 100644 index 00000000000..d8c7894f861 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/xml_zip.test @@ -0,0 +1,41 @@ +--source have_zip.inc +--source have_libxml2.inc + +let $MYSQLD_DATADIR= `select @@datadir`; + +--vertical_results + +--copy_file $MTR_SUITE_DIR/std_data/xsample2.xml $MYSQLD_DATADIR/test/xsample2.xml + +--echo # +--echo # Testing zipped XML tables +--echo # +CREATE TABLE t1 ( +ISBN CHAR(13) NOT NULL FIELD_FORMAT='@', +LANG CHAR(2) NOT NULL FIELD_FORMAT='@', +SUBJECT CHAR(12) NOT NULL FIELD_FORMAT='@', +AUTHOR_FIRSTNAME CHAR(15) NOT NULL FIELD_FORMAT='AUTHOR/FIRSTNAME', +AUTHOR_LASTNAME CHAR(8) NOT NULL FIELD_FORMAT='AUTHOR/LASTNAME', +TRANSLATOR_PREFIX CHAR(24) DEFAULT NULL FIELD_FORMAT='TRANSLATOR/@PREFIX', +TRANSLATOR_FIRSTNAME CHAR(6) DEFAULT NULL FIELD_FORMAT='TRANSLATOR/FIRSTNAME', +TRANSLATOR_LASTNAME CHAR(6) DEFAULT NULL FIELD_FORMAT='TRANSLATOR/LASTNAME', +TITLE CHAR(30) NOT NULL, +PUBLISHER_NAME CHAR(15) NOT NULL FIELD_FORMAT='PUBLISHER/NAME', +PUBLISHER_PLACE CHAR(5) NOT NULL FIELD_FORMAT='PUBLISHER/PLACE', +DATEPUB CHAR(4) NOT NULL +) ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='xsample2.zip' ZIPPED=YES +OPTION_LIST='entry=xsample2.xml,load=xsample2.xml,rownode=BOOK,xmlsup=libxml2,expand=1,mulnode=AUTHOR'; +SELECT * FROM t1; + +#testing discovery +CREATE TABLE t2 +ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='xsample2.zip' ZIPPED=YES +OPTION_LIST='xmlsup=libxml2'; +SELECT * FROM t2; +DROP TABLE t1,t2; + +# +# Clean up +# +--remove_file $MYSQLD_DATADIR/test/xsample2.xml +--remove_file $MYSQLD_DATADIR/test/xsample2.zip diff --git a/storage/connect/mysql-test/connect/t/zip.test b/storage/connect/mysql-test/connect/t/zip.test new file mode 100644 index 00000000000..a4892e9ed4e --- /dev/null +++ b/storage/connect/mysql-test/connect/t/zip.test @@ -0,0 +1,136 @@ +--source have_zip.inc +let $MYSQLD_DATADIR= `select @@datadir`; + +--copy_file $MTR_SUITE_DIR/std_data/bios.json $MYSQLD_DATADIR/test/bios.json + +--echo # +--echo # Testing zipped DOS tables +--echo # +CREATE TABLE t1 ( +digit INT(3) NOT NULL, +letter CHAR(16) NOT NULL) +ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='newdos.zip' +OPTION_LIST='ENTRY=new1.dos' ZIPPED=1; +INSERT INTO t1 VALUES(1,'One'),(2,'Two'),(3,'Three'),(4,'Four'),(5,'Five'),(6,'Six'),(7,'Seven'),(8,'Eight'),(9,'Nine'),(10,'Ten'); +SELECT * FROM t1; + +CREATE TABLE t2 ( +digit INT(3) NOT NULL, +letter CHAR(16) NOT NULL) +ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='newdos.zip' +OPTION_LIST='ENTRY=new2.dos,APPEND=1' ZIPPED=1; +INSERT INTO t2 VALUES(11,'Eleven'),(12,'Twelve'),(13,'Thirteen'),(14,'Fourteen'),(15,'Fiften'),(16,'Sixteen'),(17,'Seventeen'),(18,'Eighteen'),(19,'Nineteen'),(20,'Twenty'); +SELECT * FROM t2; + +CREATE TABLE t3 ( +digit INT(3) NOT NULL, +letter CHAR(16) NOT NULL) +ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='newdos.zip' +OPTION_LIST='MULENTRIES=1' ZIPPED=1; +SELECT * FROM t3; + +CREATE TABLE t4 ( +fn VARCHAR(256)NOT NULL, +cmpsize BIGINT NOT NULL FLAG=1, +uncsize BIGINT NOT NULL FLAG=2, +method INT NOT NULL FLAG=3) +ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='newdos.zip'; +SELECT * FROM t4; +DROP TABLE t1,t2,t3,t4; + +--echo # +--echo # Testing zipped CSV tables +--echo # +CREATE TABLE t1 ( +digit INT(3) NOT NULL, +letter CHAR(16) NOT NULL) +ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='newcsv.zip' +OPTION_LIST='ENTRY=new1.csv' HEADER=1 ZIPPED=1; +INSERT INTO t1 VALUES(1,'One'),(2,'Two'),(3,'Three'),(4,'Four'),(5,'Five'),(6,'Six'),(7,'Seven'),(8,'Eight'),(9,'Nine'),(10,'Ten'); +SELECT * FROM t1; + +# Test discovery +CREATE TABLE td1 +ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='newcsv.zip' +OPTION_LIST='ENTRY=new1.csv' HEADER=1 ZIPPED=1; +SELECT * FROM td1; +DROP TABLE td1; + +CREATE TABLE t2 ( +digit INT(3) NOT NULL, +letter CHAR(16) NOT NULL) +ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='newcsv.zip' +OPTION_LIST='ENTRY=new2.csv,APPEND=1' HEADER=1 ZIPPED=1; +INSERT INTO t2 VALUES(11,'Eleven'),(12,'Twelve'),(13,'Thirteen'),(14,'Fourteen'),(15,'Fiften'),(16,'Sixteen'),(17,'Seventeen'),(18,'Eighteen'),(19,'Nineteen'),(20,'Twenty'); +SELECT * FROM t2; + +CREATE TABLE t3 +ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='newcsv.zip' +OPTION_LIST='MULENTRIES=1' HEADER=1 ZIPPED=1; +SELECT * FROM t3; + +CREATE TABLE t4 ( +fn VARCHAR(256)NOT NULL, +cmpsize BIGINT NOT NULL FLAG=1, +uncsize BIGINT NOT NULL FLAG=2, +method INT NOT NULL FLAG=3) +ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='newcsv.zip'; +SELECT * FROM t4; +DROP TABLE t1,t2,t3,t4; + +--echo # +--echo # Testing zipped JSON tables +--echo # +CREATE TABLE t1 ( +_id INT(2) NOT NULL, +name_first CHAR(9) NOT NULL FIELD_FORMAT='name:first', +name_aka CHAR(4) DEFAULT NULL FIELD_FORMAT='name:aka', +name_last CHAR(10) NOT NULL FIELD_FORMAT='name:last', +title CHAR(12) DEFAULT NULL, +birth CHAR(20) DEFAULT NULL, +death CHAR(20) DEFAULT NULL, +contribs CHAR(7) NOT NULL FIELD_FORMAT='contribs:', +awards_award CHAR(42) DEFAULT NULL FIELD_FORMAT='awards::award', +awards_year CHAR(4) DEFAULT NULL FIELD_FORMAT='awards::year', +awards_by CHAR(38) DEFAULT NULL FIELD_FORMAT='awards::by' +) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='bios.zip' OPTION_LIST='ENTRY=bios.json,LOAD=bios.json' ZIPPED=YES; +SELECT * FROM t1; + +# Test discovery +CREATE TABLE t2 +ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='bios.zip' ZIPPED=1 +OPTION_LIST='LEVEL=5'; +SELECT * FROM t2; + +CREATE TABLE t3 ( +_id INT(2) NOT NULL, +firstname CHAR(9) NOT NULL FIELD_FORMAT='name:first', +aka CHAR(4) DEFAULT NULL FIELD_FORMAT='name:aka', +lastname CHAR(10) NOT NULL FIELD_FORMAT='name:last', +title CHAR(12) DEFAULT NULL, +birth date DEFAULT NULL date_format="YYYY-DD-MM'T'hh:mm:ss'Z'", +death date DEFAULT NULL date_format="YYYY-DD-MM'T'hh:mm:ss'Z'", +contribs CHAR(64) NOT NULL FIELD_FORMAT='contribs:[", "]', +award CHAR(42) DEFAULT NULL FIELD_FORMAT='awards:[x]:award', +year CHAR(4) DEFAULT NULL FIELD_FORMAT='awards:[x]:year', +`by` CHAR(38) DEFAULT NULL FIELD_FORMAT='awards:[x]:by' +) ENGINE=CONNECT TABLE_TYPE='json' FILE_NAME='bios.zip' ZIPPED=YES; +SELECT * FROM t3 WHERE _id = 1; + +CREATE TABLE t4 ( +fn VARCHAR(256)NOT NULL, +cmpsize BIGINT NOT NULL FLAG=1, +uncsize BIGINT NOT NULL FLAG=2, +method INT NOT NULL FLAG=3) +ENGINE=CONNECT TABLE_TYPE=ZIP FILE_NAME='bios.zip'; +SELECT * FROM t4; +DROP TABLE t1,t2,t3,t4; + +# +# Clean up +# +--remove_file $MYSQLD_DATADIR/test/newdos.zip +--remove_file $MYSQLD_DATADIR/test/newcsv.zip +--remove_file $MYSQLD_DATADIR/test/bios.zip +--remove_file $MYSQLD_DATADIR/test/bios.json + diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index 83975c6d8fa..01e9e476308 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -939,7 +939,11 @@ int PlugCloseFile(PGLOBAL g __attribute__((unused)), PFBLOCK fp, bool all) #endif // LIBXML2_SUPPORT #ifdef ZIP_SUPPORT case TYPE_FB_ZIP: - ((ZIPUTIL*)fp->File)->close(); + if (fp->Mode == MODE_INSERT) + ((ZIPUTIL*)fp->File)->close(); + else + ((UNZIPUTL*)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 71b72621b06..eb31e24235b 100644 --- a/storage/connect/plgxml.cpp +++ b/storage/connect/plgxml.cpp @@ -1,6 +1,6 @@ /******************************************************************/ /* Implementation of XML document processing using PdbXML. */ -/* Author: Olivier Bertrand 2007-2012 */ +/* Author: Olivier Bertrand 2007-2017 */ /******************************************************************/ #include "my_global.h" #include "global.h" @@ -49,7 +49,7 @@ 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); + zip = new(g) UNZIPUTL(entry, mul); return zip == NULL; #else // !ZIP_SUPPORT sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); diff --git a/storage/connect/plgxml.h b/storage/connect/plgxml.h index db7dfa6bda5..6870764c503 100644 --- a/storage/connect/plgxml.h +++ b/storage/connect/plgxml.h @@ -101,7 +101,7 @@ class XMLDOCUMENT : public BLOCK { // Members #if defined(ZIP_SUPPORT) - ZIPUTIL *zip; /* Used for zipped file */ + UNZIPUTL *zip; /* Used for zipped file */ #else // !ZIP_SUPPORT bool zip; /* Always false */ #endif // !ZIP_SUPPORT diff --git a/storage/connect/plugutil.c b/storage/connect/plugutil.c index 2551b603349..bfac8a5fd99 100644 --- a/storage/connect/plugutil.c +++ b/storage/connect/plugutil.c @@ -244,6 +244,9 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath) char *drive = NULL, *defdrv = NULL; #endif + if (trace > 1) + htrc("prefix=%s fn=%s path=%s\n", prefix, FileName, defpath); + if (!strncmp(FileName, "//", 2) || !strncmp(FileName, "\\\\", 2)) { strcpy(pBuff, FileName); // Remote file return pBuff; diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index 16cc6c33b44..ed72d89b7d3 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -102,6 +102,7 @@ DOSDEF::DOSDEF(void) Mapped = false; Zipped = false; Mulentries = false; + Append = false; Padded = false; Huge = false; Accept = false; @@ -132,10 +133,13 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int) : (am && (*am == 'B' || *am == 'b')) ? "B" : (am && !stricmp(am, "DBF")) ? "D" : "V"; - if ((Zipped = GetBoolCatInfo("Zipped", false))) - Mulentries = ((Entry = GetStringCatInfo(g, "Entry", NULL))) - ? strchr(Entry, '*') || strchr(Entry, '?') - : GetBoolCatInfo("Mulentries", false); + if ((Zipped = GetBoolCatInfo("Zipped", false))) { + Entry = GetStringCatInfo(g, "Entry", NULL); + Mulentries = (Entry && *Entry) ? strchr(Entry, '*') || strchr(Entry, '?') + : false; + Mulentries = GetBoolCatInfo("Mulentries", Mulentries); + Append = GetBoolCatInfo("Append", false); + } Desc = Fn = GetStringCatInfo(g, "Filename", NULL); Ofn = GetStringCatInfo(g, "Optname", Fn); @@ -347,10 +351,26 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode) if (Zipped) { #if defined(ZIP_SUPPORT) if (Recfm == RECFM_VAR) { - txfp = new(g)ZIPFAM(this); - tdbp = new(g)TDBDOS(this, txfp); + if (mode == MODE_READ || mode == MODE_ANY) { + txfp = new(g) UNZFAM(this); + } else if (mode == MODE_INSERT) { + txfp = new(g) ZIPFAM(this); + } else { + strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); + return NULL; + } // endif's mode + + tdbp = new(g) TDBDOS(this, txfp); } else { - txfp = new(g)ZPXFAM(this); + if (mode == MODE_READ || mode == MODE_ANY) { + txfp = new(g) UZXFAM(this); + } else if (mode == MODE_INSERT) { + txfp = new(g) ZPXFAM(this); + } else { + strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); + return NULL; + } // endif's mode + tdbp = new(g)TDBFIX(this, txfp); } // endif Recfm @@ -376,7 +396,7 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode) txfp = new(g) MPXFAM(this); else if (Compressed) { #if defined(GZ_SUPPORT) - txfp = new(g) ZIXFAM(this); + txfp = new(g) GZXFAM(this); #else // !GZ_SUPPORT sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "GZ"); return NULL; diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h index 4c8eb438a26..59c98ce9714 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 ZIPUTIL; + friend class UNZIPUTL; public: // Constructor DOSDEF(void); @@ -43,7 +43,8 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */ PSZ GetOfn(void) {return Ofn;} PSZ GetEntry(void) {return Entry;} bool GetMul(void) {return Mulentries;} - void SetBlock(int block) {Block = block;} + bool GetAppend(void) {return Append;} + void SetBlock(int block) { Block = block; } int GetBlock(void) {return Block;} int GetLast(void) {return Last;} void SetLast(int last) {Last = last;} @@ -81,6 +82,7 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */ bool Mapped; /* 0: disk file, 1: memory mapped file */ bool Zipped; /* true for zipped table file */ bool Mulentries; /* true for multiple entries */ + bool Append; /* Used when creating zipped table */ 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 b24375443f6..1bedc018473 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -5,7 +5,7 @@ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2001 - 2016 */ +/* (C) Copyright to the author Olivier BERTRAND 2001 - 2017 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -98,8 +98,9 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info) int num_read = 0, num_max = 10000000; // Statistics int len[MAXCOL], typ[MAXCOL], prc[MAXCOL]; PCSVDEF tdp; - PTDBCSV tdbp; - PQRYRES qrp; + PTDBCSV tcvp; + PTDBASE tdbp; + PQRYRES qrp; PCOLRES crp; if (info) { @@ -108,10 +109,10 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info) goto skipit; } // endif info - if (GetIntegerTableOption(g, topt, "Multiple", 0)) { - strcpy(g->Message, "Cannot find column definition for multiple table"); - return NULL; - } // endif Multiple + //if (GetIntegerTableOption(g, topt, "Multiple", 0)) { + // strcpy(g->Message, "Cannot find column definition for multiple table"); + // return NULL; + //} // endif Multiple // num_max = atoi(p+1); // Max num of record to test imax = hmax = nerr = 0; @@ -127,10 +128,20 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info) /* Get the CSV table description block. */ /*********************************************************************/ tdp = new(g) CSVDEF; + tdp->Database = dp; + + if ((tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false))) { #if defined(ZIP_SUPPORT) - tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL); - tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false); -#endif // ZIP_SUPPORT + tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL); + tdp->Mulentries = (tdp->Entry) + ? strchr(tdp->Entry, '*') || strchr(tdp->Entry, '?') + : GetBooleanTableOption(g, topt, "Mulentries", false); +#else // !ZIP_SUPPORT + strcpy(g->Message, "ZIP not supported by this version"); + return NULL; +#endif // !ZIP_SUPPORT + } // endif // Zipped + fn = tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL); if (!tdp->Fn) { @@ -141,6 +152,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info) if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0))) tdp->Lrecl = 4096; + tdp->Multiple = GetIntegerTableOption(g, topt, "Multiple", 0); p = GetStringTableOption(g, topt, "Separator", ","); tdp->Sep = (strlen(p) == 2 && p[0] == '\\' && p[1] == 't') ? '\t' : *p; @@ -177,17 +189,18 @@ 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) { -#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)); + if (tdp->Zipped) + tcvp = new(g)TDBCSV(tdp, new(g)UNZFAM(tdp)); + else + tcvp = new(g) TDBCSV(tdp, new(g) DOSFAM(tdp)); + + tcvp->SetMode(MODE_READ); - tdbp->SetMode(MODE_READ); + if (tdp->Multiple) { + tdbp = new(g)TDBMUL(tcvp); + tdbp->SetMode(MODE_READ); + } else + tdbp = tcvp; /*********************************************************************/ /* Open the CSV file. */ @@ -202,7 +215,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info) phase = 0; if ((rc = tdbp->ReadDB(g)) == RC_OK) { - p = PlgDBDup(g, tdbp->To_Line); + p = PlgDBDup(g, tcvp->To_Line); //skip leading blanks for (; *p == ' '; p++) ; @@ -245,6 +258,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info) for (i = 0; i < hmax; i++) length[0] = MY_MAX(length[0], strlen(colname[i])); + tcvp->Header = true; // In case of multiple table } // endif hdr for (num_read++; num_read <= num_max; num_read++) { @@ -265,7 +279,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info) /*******************************************************************/ i = n = phase = blank = digit = dec = 0; - for (p = tdbp->To_Line; *p; p++) + for (p = tcvp->To_Line; *p; p++) if (*p == sep) { if (phase != 1) { if (i == MAXCOL - 1) { @@ -503,7 +517,14 @@ PTDB CSVDEF::GetTable(PGLOBAL g, MODE mode) /*******************************************************************/ if (Zipped) { #if defined(ZIP_SUPPORT) - txfp = new(g) ZIPFAM(this); + if (mode == MODE_READ || mode == MODE_ANY) { + txfp = new(g) UNZFAM(this); + } else if (mode == MODE_INSERT) { + txfp = new(g) ZIPFAM(this); + } else { + strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); + return NULL; + } // endif's mode #else // !ZIP_SUPPORT strcpy(g->Message, "ZIP not supported"); return NULL; diff --git a/storage/connect/tabfmt.h b/storage/connect/tabfmt.h index 5ce8d399a64..f932ddacb39 100644 --- a/storage/connect/tabfmt.h +++ b/storage/connect/tabfmt.h @@ -52,6 +52,7 @@ public: /***********************************************************************/ class DllExport TDBCSV : public TDBDOS { friend class CSVCOL; + friend class MAPFAM; friend PQRYRES CSVColumns(PGLOBAL, char *, PTOS, bool); public: // Constructor diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index 1b9ce8b64c9..5248fda4670 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -129,7 +129,7 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info) if (tdp->Pretty == 2) { if (tdp->Zipped) { #if defined(ZIP_SUPPORT) - tjsp = new(g) TDBJSON(tdp, new(g) ZIPFAM(tdp)); + tjsp = new(g) TDBJSON(tdp, new(g) UNZFAM(tdp)); #else // !ZIP_SUPPORT sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); return NULL; @@ -151,7 +151,7 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info) if (tdp->Zipped) { #if defined(ZIP_SUPPORT) - tjnp = new(g)TDBJSN(tdp, new(g)ZIPFAM(tdp)); + tjnp = new(g)TDBJSN(tdp, new(g)UNZFAM(tdp)); #else // !ZIP_SUPPORT sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); return NULL; @@ -441,7 +441,14 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) if (Zipped) { #if defined(ZIP_SUPPORT) - txfp = new(g) ZIPFAM(this); + if (m == MODE_READ || m == MODE_UPDATE) { + txfp = new(g) UNZFAM(this); + } else if (m == MODE_INSERT) { + txfp = new(g) ZIPFAM(this); + } else { + strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); + return NULL; + } // endif's m #else // !ZIP_SUPPORT sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); return NULL; @@ -479,7 +486,15 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m) } else { if (Zipped) { #if defined(ZIP_SUPPORT) - txfp = new(g)ZIPFAM(this); + if (m == MODE_READ || m == MODE_UPDATE) { + txfp = new(g) UNZFAM(this); + } else if (m == MODE_INSERT) { + strcpy(g->Message, "INSERT supported only for zipped JSON when pretty=0"); + return NULL; + } else { + strcpy(g->Message, "UPDATE/DELETE not supported for ZIP"); + return NULL; + } // endif's m #else // !ZIP_SUPPORT sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP"); return NULL; diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp index 3b8229fcf51..aa9b612feac 100644 --- a/storage/connect/tabxml.cpp +++ b/storage/connect/tabxml.cpp @@ -537,6 +537,11 @@ PTDB XMLDEF::GetTable(PGLOBAL g, MODE m) if (Catfunc == FNC_COL) return new(g) TDBXCT(this); + if (Zipped && !(m == MODE_READ || m == MODE_ANY)) { + strcpy(g->Message, "ZIpped XML tables are read only"); + return NULL; + } // endif Zipped + PTDBASE tdbp = new(g) TDBXML(this); if (Multiple) diff --git a/storage/connect/tabzip.cpp b/storage/connect/tabzip.cpp index 11f414ee154..b91059a3843 100644 --- a/storage/connect/tabzip.cpp +++ b/storage/connect/tabzip.cpp @@ -70,8 +70,12 @@ PCOL TDBZIP::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) /* param: filename path and the filename of the zip file to open. */ /* return: true if open, false otherwise. */ /***********************************************************************/ -bool TDBZIP::open(PGLOBAL g, const char *filename) +bool TDBZIP::open(PGLOBAL g, const char *fn) { + char filename[_MAX_PATH]; + + PlugSetPath(filename, fn, GetPath()); + if (!zipfile && !(zipfile = unzOpen64(filename))) sprintf(g->Message, "Zipfile open error"); @@ -102,7 +106,7 @@ int TDBZIP::Cardinality(PGLOBAL g) unz_global_info64 ginfo; int err = unzGetGlobalInfo64(zipfile, &ginfo); - Cardinal = (err == UNZ_OK) ? ginfo.number_entry : 0; + Cardinal = (err == UNZ_OK) ? (int)ginfo.number_entry : 0; } else Cardinal = 0; @@ -221,6 +225,14 @@ void ZIPCOL::ReadColumn(PGLOBAL g) case 3: Value->SetValue((int)Tdbz->finfo.compression_method); break; + case 4: + Tdbz->finfo.tmu_date.tm_year -= 1900; + + if (((DTVAL*)Value)->MakeTime((tm*)&Tdbz->finfo.tmu_date)) + Value->SetNull(true); + + Tdbz->finfo.tmu_date.tm_year += 1900; + break; default: Value->SetValue_psz((PSZ)Tdbz->fn); } // endswitch flag diff --git a/storage/connect/tabzip.h b/storage/connect/tabzip.h index 6f1735258e7..dcec3475371 100644 --- a/storage/connect/tabzip.h +++ b/storage/connect/tabzip.h @@ -20,7 +20,7 @@ typedef class ZIPCOL *PZIPCOL; /***********************************************************************/ class DllExport ZIPDEF : public DOSDEF { /* Table description */ friend class TDBZIP; - friend class ZIPFAM; + friend class UNZFAM; public: // Constructor ZIPDEF(void) {} diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h index e18a08a54b8..0cad3ed62f8 100644 --- a/storage/connect/xtable.h +++ b/storage/connect/xtable.h @@ -243,7 +243,8 @@ class DllExport TDBCAT : public TDBASE { // Database routines virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n); - virtual int GetMaxSize(PGLOBAL g); + virtual int Cardinality(PGLOBAL) {return 10;} // To avoid assert + virtual int GetMaxSize(PGLOBAL g); virtual bool OpenDB(PGLOBAL g); virtual int ReadDB(PGLOBAL g); virtual int WriteDB(PGLOBAL g); @@ -275,7 +276,7 @@ class DllExport CATCOL : public COLBLK { virtual int GetAmType(void) {return TYPE_AM_ODBC;} // Methods - virtual void ReadColumn(PGLOBAL g); + virtual void ReadColumn(PGLOBAL g); protected: CATCOL(void) {} // Default constructor not to be used |