summaryrefslogtreecommitdiff
path: root/storage/connect
diff options
context:
space:
mode:
Diffstat (limited to 'storage/connect')
-rw-r--r--storage/connect/CMakeLists.txt41
-rw-r--r--storage/connect/array.cpp16
-rw-r--r--storage/connect/array.h1
-rw-r--r--storage/connect/blkfil.cpp28
-rw-r--r--storage/connect/block.h10
-rw-r--r--storage/connect/catalog.h48
-rw-r--r--storage/connect/checklvl.h7
-rw-r--r--storage/connect/colblk.cpp834
-rw-r--r--storage/connect/colblk.h6
-rw-r--r--storage/connect/connect.cc52
-rw-r--r--storage/connect/domdoc.cpp97
-rw-r--r--storage/connect/domdoc.h19
-rw-r--r--storage/connect/filamap.cpp35
-rw-r--r--storage/connect/filamap.h1
-rw-r--r--storage/connect/filamdbf.cpp77
-rw-r--r--storage/connect/filamfix.cpp84
-rw-r--r--storage/connect/filamtxt.cpp66
-rw-r--r--storage/connect/filamtxt.h5
-rwxr-xr-xstorage/connect/filamvct.cpp98
-rw-r--r--storage/connect/filamzip.cpp38
-rw-r--r--storage/connect/filter.cpp6
-rw-r--r--storage/connect/filter.h6
-rw-r--r--storage/connect/fmdlex.c5
-rw-r--r--storage/connect/global.h22
-rw-r--r--storage/connect/ha_connect.cc790
-rw-r--r--storage/connect/ha_connect.h20
-rw-r--r--storage/connect/json.cpp2217
-rw-r--r--storage/connect/json.h516
-rw-r--r--storage/connect/jsonudf.cpp690
-rw-r--r--storage/connect/libdoc.cpp76
-rw-r--r--storage/connect/macutil.cpp8
-rw-r--r--storage/connect/macutil.h8
-rw-r--r--storage/connect/maputil.cpp2
-rw-r--r--storage/connect/mycat.cc108
-rw-r--r--storage/connect/mycat.h44
-rw-r--r--storage/connect/myconn.cpp21
-rw-r--r--storage/connect/myconn.h12
-rw-r--r--storage/connect/mysql-test/connect/my.cnf34
-rw-r--r--storage/connect/mysql-test/connect/r/bin.result12
-rw-r--r--storage/connect/mysql-test/connect/r/json.result116
-rw-r--r--storage/connect/mysql-test/connect/r/json_udf.result167
-rw-r--r--storage/connect/mysql-test/connect/r/odbc_oracle.result10
-rw-r--r--storage/connect/mysql-test/connect/r/xml_html.result32
-rw-r--r--storage/connect/mysql-test/connect/std_data/beers.xml16
-rw-r--r--storage/connect/mysql-test/connect/std_data/biblio.json (renamed from storage/connect/mysql-test/connect/std_data/biblio.jsn)90
-rw-r--r--storage/connect/mysql-test/connect/std_data/bookstore.xml62
-rw-r--r--storage/connect/mysql-test/connect/std_data/coffee.htm24
-rw-r--r--storage/connect/mysql-test/connect/std_data/expense.json (renamed from storage/connect/mysql-test/connect/std_data/expense.jsn)316
-rw-r--r--storage/connect/mysql-test/connect/std_data/mulexp3.json (renamed from storage/connect/mysql-test/connect/std_data/mulexp3.jsn)104
-rw-r--r--storage/connect/mysql-test/connect/std_data/mulexp4.json (renamed from storage/connect/mysql-test/connect/std_data/mulexp4.jsn)104
-rw-r--r--storage/connect/mysql-test/connect/std_data/mulexp5.json (renamed from storage/connect/mysql-test/connect/std_data/mulexp5.jsn)104
-rw-r--r--storage/connect/mysql-test/connect/std_data/sexe.csv6
-rw-r--r--storage/connect/mysql-test/connect/std_data/sitmat.csv14
-rw-r--r--storage/connect/mysql-test/connect/t/alter.test278
-rw-r--r--storage/connect/mysql-test/connect/t/alter_xml.test58
-rw-r--r--storage/connect/mysql-test/connect/t/bin.test154
-rw-r--r--storage/connect/mysql-test/connect/t/datest.test32
-rw-r--r--storage/connect/mysql-test/connect/t/fmt.test170
-rw-r--r--storage/connect/mysql-test/connect/t/general.test32
-rw-r--r--storage/connect/mysql-test/connect/t/json.test511
-rw-r--r--storage/connect/mysql-test/connect/t/json_udf.inc36
-rw-r--r--storage/connect/mysql-test/connect/t/json_udf.test93
-rw-r--r--storage/connect/mysql-test/connect/t/mrr.test132
-rw-r--r--storage/connect/mysql-test/connect/t/mul.test86
-rw-r--r--storage/connect/mysql-test/connect/t/myconn.inc54
-rw-r--r--storage/connect/mysql-test/connect/t/myconn_cleanup.inc18
-rw-r--r--storage/connect/mysql-test/connect/t/mysql.test944
-rw-r--r--storage/connect/mysql-test/connect/t/mysql_discovery.test66
-rw-r--r--storage/connect/mysql-test/connect/t/mysql_exec.test90
-rw-r--r--storage/connect/mysql-test/connect/t/mysql_grant.test156
-rw-r--r--storage/connect/mysql-test/connect/t/mysql_new.test650
-rw-r--r--storage/connect/mysql-test/connect/t/null.test174
-rw-r--r--storage/connect/mysql-test/connect/t/occur.test122
-rw-r--r--storage/connect/mysql-test/connect/t/odbc_sqlite3.test180
-rw-r--r--storage/connect/mysql-test/connect/t/part_file.test332
-rw-r--r--storage/connect/mysql-test/connect/t/part_table.test184
-rw-r--r--storage/connect/mysql-test/connect/t/pivot.test326
-rw-r--r--storage/connect/mysql-test/connect/t/tbl.test106
-rw-r--r--storage/connect/mysql-test/connect/t/unsigned.test70
-rw-r--r--storage/connect/mysql-test/connect/t/upd.test306
-rw-r--r--storage/connect/mysql-test/connect/t/updelx.test192
-rw-r--r--storage/connect/mysql-test/connect/t/updelx2.test44
-rw-r--r--storage/connect/mysql-test/connect/t/xcol.test82
-rw-r--r--storage/connect/mysql-test/connect/t/xml_html.test39
-rw-r--r--storage/connect/mysql-test/connect/t/xml_mdev5261.test54
-rw-r--r--storage/connect/myutil.cpp28
-rw-r--r--storage/connect/odbccat.h14
-rw-r--r--storage/connect/odbconn.cpp189
-rw-r--r--storage/connect/odbconn.h24
-rw-r--r--storage/connect/os.h10
-rw-r--r--storage/connect/osutil.c2
-rw-r--r--storage/connect/plgdbsem.h20
-rw-r--r--storage/connect/plgdbutl.cpp75
-rw-r--r--storage/connect/plgxml.h15
-rw-r--r--storage/connect/plugutil.c58
-rw-r--r--storage/connect/rcmsg.c136
-rw-r--r--storage/connect/reldef.cpp170
-rw-r--r--storage/connect/reldef.h12
-rw-r--r--storage/connect/tabcol.cpp8
-rw-r--r--storage/connect/tabdos.cpp45
-rw-r--r--storage/connect/tabdos.h14
-rw-r--r--storage/connect/tabfix.cpp152
-rw-r--r--storage/connect/tabfix.h29
-rw-r--r--storage/connect/tabfmt.cpp18
-rw-r--r--storage/connect/tabfmt.h4
-rw-r--r--storage/connect/tabjson.cpp1276
-rw-r--r--storage/connect/tabjson.h91
-rw-r--r--storage/connect/table.cpp34
-rw-r--r--storage/connect/tabmac.cpp8
-rw-r--r--storage/connect/tabmac.h8
-rw-r--r--storage/connect/tabmul.cpp105
-rw-r--r--storage/connect/tabmul.h18
-rw-r--r--storage/connect/tabmysql.cpp60
-rw-r--r--storage/connect/tabmysql.h8
-rw-r--r--storage/connect/taboccur.cpp21
-rw-r--r--storage/connect/tabodbc.cpp245
-rw-r--r--storage/connect/tabodbc.h15
-rw-r--r--storage/connect/tabpivot.cpp39
-rw-r--r--storage/connect/tabpivot.h3
-rw-r--r--storage/connect/tabsys.cpp76
-rw-r--r--storage/connect/tabsys.h364
-rw-r--r--storage/connect/tabtbl.cpp35
-rw-r--r--storage/connect/tabtbl.h2
-rw-r--r--storage/connect/tabutil.cpp69
-rw-r--r--storage/connect/tabutil.h13
-rw-r--r--storage/connect/tabvct.cpp14
-rw-r--r--storage/connect/tabvir.cpp12
-rw-r--r--storage/connect/tabvir.h2
-rw-r--r--storage/connect/tabwmi.cpp6
-rw-r--r--storage/connect/tabxcl.cpp15
-rw-r--r--storage/connect/tabxcl.h3
-rw-r--r--storage/connect/tabxml.cpp481
-rw-r--r--storage/connect/tabxml.h26
-rw-r--r--storage/connect/user_connect.cc6
-rw-r--r--storage/connect/user_connect.h2
-rw-r--r--storage/connect/valblk.cpp17
-rw-r--r--storage/connect/valblk.h32
-rw-r--r--storage/connect/value.cpp125
-rw-r--r--storage/connect/value.h34
-rwxr-xr-xstorage/connect/xindex.cpp130
-rw-r--r--storage/connect/xindex.h32
-rw-r--r--storage/connect/xobject.cpp54
-rw-r--r--storage/connect/xobject.h6
-rw-r--r--storage/connect/xtable.h32
144 files changed, 10420 insertions, 7218 deletions
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt
index 956372e4960..02fe5ee8dad 100644
--- a/storage/connect/CMakeLists.txt
+++ b/storage/connect/CMakeLists.txt
@@ -21,18 +21,18 @@ ha_connect.cc connect.cc user_connect.cc mycat.cc
fmdlex.c osutil.c plugutil.c rcmsg.c rcmsg.h
array.cpp blkfil.cpp colblk.cpp csort.cpp
filamap.cpp filamdbf.cpp filamfix.cpp filamtxt.cpp filamvct.cpp filamzip.cpp
-filter.cpp json.cpp maputil.cpp myutil.cpp plgdbutl.cpp reldef.cpp tabcol.cpp
-tabdos.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp tabmul.cpp taboccur.cpp
-tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp tabvct.cpp tabvir.cpp
-tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp
+filter.cpp json.cpp jsonudf.cpp maputil.cpp myconn.cpp myutil.cpp plgdbutl.cpp
+reldef.cpp tabcol.cpp tabdos.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp
+tabmul.cpp tabmysql.cpp taboccur.cpp tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp
+tabvct.cpp tabvir.cpp tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp
array.h blkfil.h block.h catalog.h checklvl.h colblk.h connect.h csort.h
engmsg.h filamap.h filamdbf.h filamfix.h filamtxt.h filamvct.h filamzip.h
filter.h global.h ha_connect.h inihandl.h json.h maputil.h msgid.h mycat.h
-myutil.h os.h osutil.h plgcnx.h plgdbsem.h preparse.h reldef.h resource.h
-tabcol.h tabdos.h tabfix.h tabfmt.h tabjson.h tabmul.h taboccur.h tabpivot.h
-tabsys.h tabtbl.h tabutil.h tabvct.h tabvir.h tabxcl.h user_connect.h
-valblk.h value.h xindex.h xobject.h xtable.h)
+myconn.h myutil.h os.h osutil.h plgcnx.h plgdbsem.h preparse.h reldef.h
+resource.h tabcol.h tabdos.h tabfix.h tabfmt.h tabjson.h tabmul.h tabmysql.h
+taboccur.h tabpivot.h tabsys.h tabtbl.h tabutil.h tabvct.h tabvir.h tabxcl.h
+user_connect.h valblk.h value.h xindex.h xobject.h xtable.h)
#
# Definitions that are shared for all OSes
@@ -166,24 +166,15 @@ IF(LIBXML2_FOUND OR MSXML_FOUND)
ENDIF()
#
-# MySQL
+# MySQL is now included unconditionnally
#
-OPTION(CONNECT_WITH_MYSQL
- "Compile CONNECT storage engine with remote MySQL connection support"
- ON)
-
-IF(CONNECT_WITH_MYSQL)
- SET(CONNECT_SOURCES ${CONNECT_SOURCES}
- myconn.cpp myconn.h tabmysql.cpp tabmysql.h)
- add_definitions(-DMYSQL_SUPPORT)
- IF(NOT UNIX)
- #
- # TODO: remove this
- # change to use "#include "../../include/mysql.h" in the sources.
- INCLUDE_DIRECTORIES("../../include/mysql")
- ENDIF(NOT UNIX)
-ENDIF(CONNECT_WITH_MYSQL)
+IF(NOT UNIX)
+ #
+ # TODO: remove this
+ # change to use "#include "../../include/mysql.h" in the sources.
+ INCLUDE_DIRECTORIES("../../include/mysql")
+ENDIF(NOT UNIX)
#
@@ -232,6 +223,8 @@ IF(CONNECT_WITH_ODBC)
DOC "Specify the ODBC driver manager library here."
)
+ mark_as_advanced(ODBC_LIBRARY ODBC_INCLUDE_DIR)
+
IF(ODBC_INCLUDE_DIR AND ODBC_LIBRARY)
set(CMAKE_REQUIRED_LIBRARIES ${ODBC_LIBRARY})
set(CMAKE_REQUIRED_INCLUDES ${ODBC_INCLUDE_DIR})
diff --git a/storage/connect/array.cpp b/storage/connect/array.cpp
index a2f537436c9..193514eeb99 100644
--- a/storage/connect/array.cpp
+++ b/storage/connect/array.cpp
@@ -1,7 +1,7 @@
/************* Array C++ Functions Source Code File (.CPP) *************/
/* Name: ARRAY.CPP Version 2.3 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* This file contains the XOBJECT derived class ARRAY functions. */
/* ARRAY is used for elaborate type of processing, such as sorting */
@@ -19,14 +19,14 @@
#include "sql_class.h"
//#include "sql_time.h"
-#if defined(WIN32)
+#if defined(__WIN__)
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h> // for uintprt_h
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Include required application header files */
@@ -186,7 +186,7 @@ ARRAY::ARRAY(PGLOBAL g, int type, int size, int length, int prec)
// The error message was built by PlgDBalloc
Type = TYPE_ERROR;
else if (type != TYPE_PCHAR)
- Value = AllocateValue(g, type, Len, prec, NULL);
+ Value = AllocateValue(g, type, Len, prec);
Constant = TRUE;
} // end of ARRAY constructor
@@ -610,7 +610,7 @@ int ARRAY::Convert(PGLOBAL g, int k, PVAL vp)
// The error message was built by PlgDBalloc
return TYPE_ERROR;
else
- Value = AllocateValue(g, Type, Len, prec, NULL);
+ Value = AllocateValue(g, Type, Len, prec);
/*********************************************************************/
/* Converting STRING to DATE can be done according to date format. */
@@ -848,7 +848,7 @@ void *ARRAY::GetSortIndex(PGLOBAL g)
/* the indication of whether the Find will be always true, always not */
/* true or other. */
/***********************************************************************/
-int ARRAY::BlockTest(PGLOBAL g, int opc, int opm,
+int ARRAY::BlockTest(PGLOBAL, int opc, int opm,
void *minp, void *maxp, bool s)
{
bool bin, bax, pin, pax, veq, all = (opm == 2);
@@ -1038,7 +1038,7 @@ void ARRAY::Print(PGLOBAL g, FILE *f, uint n)
/***********************************************************************/
/* Make string output of ARRAY contents. */
/***********************************************************************/
-void ARRAY::Print(PGLOBAL g, char *ps, uint z)
+void ARRAY::Print(PGLOBAL, char *ps, uint z)
{
if (z < 16)
return;
diff --git a/storage/connect/array.h b/storage/connect/array.h
index 4a818414e9c..6fb38ae6b47 100644
--- a/storage/connect/array.h
+++ b/storage/connect/array.h
@@ -50,6 +50,7 @@ class DllExport ARRAY : public XOBJECT, public CSORT { // Array descblock
// void SetCorrel(bool b) {Correlated = b;}
// Methods
+ using XOBJECT::GetIntValue;
virtual void Reset(void) {Bot = -1;}
virtual int Qcompare(int *, int *);
virtual bool Compare(PXOB) {assert(FALSE); return FALSE;}
diff --git a/storage/connect/blkfil.cpp b/storage/connect/blkfil.cpp
index 802231b24ec..1f5a1a27ae5 100644
--- a/storage/connect/blkfil.cpp
+++ b/storage/connect/blkfil.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2004-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2004-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -20,13 +20,13 @@
#include "sql_class.h"
//#include "sql_time.h"
-#if defined(WIN32)
+#if defined(__WIN__)
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Include application header files: */
@@ -56,7 +56,7 @@ BLOCKFILTER::BLOCKFILTER(PTDBDOS tdbp, int op)
/***********************************************************************/
/* Make file output of BLOCKFILTER contents. */
/***********************************************************************/
-void BLOCKFILTER::Print(PGLOBAL g, FILE *f, uint n)
+void BLOCKFILTER::Print(PGLOBAL, FILE *f, uint n)
{
char m[64];
@@ -70,7 +70,7 @@ void BLOCKFILTER::Print(PGLOBAL g, FILE *f, uint n)
/***********************************************************************/
/* Make string output of BLOCKFILTER contents. */
/***********************************************************************/
-void BLOCKFILTER::Print(PGLOBAL g, char *ps, uint z)
+void BLOCKFILTER::Print(PGLOBAL, char *ps, uint z)
{
strncat(ps, "BlockFilter(s)", z);
} // end of Print
@@ -186,7 +186,7 @@ void BLKFILARI::Reset(PGLOBAL g)
/***********************************************************************/
/* Evaluate block filter for arithmetic operators. */
/***********************************************************************/
-int BLKFILARI::BlockEval(PGLOBAL g)
+int BLKFILARI::BlockEval(PGLOBAL)
{
int mincmp, maxcmp, n;
@@ -306,7 +306,7 @@ void BLKFILAR2::MakeValueBitmap(void)
/***********************************************************************/
/* Evaluate XDB2 block filter for arithmetic operators. */
/***********************************************************************/
-int BLKFILAR2::BlockEval(PGLOBAL g)
+int BLKFILAR2::BlockEval(PGLOBAL)
{
#if defined(_DEBUG)
assert (Colp->IsClustered());
@@ -428,7 +428,7 @@ void BLKFILMR2::MakeValueBitmap(void)
/***********************************************************************/
/* Evaluate XDB2 block filter for arithmetic operators. */
/***********************************************************************/
-int BLKFILMR2::BlockEval(PGLOBAL g)
+int BLKFILMR2::BlockEval(PGLOBAL)
{
#if defined(_DEBUG)
assert (Colp->IsClustered());
@@ -514,7 +514,7 @@ void BLKSPCARI::Reset(PGLOBAL g)
/***********************************************************************/
/* Evaluate block filter for arithmetic operators (ROWID) */
/***********************************************************************/
-int BLKSPCARI::BlockEval(PGLOBAL g)
+int BLKSPCARI::BlockEval(PGLOBAL)
{
int mincmp, maxcmp, n, m;
@@ -605,7 +605,7 @@ BLKFILIN::BLKFILIN(PGLOBAL g, PTDBDOS tdbp, int op, int opm, PXOB *xp)
/***********************************************************************/
/* Reset: have the sorted array reset its Bot value to -1 (bottom). */
/***********************************************************************/
-void BLKFILIN::Reset(PGLOBAL g)
+void BLKFILIN::Reset(PGLOBAL)
{
Arap->Reset();
// MakeValueBitmap(); // Does nothing for class BLKFILIN
@@ -736,7 +736,7 @@ void BLKFILIN2::MakeValueBitmap(void)
/* ended string in case of string argument. This is because the ARRAY */
/* can have a different width than the char column. */
/***********************************************************************/
-int BLKFILIN2::BlockEval(PGLOBAL g)
+int BLKFILIN2::BlockEval(PGLOBAL)
{
if (N < 0)
return Result; // Was set in MakeValueBitmap
@@ -909,7 +909,7 @@ int BLKFILIN2::BlockEval(PGLOBAL g)
/***********************************************************************/
/* BLKSPCIN constructor. */
/***********************************************************************/
-BLKSPCIN::BLKSPCIN(PGLOBAL g, PTDBDOS tdbp, int op, int opm,
+BLKSPCIN::BLKSPCIN(PGLOBAL, PTDBDOS tdbp, int op, int opm,
PXOB *xp, int bsize)
: BLOCKFILTER(tdbp, op)
{
@@ -930,7 +930,7 @@ BLKSPCIN::BLKSPCIN(PGLOBAL g, PTDBDOS tdbp, int op, int opm,
/***********************************************************************/
/* Reset: have the sorted array reset its Bot value to -1 (bottom). */
/***********************************************************************/
-void BLKSPCIN::Reset(PGLOBAL g)
+void BLKSPCIN::Reset(PGLOBAL)
{
Arap->Reset();
} // end of Reset
diff --git a/storage/connect/block.h b/storage/connect/block.h
index d63a899d1f5..aa4edde5ec9 100644
--- a/storage/connect/block.h
+++ b/storage/connect/block.h
@@ -24,11 +24,11 @@
#if !defined(BLOCK_DEFINED)
#define BLOCK_DEFINED
-#if defined(WIN32) && !defined(NOEX)
+#if defined(__WIN__) && !defined(NOEX)
#define DllExport __declspec( dllexport )
-#else // !WIN32
+#else // !__WIN__
#define DllExport
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Definition of class BLOCK with its method function new. */
@@ -38,7 +38,7 @@ typedef class BLOCK *PBLOCK;
class DllExport BLOCK {
public:
void * operator new(size_t size, PGLOBAL g, void *p = NULL) {
-// if (trace > 2)
+// if (trace > 3)
// htrc("New BLOCK: size=%d g=%p p=%p\n", size, g, p);
return (PlugSubAlloc(g, p, size));
@@ -50,7 +50,7 @@ class DllExport BLOCK {
#if !defined(__BORLANDC__)
// Avoid warning C4291 by defining a matching dummy delete operator
void operator delete(void *, PGLOBAL, void *) {}
- void operator delete(void *ptr,size_t size) {}
+ void operator delete(void *, size_t) {}
#endif
virtual ~BLOCK() {}
diff --git a/storage/connect/catalog.h b/storage/connect/catalog.h
index 5baab294737..6488b513ba9 100644
--- a/storage/connect/catalog.h
+++ b/storage/connect/catalog.h
@@ -1,7 +1,7 @@
/*************** Catalog H Declares Source Code File (.H) **************/
/* Name: CATALOG.H Version 3.3 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2000-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2000-2015 */
/* */
/* This file contains the CATALOG PlugDB classes definitions. */
/***********************************************************************/
@@ -73,33 +73,29 @@ class DllExport CATALOG {
// Methods
virtual void Reset(void) {}
//virtual void SetDataPath(PGLOBAL g, const char *path) {}
- virtual bool CheckName(PGLOBAL g, char *name) {return true;}
- virtual bool ClearName(PGLOBAL g, PSZ name) {return true;}
- virtual PRELDEF MakeOneTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) {return NULL;}
- virtual PRELDEF GetTableDescEx(PGLOBAL g, PTABLE tablep) {return NULL;}
- virtual PRELDEF GetTableDesc(PGLOBAL g, LPCSTR name, LPCSTR type,
- PRELDEF *prp = NULL) {return NULL;}
- virtual PRELDEF GetFirstTable(PGLOBAL g) {return NULL;}
- virtual PRELDEF GetNextTable(PGLOBAL g) {return NULL;}
- virtual bool TestCond(PGLOBAL g, const char *name, const char *type)
- {return true;}
- virtual bool DropTable(PGLOBAL g, PSZ name, bool erase) {return true;}
- virtual PTDB GetTable(PGLOBAL g, PTABLE tablep,
- MODE mode = MODE_READ, LPCSTR type = NULL)
- {return NULL;}
- virtual void TableNames(PGLOBAL g, char *buffer, int maxbuf, int info[]) {}
- virtual void ColumnNames(PGLOBAL g, char *tabname, char *buffer,
- int maxbuf, int info[]) {}
- virtual void ColumnDefs(PGLOBAL g, char *tabname, char *buffer,
- int maxbuf, int info[]) {}
- virtual void *DecodeValues(PGLOBAL g, char *tabname, char *colname,
- char *buffer, int maxbuf, int info[]) {return NULL;}
- virtual int ColumnType(PGLOBAL g, char *tabname, char *colname) {return 0;}
- virtual void ClearDB(PGLOBAL g) {}
+ virtual bool CheckName(PGLOBAL, char*) {return true;}
+ virtual bool ClearName(PGLOBAL, PSZ) {return true;}
+ virtual PRELDEF MakeOneTableDesc(PGLOBAL, LPCSTR, LPCSTR) {return NULL;}
+ virtual PRELDEF GetTableDescEx(PGLOBAL, PTABLE) {return NULL;}
+ virtual PRELDEF GetTableDesc(PGLOBAL, LPCSTR, LPCSTR,
+ PRELDEF* = NULL) {return NULL;}
+ virtual PRELDEF GetFirstTable(PGLOBAL) {return NULL;}
+ virtual PRELDEF GetNextTable(PGLOBAL) {return NULL;}
+ virtual bool TestCond(PGLOBAL, const char*, const char*) {return true;}
+ virtual bool DropTable(PGLOBAL, PSZ, bool) {return true;}
+ virtual PTDB GetTable(PGLOBAL, PTABLE,
+ MODE = MODE_READ, LPCSTR = NULL) {return NULL;}
+ virtual void TableNames(PGLOBAL, char*, int, int[]) {}
+ virtual void ColumnNames(PGLOBAL, char*, char*, int, int[]) {}
+ virtual void ColumnDefs(PGLOBAL, char*, char*, int, int[]) {}
+ virtual void *DecodeValues(PGLOBAL, char*, char*, char*,
+ int, int[]) {return NULL;}
+ virtual int ColumnType(PGLOBAL, char*, char*) {return 0;}
+ virtual void ClearDB(PGLOBAL) {}
protected:
- virtual bool ClearSection(PGLOBAL g, const char *key, const char *section) {return true;}
- virtual PRELDEF MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) {return NULL;}
+ virtual bool ClearSection(PGLOBAL, const char*, const char*) {return true;}
+ virtual PRELDEF MakeTableDesc(PGLOBAL, LPCSTR, LPCSTR) {return NULL;}
// Members
char *Cbuf; /* Buffer used for col section */
diff --git a/storage/connect/checklvl.h b/storage/connect/checklvl.h
index d1e37afbc93..0c234dfb8b8 100644
--- a/storage/connect/checklvl.h
+++ b/storage/connect/checklvl.h
@@ -40,4 +40,11 @@ enum USETEMP {TMP_NO = 0, /* Never */
TMP_FORCE = 3, /* Forced for MAP tables */
TMP_TEST = 4}; /* Testing value */
+/***********************************************************************/
+/* Following definitions indicate conversion of TEXT columns. */
+/***********************************************************************/
+enum TYPCONV {TPC_NO = 0, /* Never */
+ TPC_YES = 1, /* Always */
+ TPC_SKIP = 2}; /* Skip TEXT columns */
+
#endif // _CHKLVL_DEFINED_
diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp
index 78aba7bc494..80b405be041 100644
--- a/storage/connect/colblk.cpp
+++ b/storage/connect/colblk.cpp
@@ -1,417 +1,417 @@
-/************* Colblk C++ Functions Source Code File (.CPP) ************/
-/* Name: COLBLK.CPP Version 2.1 */
-/* */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */
-/* */
-/* This file contains the COLBLK class functions. */
-/***********************************************************************/
-
-/***********************************************************************/
-/* Include relevant MariaDB header file. */
-/***********************************************************************/
-#include "my_global.h"
-
-/***********************************************************************/
-/* Include required application header files */
-/* global.h is header containing all global Plug declarations. */
-/* plgdbsem.h is header containing the DB applic. declarations. */
-/***********************************************************************/
-#include "global.h"
-#include "plgdbsem.h"
-#include "tabcol.h"
-#include "colblk.h"
-#include "xindex.h"
-#include "xtable.h"
-
-/***********************************************************************/
-/* COLBLK protected constructor. */
-/***********************************************************************/
-COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i)
- {
- Next = NULL;
- Index = i;
-//Number = 0;
- ColUse = 0;
-
- if ((Cdp = cdp)) {
- Name = cdp->Name;
- Format = cdp->F;
- Opt = cdp->Opt;
- Long = cdp->Long;
- Precision = cdp->Precision;
- Freq = cdp->Freq;
- Buf_Type = cdp->Buf_Type;
- ColUse |= cdp->Flags; // Used by CONNECT
- Nullable = !!(cdp->Flags & U_NULLS);
- Unsigned = !!(cdp->Flags & U_UNSIGNED);
- } else {
- Name = NULL;
- memset(&Format, 0, sizeof(FORMAT));
- Opt = 0;
- Long = 0;
- Precision = 0;
- Freq = 0;
- Buf_Type = TYPE_ERROR;
- Nullable = false;
- Unsigned = false;
- } // endif cdp
-
- To_Tdb = tdbp;
- Status = BUF_NO;
-//Value = NULL; done in XOBJECT constructor
- To_Kcol = NULL;
- } // end of COLBLK constructor
-
-/***********************************************************************/
-/* COLBLK constructor used for copying columns. */
-/* tdbp is the pointer to the new table descriptor. */
-/***********************************************************************/
-COLBLK::COLBLK(PCOL col1, PTDB tdbp)
- {
- PCOL colp;
-
- // Copy the old column block to the new one
- *this = *col1;
- Next = NULL;
-//To_Orig = col1;
- To_Tdb = tdbp;
-
- if (trace > 1)
- htrc(" copying COLBLK %s from %p to %p\n", Name, col1, this);
-
- if (tdbp)
- // Attach the new column to the table block
- if (!tdbp->GetColumns())
- tdbp->SetColumns(this);
- else {
- for (colp = tdbp->GetColumns(); colp->Next; colp = colp->Next) ;
-
- colp->Next = this;
- } // endelse
-
- } // end of COLBLK copy constructor
-
-/***********************************************************************/
-/* Reset the column descriptor to non evaluated yet. */
-/***********************************************************************/
-void COLBLK::Reset(void)
- {
- Status &= ~BUF_READ;
- } // end of Reset
-
-/***********************************************************************/
-/* Compare: compares itself to an (expression) object and returns */
-/* true if it is equivalent. */
-/***********************************************************************/
-bool COLBLK::Compare(PXOB xp)
- {
- return (this == xp);
- } // end of Compare
-
-/***********************************************************************/
-/* SetFormat: function used to set SELECT output format. */
-/***********************************************************************/
-bool COLBLK::SetFormat(PGLOBAL g, FORMAT& fmt)
- {
- fmt = Format;
-
- if (trace > 1)
- htrc("COLBLK: %p format=%c(%d,%d)\n",
- this, *fmt.Type, fmt.Length, fmt.Prec);
-
- return false;
- } // end of SetFormat
-
-/***********************************************************************/
-/* Eval: get the column value from the last read record or from a */
-/* matching Index column if there is one. */
-/***********************************************************************/
-bool COLBLK::Eval(PGLOBAL g)
- {
- if (trace > 1)
- htrc("Col Eval: %s status=%.4X\n", Name, Status);
-
- if (!GetStatus(BUF_READ)) {
-// if (To_Tdb->IsNull())
-// Value->Reset();
- if (To_Kcol)
- To_Kcol->FillValue(Value);
- else
- ReadColumn(g);
-
- AddStatus(BUF_READ);
- } // endif
-
- return false;
- } // end of Eval
-
-/***********************************************************************/
-/* InitValue: prepare a column block for read operation. */
-/* Now we use Format.Length for the len parameter to avoid strings */
-/* to be truncated when converting from string to coded string. */
-/* Added in version 1.5 is the arguments GetScale() and Domain */
-/* in calling AllocateValue. Domain is used for TYPE_DATE only. */
-/***********************************************************************/
-bool COLBLK::InitValue(PGLOBAL g)
- {
- if (Value)
- return false; // Already done
-
- // Allocate a Value object
- if (!(Value = AllocateValue(g, Buf_Type, Precision,
- GetScale(), Unsigned, GetDomain())))
- return true;
-
- AddStatus(BUF_READY);
- Value->SetNullable(Nullable);
-
- if (trace > 1)
- htrc(" colp=%p type=%d value=%p coluse=%.4X status=%.4X\n",
- this, Buf_Type, Value, ColUse, Status);
-
- return false;
- } // end of InitValue
-
-/***********************************************************************/
-/* SetBuffer: prepare a column block for write operation. */
-/***********************************************************************/
-bool COLBLK::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
- {
- sprintf(g->Message, MSG(UNDEFINED_AM), "SetBuffer");
- return true;
- } // end of SetBuffer
-
-/***********************************************************************/
-/* GetLength: returns an evaluation of the column string length. */
-/***********************************************************************/
-int COLBLK::GetLengthEx(void)
- {
- return Long;
- } // end of GetLengthEx
-
-/***********************************************************************/
-/* ReadColumn: what this routine does is to access the last line */
-/* read from the corresponding table, extract from it the field */
-/* corresponding to this column and convert it to buffer type. */
-/***********************************************************************/
-void COLBLK::ReadColumn(PGLOBAL g)
- {
- sprintf(g->Message, MSG(UNDEFINED_AM), "ReadColumn");
- longjmp(g->jumper[g->jump_level], TYPE_COLBLK);
- } // end of ReadColumn
-
-/***********************************************************************/
-/* WriteColumn: what this routine does is to access the last line */
-/* read from the corresponding table, and rewrite the field */
-/* corresponding to this column from the column buffer and type. */
-/***********************************************************************/
-void COLBLK::WriteColumn(PGLOBAL g)
- {
- sprintf(g->Message, MSG(UNDEFINED_AM), "WriteColumn");
- longjmp(g->jumper[g->jump_level], TYPE_COLBLK);
- } // end of WriteColumn
-
-/***********************************************************************/
-/* Make file output of a column descriptor block. */
-/***********************************************************************/
-void COLBLK::Print(PGLOBAL g, FILE *f, uint n)
- {
- char m[64];
- int i;
- PCOL colp;
-
- memset(m, ' ', n); // Make margin string
- m[n] = '\0';
-
- for (colp = To_Tdb->GetColumns(), i = 1; colp; colp = colp->Next, i++)
- if (colp == this)
- break;
-
- fprintf(f, "%sR%dC%d type=%d F=%.2s(%d,%d)", m, To_Tdb->GetTdb_No(),
- i, GetAmType(), Format.Type, Format.Length, Format.Prec);
- fprintf(f,
- " coluse=%04X status=%04X buftyp=%d value=%p name=%s\n",
- ColUse, Status, Buf_Type, Value, Name);
- } // end of Print
-
-/***********************************************************************/
-/* Make string output of a column descriptor block. */
-/***********************************************************************/
-void COLBLK::Print(PGLOBAL g, char *ps, uint z)
- {
- sprintf(ps, "R%d.%s", To_Tdb->GetTdb_No(), Name);
- } // end of Print
-
-
-/***********************************************************************/
-/* SPCBLK constructor. */
-/***********************************************************************/
-SPCBLK::SPCBLK(PCOLUMN cp)
- : COLBLK((PCOLDEF)NULL, cp->GetTo_Table()->GetTo_Tdb(), 0)
- {
- Name = (char*)cp->GetName();
- Precision = Long = 0;
- Buf_Type = TYPE_ERROR;
- } // end of SPCBLK constructor
-
-/***********************************************************************/
-/* WriteColumn: what this routine does is to access the last line */
-/* read from the corresponding table, and rewrite the field */
-/* corresponding to this column from the column buffer and type. */
-/***********************************************************************/
-void SPCBLK::WriteColumn(PGLOBAL g)
- {
- sprintf(g->Message, MSG(SPCOL_READONLY), Name);
- longjmp(g->jumper[g->jump_level], TYPE_COLBLK);
- } // end of WriteColumn
-
-/***********************************************************************/
-/* RIDBLK constructor for the ROWID special column. */
-/***********************************************************************/
-RIDBLK::RIDBLK(PCOLUMN cp, bool rnm) : SPCBLK(cp)
- {
- Precision = Long = 10;
- Buf_Type = TYPE_INT;
- Rnm = rnm;
- *Format.Type = 'N';
- Format.Length = 10;
- } // end of RIDBLK constructor
-
-/***********************************************************************/
-/* ReadColumn: what this routine does is to return the ordinal */
-/* number of the current row in the table (if Rnm is true) or in the */
-/* current file (if Rnm is false) the same except for multiple tables.*/
-/***********************************************************************/
-void RIDBLK::ReadColumn(PGLOBAL g)
- {
- Value->SetValue(To_Tdb->RowNumber(g, Rnm));
- } // end of ReadColumn
-
-/***********************************************************************/
-/* FIDBLK constructor for the FILEID special column. */
-/***********************************************************************/
-FIDBLK::FIDBLK(PCOLUMN cp, OPVAL op) : SPCBLK(cp), Op(op)
- {
-//Is_Key = 2; for when the MUL table indexed reading will be implemented.
- Precision = Long = _MAX_PATH;
- Buf_Type = TYPE_STRING;
- *Format.Type = 'C';
- Format.Length = Long;
-#if defined(WIN32)
- Format.Prec = 1; // Case insensitive
-#endif // WIN32
- Constant = (!((PTDBASE)To_Tdb)->GetDef()->GetMultiple() &&
- To_Tdb->GetAmType() != TYPE_AM_PLG &&
- To_Tdb->GetAmType() != TYPE_AM_PLM);
- Fn = NULL;
- } // end of FIDBLK constructor
-
-/***********************************************************************/
-/* ReadColumn: what this routine does is to return the current */
-/* file ID of the table (can change for Multiple tables). */
-/***********************************************************************/
-void FIDBLK::ReadColumn(PGLOBAL g)
- {
- if (Fn != ((PTDBASE)To_Tdb)->GetFile(g)) {
- char filename[_MAX_PATH];
-
- Fn = ((PTDBASE)To_Tdb)->GetFile(g);
- PlugSetPath(filename, Fn, ((PTDBASE)To_Tdb)->GetPath());
-
- if (Op != OP_XX) {
- char buff[_MAX_PATH];
-
- Value->SetValue_psz(ExtractFromPath(g, buff, filename, Op));
- } else
- Value->SetValue_psz(filename);
-
- } // endif Fn
-
- } // end of ReadColumn
-
-/***********************************************************************/
-/* TIDBLK constructor for the TABID special column. */
-/***********************************************************************/
-TIDBLK::TIDBLK(PCOLUMN cp) : SPCBLK(cp)
- {
-//Is_Key = 2; for when the MUL table indexed reading will be implemented.
- Precision = Long = 64;
- Buf_Type = TYPE_STRING;
- *Format.Type = 'C';
- Format.Length = Long;
- Format.Prec = 1; // Case insensitive
- Constant = (To_Tdb->GetAmType() != TYPE_AM_TBL);
- Tname = NULL;
- } // end of TIDBLK constructor
-
-/***********************************************************************/
-/* ReadColumn: what this routine does is to return the table ID. */
-/***********************************************************************/
-void TIDBLK::ReadColumn(PGLOBAL g)
- {
- if (Tname == NULL) {
- Tname = (char*)To_Tdb->GetName();
- Value->SetValue_psz(Tname);
- } // endif Tname
-
- } // end of ReadColumn
-
-/***********************************************************************/
-/* PRTBLK constructor for the PARTID special column. */
-/***********************************************************************/
-PRTBLK::PRTBLK(PCOLUMN cp) : SPCBLK(cp)
- {
-//Is_Key = 2; for when the MUL table indexed reading will be implemented.
- Precision = Long = 64;
- Buf_Type = TYPE_STRING;
- *Format.Type = 'C';
- Format.Length = Long;
- Format.Prec = 1; // Case insensitive
- Constant = true; // TODO: check whether this is true indeed
- Pname = NULL;
- } // end of PRTBLK constructor
-
-/***********************************************************************/
-/* ReadColumn: what this routine does is to return the partition ID. */
-/***********************************************************************/
-void PRTBLK::ReadColumn(PGLOBAL g)
- {
- if (Pname == NULL) {
- char *p;
- PTDBASE tdbp = (PTDBASE)To_Tdb;
-
- Pname = tdbp->GetDef()->GetStringCatInfo(g, "partname", "?");
-
- p = strrchr(Pname, '#');
- Value->SetValue_psz((p) ? p + 1 : Pname);
- } // endif Pname
-
- } // end of ReadColumn
-
-/***********************************************************************/
-/* SIDBLK constructor for the SERVID special column. */
-/***********************************************************************/
-SIDBLK::SIDBLK(PCOLUMN cp) : SPCBLK(cp)
- {
-//Is_Key = 2; for when the MUL table indexed reading will be implemented.
- Precision = Long = 64;
- Buf_Type = TYPE_STRING;
- *Format.Type = 'C';
- Format.Length = Long;
- Format.Prec = 1; // Case insensitive
- Constant = (To_Tdb->GetAmType() != TYPE_AM_TBL);
- Sname = NULL;
- } // end of TIDBLK constructor
-
-/***********************************************************************/
-/* ReadColumn: what this routine does is to return the server ID. */
-/***********************************************************************/
-void SIDBLK::ReadColumn(PGLOBAL g)
- {
-//if (Sname == NULL) {
- Sname = (char*)To_Tdb->GetServer();
- Value->SetValue_psz(Sname);
-// } // endif Sname
-
- } // end of ReadColumn
-
+/************* Colblk C++ Functions Source Code File (.CPP) ************/
+/* Name: COLBLK.CPP Version 2.1 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
+/* */
+/* This file contains the COLBLK class functions. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant MariaDB header file. */
+/***********************************************************************/
+#include "my_global.h"
+
+/***********************************************************************/
+/* Include required application header files */
+/* global.h is header containing all global Plug declarations. */
+/* plgdbsem.h is header containing the DB applic. declarations. */
+/***********************************************************************/
+#include "global.h"
+#include "plgdbsem.h"
+#include "tabcol.h"
+#include "colblk.h"
+#include "xindex.h"
+#include "xtable.h"
+
+/***********************************************************************/
+/* COLBLK protected constructor. */
+/***********************************************************************/
+COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i)
+ {
+ Next = NULL;
+ Index = i;
+//Number = 0;
+ ColUse = 0;
+
+ if ((Cdp = cdp)) {
+ Name = cdp->Name;
+ Format = cdp->F;
+ Opt = cdp->Opt;
+ Long = cdp->Long;
+ Precision = cdp->Precision;
+ Freq = cdp->Freq;
+ Buf_Type = cdp->Buf_Type;
+ ColUse |= cdp->Flags; // Used by CONNECT
+ Nullable = !!(cdp->Flags & U_NULLS);
+ Unsigned = !!(cdp->Flags & U_UNSIGNED);
+ } else {
+ Name = NULL;
+ memset(&Format, 0, sizeof(FORMAT));
+ Opt = 0;
+ Long = 0;
+ Precision = 0;
+ Freq = 0;
+ Buf_Type = TYPE_ERROR;
+ Nullable = false;
+ Unsigned = false;
+ } // endif cdp
+
+ To_Tdb = tdbp;
+ Status = BUF_NO;
+//Value = NULL; done in XOBJECT constructor
+ To_Kcol = NULL;
+ } // end of COLBLK constructor
+
+/***********************************************************************/
+/* COLBLK constructor used for copying columns. */
+/* tdbp is the pointer to the new table descriptor. */
+/***********************************************************************/
+COLBLK::COLBLK(PCOL col1, PTDB tdbp)
+ {
+ PCOL colp;
+
+ // Copy the old column block to the new one
+ *this = *col1;
+ Next = NULL;
+//To_Orig = col1;
+ To_Tdb = tdbp;
+
+ if (trace > 1)
+ htrc(" copying COLBLK %s from %p to %p\n", Name, col1, this);
+
+ if (tdbp)
+ // Attach the new column to the table block
+ if (!tdbp->GetColumns())
+ tdbp->SetColumns(this);
+ else {
+ for (colp = tdbp->GetColumns(); colp->Next; colp = colp->Next) ;
+
+ colp->Next = this;
+ } // endelse
+
+ } // end of COLBLK copy constructor
+
+/***********************************************************************/
+/* Reset the column descriptor to non evaluated yet. */
+/***********************************************************************/
+void COLBLK::Reset(void)
+ {
+ Status &= ~BUF_READ;
+ } // end of Reset
+
+/***********************************************************************/
+/* Compare: compares itself to an (expression) object and returns */
+/* true if it is equivalent. */
+/***********************************************************************/
+bool COLBLK::Compare(PXOB xp)
+ {
+ return (this == xp);
+ } // end of Compare
+
+/***********************************************************************/
+/* SetFormat: function used to set SELECT output format. */
+/***********************************************************************/
+bool COLBLK::SetFormat(PGLOBAL, FORMAT& fmt)
+ {
+ fmt = Format;
+
+ if (trace > 1)
+ htrc("COLBLK: %p format=%c(%d,%d)\n",
+ this, *fmt.Type, fmt.Length, fmt.Prec);
+
+ return false;
+ } // end of SetFormat
+
+/***********************************************************************/
+/* Eval: get the column value from the last read record or from a */
+/* matching Index column if there is one. */
+/***********************************************************************/
+bool COLBLK::Eval(PGLOBAL g)
+ {
+ if (trace > 1)
+ htrc("Col Eval: %s status=%.4X\n", Name, Status);
+
+ if (!GetStatus(BUF_READ)) {
+// if (To_Tdb->IsNull())
+// Value->Reset();
+ if (To_Kcol)
+ To_Kcol->FillValue(Value);
+ else
+ ReadColumn(g);
+
+ AddStatus(BUF_READ);
+ } // endif
+
+ return false;
+ } // end of Eval
+
+/***********************************************************************/
+/* InitValue: prepare a column block for read operation. */
+/* Now we use Format.Length for the len parameter to avoid strings */
+/* to be truncated when converting from string to coded string. */
+/* Added in version 1.5 is the arguments GetScale() and Domain */
+/* in calling AllocateValue. Domain is used for TYPE_DATE only. */
+/***********************************************************************/
+bool COLBLK::InitValue(PGLOBAL g)
+ {
+ if (Value)
+ return false; // Already done
+
+ // Allocate a Value object
+ if (!(Value = AllocateValue(g, Buf_Type, Precision,
+ GetScale(), Unsigned, GetDomain())))
+ return true;
+
+ AddStatus(BUF_READY);
+ Value->SetNullable(Nullable);
+
+ if (trace > 1)
+ htrc(" colp=%p type=%d value=%p coluse=%.4X status=%.4X\n",
+ this, Buf_Type, Value, ColUse, Status);
+
+ return false;
+ } // end of InitValue
+
+/***********************************************************************/
+/* SetBuffer: prepare a column block for write operation. */
+/***********************************************************************/
+bool COLBLK::SetBuffer(PGLOBAL g, PVAL, bool, bool)
+ {
+ sprintf(g->Message, MSG(UNDEFINED_AM), "SetBuffer");
+ return true;
+ } // end of SetBuffer
+
+/***********************************************************************/
+/* GetLength: returns an evaluation of the column string length. */
+/***********************************************************************/
+int COLBLK::GetLengthEx(void)
+ {
+ return Long;
+ } // end of GetLengthEx
+
+/***********************************************************************/
+/* ReadColumn: what this routine does is to access the last line */
+/* read from the corresponding table, extract from it the field */
+/* corresponding to this column and convert it to buffer type. */
+/***********************************************************************/
+void COLBLK::ReadColumn(PGLOBAL g)
+ {
+ sprintf(g->Message, MSG(UNDEFINED_AM), "ReadColumn");
+ longjmp(g->jumper[g->jump_level], TYPE_COLBLK);
+ } // end of ReadColumn
+
+/***********************************************************************/
+/* WriteColumn: what this routine does is to access the last line */
+/* read from the corresponding table, and rewrite the field */
+/* corresponding to this column from the column buffer and type. */
+/***********************************************************************/
+void COLBLK::WriteColumn(PGLOBAL g)
+ {
+ sprintf(g->Message, MSG(UNDEFINED_AM), "WriteColumn");
+ longjmp(g->jumper[g->jump_level], TYPE_COLBLK);
+ } // end of WriteColumn
+
+/***********************************************************************/
+/* Make file output of a column descriptor block. */
+/***********************************************************************/
+void COLBLK::Print(PGLOBAL, FILE *f, uint n)
+ {
+ char m[64];
+ int i;
+ PCOL colp;
+
+ memset(m, ' ', n); // Make margin string
+ m[n] = '\0';
+
+ for (colp = To_Tdb->GetColumns(), i = 1; colp; colp = colp->Next, i++)
+ if (colp == this)
+ break;
+
+ fprintf(f, "%sR%dC%d type=%d F=%.2s(%d,%d)", m, To_Tdb->GetTdb_No(),
+ i, GetAmType(), Format.Type, Format.Length, Format.Prec);
+ fprintf(f,
+ " coluse=%04X status=%04X buftyp=%d value=%p name=%s\n",
+ ColUse, Status, Buf_Type, Value, Name);
+ } // end of Print
+
+/***********************************************************************/
+/* Make string output of a column descriptor block. */
+/***********************************************************************/
+void COLBLK::Print(PGLOBAL, char *ps, uint)
+ {
+ sprintf(ps, "R%d.%s", To_Tdb->GetTdb_No(), Name);
+ } // end of Print
+
+
+/***********************************************************************/
+/* SPCBLK constructor. */
+/***********************************************************************/
+SPCBLK::SPCBLK(PCOLUMN cp)
+ : COLBLK((PCOLDEF)NULL, cp->GetTo_Table()->GetTo_Tdb(), 0)
+ {
+ Name = (char*)cp->GetName();
+ Precision = Long = 0;
+ Buf_Type = TYPE_ERROR;
+ } // end of SPCBLK constructor
+
+/***********************************************************************/
+/* WriteColumn: what this routine does is to access the last line */
+/* read from the corresponding table, and rewrite the field */
+/* corresponding to this column from the column buffer and type. */
+/***********************************************************************/
+void SPCBLK::WriteColumn(PGLOBAL g)
+ {
+ sprintf(g->Message, MSG(SPCOL_READONLY), Name);
+ longjmp(g->jumper[g->jump_level], TYPE_COLBLK);
+ } // end of WriteColumn
+
+/***********************************************************************/
+/* RIDBLK constructor for the ROWID special column. */
+/***********************************************************************/
+RIDBLK::RIDBLK(PCOLUMN cp, bool rnm) : SPCBLK(cp)
+ {
+ Precision = Long = 10;
+ Buf_Type = TYPE_INT;
+ Rnm = rnm;
+ *Format.Type = 'N';
+ Format.Length = 10;
+ } // end of RIDBLK constructor
+
+/***********************************************************************/
+/* ReadColumn: what this routine does is to return the ordinal */
+/* number of the current row in the table (if Rnm is true) or in the */
+/* current file (if Rnm is false) the same except for multiple tables.*/
+/***********************************************************************/
+void RIDBLK::ReadColumn(PGLOBAL g)
+ {
+ Value->SetValue(To_Tdb->RowNumber(g, Rnm));
+ } // end of ReadColumn
+
+/***********************************************************************/
+/* FIDBLK constructor for the FILEID special column. */
+/***********************************************************************/
+FIDBLK::FIDBLK(PCOLUMN cp, OPVAL op) : SPCBLK(cp), Op(op)
+ {
+//Is_Key = 2; for when the MUL table indexed reading will be implemented.
+ Precision = Long = _MAX_PATH;
+ Buf_Type = TYPE_STRING;
+ *Format.Type = 'C';
+ Format.Length = Long;
+#if defined(__WIN__)
+ Format.Prec = 1; // Case insensitive
+#endif // __WIN__
+ Constant = (!((PTDBASE)To_Tdb)->GetDef()->GetMultiple() &&
+ To_Tdb->GetAmType() != TYPE_AM_PLG &&
+ To_Tdb->GetAmType() != TYPE_AM_PLM);
+ Fn = NULL;
+ } // end of FIDBLK constructor
+
+/***********************************************************************/
+/* ReadColumn: what this routine does is to return the current */
+/* file ID of the table (can change for Multiple tables). */
+/***********************************************************************/
+void FIDBLK::ReadColumn(PGLOBAL g)
+ {
+ if (Fn != ((PTDBASE)To_Tdb)->GetFile(g)) {
+ char filename[_MAX_PATH];
+
+ Fn = ((PTDBASE)To_Tdb)->GetFile(g);
+ PlugSetPath(filename, Fn, ((PTDBASE)To_Tdb)->GetPath());
+
+ if (Op != OP_XX) {
+ char buff[_MAX_PATH];
+
+ Value->SetValue_psz(ExtractFromPath(g, buff, filename, Op));
+ } else
+ Value->SetValue_psz(filename);
+
+ } // endif Fn
+
+ } // end of ReadColumn
+
+/***********************************************************************/
+/* TIDBLK constructor for the TABID special column. */
+/***********************************************************************/
+TIDBLK::TIDBLK(PCOLUMN cp) : SPCBLK(cp)
+ {
+//Is_Key = 2; for when the MUL table indexed reading will be implemented.
+ Precision = Long = 64;
+ Buf_Type = TYPE_STRING;
+ *Format.Type = 'C';
+ Format.Length = Long;
+ Format.Prec = 1; // Case insensitive
+ Constant = (To_Tdb->GetAmType() != TYPE_AM_TBL);
+ Tname = NULL;
+ } // end of TIDBLK constructor
+
+/***********************************************************************/
+/* ReadColumn: what this routine does is to return the table ID. */
+/***********************************************************************/
+void TIDBLK::ReadColumn(PGLOBAL)
+ {
+ if (Tname == NULL) {
+ Tname = (char*)To_Tdb->GetName();
+ Value->SetValue_psz(Tname);
+ } // endif Tname
+
+ } // end of ReadColumn
+
+/***********************************************************************/
+/* PRTBLK constructor for the PARTID special column. */
+/***********************************************************************/
+PRTBLK::PRTBLK(PCOLUMN cp) : SPCBLK(cp)
+ {
+//Is_Key = 2; for when the MUL table indexed reading will be implemented.
+ Precision = Long = 64;
+ Buf_Type = TYPE_STRING;
+ *Format.Type = 'C';
+ Format.Length = Long;
+ Format.Prec = 1; // Case insensitive
+ Constant = true; // TODO: check whether this is true indeed
+ Pname = NULL;
+ } // end of PRTBLK constructor
+
+/***********************************************************************/
+/* ReadColumn: what this routine does is to return the partition ID. */
+/***********************************************************************/
+void PRTBLK::ReadColumn(PGLOBAL g)
+ {
+ if (Pname == NULL) {
+ char *p;
+ PTDBASE tdbp = (PTDBASE)To_Tdb;
+
+ Pname = tdbp->GetDef()->GetStringCatInfo(g, "partname", "?");
+
+ p = strrchr(Pname, '#');
+ Value->SetValue_psz((p) ? p + 1 : Pname);
+ } // endif Pname
+
+ } // end of ReadColumn
+
+/***********************************************************************/
+/* SIDBLK constructor for the SERVID special column. */
+/***********************************************************************/
+SIDBLK::SIDBLK(PCOLUMN cp) : SPCBLK(cp)
+ {
+//Is_Key = 2; for when the MUL table indexed reading will be implemented.
+ Precision = Long = 64;
+ Buf_Type = TYPE_STRING;
+ *Format.Type = 'C';
+ Format.Length = Long;
+ Format.Prec = 1; // Case insensitive
+ Constant = (To_Tdb->GetAmType() != TYPE_AM_TBL);
+ Sname = NULL;
+ } // end of TIDBLK constructor
+
+/***********************************************************************/
+/* ReadColumn: what this routine does is to return the server ID. */
+/***********************************************************************/
+void SIDBLK::ReadColumn(PGLOBAL)
+ {
+//if (Sname == NULL) {
+ Sname = (char*)To_Tdb->GetServer();
+ Value->SetValue_psz(Sname);
+// } // endif Sname
+
+ } // end of ReadColumn
+
diff --git a/storage/connect/colblk.h b/storage/connect/colblk.h
index 5e8dc77ff69..c64f9d95129 100644
--- a/storage/connect/colblk.h
+++ b/storage/connect/colblk.h
@@ -1,7 +1,7 @@
/*************** Colblk H Declares Source Code File (.H) ***************/
/* Name: COLBLK.H Version 1.7 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* This file contains the COLBLK and derived classes declares. */
/***********************************************************************/
@@ -23,7 +23,7 @@ class DllExport COLBLK : public XOBJECT {
// Default constructors used by derived classes
COLBLK(PCOLDEF cdp = NULL, PTDB tdbp = NULL, int i = 0);
COLBLK(PCOL colp, PTDB tdbp = NULL); // Used in copy process
- COLBLK(int n) {} // Used when changing a column class in TDBXML
+ COLBLK(int) {} // Used when changing a column class in TDBXML
public:
// Implementation
@@ -69,7 +69,7 @@ class DllExport COLBLK : public XOBJECT {
virtual bool IsSpecial(void) {return false;}
virtual bool Eval(PGLOBAL g);
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
- virtual void SetTo_Val(PVAL valp) {}
+ virtual void SetTo_Val(PVAL) {}
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
virtual void Print(PGLOBAL g, FILE *, uint);
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index a54d8ebcc44..4e554b16638 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2012
+/* Copyright (C) Olivier Bertrand 2004 - 2015
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
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/***********************************************************************/
-/* Author Olivier BERTRAND bertrandop@gmail.com 2004-2012 */
+/* Author Olivier BERTRAND bertrandop@gmail.com 2004-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -42,7 +42,6 @@
#include "tabcol.h"
#include "catalog.h"
#include "ha_connect.h"
-#include "mycat.h"
#define my_strupr(p) my_caseup_str(default_charset_info, (p));
#define my_strlwr(p) my_casedn_str(default_charset_info, (p));
@@ -238,7 +237,7 @@ PTDB CntGetTDB(PGLOBAL g, LPCSTR name, MODE mode, PHC h)
/* OPENTAB: Open a Table. */
/***********************************************************************/
bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
- bool del, PHC h)
+ bool del, PHC)
{
char *p;
int i, n, rc;
@@ -469,9 +468,12 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
} while (rc == RC_NF);
+ if (rc == RC_OK)
+ rc= EvalColumns(g, tdbp, false);
+
err:
g->jump_level--;
- return (rc != RC_OK) ? rc : EvalColumns(g, tdbp, false);
+ return rc;
} // end of CntReadNext
/***********************************************************************/
@@ -707,6 +709,28 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted)
return (tdbp->To_Kindex->IsMul()) ? 2 : 1;
} // end of CntIndexInit
+#if defined(WORDS_BIGENDIAN)
+/***********************************************************************/
+/* Swap bytes of the key that are written in little endian order. */
+/***********************************************************************/
+static void SetSwapValue(PVAL valp, char *kp)
+{
+ if (valp->IsTypeNum() && valp->GetType() != TYPE_DECIM) {
+ uchar buf[8];
+ int i, k= valp->GetClen();
+
+ for (i = 0; k > 0;)
+ buf[i++]= kp[--k];
+
+
+
+ valp->SetBinValue((void*)buf);
+ } else
+ valp->SetBinValue((void*)kp);
+
+} // end of SetSwapValue
+#endif // WORDS_BIGENDIAN
+
/***********************************************************************/
/* IndexRead: fetch a record having the index value. */
/***********************************************************************/
@@ -777,7 +801,12 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
if (!valp->IsTypeNum()) {
if (colp->GetColUse(U_VAR)) {
+#if defined(WORDS_BIGENDIAN)
+ ((char*)&lg)[0]= ((char*)kp)[1];
+ ((char*)&lg)[1]= ((char*)kp)[0];
+#else // !WORDS_BIGENDIAN
lg= *(short*)kp;
+#endif //!WORDS_BIGENDIAN
kp+= sizeof(short);
rcb= valp->SetValue_char(kp, (int)lg);
} else
@@ -795,7 +824,11 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
} // endif b
} else
+#if defined(WORDS_BIGENDIAN)
+ SetSwapValue(valp, kp);
+#else // !WORDS_BIGENDIAN
valp->SetBinValue((void*)kp);
+#endif //!WORDS_BIGENDIAN
kp+= valp->GetClen();
@@ -891,7 +924,12 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
if (!valp->IsTypeNum()) {
if (colp->GetColUse(U_VAR)) {
+#if defined(WORDS_BIGENDIAN)
+ ((char*)&lg)[0]= ((char*)p)[1];
+ ((char*)&lg)[1]= ((char*)p)[0];
+#else // !WORDS_BIGENDIAN
lg= *(short*)p;
+#endif //!WORDS_BIGENDIAN
p+= sizeof(short);
rcb= valp->SetValue_char((char*)p, (int)lg);
} else
@@ -910,7 +948,11 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
} // endif b
} else
+#if defined(WORDS_BIGENDIAN)
+ SetSwapValue(valp, (char*)p);
+#else // !WORDS_BIGENDIAN
valp->SetBinValue((void*)p);
+#endif // !WORDS_BIGENDIAN
if (trace) {
char bf[32];
diff --git a/storage/connect/domdoc.cpp b/storage/connect/domdoc.cpp
index 518c806c653..64a0a172956 100644
--- a/storage/connect/domdoc.cpp
+++ b/storage/connect/domdoc.cpp
@@ -4,7 +4,7 @@
/******************************************************************/
#include "my_global.h"
#include <stdio.h>
-#if defined(WIN32)
+#if defined(__WIN__)
//#include <windows.h>
#if defined(MSX2)
#import "msxml2.dll" //Does not exist on Vista
@@ -275,7 +275,7 @@ PXNODE DOMNODE::GetNext(PGLOBAL g)
{
if (Nodep->nextSibling == NULL)
Next = NULL;
- else if (!Next)
+ else // if (!Next)
Next = new(g) DOMNODE(Doc, Nodep->nextSibling);
return Next;
@@ -288,7 +288,7 @@ PXNODE DOMNODE::GetChild(PGLOBAL g)
{
if (Nodep->firstChild == NULL)
Children = NULL;
- else if (!Children)
+ else // if (!Children)
Children = new(g) DOMNODE(Doc, Nodep->firstChild);
return Children;
@@ -441,15 +441,27 @@ PXNODE DOMNODE::SelectSingleNode(PGLOBAL g, char *xp, PXNODE np)
/******************************************************************/
PXATTR DOMNODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap)
{
- MSXML2::IXMLDOMElementPtr ep = Nodep;
- MSXML2::IXMLDOMAttributePtr atp = ep->getAttributeNode(name);
+ MSXML2::IXMLDOMElementPtr ep;
+ MSXML2::IXMLDOMNamedNodeMapPtr nmp;
+ MSXML2::IXMLDOMAttributePtr atp;
+
+ if (name) {
+ ep = Nodep;
+ atp = ep->getAttributeNode(name);
+ nmp = NULL;
+ } else {
+ nmp = Nodep->Getattributes();
+ atp = nmp->Getitem(0);
+ } // endif name
if (atp) {
if (ap) {
((PDOMATTR)ap)->Atrp = atp;
+ ((PDOMATTR)ap)->Nmp = nmp;
+ ((PDOMATTR)ap)->K = 0;
return ap;
} else
- return new(g) DOMATTR(Doc, atp);
+ return new(g) DOMATTR(Doc, atp, nmp);
} else
return NULL;
@@ -617,15 +629,86 @@ bool DOMNODELIST::DropItem(PGLOBAL g, int n)
/******************************************************************/
/* DOMATTR constructor. */
/******************************************************************/
-DOMATTR::DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap)
+DOMATTR::DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap,
+ MSXML2::IXMLDOMNamedNodeMapPtr nmp)
: XMLATTRIBUTE(dp)
{
Atrp = ap;
+ Nmp = nmp;
Ws = NULL;
Len = 0;
+ K = 0;
} // end of DOMATTR constructor
/******************************************************************/
+/* Return the attribute name. */
+/******************************************************************/
+char *DOMATTR::GetName(PGLOBAL g)
+ {
+ if (!WideCharToMultiByte(CP_ACP, 0, Atrp->nodeName, -1,
+ Name, sizeof(Name), NULL, NULL)) {
+ strcpy(g->Message, MSG(NAME_CONV_ERR));
+ return NULL;
+ } // endif
+
+ return Name;
+ } // end of GetName
+
+/******************************************************************/
+/* Return the next attribute node. */
+/* This funtion is implemented as needed by XMLColumns. */
+/******************************************************************/
+PXATTR DOMATTR::GetNext(PGLOBAL g)
+ {
+ if (!Nmp)
+ return NULL;
+
+ if (++K >= Nmp->Getlength()) {
+ Nmp->reset();
+ Nmp = NULL;
+ K = 0;
+ return NULL;
+ } // endif K
+
+ Atrp = Nmp->Getitem(K);
+ return this;
+ } // end of GetNext
+
+/******************************************************************/
+/* Return the content of a node and subnodes. */
+/******************************************************************/
+RCODE DOMATTR::GetText(PGLOBAL g, char *buf, int len)
+ {
+ RCODE rc = RC_OK;
+
+ if (!WideCharToMultiByte(CP_UTF8, 0, Atrp->text, -1,
+ buf, len, NULL, NULL)) {
+ DWORD lsr = GetLastError();
+
+ switch (lsr) {
+ case 0:
+ case ERROR_INSUFFICIENT_BUFFER: // 122L
+ sprintf(g->Message, "Truncated %s content", GetName(g));
+ rc = RC_INFO;
+ break;
+ case ERROR_NO_UNICODE_TRANSLATION: // 1113L
+ sprintf(g->Message, "Invalid character(s) in %s content",
+ GetName(g));
+ rc = RC_INFO;
+ break;
+ default:
+ sprintf(g->Message, "System error getting %s content",
+ GetName(g));
+ rc = RC_FX;
+ break;
+ } // endswitch
+
+ } // endif
+
+ return rc;
+ } // end of GetText
+
+/******************************************************************/
/* Set the text content of an attribute. */
/******************************************************************/
bool DOMATTR::SetText(PGLOBAL g, char *txtp, int len)
diff --git a/storage/connect/domdoc.h b/storage/connect/domdoc.h
index 118541d8eb0..2cffec499e2 100644
--- a/storage/connect/domdoc.h
+++ b/storage/connect/domdoc.h
@@ -122,15 +122,24 @@ class DOMATTR : public XMLATTRIBUTE {
friend class DOMDOC;
friend class DOMNODE;
public:
+ // Properties
+ virtual char *GetName(PGLOBAL g);
+ virtual PXATTR GetNext(PGLOBAL);
+
// Methods
- virtual bool SetText(PGLOBAL g, char *txtp, int len);
+ virtual RCODE GetText(PGLOBAL g, char *bufp, int len);
+ virtual bool SetText(PGLOBAL g, char *txtp, int len);
protected:
// Constructor
- DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap);
+ DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap,
+ MSXML2::IXMLDOMNamedNodeMapPtr nmp = NULL);
// Members
- MSXML2::IXMLDOMAttributePtr Atrp;
- WCHAR *Ws;
- int Len;
+ MSXML2::IXMLDOMAttributePtr Atrp;
+ MSXML2::IXMLDOMNamedNodeMapPtr Nmp;
+ char Name[64];
+ WCHAR *Ws;
+ int Len;
+ long K;
}; // end of class DOMATTR
diff --git a/storage/connect/filamap.cpp b/storage/connect/filamap.cpp
index 08f87e2b836..5cf9a4d945c 100644
--- a/storage/connect/filamap.cpp
+++ b/storage/connect/filamap.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -17,12 +17,12 @@
/* Include relevant sections of the System header files. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro
#endif // __BORLANDC__
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#if defined(UNIX)
#include <errno.h>
#include <unistd.h>
@@ -30,7 +30,7 @@
#include <io.h>
#endif // !UNIX
#include <fcntl.h>
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Include application header files: */
@@ -191,11 +191,11 @@ bool MAPFAM::OpenTableFile(PGLOBAL g)
return true;
} // endif Memory
-#if defined(WIN32)
+#if defined(__WIN__)
if (mode != MODE_DELETE) {
-#else // !WIN32
+#else // !__WIN__
if (mode == MODE_READ) {
-#endif // !WIN32
+#endif // !__WIN__
CloseFileHandle(hFile); // Not used anymore
hFile = INVALID_HANDLE_VALUE; // For Fblock
} // endif Mode
@@ -207,8 +207,7 @@ bool MAPFAM::OpenTableFile(PGLOBAL g)
/*******************************************************************/
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
fp->Type = TYPE_FB_MAP;
- fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
- strcpy((char*)fp->Fname, filename);
+ fp->Fname = PlugDup(g, filename);
fp->Next = dbuserp->Openlist;
dbuserp->Openlist = fp;
fp->Count = 1;
@@ -277,7 +276,7 @@ bool MAPFAM::SetPos(PGLOBAL g, int pos)
/***********************************************************************/
/* Record file position in case of UPDATE or DELETE. */
/***********************************************************************/
-bool MAPFAM::RecordPos(PGLOBAL g)
+bool MAPFAM::RecordPos(PGLOBAL)
{
Fpos = Mempos;
return false;
@@ -286,7 +285,7 @@ bool MAPFAM::RecordPos(PGLOBAL g)
/***********************************************************************/
/* Initialize Fpos and Mempos for indexed DELETE. */
/***********************************************************************/
-int MAPFAM::InitDelete(PGLOBAL g, int fpos, int spos)
+int MAPFAM::InitDelete(PGLOBAL, int fpos, int spos)
{
Fpos = Memory + (ptrdiff_t)fpos;
Mempos = Memory + (ptrdiff_t)spos;
@@ -372,7 +371,7 @@ int MAPFAM::ReadBuffer(PGLOBAL g)
/***********************************************************************/
/* WriteBuffer: File write routine for MAP access method. */
/***********************************************************************/
-int MAPFAM::WriteBuffer(PGLOBAL g)
+int MAPFAM::WriteBuffer(PGLOBAL g __attribute__((unused)))
{
#if defined(_DEBUG)
// Insert mode is no more handled using file mapping
@@ -453,7 +452,7 @@ int MAPFAM::DeleteRecords(PGLOBAL g, int irc)
/*****************************************************************/
n = Tpos - Memory;
-#if defined(WIN32)
+#if defined(__WIN__)
DWORD drc = SetFilePointer(fp->Handle, n, NULL, FILE_BEGIN);
if (drc == 0xFFFFFFFF) {
@@ -483,7 +482,7 @@ int MAPFAM::DeleteRecords(PGLOBAL g, int irc)
#endif // UNIX
} // endif Abort
-#if defined(WIN32)
+#if defined(__WIN__)
CloseHandle(fp->Handle);
#else // UNIX
close(fp->Handle);
@@ -496,7 +495,7 @@ int MAPFAM::DeleteRecords(PGLOBAL g, int irc)
/***********************************************************************/
/* Table file close routine for MAP access method. */
/***********************************************************************/
-void MAPFAM::CloseTableFile(PGLOBAL g, bool abort)
+void MAPFAM::CloseTableFile(PGLOBAL g, bool)
{
PlugCloseFile(g, To_Fb);
To_Fb = NULL; // To get correct file size in Cardinality
@@ -552,7 +551,7 @@ int MBKFAM::Cardinality(PGLOBAL g)
/***********************************************************************/
/* Skip one record in file. */
/***********************************************************************/
-int MBKFAM::SkipRecord(PGLOBAL g, bool header)
+int MBKFAM::SkipRecord(PGLOBAL, bool)
{
return RC_OK;
} // end of SkipRecord
@@ -686,7 +685,7 @@ bool MPXFAM::SetPos(PGLOBAL g, int pos)
/***********************************************************************/
/* Initialize CurBlk, CurNum, Mempos and Fpos for indexed DELETE. */
/***********************************************************************/
-int MPXFAM::InitDelete(PGLOBAL g, int fpos, int spos)
+int MPXFAM::InitDelete(PGLOBAL, int fpos, int)
{
Fpos = Memory + Headlen + (ptrdiff_t)fpos * Lrecl;
Mempos = Fpos + Lrecl;
@@ -741,7 +740,7 @@ int MPXFAM::ReadBuffer(PGLOBAL g)
/***********************************************************************/
/* WriteBuffer: File write routine for MAP access method. */
/***********************************************************************/
-int MPXFAM::WriteBuffer(PGLOBAL g)
+int MPXFAM::WriteBuffer(PGLOBAL g __attribute__((unused)))
{
#if defined(_DEBUG)
// Insert mode is no more handled using file mapping
diff --git a/storage/connect/filamap.h b/storage/connect/filamap.h
index 1d44239e610..b9c8ad965fd 100644
--- a/storage/connect/filamap.h
+++ b/storage/connect/filamap.h
@@ -17,6 +17,7 @@ typedef class MAPFAM *PMAPFAM;
/* This is the variable file access method using file mapping. */
/***********************************************************************/
class DllExport MAPFAM : public TXTFAM {
+ friend class TDBJSON;
public:
// Constructor
MAPFAM(PDOSDEF tdp);
diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp
index 98b8bb6fd95..8afda723578 100644
--- a/storage/connect/filamdbf.cpp
+++ b/storage/connect/filamdbf.cpp
@@ -1,11 +1,11 @@
/*********** File AM Dbf C++ Program Source Code File (.CPP) ****************/
/* PROGRAM NAME: FILAMDBF */
/* ------------- */
-/* Version 1.7 */
+/* Version 1.8 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -22,12 +22,12 @@
/* Include relevant sections of the System header files. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <fcntl.h>
//#include <errno.h>
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#if defined(UNIX)
#include <errno.h>
#include <unistd.h>
@@ -35,7 +35,7 @@
//#include <io.h>
#endif // !UNIX
//#include <fcntl.h>
-#endif // !WIN32
+#endif // !__WIN__
#include <ctype.h>
#include <stdio.h>
#include <string.h>
@@ -74,16 +74,28 @@ typedef struct _dbfheader {
//uchar Dbfox :4; /* FoxPro if equal to 3 */
uchar Version; /* Version information flags */
char Filedate[3]; /* date, YYMMDD, binary. YY=year-1900 */
- uint Records; /* records in the file */
- ushort Headlen; /* bytes in the header */
- ushort Reclen; /* bytes in a record */
- ushort Fields; /* Reserved but used to store fields */
+ 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;
/****************************************************************************/
@@ -143,7 +155,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
strcpy(g->Message, MSG(DBASE_FILE));
// Check last byte(s) of header
- if (fseek(file, buf->Headlen - dbc, SEEK_SET) != 0) {
+ if (fseek(file, buf->Headlen() - dbc, SEEK_SET) != 0) {
sprintf(g->Message, MSG(BAD_HEADER), fn);
return RC_FX;
} // endif fseek
@@ -163,7 +175,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
} // endif endmark
// Calculate here the number of fields while we have the dbc info
- buf->Fields = (buf->Headlen - dbc - 1) / 32;
+ buf->SetFields((buf->Headlen() - dbc - 1) / 32);
fseek(file, HEADLEN, SEEK_SET);
return rc;
} // end of dbfhead
@@ -219,7 +231,7 @@ PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info)
/************************************************************************/
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
- fields = mainhead.Fields;
+ fields = mainhead.Fields();
} else
fields = 0;
@@ -236,11 +248,11 @@ PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info)
if (trace) {
htrc("Structure of %s\n", filename);
htrc("headlen=%hd reclen=%hd degree=%d\n",
- mainhead.Headlen, mainhead.Reclen, fields);
+ mainhead.Headlen(), mainhead.Reclen(), fields);
htrc("flags(iem)=%d,%d,%d cp=%d\n", mainhead.Incompleteflag,
mainhead.Encryptflag, mainhead.Mdxflag, mainhead.Language);
htrc("%hd records, last changed %02d/%02d/%d\n",
- mainhead.Records, mainhead.Filedate[1], mainhead.Filedate[2],
+ mainhead.Records(), mainhead.Filedate[1], mainhead.Filedate[2],
mainhead.Filedate[0] + (mainhead.Filedate[0] <= 30) ? 2000 : 1900);
htrc("Field Type Offset Len Dec Set Mdx\n");
} // endif trace
@@ -398,13 +410,13 @@ int DBFBASE::ScanHeader(PGLOBAL g, PSZ fname, int lrecl, char *defpath)
} else if (rc == RC_FX)
return -1;
- if ((int)header.Reclen != lrecl) {
- sprintf(g->Message, MSG(BAD_LRECL), lrecl, header.Reclen);
+ if ((int)header.Reclen() != lrecl) {
+ sprintf(g->Message, MSG(BAD_LRECL), lrecl, header.Reclen());
return -1;
} // endif Lrecl
- Records = (int)header.Records;
- return (int)header.Headlen;
+ Records = (int)header.Records();
+ return (int)header.Headlen();
} // end of ScanHeader
/* ---------------------------- Class DBFFAM ------------------------------ */
@@ -516,7 +528,7 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g)
To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen);
if (mode == MODE_INSERT) {
-#if defined(WIN32)
+#if defined(__WIN__)
/************************************************************************/
/* Now we can revert to binary mode in particular because the eventual */
/* writing of a new header must be done in binary mode to avoid */
@@ -526,7 +538,7 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g)
sprintf(g->Message, MSG(BIN_MODE_FAIL), strerror(errno));
return true;
} // endif setmode
-#endif // WIN32
+#endif // __WIN__
/************************************************************************/
/* If this is a new file, the header must be generated. */
@@ -565,8 +577,8 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g)
header->Filedate[0] = datm->tm_year - 100;
header->Filedate[1] = datm->tm_mon + 1;
header->Filedate[2] = datm->tm_mday;
- header->Headlen = (ushort)hlen;
- header->Reclen = (ushort)reclen;
+ header->SetHeadlen((ushort)hlen);
+ header->SetReclen((ushort)reclen);
descp = (DESCRIPTOR*)header;
// Currently only standard Xbase types are supported
@@ -627,13 +639,13 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g)
DBFHEADER header;
if ((rc = dbfhead(g, Stream, Tdbp->GetFile(g), &header)) == RC_OK) {
- if (Lrecl != (int)header.Reclen) {
- sprintf(g->Message, MSG(BAD_LRECL), Lrecl, header.Reclen);
+ if (Lrecl != (int)header.Reclen()) {
+ sprintf(g->Message, MSG(BAD_LRECL), Lrecl, header.Reclen());
return true;
} // endif Lrecl
- Records = (int)header.Records;
- Headlen = (int)header.Headlen;
+ Records = (int)header.Records();
+ Headlen = (int)header.Headlen();
} else if (rc == RC_NF) {
Records = 0;
Headlen = 0;
@@ -868,8 +880,11 @@ void DBFFAM::CloseTableFile(PGLOBAL g, bool abort)
PlugSetPath(filename, To_File, Tdbp->GetPath());
if ((Stream= global_fopen(g, MSGID_OPEN_MODE_STRERROR, filename, "r+b")))
{
+ char nRecords[4];
+ int4store(nRecords, n);
+
fseek(Stream, 4, SEEK_SET); // Get header.Records position
- fwrite(&n, sizeof(int), 1, Stream);
+ fwrite(nRecords, sizeof(nRecords), 1, Stream);
fclose(Stream);
Stream= NULL;
Records= n; // Update Records value
@@ -944,13 +959,13 @@ bool DBMFAM::AllocateBuffer(PGLOBAL g)
/************************************************************************/
DBFHEADER *hp = (DBFHEADER*)Memory;
- if (Lrecl != (int)hp->Reclen) {
- sprintf(g->Message, MSG(BAD_LRECL), Lrecl, hp->Reclen);
+ if (Lrecl != (int)hp->Reclen()) {
+ sprintf(g->Message, MSG(BAD_LRECL), Lrecl, hp->Reclen());
return true;
} // endif Lrecl
- Records = (int)hp->Records;
- Headlen = (int)hp->Headlen;
+ Records = (int)hp->Records();
+ Headlen = (int)hp->Headlen();
} // endif Headlen
/**************************************************************************/
diff --git a/storage/connect/filamfix.cpp b/storage/connect/filamfix.cpp
index 980d558eee5..cd25429318a 100644
--- a/storage/connect/filamfix.cpp
+++ b/storage/connect/filamfix.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -17,7 +17,7 @@
/* Include relevant sections of the System header files. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <fcntl.h>
#include <errno.h>
@@ -25,7 +25,7 @@
#define __MFC_COMPAT__ // To define min/max as macro
#endif // __BORLANDC__
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#if defined(UNIX)
#include <errno.h>
#include <unistd.h>
@@ -34,7 +34,7 @@
#endif // !UNIX
#include <sys/stat.h>
#include <fcntl.h>
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Include application header files: */
@@ -46,6 +46,7 @@
#include "plgdbsem.h"
#include "filamfix.h"
#include "tabdos.h"
+#include "tabfix.h"
#include "osutil.h"
#ifndef INVALID_SET_FILE_POINTER
@@ -102,7 +103,7 @@ bool FIXFAM::SetPos(PGLOBAL g, int pos)
/***********************************************************************/
/* Initialize CurBlk and CurNum for indexed DELETE. */
/***********************************************************************/
-int FIXFAM::InitDelete(PGLOBAL g, int fpos, int spos)
+int FIXFAM::InitDelete(PGLOBAL, int fpos, int)
{
CurBlk = fpos / Nrec;
CurNum = fpos % Nrec;
@@ -133,18 +134,35 @@ bool FIXFAM::AllocateBuffer(PGLOBAL g)
if (Tdbp->GetFtype() == RECFM_BIN) {
// The buffer must be prepared depending on column types
int n = 0;
+ bool b = false;
PDOSDEF defp = (PDOSDEF)Tdbp->GetDef();
- PCOLDEF cdp;
+// PCOLDEF cdp;
+ PBINCOL colp;
// Prepare the first line of the buffer
memset(To_Buf, 0, Buflen);
+#if 0
for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) {
- if (IsTypeNum(cdp->GetType()))
- memset(To_Buf + cdp->GetOffset(), ' ', cdp->GetClen());
+ if (!IsTypeNum(cdp->GetType())) {
+ memset(To_Buf + cdp->GetOffset(), ' ', cdp->GetClen());
+ b = true;
+ } // endif not num
- n = MY_MAX(n, cdp->GetPoff() + cdp->GetClen());
+ n = MY_MAX(n, cdp->GetOffset() + cdp->GetClen());
} // endfor cdp
+#endif // 0
+
+ for (colp = (PBINCOL)Tdbp->GetColumns(); colp;
+ colp = (PBINCOL)colp->GetNext())
+ if (!colp->IsSpecial()) {
+ if (!IsTypeNum(colp->GetResultType())) {
+ memset(To_Buf + colp->GetDeplac(), ' ', colp->GetLength());
+ b = true;
+ } // endif not num
+
+ n = MY_MAX(n, colp->GetDeplac() + colp->GetFileSize());
+ } // endif !special
// We do this for binary table because the lrecl can have been
// specified with additional space to include line ending.
@@ -156,9 +174,10 @@ bool FIXFAM::AllocateBuffer(PGLOBAL g)
} // endif n
- // Now repeat this for the whole buffer
- for (int len = Lrecl; len <= Buflen - Lrecl; len += Lrecl)
- memcpy(To_Buf + len, To_Buf, Lrecl);
+ if (b)
+ // Now repeat this for the whole buffer
+ for (int len = Lrecl; len <= Buflen - Lrecl; len += Lrecl)
+ memcpy(To_Buf + len, To_Buf, Lrecl);
} else {
memset(To_Buf, ' ', Buflen);
@@ -319,10 +338,10 @@ int FIXFAM::ReadBuffer(PGLOBAL g)
} else if (feof(Stream)) {
rc = RC_EF;
} else {
-#if defined(UNIX)
- sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno));
-#else
+#if defined(__WIN__)
sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL));
+#else
+ sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno));
#endif
if (trace)
@@ -659,7 +678,7 @@ BGXFAM::BGXFAM(PBGXFAM txfp) : FIXFAM(txfp)
/***********************************************************************/
bool BGXFAM::BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, int org)
{
-#if defined(WIN32)
+#if defined(__WIN__)
char buf[256];
DWORD drc;
LARGE_INTEGER of;
@@ -675,14 +694,14 @@ bool BGXFAM::BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, int org)
sprintf(g->Message, MSG(SFP_ERROR), buf);
return true;
} // endif
-#else // !WIN32
+#else // !__WIN__
if (lseek64(h, pos, org) < 0) {
// sprintf(g->Message, MSG(ERROR_IN_LSK), errno);
sprintf(g->Message, "lseek64: %s", strerror(errno));
printf("%s\n", g->Message);
return true;
} // endif
-#endif // !WIN32
+#endif // !__WIN__
return false;
} // end of BigSeek
@@ -690,11 +709,12 @@ bool BGXFAM::BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, int org)
/***********************************************************************/
/* Read from a big file. */
/***********************************************************************/
-int BGXFAM::BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req)
+int BGXFAM::BigRead(PGLOBAL g __attribute__((unused)),
+ HANDLE h, void *inbuf, int req)
{
int rc;
-#if defined(WIN32)
+#if defined(__WIN__)
DWORD nbr, drc, len = (DWORD)req;
bool brc = ReadFile(h, inbuf, len, &nbr, NULL);
@@ -716,12 +736,12 @@ int BGXFAM::BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req)
rc = -1;
} else
rc = (int)nbr;
-#else // !WIN32
+#else // !__WIN__
size_t len = (size_t)req;
ssize_t nbr = read(h, inbuf, len);
rc = (int)nbr;
-#endif // !WIN32
+#endif // !__WIN__
return rc;
} // end of BigRead
@@ -733,7 +753,7 @@ bool BGXFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req)
{
bool rc = false;
-#if defined(WIN32)
+#if defined(__WIN__)
DWORD nbw, drc, len = (DWORD)req;
bool brc = WriteFile(h, inbuf, len, &nbw, NULL);
@@ -760,7 +780,7 @@ bool BGXFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req)
rc = true;
} // endif brc || nbw
-#else // !WIN32
+#else // !__WIN__
size_t len = (size_t)req;
ssize_t nbw = write(h, inbuf, len);
@@ -775,7 +795,7 @@ bool BGXFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req)
rc = true;
} // endif nbr
-#endif // !WIN32
+#endif // !__WIN__
return rc;
} // end of BigWrite
@@ -810,7 +830,7 @@ bool BGXFAM::OpenTableFile(PGLOBAL g)
if (trace)
htrc("OpenTableFile: filename=%s mode=%d\n", filename, mode);
-#if defined(WIN32)
+#if defined(__WIN__)
DWORD rc, access, creation, share = 0;
/*********************************************************************/
@@ -967,7 +987,7 @@ int BGXFAM::Cardinality(PGLOBAL g)
PlugSetPath(filename, To_File, Tdbp->GetPath());
-#if defined(WIN32) // OB
+#if defined(__WIN__) // OB
LARGE_INTEGER len;
DWORD rc = 0;
@@ -1326,7 +1346,7 @@ int BGXFAM::DeleteRecords(PGLOBAL g, int irc)
/*****************************************************************/
/* Remove extra records. */
/*****************************************************************/
-#if defined(WIN32)
+#if defined(__WIN__)
if (BigSeek(g, Hfile, (BIGINT)Tpos * (BIGINT)Lrecl))
return RC_FX;
@@ -1336,12 +1356,12 @@ int BGXFAM::DeleteRecords(PGLOBAL g, int irc)
sprintf(g->Message, MSG(SETEOF_ERROR), drc);
return RC_FX;
} // endif error
-#else // !WIN32
+#else // !__WIN__
if (ftruncate64(Hfile, (BIGINT)(Tpos * Lrecl))) {
sprintf(g->Message, MSG(TRUNCATE_ERROR), strerror(errno));
return RC_FX;
} // endif
-#endif // !WIN32
+#endif // !__WIN__
} // endif UseTemp
@@ -1366,7 +1386,7 @@ bool BGXFAM::OpenTempFile(PGLOBAL g)
strcat(PlugRemoveType(tempname, tempname), ".t");
remove(tempname); // Be sure it does not exist yet
-#if defined(WIN32)
+#if defined(__WIN__)
Tfile = CreateFile(tempname, GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
@@ -1506,7 +1526,7 @@ void BGXFAM::CloseTableFile(PGLOBAL g, bool abort)
void BGXFAM::Rewind(void)
{
#if 0 // This is probably unuseful because file is accessed directly
-#if defined(WIN32) //OB
+#if defined(__WIN__) //OB
SetFilePointer(Hfile, 0, NULL, FILE_BEGIN);
#else // UNIX
lseek64(Hfile, 0, SEEK_SET);
diff --git a/storage/connect/filamtxt.cpp b/storage/connect/filamtxt.cpp
index 675c021fe51..e53cdcd9ba9 100644
--- a/storage/connect/filamtxt.cpp
+++ b/storage/connect/filamtxt.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -17,7 +17,7 @@
/* Include relevant sections of the System header files. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <fcntl.h>
#include <errno.h>
@@ -25,7 +25,7 @@
#define __MFC_COMPAT__ // To define min/max as macro
#endif // __BORLANDC__
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#if defined(UNIX) || defined(UNIV_LINUX)
#include <errno.h>
#include <unistd.h>
@@ -36,7 +36,7 @@
#include <io.h>
#endif // !UNIX
#include <fcntl.h>
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Include application header files: */
@@ -289,8 +289,7 @@ bool TXTFAM::AddListValue(PGLOBAL g, int type, void *val, PPARM *top)
pp->Intval = *(int*)val;
break;
// case TYPE_STRING:
-// pp->Value = PlugSubAlloc(g, NULL, strlen((char*)val) + 1);
-// strcpy((char*)pp->Value, (char*)val);
+// pp->Value = PlugDup(g, (char*)val);
// break;
case TYPE_PCHAR:
pp->Value = val;
@@ -325,8 +324,7 @@ int TXTFAM::StoreValues(PGLOBAL g, bool upd)
if (Tdbp->PrepareWriting(g))
return RC_FX;
- buf = (char*)PlugSubAlloc(g, NULL, strlen(Tdbp->GetLine()) + 1);
- strcpy(buf, Tdbp->GetLine());
+ buf = PlugDup(g, Tdbp->GetLine());
rc = AddListValue(g, TYPE_PCHAR, buf, &To_Upd);
} // endif upd
@@ -438,7 +436,7 @@ err:
/* The purpose of this function is to deal with access methods that */
/* are not coherent regarding the use of SetPos and GetPos. */
/***********************************************************************/
-int TXTFAM::InitDelete(PGLOBAL g, int fpos, int spos)
+int TXTFAM::InitDelete(PGLOBAL g, int, int)
{
strcpy(g->Message, "InitDelete should not be used by this table type");
return RC_FX;
@@ -521,7 +519,7 @@ int DOSFAM::Cardinality(PGLOBAL g)
/* Use BlockTest to reduce the table estimated size. */
/* Note: This function is not really implemented yet. */
/***********************************************************************/
-int DOSFAM::MaxBlkSize(PGLOBAL g, int s)
+int DOSFAM::MaxBlkSize(PGLOBAL, int s)
{
return s;
} // end of MaxBlkSize
@@ -718,10 +716,10 @@ int DOSFAM::SkipRecord(PGLOBAL g, bool header)
if (feof(Stream))
return RC_EF;
-#if defined(UNIX) || defined(UNIV_LINUX)
- sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(0));
-#else
+#if defined(__WIN__)
sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL));
+#else
+ sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(0));
#endif
return RC_FX;
} // endif fgets
@@ -801,12 +799,12 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
if (trace > 1)
htrc(" Read: To_Buf=%p p=%c\n", To_Buf, To_Buf, p);
-#if defined(UNIX)
- if (true) {
- // Data files can be imported from Windows (having CRLF)
-#else
+#if defined(__WIN__)
if (Bin) {
// Data file is read in binary so CRLF remains
+#else
+ if (true) {
+ // Data files can be imported from Windows (having CRLF)
#endif
if (*p == '\n' || *p == '\r') {
// is this enough for Unix ???
@@ -835,10 +833,10 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
} else if (feof(Stream)) {
rc = RC_EF;
} else {
-#if defined(UNIX)
- sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(0));
-#else
+#if defined(__WIN__)
sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL));
+#else
+ sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(0));
#endif
if (trace)
@@ -1030,15 +1028,15 @@ int DOSFAM::DeleteRecords(PGLOBAL g, int irc)
/*****************************************************************/
/* Remove extra records. */
/*****************************************************************/
-#if defined(UNIX)
- if (ftruncate(h, (off_t)Tpos)) {
- sprintf(g->Message, MSG(TRUNCATE_ERROR), strerror(errno));
+#if defined(__WIN__)
+ if (chsize(h, Tpos)) {
+ sprintf(g->Message, MSG(CHSIZE_ERROR), strerror(errno));
close(h);
return RC_FX;
} // endif
#else
- if (chsize(h, Tpos)) {
- sprintf(g->Message, MSG(CHSIZE_ERROR), strerror(errno));
+ if (ftruncate(h, (off_t)Tpos)) {
+ sprintf(g->Message, MSG(TRUNCATE_ERROR), strerror(errno));
close(h);
return RC_FX;
} // endif
@@ -1274,7 +1272,7 @@ int BLKFAM::Cardinality(PGLOBAL g)
/***********************************************************************/
/* Use BlockTest to reduce the table estimated size. */
/***********************************************************************/
-int BLKFAM::MaxBlkSize(PGLOBAL g, int s)
+int BLKFAM::MaxBlkSize(PGLOBAL g, int)
{
int rc = RC_OK, savcur = CurBlk;
int size;
@@ -1345,7 +1343,7 @@ int BLKFAM::GetNextPos(void)
/***********************************************************************/
/* SetPos: Replace the table at the specified position. */
/***********************************************************************/
-bool BLKFAM::SetPos(PGLOBAL g, int pos)
+bool BLKFAM::SetPos(PGLOBAL g, int)
{
strcpy(g->Message, "Blocked variable tables cannot be used indexed");
return true;
@@ -1355,7 +1353,7 @@ bool BLKFAM::SetPos(PGLOBAL g, int pos)
/* Record file position in case of UPDATE or DELETE. */
/* Not used yet for blocked tables. */
/***********************************************************************/
-bool BLKFAM::RecordPos(PGLOBAL g)
+bool BLKFAM::RecordPos(PGLOBAL)
{
Fpos = (CurNum + Nrec * CurBlk); // Computed file index
return false;
@@ -1364,7 +1362,7 @@ bool BLKFAM::RecordPos(PGLOBAL g)
/***********************************************************************/
/* Skip one record in file. */
/***********************************************************************/
-int BLKFAM::SkipRecord(PGLOBAL g, bool header)
+int BLKFAM::SkipRecord(PGLOBAL, bool header)
{
if (header) {
// For Delete
@@ -1468,10 +1466,10 @@ int BLKFAM::ReadBuffer(PGLOBAL g)
} else if (feof(Stream)) {
rc = RC_EF;
} else {
-#if defined(UNIX)
- sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno));
-#else
+#if defined(__WIN__)
sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL));
+#else
+ sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno));
#endif
if (trace)
@@ -1553,11 +1551,11 @@ int BLKFAM::WriteBuffer(PGLOBAL g)
Spos = GetNextPos(); // New start position
// Prepare the output buffer
-#if defined(WIN32)
+#if defined(__WIN__)
crlf = "\r\n";
#else
crlf = "\n";
-#endif // WIN32
+#endif // __WIN__
strcat(strcpy(OutBuf, Tdbp->GetLine()), crlf);
len = strlen(OutBuf);
} else {
diff --git a/storage/connect/filamtxt.h b/storage/connect/filamtxt.h
index 864ca66dd34..ae8f74a9830 100644
--- a/storage/connect/filamtxt.h
+++ b/storage/connect/filamtxt.h
@@ -42,6 +42,7 @@ class DllExport TXTFAM : public BLOCK {
virtual PTXF Duplicate(PGLOBAL g) = 0;
virtual bool GetUseTemp(void) {return false;}
virtual int GetDelRows(void) {return DelRows;}
+ PFBLOCK GetTo_Fb(void) {return To_Fb;}
int GetCurBlk(void) {return CurBlk;}
void SetTdbp(PTDBDOS tdbp) {Tdbp = tdbp;}
int GetBlock(void) {return Block;}
@@ -56,8 +57,8 @@ class DllExport TXTFAM : public BLOCK {
virtual int GetFileLength(PGLOBAL g);
virtual int Cardinality(PGLOBAL g);
virtual int MaxBlkSize(PGLOBAL g, int s);
- virtual bool AllocateBuffer(PGLOBAL g) {return false;}
- virtual void ResetBuffer(PGLOBAL g) {}
+ virtual bool AllocateBuffer(PGLOBAL) {return false;}
+ virtual void ResetBuffer(PGLOBAL) {}
virtual int GetNerr(void) {return 0;}
virtual int GetRowID(void) = 0;
virtual bool RecordPos(PGLOBAL g) = 0;
diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp
index c449347bbcb..fdc5433f4a4 100755
--- a/storage/connect/filamvct.cpp
+++ b/storage/connect/filamvct.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -21,7 +21,7 @@
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <fcntl.h>
#if defined(__BORLANDC__)
@@ -29,7 +29,7 @@
#endif // __BORLAND__
//#include <windows.h>
#include <sys/stat.h>
-#else // !WIN32
+#else // !__WIN__
#if defined(UNIX)
#include <sys/types.h>
#include <sys/stat.h>
@@ -40,7 +40,7 @@
#include <io.h>
#endif // !UNIX
#include <fcntl.h>
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Include application header files: */
@@ -49,7 +49,7 @@
/* tabdos.h is header containing the TABDOS class declarations. */
/***********************************************************************/
#include "global.h"
-#include "osutil.h" // Unuseful for WIN32
+#include "osutil.h" // Unuseful for WINDOWS
#include "plgdbsem.h"
#include "valblk.h"
#include "filamfix.h"
@@ -279,7 +279,7 @@ bool VCTFAM::SetBlockInfo(PGLOBAL g)
/***********************************************************************/
/* Use BlockTest to reduce the table estimated size. */
/***********************************************************************/
-int VCTFAM::MaxBlkSize(PGLOBAL g, int s)
+int VCTFAM::MaxBlkSize(PGLOBAL g, int)
{
int rc = RC_OK, savcur = CurBlk;
int size;
@@ -376,11 +376,11 @@ bool VCTFAM::MakeEmptyFile(PGLOBAL g, char *fn)
int h, n;
PlugSetPath(filename, fn, Tdbp->GetPath());
-#if defined(WIN32)
+#if defined(__WIN__)
h= global_open(g, MSGID_OPEN_EMPTY_FILE, filename, _O_CREAT | _O_WRONLY, S_IREAD | S_IWRITE);
-#else // !WIN32
+#else // !__WIN__
h= global_open(g, MSGID_OPEN_EMPTY_FILE, filename, O_CREAT | O_WRONLY, S_IREAD | S_IWRITE);
-#endif // !WIN32
+#endif // !__WIN__
if (h == -1)
return true;
@@ -1451,8 +1451,7 @@ bool VCMFAM::OpenTableFile(PGLOBAL g)
/*******************************************************************/
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
fp->Type = TYPE_FB_MAP;
- fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
- strcpy((char*)fp->Fname, filename);
+ fp->Fname = PlugDup(g, filename);
fp->Next = dbuserp->Openlist;
dbuserp->Openlist = fp;
fp->Count = 1;
@@ -1670,7 +1669,7 @@ int VCMFAM::DeleteRecords(PGLOBAL g, int irc)
// Remove extra blocks
n = Block * Blksize;
-#if defined(WIN32)
+#if defined(__WIN__)
DWORD drc = SetFilePointer(fp->Handle, n, NULL, FILE_BEGIN);
if (drc == 0xFFFFFFFF) {
@@ -1717,7 +1716,7 @@ int VCMFAM::DeleteRecords(PGLOBAL g, int irc)
/***********************************************************************/
/* Move intermediate deleted or updated lines. */
/***********************************************************************/
-bool VCMFAM::MoveIntermediateLines(PGLOBAL g, bool *b)
+bool VCMFAM::MoveIntermediateLines(PGLOBAL, bool *)
{
int i, m, n;
@@ -1766,7 +1765,7 @@ bool VCMFAM::MoveIntermediateLines(PGLOBAL g, bool *b)
/***********************************************************************/
/* Data Base close routine for VMP access method. */
/***********************************************************************/
-void VCMFAM::CloseTableFile(PGLOBAL g, bool abort)
+void VCMFAM::CloseTableFile(PGLOBAL g, bool)
{
int wrc = RC_OK;
MODE mode = Tdbp->GetMode();
@@ -1801,7 +1800,7 @@ void VCMFAM::CloseTableFile(PGLOBAL g, bool abort)
/***********************************************************************/
/* ReadBlock: Read column values from current block. */
/***********************************************************************/
-bool VCMFAM::ReadBlock(PGLOBAL g, PVCTCOL colp)
+bool VCMFAM::ReadBlock(PGLOBAL, PVCTCOL colp)
{
char *mempos;
int i = colp->Index - 1;
@@ -1831,7 +1830,7 @@ bool VCMFAM::ReadBlock(PGLOBAL g, PVCTCOL colp)
/* the mapped file, except when checking for Update but in this case */
/* we do not want to write back the modifications either. */
/***********************************************************************/
-bool VCMFAM::WriteBlock(PGLOBAL g, PVCTCOL colp)
+bool VCMFAM::WriteBlock(PGLOBAL, PVCTCOL colp __attribute__((unused)))
{
#if defined(_DEBUG)
char *mempos;
@@ -2125,7 +2124,7 @@ bool VECFAM::AllocateBuffer(PGLOBAL g)
/***********************************************************************/
/* Do initial action when inserting. */
/***********************************************************************/
-bool VECFAM::InitInsert(PGLOBAL g)
+bool VECFAM::InitInsert(PGLOBAL)
{
// We come here in MODE_INSERT only
CurBlk = 0;
@@ -2366,7 +2365,7 @@ bool VECFAM::MoveLines(PGLOBAL g)
/***********************************************************************/
/* Move intermediate deleted or updated lines. */
/***********************************************************************/
-bool VECFAM::MoveIntermediateLines(PGLOBAL g, bool *bn)
+bool VECFAM::MoveIntermediateLines(PGLOBAL g, bool *)
{
int i, n;
bool b = false;
@@ -2575,11 +2574,11 @@ bool VECFAM::ReadBlock(PGLOBAL g, PVCTCOL colp)
char fn[_MAX_PATH];
sprintf(fn, Colfn, colp->Index);
-#if defined(WIN32)
+#if defined(__WIN__)
if (feof(Streams[i]))
-#else // !WIN32
+#else // !__WIN__
if (errno == NO_ERROR)
-#endif // !WIN32
+#endif // !__WIN__
sprintf(g->Message, MSG(BAD_READ_NUMBER), (int) n, fn);
else
sprintf(g->Message, MSG(READ_ERROR),
@@ -2844,8 +2843,7 @@ bool VMPFAM::MapColumnFile(PGLOBAL g, MODE mode, int i)
/*******************************************************************/
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
fp->Type = TYPE_FB_MAP;
- fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
- strcpy((char*)fp->Fname, filename);
+ fp->Fname = PlugDup(g, filename);
fp->Next = dup->Openlist;
dup->Openlist = fp;
fp->Count = 1;
@@ -2971,7 +2969,7 @@ int VMPFAM::DeleteRecords(PGLOBAL g, int irc)
/*****************************************************************/
n = Tpos * Clens[i];
-#if defined(WIN32)
+#if defined(__WIN__)
DWORD drc = SetFilePointer(fp->Handle, n, NULL, FILE_BEGIN);
if (drc == 0xFFFFFFFF) {
@@ -3011,7 +3009,7 @@ int VMPFAM::DeleteRecords(PGLOBAL g, int irc)
/***********************************************************************/
/* Data Base close routine for VMP access method. */
/***********************************************************************/
-void VMPFAM::CloseTableFile(PGLOBAL g, bool abort)
+void VMPFAM::CloseTableFile(PGLOBAL g, bool)
{
if (Tdbp->GetMode() == MODE_DELETE) {
// Set Block and Nrec values for TDBVCT::MakeBlockValues
@@ -3051,7 +3049,7 @@ BGVFAM::BGVFAM(PBGVFAM txfp) : VCTFAM(txfp)
/***********************************************************************/
bool BGVFAM::BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, bool b)
{
-#if defined(WIN32)
+#if defined(__WIN__)
char buf[256];
DWORD drc, m = (b) ? FILE_END : FILE_BEGIN;
LARGE_INTEGER of;
@@ -3067,12 +3065,12 @@ bool BGVFAM::BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, bool b)
sprintf(g->Message, MSG(SFP_ERROR), buf);
return true;
} // endif
-#else // !WIN32
+#else // !__WIN__
if (lseek64(h, pos, (b) ? SEEK_END : SEEK_SET) < 0) {
sprintf(g->Message, MSG(ERROR_IN_LSK), errno);
return true;
} // endif
-#endif // !WIN32
+#endif // !__WIN__
return false;
} // end of BigSeek
@@ -3084,7 +3082,7 @@ bool BGVFAM::BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req)
{
bool rc = false;
-#if defined(WIN32)
+#if defined(__WIN__)
DWORD nbr, drc, len = (DWORD)req;
bool brc = ReadFile(h, inbuf, len, &nbr, NULL);
@@ -3110,7 +3108,7 @@ bool BGVFAM::BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req)
rc = true;
} // endif brc || nbr
-#else // !WIN32
+#else // !__WIN__
size_t len = (size_t)req;
ssize_t nbr = read(h, inbuf, len);
@@ -3125,7 +3123,7 @@ bool BGVFAM::BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req)
rc = true;
} // endif nbr
-#endif // !WIN32
+#endif // !__WIN__
return rc;
} // end of BigRead
@@ -3137,7 +3135,7 @@ bool BGVFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req)
{
bool rc = false;
-#if defined(WIN32)
+#if defined(__WIN__)
DWORD nbw, drc, len = (DWORD)req;
bool brc = WriteFile(h, inbuf, len, &nbw, NULL);
@@ -3164,7 +3162,7 @@ bool BGVFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req)
rc = true;
} // endif brc || nbw
-#else // !WIN32
+#else // !__WIN__
size_t len = (size_t)req;
ssize_t nbw = write(h, inbuf, len);
@@ -3179,7 +3177,7 @@ bool BGVFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req)
rc = true;
} // endif nbr
-#endif // !WIN32
+#endif // !__WIN__
return rc;
} // end of BigWrite
@@ -3205,7 +3203,7 @@ int BGVFAM::GetBlockInfo(PGLOBAL g)
if (Header == 2)
strcat(PlugRemoveType(filename, filename), ".blk");
-#if defined(WIN32)
+#if defined(__WIN__)
LARGE_INTEGER len;
h = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
@@ -3217,11 +3215,11 @@ int BGVFAM::GetBlockInfo(PGLOBAL g)
} // endif h
if (h == INVALID_HANDLE_VALUE || !len.QuadPart) {
-#else // !WIN32
+#else // !__WIN__
h = open64(filename, O_RDONLY, 0);
if (h == INVALID_HANDLE_VALUE || !_filelength(h)) {
-#endif // !WIN32
+#endif // !__WIN__
// Consider this is a void table
if (trace)
htrc("Void table h=%d\n", h);
@@ -3282,17 +3280,17 @@ bool BGVFAM::SetBlockInfo(PGLOBAL g)
strcat(PlugRemoveType(filename, filename), ".blk");
if (h == INVALID_HANDLE_VALUE) {
-#if defined(WIN32)
+#if defined(__WIN__)
DWORD creation = (b) ? OPEN_EXISTING : TRUNCATE_EXISTING;
h = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0,
NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL);
-#else // !WIN32
+#else // !__WIN__
int oflag = (b) ? O_RDWR : O_RDWR | O_TRUNC;
h = open64(filename, oflag, 0);
-#endif // !WIN32
+#endif // !__WIN__
if (h == INVALID_HANDLE_VALUE) {
sprintf(g->Message, "Error opening header file %s", filename);
@@ -3330,7 +3328,7 @@ bool BGVFAM::MakeEmptyFile(PGLOBAL g, char *fn)
PlugSetPath(filename, fn, Tdbp->GetPath());
-#if defined(WIN32)
+#if defined(__WIN__)
char *p;
DWORD rc;
bool brc;
@@ -3382,7 +3380,7 @@ bool BGVFAM::MakeEmptyFile(PGLOBAL g, char *fn)
CloseHandle(h);
return true;
-#else // !WIN32
+#else // !__WIN__
int h;
BIGINT pos;
@@ -3411,7 +3409,7 @@ bool BGVFAM::MakeEmptyFile(PGLOBAL g, char *fn)
sprintf(g->Message, MSG(MAKE_EMPTY_FILE), To_File, strerror(errno));
close(h);
return true;
-#endif // !WIN32
+#endif // !__WIN__
} // end of MakeEmptyFile
/***********************************************************************/
@@ -3442,7 +3440,7 @@ bool BGVFAM::OpenTableFile(PGLOBAL g)
htrc("OpenTableFile: filename=%s mode=%d Last=%d\n",
filename, mode, Last);
-#if defined(WIN32)
+#if defined(__WIN__)
DWORD access, creation, share = 0, rc = 0;
/*********************************************************************/
@@ -3768,7 +3766,7 @@ int BGVFAM::WriteBuffer(PGLOBAL g)
if (!Closing && !MaxBlk) {
// Close the VCT file and reopen it in mode Insert
-//#if defined(WIN32) //OB
+//#if defined(__WIN__) //OB
// CloseHandle(Hfile);
//#else // UNIX
// close(Hfile);
@@ -3895,7 +3893,7 @@ int BGVFAM::DeleteRecords(PGLOBAL g, int irc)
/***************************************************************/
/* Remove extra records. */
/***************************************************************/
-#if defined(WIN32)
+#if defined(__WIN__)
BIGINT pos = (BIGINT)Block * (BIGINT)Blksize;
if (BigSeek(g, Hfile, pos))
@@ -3907,12 +3905,12 @@ int BGVFAM::DeleteRecords(PGLOBAL g, int irc)
sprintf(g->Message, MSG(SETEOF_ERROR), drc);
return RC_FX;
} // endif error
-#else // !WIN32
+#else // !__WIN__
if (ftruncate64(Hfile, (BIGINT)(Tpos * Lrecl))) {
sprintf(g->Message, MSG(TRUNCATE_ERROR), strerror(errno));
return RC_FX;
} // endif
-#endif // !WIN32
+#endif // !__WIN__
} else // MaxBlk
// Clean the unused space in the file, this is required when
// inserting again with a partial column list.
@@ -3949,7 +3947,7 @@ bool BGVFAM::OpenTempFile(PGLOBAL g)
else if (MakeEmptyFile(g, tempname))
return true;
-#if defined(WIN32)
+#if defined(__WIN__)
DWORD access = (MaxBlk) ? OPEN_EXISTING : CREATE_NEW;
Tfile = CreateFile(tempname, GENERIC_WRITE, 0, NULL,
@@ -4220,7 +4218,7 @@ void BGVFAM::Rewind(void)
CurNum = Nrec - 1;
#if 0 // This is probably unuseful as the file is directly accessed
-#if defined(WIN32) //OB
+#if defined(__WIN__) //OB
SetFilePointer(Hfile, 0, NULL, FILE_BEGIN);
#else // UNIX
lseek64(Hfile, 0, SEEK_SET);
diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp
index 1288689325c..56faa555069 100644
--- a/storage/connect/filamzip.cpp
+++ b/storage/connect/filamzip.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -17,21 +17,21 @@
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <fcntl.h>
#if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro
#endif
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#if defined(UNIX)
#include <errno.h>
#else // !UNIX
#include <io.h>
#endif
#include <fcntl.h>
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Include application header files: */
@@ -89,11 +89,11 @@ int ZIPFAM::Zerror(PGLOBAL g)
strcpy(g->Message, gzerror(Zfile, &errnum));
if (errnum == Z_ERRNO)
-#if defined(WIN32)
+#if defined(__WIN__)
sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(NULL));
-#else // !WIN32
+#else // !__WIN__
sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno));
-#endif // !WIN32
+#endif // !__WIN__
return (errnum == Z_STREAM_END) ? RC_EF : RC_FX;
} // end of Zerror
@@ -247,7 +247,7 @@ int ZIPFAM::GetNextPos(void)
/***********************************************************************/
/* SetPos: Replace the table at the specified position. */
/***********************************************************************/
-bool ZIPFAM::SetPos(PGLOBAL g, int pos)
+bool ZIPFAM::SetPos(PGLOBAL g, int pos __attribute__((unused)))
{
sprintf(g->Message, MSG(NO_SETPOS_YET), "ZIP");
return true;
@@ -267,7 +267,7 @@ bool ZIPFAM::SetPos(PGLOBAL g, int pos)
/***********************************************************************/
/* Record file position in case of UPDATE or DELETE. */
/***********************************************************************/
-bool ZIPFAM::RecordPos(PGLOBAL g)
+bool ZIPFAM::RecordPos(PGLOBAL)
{
Zpos = gztell(Zfile);
return false;
@@ -376,7 +376,7 @@ int ZIPFAM::WriteBuffer(PGLOBAL g)
/***********************************************************************/
/* Data Base delete line routine for ZDOS access method. (NIY) */
/***********************************************************************/
-int ZIPFAM::DeleteRecords(PGLOBAL g, int irc)
+int ZIPFAM::DeleteRecords(PGLOBAL g, int)
{
strcpy(g->Message, MSG(NO_ZIP_DELETE));
return RC_FX;
@@ -385,7 +385,7 @@ int ZIPFAM::DeleteRecords(PGLOBAL g, int irc)
/***********************************************************************/
/* Data Base close routine for DOS access method. */
/***********************************************************************/
-void ZIPFAM::CloseTableFile(PGLOBAL g, bool abort)
+void ZIPFAM::CloseTableFile(PGLOBAL, bool)
{
int rc = gzclose(Zfile);
@@ -431,7 +431,7 @@ ZBKFAM::ZBKFAM(PZBKFAM txfp) : ZIPFAM(txfp)
/***********************************************************************/
/* Use BlockTest to reduce the table estimated size. */
/***********************************************************************/
-int ZBKFAM::MaxBlkSize(PGLOBAL g, int s)
+int ZBKFAM::MaxBlkSize(PGLOBAL g, int)
{
int rc = RC_OK, savcur = CurBlk;
int size;
@@ -503,7 +503,7 @@ int ZBKFAM::GetPos(void)
/* Record file position in case of UPDATE or DELETE. */
/* Not used yet for fixed tables. */
/***********************************************************************/
-bool ZBKFAM::RecordPos(PGLOBAL g)
+bool ZBKFAM::RecordPos(PGLOBAL /*g*/)
{
//strcpy(g->Message, "RecordPos not implemented for zip blocked tables");
//return true;
@@ -513,7 +513,7 @@ bool ZBKFAM::RecordPos(PGLOBAL g)
/***********************************************************************/
/* Skip one record in file. */
/***********************************************************************/
-int ZBKFAM::SkipRecord(PGLOBAL g, bool header)
+int ZBKFAM::SkipRecord(PGLOBAL /*g*/, bool)
{
//strcpy(g->Message, "SkipRecord not implemented for zip blocked tables");
//return RC_FX;
@@ -668,7 +668,7 @@ int ZBKFAM::DeleteRecords(PGLOBAL g, int irc)
/***********************************************************************/
/* Data Base close routine for ZBK access method. */
/***********************************************************************/
-void ZBKFAM::CloseTableFile(PGLOBAL g, bool abort)
+void ZBKFAM::CloseTableFile(PGLOBAL g, bool)
{
int rc = RC_OK;
@@ -764,9 +764,9 @@ bool ZIXFAM::AllocateBuffer(PGLOBAL g)
if (Tdbp->GetFtype() < 2)
// if not binary, the file is physically a text file
for (int len = Lrecl; len <= Buflen; len += Lrecl) {
-#if defined(WIN32)
+#if defined(__WIN__)
To_Buf[len - 2] = '\r';
-#endif // WIN32
+#endif // __WIN__
To_Buf[len - 1] = '\n';
} // endfor len
@@ -1060,7 +1060,7 @@ int ZLBFAM::GetNextPos(void)
/***********************************************************************/
/* SetPos: Replace the table at the specified position. */
/***********************************************************************/
-bool ZLBFAM::SetPos(PGLOBAL g, int pos)
+bool ZLBFAM::SetPos(PGLOBAL g, int pos __attribute__((unused)))
{
sprintf(g->Message, MSG(NO_SETPOS_YET), "ZIP");
return true;
@@ -1350,7 +1350,7 @@ bool ZLBFAM::WriteCompressedBuffer(PGLOBAL g)
/***********************************************************************/
/* Table file close routine for DOS access method. */
/***********************************************************************/
-void ZLBFAM::CloseTableFile(PGLOBAL g, bool abort)
+void ZLBFAM::CloseTableFile(PGLOBAL g, bool)
{
int rc = RC_OK;
diff --git a/storage/connect/filter.cpp b/storage/connect/filter.cpp
index 949d49c2943..262d6b58a70 100644
--- a/storage/connect/filter.cpp
+++ b/storage/connect/filter.cpp
@@ -13,13 +13,13 @@
#include "sql_class.h"
//#include "sql_time.h"
-#if defined(WIN32)
+#if defined(__WIN__)
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
diff --git a/storage/connect/filter.h b/storage/connect/filter.h
index 78e066d9ab7..15730e2cc44 100644
--- a/storage/connect/filter.h
+++ b/storage/connect/filter.h
@@ -1,7 +1,7 @@
/*************** Filter H Declares Source Code File (.H) ***************/
/* Name: FILTER.H Version 1.2 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2010-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 2010-2015 */
/* */
/* This file contains the FILTER and derived classes declares. */
/***********************************************************************/
@@ -105,8 +105,8 @@ class FILTERX : public FILTER {
virtual bool Eval(PGLOBAL) = 0; // just to prevent direct FILTERX use
// Fake operator new used to change a filter into a derived filter
- void * operator new(size_t size, PFIL filp) {return filp;}
-#if defined(WIN32)
+ void * operator new(size_t, PFIL filp) {return filp;}
+#if defined(__WIN__)
// Avoid warning C4291 by defining a matching dummy delete operator
void operator delete(void *, PFIL) {}
#else
diff --git a/storage/connect/fmdlex.c b/storage/connect/fmdlex.c
index a72a2b9b31e..22c3a1e79ad 100644
--- a/storage/connect/fmdlex.c
+++ b/storage/connect/fmdlex.c
@@ -20,11 +20,12 @@
*/
#define FLEX_SCANNER
-#if WIN32
+#ifdef __WIN__
#define __STDC__ 1
+#define isatty _isatty
#endif
#include <stdio.h>
-#ifndef WIN32
+#ifndef __WIN__
#include <unistd.h>
#endif
diff --git a/storage/connect/global.h b/storage/connect/global.h
index 88e5094d6d2..4d01a3ff05b 100644
--- a/storage/connect/global.h
+++ b/storage/connect/global.h
@@ -13,11 +13,11 @@
#include <time.h> /* time_t type declaration */
#include <setjmp.h> /* Long jump declarations */
-#if defined(WIN32) && !defined(NOEX)
+#if defined(__WIN__) && !defined(NOEX)
#define DllExport __declspec( dllexport )
-#else // !WIN32
+#else // !__WIN__
#define DllExport
-#endif // !WIN32
+#endif // !__WIN__
#if defined(DOMDOC_SUPPORT) || defined(LIBXML2_SUPPORT)
#define XML_SUPPORT 1
@@ -42,11 +42,11 @@
#define STEP(I) MSG_##I
#endif // !XMSG and !NEWMSG
-#if defined(WIN32)
+#if defined(__WIN__)
#define CRLF 2
-#else // !WIN32
+#else // !__WIN__
#define CRLF 1
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Define access to the thread based trace value. */
@@ -104,7 +104,7 @@
#define SYS_STAMP "DOSR"
#elif defined(WIN)
#define SYS_STAMP "WIN1"
-#elif defined(WIN32)
+#elif defined(__WIN__)
#define SYS_STAMP "WIN2"
#else
#define SYS_STAMP "XXXX"
@@ -118,7 +118,7 @@ extern "C" {
/* Static variables */
/***********************************************************************/
#if defined(STORAGE)
- char sys_stamp[4] = SYS_STAMP;
+ char sys_stamp[5] = SYS_STAMP;
#else
extern char sys_stamp[];
#endif
@@ -235,7 +235,7 @@ typedef struct _global { /* Global structure */
void *Xchk; /* indexes in create/alter */
short Alchecked; /* Checked for ALTER */
short Mrr; /* True when doing mrr */
- short Trace;
+ int N; /* Utility */
int jump_level;
jmp_buf jumper[MAX_JUMP + 2];
} GLOBAL;
@@ -248,9 +248,9 @@ DllExport char *PlugReadMessage(PGLOBAL, int, char *);
#elif defined(NEWMSG)
DllExport char *PlugGetMessage(PGLOBAL, int);
#endif // XMSG || NEWMSG
-#if defined(WIN32)
+#if defined(__WIN__)
DllExport short GetLineLength(PGLOBAL); // Console line length
-#endif // WIN32
+#endif // __WIN__
DllExport PGLOBAL PlugInit(LPCSTR, uint); // Plug global initialization
DllExport int PlugExit(PGLOBAL); // Plug global termination
DllExport LPSTR PlugRemoveType(LPSTR, LPCSTR);
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index a0ac4668eba..c2fb6481cb0 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -130,24 +130,21 @@
#if defined(ODBC_SUPPORT)
#include "odbccat.h"
#endif // ODBC_SUPPORT
-#if defined(MYSQL_SUPPORT)
#include "xtable.h"
#include "tabmysql.h"
-#endif // MYSQL_SUPPORT
#include "filamdbf.h"
#include "tabxcl.h"
#include "tabfmt.h"
#include "reldef.h"
#include "tabcol.h"
#include "xindex.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include "tabwmi.h"
-#endif // WIN32
+#endif // __WIN__
#include "connect.h"
#include "user_connect.h"
#include "ha_connect.h"
-#include "mycat.h"
#include "myutil.h"
#include "preparse.h"
#include "inihandl.h"
@@ -156,6 +153,7 @@
#endif // LIBXML2_SUPPORT
#include "taboccur.h"
#include "tabpivot.h"
+#include "tabfix.h"
#define my_strupr(p) my_caseup_str(default_charset_info, (p));
#define my_strlwr(p) my_casedn_str(default_charset_info, (p));
@@ -165,40 +163,27 @@
/***********************************************************************/
/* Initialize the ha_connect static members. */
/***********************************************************************/
-#define SZCONV 8192
-#define SZWORK 67108864 // Default work area size 64M
-#define SZWMIN 4194304 // Minimum work area size 4M
+#define SZCONV 8192
+#define SZWORK 67108864 // Default work area size 64M
+#define SZWMIN 4194304 // Minimum work area size 4M
+#define JSONMAX 10 // JSON Default max grp size
extern "C" {
- char version[]= "Version 1.03.0006 January 13, 2015";
- char compver[]= "Version 1.03.0006 " __DATE__ " " __TIME__;
-
-#if defined(WIN32)
+ char version[]= "Version 1.03.0007 June 03, 2015";
+#if defined(__WIN__)
+ char compver[]= "Version 1.03.0007 " __DATE__ " " __TIME__;
char slash= '\\';
-#else // !WIN32
+#else // !__WIN__
char slash= '/';
-#endif // !WIN32
-
-// int trace= 0; // The general trace value
- ulong xconv= 0; // The type conversion option
- int zconv= 0; // The text conversion size
+#endif // !__WIN__
} // extern "C"
#if defined(XMAP)
my_bool xmap= false;
#endif // XMAP
-// uint worksize= 0;
ulong ha_connect::num= 0;
-//int DTVAL::Shift= 0;
-/* CONNECT system variables */
-//atic int conv_size= 0;
-//atic uint work_size= 0;
-//atic ulong type_conv= 0;
-#if defined(XMAP)
-//atic my_bool indx_map= 0;
-#endif // XMAP
#if defined(XMSG)
extern "C" {
char *msg_path;
@@ -209,12 +194,17 @@ extern "C" {
/* Utility functions. */
/***********************************************************************/
PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
-PQRYRES VirColumns(PGLOBAL g, char *tab, char *db, bool info);
+PQRYRES VirColumns(PGLOBAL g, bool info);
+PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info);
+PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info);
void PushWarning(PGLOBAL g, THD *thd, int level);
bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
const char *db, char *tab, const char *src, int port);
bool ExactInfo(void);
USETEMP UseTemp(void);
+int GetConvSize(void);
+TYPCONV GetTypeConv(void);
+uint GetJsonGrpSize(void);
uint GetWorkSize(void);
void SetWorkSize(uint);
extern "C" const char *msglang(void);
@@ -289,6 +279,44 @@ static MYSQL_THDVAR_UINT(work_size,
"Size of the CONNECT work area.",
NULL, NULL, SZWORK, SZWMIN, UINT_MAX, 1);
+// Size used when converting TEXT columns to VARCHAR
+static MYSQL_THDVAR_INT(conv_size,
+ PLUGIN_VAR_RQCMDARG, // opt
+ "Size used when converting TEXT columns.",
+ NULL, NULL, SZCONV, 0, 65500, 1);
+
+/**
+ Type conversion:
+ no: Unsupported types -> TYPE_ERROR
+ yes: TEXT -> VARCHAR
+ skip: skip unsupported type columns in Discovery
+*/
+const char *xconv_names[]=
+{
+ "NO", "YES", "SKIP", NullS
+};
+
+TYPELIB xconv_typelib=
+{
+ array_elements(xconv_names) - 1, "xconv_typelib",
+ xconv_names, NULL
+};
+
+static MYSQL_THDVAR_ENUM(
+ type_conv, // name
+ PLUGIN_VAR_RQCMDARG, // opt
+ "Unsupported types conversion.", // comment
+ NULL, // check
+ NULL, // update function
+ 0, // def (no)
+ &xconv_typelib); // typelib
+
+// Estimate max number of rows for JSON aggregate functions
+static MYSQL_THDVAR_UINT(json_grp_size,
+ PLUGIN_VAR_RQCMDARG, // opt
+ "max number of rows for JSON aggregate functions.",
+ NULL, NULL, JSONMAX, 1, INT_MAX, 1);
+
#if defined(XMSG) || defined(NEWMSG)
const char *language_names[]=
{
@@ -317,8 +345,11 @@ static MYSQL_THDVAR_ENUM(
extern "C" int GetTraceValue(void) {return THDVAR(current_thd, xtrace);}
bool ExactInfo(void) {return THDVAR(current_thd, exact_info);}
USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);}
+int GetConvSize(void) {return THDVAR(current_thd, conv_size);}
+TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);}
+uint GetJsonGrpSize(void) {return THDVAR(current_thd, json_grp_size);}
uint GetWorkSize(void) {return THDVAR(current_thd, work_size);}
-void SetWorkSize(uint n)
+void SetWorkSize(uint)
{
// Changing the session variable value seems to be impossible here
// and should be done in a check function
@@ -568,9 +599,9 @@ DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR name, LPCSTR dir)
delete_table method in handler.cc
*/
static const char *ha_connect_exts[]= {
- ".dos", ".fix", ".csv", ".bin", ".fmt", ".dbf", ".xml", ".ini", ".vec",
- ".dnx", ".fnx", ".bnx", ".vnx", ".dbx", ".dop", ".fop", ".bop", ".vop",
- NULL};
+ ".dos", ".fix", ".csv", ".bin", ".fmt", ".dbf", ".xml", ".json", ".ini",
+ ".vec", ".dnx", ".fnx", ".bnx", ".vnx", ".dbx", ".dop", ".fop", ".bop",
+ ".vop", NULL};
/**
@brief
@@ -598,7 +629,11 @@ static int connect_init_func(void *p)
}
#endif // 0 (LINUX)
+#if defined(__WIN__)
sql_print_information("CONNECT: %s", compver);
+#else // !__WIN__
+ sql_print_information("CONNECT: %s", version);
+#endif // !__WIN__
#ifdef LIBXML2_SUPPORT
XmlInitParserLib();
@@ -621,6 +656,7 @@ static int connect_init_func(void *p)
sql_print_information("connect_init: hton=%p", p);
DTVAL::SetTimeShift(); // Initialize time zone shift once for all
+ BINCOL::SetEndian(); // Initialize host endian setting
DBUG_RETURN(0);
} // end of connect_init_func
@@ -629,7 +665,7 @@ static int connect_init_func(void *p)
@brief
Plugin clean up
*/
-static int connect_done_func(void *p)
+static int connect_done_func(void *)
{
int error= 0;
PCONNECT pc, pn;
@@ -639,9 +675,9 @@ static int connect_done_func(void *p)
XmlCleanupParserLib();
#endif // LIBXML2_SUPPORT
-#if !defined(WIN32)
+#if !defined(__WIN__)
//PROFILE_End(); Causes signal 11
-#endif // !WIN32
+#endif // !__WIN__
for (pc= user_connect::to_users; pc; pc= pn) {
if (pc->g)
@@ -708,11 +744,11 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
xp= (table) ? GetUser(ha_thd(), NULL) : NULL;
if (xp)
xp->SetHandler(this);
-#if defined(WIN32)
+#if defined(__WIN__)
datapath= ".\\";
-#else // !WIN32
+#else // !__WIN__
datapath= "./";
-#endif // !WIN32
+#endif // !__WIN__
tdbp= NULL;
sdvalin1= sdvalin2= sdvalin3= sdvalin4= NULL;
sdvalout= NULL;
@@ -787,8 +823,6 @@ ha_connect::~ha_connect(void)
/****************************************************************************/
static PCONNECT GetUser(THD *thd, PCONNECT xp)
{
- const char *dbn= NULL;
-
if (!thd)
return NULL;
@@ -800,7 +834,7 @@ static PCONNECT GetUser(THD *thd, PCONNECT xp)
break;
if (!xp) {
- xp= new user_connect(thd, dbn);
+ xp= new user_connect(thd);
if (xp->user_init()) {
delete xp;
@@ -873,7 +907,8 @@ const char *ha_connect::index_type(uint inx)
If all_parts is set, MySQL wants to know the flags for the combined
index, up to and including 'part'.
*/
-ulong ha_connect::index_flags(uint inx, uint part, bool all_parts) const
+//ong ha_connect::index_flags(uint inx, uint part, bool all_parts) const
+ulong ha_connect::index_flags(uint, uint, bool) const
{
ulong flags= HA_READ_NEXT | HA_READ_RANGE |
HA_KEYREAD_ONLY | HA_KEY_SCAN_NOT_ROR;
@@ -934,6 +969,9 @@ ulonglong ha_connect::table_flags() const
char *GetListOption(PGLOBAL g, const char *opname,
const char *oplist, const char *def)
{
+ if (!oplist)
+ return (char*)def;
+
char key[16], val[256];
char *pk, *pv, *pn;
char *opval= (char*) def;
@@ -968,8 +1006,7 @@ char *GetListOption(PGLOBAL g, const char *opname,
} // endif pv
if (!stricmp(opname, key)) {
- opval= (char*)PlugSubAlloc(g, NULL, strlen(val) + 1);
- strcpy(opval, val);
+ opval= PlugDup(g, val);
break;
} else if (!pn)
break;
@@ -980,6 +1017,117 @@ char *GetListOption(PGLOBAL g, const char *opname,
} // end of GetListOption
/****************************************************************************/
+/* Return the value of a string option or NULL if not specified. */
+/****************************************************************************/
+char *GetStringTableOption(PGLOBAL g, PTOS options, char *opname, char *sdef)
+{
+ const char *opval= NULL;
+
+ if (!options)
+ return sdef;
+ else if (!stricmp(opname, "Type"))
+ opval= options->type;
+ else if (!stricmp(opname, "Filename"))
+ opval= options->filename;
+ else if (!stricmp(opname, "Optname"))
+ opval= options->optname;
+ else if (!stricmp(opname, "Tabname"))
+ opval= options->tabname;
+ else if (!stricmp(opname, "Tablist"))
+ opval= options->tablist;
+ else if (!stricmp(opname, "Database") ||
+ !stricmp(opname, "DBname"))
+ opval= options->dbname;
+ else if (!stricmp(opname, "Separator"))
+ opval= options->separator;
+ else if (!stricmp(opname, "Qchar"))
+ opval= options->qchar;
+ else if (!stricmp(opname, "Module"))
+ opval= options->module;
+ else if (!stricmp(opname, "Subtype"))
+ opval= options->subtype;
+ else if (!stricmp(opname, "Catfunc"))
+ opval= options->catfunc;
+ else if (!stricmp(opname, "Srcdef"))
+ opval= options->srcdef;
+ else if (!stricmp(opname, "Colist"))
+ opval= options->colist;
+ else if (!stricmp(opname, "Data_charset"))
+ opval= options->data_charset;
+
+ if (!opval && options && options->oplist)
+ opval= GetListOption(g, opname, options->oplist);
+
+ return opval ? (char*)opval : sdef;
+} // end of GetStringTableOption
+
+/****************************************************************************/
+/* Return the value of a Boolean option or bdef if not specified. */
+/****************************************************************************/
+bool GetBooleanTableOption(PGLOBAL g, PTOS options, char *opname, bool bdef)
+{
+ bool opval= bdef;
+ char *pv;
+
+ if (!options)
+ return bdef;
+ else if (!stricmp(opname, "Mapped"))
+ opval= options->mapped;
+ else if (!stricmp(opname, "Huge"))
+ opval= options->huge;
+ else if (!stricmp(opname, "Split"))
+ opval= options->split;
+ else if (!stricmp(opname, "Readonly"))
+ opval= options->readonly;
+ else if (!stricmp(opname, "SepIndex"))
+ opval= options->sepindex;
+ else if (!stricmp(opname, "Header"))
+ opval= (options->header != 0); // Is Boolean for some table types
+ else if (options->oplist)
+ if ((pv= GetListOption(g, opname, options->oplist)))
+ opval= (!*pv || *pv == 'y' || *pv == 'Y' || atoi(pv) != 0);
+
+ return opval;
+} // end of GetBooleanTableOption
+
+/****************************************************************************/
+/* Return the value of an integer option or NO_IVAL if not specified. */
+/****************************************************************************/
+int GetIntegerTableOption(PGLOBAL g, PTOS options, char *opname, int idef)
+{
+ ulonglong opval= NO_IVAL;
+
+ if (!options)
+ return idef;
+ else if (!stricmp(opname, "Lrecl"))
+ opval= options->lrecl;
+ else if (!stricmp(opname, "Elements"))
+ opval= options->elements;
+ else if (!stricmp(opname, "Multiple"))
+ opval= options->multiple;
+ else if (!stricmp(opname, "Header"))
+ opval= options->header;
+ else if (!stricmp(opname, "Quoted"))
+ opval= options->quoted;
+ else if (!stricmp(opname, "Ending"))
+ opval= options->ending;
+ else if (!stricmp(opname, "Compressed"))
+ opval= (options->compressed);
+
+ if (opval == NO_IVAL) {
+ char *pv;
+
+ if ((pv= GetListOption(g, opname, options->oplist)))
+ opval= CharToNumber(pv, strlen(pv), ULONGLONG_MAX, true);
+ else
+ return idef;
+
+ } // endif opval
+
+ return (int)opval;
+} // end of GetIntegerTableOption
+
+/****************************************************************************/
/* Return the table option structure. */
/****************************************************************************/
PTOS ha_connect::GetTableOptionStruct(TABLE_SHARE *s)
@@ -997,8 +1145,9 @@ char *ha_connect::GetRealString(const char *s)
char *sv;
if (IsPartitioned() && s) {
- sv= (char*)PlugSubAlloc(xp->g, NULL, strlen(s) + strlen(partname));
+ sv= (char*)PlugSubAlloc(xp->g, NULL, 0);
sprintf(sv, s, partname);
+ PlugSubAlloc(xp->g, NULL, strlen(sv) + 1);
} else
sv= (char*)s;
@@ -1006,7 +1155,7 @@ char *ha_connect::GetRealString(const char *s)
} // end of GetRealString
/****************************************************************************/
-/* Return the value of a string option or NULL if not specified. */
+/* Return the value of a string option or sdef if not specified. */
/****************************************************************************/
char *ha_connect::GetStringOption(char *opname, char *sdef)
{
@@ -1024,37 +1173,6 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
opval= thd_query_string(table->in_use)->str;
else if (!stricmp(opname, "Partname"))
opval= partname;
- else if (!options)
- ;
- else if (!stricmp(opname, "Type"))
- opval= (char*)options->type;
- else if (!stricmp(opname, "Filename"))
- opval= GetRealString(options->filename);
- else if (!stricmp(opname, "Optname"))
- opval= (char*)options->optname;
- else if (!stricmp(opname, "Tabname"))
- opval= GetRealString(options->tabname);
- else if (!stricmp(opname, "Tablist"))
- opval= (char*)options->tablist;
- else if (!stricmp(opname, "Database") ||
- !stricmp(opname, "DBname"))
- opval= (char*)options->dbname;
- else if (!stricmp(opname, "Separator"))
- opval= (char*)options->separator;
- else if (!stricmp(opname, "Qchar"))
- opval= (char*)options->qchar;
- else if (!stricmp(opname, "Module"))
- opval= (char*)options->module;
- else if (!stricmp(opname, "Subtype"))
- opval= (char*)options->subtype;
- else if (!stricmp(opname, "Catfunc"))
- opval= (char*)options->catfunc;
- else if (!stricmp(opname, "Srcdef"))
- opval= (char*)options->srcdef;
- else if (!stricmp(opname, "Colist"))
- opval= (char*)options->colist;
- else if (!stricmp(opname, "Data_charset"))
- opval= (char*)options->data_charset;
else if (!stricmp(opname, "Table_charset")) {
const CHARSET_INFO *chif= (tshp) ? tshp->table_charset
: table->s->table_charset;
@@ -1062,10 +1180,13 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
if (chif)
opval= (char*)chif->csname;
- } // endif Table_charset
+ } else
+ opval= GetStringTableOption(xp->g, options, opname, NULL);
- if (!opval && options && options->oplist)
- opval= GetListOption(xp->g, opname, options->oplist);
+ if (opval && (!stricmp(opname, "connect")
+ || !stricmp(opname, "tabname")
+ || !stricmp(opname, "filename")))
+ opval = GetRealString(opval);
if (!opval) {
if (sdef && !strcmp(sdef, "*")) {
@@ -1096,31 +1217,13 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
/****************************************************************************/
bool ha_connect::GetBooleanOption(char *opname, bool bdef)
{
- bool opval= bdef;
- char *pv;
+ bool opval;
PTOS options= GetTableOptionStruct();
if (!stricmp(opname, "View"))
opval= (tshp) ? tshp->is_view : table_share->is_view;
- else if (!options)
- ;
- else if (!stricmp(opname, "Mapped"))
- opval= options->mapped;
- else if (!stricmp(opname, "Huge"))
- opval= options->huge;
-//else if (!stricmp(opname, "Compressed"))
-// opval= options->compressed;
- else if (!stricmp(opname, "Split"))
- opval= options->split;
- else if (!stricmp(opname, "Readonly"))
- opval= options->readonly;
- else if (!stricmp(opname, "SepIndex"))
- opval= options->sepindex;
- else if (!stricmp(opname, "Header"))
- opval= (options->header != 0); // Is Boolean for some table types
- else if (options->oplist)
- if ((pv= GetListOption(xp->g, opname, options->oplist)))
- opval= (!*pv || *pv == 'y' || *pv == 'Y' || atoi(pv) != 0);
+ else
+ opval= GetBooleanTableOption(xp->g, options, opname, bdef);
return opval;
} // end of GetBooleanOption
@@ -1149,37 +1252,18 @@ bool ha_connect::SetBooleanOption(char *opname, bool b)
/****************************************************************************/
int ha_connect::GetIntegerOption(char *opname)
{
- ulonglong opval= NO_IVAL;
- char *pv;
+ int opval;
PTOS options= GetTableOptionStruct();
TABLE_SHARE *tsp= (tshp) ? tshp : table_share;
if (!stricmp(opname, "Avglen"))
- opval= (ulonglong)tsp->avg_row_length;
+ opval= (int)tsp->avg_row_length;
else if (!stricmp(opname, "Estimate"))
- opval= (ulonglong)tsp->max_rows;
- else if (!options)
- ;
- else if (!stricmp(opname, "Lrecl"))
- opval= options->lrecl;
- else if (!stricmp(opname, "Elements"))
- opval= options->elements;
- else if (!stricmp(opname, "Multiple"))
- opval= options->multiple;
- else if (!stricmp(opname, "Header"))
- opval= options->header;
- else if (!stricmp(opname, "Quoted"))
- opval= options->quoted;
- else if (!stricmp(opname, "Ending"))
- opval= options->ending;
- else if (!stricmp(opname, "Compressed"))
- opval= (options->compressed);
-
- if (opval == (ulonglong)NO_IVAL && options && options->oplist)
- if ((pv= GetListOption(xp->g, opname, options->oplist)))
- opval= CharToNumber(pv, strlen(pv), ULONGLONG_MAX, true);
+ opval= (int)tsp->max_rows;
+ else
+ opval= GetIntegerTableOption(xp->g, options, opname, NO_IVAL);
- return (int)opval;
+ return opval;
} // end of GetIntegerOption
/****************************************************************************/
@@ -1443,8 +1527,7 @@ PIXDEF ha_connect::GetIndexInfo(TABLE_SHARE *s)
// Now get index information
pn= (char*)s->keynames.type_names[n];
- name= (char*)PlugSubAlloc(g, NULL, strlen(pn) + 1);
- strcpy(name, pn); // This is probably unuseful
+ name= PlugDup(g, pn);
unique= (kp.flags & 1) != 0;
pkp= NULL;
@@ -1454,8 +1537,7 @@ PIXDEF ha_connect::GetIndexInfo(TABLE_SHARE *s)
// Get the the key parts info
for (int k= 0; (unsigned)k < kp.user_defined_key_parts; k++) {
pn= (char*)kp.key_part[k].field->field_name;
- name= (char*)PlugSubAlloc(g, NULL, strlen(pn) + 1);
- strcpy(name, pn); // This is probably unuseful
+ name= PlugDup(g, pn);
// Allocate the key part description block
kpp= new(g) KPARTDEF(name, k + 1);
@@ -1962,7 +2044,7 @@ int ha_connect::MakeRecord(char *buf)
/***********************************************************************/
/* Set row values from a MySQL pseudo record. Specific to MySQL. */
/***********************************************************************/
-int ha_connect::ScanRecord(PGLOBAL g, uchar *buf)
+int ha_connect::ScanRecord(PGLOBAL g, uchar *)
{
char attr_buffer[1024];
char data_buffer[1024];
@@ -2104,7 +2186,7 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *buf)
/* Check change in index column. Specific to MySQL. */
/* Should be elaborated to check for real changes. */
/***********************************************************************/
-int ha_connect::CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf)
+int ha_connect::CheckRecord(PGLOBAL g, const uchar *, uchar *newbuf)
{
return ScanRecord(g, newbuf);
} // end of dummy CheckRecord
@@ -2113,12 +2195,12 @@ int ha_connect::CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf)
/***********************************************************************/
/* Return the where clause for remote indexed read. */
/***********************************************************************/
-bool ha_connect::MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
+bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
const void *key, int klen)
{
const uchar *ptr;
uint rem, len, stlen; //, prtlen;
- bool nq, b= false;
+ bool nq, oom, b= false;
Field *fp;
KEY *kfp;
KEY_PART_INFO *kpart;
@@ -2130,7 +2212,7 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
return true;
} // endif key
- strcat(qry, " WHERE (");
+ oom= qry->Append(" WHERE (");
kfp= &table->key_info[active_index];
rem= kfp->user_defined_key_parts,
len= klen,
@@ -2143,24 +2225,26 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
nq= fp->str_needs_quotes();
if (b)
- strcat(qry, " AND ");
+ oom|= qry->Append(" AND ");
else
b= true;
- strcat(strncat(strcat(qry, q), fp->field_name, strlen(fp->field_name)), q);
+ oom|= qry->Append(q);
+ oom|= qry->Append((PSZ)fp->field_name);
+ oom|= qry->Append(q);
switch (op) {
case OP_EQ:
case OP_GT:
case OP_GE:
- strcat(qry, GetValStr(op, false));
+ oom|= qry->Append((PSZ)GetValStr(op, false));
break;
default:
- strcat(qry, " ??? ");
+ oom|= qry->Append(" ??? ");
} // endwitch op
if (nq)
- strcat(qry, "'");
+ oom|= qry->Append('\'');
if (kpart->key_part_flag & HA_VAR_LENGTH_PART) {
String varchar;
@@ -2168,17 +2252,17 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
varchar.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH,
var_length, &my_charset_bin);
- strncat(qry, varchar.ptr(), varchar.length());
+ oom|= qry->Append(varchar.ptr(), varchar.length());
} else {
char strbuff[MAX_FIELD_WIDTH];
String str(strbuff, sizeof(strbuff), kpart->field->charset()), *res;
res= fp->val_str(&str, ptr);
- strncat(qry, res->ptr(), res->length());
+ oom|= qry->Append(res->ptr(), res->length());
} // endif flag
if (nq)
- strcat(qry, "'");
+ oom|= qry->Append('\'');
if (stlen >= len)
break;
@@ -2191,8 +2275,10 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
ptr+= stlen - MY_TEST(kpart->null_bit);
} // endfor kpart
- strcat(qry, ")");
- return false;
+ if ((oom|= qry->Append(")")))
+ strcpy(g->Message, "Out of memory");
+
+ return oom;
} // end of MakeKeyWhere
@@ -2467,6 +2553,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
char *body= filp->Body;
unsigned int i;
bool ismul= false, x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
+ bool nonul= (tty == TYPE_AM_ODBC && (tdbp->GetMode() == MODE_INSERT ||
+ tdbp->GetMode() == MODE_DELETE));
OPVAL vop= OP_XX;
if (!cond)
@@ -2484,7 +2572,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
if (trace)
htrc("Cond: Ftype=%d name=%s\n", cond_item->functype(),
- cond_item->func_name());
+ cond_item->func_name());
switch (cond_item->functype()) {
case Item_func::COND_AND_FUNC: vop= OP_AND; break;
@@ -2503,7 +2591,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
for (i= 0; i < arglist->elements; i++)
if ((subitem= li++)) {
if (!CheckCond(g, filp, tty, subitem)) {
- if (vop == OP_OR)
+ if (vop == OP_OR || nonul)
return NULL;
else
*p2= 0;
@@ -2599,6 +2687,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
if (trace) {
htrc("Field index=%d\n", pField->field->field_index);
htrc("Field name=%s\n", pField->field->field_name);
+ htrc("Field type=%d\n", pField->field->type());
+ htrc("Field_type=%d\n", args[i]->field_type());
} // endif trace
// IN and BETWEEN clauses should be col VOP list
@@ -2618,8 +2708,9 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
char buff[256];
String *res, tmp(buff, sizeof(buff), &my_charset_bin);
Item_basic_constant *pval= (Item_basic_constant *)args[i];
+ Item::Type type= args[i]->real_type();
- switch (args[i]->real_type()) {
+ switch (type) {
case COND::STRING_ITEM:
case COND::INT_ITEM:
case COND::REAL_ITEM:
@@ -2644,10 +2735,73 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
if (!x) {
// Append the value to the filter
- if (args[i]->field_type() == MYSQL_TYPE_VARCHAR)
- strcat(strncat(strcat(body, "'"), res->ptr(), res->length()), "'");
- else
- strncat(body, res->ptr(), res->length());
+ switch (args[i]->field_type()) {
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ if (tty == TYPE_AM_ODBC) {
+ strcat(body, "{ts '");
+ strncat(body, res->ptr(), res->length());
+
+ if (res->length() < 19)
+ strcat(body, "1970-01-01 00:00:00" + res->length());
+
+ strcat(body, "'}");
+ break;
+ } // endif ODBC
+
+ case MYSQL_TYPE_DATE:
+ if (tty == TYPE_AM_ODBC) {
+ strcat(body, "{d '");
+ strcat(strncat(body, res->ptr(), res->length()), "'}");
+ break;
+ } // endif ODBC
+
+ case MYSQL_TYPE_TIME:
+ if (tty == TYPE_AM_ODBC) {
+ strcat(body, "{t '");
+ strcat(strncat(body, res->ptr(), res->length()), "'}");
+ break;
+ } // endif ODBC
+
+ case MYSQL_TYPE_VARCHAR:
+ if (tty == TYPE_AM_ODBC && i) {
+ switch (args[0]->field_type()) {
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ strcat(body, "{ts '");
+ strncat(body, res->ptr(), res->length());
+
+ if (res->length() < 19)
+ strcat(body, "1970-01-01 00:00:00" + res->length());
+
+ strcat(body, "'}");
+ break;
+ case MYSQL_TYPE_DATE:
+ strcat(body, "{d '");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'}");
+ break;
+ case MYSQL_TYPE_TIME:
+ strcat(body, "{t '");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'}");
+ break;
+ default:
+ strcat(body, "'");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'");
+ } // endswitch field type
+
+ } else {
+ strcat(body, "'");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'");
+ } // endif tty
+
+ break;
+ default:
+ strncat(body, res->ptr(), res->length());
+ } // endswitch field type
} else {
if (args[i]->field_type() == MYSQL_TYPE_VARCHAR) {
@@ -2753,7 +2907,7 @@ const COND *ha_connect::cond_push(const COND *cond)
} else if (x && cond)
tdbp->SetCondFil(filp); // Wrong filter
- } else
+ } else if (tty != TYPE_AM_JSN && tty != TYPE_AM_JSON)
tdbp->SetFilter(CondFilter(g, (Item *)cond));
fin:
@@ -2805,7 +2959,7 @@ bool ha_connect::get_error_message(int error, String* buf)
&dummy_errors);
if (trace)
- htrc("GEM(%u): %s\n", len, g->Message);
+ htrc("GEM(%d): len=%u %s\n", error, len, g->Message);
msg[len]= '\0';
buf->copy(msg, (uint)strlen(msg), system_charset_info);
@@ -2901,7 +3055,7 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked)
@brief
Make the indexes for this table
*/
-int ha_connect::optimize(THD* thd, HA_CHECK_OPT* check_opt)
+int ha_connect::optimize(THD* thd, HA_CHECK_OPT*)
{
int rc= 0;
PGLOBAL& g= xp->g;
@@ -3105,7 +3259,7 @@ int ha_connect::update_row(const uchar *old_data, uchar *new_data)
@see
sql_acl.cc, sql_udf.cc, sql_delete.cc, sql_insert.cc and sql_select.cc
*/
-int ha_connect::delete_row(const uchar *buf)
+int ha_connect::delete_row(const uchar *)
{
int rc= 0;
DBUG_ENTER("ha_connect::delete_row");
@@ -3385,7 +3539,8 @@ int ha_connect::index_last(uchar *buf)
/****************************************************************************/
/* This is called to get more rows having the same index value. */
/****************************************************************************/
-int ha_connect::index_next_same(uchar *buf, const uchar *key, uint keylen)
+//t ha_connect::index_next_same(uchar *buf, const uchar *key, uint keylen)
+int ha_connect::index_next_same(uchar *buf, const uchar *, uint)
{
int rc;
DBUG_ENTER("ha_connect::index_next_same");
@@ -3575,7 +3730,7 @@ int ha_connect::rnd_next(uchar *buf)
@see
filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc
*/
-void ha_connect::position(const uchar *record)
+void ha_connect::position(const uchar *)
{
DBUG_ENTER("ha_connect::position");
//if (((PTDBASE)tdbp)->GetDef()->Indexable())
@@ -3758,7 +3913,7 @@ int ha_connect::info(uint flag)
@see
ha_innodb.cc
*/
-int ha_connect::extra(enum ha_extra_function operation)
+int ha_connect::extra(enum ha_extra_function /*operation*/)
{
DBUG_ENTER("ha_connect::extra");
DBUG_RETURN(0);
@@ -3837,11 +3992,11 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
case TAB_JSON:
if (options->filename && *options->filename) {
char *s, path[FN_REFLEN], dbpath[FN_REFLEN];
-#if defined(WIN32)
+#if defined(__WIN__)
s= "\\";
-#else // !WIN32
+#else // !__WIN__
s= "/";
-#endif // !WIN32
+#endif // !__WIN__
strcpy(dbpath, mysql_real_data_home);
if (db)
@@ -3990,6 +4145,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
case SQLCOM_UPDATE_MULTI:
case SQLCOM_SELECT:
case SQLCOM_OPTIMIZE:
+ case SQLCOM_SET_OPTION:
break;
case SQLCOM_LOCK_TABLES:
locked= 1;
@@ -4014,6 +4170,10 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
break;
// } // endif partitioned
+ case SQLCOM_END:
+ // Met in procedures: IF(EXISTS(SELECT...
+ newmode= MODE_READ;
+ break;
default:
htrc("Unsupported sql_command=%d\n", thd_sql_command(thd));
strcpy(g->Message, "CONNECT Unsupported command");
@@ -4361,7 +4521,7 @@ int ha_connect::external_lock(THD *thd, int lock_type)
@see
get_lock_data() in lock.cc
*/
-THR_LOCK_DATA **ha_connect::store_lock(THD *thd,
+THR_LOCK_DATA **ha_connect::store_lock(THD *,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
{
@@ -4509,8 +4669,13 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to)
} // endif pos
- } else // Avoid infamous DBUG_ASSERT
- thd->get_stmt_da()->reset_diagnostics_area();
+ } // endif open_table_def
+
+// This below was done to avoid DBUG_ASSERT in some case that
+// we don't know anymore what they were. It was suppressed because
+// it did cause assertion in other cases (see MDEV-7935)
+// } else // Avoid infamous DBUG_ASSERT
+// thd->get_stmt_da()->reset_diagnostics_area();
free_table_share(share);
} else // Temporary file
@@ -4590,9 +4755,31 @@ ha_rows ha_connect::records_in_range(uint inx, key_range *min_key,
else
rows= HA_POS_ERROR;
+ if (trace)
+ htrc("records_in_range: rows=%llu\n", rows);
+
DBUG_RETURN(rows);
} // end of records_in_range
+// Used to check whether a MYSQL table is created on itself
+bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
+ const char *db, char *tab, const char *src, int port)
+{
+ if (src)
+ return false;
+ else if (host && stricmp(host, "localhost") && strcmp(host, "127.0.0.1"))
+ return false;
+ else if (db && stricmp(db, s->db.str))
+ return false;
+ else if (tab && stricmp(tab, s->table_name.str))
+ return false;
+ else if (port && port != (signed)GetDefaultPort())
+ return false;
+
+ strcpy(g->Message, "This MySQL table is defined on itself");
+ return true;
+} // end of CheckSelf
+
/**
Convert an ISO-8859-1 column name to UTF-8
*/
@@ -4615,12 +4802,12 @@ static char *encode(PGLOBAL g, const char *cnm)
@return
Return 0 if ok
*/
-static bool add_field(String *sql, const char *field_name, int typ,
- int len, int dec, char *key, uint tm, const char *rem,
- char *dft, char *xtra, int flag, bool dbf, char v)
+static bool add_field(String *sql, const char *field_name, int typ, int len,
+ int dec, char *key, uint tm, const char *rem, char *dft,
+ char *xtra, char *fmt, int flag, bool dbf, char v)
{
char var = (len > 255) ? 'V' : v;
- bool error= false;
+ bool q, error= false;
const char *type= PLGtoMYSQLtype(typ, dbf, var);
error|= sql->append('`');
@@ -4661,7 +4848,12 @@ static bool add_field(String *sql, const char *field_name, int typ,
if (dft && *dft) {
error|= sql->append(" DEFAULT ");
- if (!IsTypeNum(typ)) {
+ if (typ == TYPE_DATE)
+ q = (strspn(dft, "0123456789 -:/") == strlen(dft));
+ else
+ q = !IsTypeNum(typ);
+
+ if (q) {
error|= sql->append("'");
error|= sql->append_for_single_quote(dft, strlen(dft));
error|= sql->append("'");
@@ -4681,6 +4873,12 @@ static bool add_field(String *sql, const char *field_name, int typ,
error|= sql->append("'");
} // endif rem
+ if (fmt && *fmt) {
+ error|= sql->append(" FIELD_FORMAT='");
+ error|= sql->append_for_single_quote(fmt, strlen(fmt));
+ error|= sql->append("'");
+ } // endif flag
+
if (flag) {
error|= sql->append(" FLAG=");
error|= sql->append_ulonglong(flag);
@@ -4743,7 +4941,7 @@ static int init_table_share(THD* thd,
oom|= sql->append(' ');
oom|= sql->append(opt->name);
oom|= sql->append('=');
- oom|= sql->append(vull ? "ON" : "OFF");
+ oom|= sql->append(vull ? "YES" : "NO");
} // endif vull
break;
@@ -4785,25 +4983,6 @@ static int init_table_share(THD* thd,
sql->ptr(), sql->length());
} // end of init_table_share
-// Used to check whether a MYSQL table is created on itself
-bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
- const char *db, char *tab, const char *src, int port)
-{
- if (src)
- return false;
- else if (host && stricmp(host, "localhost") && strcmp(host, "127.0.0.1"))
- return false;
- else if (db && stricmp(db, s->db.str))
- return false;
- else if (tab && stricmp(tab, s->table_name.str))
- return false;
- else if (port && port != (signed)GetDefaultPort())
- return false;
-
- strcpy(g->Message, "This MySQL table is defined on itself");
- return true;
-} // end of CheckSelf
-
/**
@brief
connect_assisted_discovery() is called when creating a table with no columns.
@@ -4816,7 +4995,7 @@ bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
@note
this function is no more called in case of CREATE .. SELECT
*/
-static int connect_assisted_discovery(handlerton *hton, THD* thd,
+static int connect_assisted_discovery(handlerton *, THD* thd,
TABLE_SHARE *table_s,
HA_CREATE_INFO *create_info)
{
@@ -4825,12 +5004,15 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src;
const char *col, *ocl, *rnk, *pic, *fcl, *skc;
char *tab, *dsn, *shm, *dpath;
-#if defined(WIN32)
+#if defined(__WIN__)
char *nsp= NULL, *cls= NULL;
-#endif // WIN32
- int port= 0, hdr= 0, mxr __attribute__((unused))= 0, mxe= 0, rc= 0;
- int cop __attribute__((unused)) = 0;
+#endif // __WIN__
+ int port= 0, hdr= 0, mxr= 0, mxe= 0, rc= 0;
+ int cop __attribute__((unused))= 0, lrecl= 0;
#if defined(ODBC_SUPPORT)
+ POPARM sop = NULL;
+ char *ucnc = NULL;
+ bool cnc= false;
int cto= -1, qto= -1;
#endif // ODBC_SUPPORT
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
@@ -4872,10 +5054,12 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
hdr= (int)topt->header;
tbl= topt->tablist;
col= topt->colist;
+ lrecl= (int)topt->lrecl;
if (topt->oplist) {
host= GetListOption(g, "host", topt->oplist, "localhost");
- user= GetListOption(g, "user", topt->oplist, "root");
+ user= GetListOption(g, "user", topt->oplist,
+ (ttp == TAB_ODBC ? NULL : "root"));
// Default value db can come from the DBNAME=xxx option.
db= GetListOption(g, "database", topt->oplist, db);
col= GetListOption(g, "colist", topt->oplist, col);
@@ -4885,15 +5069,18 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
skc= GetListOption(g, "skipcol", topt->oplist, NULL);
rnk= GetListOption(g, "rankcol", topt->oplist, NULL);
pwd= GetListOption(g, "password", topt->oplist);
-#if defined(WIN32)
+#if defined(__WIN__)
nsp= GetListOption(g, "namespace", topt->oplist);
cls= GetListOption(g, "class", topt->oplist);
-#endif // WIN32
+#endif // __WIN__
port= atoi(GetListOption(g, "port", topt->oplist, "0"));
#if defined(ODBC_SUPPORT)
mxr= atoi(GetListOption(g,"maxres", topt->oplist, "0"));
cto= atoi(GetListOption(g,"ConnectTimeout", topt->oplist, "-1"));
qto= atoi(GetListOption(g,"QueryTimeout", topt->oplist, "-1"));
+
+ if ((ucnc= GetListOption(g, "UseDSN", topt->oplist)))
+ cnc= (!*ucnc || *ucnc == 'y' || *ucnc == 'Y' || atoi(ucnc) != 0);
#endif
mxe= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
#if defined(PROMPT_OK)
@@ -4901,7 +5088,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
#endif // PROMPT_OK
} else {
host= "localhost";
- user= "root";
+ user= (ttp == TAB_ODBC ? NULL : "root");
} // endif option_list
if (!(shm= (char*)db))
@@ -4942,8 +5129,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
goto err;
} // endif tbl
- tab= (char*)PlugSubAlloc(g, NULL, strlen(tbl) + 1);
- strcpy(tab, tbl);
+ tab= PlugDup(g, tbl);
if ((p= strchr(tab, ',')))
*p= 0;
@@ -4978,10 +5164,18 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endif dsn
#endif // PROMPT_OK
- } else if (!dsn)
+ } else if (!dsn) {
sprintf(g->Message, "Missing %s connection string", topt->type);
- else
+ } else {
+ // Store ODBC additional parameters
+ sop= (POPARM)PlugSubAlloc(g, NULL, sizeof(ODBCPARM));
+ sop->User= (char*)user;
+ sop->Pwd= (char*)pwd;
+ sop->Cto= cto;
+ sop->Qto= qto;
+ sop->UseCnc= cnc;
ok= true;
+ } // endif's
supfnc |= (FNC_TABLE | FNC_DSN | FNC_DRIVER);
break;
@@ -4996,7 +5190,6 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ok= true;
break;
-#if defined(MYSQL_SUPPORT)
case TAB_MYSQL:
ok= true;
@@ -5036,14 +5229,15 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ok= false;
break;
-#endif // MYSQL_SUPPORT
-#if defined(WIN32)
+#if defined(__WIN__)
case TAB_WMI:
ok= true;
break;
-#endif // WIN32
+#endif // __WIN__
+#if defined(PIVOT_SUPPORT)
case TAB_PIVOT:
supfnc= FNC_NO;
+#endif // PIVOT_SUPPORT
case TAB_PRX:
case TAB_TBL:
case TAB_XCL:
@@ -5062,6 +5256,16 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
strcpy(g->Message, "Missing OEM module or subtype");
break;
+#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT)
+ case TAB_XML:
+#endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT
+ case TAB_JSON:
+ if (!fn)
+ sprintf(g->Message, "Missing %s file name", topt->type);
+ else
+ ok= true;
+
+ break;
case TAB_VIR:
ok= true;
break;
@@ -5083,7 +5287,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endif src
if (ok) {
- char *cnm, *rem, *dft, *xtra, *key;
+ char *cnm, *rem, *dft, *xtra, *key, *fmt;
int i, len, prec, dec, typ, flg;
// if (cat)
@@ -5112,15 +5316,15 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
case FNC_NO:
case FNC_COL:
if (src) {
- qrp= ODBCSrcCols(g, dsn, (char*)src, cto, qto);
+ qrp= ODBCSrcCols(g, dsn, (char*)src, sop);
src= NULL; // for next tests
} else
- qrp= ODBCColumns(g, dsn, shm, tab, NULL,
- mxr, cto, qto, fnc == FNC_COL);
+ qrp= ODBCColumns(g, dsn, shm, tab, NULL,
+ mxr, fnc == FNC_COL, sop);
break;
case FNC_TABLE:
- qrp= ODBCTables(g, dsn, shm, tab, mxr, cto, qto, true);
+ qrp= ODBCTables(g, dsn, shm, tab, mxr, true, sop);
break;
case FNC_DSN:
qrp= ODBCDataSources(g, mxr, true);
@@ -5135,20 +5339,18 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
break;
#endif // ODBC_SUPPORT
-#if defined(MYSQL_SUPPORT)
case TAB_MYSQL:
qrp= MyColumns(g, thd, host, db, user, pwd, tab,
NULL, port, fnc == FNC_COL);
break;
-#endif // MYSQL_SUPPORT
case TAB_CSV:
qrp= CSVColumns(g, dpath, fn, spc, qch, hdr, mxe, fnc == FNC_COL);
break;
-#if defined(WIN32)
+#if defined(__WIN__)
case TAB_WMI:
qrp= WMIColumns(g, nsp, cls, fnc == FNC_COL);
break;
-#endif // WIN32
+#endif // __WIN__
case TAB_PRX:
case TAB_TBL:
case TAB_XCL:
@@ -5166,12 +5368,22 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endif OcrColumns
break;
+#if defined(PIVOT_SUPPORT)
case TAB_PIVOT:
qrp= PivotColumns(g, tab, src, pic, fcl, skc, host, db, user, pwd, port);
break;
+#endif // PIVOT_SUPPORT
case TAB_VIR:
- qrp= VirColumns(g, tab, (char*)db, fnc == FNC_COL);
+ qrp= VirColumns(g, fnc == FNC_COL);
+ break;
+ case TAB_JSON:
+ qrp= JSONColumns(g, (char*)db, topt, fnc == FNC_COL);
+ break;
+#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT)
+ case TAB_XML:
+ qrp= XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL);
break;
+#endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT
case TAB_OEM:
qrp= OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL);
break;
@@ -5188,7 +5400,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if (fnc != FNC_NO || src || ttp == TAB_PIVOT) {
// Catalog like table
for (crp= qrp->Colresp; !rc && crp; crp= crp->Next) {
- cnm= encode(g, crp->Name);
+ cnm= (ttp == TAB_PIVOT) ? crp->Name : encode(g, crp->Name);
typ= crp->Type;
len= crp->Length;
dec= crp->Prec;
@@ -5204,12 +5416,14 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
NOT_NULL_FLAG, "", flg, dbf, v);
#else // !NEW_WAY
if (add_field(&sql, cnm, typ, len, dec, NULL, NOT_NULL_FLAG,
- NULL, NULL, NULL, flg, dbf, v))
+ NULL, NULL, NULL, NULL, flg, dbf, v))
rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY
} // endfor crp
- } else {
+ } else {
+ char *schem= NULL;
+
// Not a catalog table
if (!qrp->Nblin) {
if (tab)
@@ -5225,7 +5439,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
typ= len= prec= dec= 0;
tm= NOT_NULL_FLAG;
cnm= (char*)"noname";
- dft= xtra= key= NULL;
+ dft= xtra= key= fmt= NULL;
v= ' ';
#if defined(NEW_WAY)
rem= "";
@@ -5237,9 +5451,10 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
for (crp= qrp->Colresp; crp; crp= crp->Next)
switch (crp->Fld) {
case FLD_NAME:
- if (ttp == TAB_CSV && topt->data_charset &&
+ if (ttp == TAB_PRX ||
+ (ttp == TAB_CSV && topt->data_charset &&
(!stricmp(topt->data_charset, "UTF8") ||
- !stricmp(topt->data_charset, "UTF-8")))
+ !stricmp(topt->data_charset, "UTF-8"))))
cnm= crp->Kdata->GetCharValue(i);
else
cnm= encode(g, crp->Kdata->GetCharValue(i));
@@ -5264,6 +5479,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
tm= 0; // Nullable
break;
+ case FLD_FORMAT:
+ fmt= (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL;
+ break;
case FLD_REM:
rem= crp->Kdata->GetCharValue(i);
break;
@@ -5289,27 +5507,59 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
key= crp->Kdata->GetCharValue(i);
break;
+ case FLD_SCHEM:
+#if defined(ODBC_SUPPORT)
+ if (ttp == TAB_ODBC && crp->Kdata) {
+ if (schem && stricmp(schem, crp->Kdata->GetCharValue(i))) {
+ sprintf(g->Message,
+ "Several %s tables found, specify DBNAME", tab);
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ goto err;
+ } else if (!schem)
+ schem= crp->Kdata->GetCharValue(i);
+
+ } // endif ttp
+#endif // ODBC_SUPPORT
default:
break; // Ignore
} // endswitch Fld
#if defined(ODBC_SUPPORT)
if (ttp == TAB_ODBC) {
- int plgtyp;
+ int plgtyp;
+ bool w= false; // Wide character type
// typ must be PLG type, not SQL type
- if (!(plgtyp= TranslateSQLType(typ, dec, prec, v))) {
- sprintf(g->Message, "Unsupported SQL type %d", typ);
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
- goto err;
+ if (!(plgtyp= TranslateSQLType(typ, dec, prec, v, w))) {
+ if (GetTypeConv() == TPC_SKIP) {
+ // Skip this column
+ sprintf(g->Message, "Column %s skipped (unsupported type %d)",
+ cnm, typ);
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
+ continue;
+ } else {
+ sprintf(g->Message, "Unsupported SQL type %d", typ);
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ goto err;
+ } // endif type_conv
+
} else
typ= plgtyp;
switch (typ) {
+ case TYPE_STRING:
+ if (w) {
+ sprintf(g->Message, "Column %s is wide characters", cnm);
+ push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, 0, g->Message);
+ } // endif w
+
+ break;
case TYPE_DOUBLE:
// Some data sources do not count dec in length (prec)
prec += (dec + 2); // To be safe
+ break;
case TYPE_DECIM:
+ prec= len;
break;
default:
dec= 0;
@@ -5330,7 +5580,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
tm, rem, 0, dbf, v);
#else // !NEW_WAY
if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra,
- 0, dbf, v))
+ fmt, 0, dbf, v))
rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY
} // endfor i
@@ -5562,11 +5812,11 @@ int ha_connect::create(const char *name, TABLE *table_arg,
// on Windows and libxml2 otherwise
switch (*xsup) {
case '*':
-#if defined(WIN32)
+#if defined(__WIN__)
dom= true;
-#else // !WIN32
+#else // !__WIN__
dom= false;
-#endif // !WIN32
+#endif // !__WIN__
break;
case 'M':
case 'D':
@@ -5599,6 +5849,18 @@ int ha_connect::create(const char *name, TABLE *table_arg,
} // endif type
+ if (type == TAB_JSON) {
+ int pretty= atoi(GetListOption(g, "Pretty", options->oplist, "2"));
+
+ if (!options->lrecl && pretty != 2) {
+ sprintf(g->Message, "LRECL must be specified for pretty=%d", pretty);
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ rc= HA_ERR_INTERNAL_ERROR;
+ DBUG_RETURN(rc);
+ } // endif lrecl
+
+ } // endif type
+
// Check column types
for (field= table_arg->field; *field; field++) {
fp= *field;
@@ -5901,11 +6163,11 @@ bool ha_connect::FileExists(const char *fn, bool bf)
NULL, NULL, 0, 0))
return true;
-#if defined(WIN32)
+#if defined(__WIN__)
s= "\\";
-#else // !WIN32
+#else // !__WIN__
s= "/";
-#endif // !WIN32
+#endif // !__WIN__
if (IsPartitioned()) {
sprintf(tfn, fn, GetPartName());
@@ -6247,8 +6509,7 @@ fin:
@note: This function is no more called by check_if_supported_inplace_alter
*/
-bool ha_connect::check_if_incompatible_data(HA_CREATE_INFO *info,
- uint table_changes)
+bool ha_connect::check_if_incompatible_data(HA_CREATE_INFO *, uint)
{
DBUG_ENTER("ha_connect::check_if_incompatible_data");
// TO DO: really implement and check it.
@@ -6341,58 +6602,6 @@ struct st_mysql_storage_engine connect_storage_engine=
/***********************************************************************/
/* CONNECT global variables definitions. */
/***********************************************************************/
-// Size used when converting TEXT columns to VARCHAR
-#if defined(_DEBUG)
-static MYSQL_SYSVAR_INT(conv_size, zconv,
- PLUGIN_VAR_RQCMDARG, // opt
- "Size used when converting TEXT columns.",
- NULL, NULL, SZCONV, 0, 65500, 1);
-#else
-static MYSQL_SYSVAR_INT(conv_size, zconv,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, // opt
- "Size used when converting TEXT columns.",
- NULL, NULL, SZCONV, 0, 65500, 1);
-#endif
-
-/**
- Type conversion:
- no: Unsupported types -> TYPE_ERROR
- yes: TEXT -> VARCHAR
- skip: skip unsupported type columns in Discovery
-*/
-const char *xconv_names[]=
-{
- "NO", "YES", "SKIP", NullS
-};
-
-TYPELIB xconv_typelib=
-{
- array_elements(xconv_names) - 1, "xconv_typelib",
- xconv_names, NULL
-};
-
-#if defined(_DEBUG)
-static MYSQL_SYSVAR_ENUM(
- type_conv, // name
- xconv, // varname
- PLUGIN_VAR_RQCMDARG, // opt
- "Unsupported types conversion.", // comment
- NULL, // check
- NULL, // update function
- 0, // def (no)
- &xconv_typelib); // typelib
-#else
-static MYSQL_SYSVAR_ENUM(
- type_conv, // name
- xconv, // varname
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
- "Unsupported types conversion.", // comment
- NULL, // check
- NULL, // update function
- 0, // def (no)
- &xconv_typelib); // typelib
-#endif
-
#if defined(XMAP)
// Using file mapping for indexes if true
static MYSQL_SYSVAR_BOOL(indx_map, xmap, PLUGIN_VAR_RQCMDARG,
@@ -6425,6 +6634,7 @@ static struct st_mysql_sys_var* connect_system_variables[]= {
#if defined(XMSG)
MYSQL_SYSVAR(errmsg_dir_path),
#endif // XMSG
+ MYSQL_SYSVAR(json_grp_size),
NULL
};
@@ -6441,7 +6651,7 @@ maria_declare_plugin(connect)
0x0103, /* version number (1.03) */
NULL, /* status variables */
connect_system_variables, /* system variables */
- "1.03.0005", /* string version */
+ "1.03.0007", /* string version */
MariaDB_PLUGIN_MATURITY_BETA /* maturity */
}
maria_declare_plugin_end;
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index 922a69a3991..611f9ba0b54 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2014
+/* Copyright (C) Olivier Bertrand 2004 - 2015
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
@@ -26,6 +26,11 @@
#pragma interface /* gcc class implementation */
#endif
+/****************************************************************************/
+/* mycat.h contains the TOS, PTOS, ha_table_option_struct declarations. */
+/****************************************************************************/
+#include "mycat.h"
+
static char *strz(PGLOBAL g, LEX_STRING &ls);
/****************************************************************************/
@@ -56,11 +61,7 @@ public:
oldopn= newopn= NULL;
oldpix= newpix= NULL;}
- inline char *SetName(PGLOBAL g, char *name) {
- char *nm= NULL;
- if (name) {nm= (char*)PlugSubAlloc(g, NULL, strlen(name) + 1);
- strcpy(nm, name);}
- return nm;}
+ inline char *SetName(PGLOBAL g, char *name) {return PlugDup(g, name);}
bool oldsep; // Sepindex before create/alter
bool newsep; // Sepindex after create/alter
@@ -72,7 +73,6 @@ public:
typedef class XCHK *PCHK;
typedef class user_connect *PCONNECT;
-typedef struct ha_table_option_struct TOS, *PTOS;
typedef struct ha_field_option_struct FOS, *PFOS;
typedef struct ha_index_option_struct XOS, *PXOS;
@@ -84,6 +84,9 @@ extern handlerton *connect_hton;
These can be specified in the CREATE TABLE:
CREATE TABLE ( ... ) {...here...}
*/
+#if 0 // moved to mycat.h
+typedef struct ha_table_option_struct TOS, *PTOS;
+
struct ha_table_option_struct {
const char *type;
const char *filename;
@@ -115,6 +118,7 @@ struct ha_table_option_struct {
bool readonly;
bool sepindex;
};
+#endif // 0
/**
structure for CREATE TABLE options (field options)
@@ -239,7 +243,7 @@ public:
int CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf);
int ReadIndexed(uchar *buf, OPVAL op, const uchar* key= NULL,
uint key_len= 0);
- bool MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
+ bool MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
const void *key, int klen);
inline char *Strz(LEX_STRING &ls);
diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp
index 983f45d9cee..3d03bea5d00 100644
--- a/storage/connect/json.cpp
+++ b/storage/connect/json.cpp
@@ -1,1055 +1,1162 @@
-/*************** json CPP Declares Source Code File (.H) ***************/
-/* Name: json.cpp Version 1.0 */
-/* */
-/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
-/* */
-/* This file contains the JSON classes functions. */
-/***********************************************************************/
-
-/***********************************************************************/
-/* Include relevant sections of the MariaDB header file. */
-/***********************************************************************/
-#include <my_global.h>
-
-/***********************************************************************/
-/* Include application header files: */
-/* global.h is header containing all global declarations. */
-/* plgdbsem.h is header containing the DB application declarations. */
-/* xjson.h is header containing the JSON classes declarations. */
-/***********************************************************************/
-#include "global.h"
-#include "plgdbsem.h"
-#include "json.h"
-
-#define ARGS MY_MIN(24,len-i),s+MY_MAX(i-3,0)
-
-#if defined(WIN32)
-#define EL "\r\n"
-#else
-#define EL "\n"
-#endif
-
-/***********************************************************************/
-/* Parse a json string. */
-/***********************************************************************/
-PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
-{
- int i;
- bool b = false;
- PJSON jsp = NULL;
- STRG src;
-
- if (!s || !len) {
- strcpy(g->Message, "Void JSON object");
- return NULL;
- } else if (comma)
- *comma = false;
-
- src.str = s;
- src.len = len;
-
- for (i = 0; i < len; i++)
- switch (s[i]) {
- case '[':
- if (jsp) {
- strcpy(g->Message, "More than one item in file");
- return NULL;
- } else if (!(jsp = ParseArray(g, ++i, src)))
- return NULL;
-
- break;
- case '{':
- if (jsp) {
- strcpy(g->Message, "More than one item in file");
- return NULL;
- } else if (!(jsp = ParseObject(g, ++i, src)))
- return NULL;
- break;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- break;
- case ',':
- if (jsp && pretty == 1) {
- if (comma)
- *comma = true;
-
- break;
- } // endif pretty
-
- sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
- return NULL;
- case '(':
- b = true;
- break;
- case ')':
- if (b) {
- b = false;
- break;
- } // endif b
-
- default:
- sprintf(g->Message, "Bad '%c' character near %.*s",
- s[i], ARGS);
- return NULL;
- }; // endswitch s[i]
-
- if (!jsp)
- sprintf(g->Message, "Invalid Json string '%.*s'", 50, s);
-
- return jsp;
-} // end of ParseJson
-
-/***********************************************************************/
-/* Parse a JSON Array. */
-/***********************************************************************/
-PJAR ParseArray(PGLOBAL g, int& i, STRG& src)
-{
- char *s = src.str;
- int len = src.len;
- int level = 0;
- PJAR jarp = new(g) JARRAY;
- PJVAL jvp = NULL;
-
- for (; i < len; i++)
- switch (s[i]) {
- case ',':
- if (level < 2) {
- sprintf(g->Message, "Unexpected ',' near %.*s",ARGS);
- return NULL;
- } else
- level = 1;
-
- break;
- case ']':
- if (level == 1) {
- sprintf(g->Message, "Unexpected ',]' near %.*s", ARGS);
- return NULL;
- } // endif level
-
- jarp->InitArray(g);
- return jarp;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- break;
- default:
- if (level == 2) {
- sprintf(g->Message, "Unexpected value near %.*s", ARGS);
- return NULL;
- } else if ((jvp = ParseValue(g, i, src))) {
- jarp->AddValue(g, jvp);
- level = 2;
- } else
- return NULL;
-
- level = 2;
- break;
- }; // endswitch s[i]
-
- strcpy(g->Message, "Unexpected EOF in array");
- return NULL;
-} // end of ParseArray
-
-/***********************************************************************/
-/* Parse a JSON Object. */
-/***********************************************************************/
-PJOB ParseObject(PGLOBAL g, int& i, STRG& src)
-{
- PSZ key;
- char *s = src.str;
- int len = src.len;
- int level = 0;
- PJOB jobp = new(g) JOBJECT;
- PJPR jpp = NULL;
-
- for (; i < len; i++)
- switch (s[i]) {
- case '"':
- if (level < 2) {
- if ((key = ParseString(g, ++i, src))) {
- jpp = jobp->AddPair(g, key);
- level = 1;
- } else
- return NULL;
-
- } else {
- sprintf(g->Message, "misplaced string near %.*s", ARGS);
- return NULL;
- } // endif level
-
- break;
- case ':':
- if (level == 1) {
- if (!(jpp->Val = ParseValue(g, ++i, src)))
- return NULL;
-
- level = 2;
- } else {
- sprintf(g->Message, "Unexpected ':' near %.*s", ARGS);
- return NULL;
- } // endif level
-
- break;
- case ',':
- if (level < 2) {
- sprintf(g->Message, "Unexpected ',' near %.*s", ARGS);
- return NULL;
- } else
- level = 1;
-
- break;
- case '}':
- if (level == 1) {
- sprintf(g->Message, "Unexpected '}' near %.*s", ARGS);
- return NULL;
- } // endif level
-
- return jobp;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- break;
- default:
- sprintf(g->Message, "Unexpected character '%c' near %.*s",
- s[i], ARGS);
- return NULL;
- }; // endswitch s[i]
-
- strcpy(g->Message, "Unexpected EOF in Object");
- return NULL;
-} // end of ParseObject
-
-/***********************************************************************/
-/* Parse a JSON Value. */
-/***********************************************************************/
-PJVAL ParseValue(PGLOBAL g, int& i, STRG& src)
-{
- char *strval, *s = src.str;
- int n, len = src.len;
- PJVAL jvp = new(g) JVALUE;
-
- for (; i < len; i++)
- switch (s[i]) {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- break;
- default:
- goto suite;
- } // endswitch
-
- suite:
- switch (s[i]) {
- case '[':
- if (!(jvp->Jsp = ParseArray(g, ++i, src)))
- return NULL;
-
- break;
- case '{':
- if (!(jvp->Jsp = ParseObject(g, ++i, src)))
- return NULL;
-
- break;
- case '"':
- if ((strval = ParseString(g, ++i, src)))
- jvp->Value = AllocateValue(g, strval, TYPE_STRING);
- else
- return NULL;
-
- break;
- case 't':
- if (!strncmp(s + i, "true", 4)) {
- n = 1;
- jvp->Value = AllocateValue(g, &n, TYPE_TINY);
- i += 3;
- } else
- goto err;
-
- break;
- case 'f':
- if (!strncmp(s + i, "false", 5)) {
- n = 0;
- jvp->Value = AllocateValue(g, &n, TYPE_TINY);
- i += 4;
- } else
- goto err;
-
- break;
- case 'n':
- if (!strncmp(s + i, "null", 4))
- i += 3;
- else
- goto err;
-
- break;
- case '-':
- default:
- if (s[i] == '-' || isdigit(s[i])) {
- if (!(jvp->Value = ParseNumeric(g, i, src)))
- goto err;
-
- } else
- goto err;
-
- }; // endswitch s[i]
-
- jvp->Size = 1;
- return jvp;
-
-err:
- sprintf(g->Message, "Unexpected character '%c' near %.*s",
- s[i], ARGS);
- return NULL;
-} // end of ParseValue
-
-/***********************************************************************/
-/* Unescape and parse a JSON string. */
-/***********************************************************************/
-char *ParseString(PGLOBAL g, int& i, STRG& src)
-{
- char *p, *s = src.str;
- int n = 0, len = src.len;
-
- // The size to allocate is not known yet
- p = (char*)PlugSubAlloc(g, NULL, 0);
-
- for (; i < len; i++)
- switch (s[i]) {
- case '"':
- p[n++] = 0;
- PlugSubAlloc(g, NULL, n);
- return p;
- case '\\':
- if (++i < len) {
- if (s[i] == 'u') {
- if (len - i > 5) {
-// if (charset == utf8) {
- char xs[5];
- uint hex;
-
- xs[0] = s[++i];
- xs[1] = s[++i];
- xs[2] = s[++i];
- xs[3] = s[++i];
- xs[4] = 0;
- hex = strtoul(xs, NULL, 16);
-
- if (hex < 0x80) {
- p[n] = (uchar)hex;
- } else if (hex < 0x800) {
- p[n++] = (uchar)(0xC0 | (hex >> 6));
- p[n] = (uchar)(0x80 | (hex & 0x3F));
- } else if (hex < 0x10000) {
- p[n++] = (uchar)(0xE0 | (hex >> 12));
- p[n++] = (uchar)(0x80 | ((hex >> 6) & 0x3f));
- p[n] = (uchar)(0x80 | (hex & 0x3f));
- } else
- p[n] = '?';
-
-#if 0
- } else {
- char xs[3];
- UINT hex;
-
- i += 2;
- xs[0] = s[++i];
- xs[1] = s[++i];
- xs[2] = 0;
- hex = strtoul(xs, NULL, 16);
- p[n] = (char)hex;
- } // endif charset
-#endif // 0
- } else
- goto err;
-
- } else switch(s[i]) {
- case 't': p[n] = '\t'; break;
- case 'n': p[n] = '\n'; break;
- case 'r': p[n] = '\r'; break;
- case 'b': p[n] = '\b'; break;
- case 'f': p[n] = '\f'; break;
- default: p[n] = s[i]; break;
- } // endswitch
-
- n++;
- } else
- goto err;
-
- break;
- default:
- p[n++] = s[i];
- break;
- }; // endswitch s[i]
-
- err:
- strcpy(g->Message, "Unexpected EOF in String");
- return NULL;
-} // end of ParseString
-
-/***********************************************************************/
-/* Parse a JSON numeric value. */
-/***********************************************************************/
-PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src)
-{
- char *s = src.str, buf[50];
- int n = 0, len = src.len;
- short nd = 0;
- bool has_dot = false;
- bool has_e = false;
- bool found_digit = false;
- PVAL valp = NULL;
-
- for (; i < len; i++) {
- switch (s[i]) {
- case '.':
- if (!found_digit || has_dot || has_e)
- goto err;
-
- has_dot = true;
- break;
- case 'e':
- case 'E':
- if (!found_digit || has_e)
- goto err;
-
- has_e = true;
- found_digit = false;
- break;
- case '+':
- if (!has_e)
- goto err;
-
- // passthru
- case '-':
- if (found_digit)
- goto err;
-
- break;
- default:
- if (isdigit(s[i])) {
- if (has_dot && !has_e)
- nd++; // Number of decimals
-
- found_digit = true;
- } else
- goto fin;
-
- }; // endswitch s[i]
-
- buf[n++] = s[i];
- } // endfor i
-
- fin:
- if (found_digit) {
- buf[n] = 0;
-
- if (has_dot || has_e) {
- double dv = strtod(buf, NULL);
-
- valp = AllocateValue(g, &dv, TYPE_DOUBLE, nd);
- } else {
- int iv = strtol(buf, NULL, 10);
-
- valp = AllocateValue(g, &iv, TYPE_INT);
- } // endif has
-
- i--; // Unstack following character
- return valp;
- } else {
- strcpy(g->Message, "No digit found");
- return NULL;
- } // endif found_digit
-
- err:
- strcpy(g->Message, "Unexpected EOF in number");
- return NULL;
-} // end of ParseNumeric
-
-/***********************************************************************/
-/* Serialize a JSON tree: */
-/***********************************************************************/
-PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty)
-{
- bool b = false, err = true;
- JOUT *jp;
-
- g->Message[0] = 0;
-
- if (!jsp) {
- strcpy(g->Message, "Null json tree");
- return NULL;
- } else if (!fs) {
- // Serialize to a string
- jp = new(g) JOUTSTR(g);
- b = pretty == 1;
- } else if (pretty == 2) {
- // Serialize to a pretty file
- jp = new(g) JOUTPRT(g, fs);
- } else {
- // Serialize to a flat file
- jp = new(g) JOUTFILE(g, fs);
- b = pretty == 1;
- } // endif's
-
- switch (jsp->GetType()) {
- case TYPE_JAR:
- err = SerializeArray(jp, (PJAR)jsp, b);
- break;
- case TYPE_JOB:
- err = (b && jp->WriteChr('\t'));
- err |= SerializeObject(jp, (PJOB)jsp);
- break;
- default:
- strcpy(g->Message, "json tree is not an Array or an Object");
- } // endswitch Type
-
- if (fs) {
- fputc('\n', fs);
- fclose(fs);
- return (err) ? g->Message : NULL;
- } else if (!err) {
- PSZ str = ((JOUTSTR*)jp)->Strp;
-
- jp->WriteChr('\0');
- PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
- return str;
- } else {
- if (!g->Message[0])
- strcpy(g->Message, "Error in Serialize");
-
- return NULL;
- } // endif's
-
-} // end of Serialize
-
-/***********************************************************************/
-/* Serialize a JSON Array. */
-/***********************************************************************/
-bool SerializeArray(JOUT *js, PJAR jarp, bool b)
-{
- bool first = true;
-
-
- if (js->WriteChr('['))
- return true;
- else if (b && (js->WriteStr(EL) || js->WriteChr('\t')))
- return true;
-
- for (int i = 0; i < jarp->size(); i++) {
- if (first)
- first = false;
- else if (js->WriteChr(','))
- return true;
- else if (b && (js->WriteStr(EL) || js->WriteChr('\t')))
- return true;
-
- if (SerializeValue(js, jarp->GetValue(i)))
- return true;
-
- } // endfor i
-
- if (b && js->WriteStr(EL))
- return true;
-
- return js->WriteChr(']');
-} // end of SerializeArray
-
-/***********************************************************************/
-/* Serialize a JSON Object. */
-/***********************************************************************/
-bool SerializeObject(JOUT *js, PJOB jobp)
-{
- bool first = true;
-
- if (js->WriteChr('{'))
- return true;
-
- for (PJPR pair = jobp->First; pair; pair = pair->Next) {
- if (first)
- first = false;
- else if (js->WriteChr(','))
- return true;
-
- if (js->WriteChr('\"') ||
- js->WriteStr(pair->Key) ||
- js->WriteChr('\"') ||
- js->WriteChr(':') ||
- SerializeValue(js, pair->Val))
- return true;
-
- } // endfor i
-
- return js->WriteChr('}');
-} // end of SerializeObject
-
-/***********************************************************************/
-/* Serialize a JSON Value. */
-/***********************************************************************/
-bool SerializeValue(JOUT *js, PJVAL jvp)
-{
- PJAR jap;
- PJOB jop;
- PVAL valp;
-
- if ((jap = jvp->GetArray()))
- return SerializeArray(js, jap, false);
- else if ((jop = jvp->GetObject()))
- return SerializeObject(js, jop);
- else if (!(valp = jvp->Value) || valp->IsNull())
- return js->WriteStr("null");
- else switch (valp->GetType()) {
- case TYPE_TINY:
- return js->WriteStr(valp->GetTinyValue() ? "true" : "false");
- case TYPE_STRING:
- return js->Escape(valp->GetCharValue());
- default:
- if (valp->IsTypeNum()) {
- char buf[32];
-
- return js->WriteStr(valp->GetCharString(buf));
- } // endif valp
-
- } // endswitch Type
-
-strcpy(js->g->Message, "Unrecognized value");
-return true;
-} // end of SerializeValue
-
-/* -------------------------- Class JOUTSTR -------------------------- */
-
-/***********************************************************************/
-/* JOUTSTR constructor. */
-/***********************************************************************/
-JOUTSTR::JOUTSTR(PGLOBAL g) : JOUT(g)
-{
- PPOOLHEADER pph = (PPOOLHEADER)g->Sarea;
-
- N = 0;
- Max = pph->FreeBlk;
- Max = (Max > 512) ? Max - 512 : Max;
- Strp = (char*)PlugSubAlloc(g, NULL, 0); // Size not know yet
-} // end of JOUTSTR constructor
-
-/***********************************************************************/
-/* Concatenate a string to the Serialize string. */
-/***********************************************************************/
-bool JOUTSTR::WriteStr(const char *s)
-{
- if (s) {
- size_t len = strlen(s);
-
- if (N + len > Max)
- return true;
-
- memcpy(Strp + N, s, len);
- N += len;
- return false;
- } else
- return true;
-
-} // end of WriteStr
-
-/***********************************************************************/
-/* Concatenate a character to the Serialize string. */
-/***********************************************************************/
-bool JOUTSTR::WriteChr(const char c)
-{
- if (N + 1 > Max)
- return true;
-
- Strp[N++] = c;
- return false;
-} // end of WriteChr
-
-/***********************************************************************/
-/* Escape and Concatenate a string to the Serialize string. */
-/***********************************************************************/
-bool JOUTSTR::Escape(const char *s)
-{
- WriteChr('"');
-
- for (unsigned int i = 0; i < strlen(s); i++)
- switch (s[i]) {
- case '\t':
- case '\n':
- case '\r':
- case '\b':
- case '\f':
- case '"': WriteChr('\\');
- // passthru
- default:
- WriteChr(s[i]);
- break;
- } // endswitch s[i]
-
- WriteChr('"');
- return false;
-} // end of Escape
-
-/* ------------------------- Class JOUTFILE -------------------------- */
-
-/***********************************************************************/
-/* Write a string to the Serialize file. */
-/***********************************************************************/
-bool JOUTFILE::WriteStr(const char *s)
-{
- // This is temporary
- fputs(s, Stream);
- return false;
-} // end of WriteStr
-
-/***********************************************************************/
-/* Write a character to the Serialize file. */
-/***********************************************************************/
-bool JOUTFILE::WriteChr(const char c)
-{
- // This is temporary
- fputc(c, Stream);
- return false;
-} // end of WriteChr
-
-/***********************************************************************/
-/* Escape and Concatenate a string to the Serialize string. */
-/***********************************************************************/
-bool JOUTFILE::Escape(const char *s)
-{
- // This is temporary
- fputc('"', Stream);
-
- for (unsigned int i = 0; i < strlen(s); i++)
- switch (s[i]) {
- case '\t': fputs("\\t", Stream); break;
- case '\n': fputs("\\n", Stream); break;
- case '\r': fputs("\\r", Stream); break;
- case '\b': fputs("\\b", Stream); break;
- case '\f': fputs("\\f", Stream); break;
- case '"': fputs("\\\"", Stream); break;
- default:
- fputc(s[i], Stream);
- break;
- } // endswitch s[i]
-
- fputc('"', Stream);
- return false;
-} // end of Escape
-
-/* ------------------------- Class JOUTPRT --------------------------- */
-
-/***********************************************************************/
-/* Write a string to the Serialize pretty file. */
-/***********************************************************************/
-bool JOUTPRT::WriteStr(const char *s)
-{
- // This is temporary
- if (B) {
- fputs(EL, Stream);
- M--;
-
- for (int i = 0; i < M; i++)
- fputc('\t', Stream);
-
- B = false;
- } // endif B
-
- fputs(s, Stream);
- return false;
-} // end of WriteStr
-
-/***********************************************************************/
-/* Write a character to the Serialize pretty file. */
-/***********************************************************************/
-bool JOUTPRT::WriteChr(const char c)
-{
- switch (c) {
- case ':':
- fputs(": ", Stream);
- break;
- case '{':
- case '[':
-#if 0
- if (M)
- fputs(EL, Stream);
-
- for (int i = 0; i < M; i++)
- fputc('\t', Stream);
-#endif // 0
-
- fputc(c, Stream);
- fputs(EL, Stream);
- M++;
-
- for (int i = 0; i < M; i++)
- fputc('\t', Stream);
-
- break;
- case '}':
- case ']':
- M--;
- fputs(EL, Stream);
-
- for (int i = 0; i < M; i++)
- fputc('\t', Stream);
-
- fputc(c, Stream);
- B = true;
- break;
- case ',':
- fputc(c, Stream);
- fputs(EL, Stream);
-
- for (int i = 0; i < M; i++)
- fputc('\t', Stream);
-
- B = false;
- break;
- default:
- fputc(c, Stream);
- } // endswitch c
-
-return false;
-} // end of WriteChr
-
-/* -------------------------- Class JOBJECT -------------------------- */
-
-/***********************************************************************/
-/* Add a new pair to an Object. */
-/***********************************************************************/
-PJPR JOBJECT::AddPair(PGLOBAL g, PSZ key)
-{
- PJPR jpp = new(g) JPAIR(key);
-
- if (Last)
- Last->Next = jpp;
- else
- First = jpp;
-
- Last = jpp;
- Size++;
- return jpp;
-} // end of AddPair
-
-/***********************************************************************/
-/* Get the value corresponding to the given key. */
-/***********************************************************************/
-PJVAL JOBJECT::GetValue(const char* key)
-{
- for (PJPR jp = First; jp; jp = jp->Next)
- if (!strcmp(jp->Key, key))
- return jp->Val;
-
- return NULL;
-} // end of GetValue;
-
-/***********************************************************************/
-/* Return the text corresponding to all keys (XML like). */
-/***********************************************************************/
-PSZ JOBJECT::GetText(PGLOBAL g)
-{
- char *p, *text = (char*)PlugSubAlloc(g, NULL, 0);
- bool b = true;
-
- if (!First)
- return NULL;
- else for (PJPR jp = First; jp; jp = jp->Next) {
- if (!(p = jp->Val->GetString()))
- p = "???";
-
- if (b) {
- strcpy(text, p);
- b = false;
- } else
- strcat(strcat(text, " "), p);
-
- } // endfor jp
-
- PlugSubAlloc(g, NULL, strlen(text) + 1);
- return text;
-} // end of GetValue;
-
-/***********************************************************************/
-/* Set or add a value corresponding to the given key. */
-/***********************************************************************/
-void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key)
-{
- PJPR jp;
-
- for (jp = First; jp; jp = jp->Next)
- if (!strcmp(jp->Key, key)) {
- jp->Val = jvp;
- break;
- } // endif key
-
- if (!jp) {
- jp = AddPair(g, key);
- jp->Val = jvp;
- } // endif jp
-
-} // end of SetValue
-
-/* -------------------------- Class JARRAY --------------------------- */
-
-/***********************************************************************/
-/* Make the array of values from the values list. */
-/***********************************************************************/
-void JARRAY::InitArray(PGLOBAL g)
-{
- int i;
- PJVAL jvp;
-
- for (Size = 0, jvp = First; jvp; jvp = jvp->Next)
- if (!jvp->Del)
- Size++;
-
- if (!Size) {
- return;
- } else if (Size > Alloc) {
- // No need to realloc after deleting values
- Mvals = (PJVAL*)PlugSubAlloc(g, NULL, Size * sizeof(PJVAL));
- Alloc = Size;
- } // endif Size
-
- for (i = 0, jvp = First; jvp; jvp = jvp->Next)
- if (!jvp->Del)
- Mvals[i++] = jvp;
-
-} // end of InitArray
-
-/***********************************************************************/
-/* Get the Nth value of an Array. */
-/***********************************************************************/
-PJVAL JARRAY::GetValue(int i)
-{
- if (Mvals && i >= 0 && i < Size)
- return Mvals[i];
- else
- return NULL;
-} // end of GetValue
-
-/***********************************************************************/
-/* Add a Value to the Arrays Value list. */
-/***********************************************************************/
-PJVAL JARRAY::AddValue(PGLOBAL g, PJVAL jvp)
-{
- if (!jvp)
- jvp = new(g) JVALUE;
-
- if (Last)
- Last->Next = jvp;
- else
- First = jvp;
-
- Last = jvp;
- return jvp;
-} // end of AddValue
-
-/***********************************************************************/
-/* Add a Value to the Arrays Value list. */
-/***********************************************************************/
-bool JARRAY::SetValue(PGLOBAL g, PJVAL jvp, int n)
-{
- int i = 0;
- PJVAL jp, *jpp = &First;
-
- for (i = 0, jp = First; i < n; i++, jp = *(jpp = &jp->Next))
- if (!jp)
- *jpp = jp = new(g) JVALUE;
-
- *jpp = jvp;
- jvp->Next = (jp ? jp->Next : NULL);
- return false;
-} // end of SetValue
-
-/***********************************************************************/
-/* Delete a Value from the Arrays Value list. */
-/***********************************************************************/
-bool JARRAY::DeleteValue(int n)
-{
- PJVAL jvp = GetValue(n);
-
- if (jvp) {
- jvp->Del = true;
- return false;
- } else
- return true;
-
-} // end of DeleteValue
-
-/* -------------------------- Class JVALUE- -------------------------- */
-
-/***********************************************************************/
-/* Constructor for a Value with a given string or numeric value. */
-/***********************************************************************/
-JVALUE::JVALUE(PGLOBAL g, PVAL valp) : JSON()
-{
- Jsp = NULL;
- Value = AllocateValue(g, valp);
- Next = NULL;
- Del = false;
-} // end of JVALUE constructor
-
-/***********************************************************************/
-/* Returns the type of the Value's value. */
-/***********************************************************************/
-JTYP JVALUE::GetValType(void)
-{
- if (Jsp)
- return Jsp->GetType();
- else if (Value)
- return (JTYP)Value->GetType();
- else
- return (JTYP)TYPE_VOID;
-
-} // end of GetValType
-
-/***********************************************************************/
-/* Return the Value's Object value. */
-/***********************************************************************/
-PJOB JVALUE::GetObject(void)
-{
- if (Jsp && Jsp->GetType() == TYPE_JOB)
- return (PJOB)Jsp;
-
- return NULL;
-} // end of GetObject
-
-/***********************************************************************/
-/* Return the Value's Array value. */
-/***********************************************************************/
-PJAR JVALUE::GetArray(void)
-{
- if (Jsp && Jsp->GetType() == TYPE_JAR)
- return (PJAR)Jsp;
-
- return NULL;
-} // end of GetArray
-
-/***********************************************************************/
-/* Return the Value's Integer value. */
-/***********************************************************************/
-int JVALUE::GetInteger(void)
-{
- return (Value) ? Value->GetIntValue() : 0;
-} // end of GetInteger
-
-/***********************************************************************/
-/* Return the Value's Double value. */
-/***********************************************************************/
-double JVALUE::GetFloat(void)
-{
- return (Value) ? Value->GetFloatValue() : 0.0;
-} // end of GetFloat
-
-/***********************************************************************/
-/* Return the Value's String value. */
-/***********************************************************************/
-PSZ JVALUE::GetString(void)
-{
- char buf[32];
- return (Value) ? Value->GetCharString(buf) : NULL;
-} // end of GetString
-
+/*************** json CPP Declares Source Code File (.H) ***************/
+/* Name: json.cpp Version 1.1 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
+/* */
+/* This file contains the JSON classes functions. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant sections of the MariaDB header file. */
+/***********************************************************************/
+#include <my_global.h>
+
+/***********************************************************************/
+/* Include application header files: */
+/* global.h is header containing all global declarations. */
+/* plgdbsem.h is header containing the DB application declarations. */
+/* xjson.h is header containing the JSON classes declarations. */
+/***********************************************************************/
+#include "global.h"
+#include "plgdbsem.h"
+#include "json.h"
+
+#define ARGS MY_MIN(24,len-i),s+MY_MAX(i-3,0)
+
+#if defined(__WIN__)
+#define EL "\r\n"
+#else
+#define EL "\n"
+#endif
+
+/***********************************************************************/
+/* Parse a json string. */
+/***********************************************************************/
+PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
+{
+ int i, rc;
+ bool b = false;
+ PJSON jsp = NULL;
+ STRG src;
+
+ if (!s || !len) {
+ strcpy(g->Message, "Void JSON object");
+ return NULL;
+ } else if (comma)
+ *comma = false;
+
+ src.str = s;
+ src.len = len;
+
+ // Save stack and allocation environment and prepare error return
+ if (g->jump_level == MAX_JUMP) {
+ strcpy(g->Message, MSG(TOO_MANY_JUMPS));
+ return NULL;
+ } // endif jump_level
+
+ if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
+ goto err;
+ } // endif rc
+
+ for (i = 0; i < len; i++)
+ switch (s[i]) {
+ case '[':
+ if (jsp) {
+ strcpy(g->Message, "More than one item in file");
+ goto err;
+ } else if (!(jsp = ParseArray(g, ++i, src)))
+ goto err;
+
+ break;
+ case '{':
+ if (jsp) {
+ strcpy(g->Message, "More than one item in file");
+ goto err;
+ } else if (!(jsp = ParseObject(g, ++i, src)))
+ goto err;
+
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ case ',':
+ if (jsp && pretty == 1) {
+ if (comma)
+ *comma = true;
+
+ break;
+ } // endif pretty
+
+ sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
+ goto err;
+ case '"':
+ if (!(jsp = ParseValue(g, i, src)))
+ goto err;
+
+ break;
+ case '(':
+ b = true;
+ break;
+ case ')':
+ if (b) {
+ b = false;
+ break;
+ } // endif b
+
+ default:
+ sprintf(g->Message, "Bad '%c' character near %.*s",
+ s[i], ARGS);
+ goto err;
+ }; // endswitch s[i]
+
+ if (!jsp)
+ sprintf(g->Message, "Invalid Json string '%.*s'", 50, s);
+
+ g->jump_level--;
+ return jsp;
+
+ err:
+ g->jump_level--;
+ return NULL;
+} // end of ParseJson
+
+/***********************************************************************/
+/* Parse a JSON Array. */
+/***********************************************************************/
+PJAR ParseArray(PGLOBAL g, int& i, STRG& src)
+{
+ char *s = src.str;
+ int len = src.len;
+ int level = 0;
+ PJAR jarp = new(g) JARRAY;
+ PJVAL jvp = NULL;
+
+ for (; i < len; i++)
+ switch (s[i]) {
+ case ',':
+ if (level < 2) {
+ sprintf(g->Message, "Unexpected ',' near %.*s",ARGS);
+ return NULL;
+ } else
+ level = 1;
+
+ break;
+ case ']':
+ if (level == 1) {
+ sprintf(g->Message, "Unexpected ',]' near %.*s", ARGS);
+ return NULL;
+ } // endif level
+
+ jarp->InitArray(g);
+ return jarp;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ default:
+ if (level == 2) {
+ sprintf(g->Message, "Unexpected value near %.*s", ARGS);
+ return NULL;
+ } else if ((jvp = ParseValue(g, i, src))) {
+ jarp->AddValue(g, jvp);
+ level = 2;
+ } else
+ return NULL;
+
+ level = 2;
+ break;
+ }; // endswitch s[i]
+
+ strcpy(g->Message, "Unexpected EOF in array");
+ return NULL;
+} // end of ParseArray
+
+/***********************************************************************/
+/* Parse a JSON Object. */
+/***********************************************************************/
+PJOB ParseObject(PGLOBAL g, int& i, STRG& src)
+{
+ PSZ key;
+ char *s = src.str;
+ int len = src.len;
+ int level = 0;
+ PJOB jobp = new(g) JOBJECT;
+ PJPR jpp = NULL;
+
+ for (; i < len; i++)
+ switch (s[i]) {
+ case '"':
+ if (level < 2) {
+ if ((key = ParseString(g, ++i, src))) {
+ jpp = jobp->AddPair(g, key);
+ level = 1;
+ } else
+ return NULL;
+
+ } else {
+ sprintf(g->Message, "misplaced string near %.*s", ARGS);
+ return NULL;
+ } // endif level
+
+ break;
+ case ':':
+ if (level == 1) {
+ if (!(jpp->Val = ParseValue(g, ++i, src)))
+ return NULL;
+
+ level = 2;
+ } else {
+ sprintf(g->Message, "Unexpected ':' near %.*s", ARGS);
+ return NULL;
+ } // endif level
+
+ break;
+ case ',':
+ if (level < 2) {
+ sprintf(g->Message, "Unexpected ',' near %.*s", ARGS);
+ return NULL;
+ } else
+ level = 1;
+
+ break;
+ case '}':
+ if (level == 1) {
+ sprintf(g->Message, "Unexpected '}' near %.*s", ARGS);
+ return NULL;
+ } // endif level
+
+ return jobp;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ default:
+ sprintf(g->Message, "Unexpected character '%c' near %.*s",
+ s[i], ARGS);
+ return NULL;
+ }; // endswitch s[i]
+
+ strcpy(g->Message, "Unexpected EOF in Object");
+ return NULL;
+} // end of ParseObject
+
+/***********************************************************************/
+/* Parse a JSON Value. */
+/***********************************************************************/
+PJVAL ParseValue(PGLOBAL g, int& i, STRG& src)
+{
+ char *strval, *s = src.str;
+ int n, len = src.len;
+ PJVAL jvp = new(g) JVALUE;
+
+ for (; i < len; i++)
+ switch (s[i]) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ default:
+ goto suite;
+ } // endswitch
+
+ suite:
+ switch (s[i]) {
+ case '[':
+ if (!(jvp->Jsp = ParseArray(g, ++i, src)))
+ return NULL;
+
+ break;
+ case '{':
+ if (!(jvp->Jsp = ParseObject(g, ++i, src)))
+ return NULL;
+
+ break;
+ case '"':
+ if ((strval = ParseString(g, ++i, src)))
+ jvp->Value = AllocateValue(g, strval, TYPE_STRING);
+ else
+ return NULL;
+
+ break;
+ case 't':
+ if (!strncmp(s + i, "true", 4)) {
+ n = 1;
+ jvp->Value = AllocateValue(g, &n, TYPE_TINY);
+ i += 3;
+ } else
+ goto err;
+
+ break;
+ case 'f':
+ if (!strncmp(s + i, "false", 5)) {
+ n = 0;
+ jvp->Value = AllocateValue(g, &n, TYPE_TINY);
+ i += 4;
+ } else
+ goto err;
+
+ break;
+ case 'n':
+ if (!strncmp(s + i, "null", 4))
+ i += 3;
+ else
+ goto err;
+
+ break;
+ case '-':
+ default:
+ if (s[i] == '-' || isdigit(s[i])) {
+ if (!(jvp->Value = ParseNumeric(g, i, src)))
+ goto err;
+
+ } else
+ goto err;
+
+ }; // endswitch s[i]
+
+ jvp->Size = 1;
+ return jvp;
+
+err:
+ sprintf(g->Message, "Unexpected character '%c' near %.*s",
+ s[i], ARGS);
+ return NULL;
+} // end of ParseValue
+
+/***********************************************************************/
+/* Unescape and parse a JSON string. */
+/***********************************************************************/
+char *ParseString(PGLOBAL g, int& i, STRG& src)
+{
+ char *s = src.str;
+ uchar *p;
+ int n = 0, len = src.len;
+
+ // Be sure of memory availability
+ if (len + 1 - i > (signed)((PPOOLHEADER)g->Sarea)->FreeBlk) {
+ strcpy(g->Message, "ParseString: Out of memory");
+ return NULL;
+ } // endif len
+
+ // The size to allocate is not known yet
+ p = (uchar*)PlugSubAlloc(g, NULL, 0);
+
+ for (; i < len; i++)
+ switch (s[i]) {
+ case '"':
+ p[n++] = 0;
+ PlugSubAlloc(g, NULL, n);
+ return (char*)p;
+ case '\\':
+ if (++i < len) {
+ if (s[i] == 'u') {
+ if (len - i > 5) {
+// if (charset == utf8) {
+ char xs[5];
+ uint hex;
+
+ xs[0] = s[++i];
+ xs[1] = s[++i];
+ xs[2] = s[++i];
+ xs[3] = s[++i];
+ xs[4] = 0;
+ hex = strtoul(xs, NULL, 16);
+
+ if (hex < 0x80) {
+ p[n] = (uchar)hex;
+ } else if (hex < 0x800) {
+ p[n++] = (uchar)(0xC0 | (hex >> 6));
+ p[n] = (uchar)(0x80 | (hex & 0x3F));
+ } else if (hex < 0x10000) {
+ p[n++] = (uchar)(0xE0 | (hex >> 12));
+ p[n++] = (uchar)(0x80 | ((hex >> 6) & 0x3f));
+ p[n] = (uchar)(0x80 | (hex & 0x3f));
+ } else
+ p[n] = '?';
+
+#if 0
+ } else {
+ char xs[3];
+ UINT hex;
+
+ i += 2;
+ xs[0] = s[++i];
+ xs[1] = s[++i];
+ xs[2] = 0;
+ hex = strtoul(xs, NULL, 16);
+ p[n] = (char)hex;
+ } // endif charset
+#endif // 0
+ } else
+ goto err;
+
+ } else switch(s[i]) {
+ case 't': p[n] = '\t'; break;
+ case 'n': p[n] = '\n'; break;
+ case 'r': p[n] = '\r'; break;
+ case 'b': p[n] = '\b'; break;
+ case 'f': p[n] = '\f'; break;
+ default: p[n] = s[i]; break;
+ } // endswitch
+
+ n++;
+ } else
+ goto err;
+
+ break;
+ default:
+ p[n++] = s[i];
+ break;
+ }; // endswitch s[i]
+
+ err:
+ strcpy(g->Message, "Unexpected EOF in String");
+ return NULL;
+} // end of ParseString
+
+/***********************************************************************/
+/* Parse a JSON numeric value. */
+/***********************************************************************/
+PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src)
+{
+ char *s = src.str, buf[50];
+ int n = 0, len = src.len;
+ short nd = 0;
+ bool has_dot = false;
+ bool has_e = false;
+ bool found_digit = false;
+ PVAL valp = NULL;
+
+ for (; i < len; i++) {
+ switch (s[i]) {
+ case '.':
+ if (!found_digit || has_dot || has_e)
+ goto err;
+
+ has_dot = true;
+ break;
+ case 'e':
+ case 'E':
+ if (!found_digit || has_e)
+ goto err;
+
+ has_e = true;
+ found_digit = false;
+ break;
+ case '+':
+ if (!has_e)
+ goto err;
+
+ // passthru
+ case '-':
+ if (found_digit)
+ goto err;
+
+ break;
+ default:
+ if (isdigit(s[i])) {
+ if (has_dot && !has_e)
+ nd++; // Number of decimals
+
+ found_digit = true;
+ } else
+ goto fin;
+
+ }; // endswitch s[i]
+
+ buf[n++] = s[i];
+ } // endfor i
+
+ fin:
+ if (found_digit) {
+ buf[n] = 0;
+
+ if (has_dot || has_e) {
+ double dv = strtod(buf, NULL);
+
+ valp = AllocateValue(g, &dv, TYPE_DOUBLE, nd);
+ } else {
+ int iv = strtol(buf, NULL, 10);
+
+ valp = AllocateValue(g, &iv, TYPE_INT);
+ } // endif has
+
+ i--; // Unstack following character
+ return valp;
+ } else {
+ strcpy(g->Message, "No digit found");
+ return NULL;
+ } // endif found_digit
+
+ err:
+ strcpy(g->Message, "Unexpected EOF in number");
+ return NULL;
+} // end of ParseNumeric
+
+/***********************************************************************/
+/* Serialize a JSON tree: */
+/***********************************************************************/
+PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty)
+{
+ bool b = false, err = true;
+ JOUT *jp;
+
+ g->Message[0] = 0;
+
+ if (!jsp) {
+ strcpy(g->Message, "Null json tree");
+ return NULL;
+ } else if (!fs) {
+ // Serialize to a string
+ jp = new(g) JOUTSTR(g);
+ b = pretty == 1;
+ } else if (pretty == 2) {
+ // Serialize to a pretty file
+ jp = new(g) JOUTPRT(g, fs);
+ } else {
+ // Serialize to a flat file
+ jp = new(g) JOUTFILE(g, fs);
+ b = pretty == 1;
+ } // endif's
+
+ switch (jsp->GetType()) {
+ case TYPE_JAR:
+ err = SerializeArray(jp, (PJAR)jsp, b);
+ break;
+ case TYPE_JOB:
+ err = (b && jp->WriteChr('\t'));
+ err |= SerializeObject(jp, (PJOB)jsp);
+ break;
+ case TYPE_JVAL:
+ err = SerializeValue(jp, (PJVAL)jsp);
+ break;
+ default:
+ strcpy(g->Message, "Invalid json tree");
+ } // endswitch Type
+
+ if (fs) {
+ fputc('\n', fs);
+ fclose(fs);
+ return (err) ? g->Message : NULL;
+ } else if (!err) {
+ PSZ str = ((JOUTSTR*)jp)->Strp;
+
+ jp->WriteChr('\0');
+ PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
+ return str;
+ } else {
+ if (!g->Message[0])
+ strcpy(g->Message, "Error in Serialize");
+
+ return NULL;
+ } // endif's
+
+} // end of Serialize
+
+/***********************************************************************/
+/* Serialize a JSON Array. */
+/***********************************************************************/
+bool SerializeArray(JOUT *js, PJAR jarp, bool b)
+{
+ bool first = true;
+
+
+ if (js->WriteChr('['))
+ return true;
+ else if (b && (js->WriteStr(EL) || js->WriteChr('\t')))
+ return true;
+
+ for (int i = 0; i < jarp->size(); i++) {
+ if (first)
+ first = false;
+ else if (js->WriteChr(','))
+ return true;
+ else if (b && (js->WriteStr(EL) || js->WriteChr('\t')))
+ return true;
+
+ if (SerializeValue(js, jarp->GetValue(i)))
+ return true;
+
+ } // endfor i
+
+ if (b && js->WriteStr(EL))
+ return true;
+
+ return js->WriteChr(']');
+} // end of SerializeArray
+
+/***********************************************************************/
+/* Serialize a JSON Object. */
+/***********************************************************************/
+bool SerializeObject(JOUT *js, PJOB jobp)
+{
+ bool first = true;
+
+ if (js->WriteChr('{'))
+ return true;
+
+ for (PJPR pair = jobp->First; pair; pair = pair->Next) {
+ if (first)
+ first = false;
+ else if (js->WriteChr(','))
+ return true;
+
+ if (js->WriteChr('"') ||
+ js->WriteStr(pair->Key) ||
+ js->WriteChr('"') ||
+ js->WriteChr(':') ||
+ SerializeValue(js, pair->Val))
+ return true;
+
+ } // endfor i
+
+ return js->WriteChr('}');
+} // end of SerializeObject
+
+/***********************************************************************/
+/* Serialize a JSON Value. */
+/***********************************************************************/
+bool SerializeValue(JOUT *js, PJVAL jvp)
+{
+ PJAR jap;
+ PJOB jop;
+ PVAL valp;
+
+ if ((jap = jvp->GetArray()))
+ return SerializeArray(js, jap, false);
+ else if ((jop = jvp->GetObject()))
+ return SerializeObject(js, jop);
+ else if (!(valp = jvp->Value) || valp->IsNull())
+ return js->WriteStr("null");
+ else switch (valp->GetType()) {
+ case TYPE_TINY:
+ return js->WriteStr(valp->GetTinyValue() ? "true" : "false");
+ case TYPE_STRING:
+ return js->Escape(valp->GetCharValue());
+ default:
+ if (valp->IsTypeNum()) {
+ char buf[32];
+
+ return js->WriteStr(valp->GetCharString(buf));
+ } // endif valp
+
+ } // endswitch Type
+
+strcpy(js->g->Message, "Unrecognized value");
+return true;
+} // end of SerializeValue
+
+/* -------------------------- Class JOUTSTR -------------------------- */
+
+/***********************************************************************/
+/* JOUTSTR constructor. */
+/***********************************************************************/
+JOUTSTR::JOUTSTR(PGLOBAL g) : JOUT(g)
+{
+ PPOOLHEADER pph = (PPOOLHEADER)g->Sarea;
+
+ N = 0;
+ Max = pph->FreeBlk;
+ Max = (Max > 32) ? Max - 32 : Max;
+ Strp = (char*)PlugSubAlloc(g, NULL, 0); // Size not know yet
+} // end of JOUTSTR constructor
+
+/***********************************************************************/
+/* Concatenate a string to the Serialize string. */
+/***********************************************************************/
+bool JOUTSTR::WriteStr(const char *s)
+{
+ if (s) {
+ size_t len = strlen(s);
+
+ if (N + len > Max)
+ return true;
+
+ memcpy(Strp + N, s, len);
+ N += len;
+ return false;
+ } else
+ return true;
+
+} // end of WriteStr
+
+/***********************************************************************/
+/* Concatenate a character to the Serialize string. */
+/***********************************************************************/
+bool JOUTSTR::WriteChr(const char c)
+{
+ if (N + 1 > Max)
+ return true;
+
+ Strp[N++] = c;
+ return false;
+} // end of WriteChr
+
+/***********************************************************************/
+/* Escape and Concatenate a string to the Serialize string. */
+/***********************************************************************/
+bool JOUTSTR::Escape(const char *s)
+{
+ WriteChr('"');
+
+ for (unsigned int i = 0; i < strlen(s); i++)
+ switch (s[i]) {
+ case '"':
+ case '\\':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\b':
+ case '\f': WriteChr('\\');
+ // passthru
+ default:
+ WriteChr(s[i]);
+ break;
+ } // endswitch s[i]
+
+ WriteChr('"');
+ return false;
+} // end of Escape
+
+/* ------------------------- Class JOUTFILE -------------------------- */
+
+/***********************************************************************/
+/* Write a string to the Serialize file. */
+/***********************************************************************/
+bool JOUTFILE::WriteStr(const char *s)
+{
+ // This is temporary
+ fputs(s, Stream);
+ return false;
+} // end of WriteStr
+
+/***********************************************************************/
+/* Write a character to the Serialize file. */
+/***********************************************************************/
+bool JOUTFILE::WriteChr(const char c)
+{
+ // This is temporary
+ fputc(c, Stream);
+ return false;
+} // end of WriteChr
+
+/***********************************************************************/
+/* Escape and Concatenate a string to the Serialize string. */
+/***********************************************************************/
+bool JOUTFILE::Escape(const char *s)
+{
+ // This is temporary
+ fputc('"', Stream);
+
+ for (unsigned int i = 0; i < strlen(s); i++)
+ switch (s[i]) {
+ case '"': fputs("\\\"", Stream); break;
+ case '\\': fputs("\\\\", Stream); break;
+ case '\t': fputs("\\t", Stream); break;
+ case '\n': fputs("\\n", Stream); break;
+ case '\r': fputs("\\r", Stream); break;
+ case '\b': fputs("\\b", Stream); break;
+ case '\f': fputs("\\f", Stream); break;
+ default:
+ fputc(s[i], Stream);
+ break;
+ } // endswitch s[i]
+
+ fputc('"', Stream);
+ return false;
+} // end of Escape
+
+/* ------------------------- Class JOUTPRT --------------------------- */
+
+/***********************************************************************/
+/* Write a string to the Serialize pretty file. */
+/***********************************************************************/
+bool JOUTPRT::WriteStr(const char *s)
+{
+ // This is temporary
+ if (B) {
+ fputs(EL, Stream);
+ M--;
+
+ for (int i = 0; i < M; i++)
+ fputc('\t', Stream);
+
+ B = false;
+ } // endif B
+
+ fputs(s, Stream);
+ return false;
+} // end of WriteStr
+
+/***********************************************************************/
+/* Write a character to the Serialize pretty file. */
+/***********************************************************************/
+bool JOUTPRT::WriteChr(const char c)
+{
+ switch (c) {
+ case ':':
+ fputs(": ", Stream);
+ break;
+ case '{':
+ case '[':
+#if 0
+ if (M)
+ fputs(EL, Stream);
+
+ for (int i = 0; i < M; i++)
+ fputc('\t', Stream);
+#endif // 0
+
+ fputc(c, Stream);
+ fputs(EL, Stream);
+ M++;
+
+ for (int i = 0; i < M; i++)
+ fputc('\t', Stream);
+
+ break;
+ case '}':
+ case ']':
+ M--;
+ fputs(EL, Stream);
+
+ for (int i = 0; i < M; i++)
+ fputc('\t', Stream);
+
+ fputc(c, Stream);
+ B = true;
+ break;
+ case ',':
+ fputc(c, Stream);
+ fputs(EL, Stream);
+
+ for (int i = 0; i < M; i++)
+ fputc('\t', Stream);
+
+ B = false;
+ break;
+ default:
+ fputc(c, Stream);
+ } // endswitch c
+
+return false;
+} // end of WriteChr
+
+/* -------------------------- Class JOBJECT -------------------------- */
+
+/***********************************************************************/
+/* Add a new pair to an Object. */
+/***********************************************************************/
+PJPR JOBJECT::AddPair(PGLOBAL g, PSZ key)
+{
+ PJPR jpp = new(g) JPAIR(key);
+
+ if (Last)
+ Last->Next = jpp;
+ else
+ First = jpp;
+
+ Last = jpp;
+ Size++;
+ return jpp;
+} // end of AddPair
+
+/***********************************************************************/
+/* Get the value corresponding to the given key. */
+/***********************************************************************/
+PJVAL JOBJECT::GetValue(const char* key)
+{
+ for (PJPR jp = First; jp; jp = jp->Next)
+ if (!strcmp(jp->Key, key))
+ return jp->Val;
+
+ return NULL;
+} // end of GetValue;
+
+/***********************************************************************/
+/* Return the text corresponding to all keys (XML like). */
+/***********************************************************************/
+PSZ JOBJECT::GetText(PGLOBAL g, PSZ text)
+{
+ int n;
+
+ if (!text) {
+ text = (char*)PlugSubAlloc(g, NULL, 0);
+ text[0] = 0;
+ n = 1;
+ } else
+ n = 0;
+
+ if (!First && n)
+ return NULL;
+ else for (PJPR jp = First; jp; jp = jp->Next)
+ jp->Val->GetText(g, text);
+
+ if (n)
+ PlugSubAlloc(g, NULL, strlen(text) + 1);
+
+ return text + n;
+} // end of GetValue;
+
+/***********************************************************************/
+/* Set or add a value corresponding to the given key. */
+/***********************************************************************/
+void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key)
+{
+ PJPR jp;
+
+ for (jp = First; jp; jp = jp->Next)
+ if (!strcmp(jp->Key, key)) {
+ jp->Val = jvp;
+ break;
+ } // endif key
+
+ if (!jp) {
+ jp = AddPair(g, key);
+ jp->Val = jvp;
+ } // endif jp
+
+} // end of SetValue
+
+/***********************************************************************/
+/* True if void or if all members are nulls. */
+/***********************************************************************/
+bool JOBJECT::IsNull(void)
+{
+ for (PJPR jp = First; jp; jp = jp->Next)
+ if (!jp->Val->IsNull())
+ return false;
+
+ return true;
+} // end of IsNull
+
+/* -------------------------- Class JARRAY --------------------------- */
+
+/***********************************************************************/
+/* Make the array of values from the values list. */
+/***********************************************************************/
+void JARRAY::InitArray(PGLOBAL g)
+{
+ int i;
+ PJVAL jvp;
+
+ for (Size = 0, jvp = First; jvp; jvp = jvp->Next)
+ if (!jvp->Del)
+ Size++;
+
+ if (!Size) {
+ return;
+ } else if (Size > Alloc) {
+ // No need to realloc after deleting values
+ Mvals = (PJVAL*)PlugSubAlloc(g, NULL, Size * sizeof(PJVAL));
+ Alloc = Size;
+ } // endif Size
+
+ for (i = 0, jvp = First; jvp; jvp = jvp->Next)
+ if (!jvp->Del)
+ Mvals[i++] = jvp;
+
+} // end of InitArray
+
+/***********************************************************************/
+/* Get the Nth value of an Array. */
+/***********************************************************************/
+PJVAL JARRAY::GetValue(int i)
+{
+ if (Mvals && i >= 0 && i < Size)
+ return Mvals[i];
+ else
+ return NULL;
+} // end of GetValue
+
+/***********************************************************************/
+/* Add a Value to the Arrays Value list. */
+/***********************************************************************/
+PJVAL JARRAY::AddValue(PGLOBAL g, PJVAL jvp)
+{
+ if (!jvp)
+ jvp = new(g) JVALUE;
+
+ if (Last)
+ Last->Next = jvp;
+ else
+ First = jvp;
+
+ Last = jvp;
+ return jvp;
+} // end of AddValue
+
+/***********************************************************************/
+/* Add a Value to the Arrays Value list. */
+/***********************************************************************/
+bool JARRAY::SetValue(PGLOBAL g, PJVAL jvp, int n)
+{
+ int i = 0;
+ PJVAL jp, *jpp = &First;
+
+ for (i = 0, jp = First; i < n; i++, jp = *(jpp = &jp->Next))
+ if (!jp)
+ *jpp = jp = new(g) JVALUE;
+
+ *jpp = jvp;
+ jvp->Next = (jp ? jp->Next : NULL);
+ return false;
+} // end of SetValue
+
+/***********************************************************************/
+/* Delete a Value from the Arrays Value list. */
+/***********************************************************************/
+bool JARRAY::DeleteValue(int n)
+{
+ PJVAL jvp = GetValue(n);
+
+ if (jvp) {
+ jvp->Del = true;
+ return false;
+ } else
+ return true;
+
+} // end of DeleteValue
+
+/***********************************************************************/
+/* True if void or if all members are nulls. */
+/***********************************************************************/
+bool JARRAY::IsNull(void)
+{
+ for (int i = 0; i < Size; i++)
+ if (!Mvals[i]->IsNull())
+ return false;
+
+ return true;
+} // end of IsNull
+
+/* -------------------------- Class JVALUE- -------------------------- */
+
+/***********************************************************************/
+/* Constructor for a Value with a given string or numeric value. */
+/***********************************************************************/
+JVALUE::JVALUE(PGLOBAL g, PVAL valp) : JSON()
+{
+ Jsp = NULL;
+ Value = AllocateValue(g, valp);
+ Next = NULL;
+ Del = false;
+} // end of JVALUE constructor
+
+/***********************************************************************/
+/* Returns the type of the Value's value. */
+/***********************************************************************/
+JTYP JVALUE::GetValType(void)
+{
+ if (Jsp)
+ return Jsp->GetType();
+ else if (Value)
+ return (JTYP)Value->GetType();
+ else
+ return (JTYP)TYPE_VOID;
+
+} // end of GetValType
+
+/***********************************************************************/
+/* Return the Value's Object value. */
+/***********************************************************************/
+PJOB JVALUE::GetObject(void)
+{
+ if (Jsp && Jsp->GetType() == TYPE_JOB)
+ return (PJOB)Jsp;
+
+ return NULL;
+} // end of GetObject
+
+/***********************************************************************/
+/* Return the Value's Array value. */
+/***********************************************************************/
+PJAR JVALUE::GetArray(void)
+{
+ if (Jsp && Jsp->GetType() == TYPE_JAR)
+ return (PJAR)Jsp;
+
+ return NULL;
+} // end of GetArray
+
+/***********************************************************************/
+/* Return the Value's Integer value. */
+/***********************************************************************/
+int JVALUE::GetInteger(void)
+{
+ return (Value) ? Value->GetIntValue() : 0;
+} // end of GetInteger
+
+/***********************************************************************/
+/* Return the Value's Double value. */
+/***********************************************************************/
+double JVALUE::GetFloat(void)
+{
+ return (Value) ? Value->GetFloatValue() : 0.0;
+} // end of GetFloat
+
+/***********************************************************************/
+/* Return the Value's String value. */
+/***********************************************************************/
+PSZ JVALUE::GetString(void)
+{
+ char buf[32];
+ return (Value) ? Value->GetCharString(buf) : NULL;
+} // end of GetString
+
+/***********************************************************************/
+/* Return the Value's String value. */
+/***********************************************************************/
+PSZ JVALUE::GetText(PGLOBAL g, PSZ text)
+{
+ if (Jsp && Jsp->GetType() == TYPE_JOB)
+ return Jsp->GetText(g, text);
+
+ char buf[32];
+ PSZ s = (Value) ? Value->GetCharString(buf) : NULL;
+
+ if (s)
+ strcat(strcat(text, " "), s);
+ else
+ strcat(text, " ???");
+
+ return text;
+} // end of GetText
+
+/***********************************************************************/
+/* Set the Value's value as the given integer. */
+/***********************************************************************/
+void JVALUE::SetInteger(PGLOBAL g, int n)
+{
+ Value = AllocateValue(g, &n, TYPE_INT);
+} // end of AddInteger
+
+/***********************************************************************/
+/* Set the Value's value as the given DOUBLE. */
+/***********************************************************************/
+void JVALUE::SetFloat(PGLOBAL g, double f)
+{
+ Value = AllocateValue(g, &f, TYPE_DOUBLE, 6);
+} // end of AddFloat
+
+/***********************************************************************/
+/* Set the Value's value as the given string. */
+/***********************************************************************/
+void JVALUE::SetString(PGLOBAL g, PSZ s)
+{
+ Value = AllocateValue(g, s, TYPE_STRING);
+} // end of AddFloat
+
+/***********************************************************************/
+/* True when its JSON or normal value is null. */
+/***********************************************************************/
+bool JVALUE::IsNull(void)
+{
+ return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsZero() : true;
+} // end of IsNull
+
diff --git a/storage/connect/json.h b/storage/connect/json.h
index 11e15c3acd4..da45157f124 100644
--- a/storage/connect/json.h
+++ b/storage/connect/json.h
@@ -1,246 +1,270 @@
-/**************** json H Declares Source Code File (.H) ****************/
-/* Name: json.h Version 1.0 */
-/* */
-/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
-/* */
-/* This file contains the JSON classes declares. */
-/***********************************************************************/
-#include "value.h"
-
-#if defined(_DEBUG)
-#define X assert(false);
-#else
-#define X
-#endif
-
-enum JTYP {TYPE_STRG = 1,
- TYPE_DBL = 2,
- TYPE_BOOL = 4,
- TYPE_INTG = 7,
- TYPE_JSON = 12,
- TYPE_JAR, TYPE_JOB,
- TYPE_JVAL};
-
-class JOUT;
-class JSON;
-class JMAP;
-class JVALUE;
-class JOBJECT;
-class JARRAY;
-
-typedef class JPAIR *PJPR;
-typedef class JSON *PJSON;
-typedef class JVALUE *PJVAL;
-typedef class JOBJECT *PJOB;
-typedef class JARRAY *PJAR;
-
-typedef struct {
- char *str;
- int len;
- } STRG, *PSG;
-
-PJSON ParseJson(PGLOBAL g, char *s, int n, int prty, bool *b = NULL);
-PJAR ParseArray(PGLOBAL g, int& i, STRG& src);
-PJOB ParseObject(PGLOBAL g, int& i, STRG& src);
-PJVAL ParseValue(PGLOBAL g, int& i, STRG& src);
-char *ParseString(PGLOBAL g, int& i, STRG& src);
-PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src);
-PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty);
-bool SerializeArray(JOUT *js, PJAR jarp, bool b);
-bool SerializeObject(JOUT *js, PJOB jobp);
-bool SerializeValue(JOUT *js, PJVAL jvp);
-
-/***********************************************************************/
-/* Class JOUT. Used by Serialize. */
-/***********************************************************************/
-class JOUT : public BLOCK {
- public:
- JOUT(PGLOBAL gp) : BLOCK() {g = gp;}
-
- virtual bool WriteStr(const char *s) = 0;
- virtual bool WriteChr(const char c) = 0;
- virtual bool Escape(const char *s) = 0;
-
- // Member
- PGLOBAL g;
-}; // end of class JOUT
-
-/***********************************************************************/
-/* Class JOUTSTR. Used to Serialize to a string. */
-/***********************************************************************/
-class JOUTSTR : public JOUT {
- public:
- JOUTSTR(PGLOBAL g);
-
- virtual bool WriteStr(const char *s);
- virtual bool WriteChr(const char c);
- virtual bool Escape(const char *s);
-
- // Member
- char *Strp; // The serialized string
- size_t N; // Position of next char
- size_t Max; // String max size
-}; // end of class JOUTSTR
-
-/***********************************************************************/
-/* Class JOUTFILE. Used to Serialize to a file. */
-/***********************************************************************/
-class JOUTFILE : public JOUT {
- public:
- JOUTFILE(PGLOBAL g, FILE *str) : JOUT(g) {Stream = str;}
-
- virtual bool WriteStr(const char *s);
- virtual bool WriteChr(const char c);
- virtual bool Escape(const char *s);
-
- // Member
- FILE *Stream;
-}; // end of class JOUTFILE
-
-/***********************************************************************/
-/* Class JOUTPRT. Used to Serialize to a pretty file. */
-/***********************************************************************/
-class JOUTPRT : public JOUTFILE {
- public:
- JOUTPRT(PGLOBAL g, FILE *str) : JOUTFILE(g, str) {M = 0; B = false;}
-
- virtual bool WriteStr(const char *s);
- virtual bool WriteChr(const char c);
-
- // Member
- int M;
- bool B;
-}; // end of class JOUTPRT
-
-/***********************************************************************/
-/* Class PAIR. The pairs of a json Object. */
-/***********************************************************************/
-class JPAIR : public BLOCK {
- friend class JOBJECT;
- friend PJOB ParseObject(PGLOBAL, int&, STRG&);
- friend bool SerializeObject(JOUT *, PJOB);
- public:
- JPAIR(PSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;}
-
- protected:
- PSZ Key; // This pair key name
- PJVAL Val; // To the value of the pair
- PJPR Next; // To the next pair
-}; // end of class JPAIR
-
-/***********************************************************************/
-/* Class JSON. The base class for all other json classes. */
-/***********************************************************************/
-class JSON : public BLOCK {
- public:
- JSON(void) {Size = 0;}
-
- int size(void) {return Size;}
- virtual void Clear(void) {Size = 0;}
- virtual JTYP GetType(void) {return TYPE_JSON;}
- virtual JTYP GetValType(void) {X return TYPE_JSON;}
- virtual void InitArray(PGLOBAL g) {X}
- virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL) {X return NULL;}
- virtual PJPR AddPair(PGLOBAL g, PSZ key) {X return NULL;}
- virtual PJVAL GetValue(const char *key) {X return NULL;}
- virtual PJOB GetObject(void) {X return NULL;}
- virtual PJAR GetArray(void) {X return NULL;}
- virtual PJVAL GetValue(int i) {X return NULL;}
- virtual PVAL GetValue(void) {X return NULL;}
- virtual PJSON GetJson(void) {X return NULL;}
- virtual int GetInteger(void) {X return 0;}
- virtual double GetFloat() {X return 0.0;}
- virtual PSZ GetString() {X return NULL;}
- virtual PSZ GetText(PGLOBAL g) {X return NULL;}
- virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i) {X return true;}
- virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X}
- virtual void SetValue(PVAL valp) {X}
- virtual void SetValue(PJSON jsp) {X}
- virtual bool DeleteValue(int i) {X return true;}
-
- protected:
- int Size;
-}; // end of class JSON
-
-/***********************************************************************/
-/* Class JOBJECT: contains a list of value pairs. */
-/***********************************************************************/
-class JOBJECT : public JSON {
- friend PJOB ParseObject(PGLOBAL, int&, STRG&);
- friend bool SerializeObject(JOUT *, PJOB);
- public:
- JOBJECT(void) : JSON() {First = Last = NULL;}
-
- virtual void Clear(void) {First = Last = NULL; Size = 0;}
- virtual JTYP GetType(void) {return TYPE_JOB;}
- virtual PJPR AddPair(PGLOBAL g, PSZ key);
- virtual PJOB GetObject(void) {return this;}
- virtual PJVAL GetValue(const char* key);
- virtual PSZ GetText(PGLOBAL g);
- virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key);
-
- protected:
- PJPR First;
- PJPR Last;
-}; // end of class JOBJECT
-
-/***********************************************************************/
-/* Class JARRAY. */
-/***********************************************************************/
-class JARRAY : public JSON {
- friend PJAR ParseArray(PGLOBAL, int&, STRG&);
- public:
- JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;}
-
- virtual void Clear(void) {First = Last = NULL; Size = 0;}
- virtual JTYP GetType(void) {return TYPE_JAR;}
- virtual PJAR GetArray(void) {return this;}
- virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL);
- virtual void InitArray(PGLOBAL g);
- virtual PJVAL GetValue(int i);
- virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i);
- virtual bool DeleteValue(int n);
-
- protected:
- // Members
- int Alloc; // The Mvals allocated size
- PJVAL First; // Used when constructing
- PJVAL Last; // Last constructed value
- PJVAL *Mvals; // Allocated when finished
-}; // end of class JARRAY
-
-/***********************************************************************/
-/* Class JVALUE. */
-/***********************************************************************/
-class JVALUE : public JSON {
- friend class JARRAY;
- friend PJVAL ParseValue(PGLOBAL, int&, STRG&);
- friend bool SerializeValue(JOUT *, PJVAL);
- public:
- JVALUE(void) : JSON()
- {Jsp = NULL; Value = NULL; Next = NULL; Del = false;}
- JVALUE(PJSON jsp) : JSON()
- {Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
- JVALUE(PGLOBAL g, PVAL valp);
-
- virtual void Clear(void)
- {Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;}
- virtual JTYP GetType(void) {return TYPE_JVAL;}
- virtual JTYP GetValType(void);
- virtual PJOB GetObject(void);
- virtual PJAR GetArray(void);
- virtual PVAL GetValue(void) {return Value;}
- virtual PJSON GetJson(void) {return (Jsp ? Jsp : this);}
- virtual int GetInteger(void);
- virtual double GetFloat(void);
- virtual PSZ GetString(void);
- virtual void SetValue(PVAL valp) {Value = valp;}
- virtual void SetValue(PJSON jsp) {Jsp = jsp;}
-
- protected:
- PJSON Jsp; // To the json value
- PVAL Value; // The numeric value
- PJVAL Next; // Next value in array
- bool Del; // True when deleted
-}; // end of class JVALUE
-
+/**************** json H Declares Source Code File (.H) ****************/
+/* Name: json.h Version 1.1 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
+/* */
+/* This file contains the JSON classes declares. */
+/***********************************************************************/
+#include "value.h"
+
+#if defined(_DEBUG)
+#define X assert(false);
+#else
+#define X
+#endif
+
+enum JTYP {TYPE_STRG = 1,
+ TYPE_DBL = 2,
+ TYPE_BOOL = 4,
+ TYPE_INTG = 7,
+ TYPE_JSON = 12,
+ TYPE_JAR,
+ TYPE_JOB,
+ TYPE_JVAL};
+
+class JOUT;
+class JSON;
+class JMAP;
+class JVALUE;
+class JOBJECT;
+class JARRAY;
+
+typedef class JPAIR *PJPR;
+typedef class JSON *PJSON;
+typedef class JVALUE *PJVAL;
+typedef class JOBJECT *PJOB;
+typedef class JARRAY *PJAR;
+
+typedef struct {
+ char *str;
+ int len;
+ } STRG, *PSG;
+
+PJSON ParseJson(PGLOBAL g, char *s, int n, int prty, bool *b = NULL);
+PJAR ParseArray(PGLOBAL g, int& i, STRG& src);
+PJOB ParseObject(PGLOBAL g, int& i, STRG& src);
+PJVAL ParseValue(PGLOBAL g, int& i, STRG& src);
+char *ParseString(PGLOBAL g, int& i, STRG& src);
+PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src);
+PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty);
+bool SerializeArray(JOUT *js, PJAR jarp, bool b);
+bool SerializeObject(JOUT *js, PJOB jobp);
+bool SerializeValue(JOUT *js, PJVAL jvp);
+
+/***********************************************************************/
+/* Class JOUT. Used by Serialize. */
+/***********************************************************************/
+class JOUT : public BLOCK {
+ public:
+ JOUT(PGLOBAL gp) : BLOCK() {g = gp;}
+
+ virtual bool WriteStr(const char *s) = 0;
+ virtual bool WriteChr(const char c) = 0;
+ virtual bool Escape(const char *s) = 0;
+
+ // Member
+ PGLOBAL g;
+}; // end of class JOUT
+
+/***********************************************************************/
+/* Class JOUTSTR. Used to Serialize to a string. */
+/***********************************************************************/
+class JOUTSTR : public JOUT {
+ public:
+ JOUTSTR(PGLOBAL g);
+
+ virtual bool WriteStr(const char *s);
+ virtual bool WriteChr(const char c);
+ virtual bool Escape(const char *s);
+
+ // Member
+ char *Strp; // The serialized string
+ size_t N; // Position of next char
+ size_t Max; // String max size
+}; // end of class JOUTSTR
+
+/***********************************************************************/
+/* Class JOUTFILE. Used to Serialize to a file. */
+/***********************************************************************/
+class JOUTFILE : public JOUT {
+ public:
+ JOUTFILE(PGLOBAL g, FILE *str) : JOUT(g) {Stream = str;}
+
+ virtual bool WriteStr(const char *s);
+ virtual bool WriteChr(const char c);
+ virtual bool Escape(const char *s);
+
+ // Member
+ FILE *Stream;
+}; // end of class JOUTFILE
+
+/***********************************************************************/
+/* Class JOUTPRT. Used to Serialize to a pretty file. */
+/***********************************************************************/
+class JOUTPRT : public JOUTFILE {
+ public:
+ JOUTPRT(PGLOBAL g, FILE *str) : JOUTFILE(g, str) {M = 0; B = false;}
+
+ virtual bool WriteStr(const char *s);
+ virtual bool WriteChr(const char c);
+
+ // Member
+ int M;
+ bool B;
+}; // end of class JOUTPRT
+
+/***********************************************************************/
+/* Class PAIR. The pairs of a json Object. */
+/***********************************************************************/
+class JPAIR : public BLOCK {
+ friend class JOBJECT;
+ friend PJOB ParseObject(PGLOBAL, int&, STRG&);
+ friend bool SerializeObject(JOUT *, PJOB);
+ public:
+ JPAIR(PSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;}
+
+ inline PSZ GetKey(void) {return Key;}
+ inline PJVAL GetVal(void) {return Val;}
+ inline PJPR GetNext(void) {return Next;}
+
+ protected:
+ PSZ Key; // This pair key name
+ PJVAL Val; // To the value of the pair
+ PJPR Next; // To the next pair
+}; // end of class JPAIR
+
+/***********************************************************************/
+/* Class JSON. The base class for all other json classes. */
+/***********************************************************************/
+class JSON : public BLOCK {
+ public:
+ JSON(void) {Size = 0;}
+
+ int size(void) {return Size;}
+ virtual void Clear(void) {Size = 0;}
+ virtual JTYP GetType(void) {return TYPE_JSON;}
+ virtual JTYP GetValType(void) {X return TYPE_JSON;}
+ virtual void InitArray(PGLOBAL g) {X}
+ virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL) {X return NULL;}
+ virtual PJPR AddPair(PGLOBAL g, PSZ key) {X return NULL;}
+ virtual PJVAL GetValue(const char *key) {X return NULL;}
+ virtual PJOB GetObject(void) {return NULL;}
+ virtual PJAR GetArray(void) {return NULL;}
+ virtual PJVAL GetValue(int i) {X return NULL;}
+ virtual PVAL GetValue(void) {X return NULL;}
+ virtual PJSON GetJson(void) {X return NULL;}
+ virtual PJPR GetFirst(void) {X return NULL;}
+ virtual int GetInteger(void) {X return 0;}
+ virtual double GetFloat() {X return 0.0;}
+ virtual PSZ GetString() {X return NULL;}
+ virtual PSZ GetText(PGLOBAL g, PSZ text) {X return NULL;}
+ virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i) {X return true;}
+ virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X}
+ virtual void SetValue(PVAL valp) {X}
+ virtual void SetValue(PJSON jsp) {X}
+ virtual void SetString(PGLOBAL g, PSZ s) {X}
+ virtual void SetInteger(PGLOBAL g, int n) {X}
+ virtual void SetFloat(PGLOBAL g, double f) {X}
+ virtual bool DeleteValue(int i) {X return true;}
+ virtual bool IsNull(void) {X return true;}
+
+ protected:
+ int Size;
+}; // end of class JSON
+
+/***********************************************************************/
+/* Class JOBJECT: contains a list of value pairs. */
+/***********************************************************************/
+class JOBJECT : public JSON {
+ friend PJOB ParseObject(PGLOBAL, int&, STRG&);
+ friend bool SerializeObject(JOUT *, PJOB);
+ public:
+ JOBJECT(void) : JSON() {First = Last = NULL;}
+
+ using JSON::GetValue;
+ using JSON::SetValue;
+ virtual void Clear(void) {First = Last = NULL; Size = 0;}
+ virtual JTYP GetType(void) {return TYPE_JOB;}
+ virtual PJPR GetFirst(void) {return First;}
+ virtual PJPR AddPair(PGLOBAL g, PSZ key);
+ virtual PJOB GetObject(void) {return this;}
+ virtual PJVAL GetValue(const char* key);
+ virtual PSZ GetText(PGLOBAL g, PSZ text);
+ virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key);
+ virtual bool IsNull(void);
+
+ protected:
+ PJPR First;
+ PJPR Last;
+}; // end of class JOBJECT
+
+/***********************************************************************/
+/* Class JARRAY. */
+/***********************************************************************/
+class JARRAY : public JSON {
+ friend PJAR ParseArray(PGLOBAL, int&, STRG&);
+ public:
+ JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;}
+
+ using JSON::GetValue;
+ using JSON::SetValue;
+ virtual void Clear(void) {First = Last = NULL; Size = 0;}
+ virtual JTYP GetType(void) {return TYPE_JAR;}
+ virtual PJAR GetArray(void) {return this;}
+ virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL);
+ virtual void InitArray(PGLOBAL g);
+ virtual PJVAL GetValue(int i);
+ virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i);
+ virtual bool DeleteValue(int n);
+ virtual bool IsNull(void);
+
+ protected:
+ // Members
+ int Alloc; // The Mvals allocated size
+ PJVAL First; // Used when constructing
+ PJVAL Last; // Last constructed value
+ PJVAL *Mvals; // Allocated when finished
+}; // end of class JARRAY
+
+/***********************************************************************/
+/* Class JVALUE. */
+/***********************************************************************/
+class JVALUE : public JSON {
+ friend class JARRAY;
+ friend PJVAL ParseValue(PGLOBAL, int&, STRG&);
+ friend bool SerializeValue(JOUT *, PJVAL);
+ public:
+ JVALUE(void) : JSON()
+ {Jsp = NULL; Value = NULL; Next = NULL; Del = false;}
+ JVALUE(PJSON jsp) : JSON()
+ {Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
+ JVALUE(PGLOBAL g, PVAL valp);
+
+ using JSON::GetValue;
+ using JSON::SetValue;
+ virtual void Clear(void)
+ {Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;}
+ virtual JTYP GetType(void) {return TYPE_JVAL;}
+ virtual JTYP GetValType(void);
+ virtual PJOB GetObject(void);
+ virtual PJAR GetArray(void);
+ virtual PVAL GetValue(void) {return Value;}
+ virtual PJSON GetJson(void) {return (Jsp ? Jsp : this);}
+ virtual int GetInteger(void);
+ virtual double GetFloat(void);
+ virtual PSZ GetString(void);
+ virtual PSZ GetText(PGLOBAL g, PSZ text);
+ virtual void SetValue(PVAL valp) {Value = valp;}
+ virtual void SetValue(PJSON jsp) {Jsp = jsp;}
+ virtual void SetString(PGLOBAL g, PSZ s);
+ virtual void SetInteger(PGLOBAL g, int n);
+ virtual void SetFloat(PGLOBAL g, double f);
+ virtual bool IsNull(void);
+
+ protected:
+ PJSON Jsp; // To the json value
+ PVAL Value; // The numeric value
+ PJVAL Next; // Next value in array
+ bool Del; // True when deleted
+}; // end of class JVALUE
+
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
new file mode 100644
index 00000000000..ff4025ee0fb
--- /dev/null
+++ b/storage/connect/jsonudf.cpp
@@ -0,0 +1,690 @@
+/************* jsonudf C++ Program Source Code File (.CPP) *************/
+/* PROGRAM NAME: jsonudf Version 1.0 */
+/* (C) Copyright to the author Olivier BERTRAND 2015 */
+/* This program are the JSON User Defined Functions . */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant sections of the MariaDB header file. */
+/***********************************************************************/
+#include <my_global.h>
+#include <mysqld.h>
+#include <mysql.h>
+#include <sql_error.h>
+
+#include "global.h"
+#include "plgdbsem.h"
+#include "json.h"
+
+#define MEMFIX 512
+#define UDF_EXEC_ARGS \
+ UDF_INIT*, UDF_ARGS*, char*, unsigned long*, char*, char*
+
+uint GetJsonGrpSize(void);
+
+extern "C" {
+DllExport my_bool Json_Value_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport char *Json_Value(UDF_EXEC_ARGS);
+DllExport void Json_Value_deinit(UDF_INIT*);
+
+DllExport my_bool Json_Array_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport char *Json_Array(UDF_EXEC_ARGS);
+DllExport void Json_Array_deinit(UDF_INIT*);
+
+DllExport my_bool Json_Array_Add_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport char *Json_Array_Add(UDF_EXEC_ARGS);
+DllExport void Json_Array_Add_deinit(UDF_INIT*);
+
+DllExport my_bool Json_Array_Delete_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport char *Json_Array_Delete(UDF_EXEC_ARGS);
+DllExport void Json_Array_Delete_deinit(UDF_INIT*);
+
+DllExport my_bool Json_Object_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport char *Json_Object(UDF_EXEC_ARGS);
+DllExport void Json_Object_deinit(UDF_INIT*);
+
+DllExport my_bool Json_Object_Nonull_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport char *Json_Object_Nonull(UDF_EXEC_ARGS);
+DllExport void Json_Object_Nonull_deinit(UDF_INIT*);
+
+DllExport my_bool Json_Array_Grp_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport void Json_Array_Grp_add(UDF_INIT *, UDF_ARGS *, char *, char *);
+DllExport char *Json_Array_Grp(UDF_EXEC_ARGS);
+DllExport void Json_Array_Grp_clear(UDF_INIT *, char *, char *);
+DllExport void Json_Array_Grp_deinit(UDF_INIT*);
+
+DllExport my_bool Json_Object_Grp_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport void Json_Object_Grp_add(UDF_INIT *, UDF_ARGS *, char *, char *);
+DllExport char *Json_Object_Grp(UDF_EXEC_ARGS);
+DllExport void Json_Object_Grp_clear(UDF_INIT *, char *, char *);
+DllExport void Json_Object_Grp_deinit(UDF_INIT*);
+} // extern "C"
+
+/***********************************************************************/
+/* Allocate and initialise the memory area. */
+/***********************************************************************/
+static my_bool JsonInit(UDF_INIT *initid, char *message,
+ unsigned long reslen, unsigned long memlen)
+{
+ PGLOBAL g = PlugInit(NULL, memlen);
+
+ if (!g) {
+ strcpy(message, "Allocation error");
+ return true;
+ } else if (g->Sarea_Size == 0) {
+ strcpy(message, g->Message);
+ PlugExit(g);
+ return true;
+ } else
+ initid->ptr = (char*)g;
+
+ initid->maybe_null = false;
+ initid->max_length = reslen;
+ return false;
+} // end of Json_Object_init
+
+/***********************************************************************/
+/* Returns true if the argument is a JSON string. */
+/***********************************************************************/
+static my_bool IsJson(UDF_ARGS *args, int i)
+{
+ return (args->arg_type[i] == STRING_RESULT &&
+ !strnicmp(args->attributes[i], "Json_", 5));
+} // end of IsJson
+
+/***********************************************************************/
+/* Calculate the reslen and memlen needed by a function. */
+/***********************************************************************/
+static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
+ unsigned long& reslen, unsigned long& memlen)
+{
+ unsigned long i, k;
+ reslen = args->arg_count + 2;
+
+ // Calculate the result max length
+ for (i = 0; i < args->arg_count; i++) {
+ if (obj) {
+ if (!(k = args->attribute_lengths[i]))
+ k = strlen(args->attributes[i]);
+
+ reslen += (k + 3); // For quotes and :
+ } // endif obj
+
+ switch (args->arg_type[i]) {
+ case STRING_RESULT:
+ if (IsJson(args, i))
+ reslen += args->lengths[i];
+ else
+ reslen += (args->lengths[i] + 1) * 2; // Pessimistic !
+
+ break;
+ case INT_RESULT:
+ reslen += 20;
+ break;
+ case REAL_RESULT:
+ reslen += 31;
+ break;
+ case DECIMAL_RESULT:
+ reslen += (args->lengths[i] + 7); // 6 decimals
+ break;
+ case TIME_RESULT:
+ case ROW_RESULT:
+ case IMPOSSIBLE_RESULT:
+ default:
+ // What should we do here ?
+ break;
+ } // endswitch arg_type
+
+ } // endfor i
+
+ // Calculate the amount of memory needed
+ memlen = MEMFIX + sizeof(JOUTSTR) + reslen;
+
+ for (i = 0; i < args->arg_count; i++) {
+ memlen += (args->lengths[i] + sizeof(JVALUE));
+
+ if (obj) {
+ if (!(k = args->attribute_lengths[i]))
+ k = strlen(args->attributes[i]);
+
+ memlen += (k + sizeof(JOBJECT) + sizeof(JPAIR));
+ } else
+ memlen += sizeof(JARRAY);
+
+ switch (args->arg_type[i]) {
+ case STRING_RESULT:
+ if (IsJson(args, i))
+ memlen += args->lengths[i] * 5; // Estimate parse memory
+
+ memlen += sizeof(TYPVAL<PSZ>);
+ break;
+ case INT_RESULT:
+ memlen += sizeof(TYPVAL<int>);
+ break;
+ case REAL_RESULT:
+ case DECIMAL_RESULT:
+ memlen += sizeof(TYPVAL<double>);
+ break;
+ case TIME_RESULT:
+ case ROW_RESULT:
+ case IMPOSSIBLE_RESULT:
+ default:
+ // What should we do here ?
+ break;
+ } // endswitch arg_type
+
+ } // endfor i
+
+ return false;
+} // end of CalcLen
+
+/***********************************************************************/
+/* Make a zero terminated string from the passed argument. */
+/***********************************************************************/
+static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i)
+{
+ if (args->args[i]) {
+ int n = args->lengths[i];
+ PSZ s = (PSZ)PlugSubAlloc(g, NULL, n + 1);
+
+ memcpy(s, args->args[i], n);
+ s[n] = 0;
+ return s;
+ } else
+ return NULL;
+
+} // end of MakePSZ
+
+/***********************************************************************/
+/* Make a valid key from the passed argument. */
+/***********************************************************************/
+static PSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
+{
+ int n = args->attribute_lengths[i];
+ bool b; // true if attribute is zero terminated
+ PSZ p, s = args->attributes[i];
+
+ if (s && *s && (n || *s == '\'')) {
+ if ((b = (!n || !s[n])))
+ n = strlen(s);
+
+ if (n > 5 && IsJson(args, i)) {
+ s += 5;
+ n -= 5;
+ } else if (*s == '\'' && s[n-1] == '\'') {
+ s++;
+ n -= 2;
+ b = false;
+ } // endif *s
+
+ if (n < 1)
+ return "Key";
+
+ if (!b) {
+ p = (PSZ)PlugSubAlloc(g, NULL, n + 1);
+ memcpy(p, s, n);
+ p[n] = 0;
+ s = p;
+ } // endif b
+
+ } // endif s
+
+ return s;
+} // end of MakeKey
+
+/***********************************************************************/
+/* Make a JSON value from the passed argument. */
+/***********************************************************************/
+static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, int i)
+{
+ char *sap = (args->arg_count > (unsigned)i) ? args->args[i] : NULL;
+ PJSON jsp;
+ PJVAL jvp = new(g) JVALUE;
+
+ if (sap) switch (args->arg_type[i]) {
+ case STRING_RESULT:
+ if (args->lengths[i]) {
+ if (IsJson(args, i)) {
+ if (!(jsp = ParseJson(g, sap, args->lengths[i], 0)))
+ push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
+ g->Message);
+
+ if (jsp && jsp->GetType() == TYPE_JVAL)
+ jvp = (PJVAL)jsp;
+ else
+ jvp->SetValue(jsp);
+
+ } else
+ jvp->SetString(g, MakePSZ(g, args, i));
+
+ } // endif str
+
+ break;
+ case INT_RESULT:
+ jvp->SetInteger(g, *(int*)sap);
+ break;
+ case REAL_RESULT:
+ jvp->SetFloat(g, *(double*)sap);
+ break;
+ case DECIMAL_RESULT:
+ jvp->SetFloat(g, atof(MakePSZ(g, args, i)));
+ break;
+ case TIME_RESULT:
+ case ROW_RESULT:
+ case IMPOSSIBLE_RESULT:
+ default:
+ break;
+ } // endswitch arg_type
+
+ return jvp;
+} // end of MakeValue
+
+/***********************************************************************/
+/* Make a Json value containing the parameter. */
+/***********************************************************************/
+my_bool Json_Value_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ if (args->arg_count > 1) {
+ strcpy(message, "Json_Value cannot accept more than 1 argument");
+ return true;
+ } else
+ CalcLen(args, false, reslen, memlen);
+
+ return JsonInit(initid, message, reslen, memlen);
+} // end of Json_Value_init
+
+char *Json_Value(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *, char *)
+{
+ char *str;
+ PJVAL jvp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ jvp = MakeValue(g, args, 0);
+
+ if (!(str = Serialize(g, jvp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Value
+
+void Json_Value_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Value_deinit
+
+/***********************************************************************/
+/* Make a Json array containing all the parameters. */
+/***********************************************************************/
+my_bool Json_Array_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ CalcLen(args, false, reslen, memlen);
+ return JsonInit(initid, message, reslen, memlen);
+} // end of Json_Array_init
+
+char *Json_Array(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *, char *)
+{
+ char *str;
+ uint i;
+ PJAR arp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ arp = new(g) JARRAY;
+
+ for (i = 0; i < args->arg_count; i++)
+ arp->AddValue(g, MakeValue(g, args, i));
+
+ arp->InitArray(g);
+
+ if (!(str = Serialize(g, arp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Array
+
+void Json_Array_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Array_deinit
+
+/***********************************************************************/
+/* Add values to a Json array. */
+/***********************************************************************/
+my_bool Json_Array_Add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ if (args->arg_count < 2) {
+ strcpy(message, "Json_Value_Add must have at least 2 arguments");
+ return true;
+ } else if (!IsJson(args, 0)) {
+ strcpy(message, "Json_Value_Add first argument must be a json item");
+ return true;
+ } else
+ CalcLen(args, false, reslen, memlen);
+
+ return JsonInit(initid, message, reslen, memlen);
+} // end of Json_Array_Add_init
+
+char *Json_Array_Add(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *, char *)
+{
+ char *str;
+ PJVAL jvp;
+ PJAR arp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ jvp = MakeValue(g, args, 0);
+
+ if (jvp->GetValType() != TYPE_JAR) {
+ arp = new(g) JARRAY;
+ arp->AddValue(g, jvp);
+ } else
+ arp = jvp->GetArray();
+
+ for (uint i = 1; i < args->arg_count; i++)
+ arp->AddValue(g, MakeValue(g, args, i));
+
+ arp->InitArray(g);
+
+ if (!(str = Serialize(g, arp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Array_Add
+
+void Json_Array_Add_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Array_Add_deinit
+
+/***********************************************************************/
+/* Delete a value from a Json array. */
+/***********************************************************************/
+my_bool Json_Array_Delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ if (args->arg_count != 2) {
+ strcpy(message, "Json_Value_Delete must have 2 arguments");
+ return true;
+ } else if (!IsJson(args, 0)) {
+ strcpy(message, "Json_Value_Delete first argument must be a json item");
+ return true;
+ } else
+ CalcLen(args, false, reslen, memlen);
+
+ return JsonInit(initid, message, reslen, memlen);
+} // end of Json_Array_Delete_init
+
+char *Json_Array_Delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *, char *)
+{
+ char *str;
+ int n;
+ PJVAL jvp;
+ PJAR arp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ jvp = MakeValue(g, args, 0);
+
+ if (jvp->GetValType() != TYPE_JAR) {
+ push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
+ "First argument is not an array");
+ str = args->args[0];
+ } else if (args->arg_type[1] != INT_RESULT) {
+ push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
+ "Second argument is not an integer");
+ str = args->args[0];
+ } else {
+ n = *(int*)args->args[1];
+ arp = jvp->GetArray();
+ arp->DeleteValue(n);
+ arp->InitArray(g);
+
+ if (!(str = Serialize(g, arp, NULL, 0))) {
+ str = strcpy(result, g->Message);
+ push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0, str);
+ } // endif str
+
+ } // endif's
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Array_Delete
+
+void Json_Array_Delete_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Array_Delete_deinit
+
+/***********************************************************************/
+/* Make a Json Oject containing all the parameters. */
+/***********************************************************************/
+my_bool Json_Object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ CalcLen(args, true, reslen, memlen);
+ return JsonInit(initid, message, reslen, memlen);
+} // end of Json_Object_init
+
+char *Json_Object(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *, char *)
+{
+ char *str;
+ uint i;
+ PJOB objp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ objp = new(g) JOBJECT;
+
+ for (i = 0; i < args->arg_count; i++)
+ objp->SetValue(g, MakeValue(g, args, i), MakeKey(g, args, i));
+
+ if (!(str = Serialize(g, objp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Object
+
+void Json_Object_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Object_deinit
+
+/***********************************************************************/
+/* Make a Json Oject containing all not null parameters. */
+/***********************************************************************/
+my_bool Json_Object_Nonull_init(UDF_INIT *initid, UDF_ARGS *args,
+ char *message)
+{
+ unsigned long reslen, memlen;
+
+ CalcLen(args, true, reslen, memlen);
+ return JsonInit(initid, message, reslen, memlen);
+} // end of Json_Object_Nonull_init
+
+char *Json_Object_Nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *, char *)
+{
+ char *str;
+ uint i;
+ PJOB objp;
+ PJVAL jvp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ objp = new(g) JOBJECT;
+
+ for (i = 0; i < args->arg_count; i++)
+ if (!(jvp = MakeValue(g, args, i))->IsNull())
+ objp->SetValue(g, jvp, MakeKey(g, args, i));
+
+ if (!(str = Serialize(g, objp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Object_Nonull
+
+void Json_Object_Nonull_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Object_nonull_deinit
+
+/***********************************************************************/
+/* Make a Json array from values comming from rows. */
+/***********************************************************************/
+my_bool Json_Array_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen, n = GetJsonGrpSize();
+
+ if (args->arg_count != 1) {
+ strcpy(message, "Json_Array_Grp can only accept 1 argument");
+ return true;
+ } else
+ CalcLen(args, false, reslen, memlen);
+
+ reslen *= n;
+ memlen += ((memlen - MEMFIX) * (n - 1));
+
+ if (JsonInit(initid, message, reslen, memlen))
+ return true;
+
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ g->Activityp = (PACTIVITY)new(g) JARRAY;
+ g->N = (int)n;
+ return false;
+} // end of Json_Array_Grp_init
+
+void Json_Array_Grp_add(UDF_INIT *initid, UDF_ARGS *args, char*, char*)
+{
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PJAR arp = (PJAR)g->Activityp;
+
+ if (g->N-- > 0)
+ arp->AddValue(g, MakeValue(g, args, 0));
+
+} // end of Json_Array_Grp_add
+
+char *Json_Array_Grp(UDF_INIT *initid, UDF_ARGS *, char *result,
+ unsigned long *res_length, char *, char *)
+{
+ char *str;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PJAR arp = (PJAR)g->Activityp;
+
+ if (g->N < 0)
+ push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
+ "Result truncated to json_grp_size values");
+
+ arp->InitArray(g);
+
+ if (!(str = Serialize(g, arp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Array_Grp
+
+void Json_Array_Grp_clear(UDF_INIT *initid, char*, char*)
+{
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ g->Activityp = (PACTIVITY)new(g) JARRAY;
+ g->N = GetJsonGrpSize();
+} // end of Json_Array_Grp_clear
+
+void Json_Array_Grp_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Array_Grp_deinit
+
+/***********************************************************************/
+/* Make a Json object from values comming from rows. */
+/***********************************************************************/
+my_bool Json_Object_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen, n = GetJsonGrpSize();
+
+ if (args->arg_count != 2) {
+ strcpy(message, "Json_Array_Grp can only accept 2 arguments");
+ return true;
+ } else
+ CalcLen(args, true, reslen, memlen);
+
+ reslen *= n;
+ memlen += ((memlen - MEMFIX) * (n - 1));
+
+ if (JsonInit(initid, message, reslen, memlen))
+ return true;
+
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ g->Activityp = (PACTIVITY)new(g) JOBJECT;
+ g->N = (int)n;
+ return false;
+} // end of Json_Object_Grp_init
+
+void Json_Object_Grp_add(UDF_INIT *initid, UDF_ARGS *args, char*, char*)
+{
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PJOB objp = (PJOB)g->Activityp;
+
+ if (g->N-- > 0)
+ objp->SetValue(g, MakeValue(g, args, 0), MakePSZ(g, args, 1));
+
+} // end of Json_Object_Grp_add
+
+char *Json_Object_Grp(UDF_INIT *initid, UDF_ARGS *, char *result,
+ unsigned long *res_length, char *, char *)
+{
+ char *str;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PJOB objp = (PJOB)g->Activityp;
+
+ if (g->N < 0)
+ push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
+ "Result truncated to json_grp_size values");
+
+ if (!(str = Serialize(g, objp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Object_Grp
+
+void Json_Object_Grp_clear(UDF_INIT *initid, char*, char*)
+{
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ g->Activityp = (PACTIVITY)new(g) JOBJECT;
+ g->N = GetJsonGrpSize();
+} // end of Json_Object_Grp_clear
+
+void Json_Object_Grp_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Object_Grp_deinit
+
+
diff --git a/storage/connect/libdoc.cpp b/storage/connect/libdoc.cpp
index e576c1cf5fa..c2882fc0d7c 100644
--- a/storage/connect/libdoc.cpp
+++ b/storage/connect/libdoc.cpp
@@ -1,6 +1,6 @@
/******************************************************************/
/* Implementation of XML document processing using libxml2 */
-/* Author: Olivier Bertrand 2007-2013 */
+/* Author: Olivier Bertrand 2007-2015 */
/******************************************************************/
#include "my_global.h"
#include <string.h>
@@ -162,10 +162,12 @@ class XML2ATTR : public XMLATTRIBUTE {
friend class XML2NODE;
public:
// Properties
-//virtual char *GetText(void);
+ virtual char *GetName(PGLOBAL g) {return (char*)Atrp->name;}
+ virtual PXATTR GetNext(PGLOBAL g);
// Methods
- virtual bool SetText(PGLOBAL g, char *txtp, int len);
+ virtual RCODE GetText(PGLOBAL g, char *bufp, int len);
+ virtual bool SetText(PGLOBAL g, char *txtp, int len);
protected:
// Constructor
@@ -408,8 +410,7 @@ PFBLOCK LIBXMLDOC::LinkXblock(PGLOBAL g, MODE m, int rc, char *fn)
xp->Next = (PX2BLOCK)dup->Openlist;
dup->Openlist = (PFBLOCK)xp;
xp->Type = TYPE_FB_XML2;
- xp->Fname = (LPCSTR)PlugSubAlloc(g, NULL, strlen(fn) + 1);
- strcpy((char*)xp->Fname, fn);
+ xp->Fname = (LPCSTR)PlugDup(g, fn);
xp->Count = 1;
xp->Length = (m == MODE_READ) ? 1 : 0;
xp->Retcode = rc;
@@ -532,8 +533,8 @@ int LIBXMLDOC::DumpDoc(PGLOBAL g, char *ofn)
// This function does not crash (
if (xmlSaveFormatFileEnc((const char *)ofn, Docp, Encoding, 0) < 0) {
xmlErrorPtr err = xmlGetLastError();
-
strcpy(g->Message, (err) ? err->message : "Error saving XML doc");
+ xmlResetError(Xerr);
rc = -1;
} // endif Save
// rc = xmlDocDump(of, Docp);
@@ -568,6 +569,7 @@ void LIBXMLDOC::CloseDoc(PGLOBAL g, PFBLOCK xp)
htrc("CloseDoc: xp=%p count=%d\n", xp, (xp) ? xp->Count : 0);
//if (xp && xp->Count == 1) {
+ if (xp) {
if (Nlist) {
xmlXPathFreeNodeSet(Nlist);
@@ -604,7 +606,7 @@ void LIBXMLDOC::CloseDoc(PGLOBAL g, PFBLOCK xp)
Ctxp = NULL;
} // endif Ctxp
-// } // endif Count
+ } // endif xp
CloseXML2File(g, xp, false);
} // end of Close
@@ -813,7 +815,7 @@ PXNODE XML2NODE::GetNext(PGLOBAL g)
if (!Nodep->next)
Next = NULL;
- else if (!Next)
+ else // if (!Next)
Next = new(g) XML2NODE(Doc, Nodep->next);
return Next;
@@ -829,7 +831,7 @@ PXNODE XML2NODE::GetChild(PGLOBAL g)
if (!Nodep->children)
Children = NULL;
- else if (!Children)
+ else // if (!Children)
Children = new(g) XML2NODE(Doc, Nodep->children);
return Children;
@@ -979,10 +981,16 @@ PXNODE XML2NODE::SelectSingleNode(PGLOBAL g, char *xp, PXNODE np)
/******************************************************************/
PXATTR XML2NODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap)
{
+ xmlAttrPtr atp;
+
if (trace)
- htrc("GetAttribute: %s\n", name);
+ htrc("GetAttribute: %s\n", SVP(name));
+
+ if (name)
+ atp = xmlHasProp(Nodep, BAD_CAST name);
+ else
+ atp = Nodep->properties;
- xmlAttrPtr atp = xmlHasProp(Nodep, BAD_CAST name);
if (atp) {
if (ap) {
@@ -1211,6 +1219,52 @@ XML2ATTR::XML2ATTR(PXDOC dp, xmlAttrPtr ap, xmlNodePtr np)
} // end of XML2ATTR constructor
/******************************************************************/
+/* Return the next sibling of the attribute. */
+/******************************************************************/
+PXATTR XML2ATTR::GetNext(PGLOBAL g)
+ {
+ if (trace)
+ htrc("Attr GetNext\n");
+
+ if (!Atrp->next)
+ return NULL;
+ else
+ return new(g) XML2ATTR(Doc, Atrp->next, Atrp->parent);
+
+ } // end of GetNext
+
+/******************************************************************/
+/* Return the text of an attribute. */
+/******************************************************************/
+RCODE XML2ATTR::GetText(PGLOBAL g, char *buf, int len)
+ {
+ RCODE rc = RC_OK;
+ xmlChar *txt;
+
+ if (trace)
+ htrc("GetText\n");
+
+ if ((txt = xmlGetProp(Atrp->parent, Atrp->name))) {
+ // Copy the text to the buffer
+ if (strlen((char*)txt) >= (unsigned)len) {
+ memcpy(buf, txt, len - 1);
+ buf[len - 1] = 0;
+ sprintf(g->Message, "Truncated %s content", Atrp->name);
+ rc = RC_INFO;
+ } else
+ strcpy(buf, (const char*)txt);
+
+ xmlFree(txt);
+ } else
+ *buf = '\0';
+
+ if (trace)
+ htrc("GetText: %s\n", buf);
+
+ return rc;
+ } // end of GetText
+
+/******************************************************************/
/* Set the content of an attribute. */
/******************************************************************/
bool XML2ATTR::SetText(PGLOBAL g, char *txtp, int len)
diff --git a/storage/connect/macutil.cpp b/storage/connect/macutil.cpp
index 4d3022b91b6..f5d3bb11fe9 100644
--- a/storage/connect/macutil.cpp
+++ b/storage/connect/macutil.cpp
@@ -2,11 +2,11 @@
/* MACUTIL: Author Olivier Bertrand -- 2008-2012 */
/* From the article and sample code by Khalid Shaikh. */
/***********************************************************************/
-#if defined(WIN32)
+#if defined(__WIN__)
#include "my_global.h"
-#else // !WIN32
-#error This is WIN32 only DLL
-#endif // !WIN32
+#else // !__WIN__
+#error This is WINDOWS only DLL
+#endif // !__WIN__
#include "global.h"
#include "plgdbsem.h"
#include "macutil.h"
diff --git a/storage/connect/macutil.h b/storage/connect/macutil.h
index 8a3e97e12e1..c80bd58e20a 100644
--- a/storage/connect/macutil.h
+++ b/storage/connect/macutil.h
@@ -1,10 +1,10 @@
// MACUTIL.H Olivier Bertrand 2008-2012
// Get Mac Addresses via GetAdaptersInfo
-#if defined(WIN32)
+#if defined(__WIN__)
#include <iphlpapi.h>
-#else // !WIN32
-#error This is WIN32 only
-#endif // !WIN32
+#else // !__WIN__
+#error This is WINDOWS only
+#endif // !__WIN__
#include "block.h"
typedef class MACINFO *MACIP;
diff --git a/storage/connect/maputil.cpp b/storage/connect/maputil.cpp
index 97c638b4254..c4e016f1511 100644
--- a/storage/connect/maputil.cpp
+++ b/storage/connect/maputil.cpp
@@ -14,7 +14,7 @@
#include "plgdbsem.h"
#include "maputil.h"
-#ifdef WIN32
+#ifdef __WIN__
/***********************************************************************/
/* In Insert mode, just open the file for append. Otherwise */
/* create the mapping file object. The map handle can be released */
diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc
index 0ae0537ba6f..9c72e9cd665 100644
--- a/storage/connect/mycat.cc
+++ b/storage/connect/mycat.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2014
+/* Copyright (C) Olivier Bertrand 2004 - 2015
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
@@ -18,7 +18,7 @@
/* ------------- */
/* Version 1.4 */
/* */
-/* Author: Olivier Bertrand 2012 - 2014 */
+/* Author: Olivier Bertrand 2012 - 2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -30,7 +30,7 @@
/***********************************************************************/
#include <my_config.h>
-#if defined(WIN32)
+#if defined(__WIN__)
//#include <windows.h>
//#include <sqlext.h>
#elif defined(UNIX)
@@ -66,21 +66,16 @@
#include "tabfmt.h"
#include "tabvct.h"
#include "tabsys.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include "tabmac.h"
#include "tabwmi.h"
-#endif // WIN32
+#endif // __WIN__
//#include "tabtbl.h"
#include "tabxcl.h"
#include "tabtbl.h"
#include "taboccur.h"
-#if defined(XML_SUPPORT)
-#include "tabxml.h"
-#endif // XML_SUPPORT
#include "tabmul.h"
-#if defined(MYSQL_SUPPORT)
#include "tabmysql.h"
-#endif // MYSQL_SUPPORT
#if defined(ODBC_SUPPORT)
#define NODBC
#include "tabodbc.h"
@@ -91,18 +86,40 @@
#include "tabvir.h"
#include "tabjson.h"
#include "ha_connect.h"
-#include "mycat.h"
+#if defined(XML_SUPPORT)
+#include "tabxml.h"
+#endif // XML_SUPPORT
/***********************************************************************/
/* Extern static variables. */
/***********************************************************************/
-#if defined(WIN32)
+#if defined(__WIN__)
extern "C" HINSTANCE s_hModule; // Saved module handle
-#endif // !WIN32
+#endif // !__WIN__
PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
/***********************************************************************/
+/* Get the plugin directory. */
+/***********************************************************************/
+char *GetPluginDir(void)
+{
+ char *plugin_dir;
+
+#if defined(_WIN64)
+ plugin_dir = (char *)GetProcAddress(GetModuleHandle(NULL),
+ "?opt_plugin_dir@@3PADEA");
+#elif defined(_WIN32)
+ plugin_dir = (char*)GetProcAddress(GetModuleHandle(NULL),
+ "?opt_plugin_dir@@3PADA");
+#else
+ plugin_dir = opt_plugin_dir;
+#endif
+
+ return plugin_dir;
+} // end of GetPluginDir
+
+/***********************************************************************/
/* Get a unique enum table type ID. */
/***********************************************************************/
TABTYPE GetTypeID(const char *type)
@@ -122,12 +139,10 @@ TABTYPE GetTypeID(const char *type)
#ifdef ODBC_SUPPORT
: (!stricmp(type, "ODBC")) ? TAB_ODBC
#endif
-#ifdef MYSQL_SUPPORT
: (!stricmp(type, "MYSQL")) ? TAB_MYSQL
: (!stricmp(type, "MYPRX")) ? TAB_MYSQL
-#endif
: (!stricmp(type, "DIR")) ? TAB_DIR
-#ifdef WIN32
+#ifdef __WIN__
: (!stricmp(type, "MAC")) ? TAB_MAC
: (!stricmp(type, "WMI")) ? TAB_WMI
#endif
@@ -333,12 +348,12 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
{
typedef PQRYRES (__stdcall *XCOLDEF) (PGLOBAL, void*, char*, char*, bool);
const char *module, *subtype;
- char c, getname[40] = "Col";
-#if defined(WIN32)
+ char c, soname[_MAX_PATH], getname[40] = "Col";
+#if defined(__WIN__)
HANDLE hdll; /* Handle to the external DLL */
-#else // !WIN32
+#else // !__WIN__
void *hdll; /* Handle for the loaded shared library */
-#endif // !WIN32
+#endif // !__WIN__
XCOLDEF coldef = NULL;
PQRYRES qrp = NULL;
@@ -348,6 +363,17 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
if (!module || !subtype)
return NULL;
+ /*********************************************************************/
+ /* Ensure that the .dll doesn't have a path. */
+ /* This is done to ensure that only approved dll from the system */
+ /* directories are used (to make this even remotely secure). */
+ /*********************************************************************/
+ if (check_valid_path(module, strlen(module))) {
+ strcpy(g->Message, "Module cannot contain a path");
+ return NULL;
+ } else
+ PlugSetPath(soname, module, GetPluginDir());
+
// The exported name is always in uppercase
for (int i = 0; ; i++) {
c = subtype[i];
@@ -355,13 +381,13 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
if (!c) break;
} // endfor i
-#if defined(WIN32)
+#if defined(__WIN__)
// Load the Dll implementing the table
- if (!(hdll = LoadLibrary(module))) {
+ if (!(hdll = LoadLibrary(soname))) {
char buf[256];
DWORD rc = GetLastError();
- sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, module);
+ sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
(LPTSTR)buf, sizeof(buf), NULL);
@@ -375,13 +401,13 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
FreeLibrary((HMODULE)hdll);
return NULL;
} // endif coldef
-#else // !WIN32
+#else // !__WIN__
const char *error = NULL;
// Load the desired shared library
- if (!(hdll = dlopen(module, RTLD_LAZY))) {
+ if (!(hdll = dlopen(soname, RTLD_LAZY))) {
error = dlerror();
- sprintf(g->Message, MSG(SHARED_LIB_ERR), module, SVP(error));
+ sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
return NULL;
} // endif Hdll
@@ -392,7 +418,7 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
dlclose(hdll);
return NULL;
} // endif coldef
-#endif // !WIN32
+#endif // !__WIN__
// Just in case the external Get function does not set error messages
sprintf(g->Message, "Error getting column info from %s", subtype);
@@ -400,11 +426,11 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
// Get the table column definition
qrp = coldef(g, topt, tab, db, info);
-#if defined(WIN32)
+#if defined(__WIN__)
FreeLibrary((HMODULE)hdll);
-#else // !WIN32
+#else // !__WIN__
dlclose(hdll);
-#endif // !WIN32
+#endif // !__WIN__
return qrp;
} // end of OEMColumns
@@ -416,11 +442,11 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
/***********************************************************************/
CATALOG::CATALOG(void)
{
-#if defined(WIN32)
+#if defined(__WIN__)
//DataPath= ".\\";
-#else // !WIN32
+#else // !__WIN__
//DataPath= "./";
-#endif // !WIN32
+#endif // !__WIN__
memset(&Ctb, 0, sizeof(CURTAB));
Cbuf= NULL;
Cblen= 0;
@@ -463,11 +489,11 @@ void MYCAT::SetPath(PGLOBAL g, LPCSTR *datapath, const char *path)
}
if (*path != '.') {
-#if defined(WIN32)
+#if defined(__WIN__)
char *s= "\\";
-#else // !WIN32
+#else // !__WIN__
char *s= "/";
-#endif // !WIN32
+#endif // !__WIN__
strcat(strcat(strcat(strcpy(buf, "."), s), path), s);
} else
strcpy(buf, path);
@@ -483,7 +509,7 @@ void MYCAT::SetPath(PGLOBAL g, LPCSTR *datapath, const char *path)
/* Look for a table descriptor matching the name and type. */
/***********************************************************************/
PRELDEF MYCAT::GetTableDesc(PGLOBAL g, LPCSTR name,
- LPCSTR type, PRELDEF *prp)
+ LPCSTR type, PRELDEF *)
{
if (trace)
printf("GetTableDesc: name=%s am=%s\n", name, SVP(type));
@@ -528,18 +554,16 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am)
#if defined(ODBC_SUPPORT)
case TAB_ODBC: tdp= new(g) ODBCDEF; break;
#endif // ODBC_SUPPORT
-#if defined(WIN32)
+#if defined(__WIN__)
case TAB_MAC: tdp= new(g) MACDEF; break;
case TAB_WMI: tdp= new(g) WMIDEF; break;
-#endif // WIN32
+#endif // __WIN__
case TAB_OEM: tdp= new(g) OEMDEF; break;
case TAB_TBL: tdp= new(g) TBLDEF; break;
case TAB_XCL: tdp= new(g) XCLDEF; break;
case TAB_PRX: tdp= new(g) PRXDEF; break;
case TAB_OCCUR: tdp= new(g) OCCURDEF; break;
-#if defined(MYSQL_SUPPORT)
case TAB_MYSQL: tdp= new(g) MYSQLDEF; break;
-#endif // MYSQL_SUPPORT
#if defined(PIVOT_SUPPORT)
case TAB_PIVOT: tdp= new(g) PIVOTDEF; break;
#endif // PIVOT_SUPPORT
@@ -596,7 +620,7 @@ PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type)
/***********************************************************************/
/* ClearDB: Terminates Database usage. */
/***********************************************************************/
-void MYCAT::ClearDB(PGLOBAL g)
+void MYCAT::ClearDB(PGLOBAL)
{
} // end of ClearDB
diff --git a/storage/connect/mycat.h b/storage/connect/mycat.h
index 1aaee4ed1e8..d4024e6b6c3 100644
--- a/storage/connect/mycat.h
+++ b/storage/connect/mycat.h
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2013
+/* Copyright (C) Olivier Bertrand 2004 - 2015
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
@@ -24,6 +24,46 @@
#include "block.h"
#include "catalog.h"
+//typedef struct ha_table_option_struct TOS, *PTOS;
+
+/**
+ structure for CREATE TABLE options (table options)
+
+ These can be specified in the CREATE TABLE:
+ CREATE TABLE ( ... ) {...here...}
+*/
+struct ha_table_option_struct {
+ const char *type;
+ const char *filename;
+ const char *optname;
+ const char *tabname;
+ const char *tablist;
+ const char *dbname;
+ const char *separator;
+//const char *connect;
+ const char *qchar;
+ const char *module;
+ const char *subtype;
+ const char *catfunc;
+ const char *srcdef;
+ const char *colist;
+ const char *oplist;
+ const char *data_charset;
+ ulonglong lrecl;
+ ulonglong elements;
+//ulonglong estimate;
+ ulonglong multiple;
+ ulonglong header;
+ ulonglong quoted;
+ ulonglong ending;
+ ulonglong compressed;
+ bool mapped;
+ bool huge;
+ bool split;
+ bool readonly;
+ bool sepindex;
+ };
+
// Possible value for catalog functions
#define FNC_NO (1 << 0) // Not a catalog table
#define FNC_COL (1 << 1) // Column catalog function
@@ -58,7 +98,7 @@ class MYCAT : public CATALOG {
void Reset(void);
//void SetDataPath(PGLOBAL g, const char *path)
// {SetPath(g, &DataPath, path);}
- bool StoreIndex(PGLOBAL g, PTABDEF defp) {return false;} // Temporary
+ bool StoreIndex(PGLOBAL, PTABDEF) {return false;} // Temporary
PRELDEF GetTableDesc(PGLOBAL g, LPCSTR name,
LPCSTR type, PRELDEF *prp = NULL);
PTDB GetTable(PGLOBAL g, PTABLE tablep,
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index 2f3d75b52fa..ada0109a820 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2007-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2007-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -35,11 +35,11 @@
#include "my_sys.h"
#include "mysqld_error.h"
#endif // !MYSQL_PREPARED_STATEMENTS
-#if defined(WIN32)
+#if defined(__WIN__)
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#include "osutil.h"
-#endif // !WIN32
+#endif // !__WIN__
#include "global.h"
#include "plgdbsem.h"
@@ -51,7 +51,8 @@
#define DLL_EXPORT // Items are exported from this DLL
#include "myconn.h"
-extern "C" int zconv;
+//extern "C" int zconv;
+int GetConvSize(void);
extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
extern MYSQL_PLUGIN_IMPORT char *mysqld_unix_port;
@@ -265,7 +266,7 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
return NULL;
} else if (type == TYPE_STRING) {
if (v == 'X') {
- len = zconv;
+ len = GetConvSize();
sprintf(g->Message, "Column %s converted to varchar(%d)",
colname, len);
PushWarning(g, thd);
@@ -450,15 +451,15 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db,
mysql_options(m_DB, MYSQL_OPT_READ_TIMEOUT, &nrt);
//mysql_options(m_DB, MYSQL_OPT_WRITE_TIMEOUT, ...);
-#if defined(WIN32)
+#if defined(__WIN__)
if (!strcmp(host, ".")) {
mysql_options(m_DB, MYSQL_OPT_NAMED_PIPE, NULL);
pipe = mysqld_unix_port;
} // endif host
-#else // !WIN32
+#else // !__WIN__
if (!strcmp(host, "localhost"))
pipe = mysqld_unix_port;
-#endif // !WIN32
+#endif // !__WIN__
#if 0
if (pwd && !strcmp(pwd, "*")) {
@@ -719,7 +720,7 @@ int MYSQLC::ExecSQL(PGLOBAL g, const char *query, int *w)
/***********************************************************************/
/* Get table size by executing "select count(*) from table_name". */
/***********************************************************************/
-int MYSQLC::GetTableSize(PGLOBAL g, PSZ query)
+int MYSQLC::GetTableSize(PGLOBAL g __attribute__((unused)), PSZ query)
{
if (mysql_real_query(m_DB, query, strlen(query))) {
#if defined(_DEBUG)
diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h
index 79b8a43fe5a..fa34edd804c 100644
--- a/storage/connect/myconn.h
+++ b/storage/connect/myconn.h
@@ -7,24 +7,24 @@
/* DO NOT define DLL_EXPORT in your application so these items are */
/* declared are imported from the Myconn DLL. */
/***********************************************************************/
-#if defined(WIN32)
+#if defined(__WIN__)
#include <winsock.h>
-#else // !WIN32
+#else // !__WIN__
#include <sys/socket.h>
-#endif // !WIN32
+#endif // !__WIN__
#include <mysql.h>
#include <errmsg.h>
#include "myutil.h"
-#if defined(WIN32) && defined(MYCONN_EXPORTS)
+#if defined(__WIN__) && defined(MYCONN_EXPORTS)
#if defined(DLL_EXPORT)
#define DllItem _declspec(dllexport)
#else // !DLL_EXPORT
#define DllItem _declspec(dllimport)
#endif // !DLL_EXPORT
-#else // !WIN32 || !MYCONN_EXPORTS
+#else // !__WIN__ || !MYCONN_EXPORTS
#define DllItem
-#endif // !WIN32
+#endif // !__WIN__
#define MYSQL_ENABLED 0x00000001
#define MYSQL_LOGON 0x00000002
diff --git a/storage/connect/mysql-test/connect/my.cnf b/storage/connect/mysql-test/connect/my.cnf
index 317e20012ba..6310772d01f 100644
--- a/storage/connect/mysql-test/connect/my.cnf
+++ b/storage/connect/mysql-test/connect/my.cnf
@@ -1,17 +1,17 @@
-# Use default setting for mysqld processes
-!include include/default_mysqld.cnf
-!include include/default_client.cnf
-
-[mysqld.1]
-#log-bin= master-bin
-
-[mysqld.2]
-
-[ENV]
-MASTER_MYPORT= @mysqld.1.port
-MASTER_MYSOCK= @mysqld.1.socket
-
-SLAVE_MYPORT= @mysqld.2.port
-SLAVE_MYSOCK= @mysqld.2.socket
-
-PGCLIENTENCODING= UTF8
+# Use default setting for mysqld processes
+!include include/default_mysqld.cnf
+!include include/default_client.cnf
+
+[mysqld.1]
+#log-bin= master-bin
+
+[mysqld.2]
+
+[ENV]
+MASTER_MYPORT= @mysqld.1.port
+MASTER_MYSOCK= @mysqld.1.socket
+
+SLAVE_MYPORT= @mysqld.2.port
+SLAVE_MYSOCK= @mysqld.2.socket
+
+PGCLIENTENCODING= UTF8
diff --git a/storage/connect/mysql-test/connect/r/bin.result b/storage/connect/mysql-test/connect/r/bin.result
index bbf5614b555..4ba353ac705 100644
--- a/storage/connect/mysql-test/connect/r/bin.result
+++ b/storage/connect/mysql-test/connect/r/bin.result
@@ -14,12 +14,12 @@ SET time_zone='+00:00';
CREATE TABLE t1
(
fig INT(4) NOT NULL FIELD_FORMAT='C',
-name CHAR(10) not null,
+name CHAR(10) NOT NULL,
birth DATE NOT NULL,
id CHAR(5) NOT NULL FIELD_FORMAT='S',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
dept INT(4) NOT NULL FIELD_FORMAT='S'
-) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat';
+) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat' OPTION_LIST='Endian=Little';
SELECT * FROM t1;
fig name birth id salary dept
5500 ARCHIBALD 1980-01-25 3789 4380.50 318
@@ -41,12 +41,12 @@ DROP TABLE t1;
CREATE TABLE t1
(
fig INT(4) NOT NULL FIELD_FORMAT='C',
-name CHAR(10) not null,
+name CHAR(10) NOT NULL,
birth DATE NOT NULL,
id CHAR(5) NOT NULL FIELD_FORMAT='S',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
dept INT(4) NOT NULL FIELD_FORMAT='S'
-) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat';
+) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat' OPTION_LIST='Endian=Little';
INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
ERROR HY000: Table 't1' is read only
ALTER TABLE t1 READONLY=NO;
@@ -59,7 +59,7 @@ t1 CREATE TABLE `t1` (
`id` char(5) NOT NULL `FIELD_FORMAT`='S',
`salary` double(9,2) NOT NULL DEFAULT '0.00' `FIELD_FORMAT`='F',
`dept` int(4) NOT NULL `FIELD_FORMAT`='S'
-) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=BIN `FILE_NAME`='Testbal.dat' `READONLY`=NO
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=BIN `FILE_NAME`='Testbal.dat' `OPTION_LIST`='Endian=Little' `READONLY`=NO
INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
SELECT * FROM t1;
fig name birth id salary dept
@@ -78,7 +78,7 @@ t1 CREATE TABLE `t1` (
`id` char(5) NOT NULL `FIELD_FORMAT`='S',
`salary` double(9,2) NOT NULL DEFAULT '0.00' `FIELD_FORMAT`='F',
`dept` int(4) NOT NULL `FIELD_FORMAT`='S'
-) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=BIN `FILE_NAME`='Testbal.dat' `READONLY`=YES
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=BIN `FILE_NAME`='Testbal.dat' `OPTION_LIST`='Endian=Little' `READONLY`=YES
INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
ERROR HY000: Table 't1' is read only
DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/r/json.result b/storage/connect/mysql-test/connect/r/json.result
index 094bb669d18..acb74c38e26 100644
--- a/storage/connect/mysql-test/connect/r/json.result
+++ b/storage/connect/mysql-test/connect/r/json.result
@@ -12,10 +12,10 @@ TRANSLATION CHAR(32),
TRANSLATOR CHAR(80),
PUBLISHER CHAR(32),
DATEPUB int(4)
-) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
+) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN LANG SUBJECT AUTHOR TITLE TRANSLATION TRANSLATOR PUBLISHER DATEPUB
-9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
+9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
#
@@ -34,10 +34,10 @@ Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
Year int(4) FIELD_FORMAT='DATEPUB'
)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN Language Subject Authors Title Translation Translator Publisher Location Year
-9782212090819 fr applications 2 Construire une application XML Eyrolles Paris 1999
+9782212090819 fr applications 2 Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications 1 XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
#
@@ -57,10 +57,10 @@ Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
Year int(4) FIELD_FORMAT='DATEPUB'
)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
-9782212090819 fr applications Jean-Christophe and François Bernadac and Knab Construire une application XML Eyrolles Paris 1999
+9782212090819 fr applications Jean-Christophe and François Bernadac and Knab Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
#
@@ -80,32 +80,32 @@ Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
Year int(4) FIELD_FORMAT='DATEPUB'
)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
-9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
-9782212090819 fr applications François Knab Construire une application XML Eyrolles Paris 1999
+9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML NULL NULL Eyrolles Paris 1999
+9782212090819 fr applications François Knab Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
UPDATE t1 SET AuthorFN = 'Philippe' WHERE AuthorLN = 'Knab';
SELECT * FROM t1 WHERE ISBN = '9782212090819';
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
-9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
-9782212090819 fr applications Philippe Knab Construire une application XML Eyrolles Paris 1999
+9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML NULL NULL Eyrolles Paris 1999
+9782212090819 fr applications Philippe Knab Construire une application XML NULL NULL Eyrolles Paris 1999
#
# To add an author a new table must be created
#
CREATE TABLE t2 (
FIRSTNAME CHAR(32),
LASTNAME CHAR(32))
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn' OPTION_LIST='Object=[2]:AUTHOR';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json' OPTION_LIST='Object=[1]:AUTHOR';
SELECT * FROM t2;
FIRSTNAME LASTNAME
William J. Pardi
INSERT INTO t2 VALUES('Charles','Dickens');
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
-9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
-9782212090819 fr applications Philippe Knab Construire une application XML Eyrolles Paris 1999
+9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML NULL NULL Eyrolles Paris 1999
+9782212090819 fr applications Philippe Knab Construire une application XML NULL NULL Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
9782840825685 fr applications Charles Dickens XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
@@ -117,7 +117,7 @@ CREATE TABLE t1
(
line char(255)
)
-ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='biblio.jsn';
+ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='biblio.json';
SELECT * FROM t1;
line
[
@@ -178,7 +178,7 @@ WHO CHAR(12),
WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK::EXPENSE:["+"]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK::EXPENSE:[+]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t1;
WHO WEEK WHAT AMOUNT
Joe 3 Beer+Food+Food+Car 69.00
@@ -192,26 +192,70 @@ Janet 4 Car 17.00
Janet 5 Beer+Car+Beer+Food 57.00
DROP TABLE t1;
#
-# Cannot be fully expanded
+# Now it can be fully expanded
#
CREATE TABLE t1 (
WHO CHAR(12),
WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t1;
-ERROR HY000: Got error 174 'Cannot expand more than one array' from CONNECT
+WHO WEEK WHAT AMOUNT
+Joe 3 Beer 18.00
+Joe 3 Food 12.00
+Joe 3 Food 19.00
+Joe 3 Car 20.00
+Joe 4 Beer 19.00
+Joe 4 Beer 16.00
+Joe 4 Food 17.00
+Joe 4 Food 17.00
+Joe 4 Beer 14.00
+Joe 5 Beer 14.00
+Joe 5 Food 12.00
+Beth 3 Beer 16.00
+Beth 4 Food 17.00
+Beth 4 Beer 15.00
+Beth 5 Food 12.00
+Beth 5 Beer 20.00
+Janet 3 Car 19.00
+Janet 3 Food 18.00
+Janet 3 Beer 18.00
+Janet 4 Car 17.00
+Janet 5 Beer 14.00
+Janet 5 Car 12.00
+Janet 5 Beer 19.00
+Janet 5 Food 12.00
+DROP TABLE t1;
+#
+# A table showing many calculated results
+#
+CREATE TABLE t1 (
+WHO CHAR(12) NOT NULL,
+WEEKS CHAR(12) NOT NULL FIELD_FORMAT='WEEK:[", "]:NUMBER',
+SUMS CHAR(64) NOT NULL FIELD_FORMAT='WEEK:["+"]:EXPENSE:[+]:AMOUNT',
+SUM DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[+]:EXPENSE:[+]:AMOUNT',
+AVGS CHAR(64) NOT NULL FIELD_FORMAT='WEEK:["+"]:EXPENSE:[!]:AMOUNT',
+SUMAVG DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[+]:EXPENSE:[!]:AMOUNT',
+AVGSUM DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[!]:EXPENSE:[+]:AMOUNT',
+AVGAVG DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[!]:EXPENSE:[!]:AMOUNT',
+AVERAGE DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[!]:EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
+SELECT * FROM t1;
+WHO WEEKS SUMS SUM AVGS SUMAVG AVGSUM AVGAVG AVERAGE
+Joe 3, 4, 5 69.00+83.00+26.00 178.00 17.25+16.60+13.00 46.85 59.33 15.62 16.18
+Beth 3, 4, 5 16.00+32.00+32.00 80.00 16.00+16.00+16.00 48.00 26.67 16.00 16.00
+Janet 3, 4, 5 55.00+17.00+57.00 129.00 18.33+17.00+14.25 49.58 43.00 16.53 16.12
DROP TABLE t1;
#
# Expand expense in 3 one week tables
#
CREATE TABLE t2 (
WHO CHAR(12),
-WEEK INT(2) FIELD_FORMAT='WEEK:[1]:NUMBER',
-WHAT CHAR(32) FIELD_FORMAT='WEEK:[1]:EXPENSE:[X]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[1]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+WEEK INT(2) FIELD_FORMAT='WEEK:[0]:NUMBER',
+WHAT CHAR(32) FIELD_FORMAT='WEEK:[0]:EXPENSE:[X]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[0]:EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t2;
WHO WEEK WHAT AMOUNT
Joe 3 Beer 18.00
@@ -224,10 +268,10 @@ Janet 3 Food 18.00
Janet 3 Beer 18.00
CREATE TABLE t3 (
WHO CHAR(12),
-WEEK INT(2) FIELD_FORMAT='WEEK:[2]:NUMBER',
-WHAT CHAR(32) FIELD_FORMAT='WEEK:[2]:EXPENSE:[X]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[2]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+WEEK INT(2) FIELD_FORMAT='WEEK:[1]:NUMBER',
+WHAT CHAR(32) FIELD_FORMAT='WEEK:[1]:EXPENSE:[X]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[1]:EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t3;
WHO WEEK WHAT AMOUNT
Joe 4 Beer 19.00
@@ -240,10 +284,10 @@ Beth 4 Beer 15.00
Janet 4 Car 17.00
CREATE TABLE t4 (
WHO CHAR(12),
-WEEK INT(2) FIELD_FORMAT='WEEK:[3]:NUMBER',
-WHAT CHAR(32) FIELD_FORMAT='WEEK:[3]:EXPENSE:[X]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[3]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+WEEK INT(2) FIELD_FORMAT='WEEK:[2]:NUMBER',
+WHAT CHAR(32) FIELD_FORMAT='WEEK:[2]:EXPENSE:[X]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[2]:EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t4;
WHO WEEK WHAT AMOUNT
Joe 5 Beer 14.00
@@ -298,7 +342,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp3.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp3.json';
SELECT * FROM t2;
WHO WEEK WHAT AMOUNT
Joe 3 Beer 18.00
@@ -314,7 +358,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp4.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp4.json';
SELECT * FROM t3;
WHO WEEK WHAT AMOUNT
Joe 4 Beer 19.00
@@ -330,7 +374,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp5.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp5.json';
SELECT * FROM t4;
WHO WEEK WHAT AMOUNT
Joe 5 Beer 14.00
@@ -349,7 +393,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp*.jsn' MULTIPLE=1;
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp*.json' MULTIPLE=1;
SELECT * FROM t1 ORDER BY WHO, WEEK, WHAT, AMOUNT;
WHO WEEK WHAT AMOUNT
Beth 3 Beer 16.00
@@ -385,7 +429,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp%s.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp%s.json';
ALTER TABLE t1
PARTITION BY LIST COLUMNS(WEEK) (
PARTITION `3` VALUES IN(3),
diff --git a/storage/connect/mysql-test/connect/r/json_udf.result b/storage/connect/mysql-test/connect/r/json_udf.result
new file mode 100644
index 00000000000..1455bac9017
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/json_udf.result
@@ -0,0 +1,167 @@
+#
+# Test UDF's with constant arguments
+#
+SELECT Json_Array();
+Json_Array()
+[]
+SELECT Json_Object(56,3.1416,'foo',NULL);
+Json_Object(56,3.1416,'foo',NULL)
+{"56":56,"3.1416":3.141600,"foo":"foo","NULL":null}
+SELECT Json_Object(56 qty,3.1416 price,'foo' truc, NULL garanty);
+Json_Object(56 qty,3.1416 price,'foo' truc, NULL garanty)
+{"qty":56,"price":3.141600,"truc":"foo","garanty":null}
+SELECT Json_Array(56,3.1416,'My name is "Foo"',NULL);
+Json_Array(56,3.1416,'My name is "Foo"',NULL)
+[56,3.141600,"My name is \"Foo\"",null]
+SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL)) Array;
+ERROR HY000: Can't initialize function 'Json_Array_Add'; Json_Value_Add must have at least 2 arguments
+SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL),'One more') Array;
+Array
+[56,3.141600,"foo",null,"One more"]
+SELECT Json_Array_Add(Json_Value('one value'),'One more');
+Json_Array_Add(Json_Value('one value'),'One more')
+["one value","One more"]
+SELECT Json_Array_Add('one value','One more');
+ERROR HY000: Can't initialize function 'Json_Array_Add'; Json_Value_Add first argument must be a json item
+SELECT Json_Array_Add('one value' json_,'One more');
+Json_Array_Add('one value' json_,'One more')
+[null,"One more"]
+Warnings:
+Warning 1105 Bad 'o' character near one value
+SELECT Json_Value(56,3.1416,'foo',NULL);
+ERROR HY000: Can't initialize function 'Json_Value'; Json_Value cannot accept more than 1 argument
+SELECT Json_Value(3.1416);
+Json_Value(3.1416)
+3.141600
+SELECT Json_Value('foo');
+Json_Value('foo')
+"foo"
+SELECT Json_Value(NULL);
+Json_Value(NULL)
+null
+SELECT Json_Value();
+Json_Value()
+null
+SELECT Json_Object();
+Json_Object()
+{}
+SELECT Json_Object(Json_Array(56,3.1416,'foo'),NULL);
+Json_Object(Json_Array(56,3.1416,'foo'),NULL)
+{"Array(56,3.1416,'foo')":[56,3.141600,"foo"],"NULL":null}
+SELECT Json_Array(Json_Array(56,3.1416,'foo'),NULL);
+Json_Array(Json_Array(56,3.1416,'foo'),NULL)
+[[56,3.141600,"foo"],null]
+SELECT Json_Array(Json_Object(56 "qty",3.1416 "price",'foo'),NULL);
+Json_Array(Json_Object(56 "qty",3.1416 "price",'foo'),NULL)
+[{"qty":56,"price":3.141600,"foo":"foo"},null]
+#
+# Test UDF's with column arguments
+#
+CREATE TABLE t1
+(
+ISBN CHAR(15),
+LANG CHAR(2),
+SUBJECT CHAR(32),
+AUTHOR CHAR(64),
+TITLE CHAR(32),
+TRANSLATION CHAR(32),
+TRANSLATOR CHAR(80),
+PUBLISHER CHAR(32),
+DATEPUB int(4)
+) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
+SELECT Json_Array(AUTHOR, TITLE, DATEPUB) FROM t1;
+Json_Array(AUTHOR, TITLE, DATEPUB)
+["Jean-Christophe Bernadac","Construire une application XML",1999]
+["William J. Pardi","XML en Action",1999]
+SELECT Json_Object(AUTHOR, TITLE, DATEPUB) FROM t1;
+Json_Object(AUTHOR, TITLE, DATEPUB)
+{"AUTHOR":"Jean-Christophe Bernadac","TITLE":"Construire une application XML","DATEPUB":1999}
+{"AUTHOR":"William J. Pardi","TITLE":"XML en Action","DATEPUB":1999}
+SELECT Json_Array_Grp(TITLE, DATEPUB) FROM t1;
+ERROR HY000: Can't initialize function 'Json_Array_Grp'; Json_Array_Grp can only accept 1 argument
+SELECT Json_Array_Grp(TITLE) FROM t1;
+Json_Array_Grp(TITLE)
+["Construire une application XML","XML en Action"]
+DROP TABLE t1;
+CREATE TABLE t1 (
+SERIALNO CHAR(5) NOT NULL,
+NAME VARCHAR(12) NOT NULL FLAG=6,
+SEX SMALLINT(1) NOT NULL,
+TITLE VARCHAR(15) NOT NULL FLAG=20,
+MANAGER CHAR(5) DEFAULT NULL,
+DEPARTMENT CHAr(4) NOT NULL FLAG=41,
+SECRETARY CHAR(5) DEFAULT NULL FLAG=46,
+SALARY DOUBLE(8,2) NOT NULL FLAG=52
+) ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=8 FILE_NAME='employee.dat' ENDING=1;
+SELECT Json_Object(SERIALNO, NAME, TITLE, SALARY) FROM t1 WHERE NAME = 'MERCHANT';
+Json_Object(SERIALNO, NAME, TITLE, SALARY)
+{"SERIALNO":"78943","NAME":"MERCHANT","TITLE":"SALESMAN","SALARY":8700.000000}
+SELECT DEPARTMENT, Json_Array_Grp(NAME) FROM t1 GROUP BY DEPARTMENT;
+DEPARTMENT Json_Array_Grp(NAME)
+0021 ["STRONG","SHORTSIGHT"]
+0318 ["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]
+0319 ["BULLOZER","QUINN","BROWNY","KITTY","MONAPENNY","MARTIN","FUNNIGUY","BUGHAPPY","FODDERMAN","MESSIFUL"]
+2452 ["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"]
+Warnings:
+Warning 1105 Result truncated to json_grp_size values
+set connect_json_grp_size=30;
+SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t1 GROUP BY DEPARTMENT;
+Json_Array(DEPARTMENT, Json_Array_Grp(NAME))
+["0021",["STRONG","SHORTSIGHT"]]
+["0318",["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]]
+["0319",["BULLOZER","QUINN","BROWNY","KITTY","MONAPENNY","MARTIN","FUNNIGUY","BUGHAPPY","FODDERMAN","MESSIFUL","GOOSEPEN"]]
+["2452",["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"]]
+SELECT Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) FROM t1 GROUP BY DEPARTMENT;
+Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES)
+{"DEPARTMENT":"0021","NAMES":["STRONG","SHORTSIGHT"]}
+{"DEPARTMENT":"0318","NAMES":["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]}
+{"DEPARTMENT":"0319","NAMES":["BULLOZER","QUINN","BROWNY","KITTY","MONAPENNY","MARTIN","FUNNIGUY","BUGHAPPY","FODDERMAN","MESSIFUL","GOOSEPEN"]}
+{"DEPARTMENT":"2452","NAMES":["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"]}
+SELECT Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT;
+Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES)
+{"DEPARTMENT":"0021","EMPLOYES":[{"SERIALNO":"87777","NAME":"STRONG","TITLE":"DIRECTOR","SALARY":23000.000000},{"SERIALNO":"22222","NAME":"SHORTSIGHT","TITLE":"SECRETARY","SALARY":5500.000000}]}
+{"DEPARTMENT":"0318","EMPLOYES":[{"SERIALNO":"74200","NAME":"BANCROFT","TITLE":"SALESMAN","SALARY":9600.000000},{"SERIALNO":"24888","NAME":"PLUMHEAD","TITLE":"TYPIST","SALARY":2800.000000},{"SERIALNO":"27845","NAME":"HONEY","TITLE":"SECRETARY","SALARY":4900.000000},{"SERIALNO":"73452","NAME":"TONGHO","TITLE":"ENGINEER","SALARY":6800.000000},{"SERIALNO":"74234","NAME":"WALTER","TITLE":"ENGINEER","SALARY":7400.000000},{"SERIALNO":"77777","NAME":"SHRINKY","TITLE":"ADMINISTRATOR","SALARY":7500.000000},{"SERIALNO":"70012","NAME":"WERTHER","TITLE":"DIRECTOR","SALARY":14500.000000},{"SERIALNO":"78943","NAME":"MERCHANT","TITLE":"SALESMAN","SALARY":8700.000000},{"SERIALNO":"73111","NAME":"WHEELFOR","TITLE":"SALESMAN","SALARY":10030.000000}]}
+{"DEPARTMENT":"0319","EMPLOYES":[{"SERIALNO":"76543","NAME":"BULLOZER","TITLE":"SALESMAN","SALARY":14800.000000},{"SERIALNO":"40567","NAME":"QUINN","TITLE":"DIRECTOR","SALARY":14000.000000},{"SERIALNO":"00137","NAME":"BROWNY","TITLE":"ENGINEER","SALARY":10500.000000},{"SERIALNO":"12345","NAME":"KITTY","TITLE":"TYPIST","SALARY":3000.450000},{"SERIALNO":"33333","NAME":"MONAPENNY","TITLE":"SECRETARY","SALARY":3800.000000},{"SERIALNO":"00023","NAME":"MARTIN","TITLE":"ENGINEER","SALARY":10000.000000},{"SERIALNO":"07654","NAME":"FUNNIGUY","TITLE":"ADMINISTRATOR","SALARY":8500.000000},{"SERIALNO":"45678","NAME":"BUGHAPPY","TITLE":"PROGRAMMER","SALARY":8500.000000},{"SERIALNO":"56789","NAME":"FODDERMAN","TITLE":"SALESMAN","SALARY":7000.000000},{"SERIALNO":"55555","NAME":"MESSIFUL","TITLE":"SECRETARY","SALARY":5000.500000},{"SERIALNO":"98765","NAME":"GOOSEPEN","TITLE":"ADMINISTRATOR","SALARY":4700.000000}]}
+{"DEPARTMENT":"2452","EMPLOYES":[{"SERIALNO":"34567","NAME":"BIGHEAD","TITLE":"SCIENTIST","SALARY":8000.000000},{"SERIALNO":"31416","NAME":"ORELLY","TITLE":"ENGINEER","SALARY":13400.000000},{"SERIALNO":"36666","NAME":"BIGHORN","TITLE":"SCIENTIST","SALARY":11000.000000},{"SERIALNO":"02345","NAME":"SMITH","TITLE":"ENGINEER","SALARY":9000.000000},{"SERIALNO":"11111","NAME":"CHERRY","TITLE":"SECRETARY","SALARY":4500.000000}]}
+SELECT Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT, TITLE;
+Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES)
+{"DEPARTMENT":"0021","TITLE":"DIRECTOR","EMPLOYES":[{"SERIALNO":"87777","NAME":"STRONG","SALARY":23000.000000}]}
+{"DEPARTMENT":"0021","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"22222","NAME":"SHORTSIGHT","SALARY":5500.000000}]}
+{"DEPARTMENT":"0318","TITLE":"ADMINISTRATOR","EMPLOYES":[{"SERIALNO":"77777","NAME":"SHRINKY","SALARY":7500.000000}]}
+{"DEPARTMENT":"0318","TITLE":"DIRECTOR","EMPLOYES":[{"SERIALNO":"70012","NAME":"WERTHER","SALARY":14500.000000}]}
+{"DEPARTMENT":"0318","TITLE":"ENGINEER","EMPLOYES":[{"SERIALNO":"73452","NAME":"TONGHO","SALARY":6800.000000},{"SERIALNO":"74234","NAME":"WALTER","SALARY":7400.000000}]}
+{"DEPARTMENT":"0318","TITLE":"SALESMAN","EMPLOYES":[{"SERIALNO":"74200","NAME":"BANCROFT","SALARY":9600.000000},{"SERIALNO":"78943","NAME":"MERCHANT","SALARY":8700.000000},{"SERIALNO":"73111","NAME":"WHEELFOR","SALARY":10030.000000}]}
+{"DEPARTMENT":"0318","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"27845","NAME":"HONEY","SALARY":4900.000000}]}
+{"DEPARTMENT":"0318","TITLE":"TYPIST","EMPLOYES":[{"SERIALNO":"24888","NAME":"PLUMHEAD","SALARY":2800.000000}]}
+{"DEPARTMENT":"0319","TITLE":"ADMINISTRATOR","EMPLOYES":[{"SERIALNO":"98765","NAME":"GOOSEPEN","SALARY":4700.000000},{"SERIALNO":"07654","NAME":"FUNNIGUY","SALARY":8500.000000}]}
+{"DEPARTMENT":"0319","TITLE":"DIRECTOR","EMPLOYES":[{"SERIALNO":"40567","NAME":"QUINN","SALARY":14000.000000}]}
+{"DEPARTMENT":"0319","TITLE":"ENGINEER","EMPLOYES":[{"SERIALNO":"00023","NAME":"MARTIN","SALARY":10000.000000},{"SERIALNO":"00137","NAME":"BROWNY","SALARY":10500.000000}]}
+{"DEPARTMENT":"0319","TITLE":"PROGRAMMER","EMPLOYES":[{"SERIALNO":"45678","NAME":"BUGHAPPY","SALARY":8500.000000}]}
+{"DEPARTMENT":"0319","TITLE":"SALESMAN","EMPLOYES":[{"SERIALNO":"76543","NAME":"BULLOZER","SALARY":14800.000000},{"SERIALNO":"56789","NAME":"FODDERMAN","SALARY":7000.000000}]}
+{"DEPARTMENT":"0319","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"33333","NAME":"MONAPENNY","SALARY":3800.000000},{"SERIALNO":"55555","NAME":"MESSIFUL","SALARY":5000.500000}]}
+{"DEPARTMENT":"0319","TITLE":"TYPIST","EMPLOYES":[{"SERIALNO":"12345","NAME":"KITTY","SALARY":3000.450000}]}
+{"DEPARTMENT":"2452","TITLE":"ENGINEER","EMPLOYES":[{"SERIALNO":"31416","NAME":"ORELLY","SALARY":13400.000000},{"SERIALNO":"02345","NAME":"SMITH","SALARY":9000.000000}]}
+{"DEPARTMENT":"2452","TITLE":"SCIENTIST","EMPLOYES":[{"SERIALNO":"34567","NAME":"BIGHEAD","SALARY":8000.000000},{"SERIALNO":"36666","NAME":"BIGHORN","SALARY":11000.000000}]}
+{"DEPARTMENT":"2452","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"11111","NAME":"CHERRY","SALARY":4500.000000}]}
+SELECT Json_Object_Grp(SALARY) FROM t1;
+ERROR HY000: Can't initialize function 'Json_Object_Grp'; Json_Array_Grp can only accept 2 arguments
+SELECT Json_Object_Grp(SALARY, NAME) FROM t1;
+Json_Object_Grp(SALARY, NAME)
+{"BANCROFT":9600.000000,"SMITH":9000.000000,"MERCHANT":8700.000000,"FUNNIGUY":8500.000000,"BUGHAPPY":8500.000000,"BIGHEAD":8000.000000,"SHRINKY":7500.000000,"WALTER":7400.000000,"FODDERMAN":7000.000000,"TONGHO":6800.000000,"SHORTSIGHT":5500.000000,"MESSIFUL":5000.500000,"HONEY":4900.000000,"GOOSEPEN":4700.000000,"CHERRY":4500.000000,"MONAPENNY":3800.000000,"KITTY":3000.450000,"PLUMHEAD":2800.000000,"STRONG":23000.000000,"BULLOZER":14800.000000,"WERTHER":14500.000000,"QUINN":14000.000000,"ORELLY":13400.000000,"BIGHORN":11000.000000,"BROWNY":10500.000000,"WHEELFOR":10030.000000,"MARTIN":10000.000000}
+SELECT Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES") FROM t1 GROUP BY DEPARTMENT;
+Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES")
+{"DEPARTMENT":"0021","SALARIES":{"STRONG":23000.000000,"SHORTSIGHT":5500.000000}}
+{"DEPARTMENT":"0318","SALARIES":{"BANCROFT":9600.000000,"PLUMHEAD":2800.000000,"HONEY":4900.000000,"TONGHO":6800.000000,"WALTER":7400.000000,"SHRINKY":7500.000000,"WERTHER":14500.000000,"MERCHANT":8700.000000,"WHEELFOR":10030.000000}}
+{"DEPARTMENT":"0319","SALARIES":{"BULLOZER":14800.000000,"QUINN":14000.000000,"BROWNY":10500.000000,"KITTY":3000.450000,"MONAPENNY":3800.000000,"MARTIN":10000.000000,"FUNNIGUY":8500.000000,"BUGHAPPY":8500.000000,"FODDERMAN":7000.000000,"MESSIFUL":5000.500000,"GOOSEPEN":4700.000000}}
+{"DEPARTMENT":"2452","SALARIES":{"BIGHEAD":8000.000000,"ORELLY":13400.000000,"BIGHORN":11000.000000,"SMITH":9000.000000,"CHERRY":4500.000000}}
+SELECT Json_Array_Grp(NAME) from t1;
+Json_Array_Grp(NAME)
+["BANCROFT","SMITH","MERCHANT","FUNNIGUY","BUGHAPPY","BIGHEAD","SHRINKY","WALTER","FODDERMAN","TONGHO","SHORTSIGHT","MESSIFUL","HONEY","GOOSEPEN","CHERRY","MONAPENNY","KITTY","PLUMHEAD","STRONG","BULLOZER","WERTHER","QUINN","ORELLY","BIGHORN","BROWNY","WHEELFOR","MARTIN"]
+DROP TABLE t1;
+DROP FUNCTION Json_Array;
+DROP FUNCTION Json_Array_Add;
+DROP FUNCTION Json_Object;
+DROP FUNCTION Json_Object_Nonull;
+DROP FUNCTION Json_Value;
+DROP FUNCTION Json_Array_Grp;
+DROP FUNCTION Json_Object_Grp;
diff --git a/storage/connect/mysql-test/connect/r/odbc_oracle.result b/storage/connect/mysql-test/connect/r/odbc_oracle.result
index fff2f192184..96d8e53b8e5 100644
--- a/storage/connect/mysql-test/connect/r/odbc_oracle.result
+++ b/storage/connect/mysql-test/connect/r/odbc_oracle.result
@@ -126,7 +126,7 @@ TABNAME='T1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='T1'
SELECT * FROM t1 ORDER BY A;
@@ -138,7 +138,7 @@ CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
@@ -162,7 +162,7 @@ TABNAME='MTR.T1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.T1'
SELECT * FROM t1;
@@ -178,7 +178,7 @@ TABNAME='MTR.V1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.V1'
SELECT * FROM t1;
@@ -190,7 +190,7 @@ CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
diff --git a/storage/connect/mysql-test/connect/r/xml_html.result b/storage/connect/mysql-test/connect/r/xml_html.result
new file mode 100644
index 00000000000..143f46529f6
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/xml_html.result
@@ -0,0 +1,32 @@
+Warnings:
+Warning 1105 No file name. Table will use t1.xml
+SET NAMES utf8;
+#
+# Testing HTML like XML file
+#
+CREATE TABLE beers (
+`Name` CHAR(16) FIELD_FORMAT='brandName',
+`Origin` CHAR(16) FIELD_FORMAT='origin',
+`Description` CHAR(32) FIELD_FORMAT='details')
+ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='beers.xml'
+TABNAME='table' OPTION_LIST='xmlsup=libxml2,rownode=tr,colnode=td';
+SELECT * FROM beers;
+Name Origin Description
+Huntsman Bath, UK Wonderful hop, light alcohol
+Tuborg Danmark In small bottles
+DROP TABLE beers;
+#
+# Testing HTML file
+#
+CREATE TABLE coffee (
+`Name` CHAR(16),
+`Cups` INT(8),
+`Type` CHAR(16),
+`Sugar` CHAR(4))
+ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='coffee.htm'
+TABNAME='TABLE' HEADER=1 OPTION_LIST='xmlsup=libxml2,Coltype=HTML';
+SELECT * FROM coffee;
+Name Cups Type Sugar
+T. Sexton 10 Espresso No
+J. Dinnen 5 Decaf Yes
+DROP TABLE coffee;
diff --git a/storage/connect/mysql-test/connect/std_data/beers.xml b/storage/connect/mysql-test/connect/std_data/beers.xml
new file mode 100644
index 00000000000..1abc77fe0f9
--- /dev/null
+++ b/storage/connect/mysql-test/connect/std_data/beers.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<Beers>
+ <table>
+ <th><td>Name</td><td>Origin</td><td>Description</td></th>
+ <tr>
+ <td><brandName>Huntsman</brandName></td>
+ <td><origin>Bath, UK</origin></td>
+ <td><details>Wonderful hop, light alcohol</details></td>
+ </tr>
+ <tr>
+ <td><brandName>Tuborg</brandName></td>
+ <td><origin>Danmark</origin></td>
+ <td><details>In small bottles</details></td>
+ </tr>
+ </table>
+</Beers>
diff --git a/storage/connect/mysql-test/connect/std_data/biblio.jsn b/storage/connect/mysql-test/connect/std_data/biblio.json
index bab8fd24305..cc24b162cd9 100644
--- a/storage/connect/mysql-test/connect/std_data/biblio.jsn
+++ b/storage/connect/mysql-test/connect/std_data/biblio.json
@@ -1,45 +1,45 @@
-[
- {
- "ISBN": "9782212090819",
- "LANG": "fr",
- "SUBJECT": "applications",
- "AUTHOR": [
- {
- "FIRSTNAME": "Jean-Christophe",
- "LASTNAME": "Bernadac"
- },
- {
- "FIRSTNAME": "François",
- "LASTNAME": "Knab"
- }
- ],
- "TITLE": "Construire une application XML",
- "PUBLISHER": {
- "NAME": "Eyrolles",
- "PLACE": "Paris"
- },
- "DATEPUB": 1999
- },
- {
- "ISBN": "9782840825685",
- "LANG": "fr",
- "SUBJECT": "applications",
- "AUTHOR": [
- {
- "FIRSTNAME": "William J.",
- "LASTNAME": "Pardi"
- }
- ],
- "TITLE": "XML en Action",
- "TRANSLATION": "adapté de l'anglais par",
- "TRANSLATOR": {
- "FIRSTNAME": "James",
- "LASTNAME": "Guerin"
- },
- "PUBLISHER": {
- "NAME": "Microsoft Press",
- "PLACE": "Paris"
- },
- "DATEPUB": 1999
- }
-]
+[
+ {
+ "ISBN": "9782212090819",
+ "LANG": "fr",
+ "SUBJECT": "applications",
+ "AUTHOR": [
+ {
+ "FIRSTNAME": "Jean-Christophe",
+ "LASTNAME": "Bernadac"
+ },
+ {
+ "FIRSTNAME": "François",
+ "LASTNAME": "Knab"
+ }
+ ],
+ "TITLE": "Construire une application XML",
+ "PUBLISHER": {
+ "NAME": "Eyrolles",
+ "PLACE": "Paris"
+ },
+ "DATEPUB": 1999
+ },
+ {
+ "ISBN": "9782840825685",
+ "LANG": "fr",
+ "SUBJECT": "applications",
+ "AUTHOR": [
+ {
+ "FIRSTNAME": "William J.",
+ "LASTNAME": "Pardi"
+ }
+ ],
+ "TITLE": "XML en Action",
+ "TRANSLATION": "adapté de l'anglais par",
+ "TRANSLATOR": {
+ "FIRSTNAME": "James",
+ "LASTNAME": "Guerin"
+ },
+ "PUBLISHER": {
+ "NAME": "Microsoft Press",
+ "PLACE": "Paris"
+ },
+ "DATEPUB": 1999
+ }
+]
diff --git a/storage/connect/mysql-test/connect/std_data/bookstore.xml b/storage/connect/mysql-test/connect/std_data/bookstore.xml
index 0aebbcd243e..540fa5409f4 100644
--- a/storage/connect/mysql-test/connect/std_data/bookstore.xml
+++ b/storage/connect/mysql-test/connect/std_data/bookstore.xml
@@ -1,31 +1,31 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<bookstore>
- <book category="COOKING">
- <title lang="en">Everyday Italian</title>
- <author>Giada De Laurentiis</author>
- <year>2005</year>
- <price>30.00</price>
- </book>
- <book category="CHILDREN">
- <title lang="en">Harry Potter</title>
- <author>J K. Rowling</author>
- <year>2005</year>
- <price>29.99</price>
- </book>
- <book category="WEB">
- <title lang="en">XQuery Kick Start</title>
- <author>James McGovern</author>
- <author>Per Bothner</author>
- <author>Kurt Cagle</author>
- <author>James Linn</author>
- <author>Vaidyanathan Nagarajan</author>
- <year>2003</year>
- <price>49.99</price>
- </book>
- <book category="WEB">
- <title lang="en">Learning XML</title>
- <author>Erik T. Ray</author>
- <year>2003</year>
- <price>39.95</price>
- </book>
-</bookstore>
+<?xml version="1.0" encoding="UTF-8"?>
+<bookstore>
+ <book category="COOKING">
+ <title lang="en">Everyday Italian</title>
+ <author>Giada De Laurentiis</author>
+ <year>2005</year>
+ <price>30.00</price>
+ </book>
+ <book category="CHILDREN">
+ <title lang="en">Harry Potter</title>
+ <author>J K. Rowling</author>
+ <year>2005</year>
+ <price>29.99</price>
+ </book>
+ <book category="WEB">
+ <title lang="en">XQuery Kick Start</title>
+ <author>James McGovern</author>
+ <author>Per Bothner</author>
+ <author>Kurt Cagle</author>
+ <author>James Linn</author>
+ <author>Vaidyanathan Nagarajan</author>
+ <year>2003</year>
+ <price>49.99</price>
+ </book>
+ <book category="WEB">
+ <title lang="en">Learning XML</title>
+ <author>Erik T. Ray</author>
+ <year>2003</year>
+ <price>39.95</price>
+ </book>
+</bookstore>
diff --git a/storage/connect/mysql-test/connect/std_data/coffee.htm b/storage/connect/mysql-test/connect/std_data/coffee.htm
new file mode 100644
index 00000000000..95a23d5c0ad
--- /dev/null
+++ b/storage/connect/mysql-test/connect/std_data/coffee.htm
@@ -0,0 +1,24 @@
+<TABLE summary="This table charts the number of cups of coffe
+ consumed by each senator, the type of coffee (decaf
+ or regular), and whether taken with sugar.">
+ <CAPTION>Cups of coffee consumed by each senator</CAPTION>
+ <TR>
+ <TH>Name</TH>
+ <TH>Cups</TH>
+ <TH>Type of Coffee</TH>
+ <TH>Sugar?</TH>
+ </TR>
+ <TR>
+ <TD>T. Sexton</TD>
+ <TD>10</TD>
+ <TD>Espresso</TD>
+ <TD>No</TD>
+ </TR>
+ <TR>
+ <TD>J. Dinnen</TD>
+ <TD>5</TD>
+ <TD>Decaf</TD>
+ <TD>Yes</TD>
+ </TR>
+</TABLE>
+
diff --git a/storage/connect/mysql-test/connect/std_data/expense.jsn b/storage/connect/mysql-test/connect/std_data/expense.json
index e65ad5261f1..f9373ef1a80 100644
--- a/storage/connect/mysql-test/connect/std_data/expense.jsn
+++ b/storage/connect/mysql-test/connect/std_data/expense.json
@@ -1,158 +1,158 @@
-[
- {
- "WHO": "Joe",
- "WEEK": [
- {
- "NUMBER": 3,
- "EXPENSE": [
- {
- "WHAT": "Beer",
- "AMOUNT": 18.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 12.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 19.00
- },
- {
- "WHAT": "Car",
- "AMOUNT": 20.00
- }
- ]
- },
- {
- "NUMBER": 4,
- "EXPENSE": [
- {
- "WHAT": "Beer",
- "AMOUNT": 19.00
- },
- {
- "WHAT": "Beer",
- "AMOUNT": 16.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 17.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 17.00
- },
- {
- "WHAT": "Beer",
- "AMOUNT": 14.00
- }
- ]
- },
- {
- "NUMBER": 5,
- "EXPENSE": [
- {
- "WHAT": "Beer",
- "AMOUNT": 14.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 12.00
- }
- ]
- }
- ]
- },
- {
- "WHO": "Beth",
- "WEEK": [
- {
- "NUMBER": 3,
- "EXPENSE": [
- {
- "WHAT": "Beer",
- "AMOUNT": 16.00
- }
- ]
- },
- {
- "NUMBER": 4,
- "EXPENSE": [
- {
- "WHAT": "Food",
- "AMOUNT": 17.00
- },
- {
- "WHAT": "Beer",
- "AMOUNT": 15.00
- }
- ]
- },
- {
- "NUMBER": 5,
- "EXPENSE": [
- {
- "WHAT": "Food",
- "AMOUNT": 12.00
- },
- {
- "WHAT": "Beer",
- "AMOUNT": 20.00
- }
- ]
- }
- ]
- },
- {
- "WHO": "Janet",
- "WEEK": [
- {
- "NUMBER": 3,
- "EXPENSE": [
- {
- "WHAT": "Car",
- "AMOUNT": 19.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 18.00
- },
- {
- "WHAT": "Beer",
- "AMOUNT": 18.00
- }
- ]
- },
- {
- "NUMBER": 4,
- "EXPENSE": [
- {
- "WHAT": "Car",
- "AMOUNT": 17.00
- }
- ]
- },
- {
- "NUMBER": 5,
- "EXPENSE": [
- {
- "WHAT": "Beer",
- "AMOUNT": 14.00
- },
- {
- "WHAT": "Car",
- "AMOUNT": 12.00
- },
- {
- "WHAT": "Beer",
- "AMOUNT": 19.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 12.00
- }
- ]
- }
- ]
- }
-]
+[
+ {
+ "WHO": "Joe",
+ "WEEK": [
+ {
+ "NUMBER": 3,
+ "EXPENSE": [
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 18.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 12.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 19.00
+ },
+ {
+ "WHAT": "Car",
+ "AMOUNT": 20.00
+ }
+ ]
+ },
+ {
+ "NUMBER": 4,
+ "EXPENSE": [
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 19.00
+ },
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 16.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 17.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 17.00
+ },
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 14.00
+ }
+ ]
+ },
+ {
+ "NUMBER": 5,
+ "EXPENSE": [
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 14.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 12.00
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "WHO": "Beth",
+ "WEEK": [
+ {
+ "NUMBER": 3,
+ "EXPENSE": [
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 16.00
+ }
+ ]
+ },
+ {
+ "NUMBER": 4,
+ "EXPENSE": [
+ {
+ "WHAT": "Food",
+ "AMOUNT": 17.00
+ },
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 15.00
+ }
+ ]
+ },
+ {
+ "NUMBER": 5,
+ "EXPENSE": [
+ {
+ "WHAT": "Food",
+ "AMOUNT": 12.00
+ },
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 20.00
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "WHO": "Janet",
+ "WEEK": [
+ {
+ "NUMBER": 3,
+ "EXPENSE": [
+ {
+ "WHAT": "Car",
+ "AMOUNT": 19.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 18.00
+ },
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 18.00
+ }
+ ]
+ },
+ {
+ "NUMBER": 4,
+ "EXPENSE": [
+ {
+ "WHAT": "Car",
+ "AMOUNT": 17.00
+ }
+ ]
+ },
+ {
+ "NUMBER": 5,
+ "EXPENSE": [
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 14.00
+ },
+ {
+ "WHAT": "Car",
+ "AMOUNT": 12.00
+ },
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 19.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 12.00
+ }
+ ]
+ }
+ ]
+ }
+]
diff --git a/storage/connect/mysql-test/connect/std_data/mulexp3.jsn b/storage/connect/mysql-test/connect/std_data/mulexp3.json
index c228448b073..5edd2ab1e76 100644
--- a/storage/connect/mysql-test/connect/std_data/mulexp3.jsn
+++ b/storage/connect/mysql-test/connect/std_data/mulexp3.json
@@ -1,52 +1,52 @@
-[
- {
- "WHO": "Joe",
- "WEEK": 3,
- "EXPENSE": [
- {
- "WHAT": "Beer",
- "AMOUNT": 18.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 12.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 19.00
- },
- {
- "WHAT": "Car",
- "AMOUNT": 20.00
- }
- ]
- },
- {
- "WHO": "Beth",
- "WEEK": 3,
- "EXPENSE": [
- {
- "WHAT": "Beer",
- "AMOUNT": 16.00
- }
- ]
- },
- {
- "WHO": "Janet",
- "WEEK": 3,
- "EXPENSE": [
- {
- "WHAT": "Car",
- "AMOUNT": 19.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 18.00
- },
- {
- "WHAT": "Beer",
- "AMOUNT": 18.00
- }
- ]
- }
-]
+[
+ {
+ "WHO": "Joe",
+ "WEEK": 3,
+ "EXPENSE": [
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 18.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 12.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 19.00
+ },
+ {
+ "WHAT": "Car",
+ "AMOUNT": 20.00
+ }
+ ]
+ },
+ {
+ "WHO": "Beth",
+ "WEEK": 3,
+ "EXPENSE": [
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 16.00
+ }
+ ]
+ },
+ {
+ "WHO": "Janet",
+ "WEEK": 3,
+ "EXPENSE": [
+ {
+ "WHAT": "Car",
+ "AMOUNT": 19.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 18.00
+ },
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 18.00
+ }
+ ]
+ }
+]
diff --git a/storage/connect/mysql-test/connect/std_data/mulexp4.jsn b/storage/connect/mysql-test/connect/std_data/mulexp4.json
index 0e43ffec07b..7f7b88d6afd 100644
--- a/storage/connect/mysql-test/connect/std_data/mulexp4.jsn
+++ b/storage/connect/mysql-test/connect/std_data/mulexp4.json
@@ -1,52 +1,52 @@
-[
- {
- "WHO": "Joe",
- "WEEK": 4,
- "EXPENSE": [
- {
- "WHAT": "Beer",
- "AMOUNT": 19.00
- },
- {
- "WHAT": "Beer",
- "AMOUNT": 16.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 17.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 17.00
- },
- {
- "WHAT": "Beer",
- "AMOUNT": 14.00
- }
- ]
- },
- {
- "WHO": "Beth",
- "WEEK": 4,
- "EXPENSE": [
- {
- "WHAT": "Food",
- "AMOUNT": 17.00
- },
- {
- "WHAT": "Beer",
- "AMOUNT": 15.00
- }
- ]
- },
- {
- "WHO": "Janet",
- "WEEK": 4,
- "EXPENSE": [
- {
- "WHAT": "Car",
- "AMOUNT": 17.00
- }
- ]
- }
-]
+[
+ {
+ "WHO": "Joe",
+ "WEEK": 4,
+ "EXPENSE": [
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 19.00
+ },
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 16.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 17.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 17.00
+ },
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 14.00
+ }
+ ]
+ },
+ {
+ "WHO": "Beth",
+ "WEEK": 4,
+ "EXPENSE": [
+ {
+ "WHAT": "Food",
+ "AMOUNT": 17.00
+ },
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 15.00
+ }
+ ]
+ },
+ {
+ "WHO": "Janet",
+ "WEEK": 4,
+ "EXPENSE": [
+ {
+ "WHAT": "Car",
+ "AMOUNT": 17.00
+ }
+ ]
+ }
+]
diff --git a/storage/connect/mysql-test/connect/std_data/mulexp5.jsn b/storage/connect/mysql-test/connect/std_data/mulexp5.json
index 7a707506c2f..b1713040c4b 100644
--- a/storage/connect/mysql-test/connect/std_data/mulexp5.jsn
+++ b/storage/connect/mysql-test/connect/std_data/mulexp5.json
@@ -1,52 +1,52 @@
-[
- {
- "WHO": "Joe",
- "WEEK": 5,
- "EXPENSE": [
- {
- "WHAT": "Beer",
- "AMOUNT": 14.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 12.00
- }
- ]
- },
- {
- "WHO": "Beth",
- "WEEK": 5,
- "EXPENSE": [
- {
- "WHAT": "Food",
- "AMOUNT": 12.00
- },
- {
- "WHAT": "Beer",
- "AMOUNT": 20.00
- }
- ]
- },
- {
- "WHO": "Janet",
- "WEEK": 5,
- "EXPENSE": [
- {
- "WHAT": "Beer",
- "AMOUNT": 14.00
- },
- {
- "WHAT": "Car",
- "AMOUNT": 12.00
- },
- {
- "WHAT": "Beer",
- "AMOUNT": 19.00
- },
- {
- "WHAT": "Food",
- "AMOUNT": 12.00
- }
- ]
- }
-]
+[
+ {
+ "WHO": "Joe",
+ "WEEK": 5,
+ "EXPENSE": [
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 14.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 12.00
+ }
+ ]
+ },
+ {
+ "WHO": "Beth",
+ "WEEK": 5,
+ "EXPENSE": [
+ {
+ "WHAT": "Food",
+ "AMOUNT": 12.00
+ },
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 20.00
+ }
+ ]
+ },
+ {
+ "WHO": "Janet",
+ "WEEK": 5,
+ "EXPENSE": [
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 14.00
+ },
+ {
+ "WHAT": "Car",
+ "AMOUNT": 12.00
+ },
+ {
+ "WHAT": "Beer",
+ "AMOUNT": 19.00
+ },
+ {
+ "WHAT": "Food",
+ "AMOUNT": 12.00
+ }
+ ]
+ }
+]
diff --git a/storage/connect/mysql-test/connect/std_data/sexe.csv b/storage/connect/mysql-test/connect/std_data/sexe.csv
index 37d63169133..7e5d3ec93cd 100644
--- a/storage/connect/mysql-test/connect/std_data/sexe.csv
+++ b/storage/connect/mysql-test/connect/std_data/sexe.csv
@@ -1,3 +1,3 @@
-0;Inconnu
-1;Masculin
-2;Feminin
+0;Inconnu
+1;Masculin
+2;Feminin
diff --git a/storage/connect/mysql-test/connect/std_data/sitmat.csv b/storage/connect/mysql-test/connect/std_data/sitmat.csv
index e93f121a839..a5178ed2c76 100644
--- a/storage/connect/mysql-test/connect/std_data/sitmat.csv
+++ b/storage/connect/mysql-test/connect/std_data/sitmat.csv
@@ -1,7 +1,7 @@
-.;Inconnu
-C;Celibataire
-D;Divorce
-L;Union libre
-M;Marie
-S;Separe
-V;Veuf
+.;Inconnu
+C;Celibataire
+D;Divorce
+L;Union libre
+M;Marie
+S;Separe
+V;Veuf
diff --git a/storage/connect/mysql-test/connect/t/alter.test b/storage/connect/mysql-test/connect/t/alter.test
index 49f34996bbd..0eda6355027 100644
--- a/storage/connect/mysql-test/connect/t/alter.test
+++ b/storage/connect/mysql-test/connect/t/alter.test
@@ -1,139 +1,139 @@
-let $MYSQLD_DATADIR= `select @@datadir`;
-
---echo #
---echo # Testing indexing with ALTER on inward table (in-place)
---echo #
-CREATE TABLE t1 (c INT NOT NULL, d CHAR(10) NOT NULL) ENGINE=CONNECT;
-INSERT INTO t1 VALUES (1,'One'), (2,'Two'), (3,'Three');
-SELECT * FROM t1;
-CREATE INDEX xc ON t1(c);
-DESCRIBE SELECT * FROM t1 WHERE c = 2;
-DROP INDEX xc ON t1;
-CREATE INDEX xd ON t1(d);
-DROP INDEX xd ON t1;
-ALTER TABLE t1 ADD INDEX xc (c), ADD INDEX xd (d);
-SHOW INDEX FROM t1;
-ALTER TABLE t1 DROP INDEX xc, DROP INDEX xd;
-SHOW INDEX FROM t1;
-
---echo #
---echo # Testing modifying columns inward table (not in-place)
---echo #
-ALTER TABLE t1 MODIFY COLUMN c CHAR(5) NOT NULL;
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-ALTER TABLE t1 MODIFY COLUMN c INT NOT NULL;
-
---echo #
---echo # Fails because indexing must be in-place
---echo #
---error ER_ALTER_OPERATION_NOT_SUPPORTED
-ALTER TABLE t1 MODIFY COLUMN c CHAR(10) NOT NULL, ADD INDEX xd (d);
-
---echo #
---echo # Testing changing table type (not in-place)
---echo #
-ALTER TABLE t1 TABLE_TYPE=CSV HEADER=1 QUOTED=1;
-SELECT * FROM t1;
-SHOW CREATE TABLE t1;
-
---echo # create an outward table used to see the t1 file
-CREATE TABLE t2 (line VARCHAR(100) NOT NULL) ENGINE=CONNECT FILE_NAME='t1.csv';
-SELECT * FROM t2;
-
---echo #
---echo # Testing changing engine
---echo #
-DROP TABLE t1;
-CREATE TABLE t1 (c INT NOT NULL, d CHAR(10) NOT NULL) ENGINE=CONNECT;
-INSERT INTO t1 VALUES (1,'One'), (2,'Two'), (3,'Three');
-ALTER TABLE t1 ADD INDEX xc (c), ADD INDEX xd (d);
-ALTER TABLE t1 ENGINE = MYISAM;
-SHOW CREATE TABLE t1;
-SHOW INDEX FROM t1;
-SELECT * FROM t1;
-ALTER TABLE t1 ENGINE = CONNECT TABLE_TYPE=DBF;
-SHOW CREATE TABLE t1;
-SHOW INDEX FROM t1;
-SELECT * FROM t1;
-DROP TABLE t1, t2;
-
---echo #
---echo # Testing ALTER on outward tables
---echo #
-CREATE TABLE t1 (c INT NOT NULL, d CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='tf1.txt' ENDING=1;
-INSERT INTO t1 VALUES (1,'One'), (2,'Two'), (3,'Three');
-SELECT * FROM t1;
-CREATE TABLE t2 (line VARCHAR(100) NOT NULL) ENGINE=CONNECT FILE_NAME='tf1.txt';
-SELECT * FROM t2;
-
---echo #
---echo # Indexing works the same
---echo #
-ALTER TABLE t1 ADD INDEX xc (c), ADD INDEX xd (d);
-SHOW INDEX FROM t1;
-SELECT d FROM t1 WHERE c = 2;
-ALTER TABLE t1 DROP INDEX xc, DROP INDEX xd;
-SHOW INDEX FROM t1;
-
---echo #
---echo # Other alterations do not modify the file
---echo #
-ALTER TABLE t1 MODIFY COLUMN c CHAR(5) NOT NULL;
-SELECT * FROM t2;
-SHOW CREATE TABLE t1;
-#Wrong result
---error ER_GET_ERRMSG
-SELECT * FROM t1;
-ALTER TABLE t1 MODIFY COLUMN c INT NOT NULL;
-
---echo #
---echo # Changing column order
---echo #
-ALTER TABLE t1 MODIFY COLUMN c INT NOT NULL AFTER d;
-SELECT * FROM t2;
-SHOW CREATE TABLE t1;
---echo # Wrong result
-SELECT * FROM t1;
-ALTER TABLE t1 MODIFY COLUMN c INT NOT NULL FIRST;
---echo # What should have been done
-ALTER TABLE t1 MODIFY c INT NOT NULL FLAG=0 AFTER d, MODIFY d CHAR(10) NOT NULL FLAG=11;
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-
---echo #
---echo # Changing to another engine is Ok
---echo # However, the data file is not deleted.
---echo #
-ALTER TABLE t1 ENGINE=ARIA;
-SHOW CREATE TABLE t1;
-set @old_sql_mode=@@sql_mode;
-set sql_mode=ignore_bad_table_options;
-SHOW CREATE TABLE t1;
-set sql_mode=@old_sql_mode;
-SELECT * from t1;
-SELECT * from t2;
-
---echo #
---echo # Changing back to CONNECT fails
---echo # Sure enough, the data file was not deleted.
---echo #
---error ER_UNKNOWN_ERROR
-ALTER TABLE t1 ENGINE=CONNECT;
-
---echo #
---echo # But changing back to CONNECT succeed
---echo # if the data file does not exist.
---echo #
---remove_file $MYSQLD_DATADIR/test/tf1.txt
-ALTER TABLE t1 ENGINE=CONNECT;
-SHOW CREATE TABLE t1;
-SELECT * from t1;
-SELECT * from t2;
-
-DROP TABLE t1, t2;
-
-#
-# Clean up
-#
---remove_file $MYSQLD_DATADIR/test/tf1.txt
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--echo #
+--echo # Testing indexing with ALTER on inward table (in-place)
+--echo #
+CREATE TABLE t1 (c INT NOT NULL, d CHAR(10) NOT NULL) ENGINE=CONNECT;
+INSERT INTO t1 VALUES (1,'One'), (2,'Two'), (3,'Three');
+SELECT * FROM t1;
+CREATE INDEX xc ON t1(c);
+DESCRIBE SELECT * FROM t1 WHERE c = 2;
+DROP INDEX xc ON t1;
+CREATE INDEX xd ON t1(d);
+DROP INDEX xd ON t1;
+ALTER TABLE t1 ADD INDEX xc (c), ADD INDEX xd (d);
+SHOW INDEX FROM t1;
+ALTER TABLE t1 DROP INDEX xc, DROP INDEX xd;
+SHOW INDEX FROM t1;
+
+--echo #
+--echo # Testing modifying columns inward table (not in-place)
+--echo #
+ALTER TABLE t1 MODIFY COLUMN c CHAR(5) NOT NULL;
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+ALTER TABLE t1 MODIFY COLUMN c INT NOT NULL;
+
+--echo #
+--echo # Fails because indexing must be in-place
+--echo #
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 MODIFY COLUMN c CHAR(10) NOT NULL, ADD INDEX xd (d);
+
+--echo #
+--echo # Testing changing table type (not in-place)
+--echo #
+ALTER TABLE t1 TABLE_TYPE=CSV HEADER=1 QUOTED=1;
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+
+--echo # create an outward table used to see the t1 file
+CREATE TABLE t2 (line VARCHAR(100) NOT NULL) ENGINE=CONNECT FILE_NAME='t1.csv';
+SELECT * FROM t2;
+
+--echo #
+--echo # Testing changing engine
+--echo #
+DROP TABLE t1;
+CREATE TABLE t1 (c INT NOT NULL, d CHAR(10) NOT NULL) ENGINE=CONNECT;
+INSERT INTO t1 VALUES (1,'One'), (2,'Two'), (3,'Three');
+ALTER TABLE t1 ADD INDEX xc (c), ADD INDEX xd (d);
+ALTER TABLE t1 ENGINE = MYISAM;
+SHOW CREATE TABLE t1;
+SHOW INDEX FROM t1;
+SELECT * FROM t1;
+ALTER TABLE t1 ENGINE = CONNECT TABLE_TYPE=DBF;
+SHOW CREATE TABLE t1;
+SHOW INDEX FROM t1;
+SELECT * FROM t1;
+DROP TABLE t1, t2;
+
+--echo #
+--echo # Testing ALTER on outward tables
+--echo #
+CREATE TABLE t1 (c INT NOT NULL, d CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='tf1.txt' ENDING=1;
+INSERT INTO t1 VALUES (1,'One'), (2,'Two'), (3,'Three');
+SELECT * FROM t1;
+CREATE TABLE t2 (line VARCHAR(100) NOT NULL) ENGINE=CONNECT FILE_NAME='tf1.txt';
+SELECT * FROM t2;
+
+--echo #
+--echo # Indexing works the same
+--echo #
+ALTER TABLE t1 ADD INDEX xc (c), ADD INDEX xd (d);
+SHOW INDEX FROM t1;
+SELECT d FROM t1 WHERE c = 2;
+ALTER TABLE t1 DROP INDEX xc, DROP INDEX xd;
+SHOW INDEX FROM t1;
+
+--echo #
+--echo # Other alterations do not modify the file
+--echo #
+ALTER TABLE t1 MODIFY COLUMN c CHAR(5) NOT NULL;
+SELECT * FROM t2;
+SHOW CREATE TABLE t1;
+#Wrong result
+--error ER_GET_ERRMSG
+SELECT * FROM t1;
+ALTER TABLE t1 MODIFY COLUMN c INT NOT NULL;
+
+--echo #
+--echo # Changing column order
+--echo #
+ALTER TABLE t1 MODIFY COLUMN c INT NOT NULL AFTER d;
+SELECT * FROM t2;
+SHOW CREATE TABLE t1;
+--echo # Wrong result
+SELECT * FROM t1;
+ALTER TABLE t1 MODIFY COLUMN c INT NOT NULL FIRST;
+--echo # What should have been done
+ALTER TABLE t1 MODIFY c INT NOT NULL FLAG=0 AFTER d, MODIFY d CHAR(10) NOT NULL FLAG=11;
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+
+--echo #
+--echo # Changing to another engine is Ok
+--echo # However, the data file is not deleted.
+--echo #
+ALTER TABLE t1 ENGINE=ARIA;
+SHOW CREATE TABLE t1;
+set @old_sql_mode=@@sql_mode;
+set sql_mode=ignore_bad_table_options;
+SHOW CREATE TABLE t1;
+set sql_mode=@old_sql_mode;
+SELECT * from t1;
+SELECT * from t2;
+
+--echo #
+--echo # Changing back to CONNECT fails
+--echo # Sure enough, the data file was not deleted.
+--echo #
+--error ER_UNKNOWN_ERROR
+ALTER TABLE t1 ENGINE=CONNECT;
+
+--echo #
+--echo # But changing back to CONNECT succeed
+--echo # if the data file does not exist.
+--echo #
+--remove_file $MYSQLD_DATADIR/test/tf1.txt
+ALTER TABLE t1 ENGINE=CONNECT;
+SHOW CREATE TABLE t1;
+SELECT * from t1;
+SELECT * from t2;
+
+DROP TABLE t1, t2;
+
+#
+# Clean up
+#
+--remove_file $MYSQLD_DATADIR/test/tf1.txt
diff --git a/storage/connect/mysql-test/connect/t/alter_xml.test b/storage/connect/mysql-test/connect/t/alter_xml.test
index decf5e76cdf..0b876296e58 100644
--- a/storage/connect/mysql-test/connect/t/alter_xml.test
+++ b/storage/connect/mysql-test/connect/t/alter_xml.test
@@ -1,29 +1,29 @@
---source have_libxml2.inc
-
---echo #
---echo # Testing changing table type (not in-place)
---echo #
-CREATE TABLE t1 (c INT NOT NULL, d CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV HEADER=1 QUOTED=1;
-INSERT INTO t1 VALUES (1,'One'), (2,'Two'), (3,'Three');
-SELECT * FROM t1;
-
---echo # This would fail if the top node name is not specified.
---echo # This is because the XML top node name defaults to the table name.
---echo # Sure enough the temporary table name begins with '#' and is rejected by XML.
---echo # Therefore the top node name must be specified (along with the row nodes name).
-ALTER TABLE t1 TABLE_TYPE=XML TABNAME=t1 OPTION_LIST='rownode=row';
-SELECT * FROM t1;
-SHOW CREATE TABLE t1;
-
---echo # Let us see the XML file
-CREATE TABLE t2 (line VARCHAR(100) NOT NULL) ENGINE=CONNECT FILE_NAME='t1.xml';
-SELECT * FROM t2;
---echo # NOTE: The first (ignored) row is due to the remaining HEADER=1 option.
-
---echo # Testing field option modification
-ALTER TABLE t1 MODIFY d CHAR(10) NOT NULL FIELD_FORMAT='@', HEADER=0;
-SELECT * FROM t1;
-SHOW CREATE TABLE t1;
-SELECT * FROM t2;
-
-DROP TABLE t1, t2;
+--source have_libxml2.inc
+
+--echo #
+--echo # Testing changing table type (not in-place)
+--echo #
+CREATE TABLE t1 (c INT NOT NULL, d CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV HEADER=1 QUOTED=1;
+INSERT INTO t1 VALUES (1,'One'), (2,'Two'), (3,'Three');
+SELECT * FROM t1;
+
+--echo # This would fail if the top node name is not specified.
+--echo # This is because the XML top node name defaults to the table name.
+--echo # Sure enough the temporary table name begins with '#' and is rejected by XML.
+--echo # Therefore the top node name must be specified (along with the row nodes name).
+ALTER TABLE t1 TABLE_TYPE=XML TABNAME=t1 OPTION_LIST='rownode=row';
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+
+--echo # Let us see the XML file
+CREATE TABLE t2 (line VARCHAR(100) NOT NULL) ENGINE=CONNECT FILE_NAME='t1.xml';
+SELECT * FROM t2;
+--echo # NOTE: The first (ignored) row is due to the remaining HEADER=1 option.
+
+--echo # Testing field option modification
+ALTER TABLE t1 MODIFY d CHAR(10) NOT NULL FIELD_FORMAT='@', HEADER=0;
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+SELECT * FROM t2;
+
+DROP TABLE t1, t2;
diff --git a/storage/connect/mysql-test/connect/t/bin.test b/storage/connect/mysql-test/connect/t/bin.test
index 6ef0ffc75ec..1e45bcaf93a 100644
--- a/storage/connect/mysql-test/connect/t/bin.test
+++ b/storage/connect/mysql-test/connect/t/bin.test
@@ -1,77 +1,77 @@
-let $MYSQLD_DATADIR= `select @@datadir`;
-
---copy_file $MTR_SUITE_DIR/std_data/Testbal.dat $MYSQLD_DATADIR/test/Testbal.dat
-
---echo #
---echo # Testing errors
---echo #
-CREATE TABLE t1
-(
- ID INT NOT NULL
-) Engine=CONNECT TABLE_TYPE=BIN FILE_NAME='nonexistent.txt';
---replace_regex /on .*test.nonexistent.txt/on DATADIR\/test\/nonexistent.txt/
-# TODO: check why this is needed for Windows
---replace_result Open(rt) Open(rb)
-SELECT * FROM t1;
-DROP TABLE t1;
-
-SET time_zone='+00:00';
-CREATE TABLE t1
-(
- fig INT(4) NOT NULL FIELD_FORMAT='C',
- name CHAR(10) not null,
- birth DATE NOT NULL,
- id CHAR(5) NOT NULL FIELD_FORMAT='S',
- salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
- dept INT(4) NOT NULL FIELD_FORMAT='S'
-) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat';
-SELECT * FROM t1;
-
---error ER_GET_ERRMSG
-INSERT INTO t1 VALUES (55555,'RONALD','1980-02-26','3333',4444.44,555);
-INSERT INTO t1 VALUES (5555,'RONALD','1980-02-26','3333',4444.44,555);
-SELECT * FROM t1;
-
-DROP TABLE t1;
-
---echo #
---echo # Testing READONLY tables
---echo #
-CREATE TABLE t1
-(
- fig INT(4) NOT NULL FIELD_FORMAT='C',
- name CHAR(10) not null,
- birth DATE NOT NULL,
- id CHAR(5) NOT NULL FIELD_FORMAT='S',
- salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
- dept INT(4) NOT NULL FIELD_FORMAT='S'
-) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat';
---error ER_OPEN_AS_READONLY
-INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
-ALTER TABLE t1 READONLY=NO;
-SHOW CREATE TABLE t1;
-INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
-SELECT * FROM t1;
-ALTER TABLE t1 READONLY=YES;
-SHOW CREATE TABLE t1;
---error ER_OPEN_AS_READONLY
-INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
-DROP TABLE t1;
-
-
---echo #
---echo # Testing that the underlying file is created
---echo #
-CREATE TABLE t1
-(
- c CHAR(4) NOT NULL FIELD_FORMAT='C'
-) ENGINE=CONNECT TABLE_TYPE=BIN FILE_NAME='bin2.dat';
-INSERT INTO t1 VALUES (10),(20),(300),(4000);
-SELECT * FROM t1;
-DROP TABLE t1;
-
-#
-# Clean up
-#
---remove_file $MYSQLD_DATADIR/test/Testbal.dat
---remove_file $MYSQLD_DATADIR/test/bin2.dat
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--copy_file $MTR_SUITE_DIR/std_data/Testbal.dat $MYSQLD_DATADIR/test/Testbal.dat
+
+--echo #
+--echo # Testing errors
+--echo #
+CREATE TABLE t1
+(
+ ID INT NOT NULL
+) Engine=CONNECT TABLE_TYPE=BIN FILE_NAME='nonexistent.txt';
+--replace_regex /on .*test.nonexistent.txt/on DATADIR\/test\/nonexistent.txt/
+# TODO: check why this is needed for Windows
+--replace_result Open(rt) Open(rb)
+SELECT * FROM t1;
+DROP TABLE t1;
+
+SET time_zone='+00:00';
+CREATE TABLE t1
+(
+ fig INT(4) NOT NULL FIELD_FORMAT='C',
+ name CHAR(10) NOT NULL,
+ birth DATE NOT NULL,
+ id CHAR(5) NOT NULL FIELD_FORMAT='S',
+ salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
+ dept INT(4) NOT NULL FIELD_FORMAT='S'
+) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat' OPTION_LIST='Endian=Little';
+SELECT * FROM t1;
+
+--error ER_GET_ERRMSG
+INSERT INTO t1 VALUES (55555,'RONALD','1980-02-26','3333',4444.44,555);
+INSERT INTO t1 VALUES (5555,'RONALD','1980-02-26','3333',4444.44,555);
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--echo #
+--echo # Testing READONLY tables
+--echo #
+CREATE TABLE t1
+(
+ fig INT(4) NOT NULL FIELD_FORMAT='C',
+ name CHAR(10) NOT NULL,
+ birth DATE NOT NULL,
+ id CHAR(5) NOT NULL FIELD_FORMAT='S',
+ salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
+ dept INT(4) NOT NULL FIELD_FORMAT='S'
+) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat' OPTION_LIST='Endian=Little';
+--error ER_OPEN_AS_READONLY
+INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
+ALTER TABLE t1 READONLY=NO;
+SHOW CREATE TABLE t1;
+INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
+SELECT * FROM t1;
+ALTER TABLE t1 READONLY=YES;
+SHOW CREATE TABLE t1;
+--error ER_OPEN_AS_READONLY
+INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing that the underlying file is created
+--echo #
+CREATE TABLE t1
+(
+ c CHAR(4) NOT NULL FIELD_FORMAT='C'
+) ENGINE=CONNECT TABLE_TYPE=BIN FILE_NAME='bin2.dat';
+INSERT INTO t1 VALUES (10),(20),(300),(4000);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Clean up
+#
+--remove_file $MYSQLD_DATADIR/test/Testbal.dat
+--remove_file $MYSQLD_DATADIR/test/bin2.dat
diff --git a/storage/connect/mysql-test/connect/t/datest.test b/storage/connect/mysql-test/connect/t/datest.test
index a986ce15a80..7fe5fcea8ff 100644
--- a/storage/connect/mysql-test/connect/t/datest.test
+++ b/storage/connect/mysql-test/connect/t/datest.test
@@ -1,16 +1,16 @@
---echo #
---echo # Testing out of range dates as (var)char
---echo #
-CREATE TABLE t1 (
-id INT NOT NULL,
-dat CHAR(10) NOT NULL,
-tim CHAR(8) DEFAULT '09:35:08',
-datim CHAR(19) DEFAULT '1789-08-10 14:20:30')
-ENGINE=CONNECT TABLE_TYPE=FIX;
-INSERT INTO t1(id,dat) VALUES(1,'1515-04-01'),(2,'2014-07-26'),(3,'2118-11-02');
-SELECT * FROM t1;
-SELECT id, DATE(datim) FROM t1 LIMIT 1;
-SELECT id, DAYNAME(dat) FROM t1;
-SELECT id, DAYNAME(datim) FROM t1 LIMIT 1;
-SELECT id, TIME(tim) FROM t1 LIMIT 1;
-DROP TABLE t1;
+--echo #
+--echo # Testing out of range dates as (var)char
+--echo #
+CREATE TABLE t1 (
+id INT NOT NULL,
+dat CHAR(10) NOT NULL,
+tim CHAR(8) DEFAULT '09:35:08',
+datim CHAR(19) DEFAULT '1789-08-10 14:20:30')
+ENGINE=CONNECT TABLE_TYPE=FIX;
+INSERT INTO t1(id,dat) VALUES(1,'1515-04-01'),(2,'2014-07-26'),(3,'2118-11-02');
+SELECT * FROM t1;
+SELECT id, DATE(datim) FROM t1 LIMIT 1;
+SELECT id, DAYNAME(dat) FROM t1;
+SELECT id, DAYNAME(datim) FROM t1 LIMIT 1;
+SELECT id, TIME(tim) FROM t1 LIMIT 1;
+DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/t/fmt.test b/storage/connect/mysql-test/connect/t/fmt.test
index 662bc70c8b1..2cea2dba7f9 100644
--- a/storage/connect/mysql-test/connect/t/fmt.test
+++ b/storage/connect/mysql-test/connect/t/fmt.test
@@ -1,85 +1,85 @@
-let $MYSQLD_DATADIR= `select @@datadir`;
---copy_file $MTR_SUITE_DIR/std_data/funny.txt $MYSQLD_DATADIR/test/funny.txt
---copy_file $MTR_SUITE_DIR/std_data/funny2.txt $MYSQLD_DATADIR/test/funny2.txt
-
---echo #
---echo # Testing errors
---echo #
-CREATE TABLE t1
-(
- ID INT NOT NULL field_format=' %n%d%n'
-) Engine=CONNECT table_type=FMT file_name='nonexistent.txt';
---replace_regex /on .*test.nonexistent.txt/on DATADIR\/test\/nonexistent.txt/
-# TODO: check why this is needed for Windows
---replace_result Open(rt) Open(rb)
-SELECT * FROM t1;
-DROP TABLE t1;
-
-
---echo #
---echo # Testing update on FMT tables
---echo #
-CREATE TABLE t1
-(
- id INT NOT NULL field_format=' %n%d%n'
-) ENGINE=CONNECT TABLE_TYPE=FMT FILE_NAME='t1.txt';
---error ER_GET_ERRMSG
-INSERT INTO t1 VALUES (10),(20);
-# TODO:
-#--error ER_GET_ERRMSG
-#UPDATE t1 SET id=20;
-#TRUNCATE TABLE t1;
-#DELETE FROM t1 WHERE id=10;
-#SELECT * FROM t1;
-DROP TABLE t1;
-#--remove_file $MYSQLD_DATADIR/test/t1.txt
-
-
---echo #
---echo # Testing manual examples
---echo #
-CREATE TABLE t1
-(
- ID Integer(5) not null field_format=' %n%d%n',
- NAME Char(16) not null field_format=" , '%n%[^']%n'",
- DEPNO Integer(4) not null field_format=' , #%n%d%n',
- SALARY Double(12,2) not null field_format=' ; %n%f%n'
-) Engine=CONNECT table_type=FMT file_name='funny.txt';
-SELECT * FROM t1;
-DROP TABLE t1;
-
-#
-# TODO: shoudn't a warning instead of error be returned on bad format?
-#
-CREATE TABLE t1
-(
- ID Integer(5) not null field_format=' %n%d%n',
- NAME Char(16) not null field_format=" , '%n%[^']%n'",
- DEPNO Integer(4) not null field_format=' , #%n%d%n',
- SALARY Double(12,2) not null field_format=' ; %n%f%n'
-) Engine=CONNECT table_type=FMT file_name='funny2.txt';
---error ER_GET_ERRMSG
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1
-(
- ID Integer(5) not null field_format=' %n%d%n',
- NAME Char(16) not null field_format=' , ''%n%[^'']%m',
- DEPNO Integer(4) not null field_format=''' , #%n%d%m',
- SALARY Double(12,2) not null field_format=' ; %n%f%n'
-) Engine=CONNECT table_type=FMT file_name='funny2.txt';
-SELECT * FROM t1;
---error ER_GET_ERRMSG
-UPDATE t1 SET SALARY=1234;
-# TODO: this query crashes
-# UPDATE t1 SET SALARY=1234 WHERE ID=56;
-DELETE FROM t1 WHERE ID=56;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-#
-# Clean up
-#
---remove_file $MYSQLD_DATADIR/test/funny.txt
---remove_file $MYSQLD_DATADIR/test/funny2.txt
+let $MYSQLD_DATADIR= `select @@datadir`;
+--copy_file $MTR_SUITE_DIR/std_data/funny.txt $MYSQLD_DATADIR/test/funny.txt
+--copy_file $MTR_SUITE_DIR/std_data/funny2.txt $MYSQLD_DATADIR/test/funny2.txt
+
+--echo #
+--echo # Testing errors
+--echo #
+CREATE TABLE t1
+(
+ ID INT NOT NULL field_format=' %n%d%n'
+) Engine=CONNECT table_type=FMT file_name='nonexistent.txt';
+--replace_regex /on .*test.nonexistent.txt/on DATADIR\/test\/nonexistent.txt/
+# TODO: check why this is needed for Windows
+--replace_result Open(rt) Open(rb)
+SELECT * FROM t1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing update on FMT tables
+--echo #
+CREATE TABLE t1
+(
+ id INT NOT NULL field_format=' %n%d%n'
+) ENGINE=CONNECT TABLE_TYPE=FMT FILE_NAME='t1.txt';
+--error ER_GET_ERRMSG
+INSERT INTO t1 VALUES (10),(20);
+# TODO:
+#--error ER_GET_ERRMSG
+#UPDATE t1 SET id=20;
+#TRUNCATE TABLE t1;
+#DELETE FROM t1 WHERE id=10;
+#SELECT * FROM t1;
+DROP TABLE t1;
+#--remove_file $MYSQLD_DATADIR/test/t1.txt
+
+
+--echo #
+--echo # Testing manual examples
+--echo #
+CREATE TABLE t1
+(
+ ID Integer(5) not null field_format=' %n%d%n',
+ NAME Char(16) not null field_format=" , '%n%[^']%n'",
+ DEPNO Integer(4) not null field_format=' , #%n%d%n',
+ SALARY Double(12,2) not null field_format=' ; %n%f%n'
+) Engine=CONNECT table_type=FMT file_name='funny.txt';
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# TODO: shoudn't a warning instead of error be returned on bad format?
+#
+CREATE TABLE t1
+(
+ ID Integer(5) not null field_format=' %n%d%n',
+ NAME Char(16) not null field_format=" , '%n%[^']%n'",
+ DEPNO Integer(4) not null field_format=' , #%n%d%n',
+ SALARY Double(12,2) not null field_format=' ; %n%f%n'
+) Engine=CONNECT table_type=FMT file_name='funny2.txt';
+--error ER_GET_ERRMSG
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1
+(
+ ID Integer(5) not null field_format=' %n%d%n',
+ NAME Char(16) not null field_format=' , ''%n%[^'']%m',
+ DEPNO Integer(4) not null field_format=''' , #%n%d%m',
+ SALARY Double(12,2) not null field_format=' ; %n%f%n'
+) Engine=CONNECT table_type=FMT file_name='funny2.txt';
+SELECT * FROM t1;
+--error ER_GET_ERRMSG
+UPDATE t1 SET SALARY=1234;
+# TODO: this query crashes
+# UPDATE t1 SET SALARY=1234 WHERE ID=56;
+DELETE FROM t1 WHERE ID=56;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Clean up
+#
+--remove_file $MYSQLD_DATADIR/test/funny.txt
+--remove_file $MYSQLD_DATADIR/test/funny2.txt
diff --git a/storage/connect/mysql-test/connect/t/general.test b/storage/connect/mysql-test/connect/t/general.test
index 66752b32099..34e5d4c7b6d 100644
--- a/storage/connect/mysql-test/connect/t/general.test
+++ b/storage/connect/mysql-test/connect/t/general.test
@@ -1,16 +1,16 @@
---echo #
---echo # Testing features not specific to any TABLE_TYPE
---echo #
---error ER_UNKNOWN_ERROR
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=NON_EXISTING;
-#SHOW CREATE TABLE t1;
-#DROP TABLE t1;
-
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX;
-INSERT INTO t1 VALUES (10);
-SELECT * FROM t1;
-#--error ER_GET_ERRMSG
---error ER_UNKNOWN_ERROR
-ALTER TABLE t1 TABLE_TYPE=NON_EXISTING;
-SELECT * FROM t1;
-DROP TABLE t1;
+--echo #
+--echo # Testing features not specific to any TABLE_TYPE
+--echo #
+--error ER_UNKNOWN_ERROR
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=NON_EXISTING;
+#SHOW CREATE TABLE t1;
+#DROP TABLE t1;
+
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX;
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+#--error ER_GET_ERRMSG
+--error ER_UNKNOWN_ERROR
+ALTER TABLE t1 TABLE_TYPE=NON_EXISTING;
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/t/json.test b/storage/connect/mysql-test/connect/t/json.test
index a7e630ed0cf..1cc2c054db4 100644
--- a/storage/connect/mysql-test/connect/t/json.test
+++ b/storage/connect/mysql-test/connect/t/json.test
@@ -1,247 +1,264 @@
---source include/not_embedded.inc
---source include/have_partition.inc
-
-let $MYSQLD_DATADIR= `select @@datadir`;
-
---copy_file $MTR_SUITE_DIR/std_data/biblio.jsn $MYSQLD_DATADIR/test/biblio.jsn
---copy_file $MTR_SUITE_DIR/std_data/expense.jsn $MYSQLD_DATADIR/test/expense.jsn
---copy_file $MTR_SUITE_DIR/std_data/mulexp3.jsn $MYSQLD_DATADIR/test/mulexp3.jsn
---copy_file $MTR_SUITE_DIR/std_data/mulexp4.jsn $MYSQLD_DATADIR/test/mulexp4.jsn
---copy_file $MTR_SUITE_DIR/std_data/mulexp5.jsn $MYSQLD_DATADIR/test/mulexp5.jsn
-
---echo #
---echo # Testing doc samples
---echo #
-CREATE TABLE t1
-(
- ISBN CHAR(15),
- LANG CHAR(2),
- SUBJECT CHAR(32),
- AUTHOR CHAR(64),
- TITLE CHAR(32),
- TRANSLATION CHAR(32),
- TRANSLATOR CHAR(80),
- PUBLISHER CHAR(32),
- DATEPUB int(4)
-) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
-SELECT * FROM t1;
-DROP TABLE t1;
-
-
---echo #
---echo # Testing Jpath. Get the number of authors
---echo #
-CREATE TABLE t1
-(
- ISBN CHAR(15),
- Language CHAR(2) FIELD_FORMAT='LANG',
- Subject CHAR(32) FIELD_FORMAT='SUBJECT',
- Authors INT(2) FIELD_FORMAT='AUTHOR:[#]',
- Title CHAR(32) FIELD_FORMAT='TITLE',
- Translation CHAR(32) FIELD_FORMAT='TRANSLATION',
- Translator CHAR(80) FIELD_FORMAT='TRANSLATOR',
- Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
- Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
- Year int(4) FIELD_FORMAT='DATEPUB'
-)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
-SELECT * FROM t1;
-DROP TABLE t1;
-
---echo #
---echo # Concatenates the authors
---echo #
-CREATE TABLE t1
-(
- ISBN CHAR(15),
- Language CHAR(2) FIELD_FORMAT='LANG',
- Subject CHAR(32) FIELD_FORMAT='SUBJECT',
- AuthorFN CHAR(128) FIELD_FORMAT='AUTHOR:[" and "]:FIRSTNAME',
- AuthorLN CHAR(128) FIELD_FORMAT='AUTHOR:[" and "]:LASTNAME',
- Title CHAR(32) FIELD_FORMAT='TITLE',
- Translation CHAR(32) FIELD_FORMAT='TRANSLATION',
- Translator CHAR(80) FIELD_FORMAT='TRANSLATOR',
- Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
- Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
- Year int(4) FIELD_FORMAT='DATEPUB'
-)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
-SELECT * FROM t1;
-DROP TABLE t1;
-
---echo #
---echo # Testing expanding authors
---echo #
-CREATE TABLE t1
-(
- ISBN CHAR(15),
- Language CHAR(2) FIELD_FORMAT='LANG',
- Subject CHAR(32) FIELD_FORMAT='SUBJECT',
- AuthorFN CHAR(128) FIELD_FORMAT='AUTHOR:[X]:FIRSTNAME',
- AuthorLN CHAR(128) FIELD_FORMAT='AUTHOR:[X]:LASTNAME',
- Title CHAR(32) FIELD_FORMAT='TITLE',
- Translation CHAR(32) FIELD_FORMAT='TRANSLATION',
- Translator CHAR(80) FIELD_FORMAT='TRANSLATOR',
- Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
- Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
- Year int(4) FIELD_FORMAT='DATEPUB'
-)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
-SELECT * FROM t1;
-UPDATE t1 SET AuthorFN = 'Philippe' WHERE AuthorLN = 'Knab';
-SELECT * FROM t1 WHERE ISBN = '9782212090819';
-
---echo #
---echo # To add an author a new table must be created
---echo #
-CREATE TABLE t2 (
-FIRSTNAME CHAR(32),
-LASTNAME CHAR(32))
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn' OPTION_LIST='Object=[2]:AUTHOR';
-SELECT * FROM t2;
-INSERT INTO t2 VALUES('Charles','Dickens');
-SELECT * FROM t1;
-DROP TABLE t1;
-DROP TABLE t2;
-
---echo #
---echo # Check the biblio file has the good format
---echo #
-CREATE TABLE t1
-(
- line char(255)
-)
-ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='biblio.jsn';
-SELECT * FROM t1;
-DROP TABLE t1;
-
---echo #
---echo # A file with 2 arrays
---echo #
-CREATE TABLE t1 (
-WHO CHAR(12),
-WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER',
-WHAT CHAR(32) FIELD_FORMAT='WEEK::EXPENSE:["+"]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK::EXPENSE:[+]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
-SELECT * FROM t1;
-DROP TABLE t1;
-
---echo #
---echo # Cannot be fully expanded
---echo #
-CREATE TABLE t1 (
-WHO CHAR(12),
-WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER',
-WHAT CHAR(32) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
---error ER_GET_ERRMSG
-SELECT * FROM t1;
-DROP TABLE t1;
-
---echo #
---echo # Expand expense in 3 one week tables
---echo #
-CREATE TABLE t2 (
-WHO CHAR(12),
-WEEK INT(2) FIELD_FORMAT='WEEK:[1]:NUMBER',
-WHAT CHAR(32) FIELD_FORMAT='WEEK:[1]:EXPENSE:[X]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[1]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
-SELECT * FROM t2;
-
-CREATE TABLE t3 (
-WHO CHAR(12),
-WEEK INT(2) FIELD_FORMAT='WEEK:[2]:NUMBER',
-WHAT CHAR(32) FIELD_FORMAT='WEEK:[2]:EXPENSE:[X]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[2]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
-SELECT * FROM t3;
-
-CREATE TABLE t4 (
-WHO CHAR(12),
-WEEK INT(2) FIELD_FORMAT='WEEK:[3]:NUMBER',
-WHAT CHAR(32) FIELD_FORMAT='WEEK:[3]:EXPENSE:[X]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[3]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
-SELECT * FROM t4;
-
---echo #
---echo # The expanded table is made as a TBL table
---echo #
-CREATE TABLE t1 (
-WHO CHAR(12),
-WEEK INT(2),
-WHAT CHAR(32),
-AMOUNT DOUBLE(8,2))
-ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t2,t3,t4';
-SELECT * FROM t1;
-DROP TABLE t1, t2, t3, t4;
-
---echo #
---echo # Three partial JSON tables
---echo #
-CREATE TABLE t2 (
-WHO CHAR(12),
-WEEK INT(2),
-WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp3.jsn';
-SELECT * FROM t2;
-
-CREATE TABLE t3 (
-WHO CHAR(12),
-WEEK INT(2),
-WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp4.jsn';
-SELECT * FROM t3;
-
-CREATE TABLE t4 (
-WHO CHAR(12),
-WEEK INT(2),
-WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp5.jsn';
-SELECT * FROM t4;
-
---echo #
---echo # The complete table can be a multiple JSON table
---echo #
-CREATE TABLE t1 (
-WHO CHAR(12),
-WEEK INT(2),
-WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp*.jsn' MULTIPLE=1;
-SELECT * FROM t1 ORDER BY WHO, WEEK, WHAT, AMOUNT;
-DROP TABLE t1;
-
---echo #
---echo # Or also a partition JSON table
---echo #
-CREATE TABLE t1 (
-WHO CHAR(12),
-WEEK INT(2),
-WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
-AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp%s.jsn';
-ALTER TABLE t1
-PARTITION BY LIST COLUMNS(WEEK) (
-PARTITION `3` VALUES IN(3),
-PARTITION `4` VALUES IN(4),
-PARTITION `5` VALUES IN(5));
-SHOW WARNINGS;
-SELECT * FROM t1;
-SELECT * FROM t1 WHERE WEEK = 4;
-DROP TABLE t1, t2, t3, t4;
-
-#
-# Clean up
-#
---remove_file $MYSQLD_DATADIR/test/biblio.jsn
---remove_file $MYSQLD_DATADIR/test/expense.jsn
---remove_file $MYSQLD_DATADIR/test/mulexp3.jsn
---remove_file $MYSQLD_DATADIR/test/mulexp4.jsn
---remove_file $MYSQLD_DATADIR/test/mulexp5.jsn
+--source include/not_embedded.inc
+--source include/have_partition.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--copy_file $MTR_SUITE_DIR/std_data/biblio.json $MYSQLD_DATADIR/test/biblio.json
+--copy_file $MTR_SUITE_DIR/std_data/expense.json $MYSQLD_DATADIR/test/expense.json
+--copy_file $MTR_SUITE_DIR/std_data/mulexp3.json $MYSQLD_DATADIR/test/mulexp3.json
+--copy_file $MTR_SUITE_DIR/std_data/mulexp4.json $MYSQLD_DATADIR/test/mulexp4.json
+--copy_file $MTR_SUITE_DIR/std_data/mulexp5.json $MYSQLD_DATADIR/test/mulexp5.json
+
+--echo #
+--echo # Testing doc samples
+--echo #
+CREATE TABLE t1
+(
+ ISBN CHAR(15),
+ LANG CHAR(2),
+ SUBJECT CHAR(32),
+ AUTHOR CHAR(64),
+ TITLE CHAR(32),
+ TRANSLATION CHAR(32),
+ TRANSLATOR CHAR(80),
+ PUBLISHER CHAR(32),
+ DATEPUB int(4)
+) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
+SELECT * FROM t1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing Jpath. Get the number of authors
+--echo #
+CREATE TABLE t1
+(
+ ISBN CHAR(15),
+ Language CHAR(2) FIELD_FORMAT='LANG',
+ Subject CHAR(32) FIELD_FORMAT='SUBJECT',
+ Authors INT(2) FIELD_FORMAT='AUTHOR:[#]',
+ Title CHAR(32) FIELD_FORMAT='TITLE',
+ Translation CHAR(32) FIELD_FORMAT='TRANSLATION',
+ Translator CHAR(80) FIELD_FORMAT='TRANSLATOR',
+ Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
+ Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
+ Year int(4) FIELD_FORMAT='DATEPUB'
+)
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # Concatenates the authors
+--echo #
+CREATE TABLE t1
+(
+ ISBN CHAR(15),
+ Language CHAR(2) FIELD_FORMAT='LANG',
+ Subject CHAR(32) FIELD_FORMAT='SUBJECT',
+ AuthorFN CHAR(128) FIELD_FORMAT='AUTHOR:[" and "]:FIRSTNAME',
+ AuthorLN CHAR(128) FIELD_FORMAT='AUTHOR:[" and "]:LASTNAME',
+ Title CHAR(32) FIELD_FORMAT='TITLE',
+ Translation CHAR(32) FIELD_FORMAT='TRANSLATION',
+ Translator CHAR(80) FIELD_FORMAT='TRANSLATOR',
+ Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
+ Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
+ Year int(4) FIELD_FORMAT='DATEPUB'
+)
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing expanding authors
+--echo #
+CREATE TABLE t1
+(
+ ISBN CHAR(15),
+ Language CHAR(2) FIELD_FORMAT='LANG',
+ Subject CHAR(32) FIELD_FORMAT='SUBJECT',
+ AuthorFN CHAR(128) FIELD_FORMAT='AUTHOR:[X]:FIRSTNAME',
+ AuthorLN CHAR(128) FIELD_FORMAT='AUTHOR:[X]:LASTNAME',
+ Title CHAR(32) FIELD_FORMAT='TITLE',
+ Translation CHAR(32) FIELD_FORMAT='TRANSLATION',
+ Translator CHAR(80) FIELD_FORMAT='TRANSLATOR',
+ Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
+ Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
+ Year int(4) FIELD_FORMAT='DATEPUB'
+)
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
+SELECT * FROM t1;
+UPDATE t1 SET AuthorFN = 'Philippe' WHERE AuthorLN = 'Knab';
+SELECT * FROM t1 WHERE ISBN = '9782212090819';
+
+--echo #
+--echo # To add an author a new table must be created
+--echo #
+CREATE TABLE t2 (
+FIRSTNAME CHAR(32),
+LASTNAME CHAR(32))
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json' OPTION_LIST='Object=[1]:AUTHOR';
+SELECT * FROM t2;
+INSERT INTO t2 VALUES('Charles','Dickens');
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP TABLE t2;
+
+--echo #
+--echo # Check the biblio file has the good format
+--echo #
+CREATE TABLE t1
+(
+ line char(255)
+)
+ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='biblio.json';
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # A file with 2 arrays
+--echo #
+CREATE TABLE t1 (
+WHO CHAR(12),
+WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER',
+WHAT CHAR(32) FIELD_FORMAT='WEEK::EXPENSE:["+"]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK::EXPENSE:[+]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # Now it can be fully expanded
+--echo #
+CREATE TABLE t1 (
+WHO CHAR(12),
+WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER',
+WHAT CHAR(32) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
+#--error ER_GET_ERRMSG
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # A table showing many calculated results
+--echo #
+CREATE TABLE t1 (
+WHO CHAR(12) NOT NULL,
+WEEKS CHAR(12) NOT NULL FIELD_FORMAT='WEEK:[", "]:NUMBER',
+SUMS CHAR(64) NOT NULL FIELD_FORMAT='WEEK:["+"]:EXPENSE:[+]:AMOUNT',
+SUM DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[+]:EXPENSE:[+]:AMOUNT',
+AVGS CHAR(64) NOT NULL FIELD_FORMAT='WEEK:["+"]:EXPENSE:[!]:AMOUNT',
+SUMAVG DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[+]:EXPENSE:[!]:AMOUNT',
+AVGSUM DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[!]:EXPENSE:[+]:AMOUNT',
+AVGAVG DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[!]:EXPENSE:[!]:AMOUNT',
+AVERAGE DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[!]:EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # Expand expense in 3 one week tables
+--echo #
+CREATE TABLE t2 (
+WHO CHAR(12),
+WEEK INT(2) FIELD_FORMAT='WEEK:[0]:NUMBER',
+WHAT CHAR(32) FIELD_FORMAT='WEEK:[0]:EXPENSE:[X]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[0]:EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
+SELECT * FROM t2;
+
+CREATE TABLE t3 (
+WHO CHAR(12),
+WEEK INT(2) FIELD_FORMAT='WEEK:[1]:NUMBER',
+WHAT CHAR(32) FIELD_FORMAT='WEEK:[1]:EXPENSE:[X]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[1]:EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
+SELECT * FROM t3;
+
+CREATE TABLE t4 (
+WHO CHAR(12),
+WEEK INT(2) FIELD_FORMAT='WEEK:[2]:NUMBER',
+WHAT CHAR(32) FIELD_FORMAT='WEEK:[2]:EXPENSE:[X]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[2]:EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
+SELECT * FROM t4;
+
+--echo #
+--echo # The expanded table is made as a TBL table
+--echo #
+CREATE TABLE t1 (
+WHO CHAR(12),
+WEEK INT(2),
+WHAT CHAR(32),
+AMOUNT DOUBLE(8,2))
+ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t2,t3,t4';
+SELECT * FROM t1;
+DROP TABLE t1, t2, t3, t4;
+
+--echo #
+--echo # Three partial JSON tables
+--echo #
+CREATE TABLE t2 (
+WHO CHAR(12),
+WEEK INT(2),
+WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp3.json';
+SELECT * FROM t2;
+
+CREATE TABLE t3 (
+WHO CHAR(12),
+WEEK INT(2),
+WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp4.json';
+SELECT * FROM t3;
+
+CREATE TABLE t4 (
+WHO CHAR(12),
+WEEK INT(2),
+WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp5.json';
+SELECT * FROM t4;
+
+--echo #
+--echo # The complete table can be a multiple JSON table
+--echo #
+CREATE TABLE t1 (
+WHO CHAR(12),
+WEEK INT(2),
+WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp*.json' MULTIPLE=1;
+SELECT * FROM t1 ORDER BY WHO, WEEK, WHAT, AMOUNT;
+DROP TABLE t1;
+
+--echo #
+--echo # Or also a partition JSON table
+--echo #
+CREATE TABLE t1 (
+WHO CHAR(12),
+WEEK INT(2),
+WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
+AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp%s.json';
+ALTER TABLE t1
+PARTITION BY LIST COLUMNS(WEEK) (
+PARTITION `3` VALUES IN(3),
+PARTITION `4` VALUES IN(4),
+PARTITION `5` VALUES IN(5));
+SHOW WARNINGS;
+SELECT * FROM t1;
+SELECT * FROM t1 WHERE WEEK = 4;
+DROP TABLE t1, t2, t3, t4;
+
+#
+# Clean up
+#
+--remove_file $MYSQLD_DATADIR/test/biblio.json
+--remove_file $MYSQLD_DATADIR/test/expense.json
+--remove_file $MYSQLD_DATADIR/test/mulexp3.json
+--remove_file $MYSQLD_DATADIR/test/mulexp4.json
+--remove_file $MYSQLD_DATADIR/test/mulexp5.json
diff --git a/storage/connect/mysql-test/connect/t/json_udf.inc b/storage/connect/mysql-test/connect/t/json_udf.inc
new file mode 100644
index 00000000000..098fff3663e
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/json_udf.inc
@@ -0,0 +1,36 @@
+--disable_query_log
+#
+# Check if server has support for loading plugins
+#
+if (`SELECT @@have_dynamic_loading != 'YES'`) {
+ --skip UDF requires dynamic loading
+}
+if (!$HA_CONNECT_SO) {
+ --skip Needs a dynamically built ha_connect.so
+}
+
+let $is_win = `select convert(@@version_compile_os using latin1) IN ("Win32","Win64","Windows")`;
+
+if ($is_win)
+{
+--eval CREATE FUNCTION Json_Array RETURNS STRING SONAME 'ha_connect.dll';
+--eval CREATE FUNCTION Json_Array_Add RETURNS STRING SONAME 'ha_connect.dll';
+--eval CREATE FUNCTION Json_Object RETURNS STRING SONAME 'ha_connect.dll';
+--eval CREATE FUNCTION Json_Object_Nonull RETURNS STRING SONAME 'ha_connect.dll';
+--eval CREATE FUNCTION Json_Value returns STRING SONAME 'ha_connect.dll';
+--eval CREATE AGGREGATE FUNCTION Json_Array_Grp RETURNS STRING SONAME 'ha_connect.dll';
+--eval CREATE AGGREGATE FUNCTION Json_Object_Grp RETURNS STRING SONAME 'ha_connect.dll';
+}
+
+if (!$is_win)
+{
+--eval CREATE FUNCTION Json_Array RETURNS STRING SONAME 'ha_connect.so';
+--eval CREATE FUNCTION Json_Array_Add RETURNS STRING SONAME 'ha_connect.so';
+--eval CREATE FUNCTION Json_Object RETURNS STRING SONAME 'ha_connect.so';
+--eval CREATE FUNCTION Json_Object_Nonull RETURNS STRING SONAME 'ha_connect.so';
+--eval CREATE FUNCTION Json_Value returns STRING SONAME 'ha_connect.so';
+--eval CREATE AGGREGATE FUNCTION Json_Array_Grp RETURNS STRING SONAME 'ha_connect.so';
+--eval CREATE AGGREGATE FUNCTION Json_Object_Grp RETURNS STRING SONAME 'ha_connect.so';
+}
+--enable_query_log
+
diff --git a/storage/connect/mysql-test/connect/t/json_udf.test b/storage/connect/mysql-test/connect/t/json_udf.test
new file mode 100644
index 00000000000..b4427517ca5
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/json_udf.test
@@ -0,0 +1,93 @@
+--source json_udf.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--copy_file $MTR_SUITE_DIR/std_data/biblio.json $MYSQLD_DATADIR/test/biblio.json
+--copy_file $MTR_SUITE_DIR/std_data/employee.dat $MYSQLD_DATADIR/test/employee.dat
+
+--echo #
+--echo # Test UDF's with constant arguments
+--echo #
+SELECT Json_Array();
+SELECT Json_Object(56,3.1416,'foo',NULL);
+SELECT Json_Object(56 qty,3.1416 price,'foo' truc, NULL garanty);
+SELECT Json_Array(56,3.1416,'My name is "Foo"',NULL);
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL)) Array;
+SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL),'One more') Array;
+SELECT Json_Array_Add(Json_Value('one value'),'One more');
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Array_Add('one value','One more');
+SELECT Json_Array_Add('one value' json_,'One more');
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Value(56,3.1416,'foo',NULL);
+SELECT Json_Value(3.1416);
+SELECT Json_Value('foo');
+SELECT Json_Value(NULL);
+SELECT Json_Value();
+SELECT Json_Object();
+SELECT Json_Object(Json_Array(56,3.1416,'foo'),NULL);
+SELECT Json_Array(Json_Array(56,3.1416,'foo'),NULL);
+SELECT Json_Array(Json_Object(56 "qty",3.1416 "price",'foo'),NULL);
+
+--echo #
+--echo # Test UDF's with column arguments
+--echo #
+CREATE TABLE t1
+(
+ ISBN CHAR(15),
+ LANG CHAR(2),
+ SUBJECT CHAR(32),
+ AUTHOR CHAR(64),
+ TITLE CHAR(32),
+ TRANSLATION CHAR(32),
+ TRANSLATOR CHAR(80),
+ PUBLISHER CHAR(32),
+ DATEPUB int(4)
+) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
+
+SELECT Json_Array(AUTHOR, TITLE, DATEPUB) FROM t1;
+SELECT Json_Object(AUTHOR, TITLE, DATEPUB) FROM t1;
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Array_Grp(TITLE, DATEPUB) FROM t1;
+SELECT Json_Array_Grp(TITLE) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (
+ SERIALNO CHAR(5) NOT NULL,
+ NAME VARCHAR(12) NOT NULL FLAG=6,
+ SEX SMALLINT(1) NOT NULL,
+ TITLE VARCHAR(15) NOT NULL FLAG=20,
+ MANAGER CHAR(5) DEFAULT NULL,
+ DEPARTMENT CHAr(4) NOT NULL FLAG=41,
+ SECRETARY CHAR(5) DEFAULT NULL FLAG=46,
+ SALARY DOUBLE(8,2) NOT NULL FLAG=52
+) ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=8 FILE_NAME='employee.dat' ENDING=1;
+
+SELECT Json_Object(SERIALNO, NAME, TITLE, SALARY) FROM t1 WHERE NAME = 'MERCHANT';
+SELECT DEPARTMENT, Json_Array_Grp(NAME) FROM t1 GROUP BY DEPARTMENT;
+set connect_json_grp_size=30;
+SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t1 GROUP BY DEPARTMENT;
+SELECT Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) FROM t1 GROUP BY DEPARTMENT;
+SELECT Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT;
+SELECT Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT, TITLE;
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Object_Grp(SALARY) FROM t1;
+SELECT Json_Object_Grp(SALARY, NAME) FROM t1;
+SELECT Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES") FROM t1 GROUP BY DEPARTMENT;
+SELECT Json_Array_Grp(NAME) from t1;
+DROP TABLE t1;
+
+DROP FUNCTION Json_Array;
+DROP FUNCTION Json_Array_Add;
+DROP FUNCTION Json_Object;
+DROP FUNCTION Json_Object_Nonull;
+DROP FUNCTION Json_Value;
+DROP FUNCTION Json_Array_Grp;
+DROP FUNCTION Json_Object_Grp;
+
+#
+# Clean up
+#
+--remove_file $MYSQLD_DATADIR/test/biblio.json
+--remove_file $MYSQLD_DATADIR/test/employee.dat
diff --git a/storage/connect/mysql-test/connect/t/mrr.test b/storage/connect/mysql-test/connect/t/mrr.test
index 37289ad427f..4b9e64bdaa3 100644
--- a/storage/connect/mysql-test/connect/t/mrr.test
+++ b/storage/connect/mysql-test/connect/t/mrr.test
@@ -1,66 +1,66 @@
-let $MYSQLD_DATADIR= `select @@datadir`;
---copy_file $MTR_SUITE_DIR/std_data/emp.txt $MYSQLD_DATADIR/test/emp.txt
-
---echo #
---echo # Show MRR setting. The way it is done is because the t3 table cannot be directly based on
---echo # the information_schema.session_variables table. Not being a CONNECT table, it would be
---echo # read using an intermediate MYSQL table using the MySQL API and could not reflect the
---echo # current session variable change (the call would create another session) This would be
---echo # correct only for querying GLOBAL variables but is not what we want to do here.
---echo #
-CREATE TABLE t2 (
-name VARCHAR(64) NOT NULL,
-value VARCHAR(1024) NOT NULL
-) ENGINE=CONNECT TABLE_TYPE=DOS;
-INSERT INTO t2 SELECT * FROM information_schema.session_variables WHERE variable_name = 'OPTIMIZER_SWITCH';
-# Check that MRR is OFF by default
-create table t3 (
-name CHAR(32) NOT NULL,
-value CHAR(64) NOT NULL
-) ENGINE=CONNECT TABLE_TYPE=XCOL TABNAME=t2 OPTION_LIST='Colname=value';
-SELECT value FROM t3 WHERE value LIKE 'mrr%';
-
---echo #
---echo # Testing indexing with MRR OFF
---echo #
-CREATE TABLE t1
-(
- matricule INT(4) KEY NOT NULL field_format='Z',
- nom VARCHAR(16) NOT NULL,
- prenom VARCHAR(20) NOT NULL,
- sexe SMALLINT(1) NOT NULL COMMENT 'sexe 1:M 2:F',
- aanais INT(4) NOT NULL,
- mmnais INT(2) NOT NULL,
- ddentree DATE NOT NULL date_format='YYYYMM',
- ddnom DATE NOT NULL date_format='YYYYMM',
- brut INT(5) NOT NULL,
- net DOUBLE(8,2) NOT NULL,
- service INT(2) NOT NULL,
- sitmat CHAR(1) NOT NULL,
- formation CHAR(5) NOT NULL,
- INDEX NP(nom,prenom)
-) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='emp.txt' ENDING=2;
-SELECT * FROM t1 LIMIT 10;
---echo # Without MRR, the rows are retrieved sorted by name
-SELECT matricule, nom, prenom, sitmat, net FROM t1 WHERE nom IN ('ETANG','FOCH','CERF','ITALIE','ROI');
-
---echo #
---echo # Testing indexing with MRR ON
---echo #
-SET @@LOCAL.OPTIMIZER_SWITCH='mrr=on';
---echo # Refresh the t2 table to reflect the change
-UPDATE t2, information_schema.session_variables SET value = variable_value WHERE variable_name = 'OPTIMIZER_SWITCH';
---echo # Check that MRR is ON for the session
-SELECT value FROM t3 WHERE value LIKE 'mrr%';
---echo # With MRR, the rows are retrieved sorted by their position in the table
-SELECT matricule, nom, prenom, sitmat, net FROM t1 WHERE nom IN ('ETANG','FOCH','CERF','ITALIE','ROI');
-
-DROP TABLE t1;
-DROP TABLE t2;
-DROP TABLE t3;
-
-#
-# Clean up
-#
-SET @@LOCAL.OPTIMIZER_SWITCH='mrr=off';
---remove_file $MYSQLD_DATADIR/test/emp.txt
+let $MYSQLD_DATADIR= `select @@datadir`;
+--copy_file $MTR_SUITE_DIR/std_data/emp.txt $MYSQLD_DATADIR/test/emp.txt
+
+--echo #
+--echo # Show MRR setting. The way it is done is because the t3 table cannot be directly based on
+--echo # the information_schema.session_variables table. Not being a CONNECT table, it would be
+--echo # read using an intermediate MYSQL table using the MySQL API and could not reflect the
+--echo # current session variable change (the call would create another session) This would be
+--echo # correct only for querying GLOBAL variables but is not what we want to do here.
+--echo #
+CREATE TABLE t2 (
+name VARCHAR(64) NOT NULL,
+value VARCHAR(1024) NOT NULL
+) ENGINE=CONNECT TABLE_TYPE=DOS;
+INSERT INTO t2 SELECT * FROM information_schema.session_variables WHERE variable_name = 'OPTIMIZER_SWITCH';
+# Check that MRR is OFF by default
+create table t3 (
+name CHAR(32) NOT NULL,
+value CHAR(64) NOT NULL
+) ENGINE=CONNECT TABLE_TYPE=XCOL TABNAME=t2 OPTION_LIST='Colname=value';
+SELECT value FROM t3 WHERE value LIKE 'mrr%';
+
+--echo #
+--echo # Testing indexing with MRR OFF
+--echo #
+CREATE TABLE t1
+(
+ matricule INT(4) KEY NOT NULL field_format='Z',
+ nom VARCHAR(16) NOT NULL,
+ prenom VARCHAR(20) NOT NULL,
+ sexe SMALLINT(1) NOT NULL COMMENT 'sexe 1:M 2:F',
+ aanais INT(4) NOT NULL,
+ mmnais INT(2) NOT NULL,
+ ddentree DATE NOT NULL date_format='YYYYMM',
+ ddnom DATE NOT NULL date_format='YYYYMM',
+ brut INT(5) NOT NULL,
+ net DOUBLE(8,2) NOT NULL,
+ service INT(2) NOT NULL,
+ sitmat CHAR(1) NOT NULL,
+ formation CHAR(5) NOT NULL,
+ INDEX NP(nom,prenom)
+) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='emp.txt' ENDING=2;
+SELECT * FROM t1 LIMIT 10;
+--echo # Without MRR, the rows are retrieved sorted by name
+SELECT matricule, nom, prenom, sitmat, net FROM t1 WHERE nom IN ('ETANG','FOCH','CERF','ITALIE','ROI');
+
+--echo #
+--echo # Testing indexing with MRR ON
+--echo #
+SET @@LOCAL.OPTIMIZER_SWITCH='mrr=on';
+--echo # Refresh the t2 table to reflect the change
+UPDATE t2, information_schema.session_variables SET value = variable_value WHERE variable_name = 'OPTIMIZER_SWITCH';
+--echo # Check that MRR is ON for the session
+SELECT value FROM t3 WHERE value LIKE 'mrr%';
+--echo # With MRR, the rows are retrieved sorted by their position in the table
+SELECT matricule, nom, prenom, sitmat, net FROM t1 WHERE nom IN ('ETANG','FOCH','CERF','ITALIE','ROI');
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+
+#
+# Clean up
+#
+SET @@LOCAL.OPTIMIZER_SWITCH='mrr=off';
+--remove_file $MYSQLD_DATADIR/test/emp.txt
diff --git a/storage/connect/mysql-test/connect/t/mul.test b/storage/connect/mysql-test/connect/t/mul.test
index 451b38799ad..97caba02b86 100644
--- a/storage/connect/mysql-test/connect/t/mul.test
+++ b/storage/connect/mysql-test/connect/t/mul.test
@@ -1,43 +1,43 @@
---echo #
---echo # Testing multiple 1
---echo #
-CREATE TABLE `t1` (
- `a` char(10) DEFAULT NULL,
- `b` char(10) DEFAULT NULL
-) ENGINE=CONNECT DEFAULT CHARSET=latin1 `table_type`=CSV `sep_char`=';';
-INSERT INTO t1 VALUES('test1','bla');
-SELECT * FROM t1;
-
-CREATE TABLE `t2` (
- `a` char(10) DEFAULT NULL,
- `b` char(10) DEFAULT NULL
-) ENGINE=CONNECT DEFAULT CHARSET=latin1 `table_type`=CSV `sep_char`=';';
-INSERT INTO t2 VALUES('test2','blub');
-SELECT * FROM t2;
-
-CREATE TABLE `t_all` (
- `a` char(10) DEFAULT NULL,
- `b` char(10) DEFAULT NULL
-) ENGINE=CONNECT DEFAULT CHARSET=latin1 `table_type`=CSV `file_name`='t*.csv' `sep_char`=';' `multiple`=1;
-SELECT * FROM t_all order by `a`;
-
---echo #
---echo # Testing multiple 2
---echo #
-CREATE table fnlist (
-fn char(8) not null
-) ENGINE=CONNECT DEFAULT CHARSET=latin1 table_type=DOS;
-INSERT INTO fnlist VALUES('t1.csv'),('t2.csv');
-SELECT fn FROM fnlist;
-
-CREATE TABLE `tblist` (
- `a` char(10) DEFAULT NULL,
- `b` char(10) DEFAULT NULL
-) ENGINE=CONNECT DEFAULT CHARSET=latin1 `table_type`=CSV `file_name`='fnlist.dos' `sep_char`=';' `multiple`=2;
-SELECT * FROM tblist;
-
-DROP TABLE t1;
-DROP TABLE t2;
-DROP TABLE t_all;
-DROP TABLE fnlist;
-DROP TABLE tblist;
+--echo #
+--echo # Testing multiple 1
+--echo #
+CREATE TABLE `t1` (
+ `a` char(10) DEFAULT NULL,
+ `b` char(10) DEFAULT NULL
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `table_type`=CSV `sep_char`=';';
+INSERT INTO t1 VALUES('test1','bla');
+SELECT * FROM t1;
+
+CREATE TABLE `t2` (
+ `a` char(10) DEFAULT NULL,
+ `b` char(10) DEFAULT NULL
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `table_type`=CSV `sep_char`=';';
+INSERT INTO t2 VALUES('test2','blub');
+SELECT * FROM t2;
+
+CREATE TABLE `t_all` (
+ `a` char(10) DEFAULT NULL,
+ `b` char(10) DEFAULT NULL
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `table_type`=CSV `file_name`='t*.csv' `sep_char`=';' `multiple`=1;
+SELECT * FROM t_all order by `a`;
+
+--echo #
+--echo # Testing multiple 2
+--echo #
+CREATE table fnlist (
+fn char(8) not null
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 table_type=DOS;
+INSERT INTO fnlist VALUES('t1.csv'),('t2.csv');
+SELECT fn FROM fnlist;
+
+CREATE TABLE `tblist` (
+ `a` char(10) DEFAULT NULL,
+ `b` char(10) DEFAULT NULL
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `table_type`=CSV `file_name`='fnlist.dos' `sep_char`=';' `multiple`=2;
+SELECT * FROM tblist;
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t_all;
+DROP TABLE fnlist;
+DROP TABLE tblist;
diff --git a/storage/connect/mysql-test/connect/t/myconn.inc b/storage/connect/mysql-test/connect/t/myconn.inc
index bdd60687d87..54c698e7c0f 100644
--- a/storage/connect/mysql-test/connect/t/myconn.inc
+++ b/storage/connect/mysql-test/connect/t/myconn.inc
@@ -1,27 +1,27 @@
---source include/not_embedded.inc
-
-let $PORT= `select @@port`;
-
---disable_query_log
---replace_result $PORT PORT
---error 0,ER_UNKNOWN_ERROR
-eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL
- CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/tx1';
-if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
- WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
- AND ENGINE='CONNECT'
- AND CREATE_OPTIONS LIKE '%`table_type`=MySQL%'`)
-{
- Skip Need MySQL support;
-}
-DROP TABLE t1;
---enable_query_log
-
-connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,);
-connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,);
-
-connection master;
-CREATE DATABASE connect;
-
-connection slave;
-CREATE DATABASE connect;
+--source include/not_embedded.inc
+
+let $PORT= `select @@port`;
+
+--disable_query_log
+--replace_result $PORT PORT
+--error 0,ER_UNKNOWN_ERROR
+eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/tx1';
+if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
+ WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
+ AND ENGINE='CONNECT'
+ AND CREATE_OPTIONS LIKE '%`table_type`=MySQL%'`)
+{
+ Skip Need MySQL support;
+}
+DROP TABLE t1;
+--enable_query_log
+
+connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,);
+connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,);
+
+connection master;
+CREATE DATABASE connect;
+
+connection slave;
+CREATE DATABASE connect;
diff --git a/storage/connect/mysql-test/connect/t/myconn_cleanup.inc b/storage/connect/mysql-test/connect/t/myconn_cleanup.inc
index ba2d99ed8b4..db473e512c1 100644
--- a/storage/connect/mysql-test/connect/t/myconn_cleanup.inc
+++ b/storage/connect/mysql-test/connect/t/myconn_cleanup.inc
@@ -1,9 +1,9 @@
-connection master;
---disable_warnings
-DROP TABLE IF EXISTS connect.t1;
-DROP DATABASE IF EXISTS connect;
-
-connection slave;
-DROP TABLE IF EXISTS connect.t1;
-DROP DATABASE IF EXISTS connect;
---enable_warnings
+connection master;
+--disable_warnings
+DROP TABLE IF EXISTS connect.t1;
+DROP DATABASE IF EXISTS connect;
+
+connection slave;
+DROP TABLE IF EXISTS connect.t1;
+DROP DATABASE IF EXISTS connect;
+--enable_warnings
diff --git a/storage/connect/mysql-test/connect/t/mysql.test b/storage/connect/mysql-test/connect/t/mysql.test
index e245587e562..7585c202b8b 100644
--- a/storage/connect/mysql-test/connect/t/mysql.test
+++ b/storage/connect/mysql-test/connect/t/mysql.test
@@ -1,472 +1,472 @@
--- source include/not_embedded.inc
-
-#
-# TODO: consider a possibility to run this test
-# against some remote MySQL server
-#
-
-let $PORT= `select @@port`;
-
---disable_query_log
---replace_result $PORT PORT
---error 0,ER_UNKNOWN_ERROR
---eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='tx1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
- WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
- AND ENGINE='CONNECT'
- AND CREATE_OPTIONS LIKE '%`table_type`=MySQL%'`)
-{
- Skip Need MySQL support;
-}
-DROP TABLE t1;
---enable_query_log
-
-# TODO: remote VARCHAR is displayed as CHAR
-
-CREATE TABLE t1 (a int, b char(10));
-INSERT INTO t1 VALUES (NULL,NULL),(0,'test00'),(1,'test01'),(2,'test02'),(3,'test03');
-SELECT * FROM t1;
-
---echo #
---echo # Testing errors
---echo #
-
-# Bad user name
-# Suppress "mysql_real_connect failed:" (printed in _DEBUG build)
---replace_result $PORT PORT "mysql_real_connect failed: " ""
---error ER_UNKNOWN_ERROR
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root1,port=$PORT'
-
-# Bad database name
---replace_result $PORT PORT "mysql_real_connect failed: " ""
---error ER_UNKNOWN_ERROR
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL DBNAME='unknown' TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-
-# Bad database name, with OPTION_LIST going first.
---replace_result $PORT PORT "mysql_real_connect failed: " ""
---error ER_UNKNOWN_ERROR
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL OPTION_LIST='host=localhost,user=root,port=$PORT' DBNAME='unknown' TABNAME='t1'
-
-# Bad table name
---replace_result $PORT PORT
---error ER_UNKNOWN_ERROR
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='unknown' OPTION_LIST='host=localhost,user=root,port=$PORT'
---error ER_NO_SUCH_TABLE
-SHOW CREATE TABLE t2;
-
-# Bad column name
---replace_result $PORT PORT
---eval CREATE TABLE t2 (x int, y char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
---error ER_GET_ERRMSG
-SELECT * FROM t2;
-DROP TABLE t2;
-
-# The remote table disappeared
---replace_result $PORT PORT
---eval CREATE TABLE t2 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-ALTER TABLE t1 RENAME t1backup;
---error ER_GET_ERRMSG
-SELECT * FROM t2;
-ALTER TABLE t1backup RENAME t1;
-DROP TABLE t2;
-
-
---echo #
---echo # Testing SELECT, etc.
---echo #
-
-# Automatic table structure
---replace_result $PORT PORT
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2;
-
-
-# Explicit table structure
---replace_result $PORT PORT
---eval CREATE TABLE t2 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2;
-
-
-# Explicit table structure: remote NULL, local NOT NULL
---replace_result $PORT PORT
---eval CREATE TABLE t2 (a INT NOT NULL, b CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2;
-
-
-# Explicit table structure with wrong column types
---replace_result $PORT PORT
---eval CREATE TABLE t2 (a char(10), b int) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2;
-
-DROP TABLE t1;
-
---echo #
---echo # Testing numeric data types
---echo #
-
-# TODO: tinyint is mapped to smallint
-#CREATE TABLE t1 (a tinyint);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: unsigned does not work
-#CREATE TABLE t1 (a tinyint unsigned);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-CREATE TABLE t1 (a smallint);
---replace_result $PORT PORT
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
---replace_result $PORT PORT
-SHOW CREATE TABLE t1;
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2, t1;
-
-CREATE TABLE t1 (a mediumint);
---replace_result $PORT PORT
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
---replace_result $PORT PORT
-SHOW CREATE TABLE t1;
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2, t1;
-
-CREATE TABLE t1 (a int);
---replace_result $PORT PORT
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
---replace_result $PORT PORT
-SHOW CREATE TABLE t1;
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2, t1;
-
-
-# TODO: bigint is mapped to double(20,0)
-CREATE TABLE t1 (a bigint);
---replace_result $PORT PORT
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
---replace_result $PORT PORT
-SHOW CREATE TABLE t1;
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2, t1;
-
-
-# TODO: ERROR 1439: Display width out of range for 'a' (max = 255)
-#CREATE TABLE t1 (a float);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: ERROR 1439: Display width out of range for 'a' (max = 255)
-#CREATE TABLE t1 (a double);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: decimal is converted to double
-#CREATE TABLE t1 (a decimal(20,5));
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: add test for BIT
-
---echo #
---echo # Testing character data types
---echo #
-
-# TODO: char is mapped to varchar
-CREATE TABLE t1 (a char(10));
---replace_result $PORT PORT
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
---replace_result $PORT PORT
-SHOW CREATE TABLE t1;
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2, t1;
-
-CREATE TABLE t1 (a varchar(10));
---replace_result $PORT PORT
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
---replace_result $PORT PORT
-SHOW CREATE TABLE t1;
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2, t1;
-
-# TODO: ERROR 1105: Unsupported column type tinytext
-#CREATE TABLE t1 (a tinytext);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: ERROR 1105: Unsupported column type mediumtext
-#CREATE TABLE t1 (a mediumtext);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: text is converted to varchar(256)
-#CREATE TABLE t1 (a text);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: ERROR 1105: Unsupported column type longtext
-#CREATE TABLE t1 (a longtext);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-#TODO: add tests for ENUM
-#TODO: add tests for SET
-
---echo #
---echo # Testing binary data types
---echo #
-
-# TODO: ERROR 1105: Unsupported column type binary
-#CREATE TABLE t1 (a binary(10));
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: ERROR 1105: Unsupported column type varbinary
-#CREATE TABLE t1 (a varbinary(10));
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: ERROR 1105: Unsupported column type tinyblob
-#CREATE TABLE t1 (a tinyblob);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: ERROR 1105: Unsupported column type mediumblob
-#CREATE TABLE t1 (a mediumblob);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: blob is converted to varchar(256)
-#CREATE TABLE t1 (a blob);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: ERROR 1105: Unsupported column type longblob
-#CREATE TABLE t1 (a longblob);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: ERROR 1105: Unsupported column type geometry
-#CREATE TABLE t1 (a geometry);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
---echo #
---echo # Testing temporal data types
---echo #
-
-# TODO: time is converted to date
-#CREATE TABLE t1 (a time);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-CREATE TABLE t1 (a date);
---replace_result $PORT PORT
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
---replace_result $PORT PORT
-SHOW CREATE TABLE t1;
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2, t1;
-
-# TODO: datetime is converted to date
-#CREATE TABLE t1 (a datetime);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: timestamp is converted to date
-#CREATE TABLE t1 (a timestamp);
-#--replace_result $PORT PORT
-#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $PORT PORT
-#SHOW CREATE TABLE t2;
-#SELECT * FROM t2;
-#DROP TABLE t2, t1;
-
-# TODO: add test for YEAR
-# TODO: add tests for fractional seconds
-
---echo #
---echo # MDEV-4877 mysqldump dumps all data from a connect table
---echo #
-CREATE TABLE t1 (a INT);
-INSERT INTO t1 VALUES (10),(20),(30);
---replace_result $PORT PORT
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTION='mysql://root@localhost:$PORT/test/t1'
-SELECT * FROM t2;
---echo # Start of mysqldump ------
---replace_result $PORT PORT
---exec $MYSQL_DUMP --compact test t2
---echo # End of mysqldump ------
-DROP TABLE t2;
-DROP TABLE t1;
-
---echo #
---echo # Testing getting unsigned types
---echo #
-CREATE TABLE t1 (
-a TINYINT UNSIGNED NOT NULL,
-b SMALLINT ZEROFILL NOT NULL,
-c INT UNSIGNED NOT NULL,
-d BIGINT UNSIGNED NOT NULL,
-e CHAR(32) NOT NULL DEFAULT 'Hello') ENGINE=CONNECT TABLE_TYPE=FIX;
-DESCRIBE t1;
-INSERT INTO t1(a,b,c,d) VALUES(255,65535,4294967295,18446744073709551615);
-SELECT * FROM t1;
-
-CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME=t1;
-DESCRIBE t2;
-SELECT * FROM t2;
-
-DROP TABLE t2;
-DROP TABLE t1;
-
-#
-# MDEV-6085 ALTER TABLE looses the connection string
-#
-CREATE TABLE t1 (a INT);
-INSERT INTO t1 VALUES (10),(20),(30);
---replace_result $PORT PORT
---eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTION='mysql://root@localhost:$PORT/test/t1'
-SELECT * FROM t2;
-ALTER TABLE t2 MODIFY a TINYINT;
---replace_result $PORT PORT
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2;
-DROP TABLE t1;
-
+-- source include/not_embedded.inc
+
+#
+# TODO: consider a possibility to run this test
+# against some remote MySQL server
+#
+
+let $PORT= `select @@port`;
+
+--disable_query_log
+--replace_result $PORT PORT
+--error 0,ER_UNKNOWN_ERROR
+--eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='tx1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
+ WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
+ AND ENGINE='CONNECT'
+ AND CREATE_OPTIONS LIKE '%`table_type`=MySQL%'`)
+{
+ Skip Need MySQL support;
+}
+DROP TABLE t1;
+--enable_query_log
+
+# TODO: remote VARCHAR is displayed as CHAR
+
+CREATE TABLE t1 (a int, b char(10));
+INSERT INTO t1 VALUES (NULL,NULL),(0,'test00'),(1,'test01'),(2,'test02'),(3,'test03');
+SELECT * FROM t1;
+
+--echo #
+--echo # Testing errors
+--echo #
+
+# Bad user name
+# Suppress "mysql_real_connect failed:" (printed in _DEBUG build)
+--replace_result $PORT PORT "mysql_real_connect failed: " ""
+--error ER_UNKNOWN_ERROR
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root1,port=$PORT'
+
+# Bad database name
+--replace_result $PORT PORT "mysql_real_connect failed: " ""
+--error ER_UNKNOWN_ERROR
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL DBNAME='unknown' TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+
+# Bad database name, with OPTION_LIST going first.
+--replace_result $PORT PORT "mysql_real_connect failed: " ""
+--error ER_UNKNOWN_ERROR
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL OPTION_LIST='host=localhost,user=root,port=$PORT' DBNAME='unknown' TABNAME='t1'
+
+# Bad table name
+--replace_result $PORT PORT
+--error ER_UNKNOWN_ERROR
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='unknown' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--error ER_NO_SUCH_TABLE
+SHOW CREATE TABLE t2;
+
+# Bad column name
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 (x int, y char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+--error ER_GET_ERRMSG
+SELECT * FROM t2;
+DROP TABLE t2;
+
+# The remote table disappeared
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+ALTER TABLE t1 RENAME t1backup;
+--error ER_GET_ERRMSG
+SELECT * FROM t2;
+ALTER TABLE t1backup RENAME t1;
+DROP TABLE t2;
+
+
+--echo #
+--echo # Testing SELECT, etc.
+--echo #
+
+# Automatic table structure
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+
+
+# Explicit table structure
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+
+
+# Explicit table structure: remote NULL, local NOT NULL
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 (a INT NOT NULL, b CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+
+
+# Explicit table structure with wrong column types
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 (a char(10), b int) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+
+DROP TABLE t1;
+
+--echo #
+--echo # Testing numeric data types
+--echo #
+
+# TODO: tinyint is mapped to smallint
+#CREATE TABLE t1 (a tinyint);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: unsigned does not work
+#CREATE TABLE t1 (a tinyint unsigned);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+CREATE TABLE t1 (a smallint);
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--replace_result $PORT PORT
+SHOW CREATE TABLE t1;
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2, t1;
+
+CREATE TABLE t1 (a mediumint);
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--replace_result $PORT PORT
+SHOW CREATE TABLE t1;
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2, t1;
+
+CREATE TABLE t1 (a int);
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--replace_result $PORT PORT
+SHOW CREATE TABLE t1;
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2, t1;
+
+
+# TODO: bigint is mapped to double(20,0)
+CREATE TABLE t1 (a bigint);
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--replace_result $PORT PORT
+SHOW CREATE TABLE t1;
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2, t1;
+
+
+# TODO: ERROR 1439: Display width out of range for 'a' (max = 255)
+#CREATE TABLE t1 (a float);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: ERROR 1439: Display width out of range for 'a' (max = 255)
+#CREATE TABLE t1 (a double);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: decimal is converted to double
+#CREATE TABLE t1 (a decimal(20,5));
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: add test for BIT
+
+--echo #
+--echo # Testing character data types
+--echo #
+
+# TODO: char is mapped to varchar
+CREATE TABLE t1 (a char(10));
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--replace_result $PORT PORT
+SHOW CREATE TABLE t1;
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2, t1;
+
+CREATE TABLE t1 (a varchar(10));
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--replace_result $PORT PORT
+SHOW CREATE TABLE t1;
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2, t1;
+
+# TODO: ERROR 1105: Unsupported column type tinytext
+#CREATE TABLE t1 (a tinytext);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: ERROR 1105: Unsupported column type mediumtext
+#CREATE TABLE t1 (a mediumtext);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: text is converted to varchar(256)
+#CREATE TABLE t1 (a text);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: ERROR 1105: Unsupported column type longtext
+#CREATE TABLE t1 (a longtext);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+#TODO: add tests for ENUM
+#TODO: add tests for SET
+
+--echo #
+--echo # Testing binary data types
+--echo #
+
+# TODO: ERROR 1105: Unsupported column type binary
+#CREATE TABLE t1 (a binary(10));
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: ERROR 1105: Unsupported column type varbinary
+#CREATE TABLE t1 (a varbinary(10));
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: ERROR 1105: Unsupported column type tinyblob
+#CREATE TABLE t1 (a tinyblob);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: ERROR 1105: Unsupported column type mediumblob
+#CREATE TABLE t1 (a mediumblob);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: blob is converted to varchar(256)
+#CREATE TABLE t1 (a blob);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: ERROR 1105: Unsupported column type longblob
+#CREATE TABLE t1 (a longblob);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: ERROR 1105: Unsupported column type geometry
+#CREATE TABLE t1 (a geometry);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+--echo #
+--echo # Testing temporal data types
+--echo #
+
+# TODO: time is converted to date
+#CREATE TABLE t1 (a time);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+CREATE TABLE t1 (a date);
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+--replace_result $PORT PORT
+SHOW CREATE TABLE t1;
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2, t1;
+
+# TODO: datetime is converted to date
+#CREATE TABLE t1 (a datetime);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: timestamp is converted to date
+#CREATE TABLE t1 (a timestamp);
+#--replace_result $PORT PORT
+#--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $PORT PORT
+#SHOW CREATE TABLE t2;
+#SELECT * FROM t2;
+#DROP TABLE t2, t1;
+
+# TODO: add test for YEAR
+# TODO: add tests for fractional seconds
+
+--echo #
+--echo # MDEV-4877 mysqldump dumps all data from a connect table
+--echo #
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20),(30);
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTION='mysql://root@localhost:$PORT/test/t1'
+SELECT * FROM t2;
+--echo # Start of mysqldump ------
+--replace_result $PORT PORT
+--exec $MYSQL_DUMP --compact test t2
+--echo # End of mysqldump ------
+DROP TABLE t2;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing getting unsigned types
+--echo #
+CREATE TABLE t1 (
+a TINYINT UNSIGNED NOT NULL,
+b SMALLINT ZEROFILL NOT NULL,
+c INT UNSIGNED NOT NULL,
+d BIGINT UNSIGNED NOT NULL,
+e CHAR(32) NOT NULL DEFAULT 'Hello') ENGINE=CONNECT TABLE_TYPE=FIX;
+DESCRIBE t1;
+INSERT INTO t1(a,b,c,d) VALUES(255,65535,4294967295,18446744073709551615);
+SELECT * FROM t1;
+
+CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME=t1;
+DESCRIBE t2;
+SELECT * FROM t2;
+
+DROP TABLE t2;
+DROP TABLE t1;
+
+#
+# MDEV-6085 ALTER TABLE looses the connection string
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20),(30);
+--replace_result $PORT PORT
+--eval CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTION='mysql://root@localhost:$PORT/test/t1'
+SELECT * FROM t2;
+ALTER TABLE t2 MODIFY a TINYINT;
+--replace_result $PORT PORT
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
diff --git a/storage/connect/mysql-test/connect/t/mysql_discovery.test b/storage/connect/mysql-test/connect/t/mysql_discovery.test
index 057244a2a97..cd266750274 100644
--- a/storage/connect/mysql-test/connect/t/mysql_discovery.test
+++ b/storage/connect/mysql-test/connect/t/mysql_discovery.test
@@ -1,33 +1,33 @@
--- source myconn.inc
-
-connection slave;
-
-CREATE TABLE t1 (
- `id` int(20) primary key,
- `group` int NOT NULL default 1,
- `a\\b` int NOT NULL default 2,
- `a\\` int unsigned,
- `name` varchar(32) default 'name')
- DEFAULT CHARSET=latin1;
-
-connection master;
-
---replace_result $SLAVE_MYPORT SLAVE_PORT
-eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
- CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
-
---replace_result $SLAVE_MYPORT SLAVE_PORT
-SHOW CREATE TABLE t1;
-INSERT INTO t1 (id, name) VALUES (1, 'foo');
-INSERT INTO t1 (id, name) VALUES (2, 'fee');
---sorted_result
-SELECT * FROM t1;
-DROP TABLE t1;
-
-connection slave;
---sorted_result
-SELECT * FROM t1;
-DROP TABLE t1;
-
--- source myconn_cleanup.inc
-
+-- source myconn.inc
+
+connection slave;
+
+CREATE TABLE t1 (
+ `id` int(20) primary key,
+ `group` int NOT NULL default 1,
+ `a\\b` int NOT NULL default 2,
+ `a\\` int unsigned,
+ `name` varchar(32) default 'name')
+ DEFAULT CHARSET=latin1;
+
+connection master;
+
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
+
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+SHOW CREATE TABLE t1;
+INSERT INTO t1 (id, name) VALUES (1, 'foo');
+INSERT INTO t1 (id, name) VALUES (2, 'fee');
+--sorted_result
+SELECT * FROM t1;
+DROP TABLE t1;
+
+connection slave;
+--sorted_result
+SELECT * FROM t1;
+DROP TABLE t1;
+
+-- source myconn_cleanup.inc
+
diff --git a/storage/connect/mysql-test/connect/t/mysql_exec.test b/storage/connect/mysql-test/connect/t/mysql_exec.test
index e56072a63e1..9226592eded 100644
--- a/storage/connect/mysql-test/connect/t/mysql_exec.test
+++ b/storage/connect/mysql-test/connect/t/mysql_exec.test
@@ -1,45 +1,45 @@
--- source myconn.inc
-
---echo #
---echo # Checking Sending Commands
---echo #
-connection master;
-
---replace_result $SLAVE_MYPORT SLAVE_PORT
-eval CREATE TABLE t1 (
- command VARCHAR(128) NOT NULL,
- warnings INT(4) NOT NULL FLAG=3,
- number INT(5) NOT NULL FLAG=1,
- message VARCHAR(255) FLAG=2)
- ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test' OPTION_LIST='Execsrc=1,maxerr=2';
-
-SELECT * FROM t1 WHERE command IN ('Warning','Note',
- 'drop table if exists t1',
- 'create table t1 (id int key auto_increment, msg varchar(32) not null)',
- "insert into t1(msg) values('One'),(NULL),('Three')",
- "insert into t1 values(2,'Deux') on duplicate key update msg = 'Two'",
- "insert into t1(message) values('Four'),('Five'),('Six')",
- 'insert into t1(id) values(NULL)',
- "update t1 set msg = 'Four' where id = 4",
- 'select * from t1');
-
---echo #
---echo # Checking Using Procedure
---echo #
-DROP PROCEDURE IF EXISTS p1;
-CREATE PROCEDURE p1(cmd varchar(512))
- READS SQL DATA
- SELECT * FROM t1 WHERE command IN ('Warning','Note',cmd);
-
-CALL p1('insert into t1(id) values(NULL)');
-CALL p1('update t1 set msg = "Five" where id = 5');
-DROP PROCEDURE p1;
-DROP TABLE t1;
-
-connection slave;
---sorted_result
-SELECT * FROM t1;
-DROP TABLE t1;
-
--- source myconn_cleanup.inc
-
+-- source myconn.inc
+
+--echo #
+--echo # Checking Sending Commands
+--echo #
+connection master;
+
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE t1 (
+ command VARCHAR(128) NOT NULL,
+ warnings INT(4) NOT NULL FLAG=3,
+ number INT(5) NOT NULL FLAG=1,
+ message VARCHAR(255) FLAG=2)
+ ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test' OPTION_LIST='Execsrc=1,maxerr=2';
+
+SELECT * FROM t1 WHERE command IN ('Warning','Note',
+ 'drop table if exists t1',
+ 'create table t1 (id int key auto_increment, msg varchar(32) not null)',
+ "insert into t1(msg) values('One'),(NULL),('Three')",
+ "insert into t1 values(2,'Deux') on duplicate key update msg = 'Two'",
+ "insert into t1(message) values('Four'),('Five'),('Six')",
+ 'insert into t1(id) values(NULL)',
+ "update t1 set msg = 'Four' where id = 4",
+ 'select * from t1');
+
+--echo #
+--echo # Checking Using Procedure
+--echo #
+DROP PROCEDURE IF EXISTS p1;
+CREATE PROCEDURE p1(cmd varchar(512))
+ READS SQL DATA
+ SELECT * FROM t1 WHERE command IN ('Warning','Note',cmd);
+
+CALL p1('insert into t1(id) values(NULL)');
+CALL p1('update t1 set msg = "Five" where id = 5');
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+connection slave;
+--sorted_result
+SELECT * FROM t1;
+DROP TABLE t1;
+
+-- source myconn_cleanup.inc
+
diff --git a/storage/connect/mysql-test/connect/t/mysql_grant.test b/storage/connect/mysql-test/connect/t/mysql_grant.test
index 8eb6a90c917..7c75103ed3b 100644
--- a/storage/connect/mysql-test/connect/t/mysql_grant.test
+++ b/storage/connect/mysql-test/connect/t/mysql_grant.test
@@ -1,78 +1,78 @@
--- source include/not_embedded.inc
-
-let $PORT= `select @@port`;
-
---disable_query_log
---replace_result $PORT PORT
---error 0,ER_UNKNOWN_ERROR
---eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='tx1' OPTION_LIST='host=localhost,user=root,port=$PORT'
-if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
- WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
- AND ENGINE='CONNECT'
- AND CREATE_OPTIONS LIKE '%`table_type`=MySQL%'`)
-{
- Skip Need MySQL support;
-}
-DROP TABLE t1;
---enable_query_log
-
---echo #
---echo # Testing FILE privilege
---echo #
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
---connect(user,localhost,user,,)
---connection user
-SELECT user();
---replace_result $PORT PORT
---error ER_ACCESS_DENIED_ERROR
---eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL OPTION_LIST='host=localhost,user=root1,port=$PORT'
---connection default
-SELECT user();
-CREATE TABLE t1remote (a INT NOT NULL);
-INSERT INTO t1remote VALUES (10),(20),(30);
---replace_result $PORT PORT
---eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL TABNAME=t1remote OPTION_LIST='host=localhost,user=root,port=$PORT'
-SELECT * FROM t1;
---connection user
-SELECT user();
---error ER_ACCESS_DENIED_ERROR
-SELECT * FROM t1;
---error ER_ACCESS_DENIED_ERROR
-INSERT INTO t1 VALUES ('xxx');
---error ER_ACCESS_DENIED_ERROR
-DELETE FROM t1 WHERE a='xxx';
---error ER_ACCESS_DENIED_ERROR
-UPDATE t1 SET a='yyy' WHERE a='xxx';
---error ER_ACCESS_DENIED_ERROR
-TRUNCATE TABLE t1;
---error ER_ACCESS_DENIED_ERROR
-ALTER TABLE t1 READONLY=1;
---error ER_ACCESS_DENIED_ERROR
-CREATE VIEW v1 AS SELECT * FROM t1;
-
---echo # Testing a VIEW created with FILE privileges but accessed with no FILE
---connection default
-SELECT user();
-CREATE VIEW v1 AS SELECT * FROM t1;
---connection user
-SELECT user();
---error ER_ACCESS_DENIED_ERROR
-SELECT * FROM v1;
---error ER_ACCESS_DENIED_ERROR
-INSERT INTO v1 VALUES (2);
---error ER_ACCESS_DENIED_ERROR
-UPDATE v1 SET a=123;
---error ER_ACCESS_DENIED_ERROR
-DELETE FROM v1;
-
---disconnect user
---connection default
-SELECT user();
-DROP VIEW v1;
-DROP TABLE t1, t1remote;
-DROP USER user@localhost;
---echo #
---echo # Testing FILE privileges done
---echo #
-
+-- source include/not_embedded.inc
+
+let $PORT= `select @@port`;
+
+--disable_query_log
+--replace_result $PORT PORT
+--error 0,ER_UNKNOWN_ERROR
+--eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='tx1' OPTION_LIST='host=localhost,user=root,port=$PORT'
+if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
+ WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
+ AND ENGINE='CONNECT'
+ AND CREATE_OPTIONS LIKE '%`table_type`=MySQL%'`)
+{
+ Skip Need MySQL support;
+}
+DROP TABLE t1;
+--enable_query_log
+
+--echo #
+--echo # Testing FILE privilege
+--echo #
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+--connect(user,localhost,user,,)
+--connection user
+SELECT user();
+--replace_result $PORT PORT
+--error ER_ACCESS_DENIED_ERROR
+--eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL OPTION_LIST='host=localhost,user=root1,port=$PORT'
+--connection default
+SELECT user();
+CREATE TABLE t1remote (a INT NOT NULL);
+INSERT INTO t1remote VALUES (10),(20),(30);
+--replace_result $PORT PORT
+--eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL TABNAME=t1remote OPTION_LIST='host=localhost,user=root,port=$PORT'
+SELECT * FROM t1;
+--connection user
+SELECT user();
+--error ER_ACCESS_DENIED_ERROR
+SELECT * FROM t1;
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO t1 VALUES ('xxx');
+--error ER_ACCESS_DENIED_ERROR
+DELETE FROM t1 WHERE a='xxx';
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t1 SET a='yyy' WHERE a='xxx';
+--error ER_ACCESS_DENIED_ERROR
+TRUNCATE TABLE t1;
+--error ER_ACCESS_DENIED_ERROR
+ALTER TABLE t1 READONLY=1;
+--error ER_ACCESS_DENIED_ERROR
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+--echo # Testing a VIEW created with FILE privileges but accessed with no FILE
+--connection default
+SELECT user();
+CREATE VIEW v1 AS SELECT * FROM t1;
+--connection user
+SELECT user();
+--error ER_ACCESS_DENIED_ERROR
+SELECT * FROM v1;
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO v1 VALUES (2);
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1 SET a=123;
+--error ER_ACCESS_DENIED_ERROR
+DELETE FROM v1;
+
+--disconnect user
+--connection default
+SELECT user();
+DROP VIEW v1;
+DROP TABLE t1, t1remote;
+DROP USER user@localhost;
+--echo #
+--echo # Testing FILE privileges done
+--echo #
+
diff --git a/storage/connect/mysql-test/connect/t/mysql_new.test b/storage/connect/mysql-test/connect/t/mysql_new.test
index 08f27b6b19b..c93f0407ca4 100644
--- a/storage/connect/mysql-test/connect/t/mysql_new.test
+++ b/storage/connect/mysql-test/connect/t/mysql_new.test
@@ -1,325 +1,325 @@
--- source myconn.inc
-
-#
-# This test is run against a remote MySQL server
-#
-
-connection slave;
-
-CREATE TABLE t1 (a int, b char(10));
-INSERT INTO t1 VALUES (NULL,NULL),(0,'test00'),(1,'test01'),(2,'test02'),(3,'test03');
-SELECT * FROM t1;
-
---echo #
---echo # Testing errors
---echo #
-connection master;
-
-# Bad user name
-# Suppress "mysql_real_connect failed:" (printed in _DEBUG build)
---replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " ""
---error ER_UNKNOWN_ERROR
-eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
- CONNECTION='mysql://unknown@127.0.0.1:$SLAVE_MYPORT/test/t1';
-
-# Bad database name
---replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " ""
---error ER_UNKNOWN_ERROR
-eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
- CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/unknown/t1';
-
-# Bad database name, with OPTION_LIST going first.
---replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " ""
---error ER_UNKNOWN_ERROR
-eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
- OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT' DBNAME='unknown' TABNAME='t1';
-
-# Bad table name
---replace_result $SLAVE_MYPORT SLAVE_PORT
---error ER_UNKNOWN_ERROR
-eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
- CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/unknown';
---error ER_NO_SUCH_TABLE
-SHOW CREATE TABLE t1;
-
-# Bad column name
---replace_result $SLAVE_MYPORT SLAVE_PORT
-eval CREATE TABLE t1 (x int, y char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL
- CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
---replace_result $SLAVE_MYPORT SLAVE_PORT
-SHOW CREATE TABLE t1;
---error ER_GET_ERRMSG
-SELECT * FROM t1;
-DROP TABLE t1;
-
-# The remote table disappeared
---replace_result $SLAVE_MYPORT SLAVE_PORT
-eval CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL
- CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
-
-connection slave;
-ALTER TABLE t1 RENAME t1backup;
-
-connection master;
---error ER_GET_ERRMSG
-SELECT * FROM t1;
-
-connection slave;
-ALTER TABLE t1backup RENAME t1;
-
-connection master;
-DROP TABLE t1;
-
---echo #
---echo # Testing SELECT, etc.
---echo #
-
-# Automatic table structure
---replace_result $SLAVE_MYPORT SLAVE_PORT
-eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
- CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
---replace_result $SLAVE_MYPORT SLAVE_PORT
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-# Explicit table structure
---replace_result $SLAVE_MYPORT SLAVE_PORT
-eval CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1'
- OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT';
---replace_result $SLAVE_MYPORT SLAVE_PORT
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-# Explicit table structure: remote NULL, local NOT NULL
---replace_result $SLAVE_MYPORT SLAVE_PORT
-eval CREATE TABLE t1 (a INT NOT NULL, b CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=MYSQL
- OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT';
---replace_result $SLAVE_MYPORT SLAVE_PORT
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-# Explicit table structure with wrong column types
---replace_result $SLAVE_MYPORT SLAVE_PORT
-eval CREATE TABLE t1 (a char(10), b int) ENGINE=CONNECT TABLE_TYPE=MYSQL
- CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
---replace_result $SLAVE_MYPORT SLAVE_PORT
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-connection slave;
-DROP TABLE t1;
-
---echo #
---echo # Testing numeric data types
---echo #
-
-# TODO: mediumint is converted to int, float is converted to double, decimal is converted to double
-CREATE TABLE t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float, g double, h decimal(20,5));
-SHOW CREATE TABLE t1;
-INSERT INTO t1 VALUES(100,3333,41235,1234567890,235000000000,3.14159265,3.14159265,3141.59265);
-
-connection master;
---replace_result $SLAVE_MYPORT SLAVE_PORT
-eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
- OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT';
---replace_result $SLAVE_MYPORT SLAVE_PORT
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-connection slave;
-DROP TABLE t1;
-
-# TODO: unsigned does not work
-#CREATE TABLE t1 (a tinyint unsigned);
-#SHOW CREATE TABLE t1;
-
-#connection master;
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT';
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#SELECT * FROM t1;
-#DROP TABLE t1;
-
-#connection slave;
-#DROP TABLE t1;
-
-# TODO: add test for BIT
-
---echo #
---echo # Testing character data types
---echo #
-
-CREATE TABLE t1 (a char(12), b varchar(12));
-SHOW CREATE TABLE t1;
-INSERT INTO t1 VALUES('Welcome','Hello, World');
-SELECT * FROM t1;
-
-connection master;
---replace_result $SLAVE_MYPORT SLAVE_PORT
-eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
- CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT';
---replace_result $SLAVE_MYPORT SLAVE_PORT
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-connection slave;
-DROP TABLE t1;
-
-# TODO: ERROR 1105: Unsupported column type tinytext
-#CREATE TABLE t1 (a tinytext);
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#SELECT * FROM t1;
-#DROP TABLE t1, t1;
-
-# TODO: ERROR 1105: Unsupported column type mediumtext
-#CREATE TABLE t1 (a mediumtext);
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#SELECT * FROM t1;
-#DROP TABLE t1, t1;
-
-# TODO: text is converted to varchar(256)
-#CREATE TABLE t1 (a text);
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#SELECT * FROM t1;
-#DROP TABLE t1, t1;
-
-# TODO: ERROR 1105: Unsupported column type longtext
-#CREATE TABLE t1 (a longtext);
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#SELECT * FROM t1;
-#DROP TABLE t1, t1;
-
-#TODO: add tests for ENUM
-#TODO: add tests for SET
-
-#--echo #
-#--echo # Testing binary data types
-#--echo #
-
-# TODO: ERROR 1105: Unsupported column type binary
-#CREATE TABLE t1 (a binary(10));
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#SELECT * FROM t1;
-#DROP TABLE t1, t1;
-
-# TODO: ERROR 1105: Unsupported column type varbinary
-#CREATE TABLE t1 (a varbinary(10));
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#SELECT * FROM t1;
-#DROP TABLE t1, t1;
-
-# TODO: ERROR 1105: Unsupported column type tinyblob
-#CREATE TABLE t1 (a tinyblob);
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#SELECT * FROM t1;
-#DROP TABLE t1, t1;
-
-# TODO: ERROR 1105: Unsupported column type mediumblob
-#CREATE TABLE t1 (a mediumblob);
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#SELECT * FROM t1;
-#DROP TABLE t1, t1;
-
-# TODO: blob is converted to varchar(256)
-#CREATE TABLE t1 (a blob);
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#SELECT * FROM t1;
-#DROP TABLE t1, t1;
-
-# TODO: ERROR 1105: Unsupported column type longblob
-#CREATE TABLE t1 (a longblob);
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#SELECT * FROM t1;
-#DROP TABLE t1, t1;
-
-# TODO: ERROR 1105: Unsupported column type geometry
-#CREATE TABLE t1 (a geometry);
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#--replace_result $SLAVE_MYPORT SLAVE_PORT
-#SHOW CREATE TABLE t1;
-#SELECT * FROM t1;
-#DROP TABLE t1, t1;
-
---echo #
---echo # Testing temporal data types
---echo #
-
-CREATE TABLE t1 (a date, b datetime, c time, d timestamp, e year);
-SHOW CREATE TABLE t1;
-INSERT INTO t1 VALUES('2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23');
-SELECT * FROM t1;
-
-connection master;
---replace_result $SLAVE_MYPORT SLAVE_PORT
-eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
- CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT';
---replace_result $SLAVE_MYPORT SLAVE_PORT
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-connection slave;
-DROP TABLE t1;
-
--- source myconn_cleanup.inc
-
+-- source myconn.inc
+
+#
+# This test is run against a remote MySQL server
+#
+
+connection slave;
+
+CREATE TABLE t1 (a int, b char(10));
+INSERT INTO t1 VALUES (NULL,NULL),(0,'test00'),(1,'test01'),(2,'test02'),(3,'test03');
+SELECT * FROM t1;
+
+--echo #
+--echo # Testing errors
+--echo #
+connection master;
+
+# Bad user name
+# Suppress "mysql_real_connect failed:" (printed in _DEBUG build)
+--replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " ""
+--error ER_UNKNOWN_ERROR
+eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
+ CONNECTION='mysql://unknown@127.0.0.1:$SLAVE_MYPORT/test/t1';
+
+# Bad database name
+--replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " ""
+--error ER_UNKNOWN_ERROR
+eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/unknown/t1';
+
+# Bad database name, with OPTION_LIST going first.
+--replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " ""
+--error ER_UNKNOWN_ERROR
+eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
+ OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT' DBNAME='unknown' TABNAME='t1';
+
+# Bad table name
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--error ER_UNKNOWN_ERROR
+eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/unknown';
+--error ER_NO_SUCH_TABLE
+SHOW CREATE TABLE t1;
+
+# Bad column name
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE t1 (x int, y char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+SHOW CREATE TABLE t1;
+--error ER_GET_ERRMSG
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# The remote table disappeared
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
+
+connection slave;
+ALTER TABLE t1 RENAME t1backup;
+
+connection master;
+--error ER_GET_ERRMSG
+SELECT * FROM t1;
+
+connection slave;
+ALTER TABLE t1backup RENAME t1;
+
+connection master;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing SELECT, etc.
+--echo #
+
+# Automatic table structure
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Explicit table structure
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1'
+ OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT';
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Explicit table structure: remote NULL, local NOT NULL
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE t1 (a INT NOT NULL, b CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=MYSQL
+ OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT';
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Explicit table structure with wrong column types
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE t1 (a char(10), b int) ENGINE=CONNECT TABLE_TYPE=MYSQL
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+connection slave;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing numeric data types
+--echo #
+
+# TODO: mediumint is converted to int, float is converted to double, decimal is converted to double
+CREATE TABLE t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float, g double, h decimal(20,5));
+SHOW CREATE TABLE t1;
+INSERT INTO t1 VALUES(100,3333,41235,1234567890,235000000000,3.14159265,3.14159265,3141.59265);
+
+connection master;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
+ OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT';
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+connection slave;
+DROP TABLE t1;
+
+# TODO: unsigned does not work
+#CREATE TABLE t1 (a tinyint unsigned);
+#SHOW CREATE TABLE t1;
+
+#connection master;
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT';
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#SELECT * FROM t1;
+#DROP TABLE t1;
+
+#connection slave;
+#DROP TABLE t1;
+
+# TODO: add test for BIT
+
+--echo #
+--echo # Testing character data types
+--echo #
+
+CREATE TABLE t1 (a char(12), b varchar(12));
+SHOW CREATE TABLE t1;
+INSERT INTO t1 VALUES('Welcome','Hello, World');
+SELECT * FROM t1;
+
+connection master;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT';
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+connection slave;
+DROP TABLE t1;
+
+# TODO: ERROR 1105: Unsupported column type tinytext
+#CREATE TABLE t1 (a tinytext);
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#SELECT * FROM t1;
+#DROP TABLE t1, t1;
+
+# TODO: ERROR 1105: Unsupported column type mediumtext
+#CREATE TABLE t1 (a mediumtext);
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#SELECT * FROM t1;
+#DROP TABLE t1, t1;
+
+# TODO: text is converted to varchar(256)
+#CREATE TABLE t1 (a text);
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#SELECT * FROM t1;
+#DROP TABLE t1, t1;
+
+# TODO: ERROR 1105: Unsupported column type longtext
+#CREATE TABLE t1 (a longtext);
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#SELECT * FROM t1;
+#DROP TABLE t1, t1;
+
+#TODO: add tests for ENUM
+#TODO: add tests for SET
+
+#--echo #
+#--echo # Testing binary data types
+#--echo #
+
+# TODO: ERROR 1105: Unsupported column type binary
+#CREATE TABLE t1 (a binary(10));
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#SELECT * FROM t1;
+#DROP TABLE t1, t1;
+
+# TODO: ERROR 1105: Unsupported column type varbinary
+#CREATE TABLE t1 (a varbinary(10));
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#SELECT * FROM t1;
+#DROP TABLE t1, t1;
+
+# TODO: ERROR 1105: Unsupported column type tinyblob
+#CREATE TABLE t1 (a tinyblob);
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#SELECT * FROM t1;
+#DROP TABLE t1, t1;
+
+# TODO: ERROR 1105: Unsupported column type mediumblob
+#CREATE TABLE t1 (a mediumblob);
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#SELECT * FROM t1;
+#DROP TABLE t1, t1;
+
+# TODO: blob is converted to varchar(256)
+#CREATE TABLE t1 (a blob);
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#SELECT * FROM t1;
+#DROP TABLE t1, t1;
+
+# TODO: ERROR 1105: Unsupported column type longblob
+#CREATE TABLE t1 (a longblob);
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#SELECT * FROM t1;
+#DROP TABLE t1, t1;
+
+# TODO: ERROR 1105: Unsupported column type geometry
+#CREATE TABLE t1 (a geometry);
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#--replace_result $SLAVE_MYPORT SLAVE_PORT
+#SHOW CREATE TABLE t1;
+#SELECT * FROM t1;
+#DROP TABLE t1, t1;
+
+--echo #
+--echo # Testing temporal data types
+--echo #
+
+CREATE TABLE t1 (a date, b datetime, c time, d timestamp, e year);
+SHOW CREATE TABLE t1;
+INSERT INTO t1 VALUES('2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23');
+SELECT * FROM t1;
+
+connection master;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT';
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+connection slave;
+DROP TABLE t1;
+
+-- source myconn_cleanup.inc
+
diff --git a/storage/connect/mysql-test/connect/t/null.test b/storage/connect/mysql-test/connect/t/null.test
index 3d1e33eb77c..d2c784144a5 100644
--- a/storage/connect/mysql-test/connect/t/null.test
+++ b/storage/connect/mysql-test/connect/t/null.test
@@ -1,87 +1,87 @@
-let $MYSQLD_DATADIR= `select @@datadir`;
-
---echo #
---echo # Testing FIX null columns
---echo #
-CREATE TABLE t1
-(
- id INT NOT NULL,
- nb INT,
- msg VARCHAR(12)
-) ENGINE=CONNECT TABLE_TYPE=FIX;
---error ER_BAD_NULL_ERROR
-INSERT INTO t1 values(NULL,1,'Hello');
-INSERT INTO t1 values(10,4,NULL),(20,2,'Hello'),(0,0,'Zero');
-SELECT * FROM t1;
-SELECT* FROM t1 WHERE id IS NULL;
-SELECT * FROM t1 WHERE nb IS NULL;
-SELECT * FROM t1 WHERE msg IS NOT NULL;
-DROP TABLE t1;
-
---echo #
---echo # Testing CSV null columns
---echo #
-CREATE TABLE t1
-(
- id INT NOT NULL,
- nb INT,
- msg VARCHAR(12)
-) ENGINE=CONNECT TABLE_TYPE=CSV HEADER=1;
---error ER_BAD_NULL_ERROR
-INSERT INTO t1 values(NULL,1,'Hello');
-INSERT INTO t1 values(10,4,NULL),(20,2,'Hello'),(0,0,'Zero');
-SELECT * FROM t1;
-SELECT* FROM t1 WHERE id IS NULL;
-SELECT * FROM t1 WHERE nb IS NULL;
-SELECT * FROM t1 WHERE msg IS NOT NULL;
-DROP TABLE t1;
-
---echo #
---echo # Testing BIN null columns
---echo #
-CREATE TABLE t1
-(
- id INT NOT NULL,
- nb INT,
- msg VARCHAR(12)
-) ENGINE=CONNECT TABLE_TYPE=BIN;
---error ER_BAD_NULL_ERROR
-INSERT INTO t1 values(NULL,1,'Hello');
-INSERT INTO t1 values(10,4,NULL),(20,2,'Hello'),(0,0,'Zero');
-SELECT * FROM t1;
-SELECT* FROM t1 WHERE id IS NULL;
-SELECT * FROM t1 WHERE nb IS NULL;
-SELECT * FROM t1 WHERE msg IS NOT NULL;
-DROP TABLE t1;
-
---echo #
---echo # Testing DBF null columns
---echo #
-CREATE TABLE t1
-(
- id INT NOT NULL,
- nb INT,
- msg VARCHAR(12)
-) ENGINE=CONNECT TABLE_TYPE=DBF;
---error ER_BAD_NULL_ERROR
-INSERT INTO t1 values(NULL,1,'Hello');
-INSERT INTO t1 values(10,4,NULL),(20,2,'Hello'),(0,0,'Zero');
-SELECT * FROM t1;
-SELECT* FROM t1 WHERE id IS NULL;
-SELECT * FROM t1 WHERE nb IS NULL;
-SELECT * FROM t1 WHERE msg IS NOT NULL;
-DROP TABLE t1;
-
---echo #
---echo # Testing INI null columns
---echo #
-CREATE TABLE t1
-(
- `sec` char(8) NOT NULL flag=1,
- `key` char(12)
-) ENGINE=CONNECT TABLE_TYPE=INI;
-INSERT INTO t1(sec) values('S1');
-SELECT * FROM t1;
-INSERT INTO t1 values('S1','Newval');
-SELECT * FROM t1;
-DROP TABLE t1;
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--echo #
+--echo # Testing FIX null columns
+--echo #
+CREATE TABLE t1
+(
+ id INT NOT NULL,
+ nb INT,
+ msg VARCHAR(12)
+) ENGINE=CONNECT TABLE_TYPE=FIX;
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 values(NULL,1,'Hello');
+INSERT INTO t1 values(10,4,NULL),(20,2,'Hello'),(0,0,'Zero');
+SELECT * FROM t1;
+SELECT* FROM t1 WHERE id IS NULL;
+SELECT * FROM t1 WHERE nb IS NULL;
+SELECT * FROM t1 WHERE msg IS NOT NULL;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing CSV null columns
+--echo #
+CREATE TABLE t1
+(
+ id INT NOT NULL,
+ nb INT,
+ msg VARCHAR(12)
+) ENGINE=CONNECT TABLE_TYPE=CSV HEADER=1;
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 values(NULL,1,'Hello');
+INSERT INTO t1 values(10,4,NULL),(20,2,'Hello'),(0,0,'Zero');
+SELECT * FROM t1;
+SELECT* FROM t1 WHERE id IS NULL;
+SELECT * FROM t1 WHERE nb IS NULL;
+SELECT * FROM t1 WHERE msg IS NOT NULL;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing BIN null columns
+--echo #
+CREATE TABLE t1
+(
+ id INT NOT NULL,
+ nb INT,
+ msg VARCHAR(12)
+) ENGINE=CONNECT TABLE_TYPE=BIN;
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 values(NULL,1,'Hello');
+INSERT INTO t1 values(10,4,NULL),(20,2,'Hello'),(0,0,'Zero');
+SELECT * FROM t1;
+SELECT* FROM t1 WHERE id IS NULL;
+SELECT * FROM t1 WHERE nb IS NULL;
+SELECT * FROM t1 WHERE msg IS NOT NULL;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing DBF null columns
+--echo #
+CREATE TABLE t1
+(
+ id INT NOT NULL,
+ nb INT,
+ msg VARCHAR(12)
+) ENGINE=CONNECT TABLE_TYPE=DBF;
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 values(NULL,1,'Hello');
+INSERT INTO t1 values(10,4,NULL),(20,2,'Hello'),(0,0,'Zero');
+SELECT * FROM t1;
+SELECT* FROM t1 WHERE id IS NULL;
+SELECT * FROM t1 WHERE nb IS NULL;
+SELECT * FROM t1 WHERE msg IS NOT NULL;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing INI null columns
+--echo #
+CREATE TABLE t1
+(
+ `sec` char(8) NOT NULL flag=1,
+ `key` char(12)
+) ENGINE=CONNECT TABLE_TYPE=INI;
+INSERT INTO t1(sec) values('S1');
+SELECT * FROM t1;
+INSERT INTO t1 values('S1','Newval');
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/t/occur.test b/storage/connect/mysql-test/connect/t/occur.test
index 36a4caafda1..7d7bca87f66 100644
--- a/storage/connect/mysql-test/connect/t/occur.test
+++ b/storage/connect/mysql-test/connect/t/occur.test
@@ -1,61 +1,61 @@
--- source include/not_embedded.inc
-
-let $MYSQLD_DATADIR= `select @@datadir`;
-let $PORT= `select @@port`;
---copy_file $MTR_SUITE_DIR/std_data/employee.dat $MYSQLD_DATADIR/test/employee.dat
-
-CREATE TABLE employee (
-serialno CHAR(5) NOT NULL,
-name VARCHAR(12) NOT NULL FLAG=6,
-sex TINYINT(1) NOT NULL,
-title VARCHAR(15) NOT NULL FLAG=20,
-manager CHAR(5) DEFAULT NULL,
-department CHAR(4) NOT NULL FLAG=41,
-secretary CHAR(5) DEFAULT NULL FLAG=46,
-salary DOUBLE(8,2) NOT NULL FLAG=52
-) ENGINE=connect TABLE_TYPE=fix FILE_NAME='employee.dat' ENDING=1;
-SELECT * FROM employee;
-
---replace_result $PORT PORT
---eval CREATE TABLE occurs (name CHAR(12), sex CHAR(1), title CHAR(15), department CHAR(4), salary DOUBLE(8,2), id_of CHAR(12), id CHAR(5) NOT NULL) ENGINE=CONNECT TABLE_TYPE=OCCUR TABNAME=employee OPTION_LIST='OccurCol=ID,RankCol=ID_OF,Colist=serialno;manager;secretary,port=$PORT';
-SELECT * FROM occurs;
-
-DROP TABLE occurs;
-DROP TABLE employee;
-
-CREATE TABLE pets (
-name VARCHAR(12) NOT NULL,
-dog INT NOT NULL DEFAULT 0,
-cat INT NOT NULL DEFAULT 0,
-rabbit INT NOT NULL DEFAULT 0,
-bird INT NOT NULL DEFAULT 0,
-fish INT NOT NULL DEFAULT 0) ENGINE=MYISAM;
-INSERT INTO pets(name,dog) VALUES('John',2);
-INSERT INTO pets(name,cat) VALUES('Bill',1);
-INSERT INTO pets(name,dog,cat) VALUES('Mary',1,1);
-INSERT INTO pets(name,rabbit) VALUES('Lisbeth',2);
-INSERT INTO pets(name,cat,bird) VALUES('Kevin',2,6);
-INSERT INTO pets(name,dog,fish) VALUES('Donald',1,3);
-SELECT * FROM pets;
-
---replace_result $PORT PORT
---eval CREATE TABLE xpet (name VARCHAR(12) NOT NULL, race CHAR(6) NOT NULL, number INT) ENGINE=CONNECT TABLE_TYPE=OCCUR TABNAME=pets OPTION_LIST='OccurCol=number,RankCol=race,Colist=dog;cat;rabbit;bird;fish,port=$PORT'
-
-SELECT * FROM xpet;
-SELECT name FROM xpet;
-SELECT name FROM xpet WHERE race = 'cat' AND number = 0;
-SELECT name, SUM(number) pets FROM xpet GROUP BY name;
-
-ALTER TABLE xpet MODIFY number INT NOT NULL;
-
-SELECT * FROM xpet;
-SELECT * FROM xpet WHERE number > 1;
-SELECT DISTINCT name FROM xpet WHERE number > 1;
-SELECT name FROM xpet;
-SELECT name, race FROM xpet;
-SELECT name, count(*) FROM xpet GROUP BY name, LEAST(number,1);
-SELECT name, number, count(*) FROM xpet GROUP BY name, number;
-
-DROP TABLE xpet;
-DROP TABLE pets;
---remove_file $MYSQLD_DATADIR/test/employee.dat
+-- source include/not_embedded.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+let $PORT= `select @@port`;
+--copy_file $MTR_SUITE_DIR/std_data/employee.dat $MYSQLD_DATADIR/test/employee.dat
+
+CREATE TABLE employee (
+serialno CHAR(5) NOT NULL,
+name VARCHAR(12) NOT NULL FLAG=6,
+sex TINYINT(1) NOT NULL,
+title VARCHAR(15) NOT NULL FLAG=20,
+manager CHAR(5) DEFAULT NULL,
+department CHAR(4) NOT NULL FLAG=41,
+secretary CHAR(5) DEFAULT NULL FLAG=46,
+salary DOUBLE(8,2) NOT NULL FLAG=52
+) ENGINE=connect TABLE_TYPE=fix FILE_NAME='employee.dat' ENDING=1;
+SELECT * FROM employee;
+
+--replace_result $PORT PORT
+--eval CREATE TABLE occurs (name CHAR(12), sex CHAR(1), title CHAR(15), department CHAR(4), salary DOUBLE(8,2), id_of CHAR(12), id CHAR(5) NOT NULL) ENGINE=CONNECT TABLE_TYPE=OCCUR TABNAME=employee OPTION_LIST='OccurCol=ID,RankCol=ID_OF,Colist=serialno;manager;secretary,port=$PORT';
+SELECT * FROM occurs;
+
+DROP TABLE occurs;
+DROP TABLE employee;
+
+CREATE TABLE pets (
+name VARCHAR(12) NOT NULL,
+dog INT NOT NULL DEFAULT 0,
+cat INT NOT NULL DEFAULT 0,
+rabbit INT NOT NULL DEFAULT 0,
+bird INT NOT NULL DEFAULT 0,
+fish INT NOT NULL DEFAULT 0) ENGINE=MYISAM;
+INSERT INTO pets(name,dog) VALUES('John',2);
+INSERT INTO pets(name,cat) VALUES('Bill',1);
+INSERT INTO pets(name,dog,cat) VALUES('Mary',1,1);
+INSERT INTO pets(name,rabbit) VALUES('Lisbeth',2);
+INSERT INTO pets(name,cat,bird) VALUES('Kevin',2,6);
+INSERT INTO pets(name,dog,fish) VALUES('Donald',1,3);
+SELECT * FROM pets;
+
+--replace_result $PORT PORT
+--eval CREATE TABLE xpet (name VARCHAR(12) NOT NULL, race CHAR(6) NOT NULL, number INT) ENGINE=CONNECT TABLE_TYPE=OCCUR TABNAME=pets OPTION_LIST='OccurCol=number,RankCol=race,Colist=dog;cat;rabbit;bird;fish,port=$PORT'
+
+SELECT * FROM xpet;
+SELECT name FROM xpet;
+SELECT name FROM xpet WHERE race = 'cat' AND number = 0;
+SELECT name, SUM(number) pets FROM xpet GROUP BY name;
+
+ALTER TABLE xpet MODIFY number INT NOT NULL;
+
+SELECT * FROM xpet;
+SELECT * FROM xpet WHERE number > 1;
+SELECT DISTINCT name FROM xpet WHERE number > 1;
+SELECT name FROM xpet;
+SELECT name, race FROM xpet;
+SELECT name, count(*) FROM xpet GROUP BY name, LEAST(number,1);
+SELECT name, number, count(*) FROM xpet GROUP BY name, number;
+
+DROP TABLE xpet;
+DROP TABLE pets;
+--remove_file $MYSQLD_DATADIR/test/employee.dat
diff --git a/storage/connect/mysql-test/connect/t/odbc_sqlite3.test b/storage/connect/mysql-test/connect/t/odbc_sqlite3.test
index 433e97149c6..a22fa3a7832 100644
--- a/storage/connect/mysql-test/connect/t/odbc_sqlite3.test
+++ b/storage/connect/mysql-test/connect/t/odbc_sqlite3.test
@@ -1,90 +1,90 @@
---source have_odbc_sqlite3.inc
-
-#
-# To run this test, install SQLite3 ODBC Driver from
-# http://www.ch-werner.de/sqliteodbc/
-#
-# Note, the test does not need a DSN to be created
-# (only the driver is required)
-#
-#
-# On Windows:
-# -----------
-# Download and run the installer file sqliteodbc.exe
-# Version sqliteodbc-0.991 is known to Work.
-# After running the installer the test should start working automatically.
-#
-# On Linux:
-# --------
-# 1. Download the source tarball, e.g.: sqliteodbc-0.993.tar.gz
-# 2. Unpack the sources:
-# tar -zxf sqliteodbc-0.993.tar.gz
-# 3. Compile the source and install:
-# cd sqliteodbc-0.993
-# ./configure --prefix=/opt/sqliteodbc
-# make
-# sudo make install
-#
-# (you can use a different --prefix, according to your preferences)
-#
-# 4. Add these lines into /etc/odbcinst.ini
-#
-#[SQLite3 ODBC Driver]
-#Description=SQLite3 ODBC Driver
-#Driver=/opt/sqliteodbc/libsqlite3odbc.so
-#Setup=/opt/sqliteodbc/libsqlite3odbc.so
-#
-# Adjust the directory "/opt/sqliteodbc/" according to --prefix
-# that you chose on step #3.
-#
-#
-
-SET NAMES utf8;
-
-let $MYSQLD_DATADIR= `select @@datadir`;
-
-
-#
-# For some reasons Windows does not allow to remove the data base
-# file after "DROP TABLE t1". So unlike in odbc_xls.test we won't copy
-# the data file, we'll use directly the file in std_data.
-# As we do not do any modifications in the database, this should be OK.
-#
-let $Database=$MTR_SUITE_DIR/std_data/test.sqlite3;
---replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
---eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;
---replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-
-CREATE TABLE t2 AS SELECT * FROM t1;
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-DROP TABLE t2;
-
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT * FROM v1;
-
-DROP VIEW v1;
-DROP TABLE t1;
-
---replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
---eval CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8
-SELECT * FROM t1;
-DROP TABLE t1;
-
---replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
---eval CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8
-SELECT * FROM t1;
-DROP TABLE t1;
-
-
---replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
---eval CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8
-SELECT * FROM t1 ORDER BY Table_name;
-DROP TABLE t1;
-
---replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
---eval CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8
-SELECT * FROM t1 ORDER BY Table_name;
-DROP TABLE t1;
+--source have_odbc_sqlite3.inc
+
+#
+# To run this test, install SQLite3 ODBC Driver from
+# http://www.ch-werner.de/sqliteodbc/
+#
+# Note, the test does not need a DSN to be created
+# (only the driver is required)
+#
+#
+# On Windows:
+# -----------
+# Download and run the installer file sqliteodbc.exe
+# Version sqliteodbc-0.991 is known to Work.
+# After running the installer the test should start working automatically.
+#
+# On Linux:
+# --------
+# 1. Download the source tarball, e.g.: sqliteodbc-0.993.tar.gz
+# 2. Unpack the sources:
+# tar -zxf sqliteodbc-0.993.tar.gz
+# 3. Compile the source and install:
+# cd sqliteodbc-0.993
+# ./configure --prefix=/opt/sqliteodbc
+# make
+# sudo make install
+#
+# (you can use a different --prefix, according to your preferences)
+#
+# 4. Add these lines into /etc/odbcinst.ini
+#
+#[SQLite3 ODBC Driver]
+#Description=SQLite3 ODBC Driver
+#Driver=/opt/sqliteodbc/libsqlite3odbc.so
+#Setup=/opt/sqliteodbc/libsqlite3odbc.so
+#
+# Adjust the directory "/opt/sqliteodbc/" according to --prefix
+# that you chose on step #3.
+#
+#
+
+SET NAMES utf8;
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+
+#
+# For some reasons Windows does not allow to remove the data base
+# file after "DROP TABLE t1". So unlike in odbc_xls.test we won't copy
+# the data file, we'll use directly the file in std_data.
+# As we do not do any modifications in the database, this should be OK.
+#
+let $Database=$MTR_SUITE_DIR/std_data/test.sqlite3;
+--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
+--eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;
+--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+
+CREATE TABLE t2 AS SELECT * FROM t1;
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT * FROM v1;
+
+DROP VIEW v1;
+DROP TABLE t1;
+
+--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
+--eval CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
+--eval CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8
+SELECT * FROM t1;
+DROP TABLE t1;
+
+
+--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
+--eval CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8
+SELECT * FROM t1 ORDER BY Table_name;
+DROP TABLE t1;
+
+--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
+--eval CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8
+SELECT * FROM t1 ORDER BY Table_name;
+DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/t/part_file.test b/storage/connect/mysql-test/connect/t/part_file.test
index 6efd2b9b580..8ee43a917ec 100644
--- a/storage/connect/mysql-test/connect/t/part_file.test
+++ b/storage/connect/mysql-test/connect/t/part_file.test
@@ -1,166 +1,166 @@
---source include/have_partition.inc
-let $MYSQLD_DATADIR= `select @@datadir`;
-
-set @@global.connect_exact_info=ON;
-
---echo # This will be used to see what data files are created
-CREATE TABLE dr1 (
- fname VARCHAR(256) NOT NULL FLAG=2,
- ftype CHAR(8) NOT NULL FLAG=3
-# ,FSIZE INT(6) NOT NULL FLAG=5 removed because Unix size != Windows size
-) engine=CONNECT table_type=DIR file_name='t1#P#*.*';
-
---echo #
---echo # Testing partitioning on inward table
---echo #
-CREATE TABLE t1 (
- id INT NOT NULL,
- msg VARCHAR(32)
-) ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=10
-PARTITION BY RANGE(id) (
-PARTITION first VALUES LESS THAN(10),
-PARTITION middle VALUES LESS THAN(50),
-PARTITION last VALUES LESS THAN(MAXVALUE));
-INSERT INTO t1 VALUES(4, 'four'),(24, 'twenty four');
-INSERT INTO t1 VALUES(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one');
-SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
-SELECT * FROM t1;
-EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id > 50;
-SELECT * FROM t1 WHERE id > 50;
-#TODO: Differences between Linux and Windows
-#SHOW TABLE STATUS LIKE 't1';
---error ER_GET_ERRMSG
-UPDATE t1 set id = 41 WHERE msg = 'four';
-UPDATE t1 set msg = 'quatre' WHERE id = 4;
-SELECT * FROM dr1 ORDER BY fname, ftype;
---echo #
---echo # Altering partitioning on inward table
---echo #
-ALTER TABLE t1
-PARTITION by range(id) (
-PARTITION first VALUES LESS THAN(11),
-PARTITION middle VALUES LESS THAN(50),
-PARTITION last VALUES LESS THAN(MAXVALUE));
-SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
-SELECT * FROM dr1 ORDER BY fname, ftype;
-EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id=10;
-SELECT * FROM t1 WHERE id=10;
-DELETE FROM t1 WHERE id in (4,60);
-SELECT * FROM t1;
-DROP TABLE t1;
-# TODO: this fails on Linux
-#SELECT * FROM dr1;
-
---echo #
---echo # Testing partitioning on a void outward table
---echo #
-ALTER TABLE dr1 FILE_NAME='part*.*';
-CREATE TABLE t1 (
- rwid INT(6) DEFAULT 0 SPECIAL=ROWID,
- rnum INT(6) DEFAULT 0 SPECIAL=ROWNUM,
- prtn VARCHAR(64) DEFAULT '' SPECIAL=PARTID,
- tbn VARCHAR(64) DEFAULT '' SPECIAL=TABID,
- fid VARCHAR(256) DEFAULT '' SPECIAL=FNAME,
- id INT KEY NOT NULL,
- msg VARCHAR(32)
-) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='part%s.txt';
---replace_result $MYSQLD_DATADIR "DATADIR/"
-ALTER TABLE t1
-PARTITION by range columns(id) (
-PARTITION `1` VALUES LESS THAN(10),
-PARTITION `2` VALUES LESS THAN(50),
-PARTITION `3` VALUES LESS THAN(MAXVALUE));
-SHOW INDEX FROM t1;
-# TODO: this fails on Linux
-#SELECT * FROM dr1 ORDER BY fname, ftype;
-INSERT INTO t1(id,msg) VALUES(4, 'four');
-SELECT * FROM dr1 ORDER BY fname, ftype;
-INSERT INTO t1(id,msg) VALUES(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one');
-INSERT INTO t1(id,msg) VALUES(72,'seventy two'),(20,'twenty'),(1,'one'),(35,'thirty five'),(8,'eight');
-SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
-SELECT * FROM t1;
-SELECT * FROM t1 order by id;
-EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
-SELECT * FROM t1 WHERE id = 10;
-EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id >= 10;
-SELECT * FROM t1 WHERE id >= 10;
-SELECT count(*) FROM t1 WHERE id < 10;
-SELECT case when id < 10 then 1 when id < 50 then 2 else 3 end as pn, count(*) FROM t1 group by pn;
-SELECT prtn, count(*) FROM t1 group by prtn;
-EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id > 50;
-SELECT * FROM t1 WHERE id = 35;
-SELECT * FROM dr1 ORDER BY fname, ftype;
---echo # This does not change the partition file data and is WRONG
-ALTER TABLE t1
-PARTITION by range columns(id) (
-PARTITION `1` VALUES LESS THAN(11),
-PARTITION `2` VALUES LESS THAN(70),
-PARTITION `3` VALUES LESS THAN(MAXVALUE));
-SELECT CASE WHEN id < 11 THEN 1 WHEN id < 70 THEN 2 ELSE 3 END AS pn, COUNT(*) FROM t1 GROUP BY pn;
-SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
-SELECT * FROM dr1 ORDER BY fname, ftype;
---echo #
---echo # This is the correct way to change partitioning:
---echo # Save table values, erase the table, then re-insert saved values in modified table
---echo #
-CREATE TABLE t2 (
- id INT NOT NULL,
- msg VARCHAR(32)
-) ENGINE=CONNECT TABLE_TYPE=FIX;
-INSERT INTO t2 SELECT id, msg FROM t1;
-DELETE FROM t1;
-INSERT INTO t1(id,msg) SELECT * FROM t2;
-SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
-SELECT * FROM t1;
-SELECT * FROM dr1 ORDER BY fname, ftype;
-DROP TABLE t2;
-DROP TABLE t1;
-
---echo #
---echo # Testing partitioning on a populated outward table
---echo #
-CREATE TABLE t1 (
- id INT NOT NULL,
- msg VARCHAR(32)
-) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='part%s.txt'
-PARTITION by range columns(id) (
-PARTITION `1` VALUES LESS THAN(11),
-PARTITION `2` VALUES LESS THAN(70),
-PARTITION `3` VALUES LESS THAN(MAXVALUE));
-SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
-SELECT * FROM t1 WHERE id < 11;
-SELECT * FROM t1 WHERE id >= 70;
-SELECT * FROM dr1 ORDER BY fname, ftype;
-
---echo #
---echo # Testing indexing on a partitioned table
---echo #
-CREATE INDEX XID ON t1(id);
-SHOW INDEX FROM t1;
-SELECT * FROM dr1 ORDER BY fname, ftype;
-EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
-DROP INDEX XID ON t1;
-SHOW INDEX FROM t1;
-SELECT * FROM dr1 ORDER BY fname, ftype;
-ALTER TABLE t1 ADD PRIMARY KEY (id);
-SHOW INDEX FROM t1;
-SELECT * FROM dr1 ORDER BY fname, ftype;
-EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
-ALTER TABLE t1 DROP PRIMARY KEY;
-SHOW INDEX FROM t1;
-SELECT * FROM dr1 ORDER BY fname, ftype;
-DROP TABLE t1;
-DROP TABLE dr1;
-
-#
-# Clean up
-#
-set @@global.connect_exact_info=OFF;
-
---remove_file $MYSQLD_DATADIR/test/part1.txt
---remove_file $MYSQLD_DATADIR/test/part2.txt
---remove_file $MYSQLD_DATADIR/test/part3.txt
-#--remove_file $MYSQLD_DATADIR/test/part%s.fnx
-#--remove_file $MYSQLD_DATADIR/test/part1.fnx
-#--remove_file $MYSQLD_DATADIR/test/part2.fnx
-#--remove_file $MYSQLD_DATADIR/test/part3.fnx
+--source include/have_partition.inc
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+set @@global.connect_exact_info=ON;
+
+--echo # This will be used to see what data files are created
+CREATE TABLE dr1 (
+ fname VARCHAR(256) NOT NULL FLAG=2,
+ ftype CHAR(8) NOT NULL FLAG=3
+# ,FSIZE INT(6) NOT NULL FLAG=5 removed because Unix size != Windows size
+) engine=CONNECT table_type=DIR file_name='t1#P#*.*';
+
+--echo #
+--echo # Testing partitioning on inward table
+--echo #
+CREATE TABLE t1 (
+ id INT NOT NULL,
+ msg VARCHAR(32)
+) ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=10
+PARTITION BY RANGE(id) (
+PARTITION first VALUES LESS THAN(10),
+PARTITION middle VALUES LESS THAN(50),
+PARTITION last VALUES LESS THAN(MAXVALUE));
+INSERT INTO t1 VALUES(4, 'four'),(24, 'twenty four');
+INSERT INTO t1 VALUES(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one');
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id > 50;
+SELECT * FROM t1 WHERE id > 50;
+#TODO: Differences between Linux and Windows
+#SHOW TABLE STATUS LIKE 't1';
+--error ER_GET_ERRMSG
+UPDATE t1 set id = 41 WHERE msg = 'four';
+UPDATE t1 set msg = 'quatre' WHERE id = 4;
+SELECT * FROM dr1 ORDER BY fname, ftype;
+--echo #
+--echo # Altering partitioning on inward table
+--echo #
+ALTER TABLE t1
+PARTITION by range(id) (
+PARTITION first VALUES LESS THAN(11),
+PARTITION middle VALUES LESS THAN(50),
+PARTITION last VALUES LESS THAN(MAXVALUE));
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM dr1 ORDER BY fname, ftype;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id=10;
+SELECT * FROM t1 WHERE id=10;
+DELETE FROM t1 WHERE id in (4,60);
+SELECT * FROM t1;
+DROP TABLE t1;
+# TODO: this fails on Linux
+#SELECT * FROM dr1;
+
+--echo #
+--echo # Testing partitioning on a void outward table
+--echo #
+ALTER TABLE dr1 FILE_NAME='part*.*';
+CREATE TABLE t1 (
+ rwid INT(6) DEFAULT 0 SPECIAL=ROWID,
+ rnum INT(6) DEFAULT 0 SPECIAL=ROWNUM,
+ prtn VARCHAR(64) DEFAULT '' SPECIAL=PARTID,
+ tbn VARCHAR(64) DEFAULT '' SPECIAL=TABID,
+ fid VARCHAR(256) DEFAULT '' SPECIAL=FNAME,
+ id INT KEY NOT NULL,
+ msg VARCHAR(32)
+) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='part%s.txt';
+--replace_result $MYSQLD_DATADIR "DATADIR/"
+ALTER TABLE t1
+PARTITION by range columns(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+SHOW INDEX FROM t1;
+# TODO: this fails on Linux
+#SELECT * FROM dr1 ORDER BY fname, ftype;
+INSERT INTO t1(id,msg) VALUES(4, 'four');
+SELECT * FROM dr1 ORDER BY fname, ftype;
+INSERT INTO t1(id,msg) VALUES(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one');
+INSERT INTO t1(id,msg) VALUES(72,'seventy two'),(20,'twenty'),(1,'one'),(35,'thirty five'),(8,'eight');
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1;
+SELECT * FROM t1 order by id;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
+SELECT * FROM t1 WHERE id = 10;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id >= 10;
+SELECT * FROM t1 WHERE id >= 10;
+SELECT count(*) FROM t1 WHERE id < 10;
+SELECT case when id < 10 then 1 when id < 50 then 2 else 3 end as pn, count(*) FROM t1 group by pn;
+SELECT prtn, count(*) FROM t1 group by prtn;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id > 50;
+SELECT * FROM t1 WHERE id = 35;
+SELECT * FROM dr1 ORDER BY fname, ftype;
+--echo # This does not change the partition file data and is WRONG
+ALTER TABLE t1
+PARTITION by range columns(id) (
+PARTITION `1` VALUES LESS THAN(11),
+PARTITION `2` VALUES LESS THAN(70),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+SELECT CASE WHEN id < 11 THEN 1 WHEN id < 70 THEN 2 ELSE 3 END AS pn, COUNT(*) FROM t1 GROUP BY pn;
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM dr1 ORDER BY fname, ftype;
+--echo #
+--echo # This is the correct way to change partitioning:
+--echo # Save table values, erase the table, then re-insert saved values in modified table
+--echo #
+CREATE TABLE t2 (
+ id INT NOT NULL,
+ msg VARCHAR(32)
+) ENGINE=CONNECT TABLE_TYPE=FIX;
+INSERT INTO t2 SELECT id, msg FROM t1;
+DELETE FROM t1;
+INSERT INTO t1(id,msg) SELECT * FROM t2;
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1;
+SELECT * FROM dr1 ORDER BY fname, ftype;
+DROP TABLE t2;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing partitioning on a populated outward table
+--echo #
+CREATE TABLE t1 (
+ id INT NOT NULL,
+ msg VARCHAR(32)
+) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='part%s.txt'
+PARTITION by range columns(id) (
+PARTITION `1` VALUES LESS THAN(11),
+PARTITION `2` VALUES LESS THAN(70),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1 WHERE id < 11;
+SELECT * FROM t1 WHERE id >= 70;
+SELECT * FROM dr1 ORDER BY fname, ftype;
+
+--echo #
+--echo # Testing indexing on a partitioned table
+--echo #
+CREATE INDEX XID ON t1(id);
+SHOW INDEX FROM t1;
+SELECT * FROM dr1 ORDER BY fname, ftype;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
+DROP INDEX XID ON t1;
+SHOW INDEX FROM t1;
+SELECT * FROM dr1 ORDER BY fname, ftype;
+ALTER TABLE t1 ADD PRIMARY KEY (id);
+SHOW INDEX FROM t1;
+SELECT * FROM dr1 ORDER BY fname, ftype;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
+ALTER TABLE t1 DROP PRIMARY KEY;
+SHOW INDEX FROM t1;
+SELECT * FROM dr1 ORDER BY fname, ftype;
+DROP TABLE t1;
+DROP TABLE dr1;
+
+#
+# Clean up
+#
+set @@global.connect_exact_info=OFF;
+
+--remove_file $MYSQLD_DATADIR/test/part1.txt
+--remove_file $MYSQLD_DATADIR/test/part2.txt
+--remove_file $MYSQLD_DATADIR/test/part3.txt
+#--remove_file $MYSQLD_DATADIR/test/part%s.fnx
+#--remove_file $MYSQLD_DATADIR/test/part1.fnx
+#--remove_file $MYSQLD_DATADIR/test/part2.fnx
+#--remove_file $MYSQLD_DATADIR/test/part3.fnx
diff --git a/storage/connect/mysql-test/connect/t/part_table.test b/storage/connect/mysql-test/connect/t/part_table.test
index c5358d63c8e..d839337ba6f 100644
--- a/storage/connect/mysql-test/connect/t/part_table.test
+++ b/storage/connect/mysql-test/connect/t/part_table.test
@@ -1,92 +1,92 @@
---source include/not_embedded.inc
---source include/have_partition.inc
-
-set @@global.connect_exact_info=ON;
-
-#
-# These will be used by the t1 table partition table
-#
-CREATE TABLE xt1 (
-id INT KEY NOT NULL,
-msg VARCHAR(32))
-ENGINE=MyISAM;
-INSERT INTO xt1 VALUES(4, 'four'),(7,'seven'),(1,'one'),(8,'eight');
-SELECT * FROM xt1;
-
-CREATE TABLE xt2 (
-id INT KEY NOT NULL,
-msg VARCHAR(32));
-INSERT INTO xt2 VALUES(10,'ten'),(40,'forty'),(11,'eleven'),(35,'thirty five');
-SELECT * FROM xt2;
-
-CREATE TABLE xt3 (
-id INT KEY NOT NULL,
-msg VARCHAR(32))
-ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=10;
-INSERT INTO xt3 VALUES(60,'sixty'),(81,'eighty one'),(72,'seventy two');
-SELECT * FROM xt3;
-
-#
-# Based on PROXY the table is not indexable
-#
-CREATE TABLE t1 (
-id INT NOT NULL,
-msg VARCHAR(32))
-ENGINE=CONNECT TABLE_TYPE=PROXY TABNAME='xt%s'
-PARTITION BY RANGE COLUMNS(id) (
-PARTITION `1` VALUES LESS THAN(10),
-PARTITION `2` VALUES LESS THAN(50),
-PARTITION `3` VALUES LESS THAN(MAXVALUE));
-SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
-SELECT * FROM t1;
-DELETE FROM t1;
---error ER_UNKNOWN_ERROR
-ALTER TABLE t1 ADD INDEX XID(id);
-INSERT INTO t1 VALUES(4, 'four');
-INSERT INTO t1 VALUES(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one');
-INSERT INTO t1 VALUES(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight');
-SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
-SELECT * FROM t1;
-EXPLAIN PARTITIONS
-SELECT * FROM t1 WHERE id = 81;
-DELETE FROM t1;
-DROP TABLE t1;
-
-#
-# Based on MYSQL the table is indexable
-#
-CREATE TABLE t1 (
-id INT KEY NOT NULL,
-msg VARCHAR(32))
-ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='xt%s'
-PARTITION BY RANGE COLUMNS(id) (
-PARTITION `1` VALUES LESS THAN(10),
-PARTITION `2` VALUES LESS THAN(50),
-PARTITION `3` VALUES LESS THAN(MAXVALUE));
-SHOW INDEX FROM t1;
-INSERT INTO t1 VALUES(4, 'four');
-INSERT INTO t1 VALUES(40, 'forty');
-INSERT INTO t1 VALUES(72,'seventy two');
-INSERT INTO t1 VALUES(7,'seven'),(10,'ten'),(60,'sixty'),(81,'eighty one'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight');
-SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
-SELECT * FROM t1;
-EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 81;
-SELECT * FROM t1 WHERE id = 7;
-SELECT * FROM t1 WHERE id = 35;
-UPDATE t1 SET msg = 'number' WHERE id in (60,72);
-UPDATE t1 SET msg = 'soixante' WHERE id = 60;
-SELECT * FROM t1 WHERE id > 50;
-UPDATE t1 SET msg = 'big' WHERE id > 50;
-UPDATE t1 SET msg = 'sept' WHERE id = 7;
-SELECT * FROM t1;
-DELETE FROM t1 WHERE id in (60,72);
-SELECT * FROM t1;
-DROP TABLE t1;
-DROP TABLE xt1;
-DROP TABLE xt2;
-DROP TABLE xt3;
-
-#
-# Clean up
-#
-set @@global.connect_exact_info=OFF;
+--source include/not_embedded.inc
+--source include/have_partition.inc
+
+set @@global.connect_exact_info=ON;
+
+#
+# These will be used by the t1 table partition table
+#
+CREATE TABLE xt1 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=MyISAM;
+INSERT INTO xt1 VALUES(4, 'four'),(7,'seven'),(1,'one'),(8,'eight');
+SELECT * FROM xt1;
+
+CREATE TABLE xt2 (
+id INT KEY NOT NULL,
+msg VARCHAR(32));
+INSERT INTO xt2 VALUES(10,'ten'),(40,'forty'),(11,'eleven'),(35,'thirty five');
+SELECT * FROM xt2;
+
+CREATE TABLE xt3 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=10;
+INSERT INTO xt3 VALUES(60,'sixty'),(81,'eighty one'),(72,'seventy two');
+SELECT * FROM xt3;
+
+#
+# Based on PROXY the table is not indexable
+#
+CREATE TABLE t1 (
+id INT NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=PROXY TABNAME='xt%s'
+PARTITION BY RANGE COLUMNS(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1;
+DELETE FROM t1;
+--error ER_UNKNOWN_ERROR
+ALTER TABLE t1 ADD INDEX XID(id);
+INSERT INTO t1 VALUES(4, 'four');
+INSERT INTO t1 VALUES(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one');
+INSERT INTO t1 VALUES(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight');
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1;
+EXPLAIN PARTITIONS
+SELECT * FROM t1 WHERE id = 81;
+DELETE FROM t1;
+DROP TABLE t1;
+
+#
+# Based on MYSQL the table is indexable
+#
+CREATE TABLE t1 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='xt%s'
+PARTITION BY RANGE COLUMNS(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+SHOW INDEX FROM t1;
+INSERT INTO t1 VALUES(4, 'four');
+INSERT INTO t1 VALUES(40, 'forty');
+INSERT INTO t1 VALUES(72,'seventy two');
+INSERT INTO t1 VALUES(7,'seven'),(10,'ten'),(60,'sixty'),(81,'eighty one'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight');
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 81;
+SELECT * FROM t1 WHERE id = 7;
+SELECT * FROM t1 WHERE id = 35;
+UPDATE t1 SET msg = 'number' WHERE id in (60,72);
+UPDATE t1 SET msg = 'soixante' WHERE id = 60;
+SELECT * FROM t1 WHERE id > 50;
+UPDATE t1 SET msg = 'big' WHERE id > 50;
+UPDATE t1 SET msg = 'sept' WHERE id = 7;
+SELECT * FROM t1;
+DELETE FROM t1 WHERE id in (60,72);
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP TABLE xt1;
+DROP TABLE xt2;
+DROP TABLE xt3;
+
+#
+# Clean up
+#
+set @@global.connect_exact_info=OFF;
diff --git a/storage/connect/mysql-test/connect/t/pivot.test b/storage/connect/mysql-test/connect/t/pivot.test
index d26e6cec628..09544f27afa 100644
--- a/storage/connect/mysql-test/connect/t/pivot.test
+++ b/storage/connect/mysql-test/connect/t/pivot.test
@@ -1,163 +1,163 @@
--- source include/not_embedded.inc
-
-let $MYSQLD_DATADIR= `select @@datadir`;
-let $PORT= `select @@port`;
---copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt
-
---echo #
---echo # Testing the PIVOT table type
---echo #
-CREATE TABLE expenses (
-Who CHAR(10) NOT NULL,
-Week INT(2) NOT NULL,
-What CHAR(12) NOT NULL,
-Amount DOUBLE(8,2))
-ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt' ENDING=2;
-SELECT * FROM expenses;
-
---echo #
---echo # Pivoting from What
---echo #
-CREATE TABLE pivex (
-Who CHAR(10) NOT NULL,
-Week INT(2) NOT NULL,
-Beer DOUBLE(8,2) FLAG=1,
-Car DOUBLE(8,2) FLAG=1,
-Food DOUBLE(8,2) FLAG=1)
-ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
---replace_result $PORT PORT
---eval ALTER TABLE pivex OPTION_LIST='port=$PORT'
-SELECT * FROM pivex;
-
---echo #
---echo # Restricting the columns in a Pivot Table
---echo #
-ALTER TABLE pivex DROP COLUMN week;
-SELECT * FROM pivex;
-
---echo #
---echo # Using a source definition
---echo #
-DROP TABLE pivex;
-CREATE TABLE pivex (
-Who CHAR(10) NOT NULL,
-Week INT(2) NOT NULL,
-Beer DOUBLE(8,2) FLAG=1,
-Car DOUBLE(8,2) FLAG=1,
-Food DOUBLE(8,2) FLAG=1)
-ENGINE=CONNECT TABLE_TYPE=PIVOT
-SRCDEF='select who, week, what, sum(amount) as amount from expenses where week in (4,5) group by who, week, what';
---replace_result $PORT PORT
---eval ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=$PORT'
-SELECT * FROM pivex;
-
---echo #
---echo # Pivoting from Week
---echo #
-DROP TABLE pivex;
-CREATE TABLE pivex (
-Who CHAR(10) NOT NULL,
-What CHAR(12) NOT NULL,
-`3` DOUBLE(8,2) FLAG=1,
-`4` DOUBLE(8,2) FLAG=1,
-`5` DOUBLE(8,2) FLAG=1)
-ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
---replace_result $PORT PORT
---eval ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=$PORT'
-SELECT * FROM pivex;
-
---echo #
---echo # Using scalar functions and expresssions
---echo #
-DROP TABLE pivex;
-CREATE TABLE pivex (
-Who CHAR(10) NOT NULL,
-What CHAR(12) NOT NULL,
-First DOUBLE(8,2) FLAG=1,
-Middle DOUBLE(8,2) FLAG=1,
-Last DOUBLE(8,2) FLAG=1)
-ENGINE=CONNECT TABLE_TYPE=PIVOT
-SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk';
---replace_result $PORT PORT
---eval ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=$PORT'
-SELECT * FROM pivex;
-DROP TABLE pivex;
-DROP TABLE expenses;
-
---echo #
---echo # Make the PETS table
---echo #
-CREATE TABLE pets (
-Name VARCHAR(12) NOT NULL,
-Race CHAR(6) NOT NULL,
-Number INT NOT NULL) ENGINE=MYISAM;
-INSERT INTO pets VALUES('John','dog',2);
-INSERT INTO pets VALUES('Bill','cat',1);
-INSERT INTO pets VALUES('Mary','dog',1);
-INSERT INTO pets VALUES('Mary','cat',1);
-INSERT INTO pets VALUES('Lisbeth','rabbit',2);
-INSERT INTO pets VALUES('Kevin','cat',2);
-INSERT INTO pets VALUES('Kevin','bird',6);
-INSERT INTO pets VALUES('Donald','dog',1);
-INSERT INTO pets VALUES('Donald','fish',3);
-SELECT * FROM pets;
-
---echo #
---echo # Pivot the PETS table
---echo #
-CREATE TABLE pivet (
-name VARCHAR(12) NOT NULL,
-dog INT NOT NULL DEFAULT 0 FLAG=1,
-cat INT NOT NULL DEFAULT 0 FLAG=1,
-rabbit INT NOT NULL DEFAULT 0 FLAG=1,
-bird INT NOT NULL DEFAULT 0 FLAG=1,
-fish INT NOT NULL DEFAULT 0 FLAG=1)
-ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
-SELECT * FROM pivet;
-DROP TABLE pivet;
-
---echo #
---echo # Testing the "data" column list
---echo #
-CREATE TABLE pivet (
-name VARCHAR(12) NOT NULL,
-dog INT NOT NULL DEFAULT 0 FLAG=1,
-cat INT NOT NULL DEFAULT 0 FLAG=1)
-ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
---error ER_GET_ERRMSG
-SELECT * FROM pivet;
-ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1';
-SELECT * FROM pivet;
-DROP TABLE pivet;
-
---echo #
---echo # Adding a "dump" column
---echo #
-CREATE TABLE pivet (
-name VARCHAR(12) NOT NULL,
-dog INT NOT NULL DEFAULT 0 FLAG=1,
-cat INT NOT NULL DEFAULT 0 FLAG=1,
-other INT NOT NULL DEFAULT 0 FLAG=2)
-ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
-SELECT * FROM pivet;
-
-DROP TABLE pivet;
-DROP TABLE pets;
-
---echo #
---echo # MDEV-5734
---echo #
-CREATE TABLE fruit (
- `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
- `name` varchar(32) NOT NULL,
- `cnt` int(11) DEFAULT NULL,
- PRIMARY KEY (`id`)
-) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
-INSERT INTO fruit VALUES (1,'apple',1),(2,'banana',1),(3,'apple',2),(4,'cherry',4),(5,'durazno',2);
-SELECT * FROM fruit;
-CREATE TABLE fruit_pivot ENGINE=CONNECT TABLE_TYPE=pivot TABNAME=fruit;
-SELECT * FROM fruit_pivot;
-
-DROP TABLE fruit_pivot;
-DROP TABLE fruit;
---remove_file $MYSQLD_DATADIR/test/expenses.txt
+-- source include/not_embedded.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+let $PORT= `select @@port`;
+--copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt
+
+--echo #
+--echo # Testing the PIVOT table type
+--echo #
+CREATE TABLE expenses (
+Who CHAR(10) NOT NULL,
+Week INT(2) NOT NULL,
+What CHAR(12) NOT NULL,
+Amount DOUBLE(8,2))
+ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt' ENDING=2;
+SELECT * FROM expenses;
+
+--echo #
+--echo # Pivoting from What
+--echo #
+CREATE TABLE pivex (
+Who CHAR(10) NOT NULL,
+Week INT(2) NOT NULL,
+Beer DOUBLE(8,2) FLAG=1,
+Car DOUBLE(8,2) FLAG=1,
+Food DOUBLE(8,2) FLAG=1)
+ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
+--replace_result $PORT PORT
+--eval ALTER TABLE pivex OPTION_LIST='port=$PORT'
+SELECT * FROM pivex;
+
+--echo #
+--echo # Restricting the columns in a Pivot Table
+--echo #
+ALTER TABLE pivex DROP COLUMN week;
+SELECT * FROM pivex;
+
+--echo #
+--echo # Using a source definition
+--echo #
+DROP TABLE pivex;
+CREATE TABLE pivex (
+Who CHAR(10) NOT NULL,
+Week INT(2) NOT NULL,
+Beer DOUBLE(8,2) FLAG=1,
+Car DOUBLE(8,2) FLAG=1,
+Food DOUBLE(8,2) FLAG=1)
+ENGINE=CONNECT TABLE_TYPE=PIVOT
+SRCDEF='select who, week, what, sum(amount) as amount from expenses where week in (4,5) group by who, week, what';
+--replace_result $PORT PORT
+--eval ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=$PORT'
+SELECT * FROM pivex;
+
+--echo #
+--echo # Pivoting from Week
+--echo #
+DROP TABLE pivex;
+CREATE TABLE pivex (
+Who CHAR(10) NOT NULL,
+What CHAR(12) NOT NULL,
+`3` DOUBLE(8,2) FLAG=1,
+`4` DOUBLE(8,2) FLAG=1,
+`5` DOUBLE(8,2) FLAG=1)
+ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
+--replace_result $PORT PORT
+--eval ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=$PORT'
+SELECT * FROM pivex;
+
+--echo #
+--echo # Using scalar functions and expresssions
+--echo #
+DROP TABLE pivex;
+CREATE TABLE pivex (
+Who CHAR(10) NOT NULL,
+What CHAR(12) NOT NULL,
+First DOUBLE(8,2) FLAG=1,
+Middle DOUBLE(8,2) FLAG=1,
+Last DOUBLE(8,2) FLAG=1)
+ENGINE=CONNECT TABLE_TYPE=PIVOT
+SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk';
+--replace_result $PORT PORT
+--eval ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=$PORT'
+SELECT * FROM pivex;
+DROP TABLE pivex;
+DROP TABLE expenses;
+
+--echo #
+--echo # Make the PETS table
+--echo #
+CREATE TABLE pets (
+Name VARCHAR(12) NOT NULL,
+Race CHAR(6) NOT NULL,
+Number INT NOT NULL) ENGINE=MYISAM;
+INSERT INTO pets VALUES('John','dog',2);
+INSERT INTO pets VALUES('Bill','cat',1);
+INSERT INTO pets VALUES('Mary','dog',1);
+INSERT INTO pets VALUES('Mary','cat',1);
+INSERT INTO pets VALUES('Lisbeth','rabbit',2);
+INSERT INTO pets VALUES('Kevin','cat',2);
+INSERT INTO pets VALUES('Kevin','bird',6);
+INSERT INTO pets VALUES('Donald','dog',1);
+INSERT INTO pets VALUES('Donald','fish',3);
+SELECT * FROM pets;
+
+--echo #
+--echo # Pivot the PETS table
+--echo #
+CREATE TABLE pivet (
+name VARCHAR(12) NOT NULL,
+dog INT NOT NULL DEFAULT 0 FLAG=1,
+cat INT NOT NULL DEFAULT 0 FLAG=1,
+rabbit INT NOT NULL DEFAULT 0 FLAG=1,
+bird INT NOT NULL DEFAULT 0 FLAG=1,
+fish INT NOT NULL DEFAULT 0 FLAG=1)
+ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
+SELECT * FROM pivet;
+DROP TABLE pivet;
+
+--echo #
+--echo # Testing the "data" column list
+--echo #
+CREATE TABLE pivet (
+name VARCHAR(12) NOT NULL,
+dog INT NOT NULL DEFAULT 0 FLAG=1,
+cat INT NOT NULL DEFAULT 0 FLAG=1)
+ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
+--error ER_GET_ERRMSG
+SELECT * FROM pivet;
+ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1';
+SELECT * FROM pivet;
+DROP TABLE pivet;
+
+--echo #
+--echo # Adding a "dump" column
+--echo #
+CREATE TABLE pivet (
+name VARCHAR(12) NOT NULL,
+dog INT NOT NULL DEFAULT 0 FLAG=1,
+cat INT NOT NULL DEFAULT 0 FLAG=1,
+other INT NOT NULL DEFAULT 0 FLAG=2)
+ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
+SELECT * FROM pivet;
+
+DROP TABLE pivet;
+DROP TABLE pets;
+
+--echo #
+--echo # MDEV-5734
+--echo #
+CREATE TABLE fruit (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `name` varchar(32) NOT NULL,
+ `cnt` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
+INSERT INTO fruit VALUES (1,'apple',1),(2,'banana',1),(3,'apple',2),(4,'cherry',4),(5,'durazno',2);
+SELECT * FROM fruit;
+CREATE TABLE fruit_pivot ENGINE=CONNECT TABLE_TYPE=pivot TABNAME=fruit;
+SELECT * FROM fruit_pivot;
+
+DROP TABLE fruit_pivot;
+DROP TABLE fruit;
+--remove_file $MYSQLD_DATADIR/test/expenses.txt
diff --git a/storage/connect/mysql-test/connect/t/tbl.test b/storage/connect/mysql-test/connect/t/tbl.test
index bdd928366ef..43c506c9403 100644
--- a/storage/connect/mysql-test/connect/t/tbl.test
+++ b/storage/connect/mysql-test/connect/t/tbl.test
@@ -1,53 +1,53 @@
--- source include/not_embedded.inc
-
-let $MYSQLD_DATADIR= `select @@datadir`;
-let $PORT= `select @@port`;
-
---echo #
---echo # Checking TBL tables
---echo #
-CREATE TABLE t1 (
-a INT NOT NULL,
-message CHAR(10)) ENGINE=connect;
-INSERT INTO t1 VALUES (1,'Testing'),(2,'dos table'),(3,'t1');
-SELECT * FROM t1;
-
-CREATE TABLE t2 (
-a INT NOT NULL,
-message CHAR(10)) ENGINE=connect TABLE_TYPE=BIN;
-INSERT INTO t2 VALUES (1,'Testing'),(2,NULL),(3,'t2');
-SELECT * FROM t2;
-
-CREATE TABLE t3 (
-a INT NOT NULL,
-message CHAR(10)) ENGINE=connect TABLE_TYPE=CSV;
-INSERT INTO t3 VALUES (1,'Testing'),(2,'csv table'),(3,'t3');
-SELECT * FROM t3;
-
-CREATE TABLE t4 (
-ta INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-message CHAR(20)) ENGINE=MyISAM;
-INSERT INTO t4 (message) VALUES ('Testing'),('myisam table'),('t4');
-SELECT * FROM t4;
-
---replace_result $PORT PORT
---eval CREATE TABLE total (tabname CHAR(8) NOT NULL SPECIAL='TABID', ta TINYINT NOT NULL FLAG=1, message CHAR(20)) engine=CONNECT table_type=TBL table_list='t1,t2,t3,t4' option_list='port=$PORT'
-
-select * from total;
-select * from total where tabname = 't2';
-select * from total where tabname = 't2' and ta = 3;
-select * from total where tabname in ('t1','t4');
-select * from total where ta = 3 and tabname in ('t1','t2');
-select * from total where tabname <> 't2';
-select * from total where tabname != 't2' and ta = 3;
-select * from total where tabname not in ('t2','t3');
-select * from total where ta = 3 and tabname in ('t2','t3');
-select * from total where ta = 3 or tabname in ('t2','t4');
-select * from total where not tabname = 't2';
-select * from total where tabname = 't2' or tabname = 't1';
-
-DROP TABLE total;
-DROP TABLE t1;
-DROP TABLE t2;
-DROP TABLE t3;
-DROP TABLE t4;
+-- source include/not_embedded.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+let $PORT= `select @@port`;
+
+--echo #
+--echo # Checking TBL tables
+--echo #
+CREATE TABLE t1 (
+a INT NOT NULL,
+message CHAR(10)) ENGINE=connect;
+INSERT INTO t1 VALUES (1,'Testing'),(2,'dos table'),(3,'t1');
+SELECT * FROM t1;
+
+CREATE TABLE t2 (
+a INT NOT NULL,
+message CHAR(10)) ENGINE=connect TABLE_TYPE=BIN;
+INSERT INTO t2 VALUES (1,'Testing'),(2,NULL),(3,'t2');
+SELECT * FROM t2;
+
+CREATE TABLE t3 (
+a INT NOT NULL,
+message CHAR(10)) ENGINE=connect TABLE_TYPE=CSV;
+INSERT INTO t3 VALUES (1,'Testing'),(2,'csv table'),(3,'t3');
+SELECT * FROM t3;
+
+CREATE TABLE t4 (
+ta INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+message CHAR(20)) ENGINE=MyISAM;
+INSERT INTO t4 (message) VALUES ('Testing'),('myisam table'),('t4');
+SELECT * FROM t4;
+
+--replace_result $PORT PORT
+--eval CREATE TABLE total (tabname CHAR(8) NOT NULL SPECIAL='TABID', ta TINYINT NOT NULL FLAG=1, message CHAR(20)) engine=CONNECT table_type=TBL table_list='t1,t2,t3,t4' option_list='port=$PORT'
+
+select * from total;
+select * from total where tabname = 't2';
+select * from total where tabname = 't2' and ta = 3;
+select * from total where tabname in ('t1','t4');
+select * from total where ta = 3 and tabname in ('t1','t2');
+select * from total where tabname <> 't2';
+select * from total where tabname != 't2' and ta = 3;
+select * from total where tabname not in ('t2','t3');
+select * from total where ta = 3 and tabname in ('t2','t3');
+select * from total where ta = 3 or tabname in ('t2','t4');
+select * from total where not tabname = 't2';
+select * from total where tabname = 't2' or tabname = 't1';
+
+DROP TABLE total;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+DROP TABLE t4;
diff --git a/storage/connect/mysql-test/connect/t/unsigned.test b/storage/connect/mysql-test/connect/t/unsigned.test
index 4374566086d..44eb832f8ae 100644
--- a/storage/connect/mysql-test/connect/t/unsigned.test
+++ b/storage/connect/mysql-test/connect/t/unsigned.test
@@ -1,35 +1,35 @@
---echo #
---echo # Testing unsigned types
---echo #
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 (
-a TINYINT UNSIGNED NOT NULL,
-b SMALLINT ZEROFILL NOT NULL,
-c INT UNSIGNED NOT NULL,
-d BIGINT UNSIGNED NOT NULL,
-e CHAR(32) NOT NULL DEFAULT '???') ENGINE=CONNECT TABLE_TYPE=FIX;
-DESCRIBE t1;
-INSERT INTO t1(a,b,c,d) VALUES(255,65535,4294967295,18446744073709551615);
-SELECT * FROM t1;
-UPDATE t1 SET e = d;
-SELECT * FROM t1;
-UPDATE t1 SET c = d;
-SELECT * FROM t1;
-UPDATE t1 SET c = e;
-SELECT * FROM t1;
-UPDATE t1 SET d = e;
-SELECT * FROM t1;
-
-DROP TABLE IF EXISTS t2;
-CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=PROXY TABNAME=t1;
-DESCRIBE t2;
-SELECT * FROM t2;
-
-# Moved to mysql.test (cannot be executed if embedded)
-#DROP TABLE t2;
-#CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME=t1;
-#DESCRIBE t2;
-#SELECT * FROM t2;
-
-DROP TABLE t2;
-DROP TABLE t1;
+--echo #
+--echo # Testing unsigned types
+--echo #
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+a TINYINT UNSIGNED NOT NULL,
+b SMALLINT ZEROFILL NOT NULL,
+c INT UNSIGNED NOT NULL,
+d BIGINT UNSIGNED NOT NULL,
+e CHAR(32) NOT NULL DEFAULT '???') ENGINE=CONNECT TABLE_TYPE=FIX;
+DESCRIBE t1;
+INSERT INTO t1(a,b,c,d) VALUES(255,65535,4294967295,18446744073709551615);
+SELECT * FROM t1;
+UPDATE t1 SET e = d;
+SELECT * FROM t1;
+UPDATE t1 SET c = d;
+SELECT * FROM t1;
+UPDATE t1 SET c = e;
+SELECT * FROM t1;
+UPDATE t1 SET d = e;
+SELECT * FROM t1;
+
+DROP TABLE IF EXISTS t2;
+CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=PROXY TABNAME=t1;
+DESCRIBE t2;
+SELECT * FROM t2;
+
+# Moved to mysql.test (cannot be executed if embedded)
+#DROP TABLE t2;
+#CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME=t1;
+#DESCRIBE t2;
+#SELECT * FROM t2;
+
+DROP TABLE t2;
+DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/t/upd.test b/storage/connect/mysql-test/connect/t/upd.test
index f6461bfed96..a3716694c4a 100644
--- a/storage/connect/mysql-test/connect/t/upd.test
+++ b/storage/connect/mysql-test/connect/t/upd.test
@@ -1,153 +1,153 @@
-let $MYSQLD_DATADIR= `select @@datadir`;
---copy_file $MTR_SUITE_DIR/std_data/employee.dat $MYSQLD_DATADIR/test/employee.dat
-
-CREATE TABLE employee
-(
-serialno CHAR(5) NOT NULL,
-name VARCHAR(12) NOT NULL FLAG=6,
-sex TINYINT(1) NOT NULL,
-title VARCHAR(15) NOT NULL FLAG=20,
-manager CHAR(5) NOT NULL,
-department CHAR(4) NOT NULL FLAG=41,
-secretary CHAR(5) NOT NULL FLAG=46,
-salary DOUBLE(8,2) NOT NULL FLAG=52
-) ENGINE=connect TABLE_TYPE=fix FILE_NAME='employee.dat' ENDING=1;
-SELECT * FROM employee;
-
-DELIMITER //;
-CREATE PROCEDURE test.tst_up() DETERMINISTIC
-BEGIN
-SELECT * FROM t1;
-UPDATE t1 SET salary = salary + 1, title = 'RESEARCH' WHERE title = 'SCIENTIST';
-UPDATE t1 SET salary = salary + 1, title = 'TECHNICIAN' WHERE title = 'ENGINEER';
-UPDATE t1 SET title = 'PUPPET' WHERE name = 'TONGHO';
-UPDATE t1 SET salary = 0. WHERE title = 'XXX';
-SELECT * FROM t1;
-DELETE FROM t1 WHERE title = 'SECRETARY';
-DELETE FROM t1 WHERE title = 'DIRECTOR';
-DELETE FROM t1 WHERE title = 'TYPIST';
-SELECT * FROM t1;
-DELETE FROM t1 LIMIT 3;
-INSERT INTO t1(serialno, name, title, salary) VALUES('66666','NEWMAN','ENGINEER',10000.80);
-SELECT * FROM t1;
-DROP TABLE t1;
-END//
-DELIMITER ;//
-
---echo #
---echo # Testing DOS table changes
---echo #
-CREATE TABLE t1 ENGINE=connect AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing DOS table changes
---echo #
-CREATE TABLE t1 ENGINE=connect mapped=yes AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing FIX table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=fix AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing FIX table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=fix mapped=yes AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing FIX table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=fix huge=yes AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing CSV table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=csv AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing CSV table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=csv mapped=yes AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing DBF table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=dbf AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing DBF table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=dbf mapped=yes AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing BIN table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=bin AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing BIN table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=bin mapped=yes AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing BIN table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=bin huge=yes AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing VEC table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=vec MAX_ROWS=30 AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing VEC table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=vec mapped=yes MAX_ROWS=30 AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing VEC table changes
---echo #
-CREATE TABLE t1 ENGINE=connect TABLE_TYPE=vec huge=yes MAX_ROWS=30 AS SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing INI table changes
---echo #
-CREATE TABLE t1
-(
-serialno CHAR(5) NOT NULL FLAG=1,
-name VARCHAR(12) NOT NULL,
-sex TINYINT(1),
-title VARCHAR(15) NOT NULL,
-manager CHAR(5),
-department CHAR(4),
-secretary CHAR(5),
-salary DOUBLE(8,2) NOT NULL
-) ENGINE=connect TABLE_TYPE=ini;
-INSERT INTO t1 SELECT * FROM employee;
-CALL test.tst_up();
-
---echo #
---echo # Testing XML table changes (must be in a separate test)
---echo #
-#CREATE TABLE t1 ENGINE=connect TABLE_TYPE=xml option_list='rownode=dd' AS SELECT * FROM employee;
-#CALL test.tst_up();
-
-DROP PROCEDURE test.tst_up;
-DROP TABLE employee;
-
---remove_file $MYSQLD_DATADIR/test/employee.dat
+let $MYSQLD_DATADIR= `select @@datadir`;
+--copy_file $MTR_SUITE_DIR/std_data/employee.dat $MYSQLD_DATADIR/test/employee.dat
+
+CREATE TABLE employee
+(
+serialno CHAR(5) NOT NULL,
+name VARCHAR(12) NOT NULL FLAG=6,
+sex TINYINT(1) NOT NULL,
+title VARCHAR(15) NOT NULL FLAG=20,
+manager CHAR(5) NOT NULL,
+department CHAR(4) NOT NULL FLAG=41,
+secretary CHAR(5) NOT NULL FLAG=46,
+salary DOUBLE(8,2) NOT NULL FLAG=52
+) ENGINE=connect TABLE_TYPE=fix FILE_NAME='employee.dat' ENDING=1;
+SELECT * FROM employee;
+
+DELIMITER //;
+CREATE PROCEDURE test.tst_up() DETERMINISTIC
+BEGIN
+SELECT * FROM t1;
+UPDATE t1 SET salary = salary + 1, title = 'RESEARCH' WHERE title = 'SCIENTIST';
+UPDATE t1 SET salary = salary + 1, title = 'TECHNICIAN' WHERE title = 'ENGINEER';
+UPDATE t1 SET title = 'PUPPET' WHERE name = 'TONGHO';
+UPDATE t1 SET salary = 0. WHERE title = 'XXX';
+SELECT * FROM t1;
+DELETE FROM t1 WHERE title = 'SECRETARY';
+DELETE FROM t1 WHERE title = 'DIRECTOR';
+DELETE FROM t1 WHERE title = 'TYPIST';
+SELECT * FROM t1;
+DELETE FROM t1 LIMIT 3;
+INSERT INTO t1(serialno, name, title, salary) VALUES('66666','NEWMAN','ENGINEER',10000.80);
+SELECT * FROM t1;
+DROP TABLE t1;
+END//
+DELIMITER ;//
+
+--echo #
+--echo # Testing DOS table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing DOS table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect mapped=yes AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing FIX table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=fix AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing FIX table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=fix mapped=yes AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing FIX table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=fix huge=yes AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing CSV table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=csv AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing CSV table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=csv mapped=yes AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing DBF table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=dbf AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing DBF table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=dbf mapped=yes AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing BIN table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=bin AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing BIN table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=bin mapped=yes AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing BIN table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=bin huge=yes AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing VEC table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=vec MAX_ROWS=30 AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing VEC table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=vec mapped=yes MAX_ROWS=30 AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing VEC table changes
+--echo #
+CREATE TABLE t1 ENGINE=connect TABLE_TYPE=vec huge=yes MAX_ROWS=30 AS SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing INI table changes
+--echo #
+CREATE TABLE t1
+(
+serialno CHAR(5) NOT NULL FLAG=1,
+name VARCHAR(12) NOT NULL,
+sex TINYINT(1),
+title VARCHAR(15) NOT NULL,
+manager CHAR(5),
+department CHAR(4),
+secretary CHAR(5),
+salary DOUBLE(8,2) NOT NULL
+) ENGINE=connect TABLE_TYPE=ini;
+INSERT INTO t1 SELECT * FROM employee;
+CALL test.tst_up();
+
+--echo #
+--echo # Testing XML table changes (must be in a separate test)
+--echo #
+#CREATE TABLE t1 ENGINE=connect TABLE_TYPE=xml option_list='rownode=dd' AS SELECT * FROM employee;
+#CALL test.tst_up();
+
+DROP PROCEDURE test.tst_up;
+DROP TABLE employee;
+
+--remove_file $MYSQLD_DATADIR/test/employee.dat
diff --git a/storage/connect/mysql-test/connect/t/updelx.test b/storage/connect/mysql-test/connect/t/updelx.test
index ab336d4b168..19d0d790a30 100644
--- a/storage/connect/mysql-test/connect/t/updelx.test
+++ b/storage/connect/mysql-test/connect/t/updelx.test
@@ -1,96 +1,96 @@
--- source include/not_embedded.inc
-let $MYSQLD_DATADIR= `select @@datadir`;
-
---echo #
---echo # Testing indexed UPDATE and DELETE for all table types
---echo #
-
---echo # CSV table
-CREATE TABLE t1 (
-id INT KEY NOT NULL,
-msg VARCHAR(32))
-ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=6;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=YES;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=NO BLOCK_SIZE=6;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=YES;
--- source updelx.inc
-DROP TABLE t1;
-
---echo # DOS table
-CREATE TABLE t1 (
-id INT(4) KEY NOT NULL,
-msg VARCHAR(16))
-ENGINE=CONNECT TABLE_TYPE=DOS;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=YES;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=NO BLOCK_SIZE=4;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=YES;
--- source updelx.inc
-DROP TABLE t1;
-
---echo # FIX table
-CREATE TABLE t1 (
-id INT(4) KEY NOT NULL,
-msg VARCHAR(16) CHARSET BINARY DISTRIB=CLUSTERED)
-ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=4;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=YES;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=NO HUGE=YES;
--- source updelx.inc
-DROP TABLE t1;
-
---echo # BIN table
-CREATE TABLE t1 (
-id INT(4) KEY NOT NULL,
-msg VARCHAR(16) CHARSET BINARY DISTRIB=CLUSTERED)
-ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=8;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=YES;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=NO HUGE=YES;
--- source updelx.inc
-DROP TABLE t1;
-
---echo # DBF table
-CREATE TABLE t1 (
-id INT(4) KEY NOT NULL,
-msg VARCHAR(16))
-ENGINE=CONNECT TABLE_TYPE=DBF BLOCK_SIZE=12;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=YES;
--- source updelx.inc
-#ALTER TABLE t1 MAPPED=NO HUGE=YES;
-#-- source updelx.inc
-DROP TABLE t1;
-
---echo # VEC table
-CREATE TABLE t1 (
-id INT(4) KEY NOT NULL,
-msg VARCHAR(16))
-ENGINE=CONNECT TABLE_TYPE=VEC BLOCK_SIZE=6 MAX_ROWS=16;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=YES;
--- source updelx.inc
-ALTER TABLE t1 MAPPED=NO HUGE=YES;
--- source updelx.inc
-DROP TABLE t1;
-
---echo # Split VEC table (outward)
-CREATE TABLE t1 (
-id INT(4) KEY NOT NULL,
-msg VARCHAR(16))
-ENGINE=CONNECT TABLE_TYPE=VEC BLOCK_SIZE=6 FILE_NAME='tx.vec';
--- source updelx.inc
-ALTER TABLE t1 MAPPED=YES;
--- source updelx.inc
-DROP TABLE t1;
-
-# Cleanup
---remove_file $MYSQLD_DATADIR/test/tx1.vec
---remove_file $MYSQLD_DATADIR/test/tx2.vec
+-- source include/not_embedded.inc
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--echo #
+--echo # Testing indexed UPDATE and DELETE for all table types
+--echo #
+
+--echo # CSV table
+CREATE TABLE t1 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=6;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=NO BLOCK_SIZE=6;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+DROP TABLE t1;
+
+--echo # DOS table
+CREATE TABLE t1 (
+id INT(4) KEY NOT NULL,
+msg VARCHAR(16))
+ENGINE=CONNECT TABLE_TYPE=DOS;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=NO BLOCK_SIZE=4;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+DROP TABLE t1;
+
+--echo # FIX table
+CREATE TABLE t1 (
+id INT(4) KEY NOT NULL,
+msg VARCHAR(16) CHARSET BINARY DISTRIB=CLUSTERED)
+ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=4;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=NO HUGE=YES;
+-- source updelx.inc
+DROP TABLE t1;
+
+--echo # BIN table
+CREATE TABLE t1 (
+id INT(4) KEY NOT NULL,
+msg VARCHAR(16) CHARSET BINARY DISTRIB=CLUSTERED)
+ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=8;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=NO HUGE=YES;
+-- source updelx.inc
+DROP TABLE t1;
+
+--echo # DBF table
+CREATE TABLE t1 (
+id INT(4) KEY NOT NULL,
+msg VARCHAR(16))
+ENGINE=CONNECT TABLE_TYPE=DBF BLOCK_SIZE=12;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+#ALTER TABLE t1 MAPPED=NO HUGE=YES;
+#-- source updelx.inc
+DROP TABLE t1;
+
+--echo # VEC table
+CREATE TABLE t1 (
+id INT(4) KEY NOT NULL,
+msg VARCHAR(16))
+ENGINE=CONNECT TABLE_TYPE=VEC BLOCK_SIZE=6 MAX_ROWS=16;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=NO HUGE=YES;
+-- source updelx.inc
+DROP TABLE t1;
+
+--echo # Split VEC table (outward)
+CREATE TABLE t1 (
+id INT(4) KEY NOT NULL,
+msg VARCHAR(16))
+ENGINE=CONNECT TABLE_TYPE=VEC BLOCK_SIZE=6 FILE_NAME='tx.vec';
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+DROP TABLE t1;
+
+# Cleanup
+--remove_file $MYSQLD_DATADIR/test/tx1.vec
+--remove_file $MYSQLD_DATADIR/test/tx2.vec
diff --git a/storage/connect/mysql-test/connect/t/updelx2.test b/storage/connect/mysql-test/connect/t/updelx2.test
index bf5434636ee..8b90851a127 100644
--- a/storage/connect/mysql-test/connect/t/updelx2.test
+++ b/storage/connect/mysql-test/connect/t/updelx2.test
@@ -1,22 +1,22 @@
--- source include/not_embedded.inc
-
---echo #
---echo # Testing multiple indexed UPDATE and DELETE
---echo #
-CREATE TABLE t1 (
-id INT(4) NOT NULL,
-msg VARCHAR(16) NOT NULL,
-INDEX IDM(id,msg))
-ENGINE=CONNECT TABLE_TYPE=DOS;
-INSERT INTO t1 VALUES(1,'one'),(4, 'four'),(7,'seven'),(8,'eight'),(10,'ten'),(11,'eleven'),(40,'forty'),(35,'thirty five'),(60,'sixty'),(72,'seventy two'),(81,'eighty one');
-INSERT INTO t1 VALUES(1,'un'),(4, 'quatre'),(7,'sept'),(8,'huit'),(10,'dix'),(11,'onze'),(40,'quarante'),(35,'trente cinq'),(60,'soixante'),(72,'soixante douze'),(81,'quatrevingt un');
-SELECT * FROM t1 IGNORE INDEX (IDM);
-UPDATE t1 SET msg = 'dieci' WHERE id = 10;
-SELECT * FROM t1 IGNORE INDEX (IDM);
-UPDATE t1 SET msg = 'septante deux' WHERE id = 72;
-SELECT * FROM t1 IGNORE INDEX (IDM);
-UPDATE t1 SET id=2, msg='deux' WHERE id=4 AND msg='quatre';
-SELECT * FROM t1 IGNORE INDEX (IDM);
-DELETE FROM t1 WHERE id IN (8,40);
-SELECT * FROM t1 IGNORE INDEX (IDM);
-DROP TABLE t1;
+-- source include/not_embedded.inc
+
+--echo #
+--echo # Testing multiple indexed UPDATE and DELETE
+--echo #
+CREATE TABLE t1 (
+id INT(4) NOT NULL,
+msg VARCHAR(16) NOT NULL,
+INDEX IDM(id,msg))
+ENGINE=CONNECT TABLE_TYPE=DOS;
+INSERT INTO t1 VALUES(1,'one'),(4, 'four'),(7,'seven'),(8,'eight'),(10,'ten'),(11,'eleven'),(40,'forty'),(35,'thirty five'),(60,'sixty'),(72,'seventy two'),(81,'eighty one');
+INSERT INTO t1 VALUES(1,'un'),(4, 'quatre'),(7,'sept'),(8,'huit'),(10,'dix'),(11,'onze'),(40,'quarante'),(35,'trente cinq'),(60,'soixante'),(72,'soixante douze'),(81,'quatrevingt un');
+SELECT * FROM t1 IGNORE INDEX (IDM);
+UPDATE t1 SET msg = 'dieci' WHERE id = 10;
+SELECT * FROM t1 IGNORE INDEX (IDM);
+UPDATE t1 SET msg = 'septante deux' WHERE id = 72;
+SELECT * FROM t1 IGNORE INDEX (IDM);
+UPDATE t1 SET id=2, msg='deux' WHERE id=4 AND msg='quatre';
+SELECT * FROM t1 IGNORE INDEX (IDM);
+DELETE FROM t1 WHERE id IN (8,40);
+SELECT * FROM t1 IGNORE INDEX (IDM);
+DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/t/xcol.test b/storage/connect/mysql-test/connect/t/xcol.test
index 8f0edc2b268..e0183f01db8 100644
--- a/storage/connect/mysql-test/connect/t/xcol.test
+++ b/storage/connect/mysql-test/connect/t/xcol.test
@@ -1,41 +1,41 @@
---echo #
---echo # Make the children list table
---echo #
-CREATE TABLE chlist (
-mother char(12) NOT NULL COMMENT 'The mother of the listed children',
-children varchar(30) DEFAULT NULL COMMENT 'The comma separated list of children'
-) ENGINE=CONNECT;
-INSERT INTO chlist VALUES('Sophia','Vivian, Antony');
-INSERT INTO chlist VALUES('Lisbeth','Lucy,Charles,Diana');
-INSERT INTO chlist VALUES('Corinne',NULL);
-INSERT INTO chlist VALUES('Claude','Marc');
-INSERT INTO chlist VALUES('Janet','Arthur,Sandra,Peter,John');
-SELECT * FROM chlist;
-
---echo #
---echo # Checking XCOL tables
---echo #
-CREATE TABLE child ENGINE=CONNECT TABLE_TYPE=XCOL TABNAME=chlist OPTION_LIST='colname=children';
-SELECT * FROM child;
-SELECT * FROM child ORDER BY mother;
-SELECT * FROM child ORDER BY children;
-SELECT mother FROM child;
-SELECT mother, COUNT(*) FROM child GROUP BY mother;
-SELECT mother, COUNT(children) FROM child GROUP BY mother;
-
---echo #
---echo # Test using special columns
---echo #
-CREATE TABLE `child2` (
- `row` int NOT NULL SPECIAL=ROWID,
- `num` int NOT NULL SPECIAL=ROWNUM,
- `mother` varchar(12) NOT NULL COMMENT 'The mother of the children',
- `child` varchar(12) NOT NULL COMMENT 'The child name' FLAG=2
-) ENGINE=CONNECT TABLE_TYPE=XCOL TABNAME=chlist `OPTION_LIST`='colname=child';
-SELECT * FROM child2;
---echo # List only first child
-SELECT mother, child FROM child2 where num = 1;
-
-DROP TABLE child;
-DROP TABLE chlist;
-DROP TABLE child2;
+--echo #
+--echo # Make the children list table
+--echo #
+CREATE TABLE chlist (
+mother char(12) NOT NULL COMMENT 'The mother of the listed children',
+children varchar(30) DEFAULT NULL COMMENT 'The comma separated list of children'
+) ENGINE=CONNECT;
+INSERT INTO chlist VALUES('Sophia','Vivian, Antony');
+INSERT INTO chlist VALUES('Lisbeth','Lucy,Charles,Diana');
+INSERT INTO chlist VALUES('Corinne',NULL);
+INSERT INTO chlist VALUES('Claude','Marc');
+INSERT INTO chlist VALUES('Janet','Arthur,Sandra,Peter,John');
+SELECT * FROM chlist;
+
+--echo #
+--echo # Checking XCOL tables
+--echo #
+CREATE TABLE child ENGINE=CONNECT TABLE_TYPE=XCOL TABNAME=chlist OPTION_LIST='colname=children';
+SELECT * FROM child;
+SELECT * FROM child ORDER BY mother;
+SELECT * FROM child ORDER BY children;
+SELECT mother FROM child;
+SELECT mother, COUNT(*) FROM child GROUP BY mother;
+SELECT mother, COUNT(children) FROM child GROUP BY mother;
+
+--echo #
+--echo # Test using special columns
+--echo #
+CREATE TABLE `child2` (
+ `row` int NOT NULL SPECIAL=ROWID,
+ `num` int NOT NULL SPECIAL=ROWNUM,
+ `mother` varchar(12) NOT NULL COMMENT 'The mother of the children',
+ `child` varchar(12) NOT NULL COMMENT 'The child name' FLAG=2
+) ENGINE=CONNECT TABLE_TYPE=XCOL TABNAME=chlist `OPTION_LIST`='colname=child';
+SELECT * FROM child2;
+--echo # List only first child
+SELECT mother, child FROM child2 where num = 1;
+
+DROP TABLE child;
+DROP TABLE chlist;
+DROP TABLE child2;
diff --git a/storage/connect/mysql-test/connect/t/xml_html.test b/storage/connect/mysql-test/connect/t/xml_html.test
new file mode 100644
index 00000000000..1c84b46ec38
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/xml_html.test
@@ -0,0 +1,39 @@
+--source have_libxml2.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+SET NAMES utf8;
+
+--copy_file $MTR_SUITE_DIR/std_data/beers.xml $MYSQLD_DATADIR/test/beers.xml
+--copy_file $MTR_SUITE_DIR/std_data/coffee.htm $MYSQLD_DATADIR/test/coffee.htm
+
+--echo #
+--echo # Testing HTML like XML file
+--echo #
+CREATE TABLE beers (
+`Name` CHAR(16) FIELD_FORMAT='brandName',
+`Origin` CHAR(16) FIELD_FORMAT='origin',
+`Description` CHAR(32) FIELD_FORMAT='details')
+ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='beers.xml'
+TABNAME='table' OPTION_LIST='xmlsup=libxml2,rownode=tr,colnode=td';
+SELECT * FROM beers;
+DROP TABLE beers;
+
+--echo #
+--echo # Testing HTML file
+--echo #
+CREATE TABLE coffee (
+`Name` CHAR(16),
+`Cups` INT(8),
+`Type` CHAR(16),
+`Sugar` CHAR(4))
+ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='coffee.htm'
+TABNAME='TABLE' HEADER=1 OPTION_LIST='xmlsup=libxml2,Coltype=HTML';
+SELECT * FROM coffee;
+DROP TABLE coffee;
+
+#
+# Clean up
+#
+--remove_file $MYSQLD_DATADIR/test/beers.xml
+--remove_file $MYSQLD_DATADIR/test/coffee.htm
diff --git a/storage/connect/mysql-test/connect/t/xml_mdev5261.test b/storage/connect/mysql-test/connect/t/xml_mdev5261.test
index 214900a68d6..b554f251e09 100644
--- a/storage/connect/mysql-test/connect/t/xml_mdev5261.test
+++ b/storage/connect/mysql-test/connect/t/xml_mdev5261.test
@@ -1,27 +1,27 @@
---source have_libxml2.inc
-
-let $MYSQLD_DATADIR= `select @@datadir`;
-
-SET NAMES utf8;
-
-#
-#--echo Testing indexing on not indexable table type
-#
---error ER_UNKNOWN_ERROR
-CREATE TABLE t1 (i INT UNIQUE NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='xt1.xml' OPTION_LIST='Rownode=N';
-CREATE TABLE t1 (i INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='xt1.xml' OPTION_LIST='Rownode=N';
-DESCRIBE t1;
-# one could *add* an index to an existing table
---error ER_UNKNOWN_ERROR
-ALTER TABLE t1 ADD UNIQUE(i);
---error ER_UNKNOWN_ERROR
-CREATE UNIQUE INDEX i ON t1(i);
-DESCRIBE t1;
-INSERT INTO t1 VALUES(2),(5),(7);
-SELECT * FROM t1 WHERE i = 5;
---error ER_CANT_DROP_FIELD_OR_KEY
-ALTER TABLE t1 DROP INDEX i;
---error ER_CANT_DROP_FIELD_OR_KEY
-DROP INDEX i ON t1;
-DROP TABLE t1;
---remove_file $MYSQLD_DATADIR/test/xt1.xml
+--source have_libxml2.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+SET NAMES utf8;
+
+#
+#--echo Testing indexing on not indexable table type
+#
+--error ER_UNKNOWN_ERROR
+CREATE TABLE t1 (i INT UNIQUE NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='xt1.xml' OPTION_LIST='Rownode=N';
+CREATE TABLE t1 (i INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='xt1.xml' OPTION_LIST='Rownode=N';
+DESCRIBE t1;
+# one could *add* an index to an existing table
+--error ER_UNKNOWN_ERROR
+ALTER TABLE t1 ADD UNIQUE(i);
+--error ER_UNKNOWN_ERROR
+CREATE UNIQUE INDEX i ON t1(i);
+DESCRIBE t1;
+INSERT INTO t1 VALUES(2),(5),(7);
+SELECT * FROM t1 WHERE i = 5;
+--error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t1 DROP INDEX i;
+--error ER_CANT_DROP_FIELD_OR_KEY
+DROP INDEX i ON t1;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/xt1.xml
diff --git a/storage/connect/myutil.cpp b/storage/connect/myutil.cpp
index 0d9a1e2fe16..d4416e188c8 100644
--- a/storage/connect/myutil.cpp
+++ b/storage/connect/myutil.cpp
@@ -13,11 +13,11 @@
/************************************************************************/
#include "my_global.h"
#include <mysql.h>
-#if defined(WIN32)
+#if defined(__WIN__)
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#include "osutil.h"
-#endif // !WIN32
+#endif // !__WIN__
#include "global.h"
#include "plgdbsem.h"
@@ -26,14 +26,16 @@
#include "myutil.h"
#define DLL_EXPORT // Items are exported from this DLL
-extern "C" int xconv;
+//extern "C" int xconv;
+TYPCONV GetTypeConv(void);
/************************************************************************/
/* Convert from MySQL type name to PlugDB type number */
/************************************************************************/
int MYSQLtoPLG(char *typname, char *var)
{
- int type;
+ int type;
+ TYPCONV xconv = GetTypeConv();
if (!stricmp(typname, "int") || !stricmp(typname, "mediumint") ||
!stricmp(typname, "integer"))
@@ -57,13 +59,13 @@ int MYSQLtoPLG(char *typname, char *var)
type = TYPE_TINY;
else if (!stricmp(typname, "text") && var) {
switch (xconv) {
- case 1:
+ case TPC_YES:
type = TYPE_STRING;
*var = 'X';
break;
- case 2:
+ case TPC_SKIP:
*var = 'K';
- default:
+ default: // TPC_NO
type = TYPE_ERROR;
} // endswitch xconv
@@ -88,7 +90,7 @@ int MYSQLtoPLG(char *typname, char *var)
} else if (type == TYPE_STRING && !stricmp(typname, "varchar"))
// This is to make the difference between CHAR and VARCHAR
*var = 'V';
- else if (type == TYPE_ERROR && xconv == 2)
+ else if (type == TYPE_ERROR && xconv == TPC_SKIP)
*var = 'K';
else
*var = 0;
@@ -174,7 +176,7 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v)
/************************************************************************/
int MYSQLtoPLG(int mytype, char *var)
{
- int type;
+ int type, xconv = GetTypeConv();
switch (mytype) {
case MYSQL_TYPE_SHORT:
@@ -221,7 +223,7 @@ int MYSQLtoPLG(int mytype, char *var)
case MYSQL_TYPE_LONG_BLOB:
if (var) {
switch (xconv) {
- case 1:
+ case TPC_YES:
if (*var != 'B') {
// This is a TEXT column
type = TYPE_STRING;
@@ -230,9 +232,9 @@ int MYSQLtoPLG(int mytype, char *var)
type = TYPE_ERROR;
break;
- case 2:
+ case TPC_SKIP:
*var = 'K'; // Skip
- default:
+ default: // TPC_NO
type = TYPE_ERROR;
} // endswitch xconv
diff --git a/storage/connect/odbccat.h b/storage/connect/odbccat.h
index 8642d915211..1b5febadd3a 100644
--- a/storage/connect/odbccat.h
+++ b/storage/connect/odbccat.h
@@ -2,6 +2,14 @@
#define DEFAULT_LOGIN_TIMEOUT -1 // means do not set
#define DEFAULT_QUERY_TIMEOUT -1 // means do not set
+typedef struct odbc_parms {
+ char *User; // User connect info
+ char *Pwd; // Password connect info
+ int Cto; // Connect timeout
+ int Qto; // Query timeout
+ bool UseCnc; // Use SQLConnect (!SQLDriverConnect)
+ } ODBCPARM, *POPARM;
+
/***********************************************************************/
/* ODBC catalog function prototypes. */
/***********************************************************************/
@@ -10,8 +18,8 @@ char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop);
#endif // PROMPT_OK
PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info);
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
- char *colpat, int maxres, int cto, int qto, bool info);
-PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, int cto, int qto);
+ char *colpat, int maxres, bool info, POPARM sop);
+PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, POPARM sop);
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
- int maxres, int cto, int qto, bool info);
+ int maxres, bool info, POPARM sop);
PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info);
diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp
index 3e616ec8f04..6aaa048de81 100644
--- a/storage/connect/odbconn.cpp
+++ b/storage/connect/odbconn.cpp
@@ -1,5 +1,5 @@
/************ Odbconn C++ Functions Source Code File (.CPP) ************/
-/* Name: ODBCONN.CPP Version 2.1 */
+/* Name: ODBCONN.CPP Version 2.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
/* */
@@ -11,7 +11,7 @@
/***********************************************************************/
#include <my_global.h>
#include <m_string.h>
-#if defined(WIN32)
+#if defined(__WIN__)
//nclude <io.h>
//nclude <fcntl.h>
#include <direct.h> // for getcwd
@@ -37,21 +37,23 @@
#include "xobject.h"
//#include "kindex.h"
#include "xtable.h"
-#include "tabodbc.h"
#include "odbccat.h"
+#include "tabodbc.h"
#include "plgcnx.h" // For DB types
#include "resource.h"
#include "valblk.h"
#include "osutil.h"
-#if defined(WIN32)
+#if defined(__WIN__)
/***********************************************************************/
/* For dynamic load of ODBC32.DLL */
/***********************************************************************/
#pragma comment(lib, "odbc32.lib")
extern "C" HINSTANCE s_hModule; // Saved module handle
-#endif // WIN32
+#endif // __WIN__
+
+int GetConvSize();
/***********************************************************************/
/* Some macro's (should be defined elsewhere to be more accessible) */
@@ -100,7 +102,12 @@ static int GetSQLCType(int type)
case TYPE_BIGINT: tp = SQL_C_SBIGINT; break;
case TYPE_DOUBLE: tp = SQL_C_DOUBLE; break;
case TYPE_TINY : tp = SQL_C_TINYINT; break;
+//#if (ODBCVER >= 0x0300)
+// case TYPE_DECIM: tp = SQL_C_NUMERIC; break; (CRASH!!!)
+//#else
case TYPE_DECIM: tp = SQL_C_CHAR; break;
+//#endif
+
} // endswitch type
return tp;
@@ -109,20 +116,28 @@ static int GetSQLCType(int type)
/***********************************************************************/
/* TranslateSQLType: translate a SQL Type to a PLG type. */
/***********************************************************************/
-int TranslateSQLType(int stp, int prec, int& len, char& v)
+int TranslateSQLType(int stp, int prec, int& len, char& v, bool& w)
{
int type;
switch (stp) {
+ case SQL_WVARCHAR: // (-9)
+ w = true;
case SQL_VARCHAR: // 12
v = 'V';
+ type = TYPE_STRING;
+ break;
+ case SQL_WCHAR: // (-8)
+ w = true;
case SQL_CHAR: // 1
type = TYPE_STRING;
break;
+ case SQL_WLONGVARCHAR: // (-10)
+ w = true;
case SQL_LONGVARCHAR: // (-1)
v = 'V';
type = TYPE_STRING;
- len = MY_MIN(abs(len), 256);
+ len = MY_MIN(abs(len), GetConvSize());
break;
case SQL_NUMERIC: // 2
case SQL_DECIMAL: // 3
@@ -173,7 +188,6 @@ int TranslateSQLType(int stp, int prec, int& len, char& v)
case SQL_BINARY: // (-2)
case SQL_VARBINARY: // (-3)
case SQL_LONGVARBINARY: // (-4)
-// case SQL_BIT: // (-7)
case SQL_GUID: // (-11)
default:
type = TYPE_ERROR;
@@ -291,7 +305,7 @@ static void ResetNullValues(CATPARM *cap)
/* of an ODBC table that will be retrieved by GetData commands. */
/***********************************************************************/
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
- char *colpat, int maxres, int cto, int qto, bool info)
+ char *colpat, int maxres, bool info, POPARM sop)
{
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT,
@@ -310,10 +324,8 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
/************************************************************************/
if (!info) {
ocp = new(g) ODBConn(g, NULL);
- ocp->SetLoginTimeout((DWORD)cto);
- ocp->SetQueryTimeout((DWORD)qto);
- if (ocp->Open(dsn, 10) < 1) // openReadOnly + noODBCdialog
+ if (ocp->Open(dsn, sop, 10) < 1) // openReadOnly + noODBCdialog
return NULL;
if (table && !strchr(table, '%')) {
@@ -342,7 +354,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
} // endif ocp
if (trace)
- htrc("ODBCColumns: max=%d len=%d,%d,%d\n",
+ htrc("ODBCColumns: max=%d len=%d,%d,%d,%d\n",
maxres, length[0], length[1], length[2], length[3]);
/************************************************************************/
@@ -388,12 +400,13 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
/* ODBCSrcCols: constructs the result blocks containing the */
/* description of all the columns of a Srcdef option. */
/**************************************************************************/
-PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, int cto, int qto)
+PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, POPARM sop)
{
ODBConn *ocp = new(g) ODBConn(g, NULL);
- ocp->SetLoginTimeout((DWORD)cto);
- ocp->SetQueryTimeout((DWORD)qto);
+ if (ocp->Open(dsn, sop, 10) < 1) // openReadOnly + noOdbcDialog
+ return NULL;
+
return ocp->GetMetaData(g, dsn, src);
} // end of ODBCSrcCols
@@ -404,6 +417,7 @@ PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, int cto, int qto)
PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
{
// int i, type, len, prec;
+ bool w = false;
// PCOLRES crp, crpt, crpl, crpp;
PQRYRES qrp;
ODBConn *ocp;
@@ -449,7 +463,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
type = crpt->Kdata->GetIntValue(i);
len = crpl->Kdata->GetIntValue(i);
prec = crpp->Kdata->GetIntValue(i);
- type = TranslateSQLType(type, prec, len);
+ type = TranslateSQLType(type, prec, len, w);
crpt->Kdata->SetValue(type, i);
// Some data sources do not count prec in length
@@ -574,7 +588,7 @@ PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info)
/* an ODBC database that will be retrieved by GetData commands. */
/**************************************************************************/
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
- int maxres, int cto, int qto, bool info)
+ int maxres, bool info, POPARM sop)
{
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_STRING, TYPE_STRING};
@@ -594,10 +608,8 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
/* Open the connection with the ODBC data source. */
/**********************************************************************/
ocp = new(g) ODBConn(g, NULL);
- ocp->SetLoginTimeout((DWORD)cto);
- ocp->SetQueryTimeout((DWORD)qto);
- if (ocp->Open(dsn, 2) < 1) // 2 is openReadOnly
+ if (ocp->Open(dsn, sop, 2) < 1) // 2 is openReadOnly
return NULL;
if (!maxres)
@@ -863,8 +875,7 @@ bool DBX::BuildErrorMessage(ODBConn* pdb, HSTMT hstmt)
for (int i = 0; i < MAX_NUM_OF_MSG
&& (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
&& strcmp((char*)state, "00000"); i++) {
- m_ErrMsg[i] = (PSZ)PlugSubAlloc(g, NULL, strlen((char*)msg) + 1);
- strcpy(m_ErrMsg[i], (char*)msg);
+ m_ErrMsg[i] = (PSZ)PlugDup(g, (char*)msg);
if (trace)
htrc("%s: %s, Native=%d\n", state, msg, native);
@@ -878,8 +889,7 @@ bool DBX::BuildErrorMessage(ODBConn* pdb, HSTMT hstmt)
} else {
snprintf((char*)msg, SQL_MAX_MESSAGE_LENGTH + 1, "%s: %s", m_Msg,
MSG(BAD_HANDLE_VAL));
- m_ErrMsg[0] = (PSZ)PlugSubAlloc(g, NULL, strlen((char*)msg) + 1);
- strcpy(m_ErrMsg[0], (char*)msg);
+ m_ErrMsg[0] = (PSZ)PlugDup(g, (char*)msg);
if (trace)
htrc("%s: rc=%hd\n", SVP(m_ErrMsg[0]), m_RC);
@@ -924,12 +934,15 @@ ODBConn::ODBConn(PGLOBAL g, TDBODBC *tdbp)
m_RowsetSize = (DWORD)((tdbp) ? tdbp->Rows : 10);
m_Catver = (tdbp) ? tdbp->Catver : 0;
m_Rows = 0;
+ m_Fetch = 0;
m_Connect = NULL;
+ m_User = NULL;
+ m_Pwd = NULL;
m_Updatable = true;
m_Transact = false;
m_Scrollable = (tdbp) ? tdbp->Scrollable : false;
- m_First = true;
m_Full = false;
+ m_UseCnc = false;
m_IDQuoteChar[0] = '"';
m_IDQuoteChar[1] = 0;
//*m_ErrMsg = '\0';
@@ -982,7 +995,7 @@ void ODBConn::ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt)
void ODBConn::ThrowDBX(PSZ msg)
{
- DBX* xp = new(m_G) DBX(0, msg);
+ DBX* xp = new(m_G) DBX(0, "Error");
xp->m_ErrMsg[0] = msg;
throw xp;
@@ -1005,8 +1018,7 @@ PSZ ODBConn::GetStringInfo(ushort infotype)
// *buffer = '\0';
} // endif rc
- p = (char *)PlugSubAlloc(m_G, NULL, strlen(buffer) + 1);
- strcpy(p, buffer);
+ p = PlugDup(m_G, buffer);
return p;
} // end of GetStringInfo
@@ -1061,7 +1073,7 @@ void ODBConn::OnSetOptions(HSTMT hstmt)
/***********************************************************************/
/* Open: connect to a data source. */
/***********************************************************************/
-int ODBConn::Open(PSZ ConnectString, DWORD options)
+int ODBConn::Open(PSZ ConnectString, POPARM sop, DWORD options)
{
PGLOBAL& g = m_G;
//ASSERT_VALID(this);
@@ -1070,6 +1082,11 @@ int ODBConn::Open(PSZ ConnectString, DWORD options)
m_Updatable = !(options & openReadOnly);
m_Connect = ConnectString;
+ m_User = sop->User;
+ m_Pwd = sop->Pwd;
+ m_LoginTimeout = sop->Cto;
+ m_QueryTimeout = sop->Qto;
+ m_UseCnc = sop->UseCnc;
// Allocate the HDBC and make connection
try {
@@ -1078,18 +1095,21 @@ int ODBConn::Open(PSZ ConnectString, DWORD options)
AllocConnect(options);
/*ver = GetStringInfo(SQL_ODBC_VER);*/
- if (Connect(options)) {
- strcpy(g->Message, MSG(CONNECT_CANCEL));
- return 0;
- } // endif
+ if (!m_UseCnc) {
+ if (DriverConnect(options)) {
+ strcpy(g->Message, MSG(CONNECT_CANCEL));
+ return 0;
+ } // endif
+
+ } else // Connect using SQLConnect
+ Connect();
/*ver = GetStringInfo(SQL_DRIVER_ODBC_VER);*/
// Verify support for required functionality and cache info
// VerifyConnect(); Deprecated
GetConnectInfo();
} catch(DBX *xp) {
-// strcpy(g->Message, xp->m_ErrMsg[0]);
- strcpy(g->Message, xp->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", xp->m_Msg, xp->GetErrorMessage(0));
Close();
// Free();
return -1;
@@ -1164,23 +1184,40 @@ void ODBConn::AllocConnect(DWORD Options)
} // end of AllocConnect
/***********************************************************************/
+/* Connect to data source using SQLConnect. */
+/***********************************************************************/
+void ODBConn::Connect(void)
+ {
+ SQLRETURN rc;
+ SQLSMALLINT ul = (m_User ? SQL_NTS : 0);
+ SQLSMALLINT pl = (m_Pwd ? SQL_NTS : 0);
+
+ rc = SQLConnect(m_hdbc, (SQLCHAR*)m_Connect, SQL_NTS,
+ (SQLCHAR*)m_User, ul, (SQLCHAR*)m_Pwd, pl);
+
+ if (!Check(rc))
+ ThrowDBX(rc, "SQLConnect");
+
+ } // end of Connect
+
+/***********************************************************************/
/* Connect to data source using SQLDriverConnect. */
/***********************************************************************/
-bool ODBConn::Connect(DWORD Options)
+bool ODBConn::DriverConnect(DWORD Options)
{
RETCODE rc;
SWORD nResult;
PUCHAR ConnOut = (PUCHAR)PlugSubAlloc(m_G, NULL, MAX_CONNECT_LEN);
UWORD wConnectOption = SQL_DRIVER_COMPLETE;
-#if defined(WIN32)
+#if defined(__WIN__)
HWND hWndTop = GetForegroundWindow();
HWND hWnd = GetParent(hWndTop);
if (hWnd == NULL)
hWnd = GetDesktopWindow();
-#else // !WIN32
+#else // !__WIN__
HWND hWnd = (HWND)1;
-#endif // !WIN32
+#endif // !__WIN__
PGLOBAL& g = m_G;
PDBUSER dup = PlgGetUser(g);
@@ -1193,10 +1230,10 @@ bool ODBConn::Connect(DWORD Options)
SQL_NTS, ConnOut, MAX_CONNECT_LEN,
&nResult, wConnectOption);
-#if defined(WIN32)
+#if defined(__WIN__)
if (hWndTop)
EnableWindow(hWndTop, true);
-#endif // WIN32
+#endif // __WIN__
// If user hit 'Cancel'
if (rc == SQL_NO_DATA_FOUND) {
@@ -1213,7 +1250,7 @@ bool ODBConn::Connect(DWORD Options)
// All done
return false;
- } // end of Connect
+ } // end of DriverConnect
void ODBConn::VerifyConnect()
{
@@ -1328,7 +1365,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
rc = SQLFreeStmt(m_hstmt, SQL_CLOSE);
if (!Check(rc))
- ThrowDBX(rc, "SQLFreeStmt");
+ ThrowDBX(rc, "SQLFreeStmt", m_hstmt);
m_hstmt = NULL;
} // endif m_hstmt
@@ -1343,7 +1380,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
(void*)SQL_SCROLLABLE, 0);
if (!Check(rc))
- ThrowDBX(rc, "SQLSetStmtAttr");
+ ThrowDBX(rc, "Scrollable", hstmt);
} // endif m_Scrollable
@@ -1394,7 +1431,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
for (n = 0, colp = tocols; colp; colp = (PODBCCOL)colp->GetNext())
if (!colp->IsSpecial())
- n++;
+ n++;
// n can be 0 for query such as Select count(*) from table
if (n && n != (UWORD)ncol)
@@ -1430,7 +1467,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
if (b)
SQLCancel(hstmt);
@@ -1493,7 +1530,7 @@ int ODBConn::GetResultSize(char *sql, ODBCCOL *colp)
/***********************************************************************/
/* Fetch next row. */
/***********************************************************************/
-int ODBConn::Fetch()
+int ODBConn::Fetch(int pos)
{
ASSERT(m_hstmt);
int irc;
@@ -1503,7 +1540,9 @@ int ODBConn::Fetch()
try {
// do {
- if (m_RowsetSize) {
+ if (pos) {
+ rc = SQLExtendedFetch(m_hstmt, SQL_FETCH_ABSOLUTE, pos, &crow, NULL);
+ } else if (m_RowsetSize) {
rc = SQLExtendedFetch(m_hstmt, SQL_FETCH_NEXT, 1, &crow, NULL);
} else {
rc = SQLFetch(m_hstmt);
@@ -1516,29 +1555,22 @@ int ODBConn::Fetch()
m_hstmt, m_RowsetSize, rc);
if (!Check(rc))
- ThrowDBX(rc, "Fetch", m_hstmt);
-
- irc = (rc == SQL_NO_DATA_FOUND) ? 0 : (int)crow;
-
- if (m_First) {
- // First fetch. Check whether the full table was read
- if ((m_Full = irc < (signed)m_RowsetSize)) {
- m_Tdb->Memory = 0; // Not needed anymore
- m_Rows = irc; // Table size
- } // endif m_Full
-
- m_First = false;
- } // endif m_First
+ ThrowDBX(rc, "Fetching", m_hstmt);
- if (m_Tdb->Memory == 1)
- m_Rows += irc;
+ if (rc == SQL_NO_DATA_FOUND) {
+ m_Full = (m_Fetch == 1);
+ irc = 0;
+ } else
+ irc = (int)crow;
+ m_Fetch++;
+ m_Rows += irc;
} catch(DBX *x) {
if (trace)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
irc = -1;
} // end try/catch
@@ -1574,7 +1606,7 @@ int ODBConn::PrepareSQL(char *sql)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
} // end try/catch
} // endif Mode
@@ -1620,7 +1652,7 @@ int ODBConn::PrepareSQL(char *sql)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
if (b)
SQLCancel(hstmt);
@@ -1672,7 +1704,7 @@ int ODBConn::ExecuteSQL(void)
} // endif ncol
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
SQLCancel(m_hstmt);
rc = SQLFreeStmt(m_hstmt, SQL_DROP);
m_hstmt = NULL;
@@ -1709,9 +1741,11 @@ bool ODBConn::BindParam(ODBCCOL *colp)
ThrowDBX(rc, "SQLDescribeParam", m_hstmt);
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
colsize = colp->GetPrecision();
sqlt = GetSQLType(buftype);
+ dec = IsTypeChar(buftype) ? 0 : colp->GetScale();
+ nul = SQL_NULLABLE_UNKNOWN;
} // end try/catch
buf = colp->GetBuffer(0);
@@ -1815,7 +1849,7 @@ bool ODBConn::ExecSQLcommand(char *sql)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- sprintf(g->Message, "Remote: %s", x->GetErrorMessage(0));
+ sprintf(g->Message, "Remote %s: %s", x->m_Msg, x->GetErrorMessage(0));
if (b)
SQLCancel(hstmt);
@@ -1865,9 +1899,6 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
RETCODE rc;
HSTMT hstmt;
- if (Open(dsn, 10) < 1) // openReadOnly + noOdbcDialog
- return NULL;
-
try {
rc = SQLAllocStmt(m_hdbc, &hstmt);
@@ -1903,7 +1934,7 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
} // endfor i
} catch(DBX *x) {
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
goto err;
} // end try/catch
@@ -1954,7 +1985,7 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
} // endfor i
} catch(DBX *x) {
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
qrp = NULL;
} // end try/catch
@@ -2006,7 +2037,7 @@ bool ODBConn::GetDataSources(PQRYRES qrp)
} // endfor i
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
rv = true;
} // end try/catch
@@ -2057,7 +2088,7 @@ bool ODBConn::GetDrivers(PQRYRES qrp)
} // endfor n
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
rv = true;
} // end try/catch
@@ -2375,7 +2406,7 @@ int ODBConn::GetCatInfo(CATPARM *cap)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
irc = -1;
} // end try/catch
@@ -2479,7 +2510,7 @@ int ODBConn::Rewind(char *sql, ODBCCOL *tocols)
rbuf = (int)crow;
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
rbuf = -1;
} // end try/catch
diff --git a/storage/connect/odbconn.h b/storage/connect/odbconn.h
index dfdb9fe7f56..6a24334f08c 100644
--- a/storage/connect/odbconn.h
+++ b/storage/connect/odbconn.h
@@ -29,9 +29,9 @@
//efine MAX_CURSOR_NAME 18 // Max size of a cursor name
#define DEFAULT_FIELD_TYPE SQL_TYPE_NULL // pick "C" data type to match SQL data type
-#if !defined(WIN32)
+#if !defined(__WIN__)
typedef unsigned char *PUCHAR;
-#endif // !WIN32
+#endif // !__WIN__
// Field Flags, used to indicate status of fields
//efine SQL_FIELD_FLAG_DIRTY 0x1
@@ -119,7 +119,7 @@ class ODBConn : public BLOCK {
noOdbcDialog = 0x0008, // Don't display ODBC Connect dialog
forceOdbcDialog = 0x0010}; // Always display ODBC connect dialog
- int Open(PSZ ConnectString, DWORD Options = 0);
+ int Open(PSZ ConnectString, POPARM sop, DWORD Options = 0);
int Rewind(char *sql, ODBCCOL *tocols);
void Close(void);
PQRYRES AllocateResult(PGLOBAL g);
@@ -135,11 +135,13 @@ class ODBConn : public BLOCK {
public:
// Operations
- void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
- void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
+//void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
+//void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
+//void SetUserName(PSZ user) {m_User = user;}
+//void SetUserPwd(PSZ pwd) {m_Pwd = pwd;}
int GetResultSize(char *sql, ODBCCOL *colp);
int ExecDirectSQL(char *sql, ODBCCOL *tocols);
- int Fetch(void);
+ int Fetch(int pos = 0);
int PrepareSQL(char *sql);
int ExecuteSQL(void);
bool BindParam(ODBCCOL *colp);
@@ -155,7 +157,7 @@ class ODBConn : public BLOCK {
// Implementation
public:
-// virtual ~ODBConn();
+//virtual ~ODBConn();
// ODBC operations
protected:
@@ -163,7 +165,8 @@ class ODBConn : public BLOCK {
void ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt = SQL_NULL_HSTMT);
void ThrowDBX(PSZ msg);
void AllocConnect(DWORD dwOptions);
- bool Connect(DWORD Options);
+ void Connect(void);
+ bool DriverConnect(DWORD Options);
void VerifyConnect(void);
void GetConnectInfo(void);
void Free(void);
@@ -185,11 +188,14 @@ class ODBConn : public BLOCK {
DWORD m_RowsetSize;
char m_IDQuoteChar[2];
PSZ m_Connect;
+ PSZ m_User;
+ PSZ m_Pwd;
int m_Catver;
int m_Rows;
+ int m_Fetch;
bool m_Updatable;
bool m_Transact;
bool m_Scrollable;
- bool m_First;
+ bool m_UseCnc;
bool m_Full;
}; // end of ODBConn class definition
diff --git a/storage/connect/os.h b/storage/connect/os.h
index 8f77a0ad39f..2dc603fdcda 100644
--- a/storage/connect/os.h
+++ b/storage/connect/os.h
@@ -15,16 +15,16 @@ typedef off_t off64_t;
#endif
#endif
-#if defined(WIN32)
+#if defined(__WIN__)
typedef __int64 BIGINT;
-#else // !WIN32
+#else // !__WIN__
typedef longlong BIGINT;
#define FILE_BEGIN SEEK_SET
#define FILE_CURRENT SEEK_CUR
#define FILE_END SEEK_END
-#endif // !WIN32
+#endif // !__WIN__
-#if !defined(WIN32)
+#if !defined(__WIN__)
typedef const void *LPCVOID;
typedef const char *LPCTSTR;
typedef const char *LPCSTR;
@@ -61,6 +61,6 @@ typedef int HANDLE;
#define _MAX_EXT FN_EXTLEN
#define INVALID_HANDLE_VALUE (-1)
#define __stdcall
-#endif /* !WIN32 */
+#endif /* !__WIN__ */
#endif /* _OS_H_INCLUDED */
diff --git a/storage/connect/osutil.c b/storage/connect/osutil.c
index 66985847ce7..2e9e120b0c8 100644
--- a/storage/connect/osutil.c
+++ b/storage/connect/osutil.c
@@ -4,7 +4,7 @@
#include <stdio.h>
#include "osutil.h"
-#ifdef WIN32
+#ifdef __WIN__
my_bool CloseFileHandle(HANDLE h)
{
return !CloseHandle(h);
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h
index e61a49ba9f9..b57d9e20ceb 100644
--- a/storage/connect/plgdbsem.h
+++ b/storage/connect/plgdbsem.h
@@ -1,7 +1,7 @@
/************** PlgDBSem H Declares Source Code File (.H) **************/
/* Name: PLGDBSEM.H Version 3.6 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
/* */
/* This file contains the PlugDB++ application type definitions. */
/***********************************************************************/
@@ -389,6 +389,7 @@ typedef struct _qryres *PQRYRES;
typedef struct _colres *PCOLRES;
typedef struct _datpar *PDTP;
typedef struct indx_used *PXUSED;
+typedef struct ha_table_option_struct TOS, *PTOS;
/***********************************************************************/
/* Utility blocks for file and storage. */
@@ -504,9 +505,10 @@ enum XFLD {FLD_NO = 0, /* Not a field definition item */
FLD_EXTRA = 13, /* Field extra info */
FLD_PRIV = 14, /* Field priviledges */
FLD_DATEFMT = 15, /* Field date format */
- FLD_CAT = 16, /* Table catalog */
- FLD_SCHEM = 17, /* Table schema */
- FLD_TABNAME = 18}; /* Column Table name */
+ FLD_FORMAT = 16, /* Field format */
+ FLD_CAT = 17, /* Table catalog */
+ FLD_SCHEM = 18, /* Table schema */
+ FLD_TABNAME = 19}; /* Column Table name */
/***********************************************************************/
/* Result of last SQL noconv query. */
@@ -542,11 +544,11 @@ typedef struct _colres {
char Var; /* Type added information */
} COLRES;
-#if defined(WIN32) && !defined(NOEX)
+#if defined(__WIN__) && !defined(NOEX)
#define DllExport __declspec( dllexport )
-#else // !WIN32
+#else // !__WIN__
#define DllExport
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Utility routines. */
@@ -584,6 +586,7 @@ DllExport PCATLG PlgGetCatalog(PGLOBAL g, bool jump = true);
DllExport bool PlgSetXdbPath(PGLOBAL g, PSZ, PSZ, char *, int, char *, int);
DllExport void PlgDBfree(MBLOCK&);
DllExport void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size);
+DllExport char *PlgDBDup(PGLOBAL g, const char *str);
DllExport void *PlgDBalloc(PGLOBAL, void *, MBLOCK&);
DllExport void *PlgDBrealloc(PGLOBAL, void *, MBLOCK&, size_t);
DllExport void NewPointer(PTABS, void *, void *);
@@ -591,6 +594,9 @@ DllExport void NewPointer(PTABS, void *, void *);
DllExport void SetTrc(void);
DllExport char *GetListOption(PGLOBAL, const char *, const char *,
const char *def=NULL);
+DllExport char *GetStringTableOption(PGLOBAL, PTOS, char *, char *);
+DllExport bool GetBooleanTableOption(PGLOBAL, PTOS, char *, bool);
+DllExport int GetIntegerTableOption(PGLOBAL, PTOS, char *, int);
#define MSGID_NONE 0
#define MSGID_CANNOT_OPEN 1
diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp
index d8009bcc71f..9e236da2d93 100644
--- a/storage/connect/plgdbutl.cpp
+++ b/storage/connect/plgdbutl.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -38,12 +38,12 @@
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <fcntl.h>
#include <errno.h>
#define BIGMEM 1048576 // 1 Megabyte
-#else // !WIN32
+#else // !__WIN__
#include <unistd.h>
#include <fcntl.h>
#if defined(THREAD)
@@ -51,7 +51,7 @@
#endif // THREAD
#include <stdarg.h>
#define BIGMEM 2147483647 // Max int value
-#endif // !WIN32
+#endif // !__WIN__
#include <locale.h>
/***********************************************************************/
@@ -73,11 +73,11 @@
/* Macro or external routine definition */
/***********************************************************************/
#if defined(THREAD)
-#if defined(WIN32)
+#if defined(__WIN__)
extern CRITICAL_SECTION parsec; // Used calling the Flex parser
-#else // !WIN32
+#else // !__WIN__
extern pthread_mutex_t parmut;
-#endif // !WIN32
+#endif // !__WIN__
#endif // THREAD
/***********************************************************************/
@@ -294,8 +294,7 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
#else // !XMSG
GetRcString(ids + crp->Ncol, cname, sizeof(cname));
#endif // !XMSG
- crp->Name = (PSZ)PlugSubAlloc(g, NULL, strlen(cname) + 1);
- strcpy(crp->Name, cname);
+ crp->Name = (PSZ)PlugDup(g, cname);
} else
crp->Name = NULL; // Will be set by caller
@@ -311,7 +310,7 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
else
crp->Kdata = NULL;
- if (g->Trace)
+ if (trace)
htrc("Column(%d) %s type=%d len=%d value=%p\n",
crp->Ncol, crp->Name, crp->Type, crp->Length, crp->Kdata);
@@ -404,11 +403,11 @@ char *SetPath(PGLOBAL g, const char *path)
} // endif path
if (*path != '.') {
-#if defined(WIN32)
+#if defined(__WIN__)
char *s= "\\";
-#else // !WIN32
+#else // !__WIN__
char *s= "/";
-#endif // !WIN32
+#endif // !__WIN__
strcat(strcat(strcat(strcpy(buf, "."), s), path), s);
} else
strcpy(buf, path);
@@ -427,7 +426,7 @@ char *ExtractFromPath(PGLOBAL g, char *pBuff, char *FileName, OPVAL op)
char *drive = NULL, *direc = NULL, *fname = NULL, *ftype = NULL;
switch (op) { // Determine which part to extract
-#if !defined(UNIX)
+#if defined(__WIN__)
case OP_FDISK: drive = pBuff; break;
#endif // !UNIX
case OP_FPATH: direc = pBuff; break;
@@ -703,19 +702,19 @@ PDTP MakeDateFormat(PGLOBAL g, PSZ dfmt, bool in, bool out, int flag)
/* instruction is included in an Enter/LeaveCriticalSection bracket. */
/*********************************************************************/
#if defined(THREAD)
-#if defined(WIN32)
+#if defined(__WIN__)
EnterCriticalSection((LPCRITICAL_SECTION)&parsec);
-#else // !WIN32
+#else // !__WIN__
pthread_mutex_lock(&parmut);
-#endif // !WIN32
+#endif // !__WIN__
#endif // THREAD
/*int rc =*/ fmdflex(pdp);
#if defined(THREAD)
-#if defined(WIN32)
+#if defined(__WIN__)
LeaveCriticalSection((LPCRITICAL_SECTION)&parsec);
-#else // !WIN32
+#else // !__WIN__
pthread_mutex_unlock(&parmut);
-#endif // !WIN32
+#endif // !__WIN__
#endif // THREAD
if (trace)
@@ -853,8 +852,7 @@ FILE *PlugOpenFile(PGLOBAL g, LPCSTR fname, LPCSTR ftype)
htrc(" fp=%p\n", fp);
// fname may be in volatile memory such as stack
- fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(fname) + 1);
- strcpy((char*)fp->Fname, fname);
+ fp->Fname = PlugDup(g, fname);
fp->Count = 1;
fp->Type = TYPE_FB_FILE;
fp->File = fop;
@@ -890,7 +888,7 @@ FILE *PlugReopenFile(PGLOBAL g, PFBLOCK fp, LPCSTR md)
/* Close file routine: the purpose of this routine is to avoid */
/* double closing that freeze the system on some Unix platforms. */
/***********************************************************************/
-int PlugCloseFile(PGLOBAL g, PFBLOCK fp, bool all)
+int PlugCloseFile(PGLOBAL g __attribute__((unused)), PFBLOCK fp, bool all)
{
int rc = 0;
@@ -1111,7 +1109,7 @@ char *GetAmName(PGLOBAL g, AMT am, void *memp)
return amn;
} // end of GetAmName
-#if defined(WIN32) && !defined(NOCATCH)
+#if defined(__WIN__) && !defined(NOCATCH)
/***********************************************************************/
/* GetExceptionDesc: return the description of an exception code. */
/***********************************************************************/
@@ -1199,7 +1197,7 @@ char *GetExceptionDesc(PGLOBAL g, unsigned int e)
return p;
} // end of GetExceptionDesc
-#endif // WIN32 && !NOCATCH
+#endif // __WIN__ && !NOCATCH
/***********************************************************************/
/* PlgDBalloc: allocates or suballocates memory conditionally. */
@@ -1241,7 +1239,7 @@ void *PlgDBalloc(PGLOBAL g, void *area, MBLOCK& mp)
if (!mp.Sub) {
// For allocations greater than one fourth of remaining storage
// in the area, do allocate from virtual storage.
-#if defined(WIN32)
+#if defined(__WIN__)
if (mp.Size >= BIGMEM)
mp.Memp = VirtualAlloc(NULL, mp.Size, MEM_COMMIT, PAGE_READWRITE);
else
@@ -1338,7 +1336,7 @@ void PlgDBfree(MBLOCK& mp)
htrc("PlgDBfree: %p sub=%d size=%d\n", mp.Memp, mp.Sub, mp.Size);
if (!mp.Sub && mp.Memp)
-#if defined(WIN32)
+#if defined(__WIN__)
if (mp.Size >= BIGMEM)
VirtualFree(mp.Memp, 0, MEM_RELEASE);
else
@@ -1401,6 +1399,23 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size)
} // end of PlgDBSubAlloc
/***********************************************************************/
+/* Program for sub-allocating and copying a string in a storage area. */
+/***********************************************************************/
+char *PlgDBDup(PGLOBAL g, const char *str)
+ {
+ if (str) {
+ char *sm = (char*)PlgDBSubAlloc(g, NULL, strlen(str) + 1);
+
+ if (sm)
+ strcpy(sm, str);
+
+ return sm;
+ } else
+ return NULL;
+
+ } // end of PlgDBDup
+
+/***********************************************************************/
/* PUTOUT: Plug DB object typing routine. */
/***********************************************************************/
void PlugPutOut(PGLOBAL g, FILE *f, short t, void *v, uint n)
@@ -1517,11 +1532,11 @@ int FileComp(PGLOBAL g, char *file1, char *file2)
bp[0] = buff1; bp[1] = buff2;
for (i = 0; i < 2; i++) {
-#if defined(WIN32)
+#if defined(__WIN__)
h[i]= global_open(g, MSGID_NONE, fn[i], _O_RDONLY | _O_BINARY);
-#else // !WIN32
+#else // !__WIN__
h[i]= global_open(g, MSGOD_NONE, fn[i], O_RDONLY);
-#endif // !WIN32
+#endif // !__WIN__
if (h[i] == -1) {
// if (errno != ENOENT) {
diff --git a/storage/connect/plgxml.h b/storage/connect/plgxml.h
index 74a16fd4823..b8e914e0bf1 100644
--- a/storage/connect/plgxml.h
+++ b/storage/connect/plgxml.h
@@ -1,5 +1,5 @@
/******************************************************************/
-/* Dual XML implementation base classes defines. */
+/* Dual XML implementation base classes defines. */
/******************************************************************/
#if !defined(BASE_BUFFER_SIZE)
enum ElementType { // libxml2
@@ -43,7 +43,7 @@ enum NodeType { // MS DOM
NODE_NOTATION = 12};
#endif // !NODE_TYPE_LIST
-typedef class XMLDOCUMENT *PXDOC; // Document
+typedef class XMLDOCUMENT *PXDOC; // Document
typedef class XMLNODE *PXNODE; // Node (Element)
typedef class XMLNODELIST *PXLIST; // Node list
typedef class XMLATTRIBUTE *PXATTR; // Attribute
@@ -93,9 +93,9 @@ class XMLDOCUMENT : public BLOCK {
bool MakeNSlist(PGLOBAL g);
// Members
- PNS Namespaces; /* To the namespaces */
+ PNS Namespaces; /* To the namespaces */
char *Encoding; /* The document encoding */
- char *Nslist; /* Namespace list */
+ char *Nslist; /* Namespace list */
char *DefNs; /* Default namespace */
}; // end of class XMLDOCUMENT
@@ -109,6 +109,7 @@ class XMLNODE : public BLOCK {
virtual int GetType(void) = 0;
virtual PXNODE GetNext(PGLOBAL) = 0;
virtual PXNODE GetChild(PGLOBAL) = 0;
+ virtual int GetLen(void) {return Len;}
// Methods
virtual RCODE GetContent(PGLOBAL, char *, int) = 0;
@@ -163,10 +164,12 @@ class XMLNODELIST : public BLOCK {
class XMLATTRIBUTE : public BLOCK {
public:
// Properties
-//virtual char *GetText(void) = 0;
+ virtual char *GetName(PGLOBAL) = 0;
+ virtual PXATTR GetNext(PGLOBAL) = 0;
// Methods
- virtual bool SetText(PGLOBAL, char *, int) = 0;
+ virtual RCODE GetText(PGLOBAL, char *, int) = 0;
+ virtual bool SetText(PGLOBAL, char *, int) = 0;
protected:
// Constructor
diff --git a/storage/connect/plugutil.c b/storage/connect/plugutil.c
index c77975e5e30..c0e249adf12 100644
--- a/storage/connect/plugutil.c
+++ b/storage/connect/plugutil.c
@@ -6,7 +6,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1993-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 1993-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -44,7 +44,7 @@
/* */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
//#include <windows.h>
#else
#if defined(UNIX) || defined(UNIV_LINUX)
@@ -80,9 +80,9 @@
#include "rcmsg.h"
#endif // NEWMSG
-#if defined(WIN32)
+#if defined(__WIN__)
extern HINSTANCE s_hModule; /* Saved module handle */
-#endif // WIN32
+#endif // __WIN__
#if defined(XMSG)
extern char *msg_path;
@@ -144,12 +144,12 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
return NULL;
} else {
g->Sarea_Size = worksize;
- g->Trace = 0;
g->Createas = 0;
g->Alchecked = 0;
g->Mrr = 0;
g->Activityp = g->ActivityStart = NULL;
g->Xchk = NULL;
+ g->N = 0;
strcpy(g->Message, "");
/*******************************************************************/
@@ -192,7 +192,7 @@ int PlugExit(PGLOBAL g)
/***********************************************************************/
LPSTR PlugRemoveType(LPSTR pBuff, LPCSTR FileName)
{
-#if !defined(UNIX) && !defined(UNIV_LINUX)
+#if defined(__WIN__)
char drive[_MAX_DRIVE];
#else
char *drive = NULL;
@@ -220,7 +220,7 @@ LPSTR PlugRemoveType(LPSTR pBuff, LPCSTR FileName)
BOOL PlugIsAbsolutePath(LPCSTR path)
{
-#if defined(WIN32)
+#if defined(__WIN__)
return ((path[0] >= 'a' && path[0] <= 'z') ||
(path[0] >= 'A' && path[0] <= 'Z')) && path[1] == ':';
#else
@@ -228,7 +228,6 @@ BOOL PlugIsAbsolutePath(LPCSTR path)
#endif
}
-
/***********************************************************************/
/* Set the full path of a file relatively to a given path. */
/* Note: this routine is not really implemented for Unix. */
@@ -239,7 +238,7 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
char direc[_MAX_DIR], defdir[_MAX_DIR], tmpdir[_MAX_DIR];
char fname[_MAX_FNAME];
char ftype[_MAX_EXT];
-#if !defined(UNIX) && !defined(UNIV_LINUX)
+#if defined(__WIN__)
char drive[_MAX_DRIVE], defdrv[_MAX_DRIVE];
#else
char *drive = NULL, *defdrv = NULL;
@@ -256,7 +255,7 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
return pBuff;
} // endif
-#if !defined(WIN32)
+#if !defined(__WIN__)
if (*FileName == '~') {
if (_fullpath(pBuff, FileName, _MAX_PATH)) {
if (trace > 1)
@@ -267,7 +266,7 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
return FileName; // Error, return unchanged name
} // endif FileName
-#endif // !WIN32
+#endif // !__WIN__
if (prefix && strcmp(prefix, ".") && !PlugIsAbsolutePath(defpath))
{
@@ -296,11 +295,11 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
if (trace > 1) {
htrc("after _splitpath: FileName=%s\n", FileName);
-#if defined(UNIX) || defined(UNIV_LINUX)
- htrc("dir=%s fname=%s ext=%s\n", direc, fname, ftype);
-#else
+#if defined(__WIN__)
htrc("drive=%s dir=%s fname=%s ext=%s\n", drive, direc, fname, ftype);
htrc("defdrv=%s defdir=%s\n", defdrv, defdir);
+#else
+ htrc("dir=%s fname=%s ext=%s\n", direc, fname, ftype);
#endif
} // endif trace
@@ -385,8 +384,7 @@ char *PlugReadMessage(PGLOBAL g, int mid, char *m)
err:
if (g) {
// Called by STEP
- msg = (char *)PlugSubAlloc(g, NULL, strlen(stmsg) + 1);
- strcpy(msg, stmsg);
+ msg = PlugDup(g, stmsg);
} else // Called by MSG or PlgGetErrorMsg
msg = stmsg;
@@ -421,8 +419,7 @@ char *PlugGetMessage(PGLOBAL g, int mid)
if (g) {
// Called by STEP
- msg = (char *)PlugSubAlloc(g, NULL, strlen(stmsg) + 1);
- strcpy(msg, stmsg);
+ msg = PlugDup(g, stmsg);
} else // Called by MSG or PlgGetErrorMsg
msg = stmsg;
@@ -430,7 +427,7 @@ char *PlugGetMessage(PGLOBAL g, int mid)
} // end of PlugGetMessage
#endif // NEWMSG
-#if defined(WIN32)
+#if defined(__WIN__)
/***********************************************************************/
/* Return the line length of the console screen buffer. */
/***********************************************************************/
@@ -442,7 +439,7 @@ short GetLineLength(PGLOBAL g)
return (b) ? coninfo.dwSize.X : 0;
} // end of GetLineLength
-#endif // WIN32
+#endif // __WIN__
/***********************************************************************/
/* Program for memory allocation of work and language areas. */
@@ -505,7 +502,7 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
size = ((size + 7) / 8) * 8; /* Round up size to multiple of 8 */
pph = (PPOOLHEADER)memp;
- if (trace > 2)
+ if (trace > 3)
htrc("SubAlloc in %p size=%d used=%d free=%d\n",
memp, size, pph->To_Free, pph->FreeBlk);
@@ -529,7 +526,7 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
pph->To_Free += size; /* New offset of pool free block */
pph->FreeBlk -= size; /* New size of pool free block */
- if (trace > 2)
+ if (trace > 3)
htrc("Done memp=%p used=%d free=%d\n",
memp, pph->To_Free, pph->FreeBlk);
@@ -537,6 +534,22 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
} /* end of PlugSubAlloc */
/***********************************************************************/
+/* Program for sub-allocating and copying a string in a storage area. */
+/***********************************************************************/
+char *PlugDup(PGLOBAL g, const char *str)
+ {
+ if (str) {
+ char *sm = (char*)PlugSubAlloc(g, NULL, strlen(str) + 1);
+
+ strcpy(sm, str);
+ return sm;
+ } else
+ return NULL;
+
+ } // end of PlugDup
+
+#if 0
+/***********************************************************************/
/* This routine suballocate a copy of the passed string. */
/***********************************************************************/
char *PlugDup(PGLOBAL g, const char *str)
@@ -552,6 +565,7 @@ char *PlugDup(PGLOBAL g, const char *str)
return(buf);
} /* end of PlugDup */
+#endif // 0
/***********************************************************************/
/* This routine makes a pointer from an offset to a memory pointer. */
diff --git a/storage/connect/rcmsg.c b/storage/connect/rcmsg.c
index 9eea944c697..75759e03314 100644
--- a/storage/connect/rcmsg.c
+++ b/storage/connect/rcmsg.c
@@ -1,68 +1,68 @@
-/**************** RCMsg C Program Source Code File (.C) ****************/
-/* PROGRAM NAME: RCMSG */
-/* ------------- */
-/* Version 1.3 */
-/* */
-/* COPYRIGHT */
-/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND: 2005 - 2014 */
-/* */
-/* WHAT THIS PROGRAM DOES */
-/* ----------------------- */
-/* This program simulates LoadString. */
-/* */
-/***********************************************************************/
-#if !defined(XMSG)
-#include <stdio.h>
-#include <string.h>
-#include "resource.h"
-#include "rcmsg.h"
-#if defined(NEWMSG)
-#include "msgid.h"
-#endif // NEWMSG
-
-#if !defined(WIN32)
-#define stricmp strcasecmp
-#endif // !WIN32
-
-char *msglang(void);
-
-char *GetMsgid(int id)
- {
- char *p = NULL;
-
- // This conditional until a real fix is found for MDEV-7304
-#if defined(FRENCH)
- if (!stricmp(msglang(), "french"))
- switch (id) {
-#include "frids.h"
-#if defined(NEWMSG)
-#include "frcas.h"
-#endif // NEWMSG
- } // endswitch(id)
-
- else // English
-#endif // FRENCH
- switch (id) {
-#include "enids.h"
-#if defined(NEWMSG)
-#include "encas.h"
-#endif // NEWMSG
- } // endswitch(id)
-
- return p;
- } // end of GetMsgid
-
-int GetRcString(int id, char *buf, int bufsize)
- {
- char *p = NULL, msg[32];
-
- if (!(p = GetMsgid(id))) {
- sprintf(msg, "ID=%d unknown", id);
- p = msg;
- } // endif p
-
- return sprintf(buf, "%.*s", bufsize-1, p);
- } // end of GetRcString
-
-#endif // !XMSG
+/**************** RCMsg C Program Source Code File (.C) ****************/
+/* PROGRAM NAME: RCMSG */
+/* ------------- */
+/* Version 1.3 */
+/* */
+/* COPYRIGHT */
+/* ---------- */
+/* (C) Copyright to the author Olivier BERTRAND: 2005 - 2014 */
+/* */
+/* WHAT THIS PROGRAM DOES */
+/* ----------------------- */
+/* This program simulates LoadString. */
+/* */
+/***********************************************************************/
+#if !defined(XMSG)
+#include <stdio.h>
+#include <string.h>
+#include "resource.h"
+#include "rcmsg.h"
+#if defined(NEWMSG)
+#include "msgid.h"
+#endif // NEWMSG
+
+#if !defined(__WIN__)
+#define stricmp strcasecmp
+#endif // !__WIN__
+
+char *msglang(void);
+
+char *GetMsgid(int id)
+ {
+ char *p = NULL;
+
+ // This conditional until a real fix is found for MDEV-7304
+#if defined(FRENCH)
+ if (!stricmp(msglang(), "french"))
+ switch (id) {
+#include "frids.h"
+#if defined(NEWMSG)
+#include "frcas.h"
+#endif // NEWMSG
+ } // endswitch(id)
+
+ else // English
+#endif // FRENCH
+ switch (id) {
+#include "enids.h"
+#if defined(NEWMSG)
+#include "encas.h"
+#endif // NEWMSG
+ } // endswitch(id)
+
+ return p;
+ } // end of GetMsgid
+
+int GetRcString(int id, char *buf, int bufsize)
+ {
+ char *p = NULL, msg[32];
+
+ if (!(p = GetMsgid(id))) {
+ sprintf(msg, "ID=%d unknown", id);
+ p = msg;
+ } // endif p
+
+ return sprintf(buf, "%.*s", bufsize-1, p);
+ } // end of GetRcString
+
+#endif // !XMSG
diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp
index 51d777a7d17..60d515a61ca 100644
--- a/storage/connect/reldef.cpp
+++ b/storage/connect/reldef.cpp
@@ -1,11 +1,11 @@
/************* RelDef CPP Program Source Code File (.CPP) **************/
-/* PROGRAM NAME: REFDEF */
+/* PROGRAM NAME: RELDEF */
/* ------------- */
/* Version 1.4 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2004-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2004-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -17,7 +17,7 @@
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <sqlext.h>
#else
#include <dlfcn.h> // dlopen(), dlclose(), dlsym() ...
@@ -35,7 +35,6 @@
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
-#include "mycat.h"
#include "reldef.h"
#include "colblk.h"
#include "filamap.h"
@@ -49,14 +48,15 @@
#include "tabmul.h"
#include "ha_connect.h"
-#if !defined(WIN32)
+#if !defined(__WIN__)
extern handlerton *connect_hton;
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* External function. */
/***********************************************************************/
USETEMP UseTemp(void);
+char *GetPluginDir(void);
/* --------------------------- Class RELDEF -------------------------- */
@@ -74,6 +74,14 @@ RELDEF::RELDEF(void)
} // end of RELDEF constructor
/***********************************************************************/
+/* This function return a pointer to the Table Option Struct. */
+/***********************************************************************/
+PTOS RELDEF::GetTopt(void)
+ {
+ return Hc->GetTableOptionStruct();
+ } // end of GetTopt
+
+/***********************************************************************/
/* This function sets an integer table information. */
/***********************************************************************/
bool RELDEF::SetIntCatInfo(PSZ what, int n)
@@ -153,10 +161,9 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef)
if (s) {
if (!Hc->IsPartitioned() ||
(stricmp(what, "filename") && stricmp(what, "tabname")
- && stricmp(what, "connect"))) {
- sval= (char*)PlugSubAlloc(g, NULL, strlen(s) + 1);
- strcpy(sval, s);
- } else
+ && stricmp(what, "connect")))
+ sval= PlugDup(g, s);
+ else
sval= s;
} else if (!stricmp(what, "filename")) {
@@ -213,8 +220,7 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am)
{
int poff = 0;
- Name = (PSZ)PlugSubAlloc(g, NULL, strlen(name) + 1);
- strcpy(Name, name);
+ Name = (PSZ)PlugDup(g, name);
Cat = cat;
Hc = ((MYCAT*)cat)->GetHandler();
Catfunc = GetFuncID(GetStringCatInfo(g, "Catfunc", NULL));
@@ -241,7 +247,7 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am)
/***********************************************************************/
PSZ TABDEF::GetPath(void)
{
- return (Database) ? (PSZ)Database : Hc->GetDataPath();
+ return (Database) ? (PSZ)Database : (Hc) ? Hc->GetDataPath() : NULL;
} // end of GetPath
/***********************************************************************/
@@ -250,7 +256,8 @@ PSZ TABDEF::GetPath(void)
int TABDEF::GetColCatInfo(PGLOBAL g)
{
char *type= GetStringCatInfo(g, "Type", "*");
- int i, loff, poff, nof, nlg;
+ char c, fty, eds;
+ int i, n, loff, poff, nof, nlg;
void *field= NULL;
TABTYPE tc;
PCOLDEF cdp, lcdp= NULL, tocols= NULL;
@@ -317,7 +324,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
if ((nof= cdp->Define(g, NULL, pcf, poff)) < 0)
return -1; // Error, probably unhandled type
- else if (nof)
+ else
loff= cdp->GetOffset();
switch (tc) {
@@ -325,20 +332,52 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
cdp->SetOffset(0); // Not to have shift
case TAB_BIN:
// BIN/VEC are packed by default
- if (nof)
+ if (nof) {
// Field width is the internal representation width
// that can also depend on the column format
- switch (cdp->Fmt ? *cdp->Fmt : 'X') {
- case 'C': break;
+ fty = cdp->Decode ? 'C' : 'X';
+ eds = 0;
+ n = 0;
+
+ if (cdp->Fmt && !cdp->Decode) {
+ for (i = 0; cdp->Fmt[i]; i++) {
+ c = toupper(cdp->Fmt[i]);
+
+ if (isdigit(c))
+ n = (n * 10 + (c - '0'));
+ else if (c == 'L' || c == 'B' || c == 'H')
+ eds = c;
+ else
+ fty = c;
+
+ } // endfor i
+
+ } // endif Fmt
+
+ if (n)
+ nof = n;
+ else switch (fty) {
+ case 'X':
+ if (eds && IsTypeChar(cdp->Buf_Type))
+ nof = sizeof(longlong);
+ else
+ nof= cdp->Clen;
+
+ break;
+ case 'C': break;
case 'R':
- case 'F':
- case 'L':
- case 'I': nof= 4; break;
- case 'D': nof= 8; break;
- case 'S': nof= 2; break;
- case 'T': nof= 1; break;
- default: nof= cdp->Clen;
- } // endswitch Fmt
+ case 'F': nof = sizeof(float); break;
+ case 'I': nof = sizeof(int); break;
+ case 'D': nof = sizeof(double); break;
+ case 'S': nof = sizeof(short); break;
+ case 'T': nof = sizeof(char); break;
+ case 'G': nof = sizeof(longlong); break;
+ default: /* Wrong format */
+ sprintf(g->Message, "Invalid format %c", fty);
+ return -1;
+ } // endswitch fty
+
+ } // endif nof
default:
break;
@@ -364,20 +403,16 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
// not specified (for instance if quoted is specified)
// if ((ending= Hc->GetIntegerOption("Ending")) < 0) {
if ((ending= Hc->GetIntegerOption("Ending")) <= 0) {
-#if defined(WIN32)
- ending= 2;
-#else
- ending= 1;
-#endif
+ ending= (tc == TAB_BIN || tc == TAB_VEC) ? 0 : CRLF;
Hc->SetIntegerOption("Ending", ending);
} // endif ending
// Calculate the default record size
switch (tc) {
case TAB_FIX:
+ case TAB_BIN:
recln= nlg + ending; // + length of line ending
break;
- case TAB_BIN:
case TAB_VEC:
recln= nlg;
@@ -428,20 +463,31 @@ void TABDEF::SetIndexInfo(void)
PTABDEF OEMDEF::GetXdef(PGLOBAL g)
{
typedef PTABDEF (__stdcall *XGETDEF) (PGLOBAL, void *);
- char c, getname[40] = "Get";
+ char c, soname[_MAX_PATH], getname[40] = "Get";
PTABDEF xdefp;
XGETDEF getdef = NULL;
PCATLG cat = Cat;
-#if defined(WIN32)
+ /*********************************************************************/
+ /* Ensure that the .dll doesn't have a path. */
+ /* This is done to ensure that only approved dll from the system */
+ /* directories are used (to make this even remotely secure). */
+ /*********************************************************************/
+ if (check_valid_path(Module, strlen(Module))) {
+ strcpy(g->Message, "Module cannot contain a path");
+ return NULL;
+ } else
+ PlugSetPath(soname, Module, GetPluginDir());
+
+#if defined(__WIN__)
// Is the DLL already loaded?
- if (!Hdll && !(Hdll = GetModuleHandle(Module)))
+ if (!Hdll && !(Hdll = GetModuleHandle(soname)))
// No, load the Dll implementing the function
- if (!(Hdll = LoadLibrary(Module))) {
+ if (!(Hdll = LoadLibrary(soname))) {
char buf[256];
DWORD rc = GetLastError();
- sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, Module);
+ sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
(LPTSTR)buf, sizeof(buf), NULL);
@@ -462,10 +508,11 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
FreeLibrary((HMODULE)Hdll);
return NULL;
} // endif getdef
-#else // !WIN32
+#else // !__WIN__
const char *error = NULL;
Dl_info dl_info;
-
+
+#if 0 // Don't know what all this stuff does
// The OEM lib must retrieve exported CONNECT variables
if (dladdr(&connect_hton, &dl_info)) {
if (dlopen(dl_info.dli_fname, RTLD_NOLOAD | RTLD_NOW | RTLD_GLOBAL) == 0) {
@@ -479,15 +526,16 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
sprintf(g->Message, "dladdr failed: %s, OEM not supported", SVP(error));
return NULL;
} // endif dladdr
+#endif // 0
// Is the library already loaded?
-// if (!Hdll && !(Hdll = ???))
- // Load the desired shared library
- if (!(Hdll = dlopen(Module, RTLD_LAZY))) {
- error = dlerror();
- sprintf(g->Message, MSG(SHARED_LIB_ERR), Module, SVP(error));
- return NULL;
- } // endif Hdll
+ if (!Hdll && !(Hdll = dlopen(soname, RTLD_NOLOAD)))
+ // Load the desired shared library
+ if (!(Hdll = dlopen(soname, RTLD_LAZY))) {
+ error = dlerror();
+ sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
+ return NULL;
+ } // endif Hdll
// The exported name is always in uppercase
for (int i = 0; ; i++) {
@@ -503,7 +551,7 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
dlclose(Hdll);
return NULL;
} // endif getdef
-#endif // !WIN32
+#endif // !__WIN__
// Just in case the external Get function does not set error messages
sprintf(g->Message, MSG(DEF_ALLOC_ERROR), Subtype);
@@ -543,7 +591,7 @@ bool OEMDEF::DeleteTableFile(PGLOBAL g)
/***********************************************************************/
/* Define: initialize the table definition block from XDB file. */
/***********************************************************************/
-bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int)
{
Module = GetStringCatInfo(g, "Module", "");
Subtype = GetStringCatInfo(g, "Subtype", Module);
@@ -710,10 +758,9 @@ COLDEF::COLDEF(void) : COLCRT()
/***********************************************************************/
/* Define: initialize a column definition from a COLINFO structure. */
/***********************************************************************/
-int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
+int COLDEF::Define(PGLOBAL g, void *, PCOLINFO cfp, int poff)
{
- Name = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Name) + 1);
- strcpy(Name, cfp->Name);
+ Name = (PSZ)PlugDup(g, cfp->Name);
if (!(cfp->Flags & U_SPECIAL)) {
Poff = poff;
@@ -735,22 +782,17 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
Key = cfp->Key;
Freq = cfp->Freq;
- if (cfp->Remark && *cfp->Remark) {
- Desc = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Remark) + 1);
- strcpy(Desc, cfp->Remark);
- } // endif Remark
+ if (cfp->Remark && *cfp->Remark)
+ Desc = (PSZ)PlugDup(g, cfp->Remark);
- if (cfp->Datefmt) {
- Decode = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Datefmt) + 1);
- strcpy(Decode, cfp->Datefmt);
- } // endif Datefmt
+ if (cfp->Datefmt)
+ Decode = (PSZ)PlugDup(g, cfp->Datefmt);
- } // endif special
+ } else
+ Offset = poff;
- if (cfp->Fieldfmt) {
- Fmt = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Fieldfmt) + 1);
- strcpy(Fmt, cfp->Fieldfmt);
- } // endif Fieldfmt
+ if (cfp->Fieldfmt)
+ Fmt = (PSZ)PlugDup(g, cfp->Fieldfmt);
Flags = cfp->Flags;
return (Flags & (U_VIRTUAL|U_SPECIAL)) ? 0 : Long;
diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h
index 6160ea71680..4aa29037dfc 100644
--- a/storage/connect/reldef.h
+++ b/storage/connect/reldef.h
@@ -1,7 +1,7 @@
/*************** RelDef H Declares Source Code File (.H) ***************/
/* Name: RELDEF.H Version 1.5 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2004-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2004-2015 */
/* */
/* This file contains the DEF classes definitions. */
/***********************************************************************/
@@ -12,6 +12,7 @@
#include "block.h"
#include "catalog.h"
#include "my_sys.h"
+#include "mycat.h"
typedef class INDEXDEF *PIXDEF;
typedef class ha_connect *PHC;
@@ -40,6 +41,7 @@ class DllExport RELDEF : public BLOCK { // Relation definition block
void SetCat(PCATLG cat) { Cat=cat; }
// Methods
+ PTOS GetTopt(void);
bool GetBoolCatInfo(PSZ what, bool bdef);
bool SetIntCatInfo(PSZ what, int ival);
bool Partitioned(void);
@@ -87,7 +89,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */
bool IsReadOnly(void) {return Read_Only;}
virtual AMT GetDefType(void) {return TYPE_AM_TAB;}
virtual PIXDEF GetIndx(void) {return NULL;}
- virtual void SetIndx(PIXDEF xp) {}
+ virtual void SetIndx(PIXDEF) {}
virtual bool IsHuge(void) {return false;}
const CHARSET_INFO *data_charset() {return m_data_charset;}
@@ -137,11 +139,11 @@ class DllExport OEMDEF : public TABDEF { /* OEM table */
PTABDEF GetXdef(PGLOBAL g);
// Members
-#if defined(WIN32)
+#if defined(__WIN__)
HANDLE Hdll; /* Handle to the external DLL */
-#else // !WIN32
+#else // !__WIN__
void *Hdll; /* Handle for the loaded shared library */
-#endif // !WIN32
+#endif // !__WIN__
PTABDEF Pxdef; /* Pointer to the external TABDEF class */
char *Module; /* Path/Name of the DLL implenting it */
char *Subtype; /* The name of the OEM table sub type */
diff --git a/storage/connect/tabcol.cpp b/storage/connect/tabcol.cpp
index 8f350c6f074..662c0b514cf 100644
--- a/storage/connect/tabcol.cpp
+++ b/storage/connect/tabcol.cpp
@@ -1,7 +1,7 @@
/************* TabCol C++ Functions Source Code File (.CPP) ************/
/* Name: TABCOL.CPP Version 2.7 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2013 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
/* */
/* This file contains the PlugDB++ XTAB, COLUMN and XORDER methods. */
/***********************************************************************/
@@ -91,7 +91,7 @@ void XTAB::Print(PGLOBAL g, FILE *f, uint n)
/***********************************************************************/
/* Make string output of XTAB contents. */
/***********************************************************************/
-void XTAB::Print(PGLOBAL g, char *ps, uint z)
+void XTAB::Print(PGLOBAL, char *ps, uint z)
{
char buf[128];
int i, n = (int)z - 1;
@@ -125,7 +125,7 @@ COLUMN::COLUMN(LPCSTR name) : Name(name)
/***********************************************************************/
/* COLUMN SetFormat: should never be called. */
/***********************************************************************/
-bool COLUMN::SetFormat(PGLOBAL g, FORMAT& fmt)
+bool COLUMN::SetFormat(PGLOBAL g, FORMAT&)
{
strcpy(g->Message, MSG(NO_FORMAT_COL));
return true;
@@ -154,7 +154,7 @@ void COLUMN::Print(PGLOBAL g, FILE *f, uint n)
/***********************************************************************/
/* Make string output of COLUMN contents. */
/***********************************************************************/
-void COLUMN::Print(PGLOBAL g, char *ps, uint z)
+void COLUMN::Print(PGLOBAL, char *ps, uint z)
{
char buf[80];
diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp
index ba22da52998..a1e58ab3344 100644
--- a/storage/connect/tabdos.cpp
+++ b/storage/connect/tabdos.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -17,7 +17,7 @@
/* Include relevant sections of the System header files. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <sys\timeb.h> // For testing only
#include <fcntl.h>
@@ -26,7 +26,7 @@
#define __MFC_COMPAT__ // To define min/max as macro
#endif // __BORLANDC__
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#if defined(UNIX)
#include <errno.h>
#include <unistd.h>
@@ -34,7 +34,7 @@
#include <io.h>
#endif // !UNIX
#include <fcntl.h>
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Include application header files: */
@@ -112,12 +112,13 @@ DOSDEF::DOSDEF(void)
Maxerr = 0;
ReadMode = 0;
Ending = 0;
+ Teds = 0;
} // end of DOSDEF constructor
/***********************************************************************/
/* DefineAM: define specific AM block values from XDB file. */
/***********************************************************************/
-bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
{
char buf[8];
bool map = (am && (*am == 'M' || *am == 'm'));
@@ -146,6 +147,7 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Padded = GetBoolCatInfo("Padded", false);
Blksize = GetIntCatInfo("Blksize", 0);
Eof = (GetIntCatInfo("EOF", 0) != 0);
+ Teds = toupper(*GetStringCatInfo(g, "Endian", ""));
} else if (Recfm == RECFM_DBF) {
Maxerr = GetIntCatInfo("Maxerr", 0);
Accept = GetBoolCatInfo("Accept", false);
@@ -206,11 +208,11 @@ void DOSDEF::RemoveOptValues(PGLOBAL g)
// Delete any eventually ill formed non matching optimization file
if (!GetOptFileName(g, filename))
-#if defined(WIN32)
+#if defined(__WIN__)
DeleteFile(filename);
#else // UNIX
remove(filename);
-#endif // WIN32
+#endif // __WIN__
Optimized = 0;
} // end of RemoveOptValues
@@ -251,7 +253,7 @@ bool DOSDEF::DeleteIndexFile(PGLOBAL g, PIXDEF pxdf)
/*********************************************************************/
if (sep) {
// Indexes are save in separate files
-#if !defined(UNIX)
+#if defined(__WIN__)
char drive[_MAX_DRIVE];
#else
char *drive = NULL;
@@ -268,7 +270,7 @@ bool DOSDEF::DeleteIndexFile(PGLOBAL g, PIXDEF pxdf)
strcat(strcat(fname, "_"), pxdf->GetName());
_makepath(filename, drive, direc, fname, ftype);
PlugSetPath(filename, filename, GetPath());
-#if defined(WIN32)
+#if defined(__WIN__)
if (!DeleteFile(filename))
rc |= (GetLastError() != ERROR_FILE_NOT_FOUND);
#else // UNIX
@@ -285,7 +287,7 @@ bool DOSDEF::DeleteIndexFile(PGLOBAL g, PIXDEF pxdf)
// Drop all indexes, delete the common file
PlugSetPath(filename, Ofn, GetPath());
strcat(PlugRemoveType(filename, filename), ftype);
-#if defined(WIN32)
+#if defined(__WIN__)
if (!DeleteFile(filename))
rc = (GetLastError() != ERROR_FILE_NOT_FOUND);
#else // UNIX
@@ -303,7 +305,7 @@ bool DOSDEF::DeleteIndexFile(PGLOBAL g, PIXDEF pxdf)
/***********************************************************************/
/* InvalidateIndex: mark all indexes as invalid. */
/***********************************************************************/
-bool DOSDEF::InvalidateIndex(PGLOBAL g)
+bool DOSDEF::InvalidateIndex(PGLOBAL)
{
if (To_Indx)
for (PIXDEF xp = To_Indx; xp; xp = xp->Next)
@@ -954,7 +956,7 @@ bool TDBDOS::GetBlockValues(PGLOBAL g)
#if 0
if (Mode == MODE_INSERT && Txfp->GetAmType() == TYPE_AM_DOS)
return false;
-#endif // WIN32
+#endif // __WIN__
if (defp->Optimized)
return false; // Already done or to be redone
@@ -1736,15 +1738,16 @@ err:
/***********************************************************************/
/* Make a dynamic index. */
/***********************************************************************/
-bool TDBDOS::InitialyzeIndex(PGLOBAL g, PIXDEF xdp, bool sorted)
+bool TDBDOS::InitialyzeIndex(PGLOBAL g, volatile PIXDEF xdp, bool sorted)
{
int k, rc;
- bool brc, dynamic;
+ volatile bool dynamic;
+ bool brc;
PCOL colp;
PCOLDEF cdp;
PVAL valp;
PXLOAD pxp;
- PKXBASE kxp;
+ volatile PKXBASE kxp;
PKPDEF kdp;
if (!xdp && !(xdp = To_Xdp)) {
@@ -1864,7 +1867,7 @@ int TDBDOS::GetProgCur(void)
/***********************************************************************/
/* RowNumber: return the ordinal number of the current row. */
/***********************************************************************/
-int TDBDOS::RowNumber(PGLOBAL g, bool b)
+int TDBDOS::RowNumber(PGLOBAL g, bool)
{
if (To_Kindex) {
/*******************************************************************/
@@ -1944,7 +1947,7 @@ int TDBDOS::Cardinality(PGLOBAL g)
rec = ((PDOSDEF)To_Def)->Ending;
if (AvgLen <= 0) // No given average estimate
- rec += EstimatedLength(g);
+ rec += EstimatedLength();
else // An estimate was given for the average record length
rec += AvgLen;
@@ -1988,7 +1991,7 @@ int TDBDOS::GetMaxSize(PGLOBAL g)
/* Estimate the number of lines in the table (if not known) by */
/* dividing the file length by minimum record length. */
/*****************************************************************/
- rec = EstimatedLength(g) + ((PDOSDEF)To_Def)->Ending;
+ rec = EstimatedLength() + ((PDOSDEF)To_Def)->Ending;
MaxSize = (len + rec - 1) / rec;
if (trace)
@@ -2005,7 +2008,7 @@ int TDBDOS::GetMaxSize(PGLOBAL g)
/***********************************************************************/
/* DOS EstimatedLength. Returns an estimated minimum line length. */
/***********************************************************************/
-int TDBDOS::EstimatedLength(PGLOBAL g)
+int TDBDOS::EstimatedLength(void)
{
int dep = 0;
PCOLDEF cdp = To_Def->GetCols();
@@ -2023,7 +2026,7 @@ int TDBDOS::EstimatedLength(PGLOBAL g)
/***********************************************************************/
/* DOS tables favor the use temporary files for Update. */
/***********************************************************************/
-bool TDBDOS::IsUsingTemp(PGLOBAL g)
+bool TDBDOS::IsUsingTemp(PGLOBAL)
{
USETEMP utp = UseTemp();
@@ -2183,7 +2186,7 @@ int TDBDOS::ReadDB(PGLOBAL g)
/***********************************************************************/
/* PrepareWriting: Prepare the line to write. */
/***********************************************************************/
-bool TDBDOS::PrepareWriting(PGLOBAL g)
+bool TDBDOS::PrepareWriting(PGLOBAL)
{
if (!Ftype && (Mode == MODE_INSERT || Txfp->GetUseTemp())) {
char *p;
diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h
index 156d46b9791..c098886f14b 100644
--- a/storage/connect/tabdos.h
+++ b/storage/connect/tabdos.h
@@ -1,7 +1,7 @@
/*************** TabDos H Declares Source Code File (.H) ***************/
/* Name: TABDOS.H Version 3.3 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 1999-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 1999-2015 */
/* */
/* This file contains the DOS classes declares. */
/***********************************************************************/
@@ -91,6 +91,7 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
int Maxerr; /* Maximum number of bad records (DBF) */
int ReadMode; /* Specific to DBF */
int Ending; /* Length of end of lines */
+ int Teds; /* Binary table default endian setting */
}; // end of DOSDEF
/***********************************************************************/
@@ -123,11 +124,11 @@ class DllExport TDBDOS : public TDBASE {
// Implementation
virtual AMT GetAmType(void) {return Txfp->GetAmType();}
- virtual PSZ GetFile(PGLOBAL g) {return Txfp->To_File;}
- virtual void SetFile(PGLOBAL g, PSZ fn) {Txfp->To_File = fn;}
+ virtual PSZ GetFile(PGLOBAL) {return Txfp->To_File;}
+ virtual void SetFile(PGLOBAL, PSZ fn) {Txfp->To_File = fn;}
virtual void SetAbort(bool b) {Abort = b;}
virtual RECFM GetFtype(void) {return Ftype;}
- virtual bool SkipHeader(PGLOBAL g) {return false;}
+ virtual bool SkipHeader(PGLOBAL) {return false;}
virtual void RestoreNrec(void) {Txfp->SetNrec(1);}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBDOS(g, this);}
@@ -149,7 +150,7 @@ class DllExport TDBDOS : public TDBASE {
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
- virtual char *GetOpenMode(PGLOBAL g, char *opmode) {return NULL;}
+ virtual char *GetOpenMode(PGLOBAL, char*) {return NULL;}
virtual int GetFileLength(PGLOBAL g) {return Txfp->GetFileLength(g);}
virtual int GetProgMax(PGLOBAL g);
virtual int GetProgCur(void);
@@ -168,7 +169,7 @@ class DllExport TDBDOS : public TDBASE {
virtual int ReadBuffer(PGLOBAL g) {return Txfp->ReadBuffer(g);}
// Specific routine
- virtual int EstimatedLength(PGLOBAL g);
+ virtual int EstimatedLength(void);
// Optimization routines
virtual int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add);
@@ -222,6 +223,7 @@ class DllExport DOSCOL : public COLBLK {
virtual PVBLK GetDval(void) {return Dval;}
// Methods
+ using COLBLK::Print;
virtual bool VarSize(void);
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void ReadColumn(PGLOBAL g);
diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp
index 77e47e6f8dd..acd548c86ab 100644
--- a/storage/connect/tabfix.cpp
+++ b/storage/connect/tabfix.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -17,7 +17,7 @@
/* Include relevant section of system dependant header files. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <fcntl.h>
#include <errno.h>
@@ -25,7 +25,7 @@
#define __MFC_COMPAT__ // To define min/max as macro
#endif // __BORLANDC__
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#if defined(UNIX)
#include <sys/types.h>
#include <sys/stat.h>
@@ -35,7 +35,7 @@
#include <io.h>
#endif // !UNIX
#include <fcntl.h>
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Include application header files: */
@@ -54,6 +54,7 @@
extern int num_read, num_there, num_eq[2]; // Statistics
static const longlong M2G = 0x80000000;
static const longlong M4G = (longlong)2 * M2G;
+char BINCOL::Endian = 'H';
/***********************************************************************/
/* External function. */
@@ -67,10 +68,12 @@ USETEMP UseTemp(void);
/***********************************************************************/
TDBFIX::TDBFIX(PDOSDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
{
+ Teds = tdp->Teds; // For BIN tables
} // end of TDBFIX standard constructor
TDBFIX::TDBFIX(PGLOBAL g, PTDBFIX tdbp) : TDBDOS(g, tdbp)
{
+ Teds = tdbp->Teds;
} // end of TDBFIX copy constructor
// Method
@@ -271,7 +274,7 @@ int TDBFIX::RowNumber(PGLOBAL g, bool b)
/***********************************************************************/
/* FIX tables don't use temporary files except if specified as do it. */
/***********************************************************************/
-bool TDBFIX::IsUsingTemp(PGLOBAL g)
+bool TDBFIX::IsUsingTemp(PGLOBAL)
{
// Not ready yet to handle using a temporary file with mapping
// or while deleting from DBF files.
@@ -373,19 +376,94 @@ int TDBFIX::WriteDB(PGLOBAL g)
BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
: DOSCOL(g, cdp, tp, cp, i, am)
{
- Fmt = (cdp->GetFmt()) ? toupper(*cdp->GetFmt()) : 'X';
+ char c, *fmt = cdp->GetFmt();
+
+ Fmt = GetDomain() ? 'C' : 'X';
+ Buff = NULL;
+ Eds = ((PTDBFIX)tp)->Teds;
+ N = 0;
+ M = GetTypeSize(Buf_Type, sizeof(longlong));
+ Lim = 0;
+
+ if (fmt) {
+ for (N = 0, i = 0; fmt[i]; i++) {
+ c = toupper(fmt[i]);
+
+ if (isdigit(c))
+ N = (N * 10 + (c - '0'));
+ else if (c == 'L' || c == 'B' || c == 'H')
+ Eds = c;
+ else
+ Fmt = c;
+
+ } // endfor i
+
+ // M is the size of the source value
+ switch (Fmt) {
+ case 'C': Eds = 0; break;
+ case 'X': break;
+ case 'S': M = sizeof(short); break;
+ case 'T': M = sizeof(char); break;
+ case 'I': M = sizeof(int); break;
+ case 'G': M = sizeof(longlong); break;
+ case 'R': // Real
+ case 'F': M = sizeof(float); break;
+ case 'D': M = sizeof(double); break;
+ default:
+ sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name);
+ longjmp(g->jumper[g->jump_level], 11);
+ } // endswitch Fmt
+
+ } else if (IsTypeChar(Buf_Type))
+ Eds = 0;
+
+ if (Eds) {
+ // This is a byte order specification
+ if (!N)
+ N = M;
+
+ if (Eds != 'L' && Eds != 'B')
+ Eds = Endian;
+
+ if (N != M || Eds != Endian || IsTypeChar(Buf_Type)) {
+ Buff = (char*)PlugSubAlloc(g, NULL, M);
+ memset(Buff, 0, M);
+ Lim = MY_MIN(N, M);
+ } else
+ Eds = 0; // New format is a no op
+
+ } // endif Eds
+
} // end of BINCOL constructor
/***********************************************************************/
-/* FIXCOL constructor used for copying columns. */
+/* BINCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
BINCOL::BINCOL(BINCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
{
+ Eds = col1->Eds;
Fmt = col1->Fmt;
+ N = col1->N;
+ M = col1->M;
+ Lim = col1->Lim;
} // end of BINCOL copy constructor
/***********************************************************************/
+/* Set Endian according to the host setting. */
+/***********************************************************************/
+void BINCOL::SetEndian(void)
+ {
+ union {
+ short S;
+ char C[sizeof(short)];
+ };
+
+ S = 1;
+ Endian = (C[0] == 1) ? 'L' : 'B';
+ } // end of SetEndian
+
+/***********************************************************************/
/* ReadColumn: what this routine does is to access the last line */
/* read from the corresponding table and extract from it the field */
/* corresponding to this column. */
@@ -416,22 +494,40 @@ void BINCOL::ReadColumn(PGLOBAL g)
/*********************************************************************/
/* Set Value from the line field. */
/*********************************************************************/
+ if (Eds) {
+ for (int i = 0; i < Lim; i++)
+ if (Eds == 'B' && Endian == 'L')
+ Buff[i] = p[N - i - 1];
+ else if (Eds == 'L' && Endian == 'B')
+ Buff[M - i - 1] = p[i];
+ else if (Endian == 'B')
+ Buff[M - i - 1] = p[N - i - 1];
+ else
+ Buff[i] = p[i];
+
+ p = Buff;
+ } // endif Eds
+
switch (Fmt) {
case 'X': // Standard not converted values
- Value->SetBinValue(p);
+ if (Eds && IsTypeChar(Buf_Type))
+ Value->SetValue(*(longlong*)p);
+ else
+ Value->SetBinValue(p);
+
break;
case 'S': // Short integer
- Value->SetValue((int)*(short*)p);
+ Value->SetValue(*(short*)p);
break;
case 'T': // Tiny integer
- Value->SetValue((int)*p);
+ Value->SetValue(*p);
break;
- case 'L': // Long Integer
- strcpy(g->Message, "Format L is deprecated, use I");
- longjmp(g->jumper[g->jump_level], 11);
case 'I': // Integer
Value->SetValue(*(int*)p);
break;
+ case 'G': // Large (great) integer
+ Value->SetValue(*(longlong*)p);
+ break;
case 'F': // Float
case 'R': // Real
Value->SetValue((double)*(float*)p);
@@ -483,7 +579,7 @@ void BINCOL::WriteColumn(PGLOBAL g)
if (Value != To_Val)
Value->SetValue_pval(To_Val, false); // Convert the updated value
- p = tdbp->To_Line + Deplac;
+ p = (Eds) ? Buff : tdbp->To_Line + Deplac;
/*********************************************************************/
/* Check whether updating is Ok, meaning col value is not too long. */
@@ -493,11 +589,13 @@ void BINCOL::WriteColumn(PGLOBAL g)
switch (Fmt) {
case 'X':
// Standard not converted values
- if (Value->GetBinValue(p, Long, Status)) {
+ if (Eds && IsTypeChar(Buf_Type))
+ *(longlong *)p = Value->GetBigintValue();
+ else if (Value->GetBinValue(p, Long, Status)) {
sprintf(g->Message, MSG(BIN_F_TOO_LONG),
Name, Value->GetSize(), Long);
longjmp(g->jumper[g->jump_level], 31);
- } // endif Fmt
+ } // endif p
break;
case 'S': // Short integer
@@ -520,9 +618,6 @@ void BINCOL::WriteColumn(PGLOBAL g)
*p = (char)n;
break;
- case 'L': // Long Integer
- strcpy(g->Message, "Format L is deprecated, use I");
- longjmp(g->jumper[g->jump_level], 11);
case 'I': // Integer
n = Value->GetBigintValue();
@@ -533,9 +628,9 @@ void BINCOL::WriteColumn(PGLOBAL g)
*(int *)p = Value->GetIntValue();
break;
- case 'B': // Large (big) integer
+ case 'G': // Large (great) integer
if (Status)
- *(longlong *)p = (longlong)Value->GetBigintValue();
+ *(longlong *)p = Value->GetBigintValue();
break;
case 'F': // Float
@@ -567,6 +662,21 @@ void BINCOL::WriteColumn(PGLOBAL g)
longjmp(g->jumper[g->jump_level], 11);
} // endswitch Fmt
+ if (Eds && Status) {
+ p = tdbp->To_Line + Deplac;
+
+ for (int i = 0; i < Lim; i++)
+ if (Eds == 'B' && Endian == 'L')
+ p[N - i - 1] = Buff[i];
+ else if (Eds == 'L' && Endian == 'B')
+ p[i] = Buff[M - i - 1];
+ else if (Endian == 'B')
+ p[N - i - 1] = Buff[M - i - 1];
+ else
+ p[i] = Buff[i];
+
+ } // endif Eds
+
} // end of WriteColumn
/* ------------------------ End of TabFix ---------------------------- */
diff --git a/storage/connect/tabfix.h b/storage/connect/tabfix.h
index 7d5b964da2a..49956ba0711 100644
--- a/storage/connect/tabfix.h
+++ b/storage/connect/tabfix.h
@@ -1,7 +1,7 @@
/*************** TabDos H Declares Source Code File (.H) ***************/
-/* Name: TABFIX.H Version 2.3 */
+/* Name: TABFIX.H Version 2.4 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 1999-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 1999-2015 */
/* */
/* This file contains the TDBFIX and (FIX/BIN)COL classes declares. */
/***********************************************************************/
@@ -12,7 +12,7 @@
typedef class FIXCOL *PFIXCOL;
typedef class BINCOL *PBINCOL;
-typedef class TXTFAM *PTXF;
+typedef class TXTFAM *PTXF;
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
@@ -53,7 +53,8 @@ class DllExport TDBFIX : public TDBDOS {
protected:
virtual bool PrepareWriting(PGLOBAL g) {return false;}
- // Members are inherited from TDBDOS
+ // Members
+ char Teds; /* Binary table default endian setting */
}; // end of class TDBFIX
/***********************************************************************/
@@ -68,17 +69,29 @@ class DllExport BINCOL : public DOSCOL {
BINCOL(BINCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
- virtual int GetAmType(void) {return TYPE_AM_BIN;}
+ virtual int GetAmType(void) {return TYPE_AM_BIN;}
+ int GetDeplac(void) {return Deplac;}
+ int GetFileSize(void)
+ {return N ? N : GetTypeSize(Buf_Type, Long);}
// Methods
- virtual void ReadColumn(PGLOBAL g);
- virtual void WriteColumn(PGLOBAL g);
+ virtual void ReadColumn(PGLOBAL g);
+ virtual void WriteColumn(PGLOBAL g);
+
+ // Static
+ static void SetEndian(void);
protected:
BINCOL(void) {} // Default constructor not to be used
// Members
- char Fmt; // The column numeric format
+ static char Endian; // The host endian setting (L or B)
+ char *Buff; // Utility buffer
+ char Eds; // The file endian setting
+ char Fmt; // The converted value format
+ int N; // The number of bytes in the file
+ int M; // The buffer type size
+ int Lim; // Min(N,M)
}; // end of class BINCOL
/***********************************************************************/
diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp
index d5f8dc50a89..015f8d93b15 100644
--- a/storage/connect/tabfmt.cpp
+++ b/storage/connect/tabfmt.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2001 - 2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2001 - 2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -20,7 +20,7 @@
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <fcntl.h>
#include <errno.h>
@@ -102,14 +102,14 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, const char *fn, char sep,
} // endif info
// num_max = atoi(p+1); // Max num of record to test
-#if defined(WIN32)
+#if defined(__WIN__)
if (sep == ',' || strnicmp(setlocale(LC_NUMERIC, NULL), "French", 6))
dechar = '.';
else
dechar = ',';
-#else // !WIN32
+#else // !__WIN__
dechar = '.';
-#endif // !WIN32
+#endif // !__WIN__
if (trace)
htrc("File %s sep=%c q=%c hdr=%d mxr=%d\n",
@@ -147,7 +147,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, const char *fn, char sep,
if (fgets(buf, sizeof(buf), infile)) {
n = strlen(buf) + 1;
buf[n - 2] = '\0';
-#if defined(UNIX)
+#if !defined(__WIN__)
// The file can be imported from Windows
if (buf[n - 3] == '\r')
buf[n - 3] = 0;
@@ -204,7 +204,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, const char *fn, char sep,
if (fgets(buf, sizeof(buf), infile)) {
n = strlen(buf);
buf[n - 1] = '\0';
-#if defined(UNIX)
+#if !defined(__WIN__)
// The file can be imported from Windows
if (buf[n - 2] == '\r')
buf[n - 2] = 0;
@@ -625,7 +625,7 @@ bool TDBCSV::CheckErr(void)
/***********************************************************************/
/* CSV EstimatedLength. Returns an estimated minimum line length. */
/***********************************************************************/
-int TDBCSV::EstimatedLength(PGLOBAL g)
+int TDBCSV::EstimatedLength(void)
{
int n = 0;
PCOLDEF cdp;
@@ -1118,7 +1118,7 @@ PCOL TDBFMT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/* FMT EstimatedLength. Returns an estimated minimum line length. */
/* The big problem here is how can we astimated that minimum ? */
/***********************************************************************/
-int TDBFMT::EstimatedLength(PGLOBAL g)
+int TDBFMT::EstimatedLength(void)
{
// This is rather stupid !!!
return ((PDOSDEF)To_Def)->GetEnding() + (int)((Lrecl / 10) + 1);
diff --git a/storage/connect/tabfmt.h b/storage/connect/tabfmt.h
index 8a1e1f17561..ce80a276cdc 100644
--- a/storage/connect/tabfmt.h
+++ b/storage/connect/tabfmt.h
@@ -75,7 +75,7 @@ class TDBCSV : public TDBDOS {
virtual int ReadBuffer(PGLOBAL g); // Physical file read
// Specific routines
- virtual int EstimatedLength(PGLOBAL g);
+ virtual int EstimatedLength(void);
virtual bool SkipHeader(PGLOBAL g);
virtual bool CheckErr(void);
@@ -157,7 +157,7 @@ class TDBFMT : public TDBCSV {
virtual int ReadBuffer(PGLOBAL g); // Physical file read
// Specific routines
- virtual int EstimatedLength(PGLOBAL g);
+ virtual int EstimatedLength(void);
protected:
virtual bool PrepareWriting(PGLOBAL g)
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index a3c56965794..fafba6228b9 100644
--- a/storage/connect/tabjson.cpp
+++ b/storage/connect/tabjson.cpp
@@ -1,5 +1,5 @@
/************* tabjson C++ Program Source Code File (.CPP) *************/
-/* PROGRAM NAME: tabxjson Version 1.0 */
+/* PROGRAM NAME: tabjson Version 1.1 */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* This program are the JSON class DB execution routines. */
/***********************************************************************/
@@ -19,7 +19,6 @@
#include "global.h"
#include "plgdbsem.h"
//#include "xtable.h"
-//#include "mycat.h" // for FNC_COL
#include "maputil.h"
#include "filamtxt.h"
#include "tabdos.h"
@@ -31,12 +30,324 @@
#endif // ZIP_SUPPORT
#include "tabmul.h"
#include "checklvl.h"
+#include "resource.h"
+#include "mycat.h" // for FNC_COL
+
+/***********************************************************************/
+/* This should be an option. */
+/***********************************************************************/
+#define MAXCOL 200 /* Default max column nb in result */
+#define TYPE_UNKNOWN 12 /* Must be greater than other types */
/***********************************************************************/
/* External function. */
/***********************************************************************/
USETEMP UseTemp(void);
+typedef struct _jncol {
+ struct _jncol *Next;
+ char *Name;
+ char *Fmt;
+ int Type;
+ int Len;
+ int Scale;
+ bool Cbn;
+ bool Found;
+} JCOL, *PJCL;
+
+/***********************************************************************/
+/* JSONColumns: construct the result blocks containing the description */
+/* of all the columns of a table contained inside a JSON file. */
+/***********************************************************************/
+PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info)
+{
+ static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
+ TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
+ static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
+ FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT};
+ static unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0};
+ char *fn, colname[65], fmt[129];
+ int i, j, lvl, n = 0;
+ int ncol = sizeof(buftyp) / sizeof(int);
+ PVAL valp;
+ JCOL jcol;
+ PJCL jcp, fjcp = NULL, pjcp = NULL;
+ PJPR *jrp, jpp;
+ PJSON jsp;
+ PJVAL jvp;
+ PJOB row;
+ PJDEF tdp;
+ TDBJSN *tjnp = NULL;
+ PJTDB tjsp = NULL;
+ PQRYRES qrp;
+ PCOLRES crp;
+
+ jcol.Name = jcol.Fmt = NULL;
+
+ if (info) {
+ length[0] = 128;
+ length[7] = 256;
+ goto skipit;
+ } // endif info
+
+ /*********************************************************************/
+ /* Open the input file. */
+ /*********************************************************************/
+ if (!(fn = GetStringTableOption(g, topt, "Filename", NULL))) {
+ strcpy(g->Message, MSG(MISSING_FNAME));
+ return NULL;
+ } else {
+ lvl = GetIntegerTableOption(g, topt, "Level", 0);
+ lvl = (lvl < 0) ? 0 : (lvl > 16) ? 16 : lvl;
+ } // endif fn
+
+ tdp = new(g) JSONDEF;
+ tdp->Fn = fn;
+ tdp->Database = SetPath(g, db);
+ tdp->Objname = GetStringTableOption(g, topt, "Object", NULL);
+ tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0;
+ tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2);
+
+ if (trace)
+ htrc("File %s objname=%s pretty=%d lvl=%d\n",
+ tdp->Fn, tdp->Objname, tdp->Pretty, lvl);
+
+ if (tdp->Pretty == 2) {
+ tjsp = new(g) TDBJSON(tdp, new(g) MAPFAM(tdp));
+
+ if (tjsp->MakeDocument(g))
+ return NULL;
+
+ jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetValue(0) : NULL;
+ } else {
+ if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0))) {
+ sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty);
+ return NULL;
+ } // endif lrecl
+
+ tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF);
+ tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp));
+ tjnp->SetMode(MODE_READ);
+
+ if (tjnp->OpenDB(g))
+ return NULL;
+
+ switch (tjnp->ReadDB(g)) {
+ case RC_EF:
+ strcpy(g->Message, "Void json table");
+ case RC_FX:
+ goto err;
+ default:
+ jsp = tjnp->GetRow();
+ } // endswitch ReadDB
+
+ } // endif pretty
+
+ if (!(row = (jsp) ? jsp->GetObject() : NULL)) {
+ strcpy(g->Message, "Can only retrieve columns from object rows");
+ goto err;
+ } // endif row
+
+ jcol.Next = NULL;
+ jcol.Found = true;
+ colname[64] = 0;
+ fmt[128] = 0;
+ jrp = (PJPR*)PlugSubAlloc(g, NULL, sizeof(PJPR) * lvl);
+
+ /*********************************************************************/
+ /* Analyse the JSON tree and define columns. */
+ /*********************************************************************/
+ for (i = 1; ; i++) {
+ for (jpp = row->GetFirst(); jpp; jpp = jpp->GetNext()) {
+ for (j = 0; j < lvl; j++)
+ jrp[j] = NULL;
+
+ more:
+ strncpy(colname, jpp->GetKey(), 64);
+ *fmt = 0;
+ j = 0;
+ jvp = jpp->GetVal();
+
+ retry:
+ if ((valp = jvp ? jvp->GetValue() : NULL)) {
+ jcol.Type = valp->GetType();
+ jcol.Len = valp->GetValLen();
+ jcol.Scale = valp->GetValPrec();
+ jcol.Cbn = valp->IsNull();
+ } else if (!jvp || jvp->IsNull()) {
+ jcol.Type = TYPE_UNKNOWN;
+ jcol.Len = jcol.Scale = 0;
+ jcol.Cbn = true;
+ } else if (j < lvl) {
+ if (!*fmt)
+ strcpy(fmt, colname);
+
+ jsp = jvp->GetJson();
+
+ switch (jsp->GetType()) {
+ case TYPE_JOB:
+ if (!jrp[j])
+ jrp[j] = jsp->GetFirst();
+
+ strncat(strncat(fmt, ":", 128), jrp[j]->GetKey(), 128);
+ strncat(strncat(colname, "_", 64), jrp[j]->GetKey(), 64);
+ jvp = jrp[j]->GetVal();
+ j++;
+ break;
+ case TYPE_JAR:
+ strncat(fmt, ":", 128);
+ jvp = jsp->GetValue(0);
+ break;
+ default:
+ sprintf(g->Message, "Logical error after %s", fmt);
+ goto err;
+ } // endswitch jsp
+
+ goto retry;
+ } else {
+ jcol.Type = TYPE_STRING;
+ jcol.Len = 256;
+ jcol.Scale = 0;
+ jcol.Cbn = true;
+ } // endif's
+
+ // Check whether this column was already found
+ for (jcp = fjcp; jcp; jcp = jcp->Next)
+ if (!strcmp(colname, jcp->Name))
+ break;
+
+ if (jcp) {
+ if (jcp->Type != jcol.Type)
+ jcp->Type = TYPE_STRING;
+
+ if (*fmt && (!jcp->Fmt || strlen(jcp->Fmt) < strlen(fmt))) {
+ jcp->Fmt = PlugDup(g, fmt);
+ length[7] = MY_MAX(length[7], strlen(fmt));
+ } // endif *fmt
+
+ jcp->Len = MY_MAX(jcp->Len, jcol.Len);
+ jcp->Scale = MY_MAX(jcp->Scale, jcol.Scale);
+ jcp->Cbn |= jcol.Cbn;
+ jcp->Found = true;
+ } else {
+ // New column
+ jcp = (PJCL)PlugSubAlloc(g, NULL, sizeof(JCOL));
+ *jcp = jcol;
+ jcp->Cbn |= (i > 1);
+ jcp->Name = PlugDup(g, colname);
+ length[0] = MY_MAX(length[0], strlen(colname));
+
+ if (*fmt) {
+ jcp->Fmt = PlugDup(g, fmt);
+ length[7] = MY_MAX(length[7], strlen(fmt));
+ } else
+ jcp->Fmt = NULL;
+
+ if (pjcp) {
+ jcp->Next = pjcp->Next;
+ pjcp->Next = jcp;
+ } else
+ fjcp = jcp;
+
+ n++;
+ } // endif jcp
+
+ pjcp = jcp;
+
+ for (j = lvl - 1; j >= 0; j--)
+ if (jrp[j] && (jrp[j] = jrp[j]->GetNext()))
+ goto more;
+
+ } // endfor jpp
+
+ // Missing column can be null
+ for (jcp = fjcp; jcp; jcp = jcp->Next) {
+ jcp->Cbn |= !jcp->Found;
+ jcp->Found = false;
+ } // endfor jcp
+
+ if (tdp->Pretty != 2) {
+ // Read next record
+ switch (tjnp->ReadDB(g)) {
+ case RC_EF:
+ jsp = NULL;
+ break;
+ case RC_FX:
+ goto err;
+ default:
+ jsp = tjnp->GetRow();
+ } // endswitch ReadDB
+
+ } else
+ jsp = tjsp->GetDoc()->GetValue(i);
+
+ if (!(row = (jsp) ? jsp->GetObject() : NULL))
+ break;
+
+ } // endor i
+
+ if (tdp->Pretty != 2)
+ tjnp->CloseDB(g);
+
+ skipit:
+ if (trace)
+ htrc("CSVColumns: n=%d len=%d\n", n, length[0]);
+
+ /*********************************************************************/
+ /* Allocate the structures used to refer to the result set. */
+ /*********************************************************************/
+ qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
+ buftyp, fldtyp, length, false, false);
+
+ crp = qrp->Colresp->Next->Next->Next->Next->Next->Next;
+ crp->Name = "Nullable";
+ crp->Next->Name = "Jpath";
+
+ if (info || !qrp)
+ return qrp;
+
+ qrp->Nblin = n;
+
+ /*********************************************************************/
+ /* Now get the results into blocks. */
+ /*********************************************************************/
+ for (i = 0, jcp = fjcp; jcp; i++, jcp = jcp->Next) {
+ if (jcp->Type == TYPE_UNKNOWN) // Void column
+ jcp->Type = TYPE_STRING;
+
+ crp = qrp->Colresp; // Column Name
+ crp->Kdata->SetValue(jcp->Name, i);
+ crp = crp->Next; // Data Type
+ crp->Kdata->SetValue(jcp->Type, i);
+ crp = crp->Next; // Type Name
+ crp->Kdata->SetValue(GetTypeName(jcp->Type), i);
+ crp = crp->Next; // Precision
+ crp->Kdata->SetValue(jcp->Len, i);
+ crp = crp->Next; // Length
+ crp->Kdata->SetValue(jcp->Len, i);
+ crp = crp->Next; // Scale (precision)
+ crp->Kdata->SetValue(jcp->Scale, i);
+ crp = crp->Next; // Nullable
+ crp->Kdata->SetValue(jcp->Cbn ? 1 : 0, i);
+ crp = crp->Next; // Field format
+
+ if (crp->Kdata)
+ crp->Kdata->SetValue(jcp->Fmt, i);
+
+ } // endfor i
+
+ /*********************************************************************/
+ /* Return the result pointer. */
+ /*********************************************************************/
+ return qrp;
+
+err:
+ if (tdp->Pretty != 2)
+ tjnp->CloseDB(g);
+
+ return NULL;
+ } // end of JSONColumns
+
/* -------------------------- Class JSONDEF -------------------------- */
JSONDEF::JSONDEF(void)
@@ -44,20 +355,23 @@ JSONDEF::JSONDEF(void)
Jmode = MODE_OBJECT;
Objname = NULL;
Xcol = NULL;
+ Pretty = 2;
Limit = 1;
- ReadMode = 0;
+ Base = 0;
+ Strict = false;
} // end of JSONDEF constructor
/***********************************************************************/
/* DefineAM: define specific AM block values. */
/***********************************************************************/
-bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR, int poff)
{
Jmode = (JMODE)GetIntCatInfo("Jmode", MODE_OBJECT);
Objname = GetStringCatInfo(g, "Object", NULL);
Xcol = GetStringCatInfo(g, "Expand", NULL);
Pretty = GetIntCatInfo("Pretty", 2);
Limit = GetIntCatInfo("Limit", 10);
+ Base = GetIntCatInfo("Base", 0) ? 1 : 0;
return DOSDEF::DefineAM(g, "DOS", poff);
} // end of DefineAM
@@ -66,6 +380,9 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
{
+ if (Catfunc == FNC_COL)
+ return new(g)TDBJCL(this);
+
PTDBASE tdbp;
PTXF txfp = NULL;
@@ -95,7 +412,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
// Txfp must be set for TDBDOS
tdbp = new(g) TDBJSN(this, txfp);
} else {
- txfp = new(g) DOSFAM(this);
+ txfp = new(g) MAPFAM(this);
tdbp = new(g) TDBJSON(this, txfp);
} // endif Pretty
@@ -112,37 +429,57 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
/***********************************************************************/
TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
{
+ Top = NULL;
Row = NULL;
+ Val = NULL;
Colp = NULL;
- Jmode = tdp->Jmode;
- Xcol = tdp->Xcol;
+
+ if (tdp) {
+ Jmode = tdp->Jmode;
+ Objname = tdp->Objname;
+ Xcol = tdp->Xcol;
+ Limit = tdp->Limit;
+ Pretty = tdp->Pretty;
+ B = tdp->Base ? 1 : 0;
+ Strict = tdp->Strict;
+ } else {
+ Jmode = MODE_OBJECT;
+ Objname = NULL;
+ Xcol = NULL;
+ Limit = 1;
+ Pretty = 0;
+ B = 0;
+ Strict = false;
+ } // endif tdp
+
Fpos = -1;
- Spos = N = 0;
- Limit = tdp->Limit;
- Pretty = tdp->Pretty;
- Strict = tdp->Strict;
- NextSame = false;
- Comma = false;
+ N = M = 0;
+ NextSame = 0;
SameRow = 0;
Xval = -1;
+ Comma = false;
} // end of TDBJSN standard constructor
TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
{
+ Top = tdbp->Top;
Row = tdbp->Row;
+ Val = tdbp->Val;
Colp = tdbp->Colp;
Jmode = tdbp->Jmode;
+ Objname = tdbp->Objname;
Xcol = tdbp->Xcol;
Fpos = tdbp->Fpos;
- Spos = tdbp->Spos;
N = tdbp->N;
+ M = tdbp->M;
Limit = tdbp->Limit;
- Pretty = tdbp->Pretty;
- Strict = tdbp->Strict;
NextSame = tdbp->NextSame;
- Comma = tdbp->Comma;
SameRow = tdbp->SameRow;
Xval = tdbp->Xval;
+ B = tdbp->B;
+ Pretty = tdbp->Pretty;
+ Strict = tdbp->Strict;
+ Comma = tdbp->Comma;
} // end of TDBJSN copy constructor
// Used for update
@@ -175,7 +512,7 @@ PCOL TDBJSN::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/
/* InsertSpecialColumn: Put a special column ahead of the column list.*/
/***********************************************************************/
-PCOL TDBJSN::InsertSpecialColumn(PGLOBAL g, PCOL colp)
+PCOL TDBJSN::InsertSpecialColumn(PCOL colp)
{
if (!colp->IsSpecial())
return NULL;
@@ -213,6 +550,34 @@ int TDBJSN::GetMaxSize(PGLOBAL g)
} // end of GetMaxSize
/***********************************************************************/
+/* Find the row in the tree structure. */
+/***********************************************************************/
+PJSON TDBJSN::FindRow(PGLOBAL g)
+{
+ char *p, *objpath;
+ PJSON jsp = Row;
+ PJVAL val = NULL;
+
+ for (objpath = PlugDup(g, Objname); jsp && objpath; objpath = p) {
+ if ((p = strchr(objpath, ':')))
+ *p++ = 0;
+
+ if (*objpath != '[') { // objpass is a key
+ val = (jsp->GetType() == TYPE_JOB) ?
+ jsp->GetObject()->GetValue(objpath) : NULL;
+ } else if (objpath[strlen(objpath)-1] == ']') {
+ val = (jsp->GetType() == TYPE_JAR) ?
+ jsp->GetArray()->GetValue(atoi(objpath+1) - B) : NULL;
+ } else
+ val = NULL;
+
+ jsp = (val) ? val->GetJson() : NULL;
+ } // endfor objpath
+
+ return jsp;
+} // end of FindRow
+
+/***********************************************************************/
/* OpenDB: Data Base open routine for JSN access method. */
/***********************************************************************/
bool TDBJSN::OpenDB(PGLOBAL g)
@@ -221,14 +586,8 @@ bool TDBJSN::OpenDB(PGLOBAL g)
/*******************************************************************/
/* Table already open replace it at its beginning. */
/*******************************************************************/
- for (PJCOL cp = (PJCOL)Columns; cp; cp = (PJCOL)cp->GetNext()) {
- cp->Nx = 0;
- cp->Arp = NULL;
- } // endfor cp
-
Fpos= -1;
- Spos = 0;
- NextSame = false;
+ NextSame = 0;
SameRow = 0;
} else {
/*******************************************************************/
@@ -264,11 +623,11 @@ bool TDBJSN::SkipHeader(PGLOBAL g)
return true;
#endif // _DEBUG
-#if defined(WIN32)
+#if defined(__WIN__)
#define Ending 2
-#else // !WIN32
+#else // !__WIN__
#define Ending 1
-#endif // !WIN32
+#endif // !__WIN__
if (Pretty == 1) {
if (Mode == MODE_INSERT || Mode == MODE_DELETE) {
@@ -292,7 +651,9 @@ int TDBJSN::ReadDB(PGLOBAL g)
N++;
if (NextSame) {
- SameRow++;
+ SameRow = NextSame;
+ NextSame = 0;
+ M++;
return RC_OK;
} else if ((rc = TDBDOS::ReadDB(g)) == RC_OK)
if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) {
@@ -301,8 +662,10 @@ int TDBJSN::ReadDB(PGLOBAL g)
strlen(To_Line), Pretty, &Comma))) {
rc = (Pretty == 1 && !strcmp(To_Line, "]")) ? RC_EF : RC_FX;
} else {
+ Row = FindRow(g);
SameRow = 0;
Fpos++;
+ M = 1;
rc = RC_OK;
} // endif's
@@ -310,19 +673,85 @@ int TDBJSN::ReadDB(PGLOBAL g)
} // end of ReadDB
/***********************************************************************/
+/* Make the top tree from the object path. */
+/***********************************************************************/
+int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
+ {
+ if (Objname) {
+ if (!Val) {
+ // Parse and allocate Objname item(s)
+ char *p;
+ char *objpath = PlugDup(g, Objname);
+ int i;
+ PJOB objp;
+ PJAR arp;
+ PJVAL val = NULL;
+
+ Top = NULL;
+
+ for (; objpath; objpath = p) {
+ if ((p = strchr(objpath, ':')))
+ *p++ = 0;
+
+ if (*objpath != '[') {
+ objp = new(g) JOBJECT;
+
+ if (!Top)
+ Top = objp;
+
+ if (val)
+ val->SetValue(objp);
+
+ val = new(g) JVALUE;
+ objp->SetValue(g, val, objpath);
+ } else if (objpath[strlen(objpath)-1] == ']') {
+ arp = new(g) JARRAY;
+
+ if (!Top)
+ Top = arp;
+
+ if (val)
+ val->SetValue(arp);
+
+ val = new(g) JVALUE;
+ i = atoi(objpath+1) - B;
+ arp->SetValue(g, val, i);
+ arp->InitArray(g);
+ } else {
+ sprintf(g->Message, "Invalid Table path %s", Objname);
+ return RC_FX;
+ } // endif objpath
+
+ } // endfor p
+
+ Val = val;
+ } // endif Val
+
+ Val->SetValue(jsp);
+ } else
+ Top = jsp;
+
+ return RC_OK;
+ } // end of MakeTopTree
+
+/***********************************************************************/
/* PrepareWriting: Prepare the line for WriteDB. */
/***********************************************************************/
bool TDBJSN::PrepareWriting(PGLOBAL g)
{
- PSZ s = Serialize(g, Row, NULL, Pretty);
+ PSZ s;
- if (s) {
+ if (MakeTopTree(g, Row))
+ return true;
+
+ if ((s = Serialize(g, Top, NULL, Pretty))) {
if (Comma)
strcat(s, ",");
if ((signed)strlen(s) > Lrecl) {
- sprintf(g->Message, "Line would be truncated (lrecl=%d)", Lrecl);
- return true;
+ strncpy(To_Line, s, Lrecl);
+ sprintf(g->Message, "Line truncated (lrecl=%d)", Lrecl);
+ return PushWarning(g, this);
} else
strcpy(To_Line, s);
@@ -333,21 +762,20 @@ int TDBJSN::ReadDB(PGLOBAL g)
} // end of PrepareWriting
-/* ----------------------------- JSNCOL ------------------------------- */
+/* ---------------------------- JSONCOL ------------------------------ */
/***********************************************************************/
-/* JSNCOL public constructor. */
+/* JSONCOL public constructor. */
/***********************************************************************/
JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
: DOSCOL(g, cdp, tdbp, cprec, i, "DOS")
{
Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp);
- Arp = NULL;
Jpath = cdp->GetFmt();
MulVal = NULL;
Nodes = NULL;
- Nod = Nx =0;
- Ival = -1;
+ Nod = 0;
+ Xnod = -1;
Xpd = false;
Parsed = false;
} // end of JSONCOL constructor
@@ -359,13 +787,11 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
{
Tjp = col1->Tjp;
- Arp = col1->Arp;
Jpath = col1->Jpath;
MulVal = col1->MulVal;
Nodes = col1->Nodes;
Nod = col1->Nod;
- Ival = col1->Ival;
- Nx = col1->Nx;
+ Xnod = col1->Xnod;
Xpd = col1->Xpd;
Parsed = col1->Parsed;
} // end of JSONCOL copy constructor
@@ -387,17 +813,16 @@ bool JSONCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
} // end of SetBuffer
/***********************************************************************/
-/* Analyse array processing options. */
+/* Check whether this object is expanded. */
/***********************************************************************/
bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b)
{
- if (Tjp->Xcol && nm && !strcmp(nm, Tjp->Xcol) &&
- (Tjp->Xval < 0 || Tjp->Xval == i)) {
+ if ((Tjp->Xcol && nm && !strcmp(nm, Tjp->Xcol) &&
+ (Tjp->Xval < 0 || Tjp->Xval == i)) || Xpd) {
Xpd = true; // Expandable object
- Nodes[i].Op = OP_XX;
- Tjp->Xval = i;
+ Nodes[i].Op = OP_EXP;
} else if (b) {
- strcpy(g->Message, "Cannot expand more than one array");
+ strcpy(g->Message, "Cannot expand more than one branch");
return true;
} // endif Xcol
@@ -410,7 +835,7 @@ bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b)
bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
{
int n = (int)strlen(p);
- bool dg = true;
+ bool dg = true, b = false;
PJNODE jnp = &Nodes[i];
if (*p) {
@@ -424,7 +849,8 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
return true;
} // endif p
- } // endif *p
+ } else
+ b = true;
// To check whether a numeric Rank was specified
for (int k = 0; dg && p[k]; k++)
@@ -434,21 +860,23 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
// Default specifications
if (CheckExpand(g, i, nm, false))
return true;
- else if (jnp->Op != OP_XX)
- if (!Value->IsTypeNum()) {
+ else if (jnp->Op != OP_EXP) {
+ if (b) {
+ // Return 1st value (B is the index base)
+ jnp->Rank = Tjp->B;
+ jnp->Op = OP_EQ;
+ } else if (!Value->IsTypeNum()) {
jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING);
jnp->Op = OP_CNC;
} else
jnp->Op = OP_ADD;
- } else if (dg) {
- if (atoi(p) > 0) {
- // Return nth value
- jnp->Rank = atoi(p);
- jnp->Op = OP_EQ;
- } else // Ignore array
- jnp->Op = OP_NULL;
+ } // endif OP
+ } else if (dg) {
+ // Return nth value
+ jnp->Rank = atoi(p) - Tjp->B;
+ jnp->Op = OP_EQ;
} else if (n == 1) {
// Set the Op value;
switch (*p) {
@@ -456,13 +884,13 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
case '*': jnp->Op = OP_MULT; break;
case '>': jnp->Op = OP_MAX; break;
case '<': jnp->Op = OP_MIN; break;
- case '#': jnp->Op = OP_NUM; break;
case '!': jnp->Op = OP_SEP; break; // Average
+ case '#': jnp->Op = OP_NUM; break;
case 'x':
case 'X': // Expand this array
if (!Tjp->Xcol && nm) {
Xpd = true;
- jnp->Op = OP_XX;
+ jnp->Op = OP_EXP;
Tjp->Xval = i;
Tjp->Xcol = nm;
} else if (CheckExpand(g, i, nm, true))
@@ -490,6 +918,38 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
return true;
} // endif's
+ // For calculated arrays, a local Value must be used
+ switch (jnp->Op) {
+ case OP_NUM:
+ jnp->Valp = AllocateValue(g, TYPE_INT);
+ break;
+ case OP_ADD:
+ case OP_MULT:
+ case OP_SEP:
+ if (!IsTypeChar(Buf_Type))
+ jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision());
+ else
+ jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2);
+
+ break;
+ case OP_MIN:
+ case OP_MAX:
+ jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision());
+ break;
+ case OP_CNC:
+ if (IsTypeChar(Buf_Type))
+ jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision());
+ else
+ jnp->Valp = AllocateValue(g, TYPE_STRING, 512);
+
+ break;
+ default:
+ break;
+ } // endswitch Op
+
+ if (jnp->Valp)
+ MulVal = AllocateValue(g, jnp->Valp);
+
return false;
} // end of SetArrayOptions
@@ -512,8 +972,21 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
else if (!Jpath)
Jpath = Name;
- pbuf = (char*)PlugSubAlloc(g, NULL, strlen(Jpath) + 1);
- strcpy(pbuf, Jpath);
+ if (To_Tdb->GetOrig()) {
+ // This is an updated column, get nodes from origin
+ for (PJCOL colp = (PJCOL)Tjp->GetColumns(); colp;
+ colp = (PJCOL)colp->GetNext())
+ if (!stricmp(Name, colp->GetName())) {
+ Nod = colp->Nod;
+ Nodes = colp->Nodes;
+ goto fin;
+ } // endif Name
+
+ sprintf(g->Message, "Cannot parse updated column %s", Name);
+ return true;
+ } // endif To_Orig
+
+ pbuf = PlugDup(g, Jpath);
// The Jpath must be analyzed
for (i = 0, p = pbuf; (p = strchr(p, ':')); i++, p++)
@@ -533,6 +1006,9 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
if (SetArrayOptions(g, p, i, Nodes[i-1].Key))
return true;
+ } else if (*p == '*') {
+ // Return JSON
+ Nodes[i].Op = OP_XX;
} else {
Nodes[i].Key = p;
Nodes[i].Op = OP_EXIST;
@@ -540,48 +1016,57 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
} // endfor i, p
+ fin:
MulVal = AllocateValue(g, Value);
Parsed = true;
return false;
} // end of ParseJpath
/***********************************************************************/
+/* MakeJson: Serialize the json item and set value to it. */
+/***********************************************************************/
+PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp)
+ {
+ if (Value->IsTypeNum()) {
+ strcpy(g->Message, "Cannot make Json for a numeric column");
+ Value->Reset();
+ } else
+ Value->SetValue_psz(Serialize(g, jsp, NULL, 0));
+
+ return Value;
+ } // end of MakeJson
+
+/***********************************************************************/
/* SetValue: Set a value from a JVALUE contains. */
/***********************************************************************/
void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
{
if (val) {
- if (Nodes[n].Op == OP_NUM)
- vp->SetValue(1);
- else {
- again:
- switch (val->GetValType()) {
- case TYPE_STRG:
- case TYPE_INTG:
- case TYPE_DBL:
- vp->SetValue_pval(val->GetValue());
- break;
- case TYPE_BOOL:
- if (vp->IsTypeNum())
- vp->SetValue(val->GetInteger() ? 1 : 0);
- else
- vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false"));
-
+ switch (val->GetValType()) {
+ case TYPE_STRG:
+ case TYPE_INTG:
+ case TYPE_DBL:
+ vp->SetValue_pval(val->GetValue());
+ break;
+ case TYPE_BOOL:
+ if (vp->IsTypeNum())
+ vp->SetValue(val->GetInteger() ? 1 : 0);
+ else
+ vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false"));
+
+ break;
+ case TYPE_JAR:
+ SetJsonValue(g, vp, val->GetArray()->GetValue(0), n);
+ break;
+ case TYPE_JOB:
+// if (!vp->IsTypeNum() || !Strict) {
+ vp->SetValue_psz(val->GetObject()->GetText(g, NULL));
break;
- case TYPE_JAR:
- val = val->GetArray()->GetValue(0);
- goto again;
- case TYPE_JOB:
- if (!vp->IsTypeNum()) {
- vp->SetValue_psz(val->GetObject()->GetText(g));
- break;
- } // endif Type
+// } // endif Type
- default:
- vp->Reset();
- } // endswitch Type
-
- } // endelse
+ default:
+ vp->Reset();
+ } // endswitch Type
} else
vp->Reset();
@@ -589,16 +1074,210 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
} // end of SetJsonValue
/***********************************************************************/
+/* ReadColumn: */
+/***********************************************************************/
+void JSONCOL::ReadColumn(PGLOBAL g)
+ {
+ if (!Tjp->SameRow || Xnod >= Tjp->SameRow)
+ Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0));
+
+ // Set null when applicable
+ if (Nullable)
+ Value->SetNull(Value->IsZero());
+
+ } // end of ReadColumn
+
+/***********************************************************************/
+/* GetColumnValue: */
+/***********************************************************************/
+PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
+ {
+ int n = Nod - 1;
+ bool expd = false;
+ PJAR arp;
+ PJVAL val = NULL;
+
+ for (; i < Nod && row; i++) {
+ if (Nodes[i].Op == OP_NUM) {
+ Value->SetValue(row->GetType() == TYPE_JAR ? row->size() : 1);
+ return(Value);
+ } else if (Nodes[i].Op == OP_XX) {
+ return MakeJson(g, row);
+ } else switch (row->GetType()) {
+ case TYPE_JOB:
+ if (!Nodes[i].Key) {
+ // Expected Array was not there
+ if (i < Nod-1)
+ continue;
+ else
+ val = new(g) JVALUE(row);
+
+ } else
+ val = ((PJOB)row)->GetValue(Nodes[i].Key);
+
+ break;
+ case TYPE_JAR:
+ arp = (PJAR)row;
+
+ if (!Nodes[i].Key) {
+ if (Nodes[i].Op == OP_EQ)
+ val = arp->GetValue(Nodes[i].Rank);
+ else if (Nodes[i].Op == OP_EXP)
+ return ExpandArray(g, arp, i);
+ else
+ return CalculateArray(g, arp, i);
+
+ } else if (i < Nod-1) {
+ strcpy(g->Message, "Unexpected array");
+ val = NULL; // Not an expected array
+ } else
+ val = arp->GetValue(0);
+
+ break;
+ case TYPE_JVAL:
+ val = (PJVAL)row;
+ break;
+ default:
+ sprintf(g->Message, "Invalid row JSON type %d", row->GetType());
+ val = NULL;
+ } // endswitch Type
+
+ if (i < Nod-1)
+ row = (val) ? val->GetJson() : NULL;
+
+ } // endfor i
+
+ SetJsonValue(g, Value, val, n);
+ return Value;
+ } // end of GetColumnValue
+
+/***********************************************************************/
+/* ExpandArray: */
+/***********************************************************************/
+PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n)
+ {
+ int ars;
+ PJVAL jvp;
+ JVALUE jval;
+
+ ars = MY_MIN(Tjp->Limit, arp->size());
+
+ if (!(jvp = arp->GetValue((Nodes[n].Rx = Nodes[n].Nx)))) {
+ strcpy(g->Message, "Logical error expanding array");
+ longjmp(g->jumper[g->jump_level], 666);
+ } // endif jvp
+
+ if (n < Nod - 1 && jvp->GetJson()) {
+ jval.SetValue(GetColumnValue(g, jvp->GetJson(), n + 1));
+ jvp = &jval;
+ } // endif n
+
+ if (n >= Tjp->NextSame) {
+ if (++Nodes[n].Nx == ars) {
+ Nodes[n].Nx = 0;
+ Xnod = 0;
+ } else
+ Xnod = n;
+
+ Tjp->NextSame = Xnod;
+ } // endif NextSame
+
+ SetJsonValue(g, Value, jvp, n);
+ return Value;
+ } // end of ExpandArray
+
+/***********************************************************************/
+/* CalculateArray: */
+/***********************************************************************/
+PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n)
+ {
+ int i, ars, nv = 0, nextsame = Tjp->NextSame;
+ bool err;
+ OPVAL op = Nodes[n].Op;
+ PVAL val[2], vp = Nodes[n].Valp;
+ PJVAL jvrp, jvp;
+ JVALUE jval;
+
+ vp->Reset();
+ ars = MY_MIN(Tjp->Limit, arp->size());
+
+ for (i = 0; i < ars; i++) {
+ jvrp = arp->GetValue(i);
+
+ do {
+ if (n < Nod - 1 && jvrp->GetJson()) {
+ Tjp->NextSame = nextsame;
+ jval.SetValue(GetColumnValue(g, jvrp->GetJson(), n + 1));
+ jvp = &jval;
+ } else
+ jvp = jvrp;
+
+ if (!nv++) {
+ SetJsonValue(g, vp, jvp, n);
+ continue;
+ } else
+ SetJsonValue(g, MulVal, jvp, n);
+
+ if (!MulVal->IsZero()) {
+ switch (op) {
+ case OP_CNC:
+ if (Nodes[n].CncVal) {
+ val[0] = Nodes[n].CncVal;
+ err = vp->Compute(g, val, 1, op);
+ } // endif CncVal
+
+ val[0] = MulVal;
+ err = vp->Compute(g, val, 1, op);
+ break;
+// case OP_NUM:
+ case OP_SEP:
+ val[0] = Nodes[n].Valp;
+ val[1] = MulVal;
+ err = vp->Compute(g, val, 2, OP_ADD);
+ break;
+ default:
+ val[0] = Nodes[n].Valp;
+ val[1] = MulVal;
+ err = vp->Compute(g, val, 2, op);
+ } // endswitch Op
+
+ if (err)
+ vp->Reset();
+
+ } // endif Zero
+
+ } while (Tjp->NextSame > nextsame);
+
+ } // endfor i
+
+ if (op == OP_SEP) {
+ // Calculate average
+ MulVal->SetValue(nv);
+ val[0] = vp;
+ val[1] = MulVal;
+
+ if (vp->Compute(g, val, 2, OP_DIV))
+ vp->Reset();
+
+ } // endif Op
+
+ Tjp->NextSame = nextsame;
+ return vp;
+ } // end of CalculateArray
+
+/***********************************************************************/
/* GetRow: Get the object containing this column. */
/***********************************************************************/
-PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
+PJSON JSONCOL::GetRow(PGLOBAL g)
{
- PJVAL val;
+ PJVAL val = NULL;
PJAR arp;
PJSON nwr, row = Tjp->Row;
for (int i = 0; i < Nod-1 && row; i++) {
- switch (row->GetType()) {
+ if (Nodes[i+1].Op == OP_XX)
+ break;
+ else switch (row->GetType()) {
case TYPE_JOB:
if (!Nodes[i].Key)
// Expected Array was not there
@@ -608,24 +1287,12 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
break;
case TYPE_JAR:
if (!Nodes[i].Key) {
- if (Nodes[i].Op != OP_NULL) {
- Ival = i;
- arp = (PJAR)row;
+ arp = (PJAR)row;
- if (mode < 2) // First pass
- Arp = arp;
-
- if (Nodes[i].Op != OP_XX) {
- if (Nodes[i].Rank)
- val = arp->GetValue(Nodes[i].Rank - 1);
- else
- val = arp->GetValue(arp == Arp ? Nx : 0);
-
- } else
- val = arp->GetValue(Tjp->SameRow);
-
- } else
- val = NULL;
+ if (Nodes[i].Op == OP_EQ)
+ val = arp->GetValue(Nodes[i].Rank);
+ else
+ val = arp->GetValue(Nodes[i].Rx);
} else {
strcpy(g->Message, "Unexpected array");
@@ -643,15 +1310,16 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
if (val) {
row = val->GetJson();
- } else if (mode == 1) { // mode write
+ } else {
// Construct missing objects
for (i++; row && i < Nod; i++) {
- if (!Nodes[i].Key) {
+ if (Nodes[i].Op == OP_XX)
+ break;
+ else if (!Nodes[i].Key)
// Construct intermediate array
nwr = new(g) JARRAY;
- } else {
+ else
nwr = new(g) JOBJECT;
- } // endif Nodes
if (row->GetType() == TYPE_JOB) {
((PJOB)row)->SetValue(g, new(g) JVALUE(nwr), Nodes[i-1].Key);
@@ -667,8 +1335,7 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
} // endfor i
break;
- } else
- row = NULL;
+ } // endelse
} // endfor i
@@ -676,131 +1343,6 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
} // end of GetRow
/***********************************************************************/
-/* ReadColumn: */
-/***********************************************************************/
-void JSONCOL::ReadColumn(PGLOBAL g)
- {
- int mode = 0, n = Nod - 1;
- PJSON row;
- PJVAL val = NULL;
-
- evenmore:
- row = GetRow(g, mode);
-
- more:
- if (row) switch (row->GetType()) {
- case TYPE_JOB:
- if (Nodes[n].Key)
- val = row->GetValue(Nodes[n].Key);
- else
- val = new(g) JVALUE(row);
-
- break;
- case TYPE_JAR:
- // Multiple column ?
- if (Nodes[n].Op != OP_NULL) {
- Arp = (PJAR)row;
- val = Arp->GetValue(Nodes[n].Rank > 0 ?
- Nodes[n].Rank - 1 :
- Nodes[n].Op == OP_XX ? Tjp->SameRow : Nx);
- Ival = n;
- } else
- val = NULL;
-
- break;
- case TYPE_JVAL:
- val = (PJVAL)row;
- break;
- default:
- sprintf(g->Message, "Wrong return value type %d", row->GetType());
- Value->Reset();
- return;
- } // endswitch Type
-
- if (!Nx /*|| (Xpd)*/)
- SetJsonValue(g, Value, val, n);
-
- if (Arp) {
- // Multiple column
- int ars = (Nodes[Ival].Rank > 0) ? 1 : MY_MIN(Tjp->Limit, Arp->size());
-
- if (Nodes[Ival].Op == OP_XX) {
- if (ars > Tjp->SameRow + 1)
- Tjp->NextSame = true; // More to come
- else {
- Tjp->NextSame = false;
- Arp = NULL;
- } // endelse
-
- } else {
- if (Nx && val) {
- SetJsonValue(g, MulVal, val, Ival);
-
- if (!MulVal->IsZero()) {
- PVAL val[2];
- bool err;
-
- switch (Nodes[Ival].Op) {
- case OP_CNC:
- if (Nodes[Ival].CncVal) {
- val[0] = Nodes[Ival].CncVal;
- err = Value->Compute(g, val, 1, Nodes[Ival].Op);
- } // endif CncVal
-
- val[0] = MulVal;
- err = Value->Compute(g, val, 1, Nodes[Ival].Op);
- break;
- case OP_NUM:
- case OP_SEP:
- val[0] = Value;
- val[1] = MulVal;
- err = Value->Compute(g, val, 2, OP_ADD);
- break;
- default:
- val[0] = Value;
- val[1] = MulVal;
- err = Value->Compute(g, val, 2, Nodes[Ival].Op);
- } // endswitch Op
-
- if (err)
- Value->Reset();
-
- } // endif Zero
-
- } // endif Nx
-
- if (ars > ++Nx) {
- if (Ival != n) {
- mode = 2;
- goto evenmore;
- } else
- goto more;
-
- } else {
- if (Nodes[Ival].Op == OP_SEP) {
- // Calculate average
- PVAL val[2];
-
- MulVal->SetValue(ars);
- val[0] = Value;
- val[1] = MulVal;
-
- if (Value->Compute(g, val, 2, OP_DIV))
- Value->Reset();
-
- } // endif Op
-
- Arp = NULL;
- Nx = 0;
- } // endif ars
-
- } // endif Op
-
- } // endif Arp
-
- } // end of ReadColumn
-
-/***********************************************************************/
/* WriteColumn: */
/***********************************************************************/
void JSONCOL::WriteColumn(PGLOBAL g)
@@ -817,10 +1359,11 @@ void JSONCOL::WriteColumn(PGLOBAL g)
if (Value->IsNull() && Tjp->Mode == MODE_INSERT)
return;
+ char *s;
PJOB objp = NULL;
PJAR arp = NULL;
PJVAL jvp = NULL;
- PJSON row = GetRow(g, 1);
+ PJSON jsp, row = GetRow(g);
JTYP type = row->GetType();
switch (row->GetType()) {
@@ -832,12 +1375,38 @@ void JSONCOL::WriteColumn(PGLOBAL g)
if (row) switch (Buf_Type) {
case TYPE_STRING:
+ if (Nodes[Nod-1].Op == OP_XX) {
+ s = Value->GetCharValue();
+
+ if (!(jsp = ParseJson(g, s, (int)strlen(s), 0))) {
+ strcpy(g->Message, s);
+ longjmp(g->jumper[g->jump_level], 666);
+ } // endif jsp
+
+ if (arp) {
+ if (Nod > 1 && Nodes[Nod-2].Op == OP_EQ)
+ arp->SetValue(g, new(g) JVALUE(jsp), Nodes[Nod-2].Rank);
+ else
+ arp->AddValue(g, new(g) JVALUE(jsp));
+
+ arp->InitArray(g);
+ } else if (objp) {
+ if (Nod > 1 && Nodes[Nod-2].Key)
+ objp->SetValue(g, new(g) JVALUE(jsp), Nodes[Nod-2].Key);
+
+ } else if (jvp)
+ jvp->SetValue(jsp);
+
+ break;
+ } // endif Op
+
+ // Passthru
case TYPE_DATE:
case TYPE_INT:
case TYPE_DOUBLE:
if (arp) {
- if (Nodes[Nod-1].Rank)
- arp->SetValue(g, new(g) JVALUE(g, Value), Nodes[Nod-1].Rank-1);
+ if (Nodes[Nod-1].Op == OP_EQ)
+ arp->SetValue(g, new(g) JVALUE(g, Value), Nodes[Nod-1].Rank);
else
arp->AddValue(g, new(g) JVALUE(g, Value));
@@ -863,18 +1432,14 @@ void JSONCOL::WriteColumn(PGLOBAL g)
/***********************************************************************/
TDBJSON::TDBJSON(PJDEF tdp, PTXF txfp) : TDBJSN(tdp, txfp)
{
- Top = NULL;
Doc = NULL;
- Objname = tdp->Objname;
Multiple = tdp->Multiple;
Done = Changed = false;
} // end of TDBJSON standard constructor
TDBJSON::TDBJSON(PJTDB tdbp) : TDBJSN(tdbp)
{
- Top = tdbp->Top;
Doc = tdbp->Doc;
- Objname = tdbp->Objname;
Multiple = tdbp->Multiple;
Done = tdbp->Done;
Changed = tdbp->Changed;
@@ -898,64 +1463,17 @@ PTDB TDBJSON::CopyOne(PTABS t)
} // end of CopyOne
/***********************************************************************/
-/* Make the document tree from a file. */
+/* Make the document tree from the object path. */
/***********************************************************************/
int TDBJSON::MakeNewDoc(PGLOBAL g)
{
// Create a void table that will be populated
Doc = new(g) JARRAY;
- if (Objname) {
- // Parse and allocate Objname item(s)
- char *p;
- char *objpath = (char*)PlugSubAlloc(g, NULL, strlen(Objname)+1);
- int i;
- PJOB objp;
- PJAR arp;
- PJVAL val = NULL;
-
- strcpy(objpath, Objname);
- Top = NULL;
-
- for (; objpath; objpath = p) {
- if ((p = strchr(objpath, ':')))
- *p++ = 0;
-
- if (*objpath != '[') {
- objp = new(g) JOBJECT;
-
- if (!Top)
- Top = objp;
-
- if (val)
- val->SetValue(objp);
-
- val = new(g) JVALUE;
- objp->SetValue(g, val, objpath);
- } else if (objpath[strlen(objpath)-1] == ']') {
- arp = new(g) JARRAY;
-
- if (!Top)
- Top = arp;
-
- if (val)
- val->SetValue(arp);
-
- val = new(g) JVALUE;
- i = atoi(objpath+1) - 1;
- arp->SetValue(g, val, i);
- arp->InitArray(g);
- } else {
- sprintf(g->Message, "Invalid Table path %s", Objname);
- return RC_FX;
- } // endif objpath
-
- } // endfor p
-
- val->SetValue(Doc);
- } else
- Top = Doc;
+ if (MakeTopTree(g, Doc))
+ return RC_FX;
+ Done = true;
return RC_OK;
} // end of MakeNewDoc
@@ -964,10 +1482,9 @@ int TDBJSON::MakeNewDoc(PGLOBAL g)
/***********************************************************************/
int TDBJSON::MakeDocument(PGLOBAL g)
{
- char *p, *memory, *objpath, *key, filename[_MAX_PATH];
+ char *p, *memory, *objpath, *key = NULL;
int len, i = 0;
- HANDLE hFile;
- MEMMAP mm;
+ MODE mode = Mode;
PJSON jsp;
PJOB objp = NULL;
PJAR arp = NULL;
@@ -975,70 +1492,38 @@ int TDBJSON::MakeDocument(PGLOBAL g)
if (Done)
return RC_OK;
- else
- Done = true;
-
- // Now open the JSON file
- PlugSetPath(filename, Txfp->To_File, GetPath());
-
- /*********************************************************************/
- /* Create the mapping file object. */
- /*********************************************************************/
- hFile = CreateFileMap(g, filename, &mm, MODE_READ, false);
-
- if (hFile == INVALID_HANDLE_VALUE) {
- DWORD drc = GetLastError();
-
- if (drc != ENOENT || Mode != MODE_INSERT) {
- if (!(*g->Message))
- sprintf(g->Message, MSG(OPEN_MODE_ERROR),
- "map", (int)drc, filename);
-
- return RC_FX;
- } else
- return MakeNewDoc(g);
-
- } // endif hFile
/*********************************************************************/
- /* Get the file size (assuming file is smaller than 4 GB) */
+ /* Create the mapping file object in mode read. */
/*********************************************************************/
- len = mm.lenL;
- memory = (char *)mm.memory;
+ Mode = MODE_READ;
- if (!len) { // Empty file
- CloseFileHandle(hFile);
- CloseMemMap(memory, len);
+ if (!Txfp->OpenTableFile(g)) {
+ PFBLOCK fp = Txfp->GetTo_Fb();
- if (Mode == MODE_INSERT)
- return MakeNewDoc(g);
-
- } // endif len
+ if (fp) {
+ len = fp->Length;
+ memory = fp->Memory;
+ } else {
+ Mode = mode; // Restore saved Mode
+ return MakeNewDoc(g);
+ } // endif fp
- if (!memory) {
- CloseFileHandle(hFile);
- sprintf(g->Message, MSG(MAP_VIEW_ERROR), filename, GetLastError());
+ } else
return RC_FX;
- } // endif Memory
-
- CloseFileHandle(hFile); // Not used anymore
- hFile = INVALID_HANDLE_VALUE; // For Fblock
/*********************************************************************/
/* Parse the json file and allocate its tree structure. */
/*********************************************************************/
g->Message[0] = 0;
jsp = Top = ParseJson(g, memory, len, Pretty);
- CloseMemMap(memory, len);
+ Txfp->CloseTableFile(g, false);
+ Mode = mode; // Restore saved Mode
if (!jsp && g->Message[0])
return RC_FX;
- if (Objname) {
- objpath = (char*)PlugSubAlloc(g, NULL, strlen(Objname) + 1);
- strcpy(objpath, Objname);
- } else
- objpath = NULL;
+ objpath = PlugDup(g, Objname);
/*********************************************************************/
/* Find the table in the tree structure. */
@@ -1071,7 +1556,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
arp = jsp->GetArray();
objp = NULL;
- i = atoi(objpath+1) - 1;
+ i = atoi(objpath+1) - B;
val = arp->GetValue(i);
if (!val) {
@@ -1110,6 +1595,7 @@ int TDBJSON::MakeDocument(PGLOBAL g)
} // endif jsp
+ Done = true;
return RC_OK;
} // end of MakeDocument
@@ -1156,7 +1642,7 @@ void TDBJSON::ResetSize(void)
/***********************************************************************/
/* TDBJSON is not indexable. */
/***********************************************************************/
-int TDBJSON::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add)
+int TDBJSON::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool)
{
if (pxdf) {
strcpy(g->Message, "JSON not indexable when pretty = 2");
@@ -1167,6 +1653,51 @@ int TDBJSON::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add)
} // end of MakeIndex
/***********************************************************************/
+/* Return the position in the table. */
+/***********************************************************************/
+int TDBJSON::GetRecpos(void)
+ {
+#if 0
+ union {
+ uint Rpos;
+ BYTE Spos[4];
+ };
+
+ Rpos = htonl(Fpos);
+ Spos[0] = (BYTE)NextSame;
+ return Rpos;
+#endif // 0
+ return Fpos;
+ } // end of GetRecpos
+
+/***********************************************************************/
+/* Set the position in the table. */
+/***********************************************************************/
+bool TDBJSON::SetRecpos(PGLOBAL, int recpos)
+ {
+#if 0
+ union {
+ uint Rpos;
+ BYTE Spos[4];
+ };
+
+ Rpos = recpos;
+ NextSame = Spos[0];
+ Spos[0] = 0;
+ Fpos = (signed)ntohl(Rpos);
+
+//if (Fpos != (signed)ntohl(Rpos)) {
+// Fpos = ntohl(Rpos);
+// same = false;
+//} else
+// same = true;
+#endif // 0
+
+ Fpos = recpos - 1;
+ return false;
+ } // end of SetRecpos
+
+/***********************************************************************/
/* JSON Access Method opening routine. */
/***********************************************************************/
bool TDBJSON::OpenDB(PGLOBAL g)
@@ -1175,13 +1706,7 @@ bool TDBJSON::OpenDB(PGLOBAL g)
/*******************************************************************/
/* Table already open replace it at its beginning. */
/*******************************************************************/
- for (PJCOL cp = (PJCOL)Columns; cp; cp = (PJCOL)cp->GetNext()) {
- cp->Nx = 0;
- cp->Arp = NULL;
- } // endfor cp
-
Fpos= -1;
- Spos = 0;
NextSame = false;
SameRow = 0;
return false;
@@ -1210,14 +1735,16 @@ bool TDBJSON::OpenDB(PGLOBAL g)
/***********************************************************************/
/* ReadDB: Data Base read routine for JSON access method. */
/***********************************************************************/
-int TDBJSON::ReadDB(PGLOBAL g)
+int TDBJSON::ReadDB(PGLOBAL)
{
- int rc;
+ int rc;
N++;
if (NextSame) {
- SameRow++;
+ SameRow = NextSame;
+ NextSame = false;
+ M++;
rc = RC_OK;
} else if (++Fpos < (signed)Doc->size()) {
Row = Doc->GetValue(Fpos);
@@ -1226,6 +1753,7 @@ int TDBJSON::ReadDB(PGLOBAL g)
Row = ((PJVAL)Row)->GetJson();
SameRow = 0;
+ M = 1;
rc = RC_OK;
} else
rc = RC_EF;
@@ -1257,9 +1785,10 @@ int TDBJSON::WriteDB(PGLOBAL g)
return RC_FX;
} else { // if (Jmode == MODE_VALUE)
- if (Mode == MODE_INSERT)
+ if (Mode == MODE_INSERT) {
Doc->AddValue(g, (PJVAL)Row);
- else if (Doc->SetValue(g, (PJVAL)Row, Fpos))
+ Row = new(g) JVALUE;
+ } else if (Doc->SetValue(g, (PJVAL)Row, Fpos))
return RC_FX;
} // endif Jmode
@@ -1319,4 +1848,23 @@ void TDBJSON::CloseDB(PGLOBAL g)
} // end of CloseDB
-/* -------------------------- End of json --------------------------- */
+/* ---------------------------TDBJCL class --------------------------- */
+
+/***********************************************************************/
+/* TDBJCL class constructor. */
+/***********************************************************************/
+TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp)
+ {
+ Topt = tdp->GetTopt();
+ Db = (char*)tdp->GetDB();
+ } // end of TDBJCL constructor
+
+/***********************************************************************/
+/* GetResult: Get the list the JSON file columns. */
+/***********************************************************************/
+PQRYRES TDBJCL::GetResult(PGLOBAL g)
+ {
+ return JSONColumns(g, Db, Topt, false);
+ } // end of GetResult
+
+/* --------------------------- End of json --------------------------- */
diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h
index 68f79a1526a..4505d30a21c 100644
--- a/storage/connect/tabjson.h
+++ b/storage/connect/tabjson.h
@@ -1,5 +1,5 @@
/*************** tabjson H Declares Source Code File (.H) **************/
-/* Name: tabjson.h Version 1.0 */
+/* Name: tabjson.h Version 1.1 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* */
@@ -16,8 +16,6 @@ typedef class JSONDEF *PJDEF;
typedef class TDBJSON *PJTDB;
typedef class JSONCOL *PJCOL;
-class TDBJSN;
-
/***********************************************************************/
/* The JSON tree node. Can be an Object or an Array. */
/***********************************************************************/
@@ -25,7 +23,10 @@ typedef struct _jnode {
PSZ Key; // The key used for object
OPVAL Op; // Operator used for this node
PVAL CncVal; // To cont value used for OP_CNC
+ PVAL Valp; // The internal array VALUE
int Rank; // The rank in array
+ int Rx; // Read row number
+ int Nx; // Next to read row number
} JNODE, *PJNODE;
/***********************************************************************/
@@ -34,6 +35,8 @@ typedef struct _jnode {
class JSONDEF : public DOSDEF { /* Table description */
friend class TDBJSON;
friend class TDBJSN;
+ friend class TDBJCL;
+ friend PQRYRES JSONColumns(PGLOBAL, char*, PTOS, bool);
public:
// Constructor
JSONDEF(void);
@@ -52,6 +55,8 @@ class JSONDEF : public DOSDEF { /* Table description */
char *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; /* Tne array index base */
bool Strict; /* Strict syntax checking */
}; // end of JSONDEF
@@ -69,40 +74,48 @@ class TDBJSN : public TDBDOS {
TDBJSN(TDBJSN *tdbp);
// Implementation
- virtual AMT GetAmType(void) {return TYPE_AM_JSN;}
- virtual bool SkipHeader(PGLOBAL g);
- virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBJSN(this);}
+ virtual AMT GetAmType(void) {return TYPE_AM_JSN;}
+ virtual bool SkipHeader(PGLOBAL g);
+ virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBJSN(this);}
+ PJSON GetRow(void) {return Row;}
// Methods
- virtual PTDB CopyOne(PTABS t);
- virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
- virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
- virtual int RowNumber(PGLOBAL g, BOOL b = FALSE)
- {return (b) ? N : Fpos + 1;}
+ virtual PTDB CopyOne(PTABS t);
+ virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual PCOL InsertSpecialColumn(PCOL colp);
+ virtual int RowNumber(PGLOBAL g, bool b = FALSE)
+ {return (b) ? M : N;}
// Database routines
- virtual int Cardinality(PGLOBAL g);
- virtual int GetMaxSize(PGLOBAL g);
- virtual bool OpenDB(PGLOBAL g);
- virtual bool PrepareWriting(PGLOBAL g);
- virtual int ReadDB(PGLOBAL g);
+ virtual int Cardinality(PGLOBAL g);
+ virtual int GetMaxSize(PGLOBAL g);
+ virtual bool OpenDB(PGLOBAL g);
+ virtual bool PrepareWriting(PGLOBAL g);
+ virtual int ReadDB(PGLOBAL g);
protected:
+ PJSON FindRow(PGLOBAL g);
+ int MakeTopTree(PGLOBAL g, PJSON jsp);
+
// Members
+ PJSON Top; // The top JSON tree
PJSON Row; // The current row
+ PJSON Val; // The value of the current row
PJCOL Colp; // The multiple column
JMODE Jmode; // MODE_OBJECT by default
+ char *Objname; // The table object name
char *Xcol; // Name of expandable column
int Fpos; // The current row index
- int Spos; // DELETE start index
int N; // The current Rownum
+ int M; // Index of multiple value
int Limit; // Limit of multiple values
int Pretty; // Depends on file structure
- bool Strict; // Strict syntax checking
- bool NextSame; // Same next row
- bool Comma; // Row has final comma
+ int NextSame; // Same next row
int SameRow; // Same row nb
int Xval; // Index of expandable array
+ int B; // Array index base
+ bool Strict; // Strict syntax checking
+ bool Comma; // Row has final comma
}; // end of class TDBJSN
/* -------------------------- JSONCOL class -------------------------- */
@@ -130,8 +143,12 @@ class JSONCOL : public DOSCOL {
protected:
bool CheckExpand(PGLOBAL g, int i, PSZ nm, bool b);
bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm);
- PJSON GetRow(PGLOBAL g, int mode);
+ PVAL GetColumnValue(PGLOBAL g, PJSON row, int i);
+ PVAL ExpandArray(PGLOBAL g, PJAR arp, int n);
+ PVAL CalculateArray(PGLOBAL g, PJAR arp, int n);
+ PVAL MakeJson(PGLOBAL g, PJSON jsp);
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n);
+ PJSON GetRow(PGLOBAL g);
// Default constructor not to be used
JSONCOL(void) {}
@@ -139,12 +156,10 @@ class JSONCOL : public DOSCOL {
// Members
TDBJSN *Tjp; // To the JSN table block
PVAL MulVal; // To value used by multiple column
- PJAR Arp; // The intermediate array
char *Jpath; // The json path
- JNODE *Nodes ; // The intermediate objects
+ JNODE *Nodes; // The intermediate objects
int Nod; // The number of intermediate objects
- int Ival; // Index of multiple values
- int Nx; // The last read sub-row
+ int Xnod; // Index of multiple values
bool Xpd; // True for expandable column
bool Parsed; // True when parsed
}; // end of class JSONCOL
@@ -164,6 +179,7 @@ class TDBJSON : public TDBJSN {
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_JSON;}
virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBJSON(this);}
+ PJAR GetDoc(void) {return Doc;}
// Methods
virtual PTDB CopyOne(PTABS t);
@@ -172,26 +188,43 @@ class TDBJSON : public TDBJSN {
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual void ResetSize(void);
- virtual int GetRecpos(void) {return Fpos;}
+ virtual int GetProgCur(void) {return N;}
+ virtual int GetRecpos(void);
+ virtual bool SetRecpos(PGLOBAL g, int recpos);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual bool PrepareWriting(PGLOBAL g) {return false;}
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
+ int MakeDocument(PGLOBAL g);
// Optimization routines
virtual int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add);
protected:
int MakeNewDoc(PGLOBAL g);
- int MakeDocument(PGLOBAL g);
// Members
- PJSON Top; // The file JSON tree
PJAR Doc; // The document array
- char *Objname; // The table object name
int Multiple; // 0: No 1: DIR 2: Section 3: filelist
bool Done; // True when document parsing is done
bool Changed; // After Update, Insert or Delete
}; // end of class TDBJSON
+
+/***********************************************************************/
+/* This is the class declaration for the JSON catalog table. */
+/***********************************************************************/
+class TDBJCL : public TDBCAT {
+ public:
+ // Constructor
+ TDBJCL(PJDEF tdp);
+
+ protected:
+ // Specific routines
+ virtual PQRYRES GetResult(PGLOBAL g);
+
+ // Members
+ PTOS Topt;
+ char *Db;
+ }; // end of class TDBJCL
diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp
index cbd5910d8c8..933e072c1bb 100644
--- a/storage/connect/table.cpp
+++ b/storage/connect/table.cpp
@@ -1,7 +1,7 @@
/************** Table C++ Functions Source Code File (.CPP) ************/
/* Name: TABLE.CPP Version 2.7 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 1999-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 1999-2015 */
/* */
/* This file contains the TBX, TDB and OPJOIN classes functions. */
/***********************************************************************/
@@ -74,7 +74,7 @@ TDB::TDB(PTDB tdbp) : Tdb_No(++Tnum)
/***********************************************************************/
/* RowNumber: returns the current row ordinal number. */
/***********************************************************************/
-int TDB::RowNumber(PGLOBAL g, bool b)
+int TDB::RowNumber(PGLOBAL g, bool)
{
sprintf(g->Message, MSG(ROWID_NOT_IMPL), GetAmName(g, GetAmType()));
return 0;
@@ -122,7 +122,7 @@ void TDB::Print(PGLOBAL g, FILE *f, uint n)
} // end of Print
-void TDB::Print(PGLOBAL g, char *ps, uint z)
+void TDB::Print(PGLOBAL, char *ps, uint)
{
sprintf(ps, "R%d.%s", Tdb_No, Name);
} // end of Print
@@ -263,7 +263,7 @@ PCOL TDBASE::ColDB(PGLOBAL g, PSZ name, int num)
/***********************************************************************/
/* InsertSpecialColumn: Put a special column ahead of the column list.*/
/***********************************************************************/
-PCOL TDBASE::InsertSpecialColumn(PGLOBAL g, PCOL colp)
+PCOL TDBASE::InsertSpecialColumn(PCOL colp)
{
if (!colp->IsSpecial())
return NULL;
@@ -327,7 +327,7 @@ PCOL TDBASE::InsertSpcBlk(PGLOBAL g, PCOLDEF cdp)
return NULL;
} // endif's name
- if (!(colp = InsertSpecialColumn(g, colp))) {
+ if (!(colp = InsertSpecialColumn(colp))) {
sprintf(g->Message, MSG(BAD_SPECIAL_COL), name);
return NULL;
} // endif Insert
@@ -338,7 +338,7 @@ PCOL TDBASE::InsertSpcBlk(PGLOBAL g, PCOLDEF cdp)
/***********************************************************************/
/* ResetTableOpt: Wrong for this table type. */
/***********************************************************************/
-int TDBASE::ResetTableOpt(PGLOBAL g, bool dop, bool dox)
+int TDBASE::ResetTableOpt(PGLOBAL g, bool, bool)
{
strcpy(g->Message, "This table is not indexable");
return RC_INFO;
@@ -365,7 +365,7 @@ void TDBASE::ResetKindex(PGLOBAL g, PKXBASE kxp)
/***********************************************************************/
/* SetRecpos: Replace the table at the specified position. */
/***********************************************************************/
-bool TDBASE::SetRecpos(PGLOBAL g, int recpos)
+bool TDBASE::SetRecpos(PGLOBAL g, int)
{
strcpy(g->Message, MSG(SETRECPOS_NIY));
return true;
@@ -386,7 +386,7 @@ void TDBASE::PrintAM(FILE *f, char *m)
/* Two questions here: exact meaning of U_J_INT ? */
/* Why is the eventual reference to To_Key_Col not marked U_J_EXT ? */
/***********************************************************************/
-void TDBASE::MarkDB(PGLOBAL g, PTDB tdb2)
+void TDBASE::MarkDB(PGLOBAL, PTDB tdb2)
{
if (trace)
htrc("DOS MarkDB: tdbp=%p tdb2=%p\n", this, tdb2);
@@ -453,7 +453,7 @@ bool TDBCAT::Initialize(PGLOBAL g)
/***********************************************************************/
/* CAT: Get the number of properties. */
/***********************************************************************/
-int TDBCAT::GetMaxSize(PGLOBAL g)
+int TDBCAT::GetMaxSize(PGLOBAL g __attribute__((unused)))
{
if (MaxSize < 0) {
// if (Initialize(g))
@@ -528,7 +528,7 @@ bool TDBCAT::InitCol(PGLOBAL g)
/***********************************************************************/
/* SetRecpos: Replace the table at the specified position. */
/***********************************************************************/
-bool TDBCAT::SetRecpos(PGLOBAL g, int recpos)
+bool TDBCAT::SetRecpos(PGLOBAL, int recpos)
{
N = recpos - 1;
return false;
@@ -537,7 +537,7 @@ bool TDBCAT::SetRecpos(PGLOBAL g, int recpos)
/***********************************************************************/
/* Data Base read routine for CAT access method. */
/***********************************************************************/
-int TDBCAT::ReadDB(PGLOBAL g)
+int TDBCAT::ReadDB(PGLOBAL)
{
return (++N < Qrp->Nblin) ? RC_OK : RC_EF;
} // end of ReadDB
@@ -554,7 +554,7 @@ int TDBCAT::WriteDB(PGLOBAL g)
/***********************************************************************/
/* Data Base delete line routine for CAT access methods. */
/***********************************************************************/
-int TDBCAT::DeleteDB(PGLOBAL g, int irc)
+int TDBCAT::DeleteDB(PGLOBAL g, int)
{
strcpy(g->Message, "Delete not enabled for CAT tables");
return RC_FX;
@@ -563,7 +563,7 @@ int TDBCAT::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
/* Data Base close routine for WMI access method. */
/***********************************************************************/
-void TDBCAT::CloseDB(PGLOBAL g)
+void TDBCAT::CloseDB(PGLOBAL)
{
// Nothing to do
} // end of CloseDB
@@ -584,9 +584,13 @@ CATCOL::CATCOL(PCOLDEF cdp, PTDB tdbp, int n)
/***********************************************************************/
/* Read the next Data Source elements. */
/***********************************************************************/
-void CATCOL::ReadColumn(PGLOBAL g)
+void CATCOL::ReadColumn(PGLOBAL)
{
// Get the value of the Name or Description property
- Value->SetValue_pvblk(Crp->Kdata, Tdbp->N);
+ if (Crp->Kdata)
+ Value->SetValue_pvblk(Crp->Kdata, Tdbp->N);
+ else
+ Value->Reset();
+
} // end of ReadColumn
diff --git a/storage/connect/tabmac.cpp b/storage/connect/tabmac.cpp
index f072465ced5..e6e2abb54e2 100644
--- a/storage/connect/tabmac.cpp
+++ b/storage/connect/tabmac.cpp
@@ -3,12 +3,12 @@
/* From the article and sample code by Khalid Shaikh. */
/* TABMAC: virtual table to get the list of MAC addresses. */
/***********************************************************************/
-#if defined(WIN32)
+#if defined(__WIN__)
#include "my_global.h"
//#include <iphlpapi.h>
-#else // !WIN32
-#error This is a WIN32 only table type
-#endif // !WIN32
+#else // !__WIN__
+#error This is a WINDOWS only table type
+#endif // !__WIN__
#include "global.h"
#include "plgdbsem.h"
//#include "catalog.h"
diff --git a/storage/connect/tabmac.h b/storage/connect/tabmac.h
index 5e6c98d68fb..f9a66e82eaa 100644
--- a/storage/connect/tabmac.h
+++ b/storage/connect/tabmac.h
@@ -1,11 +1,11 @@
// TABMAC.H Olivier Bertrand 2011-2012
// MAC: virtual table to Get Mac Addresses via GetAdaptersInfo
-#if defined(WIN32)
+#if defined(__WIN__)
#include <windows.h>
#include <iphlpapi.h>
-#else // !WIN32
-#error This is a WIN32 only table TYPE
-#endif // !WIN32
+#else // !__WIN__
+#error This is a WINDOWS only table TYPE
+#endif // !__WIN__
/***********************************************************************/
/* Definitions. */
diff --git a/storage/connect/tabmul.cpp b/storage/connect/tabmul.cpp
index 415a1523d30..3008ca1b8ca 100644
--- a/storage/connect/tabmul.cpp
+++ b/storage/connect/tabmul.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to PlugDB Software Development 2003 - 2012 */
+/* (C) Copyright to PlugDB Software Development 2003 - 2015 */
/* Author: Olivier BERTRAND */
/* */
/* WHAT THIS PROGRAM DOES: */
@@ -37,7 +37,7 @@
/* Include relevant section of system dependant header files. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <stdlib.h>
#include <stdio.h>
#if defined(__BORLANDC__)
@@ -145,7 +145,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
/*******************************************************************/
/* To_File is a multiple name with special characters */
/*******************************************************************/
-#if defined(WIN32)
+#if defined(__WIN__)
char drive[_MAX_DRIVE], direc[_MAX_DIR];
WIN32_FIND_DATA FileData;
HANDLE hSearch;
@@ -171,9 +171,10 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
} // endif hSearch
while (n < PFNZ) {
- strcat(strcat(strcpy(filename, drive), direc), FileData.cFileName);
- pfn[n] = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
- strcpy(pfn[n++], filename);
+ if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ strcat(strcat(strcpy(filename, drive), direc), FileData.cFileName);
+ pfn[n++] = PlugDup(g, filename);
+ } // endif dwFileAttributes
if (!FindNextFile(hSearch, &FileData)) {
rc = GetLastError();
@@ -195,7 +196,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
return true;
} // endif FindClose
-#else // !WIN32
+#else // !__WIN__
struct stat fileinfo;
char fn[FN_REFLEN], direc[FN_REFLEN], pattern[FN_HEADLEN], ftype[FN_EXTLEN];
DIR *dir;
@@ -239,8 +240,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
continue; // Not a match
strcat(strcpy(filename, direc), entry->d_name);
- pfn[n] = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
- strcpy(pfn[n++], filename);
+ pfn[n++] = PlugDup(g, filename);
if (trace)
htrc("Adding pfn[%d] %s\n", n, filename);
@@ -249,7 +249,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
// Close the dir handle.
closedir(dir);
-#endif // !WIN32
+#endif // !__WIN__
} else {
/*******************************************************************/
@@ -269,7 +269,7 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
p = filename + strlen(filename) - 1;
-#if defined(UNIX)
+#if !defined(__WIN__)
// Data files can be imported from Windows (having CRLF)
if (*p == '\n' || *p == '\r') {
// is this enough for Unix ???
@@ -292,13 +292,12 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
*(++p) = '\0';
// Suballocate the file name
- pfn[n] = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
- strcpy(pfn[n++], filename);
+ pfn[n++] = PlugDup(g, filename);
} // endfor n
} // endif Mul
-#if defined(WIN32)
+#if defined(__WIN__)
suite:
#endif
@@ -562,7 +561,7 @@ int TDBMUL::WriteDB(PGLOBAL g)
/***********************************************************************/
/* Data Base delete line routine for MUL access method. */
/***********************************************************************/
-int TDBMUL::DeleteDB(PGLOBAL g, int irc)
+int TDBMUL::DeleteDB(PGLOBAL g, int)
{
// When implementing DELETE_MODE InitFileNames must be updated to
// eliminate CRLF under Windows if the file is read in binary.
@@ -587,7 +586,7 @@ void TDBMUL::CloseDB(PGLOBAL g)
/***********************************************************************/
/* DefineAM: define specific AM block values from XDB file. */
/***********************************************************************/
-bool DIRDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+bool DIRDEF::DefineAM(PGLOBAL g, LPCSTR, int)
{
Desc = Fn = GetStringCatInfo(g, "Filename", NULL);
Incl = (GetIntCatInfo("Subdir", 0) != 0);
@@ -598,7 +597,7 @@ bool DIRDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
/* GetTable: makes a new Table Description Block. */
/***********************************************************************/
-PTDB DIRDEF::GetTable(PGLOBAL g, MODE m)
+PTDB DIRDEF::GetTable(PGLOBAL g, MODE)
{
#if 0
if (Huge)
@@ -621,17 +620,17 @@ TDBDIR::TDBDIR(PDIRDEF tdp) : TDBASE(tdp)
{
To_File = tdp->Fn;
iFile = 0;
-#if defined(WIN32)
+#if defined(__WIN__)
memset(&FileData, 0, sizeof(_finddata_t));
Hsearch = -1;
*Drive = '\0';
-#else // !WIN32
+#else // !__WIN__
memset(&Fileinfo, 0, sizeof(struct stat));
Entry = NULL;
Dir = NULL;
Done = false;
*Pattern = '\0';
-#endif // !WIN32
+#endif // !__WIN__
*Fpath = '\0';
*Direc = '\0';
*Fname = '\0';
@@ -642,17 +641,17 @@ TDBDIR::TDBDIR(PTDBDIR tdbp) : TDBASE(tdbp)
{
To_File = tdbp->To_File;
iFile = tdbp->iFile;
-#if defined(WIN32)
+#if defined(__WIN__)
FileData = tdbp->FileData;
Hsearch = tdbp->Hsearch;
strcpy(Drive, tdbp->Drive);
-#else // !WIN32
+#else // !__WIN__
Fileinfo = tdbp->Fileinfo;
Entry = tdbp->Entry;
Dir = tdbp->Dir;
Done = tdbp->Done;
strcpy(Pattern, tdbp->Pattern);
-#endif // !WIN32
+#endif // !__WIN__
strcpy(Direc, tdbp->Direc);
strcpy(Fname, tdbp->Fname);
strcpy(Ftype, tdbp->Ftype);
@@ -676,7 +675,7 @@ char* TDBDIR::Path(PGLOBAL g)
{
PCATLG cat = PlgGetCatalog(g);
-#if defined(WIN32)
+#if defined(__WIN__)
if (!*Drive) {
PlugSetPath(Fpath, To_File, ((PTABDEF)To_Def)->GetPath());
_splitpath(Fpath, Drive, Direc, Fname, Ftype);
@@ -684,7 +683,7 @@ char* TDBDIR::Path(PGLOBAL g)
_makepath(Fpath, Drive, Direc, Fname, Ftype); // Usefull ???
return Fpath;
-#else // !WIN32
+#else // !__WIN__
if (!Done) {
PlugSetPath(Fpath, To_File, ((PTABDEF)To_Def)->GetPath());
_splitpath(Fpath, NULL, Direc, Fname, Ftype);
@@ -693,7 +692,7 @@ char* TDBDIR::Path(PGLOBAL g)
} // endif Done
return Pattern;
-#endif // !WIN32
+#endif // !__WIN__
} // end of Path
/***********************************************************************/
@@ -711,7 +710,7 @@ int TDBDIR::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
int n = -1;
-#if defined(WIN32)
+#if defined(__WIN__)
int h;
// Start searching files in the target directory.
@@ -727,7 +726,7 @@ int TDBDIR::GetMaxSize(PGLOBAL g)
} else
n = 0;
-#else // !WIN32
+#else // !__WIN__
Path(g);
// Start searching files in the target directory.
@@ -751,7 +750,7 @@ int TDBDIR::GetMaxSize(PGLOBAL g)
// Close the DIR handle.
closedir(Dir);
-#endif // !WIN32
+#endif // !__WIN__
MaxSize = n;
} // endif MaxSize
@@ -777,10 +776,10 @@ bool TDBDIR::OpenDB(PGLOBAL g)
} // endif use
Use = USE_OPEN;
-#if !defined(WIN32)
+#if !defined(__WIN__)
Path(g); // Be sure it is done
Dir = NULL; // For ReadDB
-#endif // !WIN32
+#endif // !__WIN__
return false;
} // end of OpenDB
@@ -791,7 +790,7 @@ int TDBDIR::ReadDB(PGLOBAL g)
{
int rc = RC_OK;
-#if defined(WIN32)
+#if defined(__WIN__)
if (Hsearch == -1) {
/*******************************************************************/
/* Start searching files in the target directory. The use of the */
@@ -849,7 +848,7 @@ int TDBDIR::ReadDB(PGLOBAL g)
rc = RC_EF;
} // endif Entry
-#endif // !WIN32
+#endif // !__WIN__
return rc;
} // end of ReadDB
@@ -866,7 +865,7 @@ int TDBDIR::WriteDB(PGLOBAL g)
/***********************************************************************/
/* Data Base delete line routine for DIR access method. */
/***********************************************************************/
-int TDBDIR::DeleteDB(PGLOBAL g, int irc)
+int TDBDIR::DeleteDB(PGLOBAL g, int)
{
strcpy(g->Message, MSG(TABDIR_READONLY));
return RC_FX; // NIY
@@ -875,19 +874,19 @@ int TDBDIR::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
/* Data Base close routine for MUL access method. */
/***********************************************************************/
-void TDBDIR::CloseDB(PGLOBAL g)
+void TDBDIR::CloseDB(PGLOBAL)
{
-#if defined(WIN32)
+#if defined(__WIN__)
// Close the search handle.
_findclose(Hsearch);
Hsearch = -1;
-#else // !WIN32
+#else // !__WIN__
// Close the DIR handle
if (Dir) {
closedir(Dir);
Dir = NULL;
} // endif dir
-#endif // !WIN32
+#endif // !__WIN__
iFile = 0;
} // end of CloseDB
@@ -896,7 +895,7 @@ void TDBDIR::CloseDB(PGLOBAL g)
/***********************************************************************/
/* DIRCOL public constructor. */
/***********************************************************************/
-DIRCOL::DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+DIRCOL::DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ)
: COLBLK(cdp, tdbp, i)
{
if (cprec) {
@@ -936,19 +935,19 @@ void DIRCOL::ReadColumn(PGLOBAL g)
/* Retrieve the information corresponding to the column number. */
/*********************************************************************/
switch (N) {
-#if defined(WIN32)
+#if defined(__WIN__)
case 0: Value->SetValue_psz(tdbp->Drive); break;
-#endif // WIN32
+#endif // __WIN__
case 1: Value->SetValue_psz(tdbp->Direc); break;
case 2: Value->SetValue_psz(tdbp->Fname); break;
case 3: Value->SetValue_psz(tdbp->Ftype); break;
-#if defined(WIN32)
+#if defined(__WIN__)
case 4: Value->SetValue((int)tdbp->FileData.attrib); break;
case 5: Value->SetValue((int)tdbp->FileData.size); break;
case 6: Value->SetValue((int)tdbp->FileData.time_write); break;
case 7: Value->SetValue((int)tdbp->FileData.time_create); break;
case 8: Value->SetValue((int)tdbp->FileData.time_access); break;
-#else // !WIN32
+#else // !__WIN__
case 4: Value->SetValue((int)tdbp->Fileinfo.st_mode); break;
case 5: Value->SetValue((int)tdbp->Fileinfo.st_size); break;
case 6: Value->SetValue((int)tdbp->Fileinfo.st_mtime); break;
@@ -956,7 +955,7 @@ void DIRCOL::ReadColumn(PGLOBAL g)
case 8: Value->SetValue((int)tdbp->Fileinfo.st_atime); break;
case 9: Value->SetValue((int)tdbp->Fileinfo.st_uid); break;
case 10: Value->SetValue((int)tdbp->Fileinfo.st_gid); break;
-#endif // !WIN32
+#endif // !__WIN__
default:
sprintf(g->Message, MSG(INV_DIRCOL_OFST), N);
longjmp(g->jumper[g->jump_level], GetAmType());
@@ -1007,7 +1006,7 @@ int TDBSDR::FindInDir(PGLOBAL g)
size_t m = strlen(Direc);
// Start searching files in the target directory.
-#if defined(WIN32)
+#if defined(__WIN__)
int h = _findfirst(Path(g), &FileData);
if (h != -1) {
@@ -1040,7 +1039,7 @@ int TDBSDR::FindInDir(PGLOBAL g)
// Close the search handle.
_findclose(h);
} // endif h
-#else // !WIN32
+#else // !__WIN__
int k;
DIR *dir = opendir(Direc);
@@ -1074,7 +1073,7 @@ int TDBSDR::FindInDir(PGLOBAL g)
// Close the DIR handle.
closedir(dir);
-#endif // !WIN32
+#endif // !__WIN__
return n;
} // end of FindInDir
@@ -1090,13 +1089,13 @@ bool TDBSDR::OpenDB(PGLOBAL g)
Sub = (PSUBDIR)PlugSubAlloc(g, NULL, sizeof(SUBDIR));
Sub->Next = NULL;
Sub->Prev = NULL;
-#if defined(WIN32)
+#if defined(__WIN__)
Sub->H = -1;
Sub->Len = strlen(Direc);
-#else // !WIN32
+#else // !__WIN__
Sub->D = NULL;
Sub->Len = 0;
-#endif // !WIN32
+#endif // !__WIN__
} // endif To_Sub
return TDBDIR::OpenDB(g);
@@ -1109,7 +1108,7 @@ int TDBSDR::ReadDB(PGLOBAL g)
{
int rc;
-#if defined(WIN32)
+#if defined(__WIN__)
again:
rc = TDBDIR::ReadDB(g);
@@ -1161,7 +1160,7 @@ int TDBSDR::ReadDB(PGLOBAL g)
} // endif H
} // endif rc
-#else // !WIN32
+#else // !__WIN__
rc = RC_NF;
again:
@@ -1218,7 +1217,7 @@ int TDBSDR::ReadDB(PGLOBAL g)
} // endif Entry
-#endif // !WIN32
+#endif // !__WIN__
return rc;
} // end of ReadDB
diff --git a/storage/connect/tabmul.h b/storage/connect/tabmul.h
index 379e8f88e93..433cc3a2ee3 100644
--- a/storage/connect/tabmul.h
+++ b/storage/connect/tabmul.h
@@ -6,14 +6,14 @@
/* */
/* This file contains the TDBMUL and TDBDIR classes declares. */
/***********************************************************************/
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
-#else // !WIN32
+#else // !__WIN__
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <dirent.h>
-#endif // !WIN32
+#endif // !__WIN__
//#include "osutil.h"
#include "block.h"
@@ -132,17 +132,17 @@ class TDBDIR : public TDBASE {
// Members
PSZ To_File; // Points to file search pathname
int iFile; // Index of currently retrieved file
-#if defined(WIN32)
+#if defined(__WIN__)
_finddata_t FileData; // Find data structure
int Hsearch; // Search handle
char Drive[_MAX_DRIVE]; // Drive name
-#else // !WIN32
+#else // !__WIN__
struct stat Fileinfo; // File info structure
struct dirent *Entry; // Point to directory entry structure
DIR *Dir; // To searched directory structure
bool Done; // true when _splipath is done
char Pattern[_MAX_FNAME+_MAX_EXT];
-#endif // !WIN32
+#endif // !__WIN__
char Fpath[_MAX_PATH]; // Absolute file search pattern
char Direc[_MAX_DIR]; // Search path
char Fname[_MAX_FNAME]; // File name
@@ -183,11 +183,11 @@ class TDBSDR : public TDBDIR {
typedef struct _Sub_Dir {
struct _Sub_Dir *Next;
struct _Sub_Dir *Prev;
-#if defined(WIN32)
+#if defined(__WIN__)
int H; // Search handle
-#else // !WIN32
+#else // !__WIN__
DIR *D;
-#endif // !WIN32
+#endif // !__WIN__
size_t Len; // Initial directory name length
} SUBDIR, *PSUBDIR;
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index 54627ba43fd..19a5dfd758f 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -5,7 +5,7 @@
/* */
/* AUTHOR: */
/* ------- */
-/* Olivier BERTRAND 2007-2014 */
+/* Olivier BERTRAND 2007-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -35,9 +35,9 @@
#include "my_global.h"
#include "sql_class.h"
#include "sql_servers.h"
-#if defined(WIN32)
+#if defined(__WIN__)
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
//#include <fnmatch.h>
//#include <errno.h>
#include <stdlib.h>
@@ -46,7 +46,7 @@
#include "osutil.h"
//#include <io.h>
//#include <fcntl.h>
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Include application header files: */
@@ -56,7 +56,6 @@
#include "xtable.h"
#include "tabcol.h"
#include "colblk.h"
-#include "mycat.h"
#include "reldef.h"
#include "tabmysql.h"
#include "valblk.h"
@@ -308,7 +307,7 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b)
/***********************************************************************/
/* DefineAM: define specific AM block values from XCV file. */
/***********************************************************************/
-bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
{
char *url;
@@ -381,7 +380,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
/* GetTable: makes a new TDB of the proper type. */
/***********************************************************************/
-PTDB MYSQLDEF::GetTable(PGLOBAL g, MODE m)
+PTDB MYSQLDEF::GetTable(PGLOBAL g, MODE)
{
if (Xsrc)
return new(g) TDBMYEXC(this);
@@ -439,7 +438,7 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
Nparm = 0;
} // end of TDBMYSQL constructor
-TDBMYSQL::TDBMYSQL(PGLOBAL g, PTDBMY tdbp) : TDBASE(tdbp)
+TDBMYSQL::TDBMYSQL(PTDBMY tdbp) : TDBASE(tdbp)
{
Host = tdbp->Host;
Database = tdbp->Database;
@@ -469,7 +468,7 @@ PTDB TDBMYSQL::CopyOne(PTABS t)
PCOL cp1, cp2;
PGLOBAL g = t->G;
- tp = new(g) TDBMYSQL(g, this);
+ tp = new(g) TDBMYSQL(this);
for (cp1 = Columns; cp1; cp1 = cp1->GetNext()) {
cp2 = new(g) MYSQLCOL((PMYCOL)cp1, tp);
@@ -817,7 +816,7 @@ int TDBMYSQL::GetMaxSize(PGLOBAL g)
/***********************************************************************/
/* This a fake routine as ROWID does not exist in MySQL. */
/***********************************************************************/
-int TDBMYSQL::RowNumber(PGLOBAL g, bool b)
+int TDBMYSQL::RowNumber(PGLOBAL, bool)
{
return N + 1;
} // end of RowNumber
@@ -833,7 +832,7 @@ int TDBMYSQL::GetProgMax(PGLOBAL g)
/***********************************************************************/
/* MySQL Bind Parameter function. */
/***********************************************************************/
-int TDBMYSQL::BindColumns(PGLOBAL g)
+int TDBMYSQL::BindColumns(PGLOBAL g __attribute__((unused)))
{
#if defined(MYSQL_PREPARED_STATEMENTS)
if (Prep) {
@@ -1061,9 +1060,16 @@ bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
int oldlen = Query->GetLength();
if (!key || op == OP_NEXT ||
- Mode == MODE_UPDATE || Mode == MODE_DELETE)
+ Mode == MODE_UPDATE || Mode == MODE_DELETE) {
+ if (!key && Mode == MODE_READX) {
+ // This is a false indexed read
+ m_Rc = Myc.ExecSQL(g, Query->GetStr());
+ Mode = MODE_READ;
+ return (m_Rc == RC_FX) ? true : false;
+ } // endif key
+
return false;
- else if (op == OP_FIRST) {
+ } else if (op == OP_FIRST) {
if (To_CondFil) {
oom = Query->Append(" WHERE ");
@@ -1078,8 +1084,7 @@ bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
if (Myc.m_Res)
Myc.FreeResult();
- To_Def->GetHandler()->MakeKeyWhere(g, Query->GetStr(),
- op, "`", key, len);
+ To_Def->GetHandler()->MakeKeyWhere(g, Query, op, '`', key, len);
if (To_CondFil) {
oom = Query->Append(" AND (");
@@ -1141,19 +1146,16 @@ int TDBMYSQL::WriteDB(PGLOBAL g)
int rc;
uint len = Query->GetLength();
char buf[64];
- bool b, oom = false;
+ bool oom = false;
// Make the Insert command value list
for (PCOL colp = Columns; colp; colp = colp->GetNext()) {
if (!colp->GetValue()->IsNull()) {
- if ((b = colp->GetResultType() == TYPE_STRING ||
- colp->GetResultType() == TYPE_DATE))
- oom |= Query->Append('\'');
-
- oom |= Query->Append(colp->GetValue()->GetCharString(buf));
-
- if (b)
- oom |= Query->Append('\'');
+ if (colp->GetResultType() == TYPE_STRING ||
+ colp->GetResultType() == TYPE_DATE)
+ oom |= Query->Append_quoted(colp->GetValue()->GetCharString(buf));
+ else
+ oom |= Query->Append(colp->GetValue()->GetCharString(buf));
} else
oom |= Query->Append("NULL");
@@ -1423,7 +1425,7 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
/***********************************************************************/
/* WriteColumn: make sure the bind buffer is updated. */
/***********************************************************************/
-void MYSQLCOL::WriteColumn(PGLOBAL g)
+void MYSQLCOL::WriteColumn(PGLOBAL)
{
/*********************************************************************/
/* Do convert the column value if necessary. */
@@ -1461,7 +1463,7 @@ TDBMYEXC::TDBMYEXC(PMYDEF tdp) : TDBMYSQL(tdp)
Nerr = 0;
} // end of TDBMYEXC constructor
-TDBMYEXC::TDBMYEXC(PGLOBAL g, PTDBMYX tdbp) : TDBMYSQL(g, tdbp)
+TDBMYEXC::TDBMYEXC(PTDBMYX tdbp) : TDBMYSQL(tdbp)
{
Cmdlist = tdbp->Cmdlist;
Cmdcol = tdbp->Cmdcol;
@@ -1479,7 +1481,7 @@ PTDB TDBMYEXC::CopyOne(PTABS t)
PCOL cp1, cp2;
PGLOBAL g = t->G;
- tp = new(g) TDBMYEXC(g, this);
+ tp = new(g) TDBMYEXC(this);
for (cp1 = Columns; cp1; cp1 = cp1->GetNext()) {
cp2 = new(g) MYXCOL((PMYXCOL)cp1, tp);
@@ -1532,7 +1534,7 @@ PCMD TDBMYEXC::MakeCMD(PGLOBAL g)
/***********************************************************************/
/* EXC GetMaxSize: returns the maximum number of rows in the table. */
/***********************************************************************/
-int TDBMYEXC::GetMaxSize(PGLOBAL g)
+int TDBMYEXC::GetMaxSize(PGLOBAL)
{
if (MaxSize < 0) {
MaxSize = 10; // a guess
@@ -1709,7 +1711,7 @@ void MYXCOL::ReadColumn(PGLOBAL g)
/***********************************************************************/
/* WriteColumn: should never be called. */
/***********************************************************************/
-void MYXCOL::WriteColumn(PGLOBAL g)
+void MYXCOL::WriteColumn(PGLOBAL)
{
assert(false);
} // end of WriteColumn
diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h
index 99930d43a57..17d7b190340 100644
--- a/storage/connect/tabmysql.h
+++ b/storage/connect/tabmysql.h
@@ -73,11 +73,11 @@ class TDBMYSQL : public TDBASE {
public:
// Constructor
TDBMYSQL(PMYDEF tdp);
- TDBMYSQL(PGLOBAL g, PTDBMY tdbp);
+ TDBMYSQL(PTDBMY tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_MYSQL;}
- virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBMYSQL(g, this);}
+ virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBMYSQL(this);}
// Methods
virtual PTDB CopyOne(PTABS t);
@@ -180,11 +180,11 @@ class TDBMYEXC : public TDBMYSQL {
public:
// Constructors
TDBMYEXC(PMYDEF tdp);
- TDBMYEXC(PGLOBAL g, PTDBMYX tdbp);
+ TDBMYEXC(PTDBMYX tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_MYX;}
- virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBMYEXC(g, this);}
+ virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBMYEXC(this);}
// Methods
virtual PTDB CopyOne(PTABS t);
diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp
index 86f0bd20d47..07e260154e0 100644
--- a/storage/connect/taboccur.cpp
+++ b/storage/connect/taboccur.cpp
@@ -1,7 +1,7 @@
/************ TabOccur CPP Declares Source Code File (.CPP) ************/
/* Name: TABOCCUR.CPP Version 1.1 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2013 - 2015 */
/* */
/* OCCUR: Table that provides a view of a source table where the */
/* contain of several columns of the source table is placed in only */
@@ -13,7 +13,7 @@
/***********************************************************************/
#include "my_global.h"
#include "table.h" // MySQL table definitions
-#if defined(WIN32)
+#if defined(__WIN__)
#include <stdlib.h>
#include <stdio.h>
#if defined(__BORLANDC__)
@@ -45,11 +45,8 @@
#include "tabcol.h"
#include "taboccur.h"
#include "xtable.h"
-#if defined(MYSQL_SUPPORT)
#include "tabmysql.h"
-#endif // MYSQL_SUPPORT
#include "ha_connect.h"
-#include "mycat.h"
/***********************************************************************/
/* Prepare and count columns in the column list. */
@@ -93,8 +90,7 @@ bool OcrColumns(PGLOBAL g, PQRYRES qrp, const char *col,
} // endif col
// Prepare the column list
- colist = (char*)PlugSubAlloc(g, NULL, strlen(col) + 1);
- strcpy(colist, col);
+ colist = PlugDup(g, col);
m = PrepareColist(colist);
if ((rk = (rank && *rank))) {
@@ -191,8 +187,7 @@ bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, const char *col,
} // endif col
// Prepare the column list
- colist = (char*)PlugSubAlloc(g, NULL, strlen(col) + 1);
- strcpy(colist, col);
+ colist = PlugDup(g, col);
m = PrepareColist(colist);
if ((rk = (rank && *rank)))
@@ -271,7 +266,7 @@ bool OCCURDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
/* GetTable: makes a new TDB of the proper type. */
/***********************************************************************/
-PTDB OCCURDEF::GetTable(PGLOBAL g, MODE m)
+PTDB OCCURDEF::GetTable(PGLOBAL g, MODE)
{
if (Catfunc != FNC_COL)
return new(g) TDBOCCUR(this);
@@ -355,7 +350,7 @@ bool TDBOCCUR::MakeColumnList(PGLOBAL g)
for (colp = Columns; colp; colp = colp->GetNext())
if (colp->GetAmType() == TYPE_AM_PRX)
- if (((PPRXCOL)colp)->Init(g))
+ if (((PPRXCOL)colp)->Init(g, NULL))
return true;
Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL));
@@ -437,7 +432,7 @@ int TDBOCCUR::GetMaxSize(PGLOBAL g)
/* In this sample, ROWID will be the (virtual) row number, */
/* while ROWNUM will be the occurence rank in the multiple column. */
/***********************************************************************/
-int TDBOCCUR::RowNumber(PGLOBAL g, bool b)
+int TDBOCCUR::RowNumber(PGLOBAL, bool b)
{
return (b) ? M : N;
} // end of RowNumber
@@ -572,7 +567,7 @@ void OCCURCOL::ReadColumn(PGLOBAL g)
/* ReadColumn: what this routine does is to access the Mth columns of */
/* list, extract its name and set to it the rank column value. */
/***********************************************************************/
-void RANKCOL::ReadColumn(PGLOBAL g)
+void RANKCOL::ReadColumn(PGLOBAL)
{
PTDBOCCUR tdbp = (PTDBOCCUR)To_Tdb;
PCOL *col = tdbp->Col;
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index 2b771bcbead..307509848f4 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -35,7 +35,7 @@
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <fcntl.h>
#if defined(__BORLANDC__)
@@ -66,8 +66,8 @@
#include "plgdbsem.h"
#include "mycat.h"
#include "xtable.h"
-#include "tabodbc.h"
#include "odbccat.h"
+#include "tabodbc.h"
#include "tabmul.h"
#include "reldef.h"
#include "tabcol.h"
@@ -93,9 +93,10 @@ bool ExactInfo(void);
/***********************************************************************/
ODBCDEF::ODBCDEF(void)
{
- Connect= Tabname= Tabschema= Tabcat= Srcdef= Qchar= Qrystr= Sep= NULL;
+ Connect = Tabname = Tabschema = Username = Password = NULL;
+ Tabcat = Srcdef = Qchar = Qrystr = Sep = NULL;
Catver = Options = Cto = Qto = Quoted = Maxerr = Maxres = 0;
- Scrollable = Memory = Xsrc = false;
+ Scrollable = Memory = Xsrc = UseCnc = false;
} // end of ODBCDEF constructor
/***********************************************************************/
@@ -117,6 +118,8 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Tabschema = GetStringCatInfo(g, "Schema", Tabschema);
Tabcat = GetStringCatInfo(g, "Qualifier", NULL);
Tabcat = GetStringCatInfo(g, "Catalog", Tabcat);
+ Username = GetStringCatInfo(g, "User", NULL);
+ Password = GetStringCatInfo(g, "Password", NULL);
if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL)))
Read_Only = true;
@@ -132,8 +135,16 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
//Options = ODBConn::noOdbcDialog | ODBConn::useCursorLib;
Cto= GetIntCatInfo("ConnectTimeout", DEFAULT_LOGIN_TIMEOUT);
Qto= GetIntCatInfo("QueryTimeout", DEFAULT_QUERY_TIMEOUT);
- Scrollable = GetBoolCatInfo("Scrollable", false);
- Memory = GetBoolCatInfo("Memory", false);
+
+ if ((Scrollable = GetBoolCatInfo("Scrollable", false)) && !Elemt)
+ Elemt = 1; // Cannot merge SQLFetch and SQLExtendedFetch
+
+ UseCnc = GetBoolCatInfo("UseDSN", false);
+
+ // Memory was Boolean, it is now integer
+ if (!(Memory = GetIntCatInfo("Memory", 0)))
+ Memory = GetBoolCatInfo("Memory", false) ? 1 : 0;
+
Pseudo = 2; // FILID is Ok but not ROWID
return false;
} // end of DefineAM
@@ -190,34 +201,40 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
Connect = tdp->Connect;
TableName = tdp->Tabname;
Schema = tdp->Tabschema;
+ Ops.User = tdp->Username;
+ Ops.Pwd = tdp->Password;
Catalog = tdp->Tabcat;
Srcdef = tdp->Srcdef;
Qrystr = tdp->Qrystr;
Sep = tdp->GetSep();
Options = tdp->Options;
- Cto = tdp->Cto;
- Qto = tdp->Qto;
+ Ops.Cto = tdp->Cto;
+ Ops.Qto = tdp->Qto;
Quoted = MY_MAX(0, tdp->GetQuoted());
Rows = tdp->GetElemt();
Catver = tdp->Catver;
- Memory = (tdp->Memory) ? 1 : 0;
+ Memory = tdp->Memory;
Scrollable = tdp->Scrollable;
+ Ops.UseCnc = tdp->UseCnc;
} else {
Connect = NULL;
TableName = NULL;
Schema = NULL;
+ Ops.User = NULL;
+ Ops.Pwd = NULL;
Catalog = NULL;
Srcdef = NULL;
Qrystr = NULL;
Sep = 0;
Options = 0;
- Cto = DEFAULT_LOGIN_TIMEOUT;
- Qto = DEFAULT_QUERY_TIMEOUT;
+ Ops.Cto = DEFAULT_LOGIN_TIMEOUT;
+ Ops.Qto = DEFAULT_QUERY_TIMEOUT;
Quoted = 0;
Rows = 0;
Catver = 0;
Memory = 0;
Scrollable = false;
+ Ops.UseCnc = false;
} // endif tdp
Quote = NULL;
@@ -228,11 +245,13 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
DBQ = NULL;
Qrp = NULL;
Fpos = 0;
+ Curpos = 0;
AftRows = 0;
CurNum = 0;
Rbuf = 0;
BufSize = 0;
Nparm = 0;
+ Placed = false;
} // end of TDBODBC standard constructor
TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
@@ -242,6 +261,7 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
Connect = tdbp->Connect;
TableName = tdbp->TableName;
Schema = tdbp->Schema;
+ Ops = tdbp->Ops;
Catalog = tdbp->Catalog;
Srcdef = tdbp->Srcdef;
Qrystr = tdbp->Qrystr;
@@ -254,19 +274,17 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
MulConn = tdbp->MulConn;
DBQ = tdbp->DBQ;
Options = tdbp->Options;
- Cto = tdbp->Cto;
- Qto = tdbp->Qto;
Quoted = tdbp->Quoted;
Rows = tdbp->Rows;
- Fpos = tdbp->Fpos;
- AftRows = tdbp->AftRows;
-//Tpos = tdbp->Tpos;
-//Spos = tdbp->Spos;
- CurNum = tdbp->CurNum;
- Rbuf = tdbp->Rbuf;
+ Fpos = 0;
+ Curpos = 0;
+ AftRows = 0;
+ CurNum = 0;
+ Rbuf = 0;
BufSize = tdbp->BufSize;
Nparm = tdbp->Nparm;
Qrp = tdbp->Qrp;
+ Placed = false;
} // end of TDBODBC copy constructor
// Method
@@ -370,7 +388,7 @@ int TDBODBC::Decode(char *txt, char *buf, size_t n)
/***********************************************************************/
char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
{
- char *colist, *tabname, *sql, buf[64];
+ char *colist, *tabname, *sql, buf[NAM_LEN * 3];
LPCSTR schmp = NULL, catp = NULL;
int len, ncol = 0;
bool first = true;
@@ -474,6 +492,9 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
if (To_CondFil)
strcat(strcat(sql, " WHERE "), To_CondFil->Body);
+
+ if (trace)
+ htrc("sql: '%s'\n", sql);
return sql;
} // end of MakeSQL
@@ -483,7 +504,7 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
/***********************************************************************/
char *TDBODBC::MakeInsert(PGLOBAL g)
{
- char *stmt, *colist, *valist;
+ char *stmt, *colist, *valist, buf[NAM_LEN * 3];
// char *tk = "`";
int len = 0;
bool b = FALSE;
@@ -510,10 +531,13 @@ char *TDBODBC::MakeInsert(PGLOBAL g)
} else
b = true;
+ // Column name can be in UTF-8 encoding
+ Decode(colp->GetName(), buf, sizeof(buf));
+
if (Quote)
- strcat(strcat(strcat(colist, Quote), colp->GetName()), Quote);
+ strcat(strcat(strcat(colist, Quote), buf), Quote);
else
- strcat(colist, colp->GetName());
+ strcat(colist, buf);
strcat(valist, "?"); // Parameter marker
} // endfor colp
@@ -558,8 +582,7 @@ bool TDBODBC::BindParameters(PGLOBAL g)
/***********************************************************************/
char *TDBODBC::MakeCommand(PGLOBAL g)
{
- char *p, name[68], *qc = Ocp->GetQuoteChar();
- char *stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
+ char *p, *stmt, name[68], *body = NULL, *qc = Ocp->GetQuoteChar();
char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1);
bool qtd = Quoted > 0;
int i = 0, k = 0;
@@ -570,6 +593,15 @@ char *TDBODBC::MakeCommand(PGLOBAL g)
qrystr[i] = (Qrystr[i] == '`') ? *qc : tolower(Qrystr[i]);
} while (Qrystr[i++]);
+ if (To_CondFil && (p = strstr(qrystr, " where "))) {
+ p[7] = 0; // Remove where clause
+ Qrystr[(p - qrystr) + 7] = 0;
+ body = To_CondFil->Body;
+ stmt = (char*)PlugSubAlloc(g, NULL, strlen(qrystr)
+ + strlen(body) + 64);
+ } else
+ stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
+
// Check whether the table name is equal to a keyword
// If so, it must be quoted in the original query
strlwr(strcat(strcat(strcpy(name, " "), Name), " "));
@@ -597,6 +629,9 @@ char *TDBODBC::MakeCommand(PGLOBAL g)
stmt[i++] = (Qrystr[k] == '`') ? *qc : Qrystr[k];
} while (Qrystr[k++]);
+ if (body)
+ strcat(stmt, body);
+
} else {
sprintf(g->Message, "Cannot use this %s command",
(Mode == MODE_UPDATE) ? "UPDATE" : "DELETE");
@@ -698,10 +733,7 @@ int TDBODBC::Cardinality(PGLOBAL g)
char qry[96], tbn[64];
ODBConn *ocp = new(g) ODBConn(g, this);
- ocp->SetLoginTimeout((DWORD)Cto);
- ocp->SetQueryTimeout((DWORD)Qto);
-
- if (ocp->Open(Connect, Options) < 1)
+ if (ocp->Open(Connect, &Ops, Options) < 1)
return -1;
// Table name can be encoded in UTF-8
@@ -762,9 +794,9 @@ int TDBODBC::GetProgMax(PGLOBAL g)
/***********************************************************************/
bool TDBODBC::OpenDB(PGLOBAL g)
{
- bool rc = false;
+ bool rc = true;
- if (g->Trace)
+ if (trace)
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
this, Tdb_No, Use, Mode);
@@ -788,10 +820,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
return true;
} // endif Rewind
- } // endif Memory
+ } else
+ Rbuf = Qrp->Nblin;
CurNum = 0;
Fpos = 0;
+ Curpos = 1;
return false;
} // endif use
@@ -802,14 +836,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
/* and if so to allocate just a new result set. But this only for */
/* drivers allowing concurency in getting results ??? */
/*********************************************************************/
- if (!Ocp) {
+ if (!Ocp)
Ocp = new(g) ODBConn(g, this);
- Ocp->SetLoginTimeout((DWORD)Cto);
- Ocp->SetQueryTimeout((DWORD)Qto);
- } else if (Ocp->IsOpen())
+ else if (Ocp->IsOpen())
Ocp->Close();
- if (Ocp->Open(Connect, Options) < 1)
+ if (Ocp->Open(Connect, &Ops, Options) < 1)
return true;
else if (Quoted)
Quote = Ocp->GetQuoteChar();
@@ -820,6 +852,37 @@ bool TDBODBC::OpenDB(PGLOBAL g)
/* Make the command and allocate whatever is used for getting results. */
/*********************************************************************/
if (Mode == MODE_READ || Mode == MODE_READX) {
+ if (Memory > 1 && !Srcdef) {
+ char *Sql;
+ int n;
+
+ if ((Sql = MakeSQL(g, true))) {
+ // Allocate a Count(*) column
+ Cnp = new(g) ODBCCOL;
+ Cnp->InitValue(g);
+
+ if ((n = Ocp->GetResultSize(Sql, Cnp)) < 0) {
+ strcpy(g->Message, "Cannot get result size");
+ return true;
+ } // endif n
+
+ Ocp->m_Rows = n;
+
+ if ((Qrp = Ocp->AllocateResult(g)))
+ Memory = 2; // Must be filled
+ else {
+ strcpy(g->Message, "Memory allocation failed");
+ return true;
+ } // endif n
+
+ Ocp->m_Rows = 0;
+ } else {
+ strcpy(g->Message, "MakeSQL failed");
+ return true;
+ } // endif Sql
+
+ } // endif Memory
+
if ((Query = MakeSQL(g, false))) {
for (PODBCCOL colp = (PODBCCOL)Columns; colp;
colp = (PODBCCOL)colp->GetNext())
@@ -839,12 +902,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
} // endif Query
- } else if (Mode == MODE_UPDATE || Mode == MODE_DELETE)
- Query = MakeCommand(g);
- else
+ } else if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
+ rc = false; // wait for CheckCond before calling MakeCommand(g);
+ } else
sprintf(g->Message, "Invalid mode %d", Mode);
- if (!Query || rc) {
+ if (rc) {
Ocp->Close();
return true;
} // endif rc
@@ -861,10 +924,41 @@ bool TDBODBC::OpenDB(PGLOBAL g)
/***********************************************************************/
int TDBODBC::GetRecpos(void)
{
- return Fpos; // To be really implemented
+ return Fpos;
} // end of GetRecpos
/***********************************************************************/
+/* SetRecpos: set the position of next read record. */
+/***********************************************************************/
+bool TDBODBC::SetRecpos(PGLOBAL g, int recpos)
+ {
+ if (Ocp->m_Full) {
+ Fpos = 0;
+ CurNum = recpos - 1;
+ } else if (Memory == 3) {
+ Fpos = recpos;
+ CurNum = -1;
+ } else if (Scrollable) {
+ // Is new position in the current row set?
+ if (recpos >= Curpos && recpos < Curpos + Rbuf) {
+ CurNum = recpos - Curpos;
+ Fpos = 0;
+ } else {
+ Fpos = recpos;
+ CurNum = 0;
+ } // endif recpos
+
+ } else {
+ strcpy(g->Message, "This action requires a scrollable cursor");
+ return true;
+ } // endif's
+
+ // Indicate the table position was externally set
+ Placed = true;
+ return false;
+ } // end of SetRecpos
+
+/***********************************************************************/
/* VRDNDOS: Data Base read routine for odbc access method. */
/***********************************************************************/
int TDBODBC::ReadDB(PGLOBAL g)
@@ -876,6 +970,9 @@ int TDBODBC::ReadDB(PGLOBAL g)
GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
+ if (!Query && !(Query = MakeCommand(g)))
+ return RC_FX;
+
// Send the UPDATE/DELETE command to the remote table
if (!Ocp->ExecSQLcommand(Query)) {
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
@@ -900,22 +997,32 @@ int TDBODBC::ReadDB(PGLOBAL g)
/* Now start the reading process. */
/* Here is the place to fetch the line(s). */
/*********************************************************************/
- if (Memory != 3) {
- if (++CurNum >= Rbuf) {
- Rbuf = Ocp->Fetch();
- CurNum = 0;
- } // endif CurNum
+ if (Placed) {
+ if (Fpos && CurNum >= 0)
+ Rbuf = Ocp->Fetch((Curpos = Fpos));
rc = (Rbuf > 0) ? RC_OK : (Rbuf == 0) ? RC_EF : RC_FX;
- } else // Getting result from memory
- rc = (Fpos < Qrp->Nblin) ? RC_OK : RC_EF;
+ Placed = false;
+ } else {
+ if (Memory != 3) {
+ if (++CurNum >= Rbuf) {
+ Rbuf = Ocp->Fetch();
+ Curpos = Fpos + 1;
+ CurNum = 0;
+ } // endif CurNum
- if (rc == RC_OK) {
- if (Memory == 2)
- Qrp->Nblin++;
+ rc = (Rbuf > 0) ? RC_OK : (Rbuf == 0) ? RC_EF : RC_FX;
+ } else // Getting result from memory
+ rc = (Fpos < Qrp->Nblin) ? RC_OK : RC_EF;
- Fpos++; // Used for memory
- } // endif rc
+ if (rc == RC_OK) {
+ if (Memory == 2)
+ Qrp->Nblin++;
+
+ Fpos++; // Used for memory and pos
+ } // endif rc
+
+ } // endif Placed
if (trace > 1)
htrc(" Read: Rbuf=%d rc=%d\n", Rbuf, rc);
@@ -945,6 +1052,9 @@ int TDBODBC::WriteDB(PGLOBAL g)
int TDBODBC::DeleteDB(PGLOBAL g, int irc)
{
if (irc == RC_FX) {
+ if (!Query && !(Query = MakeCommand(g)))
+ return RC_FX;
+
// Send the DELETE (all) command to the remote table
if (!Ocp->ExecSQLcommand(Query)) {
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
@@ -1158,12 +1268,16 @@ void ODBCCOL::ReadColumn(PGLOBAL g)
} // endif Buf_Type
- if (g->Trace) {
+ // Handle null values
+ if (Value->IsZero())
+ Value->SetNull(Nullable);
+
+ if (trace) {
char buf[64];
htrc("ODBC Column %s: rows=%d buf=%p type=%d value=%s\n",
Name, tdbp->Rows, Bufp, Buf_Type, Value->GetCharString(buf));
- } // endif Trace
+ } // endif trace
put:
if (tdbp->Memory != 2)
@@ -1283,7 +1397,7 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
/* -------------------------- Class TDBXDBC -------------------------- */
/***********************************************************************/
-/* Implementation of the TDBODBC class. */
+/* Implementation of the TDBXDBC class. */
/***********************************************************************/
TDBXDBC::TDBXDBC(PODEF tdp) : TDBODBC(tdp)
{
@@ -1397,7 +1511,7 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
{
bool rc = false;
- if (g->Trace)
+ if (trace)
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
this, Tdb_No, Use, Mode);
@@ -1415,12 +1529,10 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
/*********************************************************************/
if (!Ocp) {
Ocp = new(g) ODBConn(g, this);
- Ocp->SetLoginTimeout((DWORD)Cto);
- Ocp->SetQueryTimeout((DWORD)Qto);
} else if (Ocp->IsOpen())
Ocp->Close();
- if (Ocp->Open(Connect, Options) < 1)
+ if (Ocp->Open(Connect, &Ops, Options) < 1)
return true;
Use = USE_OPEN; // Do it now in case we are recursively called
@@ -1554,8 +1666,11 @@ TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp)
Dsn = tdp->GetConnect();
Schema = tdp->GetTabschema();
Tab = tdp->GetTabname();
- Cto = tdp->Cto;
- Qto = tdp->Qto;
+ Ops.User = tdp->Username;
+ Ops.Pwd = tdp->Password;
+ Ops.Cto = tdp->Cto;
+ Ops.Qto = tdp->Qto;
+ Ops.UseCnc = tdp->UseCnc;
} // end of TDBOTB constructor
/***********************************************************************/
@@ -1563,7 +1678,7 @@ TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp)
/***********************************************************************/
PQRYRES TDBOTB::GetResult(PGLOBAL g)
{
- return ODBCTables(g, Dsn, Schema, Tab, Maxres, Cto, Qto, false);
+ return ODBCTables(g, Dsn, Schema, Tab, Maxres, false, &Ops);
} // end of GetResult
/* ---------------------------TDBOCL class --------------------------- */
@@ -1573,7 +1688,7 @@ PQRYRES TDBOTB::GetResult(PGLOBAL g)
/***********************************************************************/
PQRYRES TDBOCL::GetResult(PGLOBAL g)
{
- return ODBCColumns(g, Dsn, Schema, Tab, NULL, Maxres, Cto, Qto, false);
+ return ODBCColumns(g, Dsn, Schema, Tab, NULL, Maxres, false, &Ops);
} // end of GetResult
/* ------------------------ End of Tabodbc --------------------------- */
diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h
index d8644c8b6de..b8c9d85aae5 100644
--- a/storage/connect/tabodbc.h
+++ b/storage/connect/tabodbc.h
@@ -50,6 +50,8 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
PSZ Connect; /* ODBC connection string */
PSZ Tabname; /* External table name */
PSZ Tabschema; /* External table schema */
+ PSZ Username; /* User connect name */
+ PSZ Password; /* Password connect info */
PSZ Tabcat; /* External table catalog */
PSZ Srcdef; /* The source table SQL definition */
PSZ Qchar; /* Identifier quoting character */
@@ -62,9 +64,10 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
int Quoted; /* Identifier quoting level */
int Maxerr; /* Maxerr for an Exec table */
int Maxres; /* Maxres for a catalog table */
+ int Memory; /* Put result set in memory */
bool Scrollable; /* Use scrollable cursor */
- bool Memory; /* Put result set in memory */
bool Xsrc; /* Execution type */
+ bool UseCnc; /* Use SQLConnect (!SQLDriverConnect) */
}; // end of ODBCDEF
#if !defined(NODBC)
@@ -90,6 +93,7 @@ class TDBODBC : public TDBASE {
// Methods
virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void);
+ virtual bool SetRecpos(PGLOBAL g, int recpos);
virtual PSZ GetFile(PGLOBAL g);
virtual void SetFile(PGLOBAL g, PSZ fn);
virtual void ResetSize(void);
@@ -124,9 +128,12 @@ class TDBODBC : public TDBASE {
// Members
ODBConn *Ocp; // Points to an ODBC connection class
ODBCCOL *Cnp; // Points to count(*) column
+ ODBCPARM Ops; // Additional parameters
char *Connect; // Points to connection string
char *TableName; // Points to ODBC table name
char *Schema; // Points to ODBC table Schema
+ char *User; // User connect info
+ char *Pwd; // Password connect info
char *Catalog; // Points to ODBC table Catalog
char *Srcdef; // The source table SQL definition
char *Query; // Points to SQL statement
@@ -142,6 +149,7 @@ class TDBODBC : public TDBASE {
int Qto; // Query timeout
int Quoted; // The identifier quoting level
int Fpos; // Position of last read record
+ int Curpos; // Cursor position of last fetch
int AftRows; // The number of affected rows
int Rows; // Rowset size
int Catver; // Catalog ODBC version
@@ -151,6 +159,8 @@ class TDBODBC : public TDBASE {
int Nparm; // The number of statement parameters
int Memory; // 0: No 1: Alloc 2: Put 3: Get
bool Scrollable; // Use scrollable cursor
+ bool Placed; // True for position reading
+ bool UseCnc; // Use SQLConnect (!SQLDriverConnect)
PQRYRES Qrp; // Points to storage result
}; // end of class TDBODBC
@@ -316,8 +326,7 @@ class TDBOTB : public TDBDRV {
char *Dsn; // Points to connection string
char *Schema; // Points to schema name or NULL
char *Tab; // Points to ODBC table name or pattern
- int Cto; // Connect timeout
- int Qto; // Query timeout
+ ODBCPARM Ops; // Additional parameters
}; // end of class TDBOTB
/***********************************************************************/
diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp
index 94e9d7187f0..b628e26d3c7 100644
--- a/storage/connect/tabpivot.cpp
+++ b/storage/connect/tabpivot.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -17,7 +17,7 @@
/***********************************************************************/
#include "my_global.h"
#include "table.h" // MySQL table definitions
-#if defined(WIN32)
+#if defined(__WIN__)
#if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro
#endif
@@ -49,7 +49,6 @@
#include "tabpivot.h"
#include "valblk.h"
#include "ha_connect.h"
-#include "mycat.h" // For GetHandler
/***********************************************************************/
/* Make the Pivot table column list. */
@@ -150,11 +149,18 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
query = Tabsrc;
// Open a MySQL connection for this table
- if (Myc.Open(g, Host, Database, User, Pwd, Port))
- return NULL;
- else
+ if (!Myc.Open(g, Host, Database, User, Pwd, Port)) {
b = true;
+ // Returned values must be in their original character set
+ if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX)
+ goto err;
+ else
+ Myc.FreeResult();
+
+ } else
+ return NULL;
+
// Send the source command to MySQL
if (Myc.ExecSQL(g, query, &w) == RC_FX)
goto err;
@@ -241,6 +247,10 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
} else {
// The query was limited, we must get pivot column values
+ // Returned values must be in their original character set
+// if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX)
+// goto err;
+
query = (char*)PlugSubAlloc(g, NULL, 0);
sprintf(query, "SELECT DISTINCT `%s` FROM `%s`", Picol, Tabname);
PlugSubAlloc(g, NULL, strlen(query) + 1);
@@ -284,8 +294,7 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
valp->SetValue_pvblk(Rblkp, i);
colname = valp->GetCharString(buf);
- crp->Name = (char*)PlugSubAlloc(g, NULL, strlen(colname) + 1);
- strcpy(crp->Name, colname);
+ crp->Name = PlugDup(g, colname);
crp->Flag = 1;
// Add this column
@@ -367,7 +376,7 @@ bool PIVOTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
/* GetTable: makes a new TDB of the proper type. */
/***********************************************************************/
-PTDB PIVOTDEF::GetTable(PGLOBAL g, MODE m)
+PTDB PIVOTDEF::GetTable(PGLOBAL g, MODE)
{
return new(g) TDBPIVOT(this);
} // end of GetTable
@@ -558,7 +567,7 @@ bool TDBPIVOT::MakePivotColumns(PGLOBAL g)
// Check and initialize the subtable columns
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_SRC) {
- if (((PSRCCOL)cp)->Init(g))
+ if (((PSRCCOL)cp)->Init(g, NULL))
return TRUE;
} else if (cp->GetAmType() == TYPE_AM_FNC)
@@ -625,7 +634,7 @@ bool TDBPIVOT::MakeViewColumns(PGLOBAL g)
/***********************************************************************/
/* PIVOT GetMaxSize: returns the maximum number of rows in the table. */
/***********************************************************************/
-int TDBPIVOT::GetMaxSize(PGLOBAL g)
+int TDBPIVOT::GetMaxSize(PGLOBAL g __attribute__((unused)))
{
#if 0
if (MaxSize < 0)
@@ -640,7 +649,7 @@ int TDBPIVOT::GetMaxSize(PGLOBAL g)
/* In this sample, ROWID will be the (virtual) row number, */
/* while ROWNUM will be the occurence rank in the multiple column. */
/***********************************************************************/
-int TDBPIVOT::RowNumber(PGLOBAL g, bool b)
+int TDBPIVOT::RowNumber(PGLOBAL, bool b)
{
return (b) ? M : N;
} // end of RowNumber
@@ -797,7 +806,7 @@ int TDBPIVOT::WriteDB(PGLOBAL g)
/***********************************************************************/
/* Data Base delete line routine for PIVOT access methods. */
/***********************************************************************/
-int TDBPIVOT::DeleteDB(PGLOBAL g, int irc)
+int TDBPIVOT::DeleteDB(PGLOBAL g, int)
{
sprintf(g->Message, MSG(NO_TABLE_DEL), "PIVOT");
return RC_FX;
@@ -874,9 +883,9 @@ SRCCOL::SRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int n)
/***********************************************************************/
/* Initialize the column as pointing to the source column. */
/***********************************************************************/
-bool SRCCOL::Init(PGLOBAL g)
+bool SRCCOL::Init(PGLOBAL g, PTDBASE tp)
{
- if (PRXCOL::Init(g))
+ if (PRXCOL::Init(g, tp))
return true;
AddStatus(BUF_READ); // All is done here
diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h
index 25d139e895f..c397af05234 100644
--- a/storage/connect/tabpivot.h
+++ b/storage/connect/tabpivot.h
@@ -180,9 +180,10 @@ class SRCCOL : public PRXCOL {
virtual int GetAmType(void) {return TYPE_AM_SRC;}
// Methods
+ using PRXCOL::Init;
virtual void Reset(void) {}
void SetColumn(void);
- bool Init(PGLOBAL g);
+ virtual bool Init(PGLOBAL g, PTDBASE tp);
bool CompareLast(void);
protected:
diff --git a/storage/connect/tabsys.cpp b/storage/connect/tabsys.cpp
index 3ed182c5e33..76890e84429 100644
--- a/storage/connect/tabsys.cpp
+++ b/storage/connect/tabsys.cpp
@@ -3,7 +3,7 @@
/* ------------- */
/* Version 2.3 */
/* */
-/* Author Olivier BERTRAND 2004-2014 */
+/* Author Olivier BERTRAND 2004-2015 */
/* */
/* This program are the INI/CFG tables classes. */
/***********************************************************************/
@@ -12,12 +12,12 @@
/* Include relevant sections of the System header files. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro
#endif // __BORLANDC__
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#if defined(UNIX)
#include <errno.h>
#include <unistd.h>
@@ -25,7 +25,7 @@
#include <io.h>
#endif // !UNIX
#include <fcntl.h>
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Include application header files: */
@@ -36,9 +36,9 @@
#include "global.h"
#include "plgdbsem.h"
#include "reldef.h"
-#if !defined(WIN32)
+#if !defined(__WIN__)
#include "osutil.h"
-#endif // !WIN32
+#endif // !__WIN__
#include "filamtxt.h"
#include "tabdos.h"
#include "tabsys.h"
@@ -48,10 +48,10 @@
#define CSZ 36 // Column section name length
#define CDZ 256 // Column definition length
-#if !defined(WIN32)
+#if !defined(__WIN__)
#define GetPrivateProfileSectionNames(S,L,I) \
GetPrivateProfileString(NULL,NULL,"",S,L,I)
-#endif // !WIN32
+#endif // !__WIN__
/* -------------- Implementation of the INI classes ------------------ */
@@ -70,7 +70,7 @@ INIDEF::INIDEF(void)
/***********************************************************************/
/* DefineAM: define specific AM block values from XDB file. */
/***********************************************************************/
-bool INIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+bool INIDEF::DefineAM(PGLOBAL g, LPCSTR, int)
{
char buf[8];
@@ -96,7 +96,7 @@ bool INIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
/* GetTable: makes a new TDB of the proper type. */
/***********************************************************************/
-PTDB INIDEF::GetTable(PGLOBAL g, MODE m)
+PTDB INIDEF::GetTable(PGLOBAL g, MODE)
{
PTDBASE tdbp;
@@ -123,7 +123,7 @@ bool INIDEF::DeleteTableFile(PGLOBAL g)
// Delete the INI table file if not protected
if (!IsReadOnly()) {
PlugSetPath(filename, Fn, GetPath());
-#if defined(WIN32)
+#if defined(__WIN__)
rc = !DeleteFile(filename);
#else // UNIX
rc = remove(filename);
@@ -277,49 +277,27 @@ bool TDBINI::OpenDB(PGLOBAL g)
/***********************************************************************/
/* Data Base read routine for INI access method. */
/***********************************************************************/
-int TDBINI::ReadDB(PGLOBAL g)
+int TDBINI::ReadDB(PGLOBAL)
{
/*********************************************************************/
/* Now start the pseudo reading process. */
/*********************************************************************/
-#if 0 // INI tables are not indexable
- if (To_Kindex) {
- /*******************************************************************/
- /* Reading is by an index table. */
- /*******************************************************************/
- int recpos = To_Kindex->Fetch(g);
-
- switch (recpos) {
- case -1: // End of file reached
- return RC_EF;
- case -2: // No match for join
- return RC_NF;
- case -3: // Same record as last non null one
- return RC_OK;
- default:
- Section = (char*)recpos; // No good on 64 bit machines
- } // endswitch recpos
-
- } else {
-#endif // 0
- if (!Section)
- Section = Seclist;
- else
- Section += (strlen(Section) + 1);
-
- if (trace > 1)
- htrc("INI ReadDB: section=%s N=%d\n", Section, N);
+ if (!Section)
+ Section = Seclist;
+ else
+ Section += (strlen(Section) + 1);
- N++;
-//} // endif To_Kindex
+ if (trace > 1)
+ htrc("INI ReadDB: section=%s N=%d\n", Section, N);
+ N++;
return (*Section) ? RC_OK : RC_EF;
} // end of ReadDB
/***********************************************************************/
/* WriteDB: Data Base write routine for INI access methods. */
/***********************************************************************/
-int TDBINI::WriteDB(PGLOBAL g)
+int TDBINI::WriteDB(PGLOBAL)
{
// This is to check that section name was given when inserting
if (Mode == MODE_INSERT)
@@ -365,11 +343,11 @@ int TDBINI::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
/* Data Base close routine for INI access methods. */
/***********************************************************************/
-void TDBINI::CloseDB(PGLOBAL g)
+void TDBINI::CloseDB(PGLOBAL)
{
-#if !defined(WIN32)
+#if !defined(__WIN__)
PROFILE_Close(Ifile);
-#endif // !WIN32
+#endif // !__WIN__
} // end of CloseDB
// ------------------------ INICOL functions ----------------------------
@@ -377,7 +355,7 @@ void TDBINI::CloseDB(PGLOBAL g)
/***********************************************************************/
/* INICOL public constructor. */
/***********************************************************************/
-INICOL::INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+INICOL::INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ)
: COLBLK(cdp, tdbp, i)
{
if (cprec) {
@@ -471,7 +449,7 @@ bool INICOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
/* from the corresponding section, extract from it the key value */
/* corresponding to this column name and convert it to buffer type. */
/***********************************************************************/
-void INICOL::ReadColumn(PGLOBAL g)
+void INICOL::ReadColumn(PGLOBAL)
{
PTDBINI tdbp = (PTDBINI)To_Tdb;
@@ -747,7 +725,7 @@ int TDBXIN::ReadDB(PGLOBAL g)
/***********************************************************************/
/* WriteDB: Data Base write routine for XIN access methods. */
/***********************************************************************/
-int TDBXIN::WriteDB(PGLOBAL g)
+int TDBXIN::WriteDB(PGLOBAL)
{
// To check that section and key names were given when inserting
if (Mode == MODE_INSERT) {
@@ -809,7 +787,7 @@ XINCOL::XINCOL(XINCOL *col1, PTDB tdbp) : INICOL(col1, tdbp)
/* from the corresponding section, extract from it the key value */
/* corresponding to this column name and convert it to buffer type. */
/***********************************************************************/
-void XINCOL::ReadColumn(PGLOBAL g)
+void XINCOL::ReadColumn(PGLOBAL)
{
PTDBXIN tdbp = (PTDBXIN)To_Tdb;
diff --git a/storage/connect/tabsys.h b/storage/connect/tabsys.h
index aa45c260bc2..6b454322906 100644
--- a/storage/connect/tabsys.h
+++ b/storage/connect/tabsys.h
@@ -1,182 +1,182 @@
-/*************** TabSys H Declares Source Code File (.H) ***************/
-/* Name: TABSYS.H Version 2.3 */
-/* */
-/* (C) Copyright to the author Olivier BERTRAND 2004-2014 */
-/* */
-/* This file contains the XDB system tables classes declares. */
-/***********************************************************************/
-typedef class INIDEF *PINIDEF;
-typedef class TDBINI *PTDBINI;
-typedef class INICOL *PINICOL;
-typedef class TDBXIN *PTDBXIN;
-typedef class XINCOL *PXINCOL;
-
-/* --------------------------- INI classes --------------------------- */
-
-/***********************************************************************/
-/* INI, XDB and XCL tables. */
-/***********************************************************************/
-class DllExport INIDEF : public TABDEF { /* INI table description */
- friend class TDBINI;
- friend class TDBXIN;
- friend class TDBXTB;
- friend class TDBRTB;
- friend class TDBXCL;
- public:
- // Constructor
- INIDEF(void);
-
- // Implementation
- virtual const char *GetType(void) {return "INI";}
-
- // Methods
- virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
- virtual PTDB GetTable(PGLOBAL g, MODE m);
-
- protected:
- // Members
- char *Fn; /* Path/Name of corresponding file */
- char *Xname; /* The eventual table name */
- char Layout; /* R: Row, C: Column */
- int Ln; /* Length of section list buffer */
- }; // end of INIDEF
-
-/***********************************************************************/
-/* This is the class declaration for the INI tables. */
-/* These are tables represented by a INI like file. */
-/***********************************************************************/
-class TDBINI : public TDBASE {
- friend class INICOL;
- public:
- // Constructor
- TDBINI(PINIDEF tdp);
- TDBINI(PTDBINI tdbp);
-
- // Implementation
- virtual AMT GetAmType(void) {return TYPE_AM_INI;}
- virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBINI(this);}
-
- // Methods
- virtual PTDB CopyOne(PTABS t);
- virtual int GetRecpos(void) {return N;}
- virtual int GetProgCur(void) {return N;}
-//virtual int GetAffectedRows(void) {return 0;}
- virtual PSZ GetFile(PGLOBAL g) {return Ifile;}
- virtual void SetFile(PGLOBAL g, PSZ fn) {Ifile = fn;}
- virtual void ResetDB(void) {Seclist = Section = NULL; N = 0;}
- virtual void ResetSize(void) {MaxSize = -1; Seclist = NULL;}
- virtual int RowNumber(PGLOBAL g, bool b = false) {return N;}
- char *GetSeclist(PGLOBAL g);
-
- // Database routines
- virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
- virtual int Cardinality(PGLOBAL g);
- virtual int GetMaxSize(PGLOBAL g);
- virtual bool OpenDB(PGLOBAL g);
- virtual int ReadDB(PGLOBAL g);
- virtual int WriteDB(PGLOBAL g);
- virtual int DeleteDB(PGLOBAL g, int irc);
- virtual void CloseDB(PGLOBAL g);
-
- protected:
- // Members
- char *Ifile; // The INI file
- char *Seclist; // The section list
- char *Section; // The current section
- int Seclen; // Length of seclist buffer
- int N; // The current section index
- }; // end of class TDBINI
-
-/***********************************************************************/
-/* Class INICOL: XDB table access method column descriptor. */
-/***********************************************************************/
-class INICOL : public COLBLK {
- public:
- // Constructors
- INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "INI");
- INICOL(INICOL *colp, PTDB tdbp); // Constructor used in copy process
-
- // Implementation
- virtual int GetAmType(void) {return TYPE_AM_INI;}
- virtual void SetTo_Val(PVAL valp) {To_Val = valp;}
-
- // Methods
- virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
- virtual void ReadColumn(PGLOBAL g);
- virtual void WriteColumn(PGLOBAL g);
- virtual void AllocBuf(PGLOBAL g);
-
- protected:
- // Default constructor not to be used
- INICOL(void) {}
-
- // Members
- char *Valbuf; // To the key value buffer
- int Flag; // Tells what set in value
- int Long; // Buffer length
- PVAL To_Val; // To value used for Update/Insert
- }; // end of class INICOL
-
-/* --------------------------- XINI class ---------------------------- */
-
-/***********************************************************************/
-/* This is the class declaration for the XINI tables. */
-/* These are tables represented by a INI like file */
-/* having 3 columns Section, Key, and Value. */
-/***********************************************************************/
-class TDBXIN : public TDBINI {
- friend class XINCOL;
- public:
- // Constructor
- TDBXIN(PINIDEF tdp);
- TDBXIN(PTDBXIN tdbp);
-
- // Implementation
- virtual AMT GetAmType(void) {return TYPE_AM_INI;}
- virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBXIN(this);}
-
- // Methods
- virtual PTDB CopyOne(PTABS t);
- virtual int GetRecpos(void);
- virtual bool SetRecpos(PGLOBAL g, int recpos);
- virtual void ResetDB(void)
- {Seclist = Section = Keycur = NULL; N = 0; Oldsec = -1;}
- char *GetKeylist(PGLOBAL g, char *sec);
-
- // Database routines
- virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
- virtual int Cardinality(PGLOBAL g);
- virtual bool OpenDB(PGLOBAL g);
- virtual int ReadDB(PGLOBAL g);
- virtual int WriteDB(PGLOBAL g);
- virtual int DeleteDB(PGLOBAL g, int irc);
-
- protected:
- // Members
- char *Keylist; // The key list
- char *Keycur; // The current key
- int Keylen; // Length of keylist buffer
- short Oldsec; // Last current section
- }; // end of class TDBXIN
-
-/***********************************************************************/
-/* Class XINCOL: XIN table access method column descriptor. */
-/***********************************************************************/
-class XINCOL : public INICOL {
- public:
- // Constructors
- XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "INI");
- XINCOL(XINCOL *colp, PTDB tdbp); // Constructor used in copy process
-
- // Implementation
-
- // Methods
- virtual void ReadColumn(PGLOBAL g);
- virtual void WriteColumn(PGLOBAL g);
-
- protected:
- // Default constructor not to be used
- XINCOL(void) {}
-
- // Members
- }; // end of class XINICOL
+/*************** TabSys H Declares Source Code File (.H) ***************/
+/* Name: TABSYS.H Version 2.3 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2004-2014 */
+/* */
+/* This file contains the XDB system tables classes declares. */
+/***********************************************************************/
+typedef class INIDEF *PINIDEF;
+typedef class TDBINI *PTDBINI;
+typedef class INICOL *PINICOL;
+typedef class TDBXIN *PTDBXIN;
+typedef class XINCOL *PXINCOL;
+
+/* --------------------------- INI classes --------------------------- */
+
+/***********************************************************************/
+/* INI, XDB and XCL tables. */
+/***********************************************************************/
+class DllExport INIDEF : public TABDEF { /* INI table description */
+ friend class TDBINI;
+ friend class TDBXIN;
+ friend class TDBXTB;
+ friend class TDBRTB;
+ friend class TDBXCL;
+ public:
+ // Constructor
+ INIDEF(void);
+
+ // Implementation
+ virtual const char *GetType(void) {return "INI";}
+
+ // Methods
+ virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
+ virtual PTDB GetTable(PGLOBAL g, MODE m);
+
+ protected:
+ // Members
+ char *Fn; /* Path/Name of corresponding file */
+ char *Xname; /* The eventual table name */
+ char Layout; /* R: Row, C: Column */
+ int Ln; /* Length of section list buffer */
+ }; // end of INIDEF
+
+/***********************************************************************/
+/* This is the class declaration for the INI tables. */
+/* These are tables represented by a INI like file. */
+/***********************************************************************/
+class TDBINI : public TDBASE {
+ friend class INICOL;
+ public:
+ // Constructor
+ TDBINI(PINIDEF tdp);
+ TDBINI(PTDBINI tdbp);
+
+ // Implementation
+ virtual AMT GetAmType(void) {return TYPE_AM_INI;}
+ virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBINI(this);}
+
+ // Methods
+ virtual PTDB CopyOne(PTABS t);
+ virtual int GetRecpos(void) {return N;}
+ virtual int GetProgCur(void) {return N;}
+//virtual int GetAffectedRows(void) {return 0;}
+ virtual PSZ GetFile(PGLOBAL g) {return Ifile;}
+ virtual void SetFile(PGLOBAL g, PSZ fn) {Ifile = fn;}
+ virtual void ResetDB(void) {Seclist = Section = NULL; N = 0;}
+ virtual void ResetSize(void) {MaxSize = -1; Seclist = NULL;}
+ virtual int RowNumber(PGLOBAL g, bool b = false) {return N;}
+ char *GetSeclist(PGLOBAL g);
+
+ // Database routines
+ virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual int Cardinality(PGLOBAL g);
+ virtual int GetMaxSize(PGLOBAL g);
+ virtual bool OpenDB(PGLOBAL g);
+ virtual int ReadDB(PGLOBAL g);
+ virtual int WriteDB(PGLOBAL g);
+ virtual int DeleteDB(PGLOBAL g, int irc);
+ virtual void CloseDB(PGLOBAL g);
+
+ protected:
+ // Members
+ char *Ifile; // The INI file
+ char *Seclist; // The section list
+ char *Section; // The current section
+ int Seclen; // Length of seclist buffer
+ int N; // The current section index
+ }; // end of class TDBINI
+
+/***********************************************************************/
+/* Class INICOL: XDB table access method column descriptor. */
+/***********************************************************************/
+class INICOL : public COLBLK {
+ public:
+ // Constructors
+ INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "INI");
+ INICOL(INICOL *colp, PTDB tdbp); // Constructor used in copy process
+
+ // Implementation
+ virtual int GetAmType(void) {return TYPE_AM_INI;}
+ virtual void SetTo_Val(PVAL valp) {To_Val = valp;}
+
+ // Methods
+ virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
+ virtual void ReadColumn(PGLOBAL g);
+ virtual void WriteColumn(PGLOBAL g);
+ virtual void AllocBuf(PGLOBAL g);
+
+ protected:
+ // Default constructor not to be used
+ INICOL(void) {}
+
+ // Members
+ char *Valbuf; // To the key value buffer
+ int Flag; // Tells what set in value
+ int Long; // Buffer length
+ PVAL To_Val; // To value used for Update/Insert
+ }; // end of class INICOL
+
+/* --------------------------- XINI class ---------------------------- */
+
+/***********************************************************************/
+/* This is the class declaration for the XINI tables. */
+/* These are tables represented by a INI like file */
+/* having 3 columns Section, Key, and Value. */
+/***********************************************************************/
+class TDBXIN : public TDBINI {
+ friend class XINCOL;
+ public:
+ // Constructor
+ TDBXIN(PINIDEF tdp);
+ TDBXIN(PTDBXIN tdbp);
+
+ // Implementation
+ virtual AMT GetAmType(void) {return TYPE_AM_INI;}
+ virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBXIN(this);}
+
+ // Methods
+ virtual PTDB CopyOne(PTABS t);
+ virtual int GetRecpos(void);
+ virtual bool SetRecpos(PGLOBAL g, int recpos);
+ virtual void ResetDB(void)
+ {Seclist = Section = Keycur = NULL; N = 0; Oldsec = -1;}
+ char *GetKeylist(PGLOBAL g, char *sec);
+
+ // Database routines
+ virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual int Cardinality(PGLOBAL g);
+ virtual bool OpenDB(PGLOBAL g);
+ virtual int ReadDB(PGLOBAL g);
+ virtual int WriteDB(PGLOBAL g);
+ virtual int DeleteDB(PGLOBAL g, int irc);
+
+ protected:
+ // Members
+ char *Keylist; // The key list
+ char *Keycur; // The current key
+ int Keylen; // Length of keylist buffer
+ short Oldsec; // Last current section
+ }; // end of class TDBXIN
+
+/***********************************************************************/
+/* Class XINCOL: XIN table access method column descriptor. */
+/***********************************************************************/
+class XINCOL : public INICOL {
+ public:
+ // Constructors
+ XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "INI");
+ XINCOL(XINCOL *colp, PTDB tdbp); // Constructor used in copy process
+
+ // Implementation
+
+ // Methods
+ virtual void ReadColumn(PGLOBAL g);
+ virtual void WriteColumn(PGLOBAL g);
+
+ protected:
+ // Default constructor not to be used
+ XINCOL(void) {}
+
+ // Members
+ }; // end of class XINICOL
diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp
index 22ec3849b6f..7f979eaf4be 100644
--- a/storage/connect/tabtbl.cpp
+++ b/storage/connect/tabtbl.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to PlugDB Software Development 2008-2014 */
+/* (C) Copyright to PlugDB Software Development 2008-2015 */
/* Author: Olivier BERTRAND */
/* */
/* WHAT THIS PROGRAM DOES: */
@@ -39,7 +39,7 @@
//#include "sql_base.h"
#include "my_global.h"
#include "table.h" // MySQL table definitions
-#if defined(WIN32)
+#if defined(__WIN__)
#include <stdlib.h>
#include <stdio.h>
#if defined(__BORLANDC__)
@@ -70,21 +70,18 @@
#include "tabcol.h"
#include "tabdos.h" // TDBDOS and DOSCOL class dcls
#include "tabtbl.h"
-#if defined(MYSQL_SUPPORT)
#include "tabmysql.h"
-#endif // MYSQL_SUPPORT
#include "ha_connect.h"
-#include "mycat.h" // For GetHandler
-#if defined(WIN32)
+#if defined(__WIN__)
#if defined(__BORLANDC__)
#define SYSEXIT void _USERENTRY
#else
#define SYSEXIT void
#endif
-#else // !WIN32
+#else // !__WIN__
#define SYSEXIT void *
-#endif // !WIN32
+#endif // !__WIN__
/* ---------------------------- Class TBLDEF ---------------------------- */
@@ -104,7 +101,7 @@ TBLDEF::TBLDEF(void)
/**************************************************************************/
/* DefineAM: define specific AM block values from XDB file. */
/**************************************************************************/
-bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR, int)
{
char *tablist, *dbname, *def = NULL;
@@ -164,7 +161,7 @@ bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
/* GetTable: makes a new Table Description Block. */
/***********************************************************************/
-PTDB TBLDEF::GetTable(PGLOBAL g, MODE m)
+PTDB TBLDEF::GetTable(PGLOBAL g, MODE)
{
if (Catfunc == FNC_COL)
return new(g) TDBTBC(this);
@@ -205,7 +202,7 @@ PCOL TDBTBL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/
/* InsertSpecialColumn: Put a special column ahead of the column list.*/
/***********************************************************************/
-PCOL TDBTBL::InsertSpecialColumn(PGLOBAL g, PCOL scp)
+PCOL TDBTBL::InsertSpecialColumn(PCOL scp)
{
PCOL colp;
@@ -266,7 +263,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
// Real initialization will be done later.
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial())
- if (((PPRXCOL)colp)->Init(g) && !Accept)
+ if (((PPRXCOL)colp)->Init(g, NULL) && !Accept)
return TRUE;
if (Tablist)
@@ -352,7 +349,9 @@ bool TDBTBL::TestFil(PGLOBAL g, PCFIL filp, PTABLE tabp)
/***********************************************************************/
int TDBTBL::Cardinality(PGLOBAL g)
{
- if (Cardinal < 0) {
+ if (!g)
+ return 0; // Cannot make the table list
+ else if (Cardinal < 0) {
int tsz;
if (!Tablist && InitTableList(g))
@@ -468,7 +467,7 @@ bool TDBTBL::OpenDB(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
- else if (((PPRXCOL)cp)->Init(g) && !Accept)
+ else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return TRUE;
if (trace)
@@ -523,7 +522,7 @@ int TDBTBL::ReadDB(PGLOBAL g)
if (cp->GetAmType() == TYPE_AM_TABID ||
cp->GetAmType() == TYPE_AM_SRVID)
cp->COLBLK::Reset();
- else if (((PPRXCOL)cp)->Init(g) && !Accept)
+ else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return RC_FX;
if (trace)
@@ -549,7 +548,7 @@ int TDBTBL::ReadDB(PGLOBAL g)
/***********************************************************************/
/* ReadColumn: */
/***********************************************************************/
-void TBTBLK::ReadColumn(PGLOBAL g)
+void TBTBLK::ReadColumn(PGLOBAL)
{
if (trace)
htrc("TBT ReadColumn: name=%s\n", Name);
@@ -716,7 +715,7 @@ bool TDBTBM::OpenDB(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
- else if (((PPRXCOL)cp)->Init(g) && !Accept)
+ else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return TRUE;
if (trace)
@@ -807,7 +806,7 @@ int TDBTBM::ReadNextRemote(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
- else if (((PPRXCOL)cp)->Init(g) && !Accept)
+ else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return RC_FX;
if (trace)
diff --git a/storage/connect/tabtbl.h b/storage/connect/tabtbl.h
index 8bf440985ea..9d3f297f9e7 100644
--- a/storage/connect/tabtbl.h
+++ b/storage/connect/tabtbl.h
@@ -81,7 +81,7 @@ class DllExport TDBTBL : public TDBPRX {
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual int RowNumber(PGLOBAL g, bool b = FALSE);
- virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL scp);
+ virtual PCOL InsertSpecialColumn(PCOL scp);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp
index d469594916f..331a7f45d4d 100644
--- a/storage/connect/tabutil.cpp
+++ b/storage/connect/tabutil.cpp
@@ -1,7 +1,7 @@
/************* Tabutil cpp Declares Source Code File (.CPP) ************/
-/* Name: TABUTIL.CPP Version 1.0 */
+/* Name: TABUTIL.CPP Version 1.1 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2013 - 2015 */
/* */
/* Utility function used by the PROXY, XCOL, OCCUR, and TBL tables. */
/***********************************************************************/
@@ -9,11 +9,12 @@
/***********************************************************************/
/* Include relevant section of system dependant header files. */
/***********************************************************************/
-#include "my_global.h"
+#define MYSQL_SERVER 1
+#include <my_global.h>
#include "sql_class.h"
#include "table.h"
#include "field.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <stdlib.h>
#include <stdio.h>
#if defined(__BORLANDC__)
@@ -42,19 +43,16 @@
#include "plgdbsem.h"
#include "plgcnx.h" // For DB types
#include "myutil.h"
-#include "mycat.h"
#include "valblk.h"
#include "resource.h"
#include "reldef.h"
#include "xtable.h"
-#if defined(MYSQL_SUPPORT)
#include "tabmysql.h"
-#endif // MYSQL_SUPPORT
#include "tabcol.h"
#include "tabutil.h"
#include "ha_connect.h"
-extern "C" int zconv;
+int GetConvSize(void);
/************************************************************************/
/* Used by MYSQL tables to get MySQL parameters from the calling proxy */
@@ -73,11 +71,8 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
{
char key[256];
uint k;
-//TABLE_LIST table_list;
TABLE_SHARE *s;
-//table_list.init_one_table(db, strlen(db), name, strlen(name),
-// NULL, TL_IGNORE);
k = sprintf(key, "%s", db) + 1;
k += sprintf(key + k, "%s", name);
key[++k] = 0;
@@ -87,26 +82,20 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
return NULL;
} // endif s
-// 1 2 4 8
-//flags = GTS_TABLE | GTS_VIEW | GTS_NOLOCK | GTS_FORCE_DISCOVERY;
-
if (!open_table_def(thd, s, GTS_TABLE | GTS_VIEW)) {
if (!s->is_view) {
- if (stricmp(plugin_name(s->db_plugin)->str, "connect")) {
-#if defined(MYSQL_SUPPORT)
+ if (stricmp(plugin_name(s->db_plugin)->str, "connect"))
mysql = true;
-#else // !MYSQL_SUPPORT
- sprintf(g->Message, "%s.%s is not a CONNECT table", db, name);
- return NULL;
-#endif // MYSQL_SUPPORT
- } else
+ else
mysql = false;
- } else {
+ } else
mysql = true;
- } // endif is_view
} else {
+ if (thd->is_error())
+ thd->clear_error(); // Avoid stopping info commands
+
sprintf(g->Message, "Error %d opening share\n", s->error);
free_table_share(s);
return NULL;
@@ -132,6 +121,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
char *fld, *colname, *chset, *fmt, v;
int i, n, ncol = sizeof(buftyp) / sizeof(int);
int prec, len, type, scale;
+ int zconv = GetConvSize();
bool mysql;
TABLE_SHARE *s = NULL;
Field* *field;
@@ -302,7 +292,7 @@ PRXDEF::PRXDEF(void)
/***********************************************************************/
/* DefineAM: define specific AM block values from XCOL file. */
/***********************************************************************/
-bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR, int)
{
char *pn, *db, *tab, *def = NULL;
@@ -332,7 +322,7 @@ bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
/* GetTable: makes a new TDB of the proper type. */
/***********************************************************************/
-PTDB PRXDEF::GetTable(PGLOBAL g, MODE mode)
+PTDB PRXDEF::GetTable(PGLOBAL g, MODE)
{
if (Catfunc == FNC_COL)
return new(g) TDBTBC(this);
@@ -351,7 +341,7 @@ TDBPRX::TDBPRX(PPRXDEF tdp) : TDBASE(tdp)
Tdbp = NULL; // The object table
} // end of TDBPRX constructor
-TDBPRX::TDBPRX(PGLOBAL g, PTDBPRX tdbp) : TDBASE(tdbp)
+TDBPRX::TDBPRX(PTDBPRX tdbp) : TDBASE(tdbp)
{
Tdbp = tdbp->Tdbp;
} // end of TDBPRX copy constructor
@@ -363,7 +353,7 @@ PTDB TDBPRX::CopyOne(PTABS t)
PPRXCOL cp1, cp2;
PGLOBAL g = t->G;
- tp = new(g) TDBPRX(g, this);
+ tp = new(g) TDBPRX(this);
for (cp1 = (PPRXCOL)Columns; cp1; cp1 = (PPRXCOL)cp1->GetNext()) {
cp2 = new(g) PRXCOL(cp1, tp); // Make a copy
@@ -422,7 +412,6 @@ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b)
} // endif srcdef
if (mysql) {
-#if defined(MYSQL_SUPPORT)
// Access sub-table via MySQL API
if (!(tdbp= cat->GetTable(g, tabp, Mode, "MYPRX"))) {
char buf[MAX_STR];
@@ -439,11 +428,6 @@ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b)
if (Mode == MODE_UPDATE || Mode == MODE_DELETE)
tdbp->SetName(Name); // For Make_Command
-#else // !MYSQL_SUPPORT
- sprintf(g->Message, "%s.%s is not a CONNECT table",
- db, tblp->Name);
- goto err;
-#endif // MYSQL_SUPPORT
} else {
// Sub-table is a CONNECT table
tabp->Next = To_Table; // For loop checking
@@ -669,6 +653,22 @@ PRXCOL::PRXCOL(PRXCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
} // end of PRXCOL copy constructor
/***********************************************************************/
+/* Convert an UTF-8 name to latin characters. */
+/***********************************************************************/
+char *PRXCOL::Decode(PGLOBAL g, const char *cnm)
+ {
+ char *buf= (char*)PlugSubAlloc(g, NULL, strlen(cnm) + 1);
+ uint dummy_errors;
+ uint32 len= copy_and_convert(buf, strlen(cnm) + 1,
+ &my_charset_latin1,
+ cnm, strlen(cnm),
+ &my_charset_utf8_general_ci,
+ &dummy_errors);
+ buf[len]= '\0';
+ return buf;
+ } // end of Decode
+
+/***********************************************************************/
/* PRXCOL initialization routine. */
/* Look for the matching column in the object table. */
/***********************************************************************/
@@ -683,6 +683,9 @@ bool PRXCOL::Init(PGLOBAL g, PTDBASE tp)
if (Colp) {
MODE mode = To_Tdb->GetMode();
+ // Needed for MYSQL subtables
+ ((XCOLBLK*)Colp)->Name = Decode(g, Colp->GetName());
+
// May not have been done elsewhere
Colp->InitValue(g);
To_Val = Colp->GetValue();
diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h
index 606e532d526..b320d169b36 100644
--- a/storage/connect/tabutil.h
+++ b/storage/connect/tabutil.h
@@ -59,12 +59,12 @@ class DllExport TDBPRX : public TDBASE {
public:
// Constructors
TDBPRX(PPRXDEF tdp);
- TDBPRX(PGLOBAL g, PTDBPRX tdbp);
+ TDBPRX(PTDBPRX tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_PRX;}
virtual PTDB Duplicate(PGLOBAL g)
- {return (PTDB)new(g) TDBPRX(g, this);}
+ {return (PTDB)new(g) TDBPRX(this);}
// Methods
virtual PTDB CopyOne(PTABS t);
@@ -108,15 +108,18 @@ class DllExport PRXCOL : public COLBLK {
virtual int GetAmType(void) {return TYPE_AM_PRX;}
// Methods
+ using COLBLK::Init;
virtual void Reset(void);
virtual bool IsSpecial(void) {return Pseudo;}
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
{return false;}
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
- virtual bool Init(PGLOBAL g, PTDBASE tp = NULL);
+ virtual bool Init(PGLOBAL g, PTDBASE tp);
protected:
+ char *Decode(PGLOBAL g, const char *cnm);
+
// Default constructor not to be used
PRXCOL(void) {}
@@ -144,4 +147,8 @@ class TDBTBC : public TDBCAT {
PSZ Tab; // Table name
}; // end of class TDBMCL
+class XCOLBLK : public COLBLK {
+ friend class PRXCOL;
+}; // end of class XCOLBLK
+
#endif // TABUTIL
diff --git a/storage/connect/tabvct.cpp b/storage/connect/tabvct.cpp
index 3ed40540395..e788529075f 100644
--- a/storage/connect/tabvct.cpp
+++ b/storage/connect/tabvct.cpp
@@ -5,7 +5,7 @@
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1999-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 1999-2015 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -35,7 +35,7 @@
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <fcntl.h>
#if defined(__BORLANDC__)
@@ -94,7 +94,7 @@ PVBLK AllocValBlock(PGLOBAL, void *, int, int, int, int,
/***********************************************************************/
/* DefineAM: define specific AM block values from XDB file. */
/***********************************************************************/
-bool VCTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+bool VCTDEF::DefineAM(PGLOBAL g, LPCSTR, int poff)
{
DOSDEF::DefineAM(g, "BIN", poff);
@@ -146,7 +146,7 @@ bool VCTDEF::Erase(char *filename)
for (i = 1, cdp = To_Cols; cdp; i++, cdp = cdp->GetNext()) {
sprintf(filename, fpat, i);
-//#if defined(WIN32)
+//#if defined(__WIN__)
// rc |= !DeleteFile(filename);
//#else // UNIX
rc |= remove(filename);
@@ -175,7 +175,7 @@ bool VCTDEF::Erase(char *filename)
int VCTDEF::MakeFnPattern(char *fpat)
{
char pat[8];
-#if !defined(UNIX)
+#if defined(__WIN__)
char drive[_MAX_DRIVE];
#else
char *drive = NULL;
@@ -290,7 +290,7 @@ PCOL TDBVCT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/
/* VEC tables are not ready yet to use temporary files. */
/***********************************************************************/
-bool TDBVCT::IsUsingTemp(PGLOBAL g)
+bool TDBVCT::IsUsingTemp(PGLOBAL)
{
// For developpers
return (UseTemp() == TMP_TEST);
@@ -570,7 +570,7 @@ void VCTCOL::ReadColumn(PGLOBAL g)
/* On each change of block the buffer is written back to file and */
/* in mode Insert the buffer is filled with the block to update. */
/***********************************************************************/
-void VCTCOL::WriteColumn(PGLOBAL g)
+void VCTCOL::WriteColumn(PGLOBAL)
{
PTXF txfp = ((PTDBVCT)To_Tdb)->Txfp;;
diff --git a/storage/connect/tabvir.cpp b/storage/connect/tabvir.cpp
index b4c76f5ad56..356fc981357 100644
--- a/storage/connect/tabvir.cpp
+++ b/storage/connect/tabvir.cpp
@@ -29,7 +29,7 @@
/***********************************************************************/
/* Return the unique column definition to MariaDB. */
/***********************************************************************/
-PQRYRES VirColumns(PGLOBAL g, char *tab, char *db, bool info)
+PQRYRES VirColumns(PGLOBAL g, bool info)
{
int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_STRING, TYPE_STRING};
@@ -95,7 +95,7 @@ PQRYRES VirColumns(PGLOBAL g, char *tab, char *db, bool info)
/***********************************************************************/
/* GetTable: makes a new Table Description Block. */
/***********************************************************************/
-PTDB VIRDEF::GetTable(PGLOBAL g, MODE m)
+PTDB VIRDEF::GetTable(PGLOBAL g, MODE)
{
// Column blocks will be allocated only when needed.
if (Catfunc == FNC_COL)
@@ -241,7 +241,7 @@ bool TDBVIR::OpenDB(PGLOBAL g)
/***********************************************************************/
/* Data Base read routine for the VIR access method. */
/***********************************************************************/
-int TDBVIR::ReadDB(PGLOBAL g)
+int TDBVIR::ReadDB(PGLOBAL)
{
return (++N >= Size) ? RC_EF : RC_OK;
} // end of ReadDB
@@ -258,7 +258,7 @@ int TDBVIR::WriteDB(PGLOBAL g)
/***********************************************************************/
/* Data Base delete line routine for the VIR access methods. */
/***********************************************************************/
-int TDBVIR::DeleteDB(PGLOBAL g, int irc)
+int TDBVIR::DeleteDB(PGLOBAL g, int)
{
sprintf(g->Message, MSG(VIR_NO_DELETE), To_Def->GetType());
return RC_FX;
@@ -269,7 +269,7 @@ int TDBVIR::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
/* VIRCOL public constructor. */
/***********************************************************************/
-VIRCOL::VIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+VIRCOL::VIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ)
: COLBLK(cdp, tdbp, i)
{
if (cprec) {
@@ -299,7 +299,7 @@ void VIRCOL::ReadColumn(PGLOBAL g)
/***********************************************************************/
PQRYRES TDBVICL::GetResult(PGLOBAL g)
{
- return VirColumns(g, NULL, NULL, false);
+ return VirColumns(g, false);
} // end of GetResult
/* ------------------------- End of Virtual -------------------------- */
diff --git a/storage/connect/tabvir.h b/storage/connect/tabvir.h
index 8d0caa257e7..a53aceaeceb 100644
--- a/storage/connect/tabvir.h
+++ b/storage/connect/tabvir.h
@@ -11,7 +11,7 @@ typedef class TDBVIR *PTDBVIR;
/***********************************************************************/
/* Return the unique column definition to MariaDB. */
/***********************************************************************/
-PQRYRES VirColumns(PGLOBAL g, char *tab, char *db, bool info);
+PQRYRES VirColumns(PGLOBAL g, bool info);
/* --------------------------- VIR classes --------------------------- */
diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp
index 7c69426a066..98a44b9d635 100644
--- a/storage/connect/tabwmi.cpp
+++ b/storage/connect/tabwmi.cpp
@@ -2,9 +2,9 @@
/* TABWMI: Author Olivier Bertrand -- PlugDB -- 2012 - 2013 */
/* TABWMI: Virtual table to get WMI information. */
/***********************************************************************/
-#if !defined(WIN32)
-#error This is a WIN32 only table type
-#endif // !WIN32
+#if !defined(__WIN__)
+#error This is a WINDOWS only table type
+#endif // !__WIN__
#include "my_global.h"
#include <stdio.h>
diff --git a/storage/connect/tabxcl.cpp b/storage/connect/tabxcl.cpp
index 57f0e1e03b9..add61431493 100644
--- a/storage/connect/tabxcl.cpp
+++ b/storage/connect/tabxcl.cpp
@@ -17,7 +17,7 @@
/***********************************************************************/
#include "my_global.h"
#include "table.h" // MySQL table definitions
-#if defined(WIN32)
+#if defined(__WIN__)
#include <stdlib.h>
#include <stdio.h>
#if defined(__BORLANDC__)
@@ -51,11 +51,8 @@
#include "tabcol.h"
#include "tabxcl.h"
#include "xtable.h"
-#if defined(MYSQL_SUPPORT)
#include "tabmysql.h"
-#endif // MYSQL_SUPPORT
#include "ha_connect.h"
-#include "mycat.h"
/* -------------- Implementation of the XCOL classes ---------------- */
@@ -86,7 +83,7 @@ bool XCLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
/* GetTable: makes a new TDB of the proper type. */
/***********************************************************************/
-PTDB XCLDEF::GetTable(PGLOBAL g, MODE mode)
+PTDB XCLDEF::GetTable(PGLOBAL g, MODE)
{
if (Catfunc == FNC_COL)
return new(g) TDBTBC(this);
@@ -120,7 +117,7 @@ PCOL TDBXCL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
PCOL colp;
if (!stricmp(cdp->GetName(), Xcolumn)) {
- Xcolp = new(g) XCLCOL(g, cdp, this, cprec, n);
+ Xcolp = new(g) XCLCOL(cdp, this, cprec, n);
colp = Xcolp;
} else
colp = new(g) PRXCOL(cdp, this, cprec, n);
@@ -147,7 +144,7 @@ int TDBXCL::GetMaxSize(PGLOBAL g)
/* For this table type, ROWID is the (virtual) row number, */
/* while ROWNUM is be the occurence rank in the multiple column. */
/***********************************************************************/
-int TDBXCL::RowNumber(PGLOBAL g, bool b)
+int TDBXCL::RowNumber(PGLOBAL, bool b)
{
return (b) ? M : N;
} // end of RowNumber
@@ -183,7 +180,7 @@ bool TDBXCL::OpenDB(PGLOBAL g)
/*********************************************************************/
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (!cp->IsSpecial())
- if (((PPRXCOL)cp)->Init(g))
+ if (((PPRXCOL)cp)->Init(g, NULL))
return TRUE;
/*********************************************************************/
@@ -235,7 +232,7 @@ int TDBXCL::ReadDB(PGLOBAL g)
/***********************************************************************/
/* XCLCOL public constructor. */
/***********************************************************************/
-XCLCOL::XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
+XCLCOL::XCLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
: PRXCOL(cdp, tdbp, cprec, i, "XCL")
{
// Set additional XXL access method information for column.
diff --git a/storage/connect/tabxcl.h b/storage/connect/tabxcl.h
index 7e11600c090..291f0b4263a 100644
--- a/storage/connect/tabxcl.h
+++ b/storage/connect/tabxcl.h
@@ -85,9 +85,10 @@ class XCLCOL : public PRXCOL {
friend class TDBXCL;
public:
// Constructors
- XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
+ XCLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
// Methods
+ using PRXCOL::Init;
virtual void Reset(void) {} // Evaluated only by TDBXCL
virtual void ReadColumn(PGLOBAL g);
virtual bool Init(PGLOBAL g, PTDBASE tp = NULL);
diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp
index 8c73907c7ee..49fa9a1c554 100644
--- a/storage/connect/tabxml.cpp
+++ b/storage/connect/tabxml.cpp
@@ -1,9 +1,9 @@
/************* Tabxml C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABXML */
/* ------------- */
-/* Version 2.7 */
+/* Version 2.8 */
/* */
-/* Author Olivier BERTRAND 2007 - 2014 */
+/* Author Olivier BERTRAND 2007 - 2015 */
/* */
/* This program are the XML tables classes using MS-DOM or libxml2. */
/***********************************************************************/
@@ -15,12 +15,12 @@
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <winsock2.h>
//#include <windows.h>
#include <comdef.h>
-#else // !WIN32
+#else // !__WIN__
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -28,7 +28,8 @@
//#include <ctype.h>
#include "osutil.h"
#define _O_RDONLY O_RDONLY
-#endif // !WIN32
+#endif // !__WIN__
+#include "resource.h" // for IDS_COLUMNS
#define INCLUDE_TDBXML
#define NODE_TYPE_LIST
@@ -44,6 +45,7 @@
#include "reldef.h"
#include "xtable.h"
#include "colblk.h"
+#include "mycat.h"
#include "xindex.h"
#include "plgxml.h"
#include "tabxml.h"
@@ -51,11 +53,355 @@
extern "C" char version[];
-#if defined(WIN32) && defined(DOMDOC_SUPPORT)
+#if defined(__WIN__) && defined(DOMDOC_SUPPORT)
#define XMLSUP "MS-DOM"
-#else // !WIN32
+#else // !__WIN__
#define XMLSUP "libxml2"
-#endif // !WIN32
+#endif // !__WIN__
+
+#define TYPE_UNKNOWN 12 /* Must be greater than other types */
+
+/***********************************************************************/
+/* Class and structure used by XMLColumns. */
+/***********************************************************************/
+typedef class XMCOL *PXCL;
+
+class XMCOL : public BLOCK {
+ public:
+ // Constructors
+ XMCOL(void) {Next = NULL;
+ Name[0] = 0;
+ Fmt = NULL;
+ Type = 1;
+ Len = Scale = 0;
+ Cbn = false;
+ Found = true;}
+ XMCOL(PGLOBAL g, PXCL xp, char *fmt, int i) {
+ Next = NULL;
+ strcpy(Name, xp->Name);
+ Fmt = (*fmt) ? PlugDup(g, fmt) : NULL;
+ Type = xp->Type;
+ Len = xp->Len;
+ Scale = xp->Scale;
+ Cbn = (xp->Cbn || i > 1);
+ Found = true;}
+
+ // Members
+ PXCL Next;
+ char Name[64];
+ char *Fmt;
+ int Type;
+ int Len;
+ int Scale;
+ bool Cbn;
+ bool Found;
+}; // end of class XMCOL
+
+typedef struct LVL {
+ PXNODE pn;
+ PXLIST nl;
+ PXATTR atp;
+ bool b;
+ long k;
+ int m, n;
+} *PLVL;
+
+/***********************************************************************/
+/* XMLColumns: construct the result blocks containing the description */
+/* of all the columns of a table contained inside an XML file. */
+/***********************************************************************/
+PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
+{
+ static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
+ TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
+ static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
+ FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT};
+ static unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0};
+ char *fn, *op, colname[65], fmt[129], buf[512];
+ int i, j, lvl, n = 0;
+ int ncol = sizeof(buftyp) / sizeof(int);
+ bool ok = true;
+ PXCL xcol, xcp, fxcp = NULL, pxcp = NULL;
+ PLVL *lvlp, vp;
+ PXNODE node = NULL;
+ PXMLDEF tdp;
+ PTDBXML txmp;
+ PQRYRES qrp;
+ PCOLRES crp;
+
+ if (info) {
+ length[0] = 128;
+ length[7] = 256;
+ goto skipit;
+ } // endif info
+
+ /*********************************************************************/
+ /* Open the input file. */
+ /*********************************************************************/
+ if (!(fn = GetStringTableOption(g, topt, "Filename", NULL))) {
+ strcpy(g->Message, MSG(MISSING_FNAME));
+ return NULL;
+ } else {
+ lvl = GetIntegerTableOption(g, topt, "Level", 0);
+ lvl = (lvl < 0) ? 0 : (lvl > 16) ? 16 : lvl;
+ } // endif fn
+
+ if (trace)
+ htrc("File %s lvl=%d\n", topt->filename, lvl);
+
+ tdp = new(g) XMLDEF;
+ tdp->Fn = fn;
+ tdp->Database = SetPath(g, db);
+ tdp->Tabname = tab;
+
+ if (!(op = GetStringTableOption(g, topt, "Xmlsup", NULL)))
+#if defined(__WIN__)
+ tdp->Usedom = true;
+#else // !__WIN__
+ tdp->Usedom = false;
+#endif // !__WIN__
+ else
+ tdp->Usedom = (toupper(*op) == 'M' || toupper(*op) == 'D');
+
+ txmp = new(g) TDBXML(tdp);
+
+ if (txmp->Initialize(g))
+ goto err;
+
+ xcol = new(g) XMCOL;
+ colname[64] = 0;
+ fmt[128] = 0;
+ lvlp = (PLVL*)PlugSubAlloc(g, NULL, sizeof(PLVL) * (lvl + 1));
+
+ for (j = 0; j <= lvl; j++)
+ lvlp[j] = (PLVL)PlugSubAlloc(g, NULL, sizeof(LVL));
+
+ /*********************************************************************/
+ /* Analyse the XML tree and define columns. */
+ /*********************************************************************/
+ for (i = 1; ; i++) {
+ // Get next row
+ switch (txmp->ReadDB(g)) {
+ case RC_EF:
+ vp = NULL;
+ break;
+ case RC_FX:
+ goto err;
+ default:
+ vp = lvlp[0];
+ vp->pn = txmp->RowNode;
+ vp->atp = vp->pn->GetAttribute(g, NULL);
+ vp->nl = vp->pn->GetChildElements(g);
+ vp->b = true;
+ vp->k = 0;
+ vp->m = vp->n = 0;
+ j = 0;
+ } // endswitch ReadDB
+
+ if (!vp)
+ break;
+
+ while (true) {
+ if (!vp->atp &&
+ !(node = (vp->nl) ? vp->nl->GetItem(g, vp->k++, node) : NULL))
+ if (j) {
+ vp = lvlp[--j];
+
+ if (!tdp->Usedom) // nl was destroyed
+ vp->nl = vp->pn->GetChildElements(g);
+
+ if (!lvlp[j+1]->b) {
+ vp->k--;
+ ok = false;
+ } // endif b
+
+ continue;
+ } else
+ break;
+
+ xcol->Name[vp->n] = 0;
+ fmt[vp->m] = 0;
+
+ more:
+ if (vp->atp) {
+ strncpy(colname, vp->atp->GetName(g), sizeof(colname));
+ strncat(xcol->Name, colname, 64);
+
+ switch (vp->atp->GetText(g, buf, sizeof(buf))) {
+ case RC_INFO:
+ PushWarning(g, txmp);
+ case RC_OK:
+ strncat(fmt, "@", sizeof(fmt));
+ break;
+ default:
+ goto err;
+ } // enswitch rc
+
+ if (j)
+ strncat(fmt, colname, sizeof(fmt));
+
+ } else {
+ if (tdp->Usedom && node->GetType() != 1)
+ continue;
+
+ strncpy(colname, node->GetName(g), sizeof(colname));
+ strncat(xcol->Name, colname, 64);
+
+ if (j)
+ strncat(fmt, colname, sizeof(fmt));
+
+ if (j < lvl && ok) {
+ vp = lvlp[j+1];
+ vp->k = 0;
+ vp->atp = node->GetAttribute(g, NULL);
+ vp->nl = node->GetChildElements(g);
+
+ if (tdp->Usedom && vp->nl->GetLength() == 1) {
+ node = vp->nl->GetItem(g, 0, node);
+ vp->b = (node->GetType() == 1); // Must be ab element
+ } else
+ vp->b = (vp->nl && vp->nl->GetLength());
+
+ if (vp->atp || vp->b) {
+ if (!vp->atp)
+ node = vp->nl->GetItem(g, vp->k++, node);
+
+ strncat(strncat(fmt, colname, 125), "/", 125);
+ strncat(xcol->Name, "_", 64);
+ j++;
+ vp->n = (int)strlen(xcol->Name);
+ vp->m = (int)strlen(fmt);
+ goto more;
+ } else {
+ vp = lvlp[j];
+
+ if (!tdp->Usedom) // nl was destroyed
+ vp->nl = vp->pn->GetChildElements(g);
+
+ } // endif vp
+
+ } else
+ ok = true;
+
+ switch (node->GetContent(g, buf, sizeof(buf))) {
+ case RC_INFO:
+ PushWarning(g, txmp);
+ case RC_OK:
+ break;
+ default:
+ goto err;
+ } // enswitch rc
+
+ } // endif atp;
+
+ xcol->Len = strlen(buf);
+
+ // Check whether this column was already found
+ for (xcp = fxcp; xcp; xcp = xcp->Next)
+ if (!strcmp(xcol->Name, xcp->Name))
+ break;
+
+ if (xcp) {
+ if (xcp->Type != xcol->Type)
+ xcp->Type = TYPE_STRING;
+
+ if (*fmt && (!xcp->Fmt || strlen(xcp->Fmt) < strlen(fmt))) {
+ xcp->Fmt = PlugDup(g, fmt);
+ length[7] = MY_MAX(length[7], strlen(fmt));
+ } // endif *fmt
+
+ xcp->Len = MY_MAX(xcp->Len, xcol->Len);
+ xcp->Scale = MY_MAX(xcp->Scale, xcol->Scale);
+ xcp->Cbn |= xcol->Cbn;
+ xcp->Found = true;
+ } else {
+ // New column
+ xcp = new(g) XMCOL(g, xcol, fmt, i);
+ length[0] = MY_MAX(length[0], strlen(xcol->Name));
+ length[7] = MY_MAX(length[7], strlen(fmt));
+
+ if (pxcp) {
+ xcp->Next = pxcp->Next;
+ pxcp->Next = xcp;
+ } else
+ fxcp = xcp;
+
+ n++;
+ } // endif xcp
+
+ pxcp = xcp;
+
+ if (vp->atp)
+ vp->atp = vp->atp->GetNext(g);
+
+ } // endwhile
+
+ // Missing column can be null
+ for (xcp = fxcp; xcp; xcp = xcp->Next) {
+ xcp->Cbn |= !xcp->Found;
+ xcp->Found = false;
+ } // endfor xcp
+
+ } // endor i
+
+ txmp->CloseDB(g);
+
+ skipit:
+ if (trace)
+ htrc("CSVColumns: n=%d len=%d\n", n, length[0]);
+
+ /*********************************************************************/
+ /* Allocate the structures used to refer to the result set. */
+ /*********************************************************************/
+ qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
+ buftyp, fldtyp, length, false, false);
+
+ crp = qrp->Colresp->Next->Next->Next->Next->Next->Next;
+ crp->Name = "Nullable";
+ crp->Next->Name = "Xpath";
+
+ if (info || !qrp)
+ return qrp;
+
+ qrp->Nblin = n;
+
+ /*********************************************************************/
+ /* Now get the results into blocks. */
+ /*********************************************************************/
+ for (i = 0, xcp = fxcp; xcp; i++, xcp = xcp->Next) {
+ if (xcp->Type == TYPE_UNKNOWN) // Void column
+ xcp->Type = TYPE_STRING;
+
+ crp = qrp->Colresp; // Column Name
+ crp->Kdata->SetValue(xcp->Name, i);
+ crp = crp->Next; // Data Type
+ crp->Kdata->SetValue(xcp->Type, i);
+ crp = crp->Next; // Type Name
+ crp->Kdata->SetValue(GetTypeName(xcp->Type), i);
+ crp = crp->Next; // Precision
+ crp->Kdata->SetValue(xcp->Len, i);
+ crp = crp->Next; // Length
+ crp->Kdata->SetValue(xcp->Len, i);
+ crp = crp->Next; // Scale (precision)
+ crp->Kdata->SetValue(xcp->Scale, i);
+ crp = crp->Next; // Nullable
+ crp->Kdata->SetValue(xcp->Cbn ? 1 : 0, i);
+ crp = crp->Next; // Field format
+
+ if (crp->Kdata)
+ crp->Kdata->SetValue(xcp->Fmt, i);
+
+ } // endfor i
+
+ /*********************************************************************/
+ /* Return the result pointer. */
+ /*********************************************************************/
+ return qrp;
+
+err:
+ txmp->CloseDB(g);
+ return NULL;
+ } // end of XMLColumns
/* -------------- Implementation of the XMLDEF class ---------------- */
@@ -88,9 +434,7 @@ XMLDEF::XMLDEF(void)
/***********************************************************************/
bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
- char *defrow, *defcol, buf[10];
-//void *memp = Cat->GetDescp();
-//PSZ dbfile = Cat->GetDescFile();
+ char *defrow, *defcol, buf[10];
Fn = GetStringCatInfo(g, "Filename", NULL);
Encoding = GetStringCatInfo(g, "Encoding", "UTF-8");
@@ -105,7 +449,7 @@ bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
return true;
} // endif flag
- defrow = defcol = "";
+ defrow = defcol = NULL;
GetCharCatInfo("Coltype", "", buf, sizeof(buf));
switch (toupper(*buf)) {
@@ -138,36 +482,29 @@ bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Tabname = GetStringCatInfo(g, "Tabname", Tabname);
Rowname = GetStringCatInfo(g, "Rownode", defrow);
Colname = GetStringCatInfo(g, "Colnode", defcol);
- Mulnode = GetStringCatInfo(g, "Mulnode", "");
- XmlDB = GetStringCatInfo(g, "XmlDB", "");
- Nslist = GetStringCatInfo(g, "Nslist", "");
- DefNs = GetStringCatInfo(g, "DefNs", "");
+ Mulnode = GetStringCatInfo(g, "Mulnode", NULL);
+ XmlDB = GetStringCatInfo(g, "XmlDB", NULL);
+ Nslist = GetStringCatInfo(g, "Nslist", NULL);
+ DefNs = GetStringCatInfo(g, "DefNs", NULL);
Limit = GetIntCatInfo("Limit", 10);
- Xpand = (GetIntCatInfo("Expand", 0) != 0);
+ Xpand = GetBoolCatInfo("Expand", false);
Header = GetIntCatInfo("Header", 0);
GetCharCatInfo("Xmlsup", "*", buf, sizeof(buf));
-//if (*buf == '*') // Try the old (deprecated) option
-// GetCharCatInfo("Method", "*", buf, sizeof(buf));
-
-//if (*buf == '*') // Is there a default for the database?
-// GetCharCatInfo("Defxml", XMLSUP, buf, sizeof(buf));
-
// Note that if no support is specified, the default is MS-DOM
// on Windows and libxml2 otherwise
if (*buf == '*')
-#if defined(WIN32)
+#if defined(__WIN__)
Usedom = true;
-#else // !WIN32
+#else // !__WIN__
Usedom = false;
-#endif // !WIN32
+#endif // !__WIN__
else
Usedom = (toupper(*buf) == 'M' || toupper(*buf) == 'D');
// Get eventual table node attribute
- Attrib = GetStringCatInfo(g, "Attribute", "");
- Hdattr = GetStringCatInfo(g, "HeadAttr", "");
-
+ Attrib = GetStringCatInfo(g, "Attribute", NULL);
+ Hdattr = GetStringCatInfo(g, "HeadAttr", NULL);
return false;
} // end of DefineAM
@@ -176,6 +513,9 @@ bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
PTDB XMLDEF::GetTable(PGLOBAL g, MODE m)
{
+ if (Catfunc == FNC_COL)
+ return new(g) TDBXCT(this);
+
PTDBASE tdbp = new(g) TDBXML(this);
if (Multiple)
@@ -184,30 +524,6 @@ PTDB XMLDEF::GetTable(PGLOBAL g, MODE m)
return tdbp;
} // end of GetTable
-#if 0
-/***********************************************************************/
-/* DeleteTableFile: Delete XML table files using platform API. */
-/***********************************************************************/
-bool XMLDEF::DeleteTableFile(PGLOBAL g)
- {
- char filename[_MAX_PATH];
- bool rc;
-
- // Delete the XML table file if not protected
- if (!IsReadOnly()) {
- PlugSetPath(filename, Fn, GetPath());
-#if defined(WIN32)
- rc = !DeleteFile(filename);
-#else // UNIX
- rc = remove(filename);
-#endif // UNIX
- } else
- rc =true;
-
- return rc; // Return true if error
- } // end of DeleteTableFile
-#endif // 0
-
/* ------------------------- TDBXML Class ---------------------------- */
/***********************************************************************/
@@ -229,14 +545,14 @@ TDBXML::TDBXML(PXMLDEF tdp) : TDBASE(tdp)
Xfile = tdp->Fn;
Enc = tdp->Encoding;
Tabname = tdp->Tabname;
- Rowname = (*tdp->Rowname) ? tdp->Rowname : NULL;
- Colname = (*tdp->Colname) ? tdp->Colname : NULL;
- Mulnode = (*tdp->Mulnode) ? tdp->Mulnode : NULL;
- XmlDB = (*tdp->XmlDB) ? tdp->XmlDB : NULL;
- Nslist = (*tdp->Nslist) ? tdp->Nslist : NULL;
- DefNs = (*tdp->DefNs) ? tdp->DefNs : NULL;
- Attrib = (*tdp->Attrib) ? tdp->Attrib : NULL;
- Hdattr = (*tdp->Hdattr) ? tdp->Hdattr : NULL;
+ Rowname = (tdp->Rowname) ? tdp->Rowname : NULL;
+ Colname = (tdp->Colname) ? tdp->Colname : NULL;
+ Mulnode = (tdp->Mulnode) ? tdp->Mulnode : NULL;
+ XmlDB = (tdp->XmlDB) ? tdp->XmlDB : NULL;
+ Nslist = (tdp->Nslist) ? tdp->Nslist : NULL;
+ DefNs = (tdp->DefNs) ? tdp->DefNs : NULL;
+ Attrib = (tdp->Attrib) ? tdp->Attrib : NULL;
+ Hdattr = (tdp->Hdattr) ? tdp->Hdattr : NULL;
Coltype = tdp->Coltype;
Limit = tdp->Limit;
Xpand = tdp->Xpand;
@@ -332,7 +648,7 @@ PCOL TDBXML::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/
/* InsertSpecialColumn: Put a special column ahead of the column list.*/
/***********************************************************************/
-PCOL TDBXML::InsertSpecialColumn(PGLOBAL g, PCOL colp)
+PCOL TDBXML::InsertSpecialColumn(PCOL colp)
{
if (!colp->IsSpecial())
return NULL;
@@ -519,7 +835,6 @@ bool TDBXML::Initialize(PGLOBAL g)
To_Xb = Docp->LinkXblock(g, Mode, rc, filename);
// Add a CONNECT comment node
-// sprintf(buf, " Created by CONNECT %s ", version);
strcpy(buf, " Created by the MariaDB CONNECT Storage Engine");
Docp->AddComment(g, buf);
@@ -563,7 +878,7 @@ bool TDBXML::Initialize(PGLOBAL g)
Nlist = TabNode->GetChildElements(g);
Docp->SetNofree(true); // For libxml2
-#if defined(WIN32)
+#if defined(__WIN__)
} catch(_com_error e) {
// We come here if a DOM command threw an error
char buf[128];
@@ -577,7 +892,7 @@ bool TDBXML::Initialize(PGLOBAL g)
sprintf(g->Message, "%s hr=%p", MSG(COM_ERROR), e.Error());
goto error;
-#endif // WIN32
+#endif // __WIN__
#if !defined(UNIX)
} catch(...) {
// Other errors
@@ -702,7 +1017,7 @@ int TDBXML::GetMaxSize(PGLOBAL g)
else
MaxSize = 10;
- } // endif MaxSize
+ } // endif MaxSize
return MaxSize;
} // end of GetMaxSize
@@ -771,7 +1086,6 @@ bool TDBXML::OpenDB(PGLOBAL g)
NewRow = (Mode == MODE_INSERT);
Nsub = 0;
Use = USE_OPEN; // Do it now in case we are recursively called
-
return false;
} // end of OpenDB
@@ -944,8 +1258,7 @@ void TDBXML::CloseDB(PGLOBAL g)
{
if (Docp) {
if (Changed) {
- char filename[_MAX_PATH];
-// PDBUSER dup = (PDBUSER)g->Activityp->Aptr;
+ char filename[_MAX_PATH];
// We used the file name relative to recorded datapath
PlugSetPath(filename, Xfile, GetPath());
@@ -987,7 +1300,6 @@ void TDBXML::CloseDB(PGLOBAL g)
NewRow = false;
Hasnod = false;
Write = false;
-// Bufdone = false;
Nodedone = false;
Void = false;
Nrow = -1;
@@ -1079,8 +1391,6 @@ bool XMLCOL::AllocBuf(PGLOBAL g, bool mode)
if (Valbuf)
return false; // Already done
-//Valbuf = (char*)PlugSubAlloc(g, NULL, Long + 1);
-//Valbuf[Long] = '\0';
return ParseXpath(g, mode);
} // end of AllocBuf
@@ -1171,8 +1481,7 @@ bool XMLCOL::ParseXpath(PGLOBAL g, bool mode)
} else if (Type == 2) {
// HTML like table, columns are retrieved by position
new(this) XPOSCOL(Value); // Change the class of this column
- Tdbp->Hasnod = true;
- return false;
+ Inod = -1;
} else if (Type == 0 && !mode) {
strcat(strcat(pbuf, "@"), Name);
} else { // Type == 1
@@ -1322,7 +1631,6 @@ void XMLCOL::WriteColumn(PGLOBAL g)
int done = 0;
int i, n, k = 0;
PXNODE TopNode = NULL;
-//PXATTR AttNode = NULL;
if (trace > 1)
htrc("XML WriteColumn: col %s R%d coluse=%.4X status=%.4X\n",
@@ -1354,7 +1662,7 @@ void XMLCOL::WriteColumn(PGLOBAL g)
/*********************************************************************/
/* Null values are represented by no node. */
/*********************************************************************/
- if (Value->IsNull())
+ if (Value->IsNull())
return;
/*********************************************************************/
@@ -1557,7 +1865,6 @@ void XMULCOL::WriteColumn(PGLOBAL g)
int done = 0;
int i, n, len, k = 0;
PXNODE TopNode = NULL;
-//PXATTR AttNode = NULL;
if (trace)
htrc("XML WriteColumn: col %s R%d coluse=%.4X status=%.4X\n",
@@ -1847,4 +2154,24 @@ void XPOSCOL::WriteColumn(PGLOBAL g)
} // end of WriteColumn
+/* ---------------------------TDBXCT class --------------------------- */
+
+/***********************************************************************/
+/* TDBXCT class constructor. */
+/***********************************************************************/
+TDBXCT::TDBXCT(PXMLDEF tdp) : TDBCAT(tdp)
+ {
+ Topt = tdp->GetTopt();
+ Db = (char*)tdp->GetDB();
+ Tabn = tdp->Tabname;
+ } // end of TDBXCT constructor
+
+/***********************************************************************/
+/* GetResult: Get the list the JSON file columns. */
+/***********************************************************************/
+PQRYRES TDBXCT::GetResult(PGLOBAL g)
+ {
+ return XMLColumns(g, Db, Tabn, Topt, false);
+ } // end of GetResult
+
/* ------------------------ End of Tabxml ---------------------------- */
diff --git a/storage/connect/tabxml.h b/storage/connect/tabxml.h
index a3dc0a2b54c..7ba3166881d 100644
--- a/storage/connect/tabxml.h
+++ b/storage/connect/tabxml.h
@@ -1,7 +1,7 @@
/*************** Tabxml H Declares Source Code File (.H) ***************/
/* Name: TABXML.H Version 1.6 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2007-2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2007-2015 */
/* */
/* This file contains the XML table classes declares. */
/***********************************************************************/
@@ -16,6 +16,8 @@ typedef class XMLCOL *PXMLCOL;
/***********************************************************************/
class DllExport XMLDEF : public TABDEF { /* Logical table description */
friend class TDBXML;
+ friend class TDBXCT;
+ friend PQRYRES XMLColumns(PGLOBAL, char*, char*, PTOS, bool);
public:
// Constructor
XMLDEF(void);
@@ -55,6 +57,7 @@ class DllExport TDBXML : public TDBASE {
friend class XMLCOL;
friend class XMULCOL;
friend class XPOSCOL;
+ friend PQRYRES XMLColumns(PGLOBAL, char*, char*, PTOS, bool);
public:
// Constructor
TDBXML(PXMLDEF tdp);
@@ -81,7 +84,7 @@ class DllExport TDBXML : public TDBASE {
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
- virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
+ virtual PCOL InsertSpecialColumn(PCOL colp);
//virtual int GetMaxSame(PGLOBAL g) {return (Xpand) ? Limit : 1;}
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
@@ -237,4 +240,23 @@ class XPOSCOL : public XMLCOLX {
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
}; // end of class XPOSCOL
+
+/***********************************************************************/
+/* This is the class declaration for the XML catalog table. */
+/***********************************************************************/
+class TDBXCT : public TDBCAT {
+ public:
+ // Constructor
+ TDBXCT(PXMLDEF tdp);
+
+ protected:
+ // Specific routines
+ virtual PQRYRES GetResult(PGLOBAL g);
+
+ // Members
+ PTOS Topt;
+ char *Db;
+ char *Tabn;
+ }; // end of class TDBXCT
+
#endif // INCLUDE_TDBXML
diff --git a/storage/connect/user_connect.cc b/storage/connect/user_connect.cc
index 4affe447b00..34d192361a5 100644
--- a/storage/connect/user_connect.cc
+++ b/storage/connect/user_connect.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2014
+/* Copyright (C) Olivier Bertrand 2004 - 2015
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
@@ -28,7 +28,7 @@
*/
/****************************************************************************/
-/* Author: Olivier Bertrand -- bertrandop@gmail.com -- 2004-2014 */
+/* Author: Olivier Bertrand -- bertrandop@gmail.com -- 2004-2015 */
/****************************************************************************/
#ifdef USE_PRAGMA_IMPLEMENTATION
#pragma implementation // gcc: Class implementation
@@ -63,7 +63,7 @@ void SetWorkSize(uint);
/****************************************************************************/
/* Constructor. */
/****************************************************************************/
-user_connect::user_connect(THD *thd, const char *dbn)
+user_connect::user_connect(THD *thd)
{
thdp= thd;
next= NULL;
diff --git a/storage/connect/user_connect.h b/storage/connect/user_connect.h
index 44e4e94fa8a..7f37973f378 100644
--- a/storage/connect/user_connect.h
+++ b/storage/connect/user_connect.h
@@ -45,7 +45,7 @@ class user_connect
friend int connect_done_func(void *);
public:
// Constructor
- user_connect(THD *thd, const char *dbn);
+ user_connect(THD *thd);
// Destructor
virtual ~user_connect();
diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp
index df7011583cd..5fefcba5856 100644
--- a/storage/connect/valblk.cpp
+++ b/storage/connect/valblk.cpp
@@ -1,7 +1,7 @@
/************ Valblk C++ Functions Source Code File (.CPP) *************/
/* Name: VALBLK.CPP Version 2.1 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
/* */
/* This file contains the VALBLK and derived classes functions. */
/* Second family is VALBLK, representing simple suballocated arrays */
@@ -23,7 +23,7 @@
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
//#include <windows.h>
#else
#include "osutil.h"
@@ -132,7 +132,7 @@ VALBLK::VALBLK(void *mp, int type, int nval, bool un)
/***********************************************************************/
/* Raise error for numeric types. */
/***********************************************************************/
-PSZ VALBLK::GetCharValue(int n)
+PSZ VALBLK::GetCharValue(int)
{
PGLOBAL& g = Global;
@@ -145,7 +145,7 @@ PSZ VALBLK::GetCharValue(int n)
/***********************************************************************/
/* Set format so formatted dates can be converted on input. */
/***********************************************************************/
-bool VALBLK::SetFormat(PGLOBAL g, PSZ fmt, int len, int year)
+bool VALBLK::SetFormat(PGLOBAL g, PSZ, int, int)
{
sprintf(g->Message, MSG(NO_DATE_FMT), Type);
return true;
@@ -752,7 +752,7 @@ double CHRBLK::GetFloatValue(int n)
/***********************************************************************/
/* STRING GetCharString: get string representation of a char value. */
/***********************************************************************/
-char *CHRBLK::GetCharString(char *p, int n)
+char *CHRBLK::GetCharString(char *, int n)
{
return (char *)GetValPtrEx(n);
} // end of GetCharString
@@ -1155,10 +1155,9 @@ void STRBLK::SetValue(PVAL valp, int n)
void STRBLK::SetValue(PSZ p, int n)
{
if (p) {
- if (!Sorted || !n || !Strp[n-1] || strcmp(p, Strp[n-1])) {
- Strp[n] = (PSZ)PlugSubAlloc(Global, NULL, strlen(p) + 1);
- strcpy(Strp[n], p);
- } else
+ if (!Sorted || !n || !Strp[n-1] || strcmp(p, Strp[n-1]))
+ Strp[n] = (PSZ)PlugDup(Global, p);
+ else
Strp[n] = Strp[n-1];
} else
diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h
index 654db0b57b7..f6eb7258a77 100644
--- a/storage/connect/valblk.h
+++ b/storage/connect/valblk.h
@@ -95,17 +95,17 @@ class VALBLK : public BLOCK {
virtual bool IsCi(void) {return false;}
// Methods
- virtual void SetValue(short sval, int n) {assert(false);}
- virtual void SetValue(ushort sval, int n) {assert(false);}
- virtual void SetValue(int lval, int n) {assert(false);}
- virtual void SetValue(uint lval, int n) {assert(false);}
- virtual void SetValue(longlong lval, int n) {assert(false);}
- virtual void SetValue(ulonglong lval, int n) {assert(false);}
- virtual void SetValue(double fval, int n) {assert(false);}
- virtual void SetValue(char cval, int n) {assert(false);}
- virtual void SetValue(uchar cval, int n) {assert(false);}
- virtual void SetValue(PSZ sp, int n) {assert(false);}
- virtual void SetValue(char *sp, uint len, int n) {assert(false);}
+ virtual void SetValue(short, int) {assert(false);}
+ virtual void SetValue(ushort, int) {assert(false);}
+ virtual void SetValue(int, int) {assert(false);}
+ virtual void SetValue(uint, int) {assert(false);}
+ virtual void SetValue(longlong, int) {assert(false);}
+ virtual void SetValue(ulonglong, int) {assert(false);}
+ virtual void SetValue(double, int) {assert(false);}
+ virtual void SetValue(char, int) {assert(false);}
+ virtual void SetValue(uchar, int) {assert(false);}
+ virtual void SetValue(PSZ, int) {assert(false);}
+ virtual void SetValue(char *, uint, int) {assert(false);}
virtual void SetValue(PVAL valp, int n) = 0;
virtual void SetValue(PVBLK pv, int n1, int n2) = 0;
virtual void SetMin(PVAL valp, int n) = 0;
@@ -163,6 +163,7 @@ class TYPBLK : public VALBLK {
virtual void Reset(int n) {Typp[n] = 0;}
// Methods
+ using VALBLK::SetValue;
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(short sval, int n)
@@ -233,6 +234,7 @@ class CHRBLK : public VALBLK {
virtual bool IsCi(void) {return Ci;}
// Methods
+ using VALBLK::SetValue;
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(PVAL valp, int n);
@@ -269,7 +271,7 @@ class STRBLK : public VALBLK {
// Implementation
virtual void SetNull(int n, bool b) {if (b) {Strp[n] = NULL;}}
virtual bool IsNull(int n) {return Strp[n] == NULL;}
- virtual void SetNullable(bool b) {} // Always nullable
+ virtual void SetNullable(bool) {} // Always nullable
virtual bool Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return sizeof(PSZ);}
virtual PSZ GetCharValue(int n) {return Strp[n];}
@@ -282,10 +284,11 @@ class STRBLK : public VALBLK {
virtual longlong GetBigintValue(int n);
virtual ulonglong GetUBigintValue(int n);
virtual double GetFloatValue(int n) {return atof(Strp[n]);}
- virtual char *GetCharString(char *p, int n) {return Strp[n];}
+ virtual char *GetCharString(char *, int n) {return Strp[n];}
virtual void Reset(int n) {Strp[n] = NULL;}
// Methods
+ using VALBLK::SetValue;
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(PVAL valp, int n);
@@ -322,6 +325,7 @@ class DATBLK : public TYPBLK<int> {
virtual char *GetCharString(char *p, int n);
// Methods
+ using TYPBLK<int>::SetValue;
virtual void SetValue(PSZ sp, int n);
protected:
@@ -345,6 +349,8 @@ class PTRBLK : public STRBLK {
// Implementation
// Methods
+ using STRBLK::SetValue;
+ using STRBLK::CompVal;
virtual void SetValue(PSZ p, int n) {Strp[n] = p;}
virtual int CompVal(int i1, int i2);
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index 1cc40473433..03ec0eb8e40 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -1,7 +1,7 @@
/************* Value C++ Functions Source Code File (.CPP) *************/
/* Name: VALUE.CPP Version 2.5 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2001-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2001-2015 */
/* */
/* This file contains the VALUE and derived classes family functions. */
/* These classes contain values of different types. They are used so */
@@ -30,11 +30,11 @@
#include "sql_class.h"
#include "sql_time.h"
-#if defined(WIN32)
+#if defined(__WIN__)
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#include <string.h>
-#endif // !WIN32
+#endif // !__WIN__
#include <math.h>
@@ -77,12 +77,12 @@ int DTVAL::Shift = 0;
/***********************************************************************/
bool PlugEvalLike(PGLOBAL, LPCSTR, LPCSTR, bool);
-#if !defined(WIN32)
+#if !defined(__WIN__)
extern "C" {
PSZ strupr(PSZ s);
PSZ strlwr(PSZ s);
}
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Get a long long number from its character representation. */
@@ -436,6 +436,9 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned();
PVAL vp;
+ if (!valp)
+ return NULL;
+
if (newtype == TYPE_VOID) // Means allocate a value of the same type
newtype = valp->GetType();
@@ -443,8 +446,8 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
case TYPE_STRING:
p = (PSZ)PlugSubAlloc(g, NULL, 1 + valp->GetValLen());
- if ((sp = valp->GetCharString(p)) != p)
- strcpy (p, sp);
+ if ((sp = valp->GetCharString(p)) != p && sp)
+ strcpy(p, sp);
vp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec());
break;
@@ -472,7 +475,7 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
break;
case TYPE_DATE:
- vp = new(g) DTVAL(g, valp->GetIntValue());
+ vp = new(g) DTVAL(valp->GetIntValue());
break;
case TYPE_DOUBLE:
vp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_DOUBLE,
@@ -548,7 +551,7 @@ BYTE VALUE::TestValue(PVAL vp)
/***********************************************************************/
/* Compute a function on a string. */
/***********************************************************************/
-bool VALUE::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
+bool VALUE::Compute(PGLOBAL g, PVAL *, int, OPVAL)
{
strcpy(g->Message, "Compute not implemented for this value type");
return true;
@@ -624,13 +627,16 @@ int TYPVAL<double>::GetValLen(void)
template <class TYPE>
bool TYPVAL<TYPE>::SetValue_pval(PVAL valp, bool chktype)
{
- if (chktype && Type != valp->GetType())
- return true;
+ if (valp != this) {
+ if (chktype && Type != valp->GetType())
+ return true;
- if (!(Null = valp->IsNull() && Nullable))
- Tval = GetTypedValue(valp);
- else
- Reset();
+ if (!(Null = valp->IsNull() && Nullable))
+ Tval = GetTypedValue(valp);
+ else
+ Reset();
+
+ } // endif valp
return false;
} // end of SetValue
@@ -970,7 +976,7 @@ ulonglong TYPVAL<ulonglong>::MinMaxVal(bool b)
{return (b) ? 0xFFFFFFFFFFFFFFFFLL : 0;}
template <>
-double TYPVAL<double>::MinMaxVal(bool b)
+double TYPVAL<double>::MinMaxVal(bool)
{assert(false); return 0.0;}
template <>
@@ -1216,12 +1222,12 @@ TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING)
TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
: VALUE(TYPE_STRING)
{
- Len = (g) ? n : strlen(s);
+ Len = (g) ? n : (s) ? strlen(s) : 0;
if (!s) {
if (g) {
if ((Strp = (char *)PlgDBSubAlloc(g, NULL, Len + 1)))
- Strp[Len] = '\0';
+ memset(Strp, 0, Len + 1);
else
Len = 0;
@@ -1316,15 +1322,18 @@ ulonglong TYPVAL<PSZ>::GetUBigintValue(void)
/***********************************************************************/
bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype)
{
- if (chktype && (valp->GetType() != Type || valp->GetSize() > Len))
- return true;
+ if (valp != this) {
+ if (chktype && (valp->GetType() != Type || valp->GetSize() > Len))
+ return true;
- char buf[64];
+ char buf[64];
- if (!(Null = valp->IsNull() && Nullable))
- strncpy(Strp, valp->GetCharString(buf), Len);
- else
- Reset();
+ if (!(Null = valp->IsNull() && Nullable))
+ strncpy(Strp, valp->GetCharString(buf), Len);
+ else
+ Reset();
+
+ } // endif valp
return false;
} // end of SetValue_pval
@@ -1557,7 +1566,7 @@ bool TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go)
/***********************************************************************/
/* STRING ShowValue: get string representation of a char value. */
/***********************************************************************/
-char *TYPVAL<PSZ>::ShowValue(char *buf, int len)
+char *TYPVAL<PSZ>::ShowValue(char *, int)
{
return Strp;
} // end of ShowValue
@@ -1565,7 +1574,7 @@ char *TYPVAL<PSZ>::ShowValue(char *buf, int len)
/***********************************************************************/
/* STRING GetCharString: get string representation of a char value. */
/***********************************************************************/
-char *TYPVAL<PSZ>::GetCharString(char *p)
+char *TYPVAL<PSZ>::GetCharString(char *)
{
return Strp;
} // end of GetCharString
@@ -1609,10 +1618,10 @@ int TYPVAL<PSZ>::CompareValue(PVAL vp)
else
n = strcmp(Strp, vp->GetCharValue());
-#if defined(WIN32)
+#if defined(__WIN__)
if (n == _NLSCMPERROR)
return n; // Here we should raise an error
-#endif // WIN32
+#endif // __WIN__
return (n > 0) ? 1 : (n < 0) ? -1 : 0;
} // end of CompareValue
@@ -1672,7 +1681,7 @@ bool TYPVAL<PSZ>::FormatValue(PVAL vp, char *fmt)
/***********************************************************************/
/* STRING SetFormat function (used to set SELECT output format). */
/***********************************************************************/
-bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
+bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL, FORMAT& fmt)
{
fmt.Type[0] = 'C';
fmt.Length = Len;
@@ -2060,18 +2069,21 @@ double BINVAL::GetFloatValue(void)
/***********************************************************************/
bool BINVAL::SetValue_pval(PVAL valp, bool chktype)
{
- if (chktype && (valp->GetType() != Type || valp->GetSize() > Clen))
- return true;
-
bool rc = false;
-
- if (!(Null = valp->IsNull() && Nullable)) {
- if ((rc = (Len = valp->GetSize()) > Clen))
- Len = Clen;
+
+ if (valp != this) {
+ if (chktype && (valp->GetType() != Type || valp->GetSize() > Clen))
+ return true;
- memcpy(Binp, valp->GetTo_Val(), Len);
- } else
- Reset();
+ if (!(Null = valp->IsNull() && Nullable)) {
+ if ((rc = (Len = valp->GetSize()) > Clen))
+ Len = Clen;
+
+ memcpy(Binp, valp->GetTo_Val(), Len);
+ } else
+ Reset();
+
+ } // endif valp
return rc;
} // end of SetValue_pval
@@ -2288,7 +2300,7 @@ char *BINVAL::ShowValue(char *buf, int len)
/***********************************************************************/
/* BINVAL GetCharString: get string representation of a binary value. */
/***********************************************************************/
-char *BINVAL::GetCharString(char *p)
+char *BINVAL::GetCharString(char *)
{
if (!Chrp)
Chrp = (char*)PlugSubAlloc(Global, NULL, Clen * 2 + 1);
@@ -2337,7 +2349,7 @@ bool BINVAL::FormatValue(PVAL vp, char *fmt)
/***********************************************************************/
/* BINVAL SetFormat function (used to set SELECT output format). */
/***********************************************************************/
-bool BINVAL::SetConstFormat(PGLOBAL g, FORMAT& fmt)
+bool BINVAL::SetConstFormat(PGLOBAL, FORMAT& fmt)
{
fmt.Type[0] = 'B';
fmt.Length = Clen;
@@ -2367,7 +2379,7 @@ DTVAL::DTVAL(PGLOBAL g, int n, int prec, PSZ fmt)
/***********************************************************************/
/* DTVAL public constructor from int. */
/***********************************************************************/
-DTVAL::DTVAL(PGLOBAL g, int n) : TYPVAL<int>(n, TYPE_DATE)
+DTVAL::DTVAL(int n) : TYPVAL<int>(n, TYPE_DATE)
{
Pdtp = NULL;
Len = 19;
@@ -2626,21 +2638,24 @@ bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
/***********************************************************************/
bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
{
- if (chktype && Type != valp->GetType())
- return true;
+ if (valp != this) {
+ if (chktype && Type != valp->GetType())
+ return true;
- if (!(Null = valp->IsNull() && Nullable)) {
- if (Pdtp && !valp->IsTypeNum()) {
- int ndv;
- int dval[6];
+ if (!(Null = valp->IsNull() && Nullable)) {
+ if (Pdtp && !valp->IsTypeNum()) {
+ int ndv;
+ int dval[6];
+
+ ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval);
+ MakeDate(NULL, dval, ndv);
+ } else
+ Tval = valp->GetIntValue();
- ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval);
- MakeDate(NULL, dval, ndv);
} else
- Tval = valp->GetIntValue();
+ Reset();
- } else
- Reset();
+ } // endif valp
return false;
} // end of SetValue
diff --git a/storage/connect/value.h b/storage/connect/value.h
index c5aeb5c2a2f..780917c9962 100644
--- a/storage/connect/value.h
+++ b/storage/connect/value.h
@@ -36,8 +36,9 @@ typedef struct _datpar *PDTP; // For DTVAL
DllExport PSZ GetTypeName(int);
DllExport int GetTypeSize(int, int);
#ifdef ODBC_SUPPORT
-/* This function is exported for use in EOM table type DLLs */
-DllExport int TranslateSQLType(int stp, int prec, int& len, char& v);
+/* This function is exported for use in OEM table type DLLs */
+DllExport int TranslateSQLType(int stp, int prec,
+ int& len, char& v, bool& w);
#endif
DllExport char *GetFormatType(int);
DllExport int GetFormatType(char);
@@ -94,18 +95,18 @@ class DllExport VALUE : public BLOCK {
virtual bool SetValue_pval(PVAL valp, bool chktype = false) = 0;
virtual bool SetValue_char(char *p, int n) = 0;
virtual void SetValue_psz(PSZ s) = 0;
- virtual void SetValue_bool(bool b) {assert(FALSE);}
+ virtual void SetValue_bool(bool) {assert(FALSE);}
virtual int CompareValue(PVAL vp) = 0;
virtual BYTE TestValue(PVAL vp);
- virtual void SetValue(char c) {assert(false);}
- virtual void SetValue(uchar c) {assert(false);}
- virtual void SetValue(short i) {assert(false);}
- virtual void SetValue(ushort i) {assert(false);}
- virtual void SetValue(int n) {assert(false);}
- virtual void SetValue(uint n) {assert(false);}
- virtual void SetValue(longlong n) {assert(false);}
- virtual void SetValue(ulonglong n) {assert(false);}
- virtual void SetValue(double f) {assert(false);}
+ virtual void SetValue(char) {assert(false);}
+ virtual void SetValue(uchar) {assert(false);}
+ virtual void SetValue(short) {assert(false);}
+ virtual void SetValue(ushort) {assert(false);}
+ virtual void SetValue(int) {assert(false);}
+ virtual void SetValue(uint) {assert(false);}
+ virtual void SetValue(longlong) {assert(false);}
+ virtual void SetValue(ulonglong) {assert(false);}
+ virtual void SetValue(double) {assert(false);}
virtual void SetValue_pvblk(PVBLK blk, int n) = 0;
virtual void SetBinValue(void *p) = 0;
virtual bool GetBinValue(void *buf, int buflen, bool go) = 0;
@@ -338,7 +339,7 @@ class DllExport BINVAL: public VALUE {
virtual void SetValue(double f);
virtual void SetBinValue(void *p);
virtual bool GetBinValue(void *buf, int buflen, bool go);
- virtual int CompareValue(PVAL vp) {assert(false); return 0;}
+ virtual int CompareValue(PVAL) {assert(false); return 0;}
virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype);
@@ -359,14 +360,9 @@ class DllExport DTVAL : public TYPVAL<int> {
public:
// Constructors
DTVAL(PGLOBAL g, int n, int p, PSZ fmt);
- DTVAL(PGLOBAL g, PSZ s, int n);
- DTVAL(PGLOBAL g, short i);
- DTVAL(PGLOBAL g, int n);
- DTVAL(PGLOBAL g, longlong n);
- DTVAL(PGLOBAL g, double f);
+ DTVAL(int n);
// Implementation
- virtual bool IsZero(void) {return Null;}
virtual bool SetValue_pval(PVAL valp, bool chktype);
virtual bool SetValue_char(char *p, int n);
virtual void SetValue_psz(PSZ s);
diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp
index 024a9c081cd..a2d75cec8ab 100755
--- a/storage/connect/xindex.cpp
+++ b/storage/connect/xindex.cpp
@@ -1,7 +1,7 @@
/***************** Xindex C++ Class Xindex Code (.CPP) *****************/
/* Name: XINDEX.CPP Version 2.9 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2004-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 2004-2015 */
/* */
/* This file contains the class XINDEX implementation code. */
/***********************************************************************/
@@ -10,12 +10,12 @@
/* Include relevant sections of the System header files. */
/***********************************************************************/
#include "my_global.h"
-#if defined(WIN32)
+#if defined(__WIN__)
#include <io.h>
#include <fcntl.h>
#include <errno.h>
//#include <windows.h>
-#else // !WIN32
+#else // !__WIN__
#if defined(UNIX)
#include <sys/types.h>
#include <sys/stat.h>
@@ -25,7 +25,7 @@
#include <io.h>
#endif // !UNIX
#include <fcntl.h>
-#endif // !WIN32
+#endif // !__WIN__
/***********************************************************************/
/* Include required application header files */
@@ -179,7 +179,7 @@ XXBASE::XXBASE(PTDBDOS tbxp, bool b) : CSORT(b),
/***********************************************************************/
/* Make file output of XINDEX contents. */
/***********************************************************************/
-void XXBASE::Print(PGLOBAL g, FILE *f, uint n)
+void XXBASE::Print(PGLOBAL, FILE *f, uint n)
{
char m[64];
@@ -191,7 +191,7 @@ void XXBASE::Print(PGLOBAL g, FILE *f, uint n)
/***********************************************************************/
/* Make string output of XINDEX contents. */
/***********************************************************************/
-void XXBASE::Print(PGLOBAL g, char *ps, uint z)
+void XXBASE::Print(PGLOBAL, char *ps, uint z)
{
*ps = '\0';
strncat(ps, "Xindex", z);
@@ -287,7 +287,7 @@ int XINDEX::Qcompare(int *i1, int *i2)
/* Sure enough, it is done while records are read and permit to avoid */
/* reading the table while doing the join (Dynamic index only) */
/***********************************************************************/
-bool XINDEX::AddColumns(PIXDEF xdp)
+bool XINDEX::AddColumns(void)
{
if (!Dynamic)
return false; // Not applying to static index
@@ -340,6 +340,9 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
} // endif n
+ if (trace)
+ htrc("XINDEX Make: n=%d\n", n);
+
// File position must be stored
Record.Size = n * sizeof(int);
@@ -377,7 +380,7 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
To_LastCol = prev;
- if (AddColumns(sxp)) {
+ if (AddColumns()) {
PCOL kolp = To_Cols[0]; // Temporary while imposing Nk = 1
i = 0;
@@ -477,6 +480,9 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
} else
To_Rec[nkey] = Tdbp->GetRecpos();
+ if (trace > 1)
+ htrc("Make: To_Rec[%d]=%d\n", nkey, To_Rec[nkey]);
+
/*******************************************************************/
/* Get the keys and place them in the key blocks. */
/*******************************************************************/
@@ -733,7 +739,7 @@ int XINDEX::ColMaxSame(PXCOL kp)
/* Reorder: use the sort index to reorder the data in storage so */
/* it will be physically sorted and sort index can be removed. */
/***********************************************************************/
-bool XINDEX::Reorder(PGLOBAL g)
+bool XINDEX::Reorder(PGLOBAL g __attribute__((unused)))
{
register int i, j, k, n;
bool sorted = true;
@@ -835,7 +841,7 @@ bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp)
if ((sep = defp->GetBoolCatInfo("SepIndex", false))) {
// Index is saved in a separate file
-#if !defined(UNIX)
+#if defined(__WIN__)
char drive[_MAX_DRIVE];
#else
char *drive = NULL;
@@ -988,7 +994,7 @@ bool XINDEX::Init(PGLOBAL g)
if (defp->SepIndex()) {
// Index was saved in a separate file
-#if !defined(UNIX)
+#if defined(__WIN__)
char drive[_MAX_DRIVE];
#else
char *drive = NULL;
@@ -1241,7 +1247,7 @@ bool XINDEX::MapInit(PGLOBAL g)
if (defp->SepIndex()) {
// Index was save in a separate file
-#if !defined(UNIX)
+#if defined(__WIN__)
char drive[_MAX_DRIVE];
#else
char *drive = NULL;
@@ -1454,7 +1460,7 @@ bool XINDEX::GetAllSizes(PGLOBAL g,/* int &ndif,*/ int &numk)
if (defp->SepIndex()) {
// Index was saved in a separate file
-#if !defined(UNIX)
+#if defined(__WIN__)
char drive[_MAX_DRIVE];
#else
char *drive = NULL;
@@ -1585,7 +1591,7 @@ int XINDEX::Range(PGLOBAL g, int limit, bool incl)
if (++i == Nval) break;
} // endfor kp
- if ((k = FastFind(Nval)) < Num_K)
+ if ((k = FastFind()) < Num_K)
n = k;
// if (limit)
// n = (Mul) ? k : kp->Val_K;
@@ -1759,6 +1765,9 @@ int XINDEX::Fetch(PGLOBAL g)
if (Num_K == 0)
return -1; // means end of file
+ if (trace > 1)
+ htrc("XINDEX Fetch: Op=%d\n", Op);
+
/*********************************************************************/
/* Table read through a sorted index. */
/*********************************************************************/
@@ -1776,9 +1785,6 @@ int XINDEX::Fetch(PGLOBAL g)
break;
case OP_SAME: // Read next same
// Logically the key values should be the same as before
- if (trace > 1)
- htrc("looking for next same value\n");
-
if (NextVal(true)) {
Op = OP_EQ;
return -2; // no more equal values
@@ -1824,9 +1830,9 @@ int XINDEX::Fetch(PGLOBAL g)
Nth++;
if (trace > 1)
- htrc("Fetch: Looking for new value\n");
+ htrc("Fetch: Looking for new value Nth=%d\n", Nth);
- Cur_K = FastFind(Nval);
+ Cur_K = FastFind();
if (Cur_K >= Num_K)
/*************************************************************/
@@ -1857,12 +1863,12 @@ int XINDEX::Fetch(PGLOBAL g)
/* FastFind: Returns the index of matching record in a join using an */
/* optimized algorithm based on dichotomie and optimized comparing. */
/***********************************************************************/
-int XINDEX::FastFind(int nv)
+int XINDEX::FastFind(void)
{
register int curk, sup, inf, i= 0, k, n = 2;
register PXCOL kp, kcp;
- assert((int)nv == Nval);
+//assert((int)nv == Nval);
if (Nblk && Op == OP_EQ) {
// Look in block values to find in which block to search
@@ -1896,6 +1902,10 @@ int XINDEX::FastFind(int nv)
sup = To_KeyCol->Ndf;
} // endif Nblk
+ if (trace > 2)
+ htrc("XINDEX FastFind: Nblk=%d Op=%d inf=%d sup=%d\n",
+ Nblk, Op, inf, sup);
+
for (k = 0, kcp = To_KeyCol; kcp; kcp = kcp->Next) {
while (sup - inf > 1) {
i = (inf + sup) >> 1;
@@ -1970,6 +1980,9 @@ int XINDEX::FastFind(int nv)
curk = (kcp->Kof) ? kcp->Kof[kcp->Val_K] : kcp->Val_K;
} // endfor kcp
+ if (trace > 2)
+ htrc("XINDEX FastFind: curk=%d\n", curk);
+
return curk;
} // end of FastFind
@@ -2018,7 +2031,7 @@ int XINDXS::Range(PGLOBAL g, int limit, bool incl)
/*********************************************************************/
if (xp->GetType() == TYPE_CONST) {
kp->Valp->SetValue_pval(xp->GetValue(), !kp->Prefix);
- k = FastFind(Nval);
+ k = FastFind();
if (k < Num_K || Op != OP_EQ)
if (limit)
@@ -2043,8 +2056,7 @@ int XINDXS::GroupSize(void)
#if defined(_DEBUG)
assert(To_KeyCol->Val_K >= 0 && To_KeyCol->Val_K < Ndif);
#endif // _DEBUG
- return (Pof) ? Pof[To_KeyCol->Val_K + 1] - Pof[To_KeyCol->Val_K]
- : 1;
+ return (Pof) ? Pof[To_KeyCol->Val_K + 1] - Pof[To_KeyCol->Val_K] : 1;
} // end of GroupSize
/***********************************************************************/
@@ -2106,6 +2118,9 @@ int XINDXS::Fetch(PGLOBAL g)
if (Num_K == 0)
return -1; // means end of file
+ if (trace > 1)
+ htrc("XINDXS Fetch: Op=%d\n", Op);
+
/*********************************************************************/
/* Table read through a sorted index. */
/*********************************************************************/
@@ -2120,9 +2135,6 @@ int XINDXS::Fetch(PGLOBAL g)
Op = OP_NEXT;
break;
case OP_SAME: // Read next same
- if (trace > 1)
- htrc("looking for next same value\n");
-
if (!Mul || NextVal(true)) {
Op = OP_EQ;
return -2; // No more equal values
@@ -2160,9 +2172,9 @@ int XINDXS::Fetch(PGLOBAL g)
Nth++;
if (trace > 1)
- htrc("Fetch: Looking for new value\n");
+ htrc("Fetch: Looking for new value Nth=%d\n", Nth);
- Cur_K = FastFind(1);
+ Cur_K = FastFind();
if (Cur_K >= Num_K)
// Rank not whithin index table, signal record not found
@@ -2190,9 +2202,9 @@ int XINDXS::Fetch(PGLOBAL g)
/* FastFind: Returns the index of matching indexed record using an */
/* optimized algorithm based on dichotomie and optimized comparing. */
/***********************************************************************/
-int XINDXS::FastFind(int nk)
+int XINDXS::FastFind(void)
{
- register int sup, inf, i= 0, n = 2;
+ register int sup, inf, i= 0, n = 2;
register PXCOL kcp = To_KeyCol;
if (Nblk && Op == OP_EQ) {
@@ -2215,7 +2227,6 @@ int XINDXS::FastFind(int nk)
if (inf < 0)
return Num_K;
-// i = inf;
inf *= Sblk;
if ((sup = inf + Sblk) > Ndif)
@@ -2227,6 +2238,10 @@ int XINDXS::FastFind(int nk)
sup = Ndif;
} // endif Nblk
+ if (trace > 2)
+ htrc("XINDXS FastFind: Nblk=%d Op=%d inf=%d sup=%d\n",
+ Nblk, Op, inf, sup);
+
while (sup - inf > 1) {
i = (inf + sup) >> 1;
@@ -2249,6 +2264,9 @@ int XINDXS::FastFind(int nk)
n = 0;
} // endif sup
+ if (trace > 2)
+ htrc("XINDXS FastFind: n=%d i=%d\n", n, i);
+
// Loop on kcp because of dynamic indexing
for (; kcp; kcp = kcp->Next)
kcp->Val_K = i; // Used by FillValue
@@ -2330,6 +2348,10 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
} // endif
NewOff.Low = (int)ftell(Xfile);
+
+ if (trace)
+ htrc("XFILE Open: NewOff.Low=%d\n", NewOff.Low);
+
} else if (mode == MODE_WRITE) {
if (id >= 0) {
// New not sep index file. Write the header.
@@ -2337,6 +2359,10 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
Write(g, noff, sizeof(IOFF), MAX_INDX, rc);
fseek(Xfile, 0, SEEK_END);
NewOff.Low = (int)ftell(Xfile);
+
+ if (trace)
+ htrc("XFILE Open: NewOff.Low=%d\n", NewOff.Low);
+
} // endif id
} else if (mode == MODE_READ && id >= 0) {
@@ -2346,6 +2372,9 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
return true;
} // endif MAX_INDX
+ if (trace)
+ htrc("XFILE Open: noff[%d].Low=%d\n", id, noff[id].Low);
+
// Position the cursor at the offset of this index
if (fseek(Xfile, noff[id].Low, SEEK_SET)) {
sprintf(g->Message, MSG(FUNC_ERRNO), errno, "Xseek");
@@ -2360,7 +2389,8 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
/***********************************************************************/
/* Move into an index file. */
/***********************************************************************/
-bool XFILE::Seek(PGLOBAL g, int low, int high, int origin)
+bool XFILE::Seek(PGLOBAL g, int low, int high __attribute__((unused)),
+ int origin)
{
#if defined(_DEBUG)
assert(high == 0);
@@ -2371,7 +2401,6 @@ bool XFILE::Seek(PGLOBAL g, int low, int high, int origin)
return true;
} // endif
-//ftell(Xfile);
return false;
} // end of Seek
@@ -2479,7 +2508,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
if (trace)
htrc(" Xopen: filename=%s id=%d mode=%d\n", filename, id, mode);
-#if defined(WIN32)
+#if defined(__WIN__)
LONG high = 0;
DWORD rc, drc, access, share, creation;
@@ -2655,7 +2684,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
/***********************************************************************/
bool XHUGE::Seek(PGLOBAL g, int low, int high, int origin)
{
-#if defined(WIN32)
+#if defined(__WIN__)
LONG hi = high;
DWORD rc = SetFilePointer(Hfile, low, &hi, origin);
@@ -2691,7 +2720,7 @@ bool XHUGE::Read(PGLOBAL g, void *buf, int n, int size)
{
bool rc = false;
-#if defined(WIN32)
+#if defined(__WIN__)
bool brc;
DWORD nbr, count = (DWORD)(n * size);
@@ -2737,7 +2766,7 @@ bool XHUGE::Read(PGLOBAL g, void *buf, int n, int size)
/***********************************************************************/
int XHUGE::Write(PGLOBAL g, void *buf, int n, int size, bool& rc)
{
-#if defined(WIN32)
+#if defined(__WIN__)
bool brc;
DWORD nbw, count = (DWORD)n * (DWORD) size;
@@ -2779,7 +2808,7 @@ void XHUGE::Close(char *fn, int id)
if (trace)
htrc("XHUGE::Close: fn=%s id=%d NewOff=%lld\n", fn, id, NewOff.Val);
-#if defined(WIN32)
+#if defined(__WIN__)
if (id >= 0 && fn) {
CloseFileHandle(Hfile);
Hfile = CreateFile(fn, GENERIC_READ | GENERIC_WRITE, 0, NULL,
@@ -2794,7 +2823,7 @@ void XHUGE::Close(char *fn, int id)
} // endif SetFilePointer
} // endif id
-#else // !WIN32
+#else // !__WIN__
if (id >= 0 && fn) {
if (Hfile != INVALID_HANDLE_VALUE) {
if (lseek64(Hfile, id * sizeof(IOFF), SEEK_SET) >= 0) {
@@ -2810,7 +2839,7 @@ void XHUGE::Close(char *fn, int id)
htrc("(XHUGE)error reopening %s: %s\n", fn, strerror(errno));
} // endif id
-#endif // !WIN32
+#endif // !__WIN__
XLOAD::Close();
} // end of Close
@@ -2819,7 +2848,7 @@ void XHUGE::Close(char *fn, int id)
/***********************************************************************/
/* Don't know whether this is possible for huge files. */
/***********************************************************************/
-void *XHUGE::FileView(PGLOBAL g, char *fn)
+void *XHUGE::FileView(PGLOBAL g, char *)
{
strcpy(g->Message, MSG(NO_PART_MAP));
return NULL;
@@ -2879,7 +2908,7 @@ bool XXROW::Init(PGLOBAL g)
/***********************************************************************/
/* RANGE: Tell how many record exist in a given value range. */
/***********************************************************************/
-int XXROW::Range(PGLOBAL g, int limit, bool incl)
+int XXROW::Range(PGLOBAL, int limit, bool incl)
{
int n = Valp->GetIntValue();
@@ -2895,7 +2924,7 @@ int XXROW::Range(PGLOBAL g, int limit, bool incl)
/***********************************************************************/
/* XXROW: Fetch a physical or logical record. */
/***********************************************************************/
-int XXROW::Fetch(PGLOBAL g)
+int XXROW::Fetch(PGLOBAL)
{
if (Num_K == 0)
return -1; // means end of file
@@ -2904,7 +2933,7 @@ int XXROW::Fetch(PGLOBAL g)
/* Look for a key equal to the link column of previous table, */
/* and return its rank whithin the index table. */
/*********************************************************************/
- Cur_K = FastFind(1);
+ Cur_K = FastFind();
if (Cur_K >= Num_K)
/*******************************************************************/
@@ -2926,7 +2955,7 @@ int XXROW::Fetch(PGLOBAL g)
/***********************************************************************/
/* FastFind: Returns the index of matching record in a join. */
/***********************************************************************/
-int XXROW::FastFind(int nk)
+int XXROW::FastFind(void)
{
int n = Valp->GetIntValue();
@@ -3158,12 +3187,18 @@ bool KXYCOL::InitFind(PGLOBAL g, PXOB xp)
xp->Reset();
xp->Eval(g);
Valp->SetValue_pval(xp->GetValue(), false);
-// Valp->SetValue_pval(xp->GetValue(), !Prefix);
} // endif Type
+ if (trace > 1) {
+ char buf[32];
+
+ htrc("KCOL InitFind: value=%s\n", Valp->GetCharString(buf));
+ } // endif trace
+
return false;
} // end of InitFind
+#if 0
/***********************************************************************/
/* InitBinFind: initialize Value to the value pointed by vp. */
/***********************************************************************/
@@ -3171,6 +3206,7 @@ void KXYCOL::InitBinFind(void *vp)
{
Valp->SetBinValue(vp);
} // end of InitBinFind
+#endif // 0
/***********************************************************************/
/* KXYCOL FillValue: called by COLBLK::Eval when a column value is */
diff --git a/storage/connect/xindex.h b/storage/connect/xindex.h
index c702baeec83..51b678992ea 100644
--- a/storage/connect/xindex.h
+++ b/storage/connect/xindex.h
@@ -1,7 +1,7 @@
/*************** Xindex H Declares Source Code File (.H) ***************/
/* Name: XINDEX.H Version 3.5 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2004 - 2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2004 - 2015 */
/* */
/* This file contains the XINDEX class declares. */
/***********************************************************************/
@@ -65,7 +65,11 @@ typedef struct index_def : public BLOCK {
typedef struct index_off {
union {
+#if defined(WORDS_BIGENDIAN)
+ struct {int High; int Low;};
+#else // !WORDS_BIGENDIAN
struct {int Low; int High;};
+#endif //!WORDS_BIGENDIAN
longlong Val; // File position
}; // end of union
} IOFF;
@@ -205,12 +209,11 @@ class DllExport XXBASE : public CSORT, public BLOCK {
#endif // XMAP
virtual int MaxRange(void) {return 1;}
virtual int Fetch(PGLOBAL g) = 0;
- virtual bool NextVal(bool eq) {return true;}
+ virtual bool NextVal(bool) {return true;}
virtual bool PrevVal(void) {return true;}
- virtual int FastFind(int nk) = 0;
- virtual bool Reorder(PGLOBAL g) {return true;}
- virtual int Range(PGLOBAL g, int limit = 0, bool incl = true)
- {return -1;} // Means error
+ virtual int FastFind(void) = 0;
+ virtual bool Reorder(PGLOBAL) {return true;}
+ virtual int Range(PGLOBAL, int = 0, bool = true) {return -1;} // Means error
virtual int Qcompare(int *, int *) = 0;
virtual int GroupSize(void) {return 1;}
virtual void Close(void) = 0;
@@ -266,7 +269,7 @@ class DllExport XINDEX : public XXBASE {
#endif // XMAP
virtual int Qcompare(int *, int *);
virtual int Fetch(PGLOBAL g);
- virtual int FastFind(int nk);
+ virtual int FastFind(void);
virtual int GroupSize(void);
virtual int Range(PGLOBAL g, int limit = 0, bool incl = true);
virtual int MaxRange(void) {return MaxSame;}
@@ -280,7 +283,7 @@ class DllExport XINDEX : public XXBASE {
bool GetAllSizes(PGLOBAL g,/* int &ndif,*/ int &numk);
protected:
- bool AddColumns(PIXDEF xdp);
+ bool AddColumns(void);
bool NextValDif(void);
// Members
@@ -312,7 +315,7 @@ class DllExport XINDXS : public XINDEX {
// Methods
virtual int Qcompare(int *, int *);
virtual int Fetch(PGLOBAL g);
- virtual int FastFind(int nk);
+ virtual int FastFind(void);
virtual bool NextVal(bool eq);
virtual bool PrevVal(void);
virtual int Range(PGLOBAL g, int limit = 0, bool incl = true);
@@ -347,7 +350,7 @@ class DllExport XLOAD : public BLOCK {
protected:
// Members
-#if defined(WIN32)
+#if defined(__WIN__)
HANDLE Hfile; // Handle to file or map
#else // UNIX
int Hfile; // Descriptor to file or map
@@ -391,6 +394,7 @@ class DllExport XHUGE : public XLOAD {
XHUGE(void) : XLOAD() {}
// Methods
+ using XLOAD::Close;
virtual bool Open(PGLOBAL g, char *filename, int id, MODE mode);
virtual bool Seek(PGLOBAL g, int low, int high, int origin);
virtual bool Read(PGLOBAL g, void *buf, int n, int size);
@@ -420,14 +424,14 @@ class DllExport XXROW : public XXBASE {
// Methods
virtual bool Init(PGLOBAL g);
#if defined(XMAP)
- virtual bool MapInit(PGLOBAL g) {return true;}
+ virtual bool MapInit(PGLOBAL) {return true;}
#endif // XMAP
virtual int Fetch(PGLOBAL g);
- virtual int FastFind(int nk);
+ virtual int FastFind(void);
virtual int MaxRange(void) {return 1;}
virtual int Range(PGLOBAL g, int limit = 0, bool incl = true);
virtual int Qcompare(int *, int *) {assert(false); return 0;}
- virtual bool Make(PGLOBAL g, PIXDEF sxp) {return false;}
+ virtual bool Make(PGLOBAL, PIXDEF) {return false;}
virtual void Close(void) {}
protected:
@@ -462,7 +466,7 @@ class KXYCOL: public BLOCK {
virtual void FreeData(void);
virtual void FillValue(PVAL valp);
virtual int CompVal(int i);
- void InitBinFind(void *vp);
+// void InitBinFind(void *vp);
bool MakeBlockArray(PGLOBAL g, int nb, int size);
int Compare(int i1, int i2);
int CompBval(int i);
diff --git a/storage/connect/xobject.cpp b/storage/connect/xobject.cpp
index 4ddd4f5b30f..a6faebf3c2b 100644
--- a/storage/connect/xobject.cpp
+++ b/storage/connect/xobject.cpp
@@ -11,6 +11,7 @@
/* Include mariaDB header file. */
/***********************************************************************/
#include "my_global.h"
+#include "m_string.h"
/***********************************************************************/
/* Include required application header files */
@@ -290,6 +291,34 @@ bool STRING::Set(char *s, uint n)
} // end of Set
/***********************************************************************/
+/* Append a char* to a STRING. */
+/***********************************************************************/
+bool STRING::Append(const char *s, uint ln)
+{
+ if (!s)
+ return false;
+
+ uint len = Length + ln + 1;
+
+ if (len > Size) {
+ char *p = Realloc(len);
+
+ if (!p)
+ return true;
+ else if (p != Strp) {
+ strcpy(p, Strp);
+ Strp = p;
+ } // endif p
+
+ } // endif n
+
+ strncpy(Strp + Length, s, ln);
+ Length = len - 1;
+ Strp[Length] = 0;
+ return false;
+} // end of Append
+
+/***********************************************************************/
/* Append a PSZ to a STRING. */
/***********************************************************************/
bool STRING::Append(PSZ s)
@@ -347,6 +376,31 @@ bool STRING::Append(char c)
} // end of Append
/***********************************************************************/
+/* Append a quoted PSZ to a STRING. */
+/***********************************************************************/
+bool STRING::Append_quoted(PSZ s)
+{
+ bool b = Append('\'');
+
+ if (s) for (char *p = s; !b && *p; p++)
+ switch (*p) {
+ case '\'':
+ case '\\':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\b':
+ case '\f': b |= Append('\\');
+ // passthru
+ default:
+ b |= Append(*p);
+ break;
+ } // endswitch *p
+
+ return (b |= Append('\''));
+} // end of Append_quoted
+
+/***********************************************************************/
/* Resize to given length but only when last suballocated. */
/* New size should be greater than string length. */
/***********************************************************************/
diff --git a/storage/connect/xobject.h b/storage/connect/xobject.h
index bb7b0150ed8..82ff9e21225 100644
--- a/storage/connect/xobject.h
+++ b/storage/connect/xobject.h
@@ -42,9 +42,9 @@ class DllExport XOBJECT : public BLOCK {
virtual int GetResultType(void) {return TYPE_VOID;}
virtual int GetKey(void) {return 0;}
#if defined(_DEBUG)
- virtual void SetKey(int k) {assert(false);}
+ virtual void SetKey(int) {assert(false);}
#else // !_DEBUG
- virtual void SetKey(int k) {} // Only defined for COLBLK
+ virtual void SetKey(int) {} // Only defined for COLBLK
#endif // !_DEBUG
virtual int GetLength(void) = 0;
virtual int GetLengthEx(void) = 0;
@@ -134,10 +134,12 @@ class DllExport STRING : public BLOCK {
inline void Reset(void) {*Strp = 0;}
bool Set(PSZ s);
bool Set(char *s, uint n);
+ bool Append(const char *s, uint ln);
bool Append(PSZ s);
bool Append(STRING &str);
bool Append(char c);
bool Resize(uint n);
+ bool Append_quoted(PSZ s);
inline void Trim(void) {(void)Resize(Length + 1);}
inline void Chop(void) {if (Length) Strp[--Length] = 0;}
inline void RepLast(char c) {if (Length) Strp[Length-1] = c;}
diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h
index 501a5e87cfa..1a75d97bafa 100644
--- a/storage/connect/xtable.h
+++ b/storage/connect/xtable.h
@@ -1,7 +1,7 @@
/**************** Table H Declares Source Code File (.H) ***************/
/* Name: TABLE.H Version 2.3 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 1999-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 1999-2015 */
/* */
/* This file contains the TBX, OPJOIN and TDB class definitions. */
/***********************************************************************/
@@ -24,9 +24,7 @@ typedef class CMD *PCMD;
class CMD : public BLOCK {
public:
// Constructor
- CMD(PGLOBAL g, char *cmd) {
- Cmd = (char*)PlugSubAlloc(g, NULL, strlen(cmd) + 1);
- strcpy(Cmd, cmd); Next = NULL; }
+ CMD(PGLOBAL g, char *cmd) {Cmd = PlugDup(g, cmd); Next = NULL;}
// Members
PCMD Next;
@@ -79,21 +77,21 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
virtual int GetTdb_No(void) {return Tdb_No;}
virtual PTDB GetNext(void) {return Next;}
virtual PCATLG GetCat(void) {return NULL;}
- virtual void SetAbort(bool b) {;}
+ virtual void SetAbort(bool) {;}
// Methods
virtual bool IsSame(PTDB tp) {return tp == this;}
virtual bool IsSpecial(PSZ name) = 0;
- virtual bool GetBlockValues(PGLOBAL g) {return false;}
- virtual int Cardinality(PGLOBAL g) {return 0;}
+ virtual bool GetBlockValues(PGLOBAL) {return false;}
+ virtual int Cardinality(PGLOBAL) {return 0;}
virtual int GetMaxSize(PGLOBAL) = 0;
virtual int GetProgMax(PGLOBAL) = 0;
virtual int GetProgCur(void) = 0;
virtual int RowNumber(PGLOBAL g, bool b = false);
virtual bool IsReadOnly(void) {return true;}
virtual const CHARSET_INFO *data_charset() {return NULL;}
- virtual PTDB Duplicate(PGLOBAL g) {return NULL;}
- virtual PTDB CopyOne(PTABS t) {return this;}
+ virtual PTDB Duplicate(PGLOBAL) {return NULL;}
+ virtual PTDB CopyOne(PTABS) {return this;}
virtual PTDB Copy(PTABS t);
virtual void PrintAM(FILE *f, char *m)
{fprintf(f, "%s AM(%d)\n", m, GetAmType());}
@@ -110,7 +108,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
virtual int WriteDB(PGLOBAL) = 0;
virtual int DeleteDB(PGLOBAL, int) = 0;
virtual void CloseDB(PGLOBAL) = 0;
- virtual int CheckWrite(PGLOBAL g) {return 0;}
+ virtual int CheckWrite(PGLOBAL) {return 0;}
virtual bool ReadKey(PGLOBAL, OPVAL, const void *, int) = 0;
protected:
@@ -157,7 +155,7 @@ class DllExport TDBASE : public TDB {
PCOL Key(int i) {return (To_Key_Col) ? To_Key_Col[i] : NULL;}
// Methods
- virtual bool IsUsingTemp(PGLOBAL g) {return false;}
+ virtual bool IsUsingTemp(PGLOBAL) {return false;}
virtual bool IsIndexed(void) {return false;}
virtual bool IsSpecial(PSZ name);
virtual PCATLG GetCat(void);
@@ -172,9 +170,9 @@ class DllExport TDBASE : public TDB {
virtual CHARSET_INFO *data_charset(void);
virtual int GetProgMax(PGLOBAL g) {return GetMaxSize(g);}
virtual int GetProgCur(void) {return GetRecpos();}
- virtual PSZ GetFile(PGLOBAL g) {return "Not a file";}
+ virtual PSZ GetFile(PGLOBAL) {return "Not a file";}
virtual int GetRemote(void) {return 0;}
- virtual void SetFile(PGLOBAL g, PSZ fn) {}
+ virtual void SetFile(PGLOBAL, PSZ) {}
virtual void ResetDB(void) {}
virtual void ResetSize(void) {MaxSize = -1;}
virtual void RestoreNrec(void) {}
@@ -185,12 +183,12 @@ class DllExport TDBASE : public TDB {
virtual PCOL ColDB(PGLOBAL g, PSZ name, int num);
virtual PCOL MakeCol(PGLOBAL, PCOLDEF, PCOL, int)
{assert(false); return NULL;}
- virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
+ virtual PCOL InsertSpecialColumn(PCOL colp);
virtual PCOL InsertSpcBlk(PGLOBAL g, PCOLDEF cdp);
virtual void MarkDB(PGLOBAL g, PTDB tdb2);
- virtual int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add)
+ virtual int MakeIndex(PGLOBAL g, PIXDEF, bool)
{strcpy(g->Message, "Remote index"); return RC_INFO;}
- virtual bool ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
+ virtual bool ReadKey(PGLOBAL, OPVAL, const void *, int)
{assert(false); return true;}
protected:
@@ -227,7 +225,7 @@ class DllExport TDBCAT : public TDBASE {
// Methods
virtual int GetRecpos(void) {return N;}
virtual int GetProgCur(void) {return N;}
- virtual int RowNumber(PGLOBAL g, bool b = false) {return N + 1;}
+ virtual int RowNumber(PGLOBAL, bool = false) {return N + 1;}
virtual bool SetRecpos(PGLOBAL g, int recpos);
// Database routines