summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mnogosearch.org>2013-06-08 01:16:00 +0400
committerAlexander Barkov <bar@mnogosearch.org>2013-06-08 01:16:00 +0400
commita2cfb8023f3f2dfe06462a5294b53655abad4c9f (patch)
treec79e435fcc8fe09a750d89699f756ad56caf50da /storage
parent72ba95873a6d99def07a4bfecda44fb942165142 (diff)
parentffa2eb43560faca9f7d05c79d4c54657d33c62a6 (diff)
downloadmariadb-git-a2cfb8023f3f2dfe06462a5294b53655abad4c9f.tar.gz
Merge from 10.0-connect
added: include/mysql/service_thd_timezone.h libservices/thd_timezone_service.c storage/connect/inihandl.h storage/connect/mysql-test/connect/r/grant.result storage/connect/mysql-test/connect/r/ini_grant.result storage/connect/mysql-test/connect/r/mysql_grant.result storage/connect/mysql-test/connect/r/occur.result storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result storage/connect/mysql-test/connect/r/pivot.result storage/connect/mysql-test/connect/r/xcol.result storage/connect/mysql-test/connect/r/xml_grant.result storage/connect/mysql-test/connect/std_data/expenses.txt storage/connect/mysql-test/connect/t/grant.test storage/connect/mysql-test/connect/t/have_odbc_sqlite3.inc storage/connect/mysql-test/connect/t/ini_grant.test storage/connect/mysql-test/connect/t/mysql_grant.test storage/connect/mysql-test/connect/t/occur.test storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test storage/connect/mysql-test/connect/t/pivot.test storage/connect/mysql-test/connect/t/xcol.test storage/connect/mysql-test/connect/t/xml_grant.test storage/connect/rcmsg.h storage/connect/taboccur.cpp storage/connect/taboccur.h storage/connect/tabutil.cpp storage/connect/tabutil.h storage/connect/tabxcl.cpp storage/connect/tabxcl.h modified: include/my_global.h include/my_time.h include/mysql.h.pp include/mysql/plugin.h include/mysql/plugin_audit.h.pp include/mysql/plugin_auth.h.pp include/mysql/plugin_ftparser.h.pp include/mysql/services.h include/mysql_time.h include/probes_mysql_nodtrace.h include/service_versions.h libservices/CMakeLists.txt mysql-test/r/handlersocket.result mysql-test/r/plugin.result mysql-test/suite/plugins/r/show_all_plugins.result sql/item_func.cc sql/mysqld.cc sql/set_var.cc sql/sql_class.cc sql/sql_plugin.cc sql/sql_plugin.h sql/sql_plugin_services.h sql/sql_show.cc sql/sys_vars.cc storage/connect/CMakeLists.txt storage/connect/catalog.h storage/connect/colblk.cpp storage/connect/colblk.h storage/connect/connect.cc storage/connect/connect.h storage/connect/filamdbf.cpp storage/connect/global.h storage/connect/ha_connect.cc storage/connect/ha_connect.h storage/connect/inihandl.c storage/connect/maputil.h storage/connect/mycat.cc storage/connect/myconn.cpp storage/connect/myconn.h storage/connect/mysql-test/connect/r/bin.result storage/connect/mysql-test/connect/r/csv.result storage/connect/mysql-test/connect/r/dbf.result storage/connect/mysql-test/connect/r/dir.result storage/connect/mysql-test/connect/r/fix.result storage/connect/mysql-test/connect/r/fmt.result storage/connect/mysql-test/connect/r/ini.result storage/connect/mysql-test/connect/r/mysql.result storage/connect/mysql-test/connect/r/odbc_sqlite3.result storage/connect/mysql-test/connect/r/tbl.result storage/connect/mysql-test/connect/r/upd.result storage/connect/mysql-test/connect/r/vec.result storage/connect/mysql-test/connect/r/xml.result storage/connect/mysql-test/connect/t/bin.test storage/connect/mysql-test/connect/t/csv.test storage/connect/mysql-test/connect/t/dbf.test storage/connect/mysql-test/connect/t/dir.test storage/connect/mysql-test/connect/t/fix.test storage/connect/mysql-test/connect/t/fmt.test storage/connect/mysql-test/connect/t/ini.test storage/connect/mysql-test/connect/t/mysql.test storage/connect/mysql-test/connect/t/odbc_sqlite3.test storage/connect/mysql-test/connect/t/tbl.test storage/connect/mysql-test/connect/t/vec.test storage/connect/mysql-test/connect/t/xml.test storage/connect/odbconn.cpp storage/connect/osutil.c storage/connect/osutil.h storage/connect/plgcnx.h storage/connect/plgdbsem.h storage/connect/plgdbutl.cpp storage/connect/plugutil.c storage/connect/rcmsg.c storage/connect/reldef.cpp storage/connect/tabcol.cpp storage/connect/tabcol.h storage/connect/tabfmt.cpp storage/connect/tabmysql.cpp storage/connect/tabmysql.h storage/connect/tabodbc.cpp storage/connect/tabpivot.cpp storage/connect/tabpivot.h storage/connect/tabsys.cpp storage/connect/tabsys.h storage/connect/tabtbl.cpp storage/connect/tabtbl.h storage/connect/tabwmi.cpp storage/connect/user_connect.cc storage/connect/valblk.cpp storage/connect/valblk.h storage/connect/value.cpp storage/connect/value.h storage/connect/xobject.h storage/connect/xtable.h storage/perfschema/ha_perfschema.cc pending merges: Alexander Barkov 2013-06-08 Fixing a few compiler warnings Olivier Bertrand 2013-06-05 - Change CRLF line endings to LF Olivier Bertrand 2013-06-04 - Adding parallelism to the TBL table type Sergei Golubchik 2013-06-03 compiler warnings Alexander Barkov 2013-06-03 Fixing the problem with my_bool_t define... Olivier Bertrand 2013-05-28 - Fix crash when a null qrp is returned ... Olivier Bertrand 2013-05-28 - Extending connect_assisted_discovery c... Alexander Barkov 2013-05-28 Recording test results forgotten in the ... Alexander Barkov 2013-05-27 [merge] Merging with the latest 10.0 Alexander Barkov 2013-05-27 - Fixing embedded verision of the Connec... Alexander Barkov 2013-05-27 Fixing ABI template, to take into accoun... Alexander Barkov 2013-05-27 Fixing ABI template, to take into accoun... Olivier Bertrand 2013-05-27 - Fix Windows compile error Alexander Barkov 2013-05-24 Adding the timezone plugin service, to c... Alexander Barkov 2013-05-24 Do not run mysql.test in case of embedde... Alexander Barkov 2013-05-24 Splitting SQLite3 tests into two parts: Alexander Barkov 2013-05-24 Removing more cases of direct use of thd. Alexander Barkov 2013-05-24 Removing direct access to thd, using fun... Olivier Bertrand 2013-05-24 - Fix setting default type to MYSQL->PRO... Alexander Barkov 2013-05-23 Connect: fixing non thread-safe code. Olivier Bertrand 2013-05-22 - Changing CONNECT version number and date Alexander Barkov 2013-05-21 "mtr --suite=connect --embedded" tests d... Olivier Bertrand 2013-05-20 - Correct misplaced parenthesis in last ... Olivier Bertrand 2013-05-20 - Save and restore srcdef when getting a... Olivier Bertrand 2013-05-19 - Removing unused copy file Olivier Bertrand 2013-05-19 [merge] - Commit merged and resolve Alexander Barkov 2013-05-13 Fixing warnings (mostly "no previous dec... Alexander Barkov 2013-05-13 Fixing compiler warnings ("no previous d... Alexander Barkov 2013-05-13 Fixing a few "no previous declaration" w... Alexander Barkov 2013-05-13 Fixing a few compilation warnings ("no p... Olivier Bertrand 2013-05-19 - Allowing views and queries as paramete... Olivier Bertrand 2013-05-13 [merge] - Commit merged changes Alexander Barkov 2013-05-13 [merge] Merge from maria-10.0 Alexander Barkov 2013-05-13 Enabling --suite=connect by default Olivier Bertrand 2013-05-13 - Code cleaning. Eliminating unused code... Olivier Bertrand 2013-05-13 - fix use of uninitialized variable (colp) Olivier Bertrand 2013-05-13 - Set tdbp to NULL when ignored Olivier Bertrand 2013-05-12 - Changing mode from +x to -x Olivier Bertrand 2013-05-12 - Code cleaning. Olivier Bertrand 2013-05-11 - Fix tabpivot compile errors on Linux. Olivier Bertrand 2013-05-11 - Added a test case for PIVOT tables Olivier Bertrand 2013-05-10 - Add pivot table files and support Olivier Bertrand 2013-05-10 - Added table type PIVOT Olivier Bertrand 2013-05-09 - Fix inverted test on am in MYSQLDEF::D... Olivier Bertrand 2013-05-05 - General code cleaning, eliminating a f... Olivier Bertrand 2013-05-04 - Add test for XCOL and OCCUR tables Olivier Bertrand 2013-05-02 - Adding a loop test to prevent PROXY ba... Olivier Bertrand 2013-04-30 - Change in connect_assisted_discovery t... Olivier Bertrand 2013-04-30 - Allow PROXY based tables to specify My... Olivier Bertrand 2013-04-29 - Fix a bug causing a crash when using O... Olivier Bertrand 2013-04-29 - Adding 3 new table types:
Diffstat (limited to 'storage')
-rw-r--r--storage/connect/CMakeLists.txt15
-rw-r--r--storage/connect/catalog.h10
-rw-r--r--storage/connect/colblk.cpp13
-rw-r--r--storage/connect/colblk.h1
-rw-r--r--storage/connect/connect.cc26
-rw-r--r--storage/connect/connect.h1
-rw-r--r--storage/connect/filamdbf.cpp7
-rw-r--r--storage/connect/global.h3
-rw-r--r--storage/connect/ha_connect.cc559
-rw-r--r--storage/connect/ha_connect.h60
-rw-r--r--storage/connect/inihandl.c12
-rw-r--r--storage/connect/inihandl.h54
-rw-r--r--storage/connect/maputil.h1
-rw-r--r--storage/connect/mycat.cc86
-rw-r--r--storage/connect/myconn.cpp62
-rw-r--r--storage/connect/myconn.h9
-rw-r--r--storage/connect/mysql-test/connect/r/bin.result94
-rw-r--r--storage/connect/mysql-test/connect/r/csv.result94
-rw-r--r--storage/connect/mysql-test/connect/r/dbf.result94
-rw-r--r--storage/connect/mysql-test/connect/r/dir.result69
-rw-r--r--storage/connect/mysql-test/connect/r/fix.result94
-rw-r--r--storage/connect/mysql-test/connect/r/fmt.result4
-rw-r--r--storage/connect/mysql-test/connect/r/grant.result539
-rw-r--r--storage/connect/mysql-test/connect/r/ini.result79
-rw-r--r--storage/connect/mysql-test/connect/r/ini_grant.result79
-rw-r--r--storage/connect/mysql-test/connect/r/mysql.result63
-rw-r--r--storage/connect/mysql-test/connect/r/mysql_grant.result63
-rw-r--r--storage/connect/mysql-test/connect/r/occur.result255
-rw-r--r--storage/connect/mysql-test/connect/r/odbc_sqlite3.result69
-rw-r--r--storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result72
-rw-r--r--storage/connect/mysql-test/connect/r/pivot.result230
-rw-r--r--storage/connect/mysql-test/connect/r/tbl.result3
-rw-r--r--storage/connect/mysql-test/connect/r/upd.result6
-rw-r--r--storage/connect/mysql-test/connect/r/vec.result94
-rw-r--r--storage/connect/mysql-test/connect/r/xcol.result85
-rw-r--r--storage/connect/mysql-test/connect/r/xml.result106
-rw-r--r--storage/connect/mysql-test/connect/r/xml_grant.result96
-rw-r--r--storage/connect/mysql-test/connect/std_data/expenses.txt24
-rw-r--r--storage/connect/mysql-test/connect/t/bin.test4
-rw-r--r--storage/connect/mysql-test/connect/t/csv.test4
-rw-r--r--storage/connect/mysql-test/connect/t/dbf.test4
-rw-r--r--storage/connect/mysql-test/connect/t/dir.test70
-rw-r--r--storage/connect/mysql-test/connect/t/fix.test4
-rw-r--r--storage/connect/mysql-test/connect/t/fmt.test170
-rw-r--r--storage/connect/mysql-test/connect/t/grant.test95
-rw-r--r--storage/connect/mysql-test/connect/t/have_odbc_sqlite3.inc15
-rw-r--r--storage/connect/mysql-test/connect/t/ini.test75
-rw-r--r--storage/connect/mysql-test/connect/t/ini_grant.test79
-rw-r--r--storage/connect/mysql-test/connect/t/mysql.test67
-rw-r--r--storage/connect/mysql-test/connect/t/mysql_grant.test78
-rw-r--r--storage/connect/mysql-test/connect/t/occur.test61
-rw-r--r--storage/connect/mysql-test/connect/t/odbc_sqlite3.test71
-rw-r--r--storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test79
-rw-r--r--storage/connect/mysql-test/connect/t/pivot.test146
-rw-r--r--storage/connect/mysql-test/connect/t/tbl.test2
-rw-r--r--storage/connect/mysql-test/connect/t/vec.test4
-rw-r--r--storage/connect/mysql-test/connect/t/xcol.test28
-rw-r--r--storage/connect/mysql-test/connect/t/xml.test17
-rw-r--r--storage/connect/mysql-test/connect/t/xml_grant.test23
-rw-r--r--storage/connect/odbconn.cpp37
-rw-r--r--storage/connect/osutil.c4
-rw-r--r--storage/connect/osutil.h42
-rw-r--r--storage/connect/plgcnx.h11
-rw-r--r--storage/connect/plgdbsem.h23
-rw-r--r--storage/connect/plgdbutl.cpp10
-rw-r--r--storage/connect/plugutil.c40
-rw-r--r--storage/connect/rcmsg.c1
-rw-r--r--storage/connect/rcmsg.h15
-rw-r--r--storage/connect/reldef.cpp13
-rw-r--r--storage/connect/tabcol.cpp20
-rw-r--r--storage/connect/tabcol.h19
-rw-r--r--storage/connect/tabfmt.cpp28
-rw-r--r--storage/connect/tabmysql.cpp251
-rw-r--r--storage/connect/tabmysql.h15
-rw-r--r--storage/connect/taboccur.cpp592
-rw-r--r--storage/connect/taboccur.h139
-rw-r--r--storage/connect/tabodbc.cpp3
-rw-r--r--storage/connect/tabpivot.cpp1296
-rw-r--r--storage/connect/tabpivot.h217
-rw-r--r--storage/connect/tabsys.cpp83
-rw-r--r--storage/connect/tabsys.h5
-rw-r--r--storage/connect/tabtbl.cpp607
-rw-r--r--storage/connect/tabtbl.h139
-rw-r--r--storage/connect/tabutil.cpp624
-rw-r--r--storage/connect/tabutil.h141
-rw-r--r--storage/connect/tabwmi.cpp6
-rw-r--r--storage/connect/tabxcl.cpp283
-rw-r--r--storage/connect/tabxcl.h104
-rw-r--r--storage/connect/user_connect.cc6
-rw-r--r--storage/connect/valblk.cpp66
-rw-r--r--storage/connect/valblk.h7
-rw-r--r--storage/connect/value.cpp93
-rw-r--r--storage/connect/value.h7
-rw-r--r--storage/connect/xobject.h1
-rw-r--r--storage/connect/xtable.h1
-rw-r--r--storage/perfschema/ha_perfschema.cc4
96 files changed, 6077 insertions, 3203 deletions
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt
index 4f02924d6b3..34bf7fc2491 100644
--- a/storage/connect/CMakeLists.txt
+++ b/storage/connect/CMakeLists.txt
@@ -18,25 +18,27 @@ SET(CONNECT_PLUGIN_DYNAMIC "connect")
SET(CONNECT_SOURCES
ha_connect.cc connect.cc user_connect.cc mycat.cc
-fmdlex.c osutil.c plugutil.c rcmsg.c
+fmdlex.c osutil.c plugutil.c rcmsg.c rcmsg.h
csort.cpp maputil.cpp plgdbutl.cpp
colblk.cpp reldef.cpp tabcol.cpp table.cpp
filamap.cpp filamdbf.cpp filamfix.cpp filamtxt.cpp filamvct.cpp
tabdos.cpp tabfix.cpp tabfmt.cpp tabmul.cpp tabsys.cpp tabvct.cpp
valblk.cpp value.cpp xindex.cpp xobject.cpp
filamzip.cpp tabtbl.cpp myutil.cpp
+tabutil.cpp tabxcl.cpp taboccur.cpp tabpivot.cpp
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
-global.h ha_connect.h maputil.h msgid.h mycat.h myutil.h os.h
+global.h ha_connect.h inihandl.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 tabmul.h tabsys.h tabtbl.h tabvct.h
-user_connect.h valblk.h value.h xindex.h xobject.h xtable.h)
+user_connect.h valblk.h value.h xindex.h xobject.h xtable.h
+tabutil.h tabxcl.h taboccur.h tabpivot.h)
#
# Definitions that are shared for all OSes
#
add_definitions( -DMARIADB -DFORCE_INIT_OF_VARS )
-add_definitions( -DHUGE_SUPPORT -DZIP_SUPPORT )
+add_definitions( -DHUGE_SUPPORT -DZIP_SUPPORT -DPIVOT_SUPPORT )
#
@@ -46,7 +48,6 @@ IF(UNIX)
# Bar: -Wfatal-errors removed (does not present in gcc on solaris10)
if(WITH_WARNINGS)
add_definitions(-Wall -Wextra -Wmissing-declarations)
- add_definitions(-Wno-non-virtual-dtor)
message(STATUS "CONNECT: GCC: All warnings enabled")
else()
add_definitions(-Wall -Wmissing-declarations)
@@ -62,13 +63,11 @@ IF(UNIX)
# add_definitions(-Wno-int-to-pointer-cast)
# Bar: -Wno-narrowing commented (does not present in gcc on solaris10)
# add_definitions(-Wno-narrowing)
- add_definitions(-Wno-non-virtual-dtor)
# This switch is for pure C only:
# add_definitions(-Wno-implicit-function-declaration)
# These switches are for C++ only
# add_definitions(-Wno-reorder)
-# add_definitions(-Wno-delete-non-virtual-dtor)
message(STATUS "CONNECT: GCC: Some warnings disabled")
endif(WITH_WARNINGS)
@@ -176,7 +175,7 @@ OPTION(CONNECT_WITH_MYSQL
IF(CONNECT_WITH_MYSQL)
SET(CONNECT_SOURCES ${CONNECT_SOURCES}
- myconn.cpp myconn.h tabmysql.cpp tabxml.h)
+ myconn.cpp myconn.h tabmysql.cpp tabmysql.h)
add_definitions(-DMYSQL_SUPPORT)
IF(NOT UNIX)
#
diff --git a/storage/connect/catalog.h b/storage/connect/catalog.h
index 4f0584ef7bc..3a06aea7a30 100644
--- a/storage/connect/catalog.h
+++ b/storage/connect/catalog.h
@@ -62,14 +62,9 @@ class DllExport CATALOG {
virtual ~CATALOG() { } // Make -Wdelete-non-virtual-dtor happy
// Implementation
- void *GetDescp(void) {return Descp;}
- PRELDEF GetTo_Desc(void) {return To_Desc;}
-//PSZ GetDescFile(void) {return DescFile;}
int GetCblen(void) {return Cblen;}
bool GetDefHuge(void) {return DefHuge;}
void SetDefHuge(bool b) {DefHuge = b;}
-//bool GetSepIndex(void) {return SepIndex;}
-//void SetSepIndex(bool b) {SepIndex = b;}
char *GetCbuf(void) {return Cbuf;}
char *GetDataPath(void) {return (char*)DataPath;}
@@ -115,15 +110,10 @@ class DllExport CATALOG {
virtual PRELDEF MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) {return NULL;}
// Members
- PRELDEF To_Desc; /* To chain of relation desc. */
- void *Descp; /* To DB description area */
-//AREADEF DescArea; /* Table desc. area size */
char *Cbuf; /* Buffer used for col section */
int Cblen; /* Length of suballoc. buffer */
CURTAB Ctb; /* Used to enumerate tables */
bool DefHuge; /* true: tables default to huge */
-//bool SepIndex; /* true: separate index files */
-//char DescFile[_MAX_PATH]; /* DB description filename */
LPCSTR DataPath; /* Is the Path of DB data dir */
}; // end of class CATALOG
diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp
index cdbf6f4b42b..dfdc82e99a7 100644
--- a/storage/connect/colblk.cpp
+++ b/storage/connect/colblk.cpp
@@ -160,19 +160,6 @@ bool COLBLK::CheckSort(PTDB tdbp)
} // end of CheckSort
/***********************************************************************/
-/* MarkCol: see PlugMarkCol for column references to mark. */
-/***********************************************************************/
-void COLBLK::MarkCol(ushort bits)
- {
- ColUse |= bits;
-
-#ifdef DEBTRACE
- htrc(" column R%d.%s marked as %04X\n",
- To_Tdb->GetTdb_No(), Name, ColUse);
-#endif
- } // end of MarkCol
-
-/***********************************************************************/
/* 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. */
diff --git a/storage/connect/colblk.h b/storage/connect/colblk.h
index cf6fb443308..5fbb118fc72 100644
--- a/storage/connect/colblk.h
+++ b/storage/connect/colblk.h
@@ -64,7 +64,6 @@ class DllExport COLBLK : public XOBJECT {
virtual bool IsSpecial(void) {return false;}
virtual int CheckSpcCol(PTDB tdbp, int n) {return 2;}
virtual bool CheckSort(PTDB tdbp);
- virtual void MarkCol(ushort bits);
virtual bool Eval(PGLOBAL g);
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void SetTo_Val(PVAL valp) {}
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index 54816f80e5c..41fb061bd7f 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -31,7 +31,6 @@
/* global.h is header containing all global declarations. */
/* plgdbsem.h is header containing the DB applic. declarations. */
/***********************************************************************/
-#define MYSQL_SERVER 1
#define DONT_DEFINE_VOID
#include "handler.h"
#undef OFFSET
@@ -71,10 +70,7 @@ int rename_file_ext(const char *from, const char *to,const char *ext);
PGLOBAL CntExit(PGLOBAL g)
{
if (g) {
- PDBUSER dup= PlgGetUser(g);
-
CntEndDB(g);
- free(dup);
if (g->Activityp)
delete g->Activityp;
@@ -94,13 +90,10 @@ void CntEndDB(PGLOBAL g)
PDBUSER dbuserp= PlgGetUser(g);
if (dbuserp) {
- if (dbuserp->Catalog) {
+ if (dbuserp->Catalog)
delete dbuserp->Catalog;
- dbuserp->Catalog= NULL;
- } // endif Catalog
- *dbuserp->Name= '\0';
-// *dbuserp->Work= '\0';
+ free(dbuserp);
} // endif dbuserp
} // end of CntEndDB
@@ -258,10 +251,12 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
return true;
} // endif tdbp
- if (!c1)
- // Allocate all column blocks for that table
- tdbp->ColDB(g, NULL, 0);
- else for (p= c1; *p; p+= n) {
+ if (!c1) {
+ if (mode == MODE_INSERT)
+ // Allocate all column blocks for that table
+ tdbp->ColDB(g, NULL, 0);
+
+ } else for (p= c1; *p; p+= n) {
// Allocate only used column blocks
if (xtrace)
printf("Allocating column %s\n", p);
@@ -657,11 +652,6 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id)
cdp= tdbp->Key(k)->GetCdp();
valp= AllocateValue(g, cdp->GetType(), cdp->GetLength());
tdbp->To_Link[k]= new(g) CONSTANT(valp);
-
-//if (kdp->Klen && tdbp->To_Link[k]->GetResultType() == TYPE_STRING)
-// ((XCOLBLK*)tdbp->To_Link[k])->SetLength(kdp->Klen);
-
-//((PCOL)tdbp->To_Link[k])->InitValue(g);
} // endfor k
// Make the index on xdp
diff --git a/storage/connect/connect.h b/storage/connect/connect.h
index 3fd52d283c6..e81e54776c9 100644
--- a/storage/connect/connect.h
+++ b/storage/connect/connect.h
@@ -44,6 +44,7 @@ RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all);
bool CntInfo(PGLOBAL g, PTDB tdbp, PXF info);
int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
bool *incl, key_part_map *kmap);
+PGLOBAL CntExit(PGLOBAL g);
/***********************************************************************/
/* Definition of classes XCOLCRT, XIXDEF, XKPDEF, DOXDEF, TDBDOX */
diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp
index 3575a6b422a..0a67195b200 100644
--- a/storage/connect/filamdbf.cpp
+++ b/storage/connect/filamdbf.cpp
@@ -178,15 +178,13 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
/****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info)
{
- static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
- DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME,
FLD_PREC, FLD_LENGTH, FLD_SCALE};
static unsigned int length[] = {11, 6, 8, 10, 10, 6};
char buf[2], filename[_MAX_PATH];
- int ncol = sizeof(dbtype) / sizeof(int);
+ int ncol = sizeof(buftyp) / sizeof(int);
int rc, type, len, field, fields;
BOOL bad;
DBFHEADER mainhead;
@@ -228,8 +226,7 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info)
fields = 0;
qrp = PlgAllocResult(g, ncol, fields, IDS_COLUMNS + 3,
- dbtype, buftyp, fldtyp, length, true, false);
-//qrp->Info = info || (rc == RC_INFO);
+ buftyp, fldtyp, length, true, false);
if (info)
return qrp;
diff --git a/storage/connect/global.h b/storage/connect/global.h
index ae50e5ac160..303078f5a18 100644
--- a/storage/connect/global.h
+++ b/storage/connect/global.h
@@ -239,7 +239,8 @@ DllExport short GetLineLength(PGLOBAL); // Console line length
DllExport PGLOBAL PlugInit(LPCSTR, uint); // Plug global initialization
DllExport int PlugExit(PGLOBAL); // Plug global termination
DllExport LPSTR PlugRemoveType(LPSTR, LPCSTR);
-DllExport LPCSTR PlugSetPath(LPSTR, LPCSTR, LPCSTR);
+DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR prefix, LPCSTR name, LPCSTR dir);
+DllExport BOOL PlugIsAbsolutePath(LPCSTR path);
DllExport void *PlugAllocMem(PGLOBAL, uint);
DllExport BOOL PlugSubSet(PGLOBAL, void *, uint);
DllExport void *PlugSubAlloc(PGLOBAL, void *, size_t);
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 8136e6d0263..7d37b79bae8 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -27,11 +27,12 @@
ha_connect will let you create/open/delete tables, the created table can be
done specifying an already existing file, the drop table command will just
suppress the table definition but not the eventual data file.
- Indexes are not yet supported but data can be inserted, updated or deleted.
+ Indexes are not supported for all table types but data can be inserted,
+ updated or deleted.
You can enable the CONNECT storage engine in your build by doing the
following during your build process:<br> ./configure
- --with-connect-storage-engine (not implemented yet)
+ --with-connect-storage-engine
You can install the CONNECT handler as all other storage handlers.
@@ -122,6 +123,7 @@
#include "tabmysql.h"
#endif // MYSQL_SUPPORT
#include "filamdbf.h"
+#include "tabxcl.h"
#include "tabfmt.h"
#include "reldef.h"
#include "tabcol.h"
@@ -136,6 +138,7 @@
#include "mycat.h"
#include "myutil.h"
#include "preparse.h"
+#include "inihandl.h"
#define PLGXINI "plgcnx.ini" /* Configuration settings file */
#define my_strupr(p) my_caseup_str(default_charset_info, (p));
@@ -156,7 +159,7 @@ extern "C" char nmfile[];
extern "C" char pdebug[];
extern "C" {
- char version[]= "Version 1.01.0004 April 10, 2013";
+ char version[]= "Version 1.01.0006 Mai 21, 2013";
#if defined(XMSG)
char msglang[]; // Default message language
@@ -164,6 +167,16 @@ extern "C" {
int trace= 0; // The general trace value
} // extern "C"
+bool OcrColumns(PGLOBAL g, PQRYRES qrp, const char *col,
+ const char *ocr, const char *rank);
+bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, const char *col,
+ const char *ocr, const char *rank);
+PQRYRES PivotColumns(PGLOBAL g, const char *tab, const char *src,
+ const char *picol, const char *fncol,
+ const char *host, const char *db,
+ const char *user, const char *pwd,
+ int port);
+
/****************************************************************************/
/* Initialize the ha_connect static members. */
/****************************************************************************/
@@ -187,44 +200,13 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
handlerton *connect_hton;
/**
- structure for CREATE TABLE options (table options)
+ CREATE TABLE option list (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 *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;
- };
-
ha_create_table_option connect_table_option_list[]=
{
- // These option are for stand alone Connect tables
HA_TOPTION_STRING("TABLE_TYPE", type),
HA_TOPTION_STRING("FILE_NAME", filename),
HA_TOPTION_STRING("XFILE_NAME", optname),
@@ -237,6 +219,8 @@ ha_create_table_option connect_table_option_list[]=
HA_TOPTION_STRING("MODULE", module),
HA_TOPTION_STRING("SUBTYPE", subtype),
HA_TOPTION_STRING("CATFUNC", catfunc),
+ HA_TOPTION_STRING("SRCDEF", srcdef),
+ HA_TOPTION_STRING("COLIST", colist),
HA_TOPTION_STRING("OPTION_LIST", oplist),
HA_TOPTION_STRING("DATA_CHARSET", data_charset),
HA_TOPTION_NUMBER("LRECL", lrecl, 0, 0, INT_MAX32, 1),
@@ -244,8 +228,8 @@ ha_create_table_option connect_table_option_list[]=
//HA_TOPTION_NUMBER("ESTIMATE", estimate, 0, 0, INT_MAX32, 1),
HA_TOPTION_NUMBER("MULTIPLE", multiple, 0, 0, 2, 1),
HA_TOPTION_NUMBER("HEADER", header, 0, 0, 3, 1),
- HA_TOPTION_NUMBER("QUOTED", quoted, -1, 0, 3, 1),
- HA_TOPTION_NUMBER("ENDING", ending, -1, 0, INT_MAX32, 1),
+ HA_TOPTION_NUMBER("QUOTED", quoted, (ulonglong) -1, 0, 3, 1),
+ HA_TOPTION_NUMBER("ENDING", ending, (ulonglong) -1, 0, INT_MAX32, 1),
HA_TOPTION_NUMBER("COMPRESS", compressed, 0, 0, 2, 1),
//HA_TOPTION_BOOL("COMPRESS", compressed, 0),
HA_TOPTION_BOOL("MAPPED", mapped, 0),
@@ -258,25 +242,14 @@ ha_create_table_option connect_table_option_list[]=
/**
- structure for CREATE TABLE options (field options)
+ CREATE TABLE option list (field options)
These can be specified in the CREATE TABLE per field:
CREATE TABLE ( field ... {...here...}, ... )
*/
-struct ha_field_option_struct
-{
- ulonglong offset;
- ulonglong freq; // Not used by this version
- ulonglong opt; // Not used by this version
- ulonglong fldlen;
- const char *dateformat;
- const char *fieldformat;
- char *special;
-};
-
ha_create_table_option connect_field_option_list[]=
{
- HA_FOPTION_NUMBER("FLAG", offset, -1, 0, INT_MAX32, 1),
+ HA_FOPTION_NUMBER("FLAG", offset, (ulonglong) -1, 0, INT_MAX32, 1),
HA_FOPTION_NUMBER("FREQUENCY", freq, 0, 0, INT_MAX32, 1), // not used
HA_FOPTION_NUMBER("OPT_VALUE", opt, 0, 0, 2, 1), // used for indexing
HA_FOPTION_NUMBER("FIELD_LENGTH", fldlen, 0, 0, INT_MAX32, 1),
@@ -327,6 +300,13 @@ static void init_connect_psi_keys() {}
#endif
+DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR name, LPCSTR dir)
+{
+ const char *res= PlugSetPath(to, mysql_data_home, name, dir);
+ return res;
+}
+
+
/**
@brief
If frm_error() is called then we will use this to determine
@@ -345,9 +325,8 @@ static void init_connect_psi_keys() {}
delete_table method in handler.cc
*/
static const char *ha_connect_exts[]= {
- ".tbl", ".dnx", ".fnx", ".bnx", ".vnx", ".dbx", ".dos", ".fix", ".csv",
- ".fmt", ".dbf", ".xml", ".ini", ".vec", ".odbc", ".mysql", ".dir",
- ".mac", ".wmi", ".bin", ".oem",
+ ".dos", ".fix", ".csv",".bin", ".fmt", ".dbf", ".xml", ".ini", ".vec",
+ ".dnx", ".fnx", ".bnx", ".vnx", ".dbx",
NULL
};
@@ -632,7 +611,7 @@ static char *GetListOption(PGLOBAL g, const char *opname,
} else {
if (pn) {
- n= pn - pk;
+ n= min(pn - pk, 15);
memcpy(key, pk, n);
key[n]= 0;
} else
@@ -697,6 +676,10 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
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;
@@ -708,6 +691,14 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
// Return the handler default value
if (!stricmp(opname, "Dbname") || !stricmp(opname, "Database"))
opval= (char*)GetDBName(NULL); // Current database
+ else if (!stricmp(opname, "Type")) // Default type
+ opval= (!options) ? NULL :
+ (options->srcdef) ? (char*)"MYSQL" :
+ (options->tabname) ? (char*)"PROXY" : (char*)"DOS";
+ else if (!stricmp(opname, "User")) // Connected user
+ opval= (char *) "root";
+ else if (!stricmp(opname, "Host")) // Connected user host
+ opval= (char *) "localhost";
else
opval= sdef; // Caller default
@@ -728,7 +719,9 @@ bool ha_connect::GetBooleanOption(char *opname, bool bdef)
char *pv;
PTOS options= GetTableOptionStruct(table);
- if (!options)
+ if (!stricmp(opname, "View"))
+ opval= (tshp) ? tshp->is_view : table->s->is_view;
+ else if (!options)
;
else if (!stricmp(opname, "Mapped"))
opval= options->mapped;
@@ -773,9 +766,9 @@ bool ha_connect::SetBooleanOption(char *opname, bool b)
/****************************************************************************/
int ha_connect::GetIntegerOption(char *opname)
{
- int opval= NO_IVAL;
- char *pv;
- PTOS options= GetTableOptionStruct(table);
+ ulonglong opval= NO_IVAL;
+ char *pv;
+ PTOS options= GetTableOptionStruct(table);
if (!options)
;
@@ -799,11 +792,11 @@ int ha_connect::GetIntegerOption(char *opname)
else if (!stricmp(opname, "Compressed"))
opval= (options->compressed);
- if (opval == NO_IVAL && options && options->oplist)
+ if (opval == (ulonglong)NO_IVAL && options && options->oplist)
if ((pv= GetListOption(xp->g, opname, options->oplist)))
- opval= atoi(pv);
+ opval= (unsigned)atoll(pv);
- return opval;
+ return (int)opval;
} // end of GetIntegerOption
/****************************************************************************/
@@ -870,7 +863,7 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf)
} else
fldp= (tshp) ? tshp->field : table->field;
- if (!(fp= *fldp))
+ if (!fldp || !(fp= *fldp))
return NULL;
// Get the CONNECT field options structure
@@ -885,13 +878,13 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf)
pcf->Name= (char*)fp->field_name;
pcf->Prec= 0;
- pcf->Opt= (fop) ? fop->opt : 0;
+ pcf->Opt= (fop) ? (int)fop->opt : 0;
if ((pcf->Length= fp->field_length) < 0)
pcf->Length= 256; // BLOB?
if (fop) {
- pcf->Offset= fop->offset;
+ pcf->Offset= (int)fop->offset;
// pcf->Freq= fop->freq;
pcf->Datefmt= (char*)fop->dateformat;
pcf->Fieldfmt= (char*)fop->fieldformat;
@@ -905,6 +898,7 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf)
switch (fp->type()) {
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
pcf->Flags |= U_VAR;
case MYSQL_TYPE_STRING:
pcf->Type= TYPE_STRING;
@@ -941,7 +935,7 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf)
// Field_length is only used for DATE columns
if (fop->fldlen)
- pcf->Length= fop->fldlen;
+ pcf->Length= (int)fop->fldlen;
else {
int len;
@@ -1122,8 +1116,9 @@ PTDB ha_connect::GetTDB(PGLOBAL g)
table_name= GetTableName();
- if (tdbp && !stricmp(tdbp->GetName(), table_name)
- && tdbp->GetMode() == xmod && !xp->CheckQuery(valid_query_id)) {
+ if (!xp->CheckQuery(valid_query_id) && tdbp
+ && !stricmp(tdbp->GetName(), table_name)
+ && tdbp->GetMode() == xmod) {
tp= tdbp;
tp->SetMode(xmod);
} else if ((tp= CntGetTDB(g, table_name, xmod, this)))
@@ -1874,11 +1869,13 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked)
// Try to get the user if possible
xp= GetUser(ha_thd(), xp);
- PGLOBAL g= xp->g;
+ PGLOBAL g= (xp) ? xp->g : NULL;
// Try to set the database environment
if (g)
rc= (CntCheckDB(g, this, name)) ? (-2) : 0;
+ else
+ rc= HA_ERR_INTERNAL_ERROR;
DBUG_RETURN(rc);
} // end of open
@@ -2688,18 +2685,24 @@ int ha_connect::delete_all_rows()
bool ha_connect::check_privileges(THD *thd, PTOS options)
{
- if (!options->type)
- options->type= "DOS";
+ if (!options->type) {
+ if (options->srcdef)
+ options->type= "MYSQL";
+ else if (options->tabname)
+ options->type= "PROXY";
+ else
+ options->type= "DOS";
+
+ } // endif type
switch (GetTypeID(options->type))
{
case TAB_UNDEF:
- case TAB_CATLG:
+// case TAB_CATLG:
case TAB_PLG:
case TAB_JCT:
case TAB_DMY:
case TAB_NIY:
- case TAB_PIVOT:
my_printf_error(ER_UNKNOWN_ERROR,
"Unsupported table type %s", MYF(0), options->type);
return true;
@@ -2733,13 +2736,18 @@ bool ha_connect::check_privileges(THD *thd, PTOS options)
case TAB_OEM:
return check_access(thd, FILE_ACL, NULL, NULL, NULL, 0, 0);
+ // This is temporary until a solution is found
case TAB_TBL:
+ case TAB_XCL:
+ case TAB_PRX:
+ case TAB_OCCUR:
+ case TAB_PIVOT:
return false;
}
my_printf_error(ER_UNKNOWN_ERROR, "check_privileges failed", MYF(0));
return true;
-}
+} // end of check_privileges
// Check that two indexes are equivalent
bool ha_connect::IsSameIndex(PIXDEF xp1, PIXDEF xp2)
@@ -2791,12 +2799,14 @@ bool ha_connect::IsSameIndex(PIXDEF xp1, PIXDEF xp2)
int ha_connect::external_lock(THD *thd, int lock_type)
{
int rc= 0;
- bool del= false, xcheck=false, cras= false;
+ bool xcheck=false, cras= false;
MODE newmode;
PTOS options= GetTableOptionStruct(table);
PGLOBAL g= GetPlug(thd, xp);
DBUG_ENTER("ha_connect::external_lock");
+ DBUG_ASSERT(thd == current_thd);
+
if (xtrace)
printf("%p external_lock: lock_type=%d\n", this, lock_type);
@@ -2831,6 +2841,10 @@ int ha_connect::external_lock(THD *thd, int lock_type)
bool oldsep= ((PCHK)g->Xchk)->oldsep;
bool newsep= ((PCHK)g->Xchk)->newsep;
PTDBDOS tdp= (PTDBDOS)(tdbp ? tdbp : GetTDB(g));
+
+ if (!tdp)
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+
PDOSDEF ddp= (PDOSDEF)tdp->GetDef();
PIXDEF xp, xp1, xp2, drp=NULL, adp= NULL;
PIXDEF oldpix= ((PCHK)g->Xchk)->oldpix;
@@ -2913,16 +2927,16 @@ int ha_connect::external_lock(THD *thd, int lock_type)
} // endif MODE_ANY
if (xtrace) {
- printf("%p external_lock: cmdtype=%d\n", this, thd->lex->sql_command);
- printf("Cmd=%.*s\n", (int) thd->query_string.length(),
- thd->query_string.str());
+ LEX_STRING *query_string= thd_query_string(thd);
+ printf("%p external_lock: cmdtype=%d\n", this, thd_sql_command(thd));
+ printf("Cmd=%.*s\n", (int) query_string->length, query_string->str);
} // endif xtrace
// Next code is temporarily replaced until sql_command is set
stop= false;
if (newmode == MODE_WRITE) {
- switch (thd->lex->sql_command) {
+ switch (thd_sql_command(thd)) {
case SQLCOM_CREATE_TABLE:
case SQLCOM_INSERT:
case SQLCOM_LOAD:
@@ -2935,7 +2949,6 @@ int ha_connect::external_lock(THD *thd, int lock_type)
// break;
case SQLCOM_DELETE:
case SQLCOM_DELETE_MULTI:
- del= true;
case SQLCOM_TRUNCATE:
newmode= MODE_DELETE;
break;
@@ -2962,13 +2975,13 @@ int ha_connect::external_lock(THD *thd, int lock_type)
newmode= MODE_ANY;
break;
default:
- printf("Unsupported sql_command=%d", thd->lex->sql_command);
- sprintf(g->Message, "Unsupported sql_command=%d", thd->lex->sql_command);
+ printf("Unsupported sql_command=%d", thd_sql_command(thd));
+ sprintf(g->Message, "Unsupported sql_command=%d", thd_sql_command(thd));
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endswitch newmode
} else if (newmode == MODE_READ) {
- switch (thd->lex->sql_command) {
+ switch (thd_sql_command(thd)) {
case SQLCOM_CREATE_TABLE:
xcheck= true;
cras= true;
@@ -2999,8 +3012,8 @@ int ha_connect::external_lock(THD *thd, int lock_type)
newmode= MODE_ANY;
break;
default:
- printf("Unsupported sql_command=%d", thd->lex->sql_command);
- sprintf(g->Message, "Unsupported sql_command=%d", thd->lex->sql_command);
+ printf("Unsupported sql_command=%d", thd_sql_command(thd));
+ sprintf(g->Message, "Unsupported sql_command=%d", thd_sql_command(thd));
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endswitch newmode
@@ -3036,8 +3049,15 @@ int ha_connect::external_lock(THD *thd, int lock_type)
// This can NOT be called without open called first, but
// the table can have been closed since then
} else if (!tdbp || xp->CheckQuery(valid_query_id) || xmod != newmode) {
- if (tdbp)
- CloseTable(g);
+ if (tdbp) {
+ // If this is called by a later query, the table may have
+ // been already closed and the tdbp is not valid anymore.
+ if (xp->last_query_id == valid_query_id)
+ rc= CloseTable(g);
+ else
+ tdbp= NULL;
+
+ }// endif tdbp
xmod= newmode;
@@ -3103,6 +3123,63 @@ THR_LOCK_DATA **ha_connect::store_lock(THD *thd,
/**
+ Searches for a pointer to the last occurrence of the
+ character c in the string src.
+ Returns true on failure, false on success.
+*/
+static bool
+strnrchr(LEX_CSTRING *ls, const char *src, size_t length, int c)
+{
+ const char *srcend, *s;
+ for (s= srcend= src + length; s > src; s--)
+ {
+ if (s[-1] == c)
+ {
+ ls->str= s;
+ ls->length= srcend - s;
+ return false;
+ }
+ }
+ return true;
+}
+
+
+/**
+ Split filename into database and table name.
+*/
+static bool
+filename_to_dbname_and_tablename(const char *filename,
+ char *database, size_t database_size,
+ char *table, size_t table_size)
+{
+#if defined(WIN32)
+ char slash= '\\';
+#else // !WIN32
+ char slash= '/';
+#endif // !WIN32
+ LEX_CSTRING d, t;
+ size_t length= strlen(filename);
+
+ /* Find filename - the rightmost directory part */
+ if (strnrchr(&t, filename, length, slash) || t.length + 1 > table_size)
+ return true;
+ memcpy(table, t.str, t.length);
+ table[t.length]= '\0';
+ if (!(length-= t.length))
+ return true;
+
+ length--; /* Skip slash */
+
+ /* Find database name - the second rightmost directory part */
+ if (strnrchr(&d, filename, length, slash) || d.length + 1 > database_size)
+ return true;
+ memcpy(database, d.str, d.length);
+ database[d.length]= '\0';
+ return false;
+}
+
+
+/**
@brief
Used to delete or rename a table. By the time delete_table() has been
called all opened references to this table will have been closed
@@ -3128,22 +3205,20 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to)
DBUG_ENTER("ha_connect::delete_or_rename_table");
/* We have to retrieve the information about this table options. */
ha_table_option_struct *pos;
-#if defined(WIN32)
- const char *fmt= ".\\%[^\\]\\%s";
-#else // !WIN32
- const char *fmt= "./%[^/]/%s";
-#endif // !WIN32
char key[MAX_DBKEY_LENGTH], db[128], tabname[128];
- int rc;
+ int rc = 0;
uint key_length;
TABLE_SHARE *share;
THD *thd= current_thd;
- if (to)
- if (sscanf(to, fmt, db, tabname) != 2 || *tabname == '#')
- goto fin;
+ if (to && (filename_to_dbname_and_tablename(to, db, sizeof(db),
+ tabname, sizeof(tabname)) ||
+ *tabname == '#'))
+ goto fin;
- if (sscanf(name, fmt, db, tabname) != 2 || *tabname == '#')
+ if (filename_to_dbname_and_tablename(name, db, sizeof(db),
+ tabname, sizeof(tabname)) ||
+ *tabname == '#')
goto fin;
key_length= create_table_def_key(key, db, tabname);
@@ -3177,7 +3252,7 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to)
err:
free_table_share(share);
fin:
- DBUG_RETURN(0);
+ DBUG_RETURN(rc);
} // end of delete_or_rename_table
int ha_connect::delete_table(const char *name)
@@ -3267,35 +3342,43 @@ static char *encode(PGLOBAL g, char *cnm)
Return 0 if ok
*/
-bool add_field(String *sql, const char *field_name, const char *type,
- int len, int dec, uint tm, const char *rem)
+static bool add_field(String *sql, const char *field_name, const char *type,
+ int len, int dec, uint tm, const char *rem, int flag)
{
bool error= false;
+ error|= sql->append('`');
error|= sql->append(field_name);
- error|= sql->append(' ');
+ error|= sql->append("` ");
error|= sql->append(type);
+
if (len) {
error|= sql->append('(');
error|= sql->append_ulonglong(len);
- if (dec) {
+
+ if (dec || !strcmp(type, "DOUBLE")) {
error|= sql->append(',');
error|= sql->append_ulonglong(dec);
- }
+ } // endif dec
+
error|= sql->append(')');
- }
+ } // endif len
if (tm)
error|= sql->append(STRING_WITH_LEN(" NOT NULL"), system_charset_info);
if (rem && *rem) {
- error|= sql->append(" COMMENT='");
+ error|= sql->append(" COMMENT '");
error|= sql->append_for_single_quote(rem, strlen(rem));
error|= sql->append("'");
- }
+ } // endif rem
- sql->append(',');
+ if (flag) {
+ error|= sql->append(" FLAG=");
+ error|= sql->append_ulonglong(flag);
+ } // endif flag
+ sql->append(',');
return error;
} // end of add_field
@@ -3314,17 +3397,16 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
{
char spc= ',', qch= 0;
const char *fncn= "?";
- const char *user, *fn, *tab, *db, *host, *pwd, *prt, *sep; // *csn;
- char *dsn;
+ const char *user, *fn, *db, *host, *pwd, *prt, *sep, *tbl, *src;
+ const char *col, *ocl, *rnk, *pic, *fcl;
+ char *tab, *dsn;
#if defined(WIN32)
char *nsp= NULL, *cls= NULL;
#endif // WIN32
- int port= MYSQL_PORT, hdr= 0, mxr= 0, b= 0;
+ int port= 0, hdr= 0, mxr= 0, b= 0;
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
- bool ok= false, dbf= false;
+ bool bif, ok= false, dbf= false;
TABTYPE ttp= TAB_UNDEF;
- MEM_ROOT *mem= thd->mem_root;
- CHARSET_INFO *cs;
PQRYRES qrp;
PCOLRES crp;
PGLOBAL g= GetPlug(thd, NULL);
@@ -3338,51 +3420,88 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info);
- user= host= pwd= prt= dsn= NULL;
+ user= host= pwd= prt= tbl= src= col= ocl= pic= fcl= rnk= dsn= NULL;
// Get the useful create options
- ttp= GetTypeID(topt->type);
- fn= topt->filename;
- tab= topt->tabname;
- db= topt->dbname;
+ ttp= GetTypeID(topt->type);
+ fn= topt->filename;
+ tab= (char*)topt->tabname;
+ src= topt->srcdef;
+ db= topt->dbname;
fncn= topt->catfunc;
fnc= GetFuncID(fncn);
- sep= topt->separator;
+ sep= topt->separator;
spc= (!sep || !strcmp(sep, "\\t")) ? '\t' : *sep;
qch= topt->qchar ? *topt->qchar : topt->quoted >= 0 ? '"' : 0;
- hdr= topt->header;
+ hdr= (int)topt->header;
+ tbl= topt->tablist;
+ col= topt->colist;
+
if (topt->oplist) {
- host= GetListOption(g,"host", topt->oplist, "localhost");
- user= GetListOption(g,"user", topt->oplist, "root");
- // Default value db can come from the DBNAME=xxx option.
- db= GetListOption(g,"database", topt->oplist, db);
- pwd= GetListOption(g,"password", topt->oplist);
- prt= GetListOption(g,"port", topt->oplist);
- port= (prt) ? atoi(prt) : MYSQL_PORT;
+ host= GetListOption(g,"host", topt->oplist, "localhost");
+ user= GetListOption(g,"user", topt->oplist, "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);
+ ocl= GetListOption(g,"occurcol", topt->oplist, NULL);
+ pic= GetListOption(g,"pivotcol", topt->oplist, NULL);
+ fcl= GetListOption(g,"fnccol", topt->oplist, NULL);
+ rnk= GetListOption(g,"rankcol", topt->oplist, NULL);
+ pwd= GetListOption(g,"password", topt->oplist);
+ prt= GetListOption(g,"port", topt->oplist);
+ port= (prt) ? atoi(prt) : 0;
#if defined(WIN32)
- nsp= GetListOption(g,"namespace", topt->oplist);
- cls= GetListOption(g,"class", topt->oplist);
+ nsp= GetListOption(g,"namespace", topt->oplist);
+ cls= GetListOption(g,"class", topt->oplist);
#endif // WIN32
- mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
- } // endelse option_list
+ mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
+ } else {
+ host= "localhost";
+ user= "root";
+ } // endif option_list
if (!db)
- db= thd->db; // Default value
+ db= table_s->db.str; // Default value
// Check table type
if (ttp == TAB_UNDEF) {
- strcpy(g->Message, "No table_type. Was set to DOS");
+ topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS";
+ ttp= GetTypeID(topt->type);
+ sprintf(g->Message, "No table_type. Was set to %s", topt->type);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message);
- ttp= TAB_DOS;
- topt->type= "DOS";
} else if (ttp == TAB_NIY) {
sprintf(g->Message, "Unsupported table type %s", topt->type);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return HA_ERR_INTERNAL_ERROR;
} // endif ttp
- if (!tab && !(fnc & (FNC_TABLE | FNC_COL)))
- tab= (char*)create_info->alias;
+ if (!tab) {
+ if (ttp == TAB_TBL) {
+ // Make tab the first table of the list
+ char *p;
+
+ if (!tbl) {
+ strcpy(g->Message, "Missing table list");
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ return HA_ERR_INTERNAL_ERROR;
+ } // endif tbl
+
+ tab= (char*)PlugSubAlloc(g, NULL, strlen(tbl) + 1);
+ strcpy(tab, tbl);
+
+ if ((p= strchr(tab, ',')))
+ *p= 0;
+
+ if ((p=strchr(tab, '.'))) {
+ *p= 0;
+ db= tab;
+ tab= p + 1;
+ } // endif p
+
+ } else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL)))
+ tab= (char*)create_info->alias;
+
+ } // endif tab
switch (ttp) {
#if defined(ODBC_SUPPORT)
@@ -3433,7 +3552,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ok= false;
} else if (!user)
- user= "root"; // Avoid crash
+ user= "root";
break;
#endif // MYSQL_SUPPORT
@@ -3442,6 +3561,14 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ok= true;
break;
#endif // WIN32
+ case TAB_PIVOT:
+ supfnc = FNC_NO;
+ case TAB_PRX:
+ case TAB_TBL:
+ case TAB_XCL:
+ case TAB_OCCUR:
+ ok= true;
+ break;
default:
sprintf(g->Message, "Cannot get column info for table type %s", topt->type);
} // endif ttp
@@ -3453,19 +3580,36 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ok= false;
} // endif supfnc
+ if (src && fnc != FNC_NO) {
+ strcpy(g->Message, "Cannot make catalog table from srcdef");
+ ok= false;
+ } // endif src
+
+ // Here we should test the flag column options when
+ // this function is called in case of CREATE .. SELECT
+
if (ok) {
char *cnm, *rem;
- int i, len, dec, typ;
+ int i, len, dec, typ, flg;
const char *type;
PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL;
if (cat)
- cat->SetDataPath(g, thd->db);
+ cat->SetDataPath(g, table_s->db.str);
else
return HA_ERR_INTERNAL_ERROR; // Should never happen
- switch (ttp) {
+ if (src && ttp != TAB_PIVOT) {
+ qrp= SrcColumns(g, host, db, user, pwd, src, port);
+
+ if (qrp && ttp == TAB_OCCUR)
+ if (OcrSrcCols(g, qrp, col, ocl, rnk)) {
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ return HA_ERR_INTERNAL_ERROR;
+ } // endif OcrSrcCols
+
+ } else switch (ttp) {
case TAB_DBF:
qrp= DBFColumns(g, fn, fnc == FNC_COL);
break;
@@ -3494,7 +3638,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
#if defined(MYSQL_SUPPORT)
case TAB_MYSQL:
qrp= MyColumns(g, host, db, user, pwd, tab,
- NULL, port, false, fnc == FNC_COL);
+ NULL, port, fnc == FNC_COL);
break;
#endif // MYSQL_SUPPORT
case TAB_CSV:
@@ -3505,6 +3649,26 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
qrp= WMIColumns(g, nsp, cls, fnc == FNC_COL);
break;
#endif // WIN32
+ case TAB_PRX:
+ case TAB_TBL:
+ case TAB_XCL:
+ case TAB_OCCUR:
+ bif= fnc == FNC_COL;
+ qrp= TabColumns(g, thd, db, tab, bif);
+
+ if (!qrp && bif && fnc != FNC_COL) // tab is a view
+ qrp= MyColumns(g, host, db, user, pwd, tab, NULL, port, false);
+
+ if (qrp && ttp == TAB_OCCUR && fnc != FNC_COL)
+ if (OcrColumns(g, qrp, col, ocl, rnk)) {
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ return HA_ERR_INTERNAL_ERROR;
+ } // endif OcrColumns
+
+ break;
+ case TAB_PIVOT:
+ qrp= PivotColumns(g, tab, src, pic, fcl, host, db, user, pwd, port);
+ break;
default:
strcpy(g->Message, "System error during assisted discovery");
break;
@@ -3515,15 +3679,17 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
return HA_ERR_INTERNAL_ERROR;
} // endif qrp
- if (fnc != FNC_NO) {
- // Catalog table
+ if (fnc != FNC_NO || src || ttp == TAB_PIVOT) {
+ // Catalog like table
for (crp=qrp->Colresp; !b && crp; crp= crp->Next) {
cnm= encode(g, crp->Name);
type= PLGtoMYSQLtype(crp->Type, dbf);
len= crp->Length;
+ dec= crp->Prec;
+ flg= crp->Flag;
// Now add the field
- if (add_field(&sql, cnm, type, len, 0, NOT_NULL_FLAG, 0))
+ if (add_field(&sql, cnm, type, len, dec, NOT_NULL_FLAG, 0, flg))
b= HA_ERR_OUT_OF_MEM;
} // endfor crp
@@ -3532,7 +3698,6 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
rem= NULL;
typ= len= dec= 0;
tm= NOT_NULL_FLAG;
- cs= NULL;
for (crp= qrp->Colresp; crp; crp= crp->Next)
switch (crp->Fld) {
@@ -3587,11 +3752,16 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endif ttp
#endif // ODBC_SUPPORT
+ // Make the arguments as required by add_fields
type= PLGtoMYSQLtype(typ, true);
+
if (typ == TYPE_DATE)
len= 0;
- if (add_field(&sql, cnm, type, len, dec, tm, rem))
+
+ // Now add the field
+ if (add_field(&sql, cnm, type, len, dec, tm, rem, 0))
b= HA_ERR_OUT_OF_MEM;
+
} // endfor i
sql.length(sql.length()-1); // remove the trailing comma
@@ -3602,59 +3772,79 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ulonglong vull;
const char *vstr;
bool oom= false;
+
switch (opt->type) {
case HA_OPTION_TYPE_ULL:
- vull= *(ulonglong*)(((char*)topt) + opt->offset);
+ vull= *(ulonglong*)(((char*)topt) + opt->offset);
+
if (vull != opt->def_value) {
oom|= sql.append(' ');
oom|= sql.append(opt->name);
oom|= sql.append('=');
oom|= sql.append_ulonglong(vull);
- }
+ } // endif vull
+
break;
case HA_OPTION_TYPE_STRING:
- vstr= *(char**)(((char*)topt) + opt->offset);
+ vstr= *(char**)(((char*)topt) + opt->offset);
+
if (vstr) {
oom|= sql.append(' ');
oom|= sql.append(opt->name);
oom|= sql.append("='");
oom|= sql.append_for_single_quote(vstr, strlen(vstr));
oom|= sql.append('\'');
- }
+ } // endif vstr
+
break;
case HA_OPTION_TYPE_BOOL:
- vull= *(bool*)(((char*)topt) + opt->offset);
+ vull= *(bool*)(((char*)topt) + opt->offset);
+
if (vull != opt->def_value) {
oom|= sql.append(' ');
oom|= sql.append(opt->name);
oom|= sql.append('=');
oom|= sql.append(vull ? "ON" : "OFF");
- }
+ } // endif vull
+
break;
default: // no enums here, good :)
break;
- }
+ } // endswitch type
+
if (oom)
b= HA_ERR_OUT_OF_MEM;
- }
+
+ } // endfor opt
if (create_info->connect_string.length) {
bool oom= false;
+
oom|= sql.append(' ');
oom|= sql.append("CONNECTION='");
oom|= sql.append_for_single_quote(create_info->connect_string.str,
create_info->connect_string.length);
oom|= sql.append('\'');
+
if (oom)
b= HA_ERR_OUT_OF_MEM;
- }
+
+ } // endif string
if (create_info->default_table_charset) {
bool oom= false;
+
oom|= sql.append(' ');
oom|= sql.append("CHARSET=");
oom|= sql.append(create_info->default_table_charset->csname);
- }
+
+ if (oom)
+ b= HA_ERR_OUT_OF_MEM;
+
+ } // endif charset
+
+ if (xtrace)
+ printf("s_init: %.*s\n", sql.length(), sql.ptr());
if (!b)
b= table_s->init_from_sql_statement_string(thd, true,
@@ -3664,7 +3854,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return HA_ERR_INTERNAL_ERROR;
-} // end of pre_create
+} // end of connect_assisted_discovery
/**
@brief
@@ -3700,7 +3890,8 @@ int ha_connect::create(const char *name, TABLE *table_arg,
Field *fp;
TABTYPE type;
TABLE *st= table; // Probably unuseful
- xp= GetUser(ha_thd(), xp);
+ THD *thd= ha_thd();
+ xp= GetUser(thd, xp);
PGLOBAL g= xp->g;
DBUG_ENTER("ha_connect::create");
@@ -3710,7 +3901,20 @@ int ha_connect::create(const char *name, TABLE *table_arg,
DBUG_ASSERT(options);
type= GetTypeID(options->type);
- if (check_privileges(ha_thd(), options))
+ // Check table type
+ if (type == TAB_UNDEF) {
+ options->type= (options->srcdef) ? "MYSQL" :
+ (options->tabname) ? "PROXY" : "DOS";
+ type= GetTypeID(options->type);
+ sprintf(g->Message, "No table_type. Will be set to %s", options->type);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message);
+ } else if (type == TAB_NIY) {
+ sprintf(g->Message, "Unsupported table type %s", options->type);
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+ } // endif ttp
+
+ if (check_privileges(thd, options))
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
if (options->data_charset) {
@@ -3737,6 +3941,34 @@ int ha_connect::create(const char *name, TABLE *table_arg,
} else
dbf= (GetTypeID(options->type) == TAB_DBF && !options->catfunc);
+ // Can be null in ALTER TABLE
+ if (create_info->alias)
+ // Check whether a table is defined on itself
+ switch (type) {
+ case TAB_PRX:
+ case TAB_XCL:
+ case TAB_OCCUR:
+ if (options->srcdef) {
+ strcpy(g->Message, "Cannot check looping reference");
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message);
+ } else if (options->tabname) {
+ if (!stricmp(options->tabname, create_info->alias) &&
+ (!options->dbname || !stricmp(options->dbname, table_arg->s->db.str))) {
+ sprintf(g->Message, "A %s table cannot refer to itself",
+ options->type);
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+ } // endif tab
+
+ } else {
+ strcpy(g->Message, "Missing object table name or definition");
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+ } // endif tabname
+
+ default: /* do nothing */;
+ } // endswitch ttp
+
if (type == TAB_XML) {
bool dom; // True: MS-DOM, False libxml2
char *xsup= GetListOption(g, "Xmlsup", options->oplist, "*");
@@ -3906,8 +4138,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
strcat(strcat(buf, "."), lwt);
sprintf(g->Message, "No file name. Table will use %s", buf);
- push_warning(table->in_use,
- MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message);
strcat(strcat(strcpy(dbpath, "./"), table->s->db.str), "/");
PlugSetPath(fn, buf, dbpath);
@@ -3935,8 +4166,8 @@ int ha_connect::create(const char *name, TABLE *table_arg,
PIXDEF xdp;
// We should be in CREATE TABLE
- if (table->in_use->lex->sql_command != SQLCOM_CREATE_TABLE)
- push_warning(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ if (thd_sql_command(table->in_use) != SQLCOM_CREATE_TABLE)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
"Wrong command in create, please contact CONNECT team");
// Get the index definitions
@@ -3945,7 +4176,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
PCATLG cat= (dup) ? dup->Catalog : NULL;
if (cat) {
- cat->SetDataPath(g, table_arg->in_use->db);
+ cat->SetDataPath(g, table_arg->s->db.str);
if ((rc= optimize(table->in_use, NULL))) {
printf("Create rc=%d %s\n", rc, g->Message);
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index b8c92479543..0d6354ca078 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2011
+/* Copyright (C) Olivier Bertrand 2004 - 2013
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
@@ -64,6 +64,61 @@ typedef struct ha_field_option_struct FOS, *PFOS;
extern handlerton *connect_hton;
+/**
+ 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;
+ };
+
+/**
+ structure for CREATE TABLE options (field options)
+
+ These can be specified in the CREATE TABLE per field:
+ CREATE TABLE ( field ... {...here...}, ... )
+*/
+struct ha_field_option_struct
+{
+ ulonglong offset;
+ ulonglong freq; // Not used by this version
+ ulonglong opt; // Not used by this version
+ ulonglong fldlen;
+ const char *dateformat;
+ const char *fieldformat;
+ char *special;
+};
+
/** @brief
CONNECT_SHARE is a structure that will be shared among all open handlers.
This example implements the minimum of what you will probably need.
@@ -143,8 +198,7 @@ public:
{
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_HAS_RECORDS |
HA_NO_AUTO_INCREMENT | HA_NO_PREFIX_CHAR_KEYS |
- HA_NO_COPY_ON_ALTER |
- HA_CAN_VIRTUAL_COLUMNS |
+ HA_NO_COPY_ON_ALTER | HA_CAN_VIRTUAL_COLUMNS |
HA_NULL_IN_KEY | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE);
}
diff --git a/storage/connect/inihandl.c b/storage/connect/inihandl.c
index 25629b04e60..60b72bd2604 100644
--- a/storage/connect/inihandl.c
+++ b/storage/connect/inihandl.c
@@ -29,9 +29,8 @@
//#include <sys/types.h>
//#include <memory.h>
#include "my_global.h"
-//#include "osutil.h"
#include "global.h"
-
+#include "inihandl.h"
// The types and variables used locally
//typedef int bool;
@@ -672,7 +671,7 @@ static BOOL PROFILE_DeleteKey(PROFILESECTION* *section,
*
* Delete all keys from a profile tree.
***********************************************************************/
-void PROFILE_DeleteAllKeys(LPCSTR section_name)
+static void PROFILE_DeleteAllKeys(LPCSTR section_name)
{
PROFILESECTION* *section= &CurProfile->section;
@@ -1038,6 +1037,7 @@ static BOOL PROFILE_SetString(LPCSTR section_name, LPCSTR key_name,
* Convenience function that turns a string 'xxx, yyy, zzz' into
* the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
***********************************************************************/
+#if 0
char *PROFILE_GetStringItem(char* start)
{
char *lpchX, *lpch;
@@ -1065,6 +1065,7 @@ char *PROFILE_GetStringItem(char* start)
return NULL;
} // end of PROFILE_GetStringItem
+#endif
/**********************************************************************
* if allow_section_name_copy is TRUE, allow the copying :
@@ -1132,7 +1133,7 @@ static int PROFILE_GetPrivateProfileString(LPCSTR section, LPCSTR entry,
* GetPrivateProfileStringA (KERNEL32.@)
***********************************************************************/
int GetPrivateProfileString(LPCSTR section, LPCSTR entry, LPCSTR def_val,
- LPSTR buffer, uint len, LPCSTR filename)
+ LPSTR buffer, DWORD len, LPCSTR filename)
{
return PROFILE_GetPrivateProfileString(section, entry, def_val,
buffer, len, filename, TRUE);
@@ -1308,7 +1309,8 @@ BOOL WritePrivateProfileSection(LPCSTR section,
* Note that when the buffer is big enough then the return value may be any
* value between 1 and len-1 (or len in Win95), including len-2.
*/
-DWORD GetPrivateProfileSectionNames(LPSTR buffer, DWORD size, LPCSTR filename)
+static DWORD
+GetPrivateProfileSectionNames(LPSTR buffer, DWORD size, LPCSTR filename)
{
DWORD ret = 0;
diff --git a/storage/connect/inihandl.h b/storage/connect/inihandl.h
new file mode 100644
index 00000000000..7f6fcb1f582
--- /dev/null
+++ b/storage/connect/inihandl.h
@@ -0,0 +1,54 @@
+#ifndef __INIHANDL_H__
+#define __INIHANDL_H__
+
+#if defined(UNIX) || defined(UNIV_LINUX)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void PROFILE_Close(LPCSTR filename);
+
+int GetPrivateProfileString(
+ LPCTSTR lpAppName, // section name
+ LPCTSTR lpKeyName, // key name
+ LPCTSTR lpDefault, // default string
+ LPTSTR lpReturnedString, // destination buffer
+ DWORD nSize, // size of destination buffer
+ LPCTSTR lpFileName // initialization file name
+ );
+
+uint GetPrivateProfileInt(
+ LPCTSTR lpAppName, // section name
+ LPCTSTR lpKeyName, // key name
+ INT nDefault, // return value if key name not found
+ LPCTSTR lpFileName // initialization file name
+ );
+
+BOOL WritePrivateProfileString(
+ LPCTSTR lpAppName, // section name
+ LPCTSTR lpKeyName, // key name
+ LPCTSTR lpString, // string to add
+ LPCTSTR lpFileName // initialization file
+ );
+
+int GetPrivateProfileSection(
+ LPCTSTR lpAppName, // section name
+ LPTSTR lpReturnedString, // return buffer
+ DWORD nSize, // size of return buffer
+ LPCTSTR lpFileName // initialization file name
+ );
+
+BOOL WritePrivateProfileSection(
+ LPCTSTR lpAppName, // section name
+ LPCTSTR lpString, // data
+ LPCTSTR lpFileName // file name
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* defined(UNIX) */
+
+#endif /* __INIHANDL_H__ */
diff --git a/storage/connect/maputil.h b/storage/connect/maputil.h
index 8ab41487a63..b5e54affcea 100644
--- a/storage/connect/maputil.h
+++ b/storage/connect/maputil.h
@@ -13,7 +13,6 @@ typedef struct {
HANDLE CreateFileMap(PGLOBAL, LPCSTR, MEMMAP *, MODE, bool);
bool CloseMemMap(void *memory, size_t dwSize);
-my_bool CloseFileHandle(HANDLE h);
#ifdef __cplusplus
}
diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc
index 4db70efe27f..e243a706f01 100644
--- a/storage/connect/mycat.cc
+++ b/storage/connect/mycat.cc
@@ -68,7 +68,10 @@
#include "tabmac.h"
#include "tabwmi.h"
#endif // WIN32
+//#include "tabtbl.h"
+#include "tabxcl.h"
#include "tabtbl.h"
+#include "taboccur.h"
#if defined(XML_SUPPORT)
#include "tabxml.h"
#endif // XML_SUPPORT
@@ -117,6 +120,7 @@ TABTYPE GetTypeID(const char *type)
#endif
#ifdef MYSQL_SUPPORT
: (!stricmp(type, "MYSQL")) ? TAB_MYSQL
+ : (!stricmp(type, "MYPRX")) ? TAB_MYSQL
#endif
: (!stricmp(type, "DIR")) ? TAB_DIR
#ifdef WIN32
@@ -124,6 +128,13 @@ TABTYPE GetTypeID(const char *type)
: (!stricmp(type, "WMI")) ? TAB_WMI
#endif
: (!stricmp(type, "TBL")) ? TAB_TBL
+ : (!stricmp(type, "XCOL")) ? TAB_XCL
+ : (!stricmp(type, "OCCUR")) ? TAB_OCCUR
+ : (!stricmp(type, "CATLG")) ? TAB_PRX // Legacy
+ : (!stricmp(type, "PROXY")) ? TAB_PRX
+#ifdef PIVOT_SUPPORT
+ : (!stricmp(type, "PIVOT")) ? TAB_PIVOT
+#endif
: (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY;
} // end of GetTypeID
@@ -186,7 +197,6 @@ bool IsTypeNullable(TABTYPE type)
break;
} // endswitch type
-
return nullable;
} // end of IsTypeNullable
@@ -246,15 +256,11 @@ uint GetFuncID(const char *func)
/***********************************************************************/
CATALOG::CATALOG(void)
{
- To_Desc= NULL;
-//*DescFile= '\0';
#if defined(WIN32)
DataPath= ".\\";
#else // !WIN32
DataPath= "./";
#endif // !WIN32
- Descp= NULL;
-//memset(&DescArea, 0, sizeof(AREADEF));
memset(&Ctb, 0, sizeof(CURTAB));
Cbuf= NULL;
Cblen= 0;
@@ -269,17 +275,14 @@ CATALOG::CATALOG(void)
MYCAT::MYCAT(PHC hc) : CATALOG()
{
Hc= hc;
- To_Desc= NULL;
DefHuge= false;
-//SepIndex= true; // Temporay until we can store offet and size
} // end of MYCAT constructor
/***********************************************************************/
-/* When using volatile storage, reset values pointing to Sarea. */
+/* Nothing to do for CONNECT. */
/***********************************************************************/
void MYCAT::Reset(void)
{
- To_Desc= NULL;
} // end of Reset
/***********************************************************************/
@@ -290,6 +293,13 @@ void MYCAT::SetPath(PGLOBAL g, LPCSTR *datapath, const char *path)
if (path) {
size_t len= strlen(path) + (*path != '.' ? 4 : 1);
char *buf= (char*)PlugSubAlloc(g, NULL, len);
+
+ if (PlugIsAbsolutePath(path))
+ {
+ strcpy(buf, path);
+ *datapath= buf;
+ return;
+ }
if (*path != '.') {
#if defined(WIN32)
@@ -380,20 +390,23 @@ char *MYCAT::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef)
strcpy(sval, s);
} else if (!stricmp(what, "filename")) {
// Return default file name
- char *ftype= Hc->GetStringOption("Type", "dos");
+ char *ftype= Hc->GetStringOption("Type", "*");
int i, n;
- sval= (char*)PlugSubAlloc(g, NULL, strlen(Hc->GetTableName()) + 12);
- strcat(strcpy(sval, Hc->GetTableName()), ".");
- n= strlen(sval);
-
- // Fold ftype to lower case
- for (i= 0; i < 12; i++)
- if (!ftype[i]) {
- sval[n+i]= 0;
- break;
- } else
- sval[n+i]= tolower(ftype[i]);
+ if (IsFileType(GetTypeID(ftype))) {
+ sval= (char*)PlugSubAlloc(g, NULL, strlen(Hc->GetTableName()) + 12);
+ strcat(strcpy(sval, Hc->GetTableName()), ".");
+ n= strlen(sval);
+
+ // Fold ftype to lower case
+ for (i= 0; i < 12; i++)
+ if (!ftype[i]) {
+ sval[n+i]= 0;
+ break;
+ } else
+ sval[n+i]= tolower(ftype[i]);
+
+ } // endif FileType
} else
sval = NULL;
@@ -406,7 +419,7 @@ char *MYCAT::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef)
/***********************************************************************/
int MYCAT::GetColCatInfo(PGLOBAL g, PTABDEF defp)
{
- char *type= GetStringCatInfo(g, "Type", "DOS");
+ char *type= GetStringCatInfo(g, "Type", "*");
int i, loff, poff, nof, nlg;
void *field= NULL;
TABTYPE tc;
@@ -414,7 +427,7 @@ int MYCAT::GetColCatInfo(PGLOBAL g, PTABDEF defp)
PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO));
// Get a unique char identifier for type
- tc= (defp->Catfunc == FNC_NO) ? GetTypeID(type) : TAB_CATLG;
+ tc= (defp->Catfunc == FNC_NO) ? GetTypeID(type) : TAB_PRX;
// Take care of the column definitions
i= poff= nof= nlg= 0;
@@ -443,6 +456,9 @@ int MYCAT::GetColCatInfo(PGLOBAL g, PTABDEF defp)
case TAB_INI:
case TAB_MAC:
case TAB_TBL:
+ case TAB_XCL:
+ case TAB_OCCUR:
+ case TAB_PRX:
case TAB_OEM:
poff = 0; // Offset represents an independant flag
break;
@@ -576,9 +592,7 @@ bool MYCAT::GetIndexInfo(PGLOBAL g, PTABDEF defp)
/***********************************************************************/
/* GetTableDesc: retrieve a table descriptor. */
-/* Look for a table descriptor matching the name and type. If found */
-/* in storage, return a pointer to it, else look in the XDB file. If */
-/* found, make and add the descriptor and return a pointer to it. */
+/* Look for a table descriptor matching the name and type. */
/***********************************************************************/
PRELDEF MYCAT::GetTableDesc(PGLOBAL g, LPCSTR name,
LPCSTR type, PRELDEF *prp)
@@ -586,13 +600,9 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, LPCSTR name,
if (xtrace)
printf("GetTableDesc: name=%s am=%s\n", name, SVP(type));
- // Firstly check whether this table descriptor is in memory
- if (To_Desc)
- return To_Desc;
-
// If not specified get the type of this table
- if (!type && !(type= Hc->GetStringOption("Type")))
- type= "DOS";
+ if (!type)
+ type= Hc->GetStringOption("Type","*");
return MakeTableDesc(g, name, type);
} // end of GetTableDesc
@@ -636,17 +646,20 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am)
#endif // WIN32
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
+#if defined(PIVOT_SUPPORT)
+ case TAB_PIVOT: tdp= new(g) PIVOTDEF; break;
+#endif // PIVOT_SUPPORT
default:
sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name);
} // endswitch
- // Do make the table/view definition from XDB file information
+ // Do make the table/view definition
if (tdp && tdp->Define(g, this, name, am))
tdp= NULL;
@@ -694,7 +707,6 @@ PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type)
/***********************************************************************/
void MYCAT::ClearDB(PGLOBAL g)
{
- To_Desc= NULL;
} // end of ClearDB
/* ------------------------ End of MYCAT --------------------------- */
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index 3edf07004ea..9ebf77ff35a 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -62,21 +62,25 @@ static char *server_groups[] = {
#endif // EMBEDDED
extern "C" int trace;
+extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
+
+// Returns the current used port
+uint GetDefaultPort(void)
+{
+ return mysqld_port;
+} // end of GetDefaultPort
/************************************************************************/
/* MyColumns: constructs the result blocks containing all columns */
-/* of a MySQL table that will be retrieved by GetData commands. */
-/* key = TRUE when called from Create Table to get key informations. */
+/* of a MySQL table or view. */
+/* info = TRUE to get catalog column informations. */
/************************************************************************/
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
const char *user, const char *pwd,
const char *table, const char *colpat,
- int port, bool key, bool info)
+ int port, bool info)
{
- static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, DB_INT,
- DB_CHAR, DB_SHORT, DB_SHORT, DB_SHORT,
- DB_CHAR, DB_CHAR, DB_CHAR};
- static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
+ static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT,
TYPE_STRING, TYPE_STRING, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
@@ -84,12 +88,15 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
FLD_REM, FLD_NO, FLD_CHARSET};
static unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 256, 32, 32};
char *fld, *fmt, cmd[128];
- int i, n, nf, ncol = sizeof(dbtype) / sizeof(int);
+ int i, n, nf, ncol = sizeof(buftyp) / sizeof(int);
int len, type, prec, rc, k = 0;
PQRYRES qrp;
PCOLRES crp;
MYSQLC myc;
+ if (!port)
+ port = mysqld_port;
+
if (!info) {
/********************************************************************/
/* Open the connection with the MySQL server. */
@@ -123,14 +130,11 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
length[0] = 128;
} // endif info
-//if (!key) // We are not called from Create table
-// ncol--; // No date format column yet
-
/**********************************************************************/
/* Allocate the structures used to refer to the result set. */
/**********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
- dbtype, buftyp, fldtyp, length, true, true);
+ buftyp, fldtyp, length, true, true);
// Some columns must be renamed
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
@@ -218,6 +222,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
crp->Kdata->SetValue(fld, i);
} // endfor i
+#if 0
if (k > 1) {
// Multicolumn primary key
PVBLK vbp = qrp->Colresp->Next->Next->Next->Next->Kdata;
@@ -227,6 +232,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
vbp->SetValue(k, i);
} // endif k
+#endif // 0
/**********************************************************************/
/* Close MySQL connection. */
@@ -239,6 +245,33 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
return qrp;
} // end of MyColumns
+/************************************************************************/
+/* SrcColumns: constructs the result blocks containing all columns */
+/* resulting from an SQL source definition query execution. */
+/************************************************************************/
+PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
+ const char *user, const char *pwd,
+ const char *srcdef, int port)
+ {
+ int w;
+ MYSQLC myc;
+ PQRYRES qrp = NULL;
+
+ if (!port)
+ port = mysqld_port;
+
+ // Open a MySQL connection for this table
+ if (myc.Open(g, host, db, user, pwd, port))
+ return NULL;
+
+ // Send the source command to MySQL
+ if (myc.ExecSQL(g, srcdef, &w) == RC_OK)
+ qrp = myc.GetResult(g);
+
+ myc.Close();
+ return qrp;
+ } // end of SrcColumns
+
/* -------------------------- Class MYSQLC --------------------------- */
/***********************************************************************/
@@ -289,6 +322,7 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db,
// This is critical, because the server will not accept the
// client's options, and vice versa.
mysql_options(m_DB, MYSQL_READ_DEFAULT_GROUP, "PlugDB_CLIENT");
+ mysql_options(m_DB, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL);
#if 0
if (pwd && !strcmp(pwd, "*")) {
@@ -645,6 +679,7 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
*pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
crp = *pcrp;
pcrp = &crp->Next;
+ memset(crp, 0, sizeof(COLRES));
crp->Ncol = ++qrp->Nbcol;
crp->Name = (char*)PlugSubAlloc(g, NULL, fld->name_length + 1);
@@ -658,10 +693,9 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
// For direct MySQL connection, display the MySQL date string
crp->Type = TYPE_STRING;
- crp->Prec = fld->decimals;
+ crp->Prec = (crp->Type == TYPE_FLOAT) ? fld->decimals : 0;
crp->Length = fld->max_length;
crp->Clen = GetTypeSize(crp->Type, crp->Length);
- crp->DBtype = GetDBType((int)crp->Type);
if (!(crp->Kdata = AllocValBlock(g, NULL, crp->Type, m_Rows,
crp->Clen, 0, FALSE, TRUE))) {
diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h
index 72ce58e70aa..f8c8c3dcbae 100644
--- a/storage/connect/myconn.h
+++ b/storage/connect/myconn.h
@@ -38,7 +38,13 @@ typedef class MYSQLC *PMYC;
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
const char *user, const char *pwd,
const char *table, const char *colpat,
- int port, bool key, bool info);
+ int port, bool info);
+
+PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
+ const char *user, const char *pwd,
+ const char *srcdef, int port);
+
+uint GetDefaultPort(void);
/* -------------------------- MYCONN class --------------------------- */
@@ -47,6 +53,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
/***********************************************************************/
class DllItem MYSQLC {
friend class TDBMYSQL;
+ friend class MYSQLCOL;
// Construction
public:
MYSQLC(void);
diff --git a/storage/connect/mysql-test/connect/r/bin.result b/storage/connect/mysql-test/connect/r/bin.result
index d476aef6293..c64b270b538 100644
--- a/storage/connect/mysql-test/connect/r/bin.result
+++ b/storage/connect/mysql-test/connect/r/bin.result
@@ -1,98 +1,4 @@
#
-# Beginning of grant.inc
-#
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
-SELECT user();
-user()
-user@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN;
-Warnings:
-Warning 1105 No file name. Table will use t1.bin
-INSERT INTO t1 VALUES (10);
-SELECT * FROM t1;
-a
-10
-UPDATE t1 SET a=20;
-SELECT * FROM t1;
-a
-20
-DELETE FROM t1;
-SELECT * FROM t1;
-a
-INSERT INTO t1 VALUES(10);
-TRUNCATE TABLE t1;
-SELECT * FROM t1;
-a
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT * FROM v1;
-a
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN FILE_NAME='t1.EXT';
-INSERT INTO t1 VALUES (10);
-SELECT user();
-user()
-user@localhost
-INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-# Testing a VIEW created with FILE privileges but accessed with no FILE
-SELECT user();
-user()
-root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT user();
-user()
-user@localhost
-SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN;
-Warnings:
-Warning 1105 No file name. Table will use t1.bin
-INSERT INTO t1 VALUES (10);
-SELECT user();
-user()
-user@localhost
-ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-DROP USER user@localhost;
-#
-# End of grant.inc
-#
-#
# Testing errors
#
CREATE TABLE t1
diff --git a/storage/connect/mysql-test/connect/r/csv.result b/storage/connect/mysql-test/connect/r/csv.result
index 34734e164c0..b2498326edb 100644
--- a/storage/connect/mysql-test/connect/r/csv.result
+++ b/storage/connect/mysql-test/connect/r/csv.result
@@ -1,97 +1,3 @@
-#
-# Beginning of grant.inc
-#
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
-SELECT user();
-user()
-user@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV;
-Warnings:
-Warning 1105 No file name. Table will use t1.csv
-INSERT INTO t1 VALUES (10);
-SELECT * FROM t1;
-a
-10
-UPDATE t1 SET a=20;
-SELECT * FROM t1;
-a
-20
-DELETE FROM t1;
-SELECT * FROM t1;
-a
-INSERT INTO t1 VALUES(10);
-TRUNCATE TABLE t1;
-SELECT * FROM t1;
-a
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT * FROM v1;
-a
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='t1.EXT';
-INSERT INTO t1 VALUES (10);
-SELECT user();
-user()
-user@localhost
-INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-# Testing a VIEW created with FILE privileges but accessed with no FILE
-SELECT user();
-user()
-root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT user();
-user()
-user@localhost
-SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV;
-Warnings:
-Warning 1105 No file name. Table will use t1.csv
-INSERT INTO t1 VALUES (10);
-SELECT user();
-user()
-user@localhost
-ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-DROP USER user@localhost;
-#
-# End of grant.inc
-#
SET NAMES utf8;
#
# Testing errors
diff --git a/storage/connect/mysql-test/connect/r/dbf.result b/storage/connect/mysql-test/connect/r/dbf.result
index 27abbb84dc6..2e84c5b3090 100644
--- a/storage/connect/mysql-test/connect/r/dbf.result
+++ b/storage/connect/mysql-test/connect/r/dbf.result
@@ -1,98 +1,4 @@
#
-# Beginning of grant.inc
-#
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
-SELECT user();
-user()
-user@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF;
-Warnings:
-Warning 1105 No file name. Table will use t1.dbf
-INSERT INTO t1 VALUES (10);
-SELECT * FROM t1;
-a
-10
-UPDATE t1 SET a=20;
-SELECT * FROM t1;
-a
-20
-DELETE FROM t1;
-SELECT * FROM t1;
-a
-INSERT INTO t1 VALUES(10);
-TRUNCATE TABLE t1;
-SELECT * FROM t1;
-a
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT * FROM v1;
-a
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1.EXT';
-INSERT INTO t1 VALUES (10);
-SELECT user();
-user()
-user@localhost
-INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-# Testing a VIEW created with FILE privileges but accessed with no FILE
-SELECT user();
-user()
-root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT user();
-user()
-user@localhost
-SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF;
-Warnings:
-Warning 1105 No file name. Table will use t1.dbf
-INSERT INTO t1 VALUES (10);
-SELECT user();
-user()
-user@localhost
-ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-DROP USER user@localhost;
-#
-# End of grant.inc
-#
-#
# Testing errors
#
CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1.dbf';
diff --git a/storage/connect/mysql-test/connect/r/dir.result b/storage/connect/mysql-test/connect/r/dir.result
index 7beae815580..f4feb5fa960 100644
--- a/storage/connect/mysql-test/connect/r/dir.result
+++ b/storage/connect/mysql-test/connect/r/dir.result
@@ -1,72 +1,3 @@
-#
-# Testing FILE privilege
-#
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
-SELECT user();
-user()
-user@localhost
-CREATE TABLE t1 (
-path VARCHAR(256) NOT NULL flag=1,
-fname VARCHAR(256) NOT NULL,
-ftype CHAR(4) NOT NULL,
-size DOUBLE(12,0) NOT NULL flag=5
-) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-CREATE TABLE t1 (
-path VARCHAR(256) NOT NULL flag=1,
-fname VARCHAR(256) NOT NULL,
-ftype CHAR(4) NOT NULL,
-size DOUBLE(12,0) NOT NULL flag=5
-) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*';
-SELECT fname, ftype, size FROM t1 WHERE size>0;
-fname ftype size
-t1 .frm 1081
-SELECT user();
-user()
-user@localhost
-SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO t1 VALUES ();
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM t1 WHERE path='xxx';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE t1 SET path='yyy' WHERE path='xxx';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-# Testing a VIEW created with FILE privileges but accessed with no FILE
-SELECT user();
-user()
-root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT user();
-user()
-user@localhost
-SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO v1 VALUES (1,1,1,1);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE v1 SET path=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-DROP VIEW v1;
-DROP TABLE t1;
-DROP USER user@localhost;
-#
-# Testing FILE privileges done
-#
CREATE TABLE t1 (
path VARCHAR(256) NOT NULL flag=1,
fname VARCHAR(256) NOT NULL,
diff --git a/storage/connect/mysql-test/connect/r/fix.result b/storage/connect/mysql-test/connect/r/fix.result
index e9eb31d9bc8..c8f51abe961 100644
--- a/storage/connect/mysql-test/connect/r/fix.result
+++ b/storage/connect/mysql-test/connect/r/fix.result
@@ -1,98 +1,4 @@
#
-# Beginning of grant.inc
-#
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
-SELECT user();
-user()
-user@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX;
-Warnings:
-Warning 1105 No file name. Table will use t1.fix
-INSERT INTO t1 VALUES (10);
-SELECT * FROM t1;
-a
-10
-UPDATE t1 SET a=20;
-SELECT * FROM t1;
-a
-20
-DELETE FROM t1;
-SELECT * FROM t1;
-a
-INSERT INTO t1 VALUES(10);
-TRUNCATE TABLE t1;
-SELECT * FROM t1;
-a
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT * FROM v1;
-a
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='t1.EXT';
-INSERT INTO t1 VALUES (10);
-SELECT user();
-user()
-user@localhost
-INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-# Testing a VIEW created with FILE privileges but accessed with no FILE
-SELECT user();
-user()
-root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT user();
-user()
-user@localhost
-SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX;
-Warnings:
-Warning 1105 No file name. Table will use t1.fix
-INSERT INTO t1 VALUES (10);
-SELECT user();
-user()
-user@localhost
-ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-DROP USER user@localhost;
-#
-# End of grant.inc
-#
-#
# Testing errors
#
CREATE TABLE t1
diff --git a/storage/connect/mysql-test/connect/r/fmt.result b/storage/connect/mysql-test/connect/r/fmt.result
index dc3b42b2231..0be10f69bfd 100644
--- a/storage/connect/mysql-test/connect/r/fmt.result
+++ b/storage/connect/mysql-test/connect/r/fmt.result
@@ -18,7 +18,7 @@ CREATE TABLE t1
id INT NOT NULL field_format=' %n%d%n'
) ENGINE=CONNECT TABLE_TYPE=FMT FILE_NAME='t1.txt';
INSERT INTO t1 VALUES (10),(20);
-ERROR HY000: Got error 122 'Writing FMT files is not implemented yet' from CONNECT
+ERROR HY000: Got error 174 'Writing FMT files is not implemented yet' from CONNECT
DROP TABLE t1;
#
# Testing manual examples
@@ -59,7 +59,7 @@ ID NAME DEPNO SALARY
56 POIROT-DELMOTTE 0 18009.00
345 67 19000.25
UPDATE t1 SET SALARY=1234;
-ERROR HY000: Got error 122 'Writing FMT files is not implemented yet' from CONNECT
+ERROR HY000: Got error 174 'Writing FMT files is not implemented yet' from CONNECT
DELETE FROM t1 WHERE ID=56;
SELECT * FROM t1;
ID NAME DEPNO SALARY
diff --git a/storage/connect/mysql-test/connect/r/grant.result b/storage/connect/mysql-test/connect/r/grant.result
new file mode 100644
index 00000000000..ba5728703a5
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/grant.result
@@ -0,0 +1,539 @@
+#
+# Testing FILE privilege
+#
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+SELECT user();
+user()
+user@localhost
+CREATE TABLE t1 (
+path VARCHAR(256) NOT NULL flag=1,
+fname VARCHAR(256) NOT NULL,
+ftype CHAR(4) NOT NULL,
+size DOUBLE(12,0) NOT NULL flag=5
+) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+CREATE TABLE t1 (
+path VARCHAR(256) NOT NULL flag=1,
+fname VARCHAR(256) NOT NULL,
+ftype CHAR(4) NOT NULL,
+size DOUBLE(12,0) NOT NULL flag=5
+) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*';
+SELECT fname, ftype, size FROM t1 WHERE size>0;
+fname ftype size
+t1 .frm 1081
+SELECT user();
+user()
+user@localhost
+SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO t1 VALUES ();
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM t1 WHERE path='xxx';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1 SET path='yyy' WHERE path='xxx';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+TRUNCATE TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 READONLY=1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE VIEW v1 AS SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+# Testing a VIEW created with FILE privileges but accessed with no FILE
+SELECT user();
+user()
+root@localhost
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT user();
+user()
+user@localhost
+SELECT * FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1 VALUES (1,1,1,1);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1 SET path=123;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+DROP VIEW v1;
+DROP TABLE t1;
+DROP USER user@localhost;
+#
+# Testing FILE privileges done
+#
+#
+# Beginning of grant.inc
+#
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+SELECT user();
+user()
+user@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN;
+Warnings:
+Warning 1105 No file name. Table will use t1.bin
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+a
+10
+UPDATE t1 SET a=20;
+SELECT * FROM t1;
+a
+20
+DELETE FROM t1;
+SELECT * FROM t1;
+a
+INSERT INTO t1 VALUES(10);
+TRUNCATE TABLE t1;
+SELECT * FROM t1;
+a
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT * FROM v1;
+a
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN FILE_NAME='t1.EXT';
+INSERT INTO t1 VALUES (10);
+SELECT user();
+user()
+user@localhost
+INSERT INTO t1 VALUES (10);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1 SET a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+TRUNCATE TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 READONLY=1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 FILE_NAME='t2.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE VIEW v1 AS SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+# Testing a VIEW created with FILE privileges but accessed with no FILE
+SELECT user();
+user()
+root@localhost
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT user();
+user()
+user@localhost
+SELECT * FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1 VALUES (2);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1 SET a=123;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN;
+Warnings:
+Warning 1105 No file name. Table will use t1.bin
+INSERT INTO t1 VALUES (10);
+SELECT user();
+user()
+user@localhost
+ALTER TABLE t1 FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+DROP USER user@localhost;
+#
+# End of grant.inc
+#
+#
+# Beginning of grant.inc
+#
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+SELECT user();
+user()
+user@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV;
+Warnings:
+Warning 1105 No file name. Table will use t1.csv
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+a
+10
+UPDATE t1 SET a=20;
+SELECT * FROM t1;
+a
+20
+DELETE FROM t1;
+SELECT * FROM t1;
+a
+INSERT INTO t1 VALUES(10);
+TRUNCATE TABLE t1;
+SELECT * FROM t1;
+a
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT * FROM v1;
+a
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='t1.EXT';
+INSERT INTO t1 VALUES (10);
+SELECT user();
+user()
+user@localhost
+INSERT INTO t1 VALUES (10);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1 SET a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+TRUNCATE TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 READONLY=1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 FILE_NAME='t2.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE VIEW v1 AS SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+# Testing a VIEW created with FILE privileges but accessed with no FILE
+SELECT user();
+user()
+root@localhost
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT user();
+user()
+user@localhost
+SELECT * FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1 VALUES (2);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1 SET a=123;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV;
+Warnings:
+Warning 1105 No file name. Table will use t1.csv
+INSERT INTO t1 VALUES (10);
+SELECT user();
+user()
+user@localhost
+ALTER TABLE t1 FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+DROP USER user@localhost;
+#
+# End of grant.inc
+#
+#
+# Beginning of grant.inc
+#
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+SELECT user();
+user()
+user@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF;
+Warnings:
+Warning 1105 No file name. Table will use t1.dbf
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+a
+10
+UPDATE t1 SET a=20;
+SELECT * FROM t1;
+a
+20
+DELETE FROM t1;
+SELECT * FROM t1;
+a
+INSERT INTO t1 VALUES(10);
+TRUNCATE TABLE t1;
+SELECT * FROM t1;
+a
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT * FROM v1;
+a
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1.EXT';
+INSERT INTO t1 VALUES (10);
+SELECT user();
+user()
+user@localhost
+INSERT INTO t1 VALUES (10);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1 SET a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+TRUNCATE TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 READONLY=1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 FILE_NAME='t2.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE VIEW v1 AS SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+# Testing a VIEW created with FILE privileges but accessed with no FILE
+SELECT user();
+user()
+root@localhost
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT user();
+user()
+user@localhost
+SELECT * FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1 VALUES (2);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1 SET a=123;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF;
+Warnings:
+Warning 1105 No file name. Table will use t1.dbf
+INSERT INTO t1 VALUES (10);
+SELECT user();
+user()
+user@localhost
+ALTER TABLE t1 FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+DROP USER user@localhost;
+#
+# End of grant.inc
+#
+#
+# Beginning of grant.inc
+#
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+SELECT user();
+user()
+user@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX;
+Warnings:
+Warning 1105 No file name. Table will use t1.fix
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+a
+10
+UPDATE t1 SET a=20;
+SELECT * FROM t1;
+a
+20
+DELETE FROM t1;
+SELECT * FROM t1;
+a
+INSERT INTO t1 VALUES(10);
+TRUNCATE TABLE t1;
+SELECT * FROM t1;
+a
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT * FROM v1;
+a
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='t1.EXT';
+INSERT INTO t1 VALUES (10);
+SELECT user();
+user()
+user@localhost
+INSERT INTO t1 VALUES (10);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1 SET a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+TRUNCATE TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 READONLY=1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 FILE_NAME='t2.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE VIEW v1 AS SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+# Testing a VIEW created with FILE privileges but accessed with no FILE
+SELECT user();
+user()
+root@localhost
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT user();
+user()
+user@localhost
+SELECT * FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1 VALUES (2);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1 SET a=123;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX;
+Warnings:
+Warning 1105 No file name. Table will use t1.fix
+INSERT INTO t1 VALUES (10);
+SELECT user();
+user()
+user@localhost
+ALTER TABLE t1 FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+DROP USER user@localhost;
+#
+# End of grant.inc
+#
+#
+# Beginning of grant.inc
+#
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+SELECT user();
+user()
+user@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100;
+Warnings:
+Warning 1105 No file name. Table will use t1.vec
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+a
+10
+UPDATE t1 SET a=20;
+SELECT * FROM t1;
+a
+20
+DELETE FROM t1;
+SELECT * FROM t1;
+a
+INSERT INTO t1 VALUES(10);
+TRUNCATE TABLE t1;
+SELECT * FROM t1;
+a
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT * FROM v1;
+a
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100 FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100 FILE_NAME='t1.EXT';
+INSERT INTO t1 VALUES (10);
+SELECT user();
+user()
+user@localhost
+INSERT INTO t1 VALUES (10);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1 SET a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+TRUNCATE TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 READONLY=1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 FILE_NAME='t2.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE VIEW v1 AS SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+# Testing a VIEW created with FILE privileges but accessed with no FILE
+SELECT user();
+user()
+root@localhost
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT user();
+user()
+user@localhost
+SELECT * FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1 VALUES (2);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1 SET a=123;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100;
+Warnings:
+Warning 1105 No file name. Table will use t1.vec
+INSERT INTO t1 VALUES (10);
+SELECT user();
+user()
+user@localhost
+ALTER TABLE t1 FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+DROP USER user@localhost;
+#
+# End of grant.inc
+#
diff --git a/storage/connect/mysql-test/connect/r/ini.result b/storage/connect/mysql-test/connect/r/ini.result
index da846d466ba..83ba98fbd84 100644
--- a/storage/connect/mysql-test/connect/r/ini.result
+++ b/storage/connect/mysql-test/connect/r/ini.result
@@ -1,83 +1,4 @@
#
-# Checking FILE privileges
-#
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
-SELECT user();
-user()
-user@localhost
-CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI;
-Warnings:
-Warning 1105 No file name. Table will use t1.ini
-INSERT INTO t1 VALUES ('sec1','val1');
-SELECT * FROM t1;
-sec val
-sec1 val1
-UPDATE t1 SET val='val11';
-SELECT * FROM t1;
-sec val
-sec1 val11
-DELETE FROM t1;
-SELECT * FROM t1;
-sec val
-INSERT INTO t1 VALUES('sec2','val2');
-TRUNCATE TABLE t1;
-SELECT * FROM t1;
-sec val
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT * FROM v1;
-sec val
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT';
-INSERT INTO t1 VALUES ('sec1','val1');
-SELECT user();
-user()
-user@localhost
-INSERT INTO t1 VALUES ('sec2','val2');
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE t1 SET val='val11';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-# Testing a VIEW created with FILE privileges but accessed with no FILE
-SELECT user();
-user()
-root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT user();
-user()
-user@localhost
-SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO v1 VALUES ('sec3','val3');
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE v1 SET val='val11';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP VIEW v1;
-DROP TABLE t1;
-DROP USER user@localhost;
-#
-# Checking FILE privileges: done
-#
-#
# Testing errors
#
CREATE TABLE t1
diff --git a/storage/connect/mysql-test/connect/r/ini_grant.result b/storage/connect/mysql-test/connect/r/ini_grant.result
new file mode 100644
index 00000000000..c3acf7c8dfc
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/ini_grant.result
@@ -0,0 +1,79 @@
+#
+# Checking FILE privileges
+#
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+SELECT user();
+user()
+user@localhost
+CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI;
+Warnings:
+Warning 1105 No file name. Table will use t1.ini
+INSERT INTO t1 VALUES ('sec1','val1');
+SELECT * FROM t1;
+sec val
+sec1 val1
+UPDATE t1 SET val='val11';
+SELECT * FROM t1;
+sec val
+sec1 val11
+DELETE FROM t1;
+SELECT * FROM t1;
+sec val
+INSERT INTO t1 VALUES('sec2','val2');
+TRUNCATE TABLE t1;
+SELECT * FROM t1;
+sec val
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT * FROM v1;
+sec val
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT';
+INSERT INTO t1 VALUES ('sec1','val1');
+SELECT user();
+user()
+user@localhost
+INSERT INTO t1 VALUES ('sec2','val2');
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1 SET val='val11';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+TRUNCATE TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 READONLY=1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE VIEW v1 AS SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+# Testing a VIEW created with FILE privileges but accessed with no FILE
+SELECT user();
+user()
+root@localhost
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT user();
+user()
+user@localhost
+SELECT * FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1 VALUES ('sec3','val3');
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1 SET val='val11';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP VIEW v1;
+DROP TABLE t1;
+DROP USER user@localhost;
+#
+# Checking FILE privileges: done
+#
diff --git a/storage/connect/mysql-test/connect/r/mysql.result b/storage/connect/mysql-test/connect/r/mysql.result
index a538c57c5ce..8d5507e121a 100644
--- a/storage/connect/mysql-test/connect/r/mysql.result
+++ b/storage/connect/mysql-test/connect/r/mysql.result
@@ -1,66 +1,3 @@
-#
-# Testing FILE privilege
-#
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
-SELECT user();
-user()
-user@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL OPTION_LIST='host=localhost,user=root1,port=PORT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-CREATE TABLE t1remote (a INT NOT NULL);
-INSERT INTO t1remote VALUES (10),(20),(30);
-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;
-a
-10
-20
-30
-SELECT user();
-user()
-user@localhost
-SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO t1 VALUES ('xxx');
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM t1 WHERE a='xxx';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE t1 SET a='yyy' WHERE a='xxx';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-# Testing a VIEW created with FILE privileges but accessed with no FILE
-SELECT user();
-user()
-root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT user();
-user()
-user@localhost
-SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-DROP VIEW v1;
-DROP TABLE t1, t1remote;
-DROP USER user@localhost;
-#
-# Testing FILE privileges done
-#
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;
diff --git a/storage/connect/mysql-test/connect/r/mysql_grant.result b/storage/connect/mysql-test/connect/r/mysql_grant.result
new file mode 100644
index 00000000000..f8d0ee6ad6f
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/mysql_grant.result
@@ -0,0 +1,63 @@
+#
+# Testing FILE privilege
+#
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+SELECT user();
+user()
+user@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL OPTION_LIST='host=localhost,user=root1,port=PORT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+CREATE TABLE t1remote (a INT NOT NULL);
+INSERT INTO t1remote VALUES (10),(20),(30);
+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;
+a
+10
+20
+30
+SELECT user();
+user()
+user@localhost
+SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO t1 VALUES ('xxx');
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM t1 WHERE a='xxx';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1 SET a='yyy' WHERE a='xxx';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+TRUNCATE TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 READONLY=1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE VIEW v1 AS SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+# Testing a VIEW created with FILE privileges but accessed with no FILE
+SELECT user();
+user()
+root@localhost
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT user();
+user()
+user@localhost
+SELECT * FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1 VALUES (2);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1 SET a=123;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+DROP VIEW v1;
+DROP TABLE t1, t1remote;
+DROP USER user@localhost;
+#
+# Testing FILE privileges done
+#
diff --git a/storage/connect/mysql-test/connect/r/occur.result b/storage/connect/mysql-test/connect/r/occur.result
new file mode 100644
index 00000000000..a497dfc9942
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/occur.result
@@ -0,0 +1,255 @@
+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;
+serialno name sex title manager department secretary salary
+74200 BANCROFT 2 SALESMAN 70012 0318 24888 9600.00
+02345 SMITH 1 ENGINEER 31416 2452 11111 9000.00
+78943 MERCHANT 1 SALESMAN 70012 0318 24888 8700.00
+07654 FUNNIGUY 1 ADMINISTRATOR 40567 0319 33333 8500.00
+45678 BUGHAPPY 1 PROGRAMMER 40567 0319 12345 8500.00
+34567 BIGHEAD 1 SCIENTIST 31416 2452 11111 8000.00
+77777 SHRINKY 2 ADMINISTRATOR 70012 0318 27845 7500.00
+74234 WALTER 1 ENGINEER 70012 0318 24888 7400.00
+56789 FODDERMAN 1 SALESMAN 40567 0319 12345 7000.00
+73452 TONGHO 1 ENGINEER 70012 0318 24888 6800.00
+22222 SHORTSIGHT 2 SECRETARY 87777 0021 NULL 5500.00
+55555 MESSIFUL 2 SECRETARY 40567 0319 12345 5000.50
+27845 HONEY 2 SECRETARY 70012 0318 24888 4900.00
+98765 GOOSEPEN 1 ADMINISTRATOR 07654 0319 33333 4700.00
+11111 CHERRY 2 SECRETARY 31416 2452 NULL 4500.00
+33333 MONAPENNY 2 SECRETARY 07654 0319 NULL 3800.00
+12345 KITTY 2 TYPIST 40567 0319 NULL 3000.45
+24888 PLUMHEAD 2 TYPIST 27845 0318 NULL 2800.00
+87777 STRONG 1 DIRECTOR NULL 0021 22222 23000.00
+76543 BULLOZER 1 SALESMAN 40567 0319 12345 14800.00
+70012 WERTHER 1 DIRECTOR 87777 0318 27845 14500.00
+40567 QUINN 1 DIRECTOR 87777 0319 55555 14000.00
+31416 ORELLY 1 ENGINEER 87777 2452 11111 13400.00
+36666 BIGHORN 1 SCIENTIST 31416 2452 11111 11000.00
+00137 BROWNY 1 ENGINEER 40567 0319 12345 10500.00
+73111 WHEELFOR 1 SALESMAN 70012 0318 24888 10030.00
+00023 MARTIN 1 ENGINEER 40567 0319 12345 10000.00
+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;
+name sex title department salary id_of id
+BANCROFT 2 SALESMAN 0318 9600.00 serialno 74200
+BANCROFT 2 SALESMAN 0318 9600.00 manager 70012
+BANCROFT 2 SALESMAN 0318 9600.00 secretary 24888
+SMITH 1 ENGINEER 2452 9000.00 serialno 02345
+SMITH 1 ENGINEER 2452 9000.00 manager 31416
+SMITH 1 ENGINEER 2452 9000.00 secretary 11111
+MERCHANT 1 SALESMAN 0318 8700.00 serialno 78943
+MERCHANT 1 SALESMAN 0318 8700.00 manager 70012
+MERCHANT 1 SALESMAN 0318 8700.00 secretary 24888
+FUNNIGUY 1 ADMINISTRATOR 0319 8500.00 serialno 07654
+FUNNIGUY 1 ADMINISTRATOR 0319 8500.00 manager 40567
+FUNNIGUY 1 ADMINISTRATOR 0319 8500.00 secretary 33333
+BUGHAPPY 1 PROGRAMMER 0319 8500.00 serialno 45678
+BUGHAPPY 1 PROGRAMMER 0319 8500.00 manager 40567
+BUGHAPPY 1 PROGRAMMER 0319 8500.00 secretary 12345
+BIGHEAD 1 SCIENTIST 2452 8000.00 serialno 34567
+BIGHEAD 1 SCIENTIST 2452 8000.00 manager 31416
+BIGHEAD 1 SCIENTIST 2452 8000.00 secretary 11111
+SHRINKY 2 ADMINISTRATOR 0318 7500.00 serialno 77777
+SHRINKY 2 ADMINISTRATOR 0318 7500.00 manager 70012
+SHRINKY 2 ADMINISTRATOR 0318 7500.00 secretary 27845
+WALTER 1 ENGINEER 0318 7400.00 serialno 74234
+WALTER 1 ENGINEER 0318 7400.00 manager 70012
+WALTER 1 ENGINEER 0318 7400.00 secretary 24888
+FODDERMAN 1 SALESMAN 0319 7000.00 serialno 56789
+FODDERMAN 1 SALESMAN 0319 7000.00 manager 40567
+FODDERMAN 1 SALESMAN 0319 7000.00 secretary 12345
+TONGHO 1 ENGINEER 0318 6800.00 serialno 73452
+TONGHO 1 ENGINEER 0318 6800.00 manager 70012
+TONGHO 1 ENGINEER 0318 6800.00 secretary 24888
+SHORTSIGHT 2 SECRETARY 0021 5500.00 serialno 22222
+SHORTSIGHT 2 SECRETARY 0021 5500.00 manager 87777
+MESSIFUL 2 SECRETARY 0319 5000.50 serialno 55555
+MESSIFUL 2 SECRETARY 0319 5000.50 manager 40567
+MESSIFUL 2 SECRETARY 0319 5000.50 secretary 12345
+HONEY 2 SECRETARY 0318 4900.00 serialno 27845
+HONEY 2 SECRETARY 0318 4900.00 manager 70012
+HONEY 2 SECRETARY 0318 4900.00 secretary 24888
+GOOSEPEN 1 ADMINISTRATOR 0319 4700.00 serialno 98765
+GOOSEPEN 1 ADMINISTRATOR 0319 4700.00 manager 07654
+GOOSEPEN 1 ADMINISTRATOR 0319 4700.00 secretary 33333
+CHERRY 2 SECRETARY 2452 4500.00 serialno 11111
+CHERRY 2 SECRETARY 2452 4500.00 manager 31416
+MONAPENNY 2 SECRETARY 0319 3800.00 serialno 33333
+MONAPENNY 2 SECRETARY 0319 3800.00 manager 07654
+KITTY 2 TYPIST 0319 3000.45 serialno 12345
+KITTY 2 TYPIST 0319 3000.45 manager 40567
+PLUMHEAD 2 TYPIST 0318 2800.00 serialno 24888
+PLUMHEAD 2 TYPIST 0318 2800.00 manager 27845
+STRONG 1 DIRECTOR 0021 23000.00 serialno 87777
+STRONG 1 DIRECTOR 0021 23000.00 secretary 22222
+BULLOZER 1 SALESMAN 0319 14800.00 serialno 76543
+BULLOZER 1 SALESMAN 0319 14800.00 manager 40567
+BULLOZER 1 SALESMAN 0319 14800.00 secretary 12345
+WERTHER 1 DIRECTOR 0318 14500.00 serialno 70012
+WERTHER 1 DIRECTOR 0318 14500.00 manager 87777
+WERTHER 1 DIRECTOR 0318 14500.00 secretary 27845
+QUINN 1 DIRECTOR 0319 14000.00 serialno 40567
+QUINN 1 DIRECTOR 0319 14000.00 manager 87777
+QUINN 1 DIRECTOR 0319 14000.00 secretary 55555
+ORELLY 1 ENGINEER 2452 13400.00 serialno 31416
+ORELLY 1 ENGINEER 2452 13400.00 manager 87777
+ORELLY 1 ENGINEER 2452 13400.00 secretary 11111
+BIGHORN 1 SCIENTIST 2452 11000.00 serialno 36666
+BIGHORN 1 SCIENTIST 2452 11000.00 manager 31416
+BIGHORN 1 SCIENTIST 2452 11000.00 secretary 11111
+BROWNY 1 ENGINEER 0319 10500.00 serialno 00137
+BROWNY 1 ENGINEER 0319 10500.00 manager 40567
+BROWNY 1 ENGINEER 0319 10500.00 secretary 12345
+WHEELFOR 1 SALESMAN 0318 10030.00 serialno 73111
+WHEELFOR 1 SALESMAN 0318 10030.00 manager 70012
+WHEELFOR 1 SALESMAN 0318 10030.00 secretary 24888
+MARTIN 1 ENGINEER 0319 10000.00 serialno 00023
+MARTIN 1 ENGINEER 0319 10000.00 manager 40567
+MARTIN 1 ENGINEER 0319 10000.00 secretary 12345
+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;
+name dog cat rabbit bird fish
+John 2 0 0 0 0
+Bill 0 1 0 0 0
+Mary 1 1 0 0 0
+Lisbeth 0 0 2 0 0
+Kevin 0 2 0 6 0
+Donald 1 0 0 0 3
+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;
+name race number
+John dog 2
+John cat 0
+John rabbit 0
+John bird 0
+John fish 0
+Bill dog 0
+Bill cat 1
+Bill rabbit 0
+Bill bird 0
+Bill fish 0
+Mary dog 1
+Mary cat 1
+Mary rabbit 0
+Mary bird 0
+Mary fish 0
+Lisbeth dog 0
+Lisbeth cat 0
+Lisbeth rabbit 2
+Lisbeth bird 0
+Lisbeth fish 0
+Kevin dog 0
+Kevin cat 2
+Kevin rabbit 0
+Kevin bird 6
+Kevin fish 0
+Donald dog 1
+Donald cat 0
+Donald rabbit 0
+Donald bird 0
+Donald fish 3
+SELECT name FROM xpet;
+name
+John
+Bill
+Mary
+Lisbeth
+Kevin
+Donald
+SELECT name FROM xpet WHERE race = 'cat' AND number = 0;
+name
+John
+Lisbeth
+Donald
+SELECT name, SUM(number) pets FROM xpet GROUP BY name;
+name pets
+Bill 1
+Donald 4
+John 2
+Kevin 8
+Lisbeth 2
+Mary 2
+ALTER TABLE xpet MODIFY number INT NOT NULL;
+SELECT * FROM xpet;
+name race number
+John dog 2
+Bill cat 1
+Mary dog 1
+Mary cat 1
+Lisbeth rabbit 2
+Kevin cat 2
+Kevin bird 6
+Donald dog 1
+Donald fish 3
+SELECT * FROM xpet WHERE number > 1;
+name race number
+John dog 2
+Lisbeth rabbit 2
+Kevin cat 2
+Kevin bird 6
+Donald fish 3
+SELECT DISTINCT name FROM xpet WHERE number > 1;
+name
+John
+Lisbeth
+Kevin
+Donald
+SELECT name FROM xpet;
+name
+John
+Bill
+Mary
+Lisbeth
+Kevin
+Donald
+SELECT name, race FROM xpet;
+name race
+John
+Bill
+Mary
+Lisbeth
+Kevin
+Donald
+SELECT name, count(*) FROM xpet GROUP BY name, LEAST(number,1);
+name count(*)
+Bill 1
+Donald 2
+John 1
+Kevin 2
+Lisbeth 1
+Mary 2
+SELECT name, number, count(*) FROM xpet GROUP BY name, number;
+name number count(*)
+Bill 1 1
+Donald 1 1
+Donald 3 1
+John 2 1
+Kevin 2 1
+Kevin 6 1
+Lisbeth 2 1
+Mary 1 2
+DROP TABLE xpet;
+DROP TABLE pets;
diff --git a/storage/connect/mysql-test/connect/r/odbc_sqlite3.result b/storage/connect/mysql-test/connect/r/odbc_sqlite3.result
index 87f7803166c..339dbb6a53d 100644
--- a/storage/connect/mysql-test/connect/r/odbc_sqlite3.result
+++ b/storage/connect/mysql-test/connect/r/odbc_sqlite3.result
@@ -4,20 +4,6 @@ t1 CREATE TABLE `t1` (
`Attributes` varchar(256) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers'
SET NAMES utf8;
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
-SELECT user();
-user()
-user@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;;
SHOW CREATE TABLE t1;
Table Create Table
@@ -31,42 +17,27 @@ test2
тест1
тест2
ÆÇÈÉË
-SELECT user();
-user()
-user@localhost
-SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO t1 VALUES ('xxx');
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM t1 WHERE a='xxx';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE t1 SET a='yyy' WHERE a='xxx';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-# Testing a VIEW created with FILE privileges but accessed with no FILE
-SELECT user();
-user()
-root@localhost
+CREATE TABLE t2 AS SELECT * FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` varchar(64) CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2;
+a
+test1
+test2
+тест1
+тест2
+ÆÇÈÉË
+DROP TABLE t2;
CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT user();
-user()
-user@localhost
SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
+a
+test1
+test2
+тест1
+тест2
+ÆÇÈÉË
DROP VIEW v1;
DROP TABLE t1;
-DROP USER user@localhost;
diff --git a/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result b/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result
new file mode 100644
index 00000000000..87f7803166c
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result
@@ -0,0 +1,72 @@
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `Description` varchar(128) NOT NULL,
+ `Attributes` varchar(256) NOT NULL
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers'
+SET NAMES utf8;
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+SELECT user();
+user()
+user@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(64) DEFAULT NULL
+) ENGINE=CONNECT DEFAULT CHARSET=utf8 CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' `TABLE_TYPE`='ODBC' `DATA_CHARSET`='utf8'
+SELECT * FROM t1;
+a
+test1
+test2
+тест1
+тест2
+ÆÇÈÉË
+SELECT user();
+user()
+user@localhost
+SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO t1 VALUES ('xxx');
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM t1 WHERE a='xxx';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1 SET a='yyy' WHERE a='xxx';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+TRUNCATE TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 READONLY=1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE VIEW v1 AS SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+# Testing a VIEW created with FILE privileges but accessed with no FILE
+SELECT user();
+user()
+root@localhost
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT user();
+user()
+user@localhost
+SELECT * FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1 VALUES (2);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1 SET a=123;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+DROP VIEW v1;
+DROP TABLE t1;
+DROP USER user@localhost;
diff --git a/storage/connect/mysql-test/connect/r/pivot.result b/storage/connect/mysql-test/connect/r/pivot.result
new file mode 100644
index 00000000000..1b790662c4b
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/pivot.result
@@ -0,0 +1,230 @@
+#
+# Testing the PIVOT table type
+#
+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;
+Who Week What Amount
+Joe 3 Beer 18.00
+Beth 4 Food 17.00
+Janet 5 Beer 14.00
+Joe 3 Food 12.00
+Joe 4 Beer 19.00
+Janet 5 Car 12.00
+Joe 3 Food 19.00
+Beth 4 Beer 15.00
+Janet 5 Beer 19.00
+Joe 3 Car 20.00
+Joe 4 Beer 16.00
+Beth 5 Food 12.00
+Beth 3 Beer 16.00
+Joe 4 Food 17.00
+Joe 5 Beer 14.00
+Janet 3 Car 19.00
+Joe 4 Food 17.00
+Beth 5 Beer 20.00
+Janet 3 Food 18.00
+Joe 4 Beer 14.00
+Joe 5 Food 12.00
+Janet 3 Beer 18.00
+Janet 4 Car 17.00
+Janet 5 Food 12.00
+#
+# Pivoting from What
+#
+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;
+ALTER TABLE pivex OPTION_LIST='port=PORT';
+Warnings:
+Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
+SELECT * FROM pivex;
+Who Week Beer Car Food
+Beth 3 16.00 0.00 0.00
+Beth 4 15.00 0.00 17.00
+Beth 5 20.00 0.00 12.00
+Janet 3 18.00 19.00 18.00
+Janet 4 0.00 17.00 0.00
+Janet 5 33.00 12.00 12.00
+Joe 3 18.00 20.00 31.00
+Joe 4 49.00 0.00 34.00
+Joe 5 14.00 0.00 12.00
+#
+# Restricting the columns in a Pivot Table
+#
+ALTER TABLE pivex DROP COLUMN week;
+SELECT * FROM pivex;
+Who Beer Car Food
+Beth 51.00 0.00 29.00
+Janet 51.00 48.00 30.00
+Joe 81.00 20.00 77.00
+#
+# Using a source definition
+#
+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';
+ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=PORT';
+Warnings:
+Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
+SELECT * FROM pivex;
+Who Week Beer Car Food
+Beth 4 15.00 0.00 17.00
+Beth 5 20.00 0.00 12.00
+Janet 4 0.00 17.00 0.00
+Janet 5 33.00 12.00 12.00
+Joe 4 49.00 0.00 34.00
+Joe 5 14.00 0.00 12.00
+#
+# Pivoting from Week
+#
+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;
+ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=PORT';
+Warnings:
+Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
+SELECT * FROM pivex;
+Who What 3 4 5
+Beth Beer 16.00 15.00 20.00
+Beth Food 0.00 17.00 12.00
+Janet Beer 18.00 0.00 33.00
+Janet Car 19.00 17.00 12.00
+Janet Food 18.00 0.00 12.00
+Joe Beer 18.00 49.00 14.00
+Joe Car 20.00 0.00 0.00
+Joe Food 31.00 34.00 12.00
+#
+# Using scalar functions and expresssions
+#
+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';
+ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=PORT';
+Warnings:
+Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
+SELECT * FROM pivex;
+Who What First Middle Last
+Beth Beer 104.96 98.40 131.20
+Beth Food 0.00 111.52 78.72
+Janet Beer 118.08 0.00 216.48
+Janet Car 124.64 111.52 78.72
+Janet Food 118.08 0.00 78.72
+Joe Beer 118.08 321.44 91.84
+Joe Car 131.20 0.00 0.00
+Joe Food 203.36 223.04 78.72
+DROP TABLE pivex;
+DROP TABLE expenses;
+#
+# Make the PETS table
+#
+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;
+Name Race Number
+John dog 2
+Bill cat 1
+Mary dog 1
+Mary cat 1
+Lisbeth rabbit 2
+Kevin cat 2
+Kevin bird 6
+Donald dog 1
+Donald fish 3
+#
+# Pivot the PETS table
+#
+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;
+name dog cat rabbit bird fish
+John 2 0 0 0 0
+Bill 0 1 0 0 0
+Mary 1 1 0 0 0
+Lisbeth 0 0 2 0 0
+Kevin 0 2 0 6 0
+Donald 1 0 0 0 3
+DROP TABLE pivet;
+#
+# Testing the "data" column list
+#
+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';
+SELECT * FROM pivet;
+ERROR HY000: Got error 122 'Cannot find matching column' from CONNECT
+ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1';
+Warnings:
+Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
+SELECT * FROM pivet;
+name dog cat
+John 2 0
+Bill 0 1
+Mary 1 1
+Lisbeth 0 0
+Kevin 0 2
+Donald 1 0
+DROP TABLE pivet;
+#
+# Adding a "dump" column
+#
+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;
+name dog cat other
+John 2 0 0
+Bill 0 1 0
+Mary 1 1 0
+Lisbeth 0 0 2
+Kevin 0 2 6
+Donald 1 0 3
+DROP TABLE pivet;
+DROP TABLE pets;
diff --git a/storage/connect/mysql-test/connect/r/tbl.result b/storage/connect/mysql-test/connect/r/tbl.result
index 01a6afcebe8..bc77516c22d 100644
--- a/storage/connect/mysql-test/connect/r/tbl.result
+++ b/storage/connect/mysql-test/connect/r/tbl.result
@@ -4,6 +4,9 @@
CREATE TABLE t1 (
a INT NOT NULL,
message CHAR(10)) ENGINE=connect;
+Warnings:
+Warning 1105 No table_type. Will be set to DOS
+Warning 1105 No file name. Table will use t1.dos
INSERT INTO t1 VALUES (1,'Testing'),(2,'dos table'),(3,'t1');
SELECT * FROM t1;
a message
diff --git a/storage/connect/mysql-test/connect/r/upd.result b/storage/connect/mysql-test/connect/r/upd.result
index 24cfdafaa9a..fa519c4b688 100644
--- a/storage/connect/mysql-test/connect/r/upd.result
+++ b/storage/connect/mysql-test/connect/r/upd.result
@@ -59,6 +59,9 @@ END//
# Testing DOS table changes
#
CREATE TABLE t1 ENGINE=connect AS SELECT * FROM employee;
+Warnings:
+Warning 1105 No table_type. Will be set to DOS
+Warning 1105 No file name. Table will use t1.dos
CALL test.tst_up();
serialno name sex title manager department secretary salary
74200 BANCROFT 2 SALESMAN 70012 0318 24888 9600.00
@@ -154,6 +157,9 @@ serialno name sex title manager department secretary salary
# Testing DOS table changes
#
CREATE TABLE t1 ENGINE=connect mapped=yes AS SELECT * FROM employee;
+Warnings:
+Warning 1105 No table_type. Will be set to DOS
+Warning 1105 No file name. Table will use t1.dos
CALL test.tst_up();
serialno name sex title manager department secretary salary
74200 BANCROFT 2 SALESMAN 70012 0318 24888 9600.00
diff --git a/storage/connect/mysql-test/connect/r/vec.result b/storage/connect/mysql-test/connect/r/vec.result
index 9461966aef7..65513dc07db 100644
--- a/storage/connect/mysql-test/connect/r/vec.result
+++ b/storage/connect/mysql-test/connect/r/vec.result
@@ -1,97 +1,3 @@
-#
-# Beginning of grant.inc
-#
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
-SELECT user();
-user()
-user@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100;
-Warnings:
-Warning 1105 No file name. Table will use t1.vec
-INSERT INTO t1 VALUES (10);
-SELECT * FROM t1;
-a
-10
-UPDATE t1 SET a=20;
-SELECT * FROM t1;
-a
-20
-DELETE FROM t1;
-SELECT * FROM t1;
-a
-INSERT INTO t1 VALUES(10);
-TRUNCATE TABLE t1;
-SELECT * FROM t1;
-a
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT * FROM v1;
-a
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100 FILE_NAME='t1.EXT';
-INSERT INTO t1 VALUES (10);
-SELECT user();
-user()
-user@localhost
-INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-# Testing a VIEW created with FILE privileges but accessed with no FILE
-SELECT user();
-user()
-root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT user();
-user()
-user@localhost
-SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100;
-Warnings:
-Warning 1105 No file name. Table will use t1.vec
-INSERT INTO t1 VALUES (10);
-SELECT user();
-user()
-user@localhost
-ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-DROP USER user@localhost;
-#
-# End of grant.inc
-#
CREATE TABLE dir1 (
spath VARCHAR(256) NOT NULL flag=1,
fname VARCHAR(256) NOT NULL,
diff --git a/storage/connect/mysql-test/connect/r/xcol.result b/storage/connect/mysql-test/connect/r/xcol.result
new file mode 100644
index 00000000000..f6899b47504
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/xcol.result
@@ -0,0 +1,85 @@
+#
+# Checking XCOL tables
+#
+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;
+Warnings:
+Warning 1105 No table_type. Will be set to DOS
+Warning 1105 No file name. Table will use chlist.dos
+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;
+mother children
+Sophia Vivian, Antony
+Lisbeth Lucy,Charles,Diana
+Corinne NULL
+Claude Marc
+Janet Arthur,Sandra,Peter,John
+CREATE TABLE child ENGINE=CONNECT TABLE_TYPE=XCOL TABNAME=chlist OPTION_LIST='colname=children,port=PORT';
+SELECT * FROM child;
+mother children
+Sophia Vivian
+Sophia Antony
+Lisbeth Lucy
+Lisbeth Charles
+Lisbeth Diana
+Corinne NULL
+Claude Marc
+Janet Arthur
+Janet Sandra
+Janet Peter
+Janet John
+SELECT * FROM child ORDER BY mother;
+mother children
+Claude Marc
+Corinne NULL
+Janet Peter
+Janet Sandra
+Janet Arthur
+Janet John
+Lisbeth Diana
+Lisbeth Charles
+Lisbeth Lucy
+Sophia Antony
+Sophia Vivian
+SELECT * FROM child ORDER BY children;
+mother children
+Corinne NULL
+Sophia Antony
+Janet Arthur
+Lisbeth Charles
+Lisbeth Diana
+Janet John
+Lisbeth Lucy
+Claude Marc
+Janet Peter
+Janet Sandra
+Sophia Vivian
+SELECT mother FROM child;
+mother
+Sophia
+Lisbeth
+Corinne
+Claude
+Janet
+SELECT mother, COUNT(*) FROM child GROUP BY mother;
+mother COUNT(*)
+Claude 1
+Corinne 1
+Janet 1
+Lisbeth 1
+Sophia 1
+SELECT mother, COUNT(children) FROM child GROUP BY mother;
+mother COUNT(children)
+Claude 1
+Corinne 0
+Janet 4
+Lisbeth 3
+Sophia 2
+DROP TABLE child;
+DROP TABLE chlist;
diff --git a/storage/connect/mysql-test/connect/r/xml.result b/storage/connect/mysql-test/connect/r/xml.result
index e7dcf8f4c73..67fcc5f121e 100644
--- a/storage/connect/mysql-test/connect/r/xml.result
+++ b/storage/connect/mysql-test/connect/r/xml.result
@@ -1,99 +1,5 @@
Warnings:
Warning 1105 No file name. Table will use t1.xml
-#
-# Beginning of grant.inc
-#
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
-SELECT user();
-user()
-user@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row';
-Warnings:
-Warning 1105 No file name. Table will use t1.xml
-INSERT INTO t1 VALUES (10);
-SELECT * FROM t1;
-a
-10
-UPDATE t1 SET a=20;
-SELECT * FROM t1;
-a
-20
-DELETE FROM t1;
-SELECT * FROM t1;
-a
-INSERT INTO t1 VALUES(10);
-TRUNCATE TABLE t1;
-SELECT * FROM t1;
-a
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT * FROM v1;
-a
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row' FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row' FILE_NAME='t1.EXT';
-INSERT INTO t1 VALUES (10);
-SELECT user();
-user()
-user@localhost
-INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-# Testing a VIEW created with FILE privileges but accessed with no FILE
-SELECT user();
-user()
-root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT user();
-user()
-user@localhost
-SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-SELECT user();
-user()
-root@localhost
-DROP VIEW v1;
-DROP TABLE t1;
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row';
-Warnings:
-Warning 1105 No file name. Table will use t1.xml
-INSERT INTO t1 VALUES (10);
-SELECT user();
-user()
-user@localhost
-ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
-DROP TABLE t1;
-DROP USER user@localhost;
-#
-# End of grant.inc
-#
SET NAMES utf8;
#
# Testing tag values
@@ -253,8 +159,8 @@ TITLE XML, Langage et Applications
TRANSLATOR NULL
PUBLISHER Eyrolles Paris
DATEPUB 1998
-SELECT LOAD_FILE('test/xsample2.xml');
-LOAD_FILE('test/xsample2.xml') <?xml version="1.0" encoding="UTF-8"?>
+SELECT LOAD_FILE('MYSQLD_DATADIR/test/xsample2.xml') AS xml;
+xml <?xml version="1.0" encoding="UTF-8"?>
<BIBLIO SUBJECT="XML">
<BOOK ISBN="9782212090819" LANG="fr" SUBJECT="applications">
<AUTHOR>
@@ -467,7 +373,7 @@ SELECT node, hex(node) FROM t1;
node ÀÁÂÃ
hex(node) C0C1C2C3
DROP TABLE t1;
-SET @a=LOAD_FILE('test/t1.xml');
+SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml');
SELECT LEFT(@a,38);
LEFT(@a,38) <?xml version="1.0" encoding="utf-8"?>
SELECT HEX(EXTRACTVALUE(@a,'/t1/line/node'));
@@ -481,7 +387,7 @@ SELECT node, hex(node) FROM t1;
node ÀÁÂÃ
hex(node) C0C1C2C3
DROP TABLE t1;
-SET @a=LOAD_FILE('test/t1.xml');
+SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml');
SELECT LEFT(@a,43);
LEFT(@a,43) <?xml version="1.0" encoding="iso-8859-1"?>
SELECT HEX(EXTRACTVALUE(@a,'/t1/line/node'));
@@ -504,10 +410,10 @@ hex(node) D090D091D092D093
node &<>"'
hex(node) 263C3E2227
DROP TABLE t1;
-SET @a=LOAD_FILE('test/t1.xml');
+SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml');
SELECT CAST(@a AS CHAR CHARACTER SET latin1);
CAST(@a AS CHAR CHARACTER SET latin1) <?xml version="1.0" encoding="iso-8859-1"?>
-<!-- Created by CONNECT Version 1.01.0004 April 10, 2013 -->
+<!-- Created by CONNECT Version 1.01.0006 Mai 21, 2013 -->
<t1>
<line>
<node>ÀÁÂÃ</node>
diff --git a/storage/connect/mysql-test/connect/r/xml_grant.result b/storage/connect/mysql-test/connect/r/xml_grant.result
new file mode 100644
index 00000000000..ea38e57af86
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/xml_grant.result
@@ -0,0 +1,96 @@
+Warnings:
+Warning 1105 No file name. Table will use t1.xml
+#
+# Beginning of grant.inc
+#
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+SELECT user();
+user()
+user@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row';
+Warnings:
+Warning 1105 No file name. Table will use t1.xml
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+a
+10
+UPDATE t1 SET a=20;
+SELECT * FROM t1;
+a
+20
+DELETE FROM t1;
+SELECT * FROM t1;
+a
+INSERT INTO t1 VALUES(10);
+TRUNCATE TABLE t1;
+SELECT * FROM t1;
+a
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT * FROM v1;
+a
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row' FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row' FILE_NAME='t1.EXT';
+INSERT INTO t1 VALUES (10);
+SELECT user();
+user()
+user@localhost
+INSERT INTO t1 VALUES (10);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1 SET a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+TRUNCATE TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 READONLY=1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ALTER TABLE t1 FILE_NAME='t2.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE VIEW v1 AS SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+# Testing a VIEW created with FILE privileges but accessed with no FILE
+SELECT user();
+user()
+root@localhost
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT user();
+user()
+user@localhost
+SELECT * FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1 VALUES (2);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1 SET a=123;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM v1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT user();
+user()
+root@localhost
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row';
+Warnings:
+Warning 1105 No file name. Table will use t1.xml
+INSERT INTO t1 VALUES (10);
+SELECT user();
+user()
+user@localhost
+ALTER TABLE t1 FILE_NAME='t1.EXT';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+DROP USER user@localhost;
+#
+# End of grant.inc
+#
diff --git a/storage/connect/mysql-test/connect/std_data/expenses.txt b/storage/connect/mysql-test/connect/std_data/expenses.txt
new file mode 100644
index 00000000000..66a94edbb9a
--- /dev/null
+++ b/storage/connect/mysql-test/connect/std_data/expenses.txt
@@ -0,0 +1,24 @@
+Joe 3Beer 18.00
+Beth 4Food 17.00
+Janet 5Beer 14.00
+Joe 3Food 12.00
+Joe 4Beer 19.00
+Janet 5Car 12.00
+Joe 3Food 19.00
+Beth 4Beer 15.00
+Janet 5Beer 19.00
+Joe 3Car 20.00
+Joe 4Beer 16.00
+Beth 5Food 12.00
+Beth 3Beer 16.00
+Joe 4Food 17.00
+Joe 5Beer 14.00
+Janet 3Car 19.00
+Joe 4Food 17.00
+Beth 5Beer 20.00
+Janet 3Food 18.00
+Joe 4Beer 14.00
+Joe 5Food 12.00
+Janet 3Beer 18.00
+Janet 4Car 17.00
+Janet 5Food 12.00
diff --git a/storage/connect/mysql-test/connect/t/bin.test b/storage/connect/mysql-test/connect/t/bin.test
index 0266fd3e357..a9dab32987e 100644
--- a/storage/connect/mysql-test/connect/t/bin.test
+++ b/storage/connect/mysql-test/connect/t/bin.test
@@ -1,9 +1,5 @@
let $MYSQLD_DATADIR= `select @@datadir`;
-let $TABLE_OPTIONS=TABLE_TYPE=BIN;
-let $FILE_EXT=BIN;
---source grant.inc
-
--copy_file $MTR_SUITE_DIR/std_data/Testbal.dat $MYSQLD_DATADIR/test/Testbal.dat
--echo #
diff --git a/storage/connect/mysql-test/connect/t/csv.test b/storage/connect/mysql-test/connect/t/csv.test
index 6578ba83a9a..685ac434df7 100644
--- a/storage/connect/mysql-test/connect/t/csv.test
+++ b/storage/connect/mysql-test/connect/t/csv.test
@@ -1,9 +1,5 @@
let $MYSQLD_DATADIR= `select @@datadir`;
-let $TABLE_OPTIONS=TABLE_TYPE=CSV;
-let $FILE_EXT=CSV;
---source grant.inc
-
--copy_file $MTR_SUITE_DIR/std_data/people.csv $MYSQLD_DATADIR/test/people.csv
SET NAMES utf8;
diff --git a/storage/connect/mysql-test/connect/t/dbf.test b/storage/connect/mysql-test/connect/t/dbf.test
index fb0bc21f52d..b9a1b6e2183 100644
--- a/storage/connect/mysql-test/connect/t/dbf.test
+++ b/storage/connect/mysql-test/connect/t/dbf.test
@@ -1,9 +1,5 @@
let $MYSQLD_DATADIR= `select @@datadir`;
-let $TABLE_OPTIONS=TABLE_TYPE=DBF;
-let $FILE_EXT=DBF;
---source grant.inc
-
--echo #
--echo # Testing errors
--echo #
diff --git a/storage/connect/mysql-test/connect/t/dir.test b/storage/connect/mysql-test/connect/t/dir.test
index 073cdaa380b..fb69813d9f0 100644
--- a/storage/connect/mysql-test/connect/t/dir.test
+++ b/storage/connect/mysql-test/connect/t/dir.test
@@ -1,76 +1,6 @@
let $MYSQLD_DATADIR= `select @@datadir`;
---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();
---error ER_ACCESS_DENIED_ERROR
-CREATE TABLE t1 (
- path VARCHAR(256) NOT NULL flag=1,
- fname VARCHAR(256) NOT NULL,
- ftype CHAR(4) NOT NULL,
- size DOUBLE(12,0) NOT NULL flag=5
-) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*';
---connection default
-SELECT user();
-CREATE TABLE t1 (
- path VARCHAR(256) NOT NULL flag=1,
- fname VARCHAR(256) NOT NULL,
- ftype CHAR(4) NOT NULL,
- size DOUBLE(12,0) NOT NULL flag=5
-) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*';
-# "size>0" to skip directory names on Windows
---replace_result $MYSQLD_DATADIR DATADIR/
-SELECT fname, ftype, size FROM t1 WHERE size>0;
-
---connection user
-SELECT user();
---error ER_ACCESS_DENIED_ERROR
-SELECT * FROM t1;
---error ER_ACCESS_DENIED_ERROR
-INSERT INTO t1 VALUES ();
---error ER_ACCESS_DENIED_ERROR
-DELETE FROM t1 WHERE path='xxx';
---error ER_ACCESS_DENIED_ERROR
-UPDATE t1 SET path='yyy' WHERE path='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 (1,1,1,1);
---error ER_ACCESS_DENIED_ERROR
-UPDATE v1 SET path=123;
---error ER_ACCESS_DENIED_ERROR
-DELETE FROM v1;
-
---disconnect user
---connection default
-SELECT user();
-DROP VIEW v1;
-DROP TABLE t1;
-DROP USER user@localhost;
---echo #
---echo # Testing FILE privileges done
---echo #
-
-
CREATE TABLE t1 (
path VARCHAR(256) NOT NULL flag=1,
fname VARCHAR(256) NOT NULL,
diff --git a/storage/connect/mysql-test/connect/t/fix.test b/storage/connect/mysql-test/connect/t/fix.test
index d2dfeb21352..c3cec55a217 100644
--- a/storage/connect/mysql-test/connect/t/fix.test
+++ b/storage/connect/mysql-test/connect/t/fix.test
@@ -1,9 +1,5 @@
let $MYSQLD_DATADIR= `select @@datadir`;
-let $TABLE_OPTIONS=TABLE_TYPE=FIX;
-let $FILE_EXT=FIX;
---source grant.inc
-
--copy_file $MTR_SUITE_DIR/std_data/dept.dat $MYSQLD_DATADIR/test/dept.dat
--copy_file $MTR_SUITE_DIR/std_data/boys.txt $MYSQLD_DATADIR/test/boys.txt
--copy_file $MTR_SUITE_DIR/std_data/boyswin.txt $MYSQLD_DATADIR/test/boyswin.txt
diff --git a/storage/connect/mysql-test/connect/t/fmt.test b/storage/connect/mysql-test/connect/t/fmt.test
index de7f8c06c1b..662bc70c8b1 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/grant.test b/storage/connect/mysql-test/connect/t/grant.test
new file mode 100644
index 00000000000..909bb4117a1
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/grant.test
@@ -0,0 +1,95 @@
+-- source include/not_embedded.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--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();
+--error ER_ACCESS_DENIED_ERROR
+CREATE TABLE t1 (
+ path VARCHAR(256) NOT NULL flag=1,
+ fname VARCHAR(256) NOT NULL,
+ ftype CHAR(4) NOT NULL,
+ size DOUBLE(12,0) NOT NULL flag=5
+) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*';
+--connection default
+SELECT user();
+CREATE TABLE t1 (
+ path VARCHAR(256) NOT NULL flag=1,
+ fname VARCHAR(256) NOT NULL,
+ ftype CHAR(4) NOT NULL,
+ size DOUBLE(12,0) NOT NULL flag=5
+) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*';
+# "size>0" to skip directory names on Windows
+--replace_result $MYSQLD_DATADIR DATADIR/
+SELECT fname, ftype, size FROM t1 WHERE size>0;
+
+--connection user
+SELECT user();
+--error ER_ACCESS_DENIED_ERROR
+SELECT * FROM t1;
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO t1 VALUES ();
+--error ER_ACCESS_DENIED_ERROR
+DELETE FROM t1 WHERE path='xxx';
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t1 SET path='yyy' WHERE path='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 (1,1,1,1);
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1 SET path=123;
+--error ER_ACCESS_DENIED_ERROR
+DELETE FROM v1;
+
+--disconnect user
+--connection default
+SELECT user();
+DROP VIEW v1;
+DROP TABLE t1;
+DROP USER user@localhost;
+--echo #
+--echo # Testing FILE privileges done
+--echo #
+
+
+let $TABLE_OPTIONS=TABLE_TYPE=BIN;
+let $FILE_EXT=BIN;
+--source grant.inc
+
+let $TABLE_OPTIONS=TABLE_TYPE=CSV;
+let $FILE_EXT=CSV;
+--source grant.inc
+
+let $TABLE_OPTIONS=TABLE_TYPE=DBF;
+let $FILE_EXT=DBF;
+--source grant.inc
+
+let $TABLE_OPTIONS=TABLE_TYPE=FIX;
+let $FILE_EXT=FIX;
+--source grant.inc
+
+let $TABLE_OPTIONS=TABLE_TYPE=VEC MAX_ROWS=100;
+let $FILE_EXT=VEC;
+--source grant.inc
+
+
diff --git a/storage/connect/mysql-test/connect/t/have_odbc_sqlite3.inc b/storage/connect/mysql-test/connect/t/have_odbc_sqlite3.inc
new file mode 100644
index 00000000000..9528e00ff56
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/have_odbc_sqlite3.inc
@@ -0,0 +1,15 @@
+--disable_query_log
+--error 0,ER_UNKNOWN_ERROR
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers;
+if ($mysql_errno)
+{
+ Skip No ODBC support;
+}
+if (!`SELECT count(*) FROM t1 WHERE Description='SQLite3 ODBC Driver'`)
+{
+ DROP TABLE t1;
+ Skip Need SQLite3 ODBC Driver;
+}
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+--enable_query_log
diff --git a/storage/connect/mysql-test/connect/t/ini.test b/storage/connect/mysql-test/connect/t/ini.test
index e862f3cd672..0d23142ac9e 100644
--- a/storage/connect/mysql-test/connect/t/ini.test
+++ b/storage/connect/mysql-test/connect/t/ini.test
@@ -1,80 +1,5 @@
let $MYSQLD_DATADIR= `select @@datadir`;
---echo #
---echo # Checking FILE privileges
---echo #
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
---connect(user,localhost,user,,)
---connection user
-SELECT user();
-CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI;
-INSERT INTO t1 VALUES ('sec1','val1');
-SELECT * FROM t1;
-UPDATE t1 SET val='val11';
-SELECT * FROM t1;
-DELETE FROM t1;
-SELECT * FROM t1;
-INSERT INTO t1 VALUES('sec2','val2');
-TRUNCATE TABLE t1;
-SELECT * FROM t1;
-CREATE VIEW v1 AS SELECT * FROM t1;
-SELECT * FROM v1;
-DROP VIEW v1;
-DROP TABLE t1;
-# Making sure DROP erased the data file
---error 1
---remove_file $MYSQLD_DATADIR/test/t1.ini
---error ER_ACCESS_DENIED_ERROR
-CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT';
---connection default
-SELECT user();
-CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT';
-INSERT INTO t1 VALUES ('sec1','val1');
---connection user
-SELECT user();
---error ER_ACCESS_DENIED_ERROR
-INSERT INTO t1 VALUES ('sec2','val2');
---error ER_ACCESS_DENIED_ERROR
-SELECT * FROM t1;
---error ER_ACCESS_DENIED_ERROR
-UPDATE t1 SET val='val11';
---error ER_ACCESS_DENIED_ERROR
-DELETE FROM t1;
---error ER_ACCESS_DENIED_ERROR
-TRUNCATE TABLE t1;
---error ER_ACCESS_DENIED_ERROR
-ALTER TABLE t1 READONLY=1;
---error ER_ACCESS_DENIED_ERROR
-DROP TABLE t1;
---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 ('sec3','val3');
---error ER_ACCESS_DENIED_ERROR
-UPDATE v1 SET val='val11';
---error ER_ACCESS_DENIED_ERROR
-DELETE FROM v1;
---disconnect user
---connection default
-DROP VIEW v1;
-DROP TABLE t1;
---remove_file $MYSQLD_DATADIR/test/t1.EXT
-DROP USER user@localhost;
-
---echo #
---echo # Checking FILE privileges: done
---echo #
-
-
--copy_file $MTR_SUITE_DIR/std_data/contact.ini $MYSQLD_DATADIR/test/contact.ini
--echo #
diff --git a/storage/connect/mysql-test/connect/t/ini_grant.test b/storage/connect/mysql-test/connect/t/ini_grant.test
new file mode 100644
index 00000000000..30678645692
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/ini_grant.test
@@ -0,0 +1,79 @@
+-- source include/not_embedded.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--echo #
+--echo # Checking FILE privileges
+--echo #
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+--connect(user,localhost,user,,)
+--connection user
+SELECT user();
+CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI;
+INSERT INTO t1 VALUES ('sec1','val1');
+SELECT * FROM t1;
+UPDATE t1 SET val='val11';
+SELECT * FROM t1;
+DELETE FROM t1;
+SELECT * FROM t1;
+INSERT INTO t1 VALUES('sec2','val2');
+TRUNCATE TABLE t1;
+SELECT * FROM t1;
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT * FROM v1;
+DROP VIEW v1;
+DROP TABLE t1;
+# Making sure DROP erased the data file
+--error 1
+--remove_file $MYSQLD_DATADIR/test/t1.ini
+--error ER_ACCESS_DENIED_ERROR
+CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT';
+--connection default
+SELECT user();
+CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT';
+INSERT INTO t1 VALUES ('sec1','val1');
+--connection user
+SELECT user();
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO t1 VALUES ('sec2','val2');
+--error ER_ACCESS_DENIED_ERROR
+SELECT * FROM t1;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t1 SET val='val11';
+--error ER_ACCESS_DENIED_ERROR
+DELETE FROM t1;
+--error ER_ACCESS_DENIED_ERROR
+TRUNCATE TABLE t1;
+--error ER_ACCESS_DENIED_ERROR
+ALTER TABLE t1 READONLY=1;
+--error ER_ACCESS_DENIED_ERROR
+DROP TABLE t1;
+--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 ('sec3','val3');
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1 SET val='val11';
+--error ER_ACCESS_DENIED_ERROR
+DELETE FROM v1;
+--disconnect user
+--connection default
+DROP VIEW v1;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.EXT
+DROP USER user@localhost;
+
+--echo #
+--echo # Checking FILE privileges: done
+--echo #
+
+
diff --git a/storage/connect/mysql-test/connect/t/mysql.test b/storage/connect/mysql-test/connect/t/mysql.test
index 45d26cdf9eb..c7eacbd3d06 100644
--- a/storage/connect/mysql-test/connect/t/mysql.test
+++ b/storage/connect/mysql-test/connect/t/mysql.test
@@ -1,3 +1,10 @@
+-- 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
@@ -14,66 +21,6 @@ if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
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 #
-
# TODO: remote VARCHAR is displayed as CHAR
CREATE TABLE t1 (a int, b char(10));
diff --git a/storage/connect/mysql-test/connect/t/mysql_grant.test b/storage/connect/mysql-test/connect/t/mysql_grant.test
new file mode 100644
index 00000000000..e825e70a84b
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/mysql_grant.test
@@ -0,0 +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='t1' 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/occur.test b/storage/connect/mysql-test/connect/t/occur.test
new file mode 100644
index 00000000000..36a4caafda1
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/occur.test
@@ -0,0 +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
diff --git a/storage/connect/mysql-test/connect/t/odbc_sqlite3.test b/storage/connect/mysql-test/connect/t/odbc_sqlite3.test
index 5f6abb0e2bc..f32196e3f04 100644
--- a/storage/connect/mysql-test/connect/t/odbc_sqlite3.test
+++ b/storage/connect/mysql-test/connect/t/odbc_sqlite3.test
@@ -1,3 +1,5 @@
+--source have_odbc_sqlite3.inc
+
#
# To run this test, install SQLite3 ODBC Driver from
# http://www.ch-werner.de/sqliteodbc/
@@ -18,42 +20,11 @@
# Note, the test does not need a DSN to be created.
#
---disable_query_log
---error 0,ER_UNKNOWN_ERROR
-CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers;
-if ($mysql_errno)
-{
- Skip No ODBC support;
-}
-if (!`SELECT count(*) FROM t1 WHERE Description='SQLite3 ODBC Driver'`)
-{
- DROP TABLE t1;
- Skip Need SQLite3 ODBC Driver;
-}
-SHOW CREATE TABLE t1;
-DROP TABLE t1;
---enable_query_log
-
SET NAMES utf8;
let $MYSQLD_DATADIR= `select @@datadir`;
-GRANT ALL PRIVILEGES ON *.* TO user@localhost;
-REVOKE FILE ON *.* FROM user@localhost;
---connect(user,localhost,user,,)
---connection user
-SELECT user();
---error ER_ACCESS_DENIED_ERROR
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC;
---error ER_ACCESS_DENIED_ERROR
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers;
---error ER_ACCESS_DENIED_ERROR
-CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources;
---connection default
-SELECT user();
-
-
#
# 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
@@ -66,42 +37,14 @@ let $Database=$MTR_SUITE_DIR/std_data/test.sqlite3;
--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
SHOW CREATE TABLE t1;
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 TABLE t2 AS SELECT * FROM t1;
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+
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;
-
-DROP USER user@localhost;
diff --git a/storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test b/storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test
new file mode 100644
index 00000000000..7664a4473ba
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test
@@ -0,0 +1,79 @@
+-- source include/not_embedded.inc
+-- source have_odbc_sqlite3.inc
+
+#
+# For the instructions on how to setup SQLite3 ODBC DSN,
+# please see odbc_sqlite3.test
+#
+
+SET NAMES utf8;
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+--connect(user,localhost,user,,)
+--connection user
+SELECT user();
+--error ER_ACCESS_DENIED_ERROR
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC;
+--error ER_ACCESS_DENIED_ERROR
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers;
+--error ER_ACCESS_DENIED_ERROR
+CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources;
+--connection default
+SELECT user();
+
+
+#
+# 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;
+--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;
+
+DROP USER user@localhost;
diff --git a/storage/connect/mysql-test/connect/t/pivot.test b/storage/connect/mysql-test/connect/t/pivot.test
new file mode 100644
index 00000000000..7679434bca8
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/pivot.test
@@ -0,0 +1,146 @@
+-- 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;
+--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 143c7643afd..bdd928366ef 100644
--- a/storage/connect/mysql-test/connect/t/tbl.test
+++ b/storage/connect/mysql-test/connect/t/tbl.test
@@ -1,3 +1,5 @@
+-- source include/not_embedded.inc
+
let $MYSQLD_DATADIR= `select @@datadir`;
let $PORT= `select @@port`;
diff --git a/storage/connect/mysql-test/connect/t/vec.test b/storage/connect/mysql-test/connect/t/vec.test
index 79ed4eabd86..ee504e9925a 100644
--- a/storage/connect/mysql-test/connect/t/vec.test
+++ b/storage/connect/mysql-test/connect/t/vec.test
@@ -1,9 +1,5 @@
let $MYSQLD_DATADIR= `select @@datadir`;
-let $TABLE_OPTIONS=TABLE_TYPE=VEC MAX_ROWS=100;
-let $FILE_EXT=VEC;
---source grant.inc
-
CREATE TABLE dir1 (
spath VARCHAR(256) NOT NULL flag=1,
fname VARCHAR(256) NOT NULL,
diff --git a/storage/connect/mysql-test/connect/t/xcol.test b/storage/connect/mysql-test/connect/t/xcol.test
new file mode 100644
index 00000000000..b6998ee77e0
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/xcol.test
@@ -0,0 +1,28 @@
+let $MYSQLD_DATADIR= `select @@datadir`;
+let $PORT= `select @@port`;
+
+--echo #
+--echo # Checking XCOL tables
+--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;
+
+--replace_result $PORT PORT
+--eval CREATE TABLE child ENGINE=CONNECT TABLE_TYPE=XCOL TABNAME=chlist OPTION_LIST='colname=children,port=$PORT'
+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;
+
+DROP TABLE child;
+DROP TABLE chlist;
diff --git a/storage/connect/mysql-test/connect/t/xml.test b/storage/connect/mysql-test/connect/t/xml.test
index 96e7e1a3a97..3914bed307d 100644
--- a/storage/connect/mysql-test/connect/t/xml.test
+++ b/storage/connect/mysql-test/connect/t/xml.test
@@ -16,11 +16,6 @@ DROP TABLE t1;
let $MYSQLD_DATADIR= `select @@datadir`;
-let $TABLE_OPTIONS=TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row';
-let $FILE_EXT=XML;
---source grant.inc
-
-
SET NAMES utf8;
--vertical_results
@@ -132,7 +127,8 @@ INSERT INTO t1 (ISBN, LANG, SUBJECT, AUTHOR, TITLE, PUBLISHEr, DATEPUB)
VALUES('9782212090529','fr','général','Alain Michard',
'XML, Langage et Applications','Eyrolles Paris',1998);
SELECT * FROM t1;
-SELECT LOAD_FILE('test/xsample2.xml');
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+--eval SELECT LOAD_FILE('$MYSQLD_DATADIR/test/xsample2.xml') AS xml
DROP TABLE t1;
--remove_file $MYSQLD_DATADIR/test/xsample2.xml
@@ -289,7 +285,8 @@ INSERT INTO t1 VALUES (_latin1 0xC0C1C2C3);
SELECT node, hex(node) FROM t1;
DROP TABLE t1;
--chmod 0777 $MYSQLD_DATADIR/test/t1.xml
-SET @a=LOAD_FILE('test/t1.xml');
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+--eval SET @a=LOAD_FILE('$MYSQLD_DATADIR/test/t1.xml')
SELECT LEFT(@a,38);
SELECT HEX(EXTRACTVALUE(@a,'/t1/line/node'));
--remove_file $MYSQLD_DATADIR/test/t1.xml
@@ -302,7 +299,8 @@ INSERT INTO t1 VALUES (_latin1 0xC0C1C2C3);
SELECT node, hex(node) FROM t1;
DROP TABLE t1;
--chmod 0777 $MYSQLD_DATADIR/test/t1.xml
-SET @a=LOAD_FILE('test/t1.xml');
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+--eval SET @a=LOAD_FILE('$MYSQLD_DATADIR/test/t1.xml')
SELECT LEFT(@a,43);
SELECT HEX(EXTRACTVALUE(@a,'/t1/line/node'));
--remove_file $MYSQLD_DATADIR/test/t1.xml
@@ -321,7 +319,8 @@ INSERT INTO t1 VALUES ('&<>"\'');
SELECT node, hex(node) FROM t1;
DROP TABLE t1;
--chmod 0777 $MYSQLD_DATADIR/test/t1.xml
-SET @a=LOAD_FILE('test/t1.xml');
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+--eval SET @a=LOAD_FILE('$MYSQLD_DATADIR/test/t1.xml')
SELECT CAST(@a AS CHAR CHARACTER SET latin1);
--remove_file $MYSQLD_DATADIR/test/t1.xml
diff --git a/storage/connect/mysql-test/connect/t/xml_grant.test b/storage/connect/mysql-test/connect/t/xml_grant.test
new file mode 100644
index 00000000000..f8401efaa64
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/xml_grant.test
@@ -0,0 +1,23 @@
+-- source include/not_embedded.inc
+
+--disable_query_log
+--error 0,ER_UNKNOWN_ERROR
+CREATE TABLE t1 (a VARCHAR(10))
+ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2';
+if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
+ WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
+ AND ENGINE='CONNECT'
+ AND CREATE_OPTIONS LIKE '%`table_type`=XML%'
+ AND CREATE_OPTIONS LIKE '%xmlsup=libxml2%'`)
+{
+ Skip Need LIBXML2;
+}
+DROP TABLE t1;
+--enable_query_log
+
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+let $TABLE_OPTIONS=TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row';
+let $FILE_EXT=XML;
+--source grant.inc
diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp
index 6de2acef391..b39f1c9ba5b 100644
--- a/storage/connect/odbconn.cpp
+++ b/storage/connect/odbconn.cpp
@@ -36,6 +36,7 @@
//#include "kindex.h"
#include "xtable.h"
#include "tabodbc.h"
+#include "odbccat.h"
#include "plgcnx.h" // For DB types
#include "resource.h"
#include "valblk.h"
@@ -47,9 +48,7 @@
/***********************************************************************/
#pragma comment(lib, "odbc32.lib")
extern "C" HINSTANCE s_hModule; // Saved module handle
-#else // !WIN32
-extern "C" int GetRcString(int id, char *buf, int bufsize);
-#endif // !WIN32
+#endif // WIN32
/***********************************************************************/
/* Some macro's (should be defined elsewhere to be more accessible) */
@@ -176,7 +175,7 @@ int TranslateSQLType(int stp, int prec, int& len)
/***********************************************************************/
/* Allocate the structure used to refer to the result set. */
/***********************************************************************/
-CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp)
+static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp)
{
size_t i, m, n;
CATPARM *cap;
@@ -203,7 +202,7 @@ CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp)
/***********************************************************************/
/* Check for nulls and reset them to Null (?) values. */
/***********************************************************************/
-void ResetNullValues(CATPARM *cap)
+static void ResetNullValues(CATPARM *cap)
{
int i, n, ncol;
PCOLRES crp;
@@ -230,11 +229,7 @@ void ResetNullValues(CATPARM *cap)
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
char *colpat, bool info)
{
- static int dbtype[] = {DB_CHAR, DB_CHAR, DB_CHAR,
- DB_CHAR, DB_SHORT, DB_CHAR,
- DB_INT, DB_INT, DB_SHORT,
- DB_SHORT, DB_SHORT, DB_CHAR};
- static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
+ static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT,
TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
@@ -285,7 +280,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_COLUMNS,
- dbtype, buftyp, fldtyp, length, true, true);
+ buftyp, fldtyp, length, true, true);
if (info) // Info table
return qrp;
@@ -396,7 +391,6 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
/*************************************************************************/
PQRYRES ODBCDataSources(PGLOBAL g, bool info)
{
- static int dbtype[] = {DB_CHAR, DB_CHAR};
static int buftyp[] = {TYPE_STRING, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NAME, FLD_REM};
static unsigned int length[] = {0, 256};
@@ -425,7 +419,7 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info)
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC,
- dbtype, buftyp, fldtyp, length, true, true);
+ buftyp, fldtyp, length, true, true);
/************************************************************************/
/* Now get the results into blocks. */
@@ -446,7 +440,6 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info)
/*************************************************************************/
PQRYRES ODBCDrivers(PGLOBAL g, bool info)
{
- static int dbtype[] = {DB_CHAR, DB_CHAR};
static int buftyp[] = {TYPE_STRING, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NAME, FLD_REM};
static unsigned int length[] = {128, 256};
@@ -471,7 +464,7 @@ PQRYRES ODBCDrivers(PGLOBAL g, bool info)
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_DRIVER,
- dbtype, buftyp, fldtyp, length, true, true);
+ buftyp, fldtyp, length, true, true);
/************************************************************************/
/* Now get the results into blocks. */
@@ -492,8 +485,7 @@ PQRYRES ODBCDrivers(PGLOBAL g, bool info)
/***********************************************************************/
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info)
{
- static int dbtype[] = {DB_CHAR, DB_CHAR, DB_CHAR, DB_CHAR, DB_CHAR};
- static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
+ static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_STRING, TYPE_STRING};
static XFLD fldtyp[] = {FLD_QUALIF, FLD_OWNER, FLD_NAME,
FLD_TYPE, FLD_REM};
@@ -536,7 +528,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info)
/************************************************************************/
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
- qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES, dbtype, buftyp,
+ qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES, buftyp,
fldtyp, length, true, true);
if (info)
@@ -579,8 +571,6 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info)
/**************************************************************************/
PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table)
{
- static int dbtype[] = {DB_CHAR, DB_CHAR, DB_CHAR,
- DB_CHAR, DB_SHORT, DB_CHAR};
static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_STRING, TYPE_SHORT, TYPE_STRING};
static unsigned int length[] = {0, 0, 0, 0, 6, 128};
@@ -623,7 +613,7 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table)
/* Allocate the structure used to refer to the result set. */
/************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_PKEY,
- dbtype, buftyp, NULL, length, true, true);
+ buftyp, NULL, length, true, true);
if (trace)
htrc("Getting pkey results ncol=%d\n", qrp->Nbcol);
@@ -662,9 +652,6 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table)
PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat,
int un, int acc)
{
- static int dbtype[] = {DB_CHAR, DB_CHAR, DB_CHAR, DB_SHORT, DB_CHAR,
- DB_CHAR, DB_SHORT, DB_SHORT, DB_CHAR, DB_CHAR,
- DB_INT, DB_INT, DB_CHAR};
static int buftyp[] = {TYPE_STRING,
TYPE_STRING, TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_STRING,
@@ -708,7 +695,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat,
/* Allocate the structure used to refer to the result set. */
/************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_STAT,
- dbtype, buftyp, NULL, length, true, true);
+ buftyp, NULL, length, true, true);
if (trace)
htrc("Getting stat results ncol=%d\n", qrp->Nbcol);
diff --git a/storage/connect/osutil.c b/storage/connect/osutil.c
index 45c834a4cfc..1b7332357e6 100644
--- a/storage/connect/osutil.c
+++ b/storage/connect/osutil.c
@@ -142,10 +142,12 @@ my_bool CloseFileHandle(HANDLE h)
return (close(h)) ? TRUE : FALSE;
} /* end of CloseFileHandle */
+#if 0
void Sleep(DWORD time)
{
//FIXME: TODO
} /* end of Sleep */
+#endif
int GetLastError()
{
@@ -213,6 +215,7 @@ int _isatty(int fileNo)
return isatty(fileNo);
} /* end of _isatty */
+#if 0
/* This function is ridiculous and should be revisited */
DWORD FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId,
DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, ...)
@@ -227,5 +230,6 @@ DWORD FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId,
strncpy(lpBuffer, buff, nSize);
return min(n, nSize);
} /* end of FormatMessage */
+#endif
#endif // UNIX
diff --git a/storage/connect/osutil.h b/storage/connect/osutil.h
index 440373dd7a1..63a3e18084c 100644
--- a/storage/connect/osutil.h
+++ b/storage/connect/osutil.h
@@ -32,44 +32,6 @@ char *_fullpath(char *absPath, const char *relPath, size_t maxLength);
BOOL MessageBeep(uint);
unsigned long _filelength(int fd);
-void PROFILE_Close(LPCSTR filename);
-
-int GetPrivateProfileString(
- LPCTSTR lpAppName, // section name
- LPCTSTR lpKeyName, // key name
- LPCTSTR lpDefault, // default string
- LPTSTR lpReturnedString, // destination buffer
- int nSize, // size of destination buffer
- LPCTSTR lpFileName // initialization file name
- );
-
-uint GetPrivateProfileInt(
- LPCTSTR lpAppName, // section name
- LPCTSTR lpKeyName, // key name
- INT nDefault, // return value if key name not found
- LPCTSTR lpFileName // initialization file name
- );
-
-BOOL WritePrivateProfileString(
- LPCTSTR lpAppName, // section name
- LPCTSTR lpKeyName, // key name
- LPCTSTR lpString, // string to add
- LPCTSTR lpFileName // initialization file
- );
-
-int GetPrivateProfileSection(
- LPCTSTR lpAppName, // section name
- LPTSTR lpReturnedString, // return buffer
- int nSize, // size of return buffer
- LPCTSTR lpFileName // initialization file name
- );
-
-BOOL WritePrivateProfileSection(
- LPCTSTR lpAppName, // section name
- LPCTSTR lpString, // data
- LPCTSTR lpFileName // file name
- );
-
PSZ strupr(PSZ s);
PSZ strlwr(PSZ s);
@@ -90,12 +52,14 @@ typedef __int64 FILEPOS;
#define XSTR(x) ((x)?(x):"<null>")
+
#ifdef __cplusplus
extern "C" {
#endif
-
+my_bool CloseFileHandle(HANDLE h);
#ifdef __cplusplus
}
#endif
+
#endif /* __OSUTIL_H__ */
diff --git a/storage/connect/plgcnx.h b/storage/connect/plgcnx.h
index 33b0ba64edc..7ce72b45268 100644
--- a/storage/connect/plgcnx.h
+++ b/storage/connect/plgcnx.h
@@ -50,17 +50,6 @@ enum RCODE {RC_OK = 0, /* No error return code */
#endif // !RC_OK_DEFINED
/**************************************************************************/
-/* Data types. */
-/**************************************************************************/
-enum XDBTYPE {DB_ERROR = 0, /* Unknown or wrong type */
- DB_STRING = 1, /* Null terminated string */
- DB_CHAR = 2, /* Character array */
- DB_SHORT = 3, /* Used by some catalog functions */
- DB_INT = 4, /* Long integer array */
- DB_DOUBLE = 5, /* Double float array */
- DB_DATE = 6}; /* Datetime value array */
-
-/**************************************************************************/
/* Index of info values within the info int integer array. */
/**************************************************************************/
enum INFO {INDX_RC, /* Index of PlugDB return code field */
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h
index 611b0067e18..919f3452a4d 100644
--- a/storage/connect/plgdbsem.h
+++ b/storage/connect/plgdbsem.h
@@ -24,8 +24,8 @@
#define DOS_BUFF_LEN 100 /* Number of lines in binary file buffer */
#undef DOMAIN /* For Unix version */
-enum BLKTYP {TYPE_TABLE = 50, /* Table Name/Correl Block */
- TYPE_COLUMN = 51, /* Column Name/Correl Block */
+enum BLKTYP {TYPE_TABLE = 50, /* Table Name/Srcdef/... Block */
+ TYPE_COLUMN = 51, /* Column Name/Qualifier Block */
// TYPE_OPVAL = 52, /* Operator value (OPVAL) */
TYPE_TDB = 53, /* Table Description Block */
TYPE_COLBLK = 54, /* Column Description Block */
@@ -69,12 +69,14 @@ enum TABTYPE {TAB_UNDEF = 0, /* Table of undefined type */
TAB_WMI = 14, /* WMI tables (Windows only) */
TAB_TBL = 15, /* Collection of CONNECT tables */
TAB_OEM = 16, /* OEM implemented table */
- TAB_CATLG = 17, /* Catalog table */
- TAB_PLG = 18, /* PLG NIY */
- TAB_PIVOT = 19, /* PIVOT NIY */
- TAB_JCT = 20, /* Junction tables NIY */
- TAB_DMY = 21, /* DMY Dummy tables NIY */
- TAB_NIY = 22}; /* Table not implemented yet */
+ TAB_XCL = 17, /* XCL table */
+ TAB_OCCUR = 18, /* OCCUR table */
+ TAB_PRX = 19, /* Proxy (catalog) table */
+ TAB_PLG = 20, /* PLG NIY */
+ TAB_PIVOT = 21, /* PIVOT NIY */
+ TAB_JCT = 22, /* Junction tables NIY */
+ TAB_DMY = 23, /* DMY Dummy tables NIY */
+ TAB_NIY = 24}; /* Table not implemented yet */
enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_ROWID = 1, /* ROWID type (special column) */
@@ -511,12 +513,12 @@ typedef struct _colres {
PVBLK Kdata; /* Column block of values */
char *Nulls; /* Column null value array */
int Type; /* Internal type */
- int DBtype; /* Data type */
int Datasize; /* Overall data size */
int Ncol; /* Column number */
int Clen; /* Data individual internal size */
int Length; /* Data individual print length */
int Prec; /* Precision */
+ int Flag; /* Flag option value */
XFLD Fld; /* Type of field info */
} COLRES;
@@ -543,7 +545,7 @@ int ExtractDate(char *, PDTP, int, int val[6]);
/* Allocate the result structure that will contain result data. */
/**************************************************************************/
PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
- int *dbtype, int *buftyp, XFLD *fldtyp,
+ int *buftyp, XFLD *fldtyp,
unsigned int *length, bool blank, bool nonull);
/***********************************************************************/
@@ -576,5 +578,6 @@ DllExport void NewPointer(PTABS, void *, void *);
FILE *global_fopen(GLOBAL *g, int msgid, const char *path, const char *mode);
int global_open(GLOBAL *g, int msgid, const char *filename, int flags);
int global_open(GLOBAL *g, int msgid, const char *filename, int flags, int mode);
+DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR name, LPCSTR dir);
bool PushWarning(PGLOBAL, PTDBASE);
diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp
index 6d1e502945b..73b468c9209 100644
--- a/storage/connect/plgdbutl.cpp
+++ b/storage/connect/plgdbutl.cpp
@@ -67,6 +67,7 @@
#include "xtable.h" // header of TBX, TDB and TDBASE classes
#include "tabcol.h" // header of XTAB and COLUMN classes
#include "valblk.h"
+#include "rcmsg.h"
/***********************************************************************/
/* Macro or external routine definition */
@@ -129,7 +130,6 @@ void CloseXMLFile(PGLOBAL, PFBLOCK, bool);
void CloseXML2File(PGLOBAL, PFBLOCK, bool);
#endif // LIBXML2_SUPPORT
-extern "C" int GetRcString(int id, char *buf, int bufsize);
/***********************************************************************/
/* Routines for file IO with error reporting to g->Message */
@@ -270,7 +270,7 @@ void ptrc(char const *fmt, ...)
/* Allocate the result structure that will contain result data. */
/**************************************************************************/
PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
- int *dbtype, int *buftyp, XFLD *fldtyp,
+ int *buftyp, XFLD *fldtyp,
unsigned int *length, bool blank, bool nonull)
{
char cname[NAM_LEN+1];
@@ -298,13 +298,13 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
*pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
crp = *pcrp;
pcrp = &crp->Next;
+ memset(crp, 0, sizeof(COLRES));
crp->Colp = NULL;
crp->Ncol = ++qrp->Nbcol;
crp->Type = buftyp[i];
crp->Length = length[i];
crp->Clen = GetTypeSize(crp->Type, length[i]);
crp->Prec = 0;
- crp->DBtype = dbtype[i];
if (ids > 0) {
#if defined(XMSG)
@@ -520,6 +520,7 @@ bool PlgSetXdbPath(PGLOBAL g, PSZ dbname, PSZ dbpath,
/* Extract from a path name the required component. */
/* This function assumes there is enough space in the buffer. */
/***********************************************************************/
+#if 0
char *ExtractFromPath(PGLOBAL g, char *pBuff, char *FileName, OPVAL op)
{
char *drive = NULL, *direc = NULL, *fname = NULL, *ftype = NULL;
@@ -540,13 +541,14 @@ char *ExtractFromPath(PGLOBAL g, char *pBuff, char *FileName, OPVAL op)
_splitpath(FileName, drive, direc, fname, ftype);
return pBuff;
} // end of PlgExtractFromPath
+#endif
/***********************************************************************/
/* Check the occurence and matching of a pattern against a string. */
/* Because this function is only used for catalog name checking, */
/* it must be case insensitive. */
/***********************************************************************/
-bool PlugCheckPattern(PGLOBAL g, LPCSTR string, LPCSTR pat)
+static bool PlugCheckPattern(PGLOBAL g, LPCSTR string, LPCSTR pat)
{
if (pat && strlen(pat)) {
// This leaves 512 bytes (MAX_STR / 2) for each components
diff --git a/storage/connect/plugutil.c b/storage/connect/plugutil.c
index 693ae96cf52..e8098bb2512 100644
--- a/storage/connect/plugutil.c
+++ b/storage/connect/plugutil.c
@@ -107,7 +107,7 @@ ACTIVITY defActivity = { /* Describes activity and language */
#endif // XMSG || NEWMSG
#if defined(UNIX) || defined(UNIV_LINUX)
-int GetRcString(int id, char *buf, int bufsize);
+#include "rcmsg.h"
#endif // UNIX
/**************************************************************************/
@@ -147,6 +147,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
if (!(g = malloc(sizeof(GLOBAL)))) {
fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL));
+ return NULL;
} else {
g->Sarea_Size = worksize;
g->Trace = 0;
@@ -180,7 +181,9 @@ int PlugExit(PGLOBAL g)
if (!g)
return rc;
- free(g->Sarea);
+ if (g->Sarea)
+ free(g->Sarea);
+
free(g);
return rc;
} /* end of PlugExit */
@@ -216,11 +219,23 @@ LPSTR PlugRemoveType(LPSTR pBuff, LPCSTR FileName)
return pBuff;
} // end of PlugRemoveType
+
+BOOL PlugIsAbsolutePath(LPCSTR path)
+{
+#if defined(WIN32)
+ return ((path[0] >= 'a' && path[0] <= 'z') ||
+ (path[0] >= 'A' && path[0] <= 'Z')) && path[1] == ':';
+#else
+ return path[0] == '/';
+#endif
+}
+
+
/***********************************************************************/
/* Set the full path of a file relatively to a given path. */
/* Note: this routine is not really implemented for Unix. */
/***********************************************************************/
-LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR FileName, LPCSTR defpath)
+LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
{
char newname[_MAX_PATH];
char direc[_MAX_DIR], defdir[_MAX_DIR];
@@ -237,6 +252,22 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR FileName, LPCSTR defpath)
return pBuff;
} // endif
+ if (PlugIsAbsolutePath(FileName))
+ {
+ strcpy(pBuff, FileName); // FileName includes absolute path
+ return pBuff;
+ } // endif
+
+ if (strcmp(prefix, ".") && !PlugIsAbsolutePath(defpath))
+ {
+ char tmp[_MAX_PATH];
+ int len= snprintf(tmp, sizeof(tmp) - 1, "%s%s%s",
+ prefix, defpath, FileName);
+ memcpy(pBuff, tmp, (size_t) len);
+ pBuff[len]= '\0';
+ return pBuff;
+ }
+
_splitpath(FileName, drive, direc, fname, ftype);
_splitpath(defpath, defdrv, defdir, NULL, NULL);
@@ -491,9 +522,10 @@ void *MakePtr(void *memp, OFFSET offset)
/***********************************************************************/
/* This routine makes an offset from a pointer new format. */
/***********************************************************************/
+#if 0
OFFSET MakeOff(void *memp, void *ptr)
{
return ((!ptr) ? 0 : (OFFSET)((char *)ptr - (char *)memp));
} /* end of MakeOff */
-
+#endif
/*--------------------- End of PLUGUTIL program -----------------------*/
diff --git a/storage/connect/rcmsg.c b/storage/connect/rcmsg.c
index e1a71cde9c6..0c63fd55242 100644
--- a/storage/connect/rcmsg.c
+++ b/storage/connect/rcmsg.c
@@ -14,6 +14,7 @@
/***********************************************************************/
#include <stdio.h>
#include "resource.h"
+#include "rcmsg.h"
char *GetMsgid(int id)
{
diff --git a/storage/connect/rcmsg.h b/storage/connect/rcmsg.h
new file mode 100644
index 00000000000..b22e77f5175
--- /dev/null
+++ b/storage/connect/rcmsg.h
@@ -0,0 +1,15 @@
+#ifndef __RCMSG_H__
+#define __RCMSG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *GetMsgid(int id);
+int GetRcString(int id, char *buf, int bufsize);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __RCMSG_H__ */
diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp
index 77f2f43ec31..8525fd09cbc 100644
--- a/storage/connect/reldef.cpp
+++ b/storage/connect/reldef.cpp
@@ -90,11 +90,9 @@ TABDEF::TABDEF(void)
/***********************************************************************/
bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am)
{
-//char buf[8];
int poff = 0;
- void *memp = cat->Descp;
- Name = (PSZ)PlugSubAlloc(g, memp, strlen(name) + 1);
+ Name = (PSZ)PlugSubAlloc(g, NULL, strlen(name) + 1);
strcpy(Name, name);
Cat = cat;
Catfunc = GetFuncID(Cat->GetStringCatInfo(g, "Catfunc", NULL));
@@ -127,7 +125,6 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
PTABDEF xdefp;
XGETDEF getdef = NULL;
PCATLG cat = Cat;
- void *memp = cat->Descp;
#if defined(WIN32)
// Is the DLL already loaded?
@@ -189,7 +186,7 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
sprintf(g->Message, MSG(DEF_ALLOC_ERROR), Subtype);
// Get the table definition block
- if (!(xdefp = getdef(g, memp)))
+ if (!(xdefp = getdef(g, NULL)))
return NULL;
// Have the external class do its complete definition
@@ -223,15 +220,13 @@ bool OEMDEF::DeleteTableFile(PGLOBAL g)
/***********************************************************************/
bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
- void *memp = Cat->Descp;
-
Module = Cat->GetStringCatInfo(g, "Module", "");
Subtype = Cat->GetStringCatInfo(g, "Subtype", Module);
if (!*Module)
Module = Subtype;
- Desc = (char*)PlugSubAlloc(g, memp, strlen(Module)
+ Desc = (char*)PlugSubAlloc(g, NULL, strlen(Module)
+ strlen(Subtype) + 3);
sprintf(Desc, "%s(%s)", Module, Subtype);
return false;
@@ -304,7 +299,7 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode)
else
txfp = new(g) DOSFAM(defp);
- } else if (rfm == RECFM_FIX || rfm == RECFM_FIX) {
+ } else if (rfm == RECFM_FIX || rfm == RECFM_BIN) {
if (map)
txfp = new(g) MPXFAM(defp);
else
diff --git a/storage/connect/tabcol.cpp b/storage/connect/tabcol.cpp
index f0e010291c3..9af52043f0c 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.6 */
+/* Name: TABCOL.CPP Version 2.7 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2013 */
/* */
/* This file contains the PlugDB++ XTAB, COLUMN and XORDER methods. */
/***********************************************************************/
@@ -23,18 +23,18 @@
#include "tabcol.h"
/***********************************************************************/
-/* XTAB public constructor (in which Correl defaults to Name). */
+/* XTAB public constructor. */
/***********************************************************************/
-XTAB::XTAB(LPCSTR name, LPCSTR correl) : Name(name)
+XTAB::XTAB(LPCSTR name, LPCSTR srcdef) : Name(name)
{
Next = NULL;
To_Tdb = NULL;
- Correl = (correl) ? correl : name;
+ Srcdef = srcdef;
Creator = NULL;
Qualifier = NULL;
#ifdef DEBTRACE
- htrc(" making new TABLE %s %s\n", Name, Correl);
+ htrc(" making new TABLE %s %s\n", Name, Srcdef);
#endif
} // end of XTAB constructor
@@ -45,12 +45,12 @@ XTAB::XTAB(PTABLE tp) : Name(tp->Name)
{
Next = NULL;
To_Tdb = NULL;
- Correl = tp->Correl;
+ Srcdef = tp->Srcdef;
Creator = tp->Creator;
Qualifier = tp->Qualifier;
#ifdef DEBTRACE
- htrc(" making copy TABLE %s %s\n", Name, Correl);
+ htrc(" making copy TABLE %s %s\n", Name, Srcdef);
#endif
} // end of XTAB constructor
@@ -83,7 +83,7 @@ void XTAB::Print(PGLOBAL g, FILE *f, uint n)
for (PTABLE tp = this; tp; tp = tp->Next) {
fprintf(f, "%sTABLE: %s.%s %s\n",
- m, SVP(tp->Creator), tp->Name, SVP(tp->Correl));
+ m, SVP(tp->Creator), tp->Name, SVP(tp->Srcdef));
PlugPutOut(g, f, TYPE_TDB, tp->To_Tdb, n + 2);
} /* endfor tp */
@@ -101,7 +101,7 @@ void XTAB::Print(PGLOBAL g, char *ps, uint z)
for (PTABLE tp = this; tp && n > 0; tp = tp->Next) {
i = sprintf(buf, "TABLE: %s.%s %s To_Tdb=%p ",
- SVP(tp->Creator), tp->Name, SVP(tp->Correl), tp->To_Tdb);
+ SVP(tp->Creator), tp->Name, SVP(tp->Srcdef), tp->To_Tdb);
strncat(ps, buf, n);
n -= i;
} // endif tp
diff --git a/storage/connect/tabcol.h b/storage/connect/tabcol.h
index 5cc2050f872..c5ebfdbb10d 100644
--- a/storage/connect/tabcol.h
+++ b/storage/connect/tabcol.h
@@ -1,7 +1,7 @@
/*************** TabCol H Declares Source Code File (.H) ***************/
-/* Name: TABCOL.H Version 2.7 */
+/* Name: TABCOL.H Version 2.8 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2013 */
/* */
/* This file contains the XTAB, COLUMN and XORDER class definitions. */
/***********************************************************************/
@@ -15,22 +15,24 @@
/***********************************************************************/
/* Definition of class XTAB with all its method functions. */
/***********************************************************************/
- class DllExport XTAB: public BLOCK { // Table Name-Owner-Correl block.
+class DllExport XTAB: public BLOCK { // Table Name-Owner-Srcdef block.
+ friend class TDBPRX;
+ friend class TDBTBM;
public:
// Constructors
- XTAB(LPCSTR name, LPCSTR correl = NULL);
+ XTAB(LPCSTR name, LPCSTR srcdef = NULL);
XTAB(PTABLE tp);
// Implementation
PTABLE GetNext(void) {return Next;}
PTDB GetTo_Tdb(void) {return To_Tdb;}
LPCSTR GetName(void) {return Name;}
- LPCSTR GetCorrel(void) {return Correl;}
+ LPCSTR GetSrc(void) {return Srcdef;}
LPCSTR GetCreator(void) {return Creator;}
LPCSTR GetQualifier(void) {return Qualifier;}
void SetTo_Tdb(PTDB tdbp) {To_Tdb = tdbp;}
void SetName(LPCSTR name) {Name = name;}
- void SetCorrel(LPCSTR correl) {Correl = correl;}
+ void SetSrc(LPCSTR srcdef) {Srcdef = srcdef;}
void SetCreator(LPCSTR crname) {Creator = crname;}
void SetQualifier(LPCSTR qname) {Qualifier = qname;}
@@ -43,8 +45,8 @@
// Members
PTABLE Next; // Points to next table in chain
PTDB To_Tdb; // Points to Table description Block
- LPCSTR Name; // Table name (can be changed by LNA and PLG)
- LPCSTR Correl; // Correlation name
+ LPCSTR Name; // Table name
+ LPCSTR Srcdef; // Table Source definition
LPCSTR Creator; // Creator name
LPCSTR Qualifier; // Qualifier name
}; // end of class XTAB
@@ -85,7 +87,6 @@ class DllExport COLUMN: public XOBJECT { // Column Name/Qualifier block.
virtual bool Eval(PGLOBAL) {assert(false); return true;}
virtual int CheckSpcCol(PTDB, int) {assert(false); return 2;}
virtual bool CheckSort(PTDB) {assert(false); return false;}
- virtual void MarkCol(ushort) {assert(false);}
private:
// Members
diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp
index 51631107f6e..860a1304a14 100644
--- a/storage/connect/tabfmt.cpp
+++ b/storage/connect/tabfmt.cpp
@@ -78,8 +78,6 @@ extern "C" int trace;
PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
int hdr, int mxr, bool info)
{
- static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
- DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME,
@@ -87,7 +85,7 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
static unsigned int length[] = {6, 6, 8, 10, 10, 6};
char *p, *colname[MAXCOL], dechar, filename[_MAX_PATH], buf[4096];
int i, imax, hmax, n, nerr, phase, blank, digit, dec, type;
- int ncol = sizeof(dbtype) / sizeof(int);
+ int ncol = sizeof(buftyp) / sizeof(int);
int num_read = 0, num_max = 10000000; // Statistics
int len[MAXCOL], typ[MAXCOL], prc[MAXCOL];
FILE *infile;
@@ -341,7 +339,7 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
/* Allocate the structures used to refer to the result set. */
/*********************************************************************/
qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3,
- dbtype, buftyp, fldtyp, length, true, false);
+ buftyp, fldtyp, length, true, false);
qrp->Nblin = imax;
if (info)
@@ -1090,7 +1088,12 @@ bool TDBFMT::OpenDB(PGLOBAL g)
{
Linenum = 0;
- if (Use != USE_OPEN && (Columns || Mode == MODE_UPDATE)) {
+ if (Mode == MODE_INSERT || Mode == MODE_UPDATE) {
+ sprintf(g->Message, MSG(FMT_WRITE_NIY), "FMT");
+ return true; // NIY
+ } // endif Mode
+
+ if (Use != USE_OPEN && Columns) {
// Make the formats used to read records
PSZ pfm;
int i, n;
@@ -1098,17 +1101,12 @@ bool TDBFMT::OpenDB(PGLOBAL g)
PCOLDEF cdp;
PDOSDEF tdp = (PDOSDEF)To_Def;
-// if (Mode != MODE_UPDATE) {
- for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next)
- if (!colp->IsSpecial()) // Not a pseudo column
- Fields = max(Fields, (int)colp->Fldnum);
-
- if (Columns)
- Fields++; // Fldnum was 0 based
+ for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next)
+ if (!colp->IsSpecial()) // Not a pseudo column
+ Fields = max(Fields, (int)colp->Fldnum);
-// } else
-// for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
-// Fields++;
+ if (Columns)
+ Fields++; // Fldnum was 0 based
To_Fld = PlugSubAlloc(g, NULL, Lrecl + 1);
FldFormat = (PSZ*)PlugSubAlloc(g, NULL, sizeof(PSZ) * Fields);
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index 7b38cc8ab1b..1a19b4cbf33 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -57,12 +57,14 @@
#include "reldef.h"
#include "tabmysql.h"
#include "valblk.h"
+#include "tabutil.h"
#if defined(_CONSOLE)
void PrintResult(PGLOBAL, PSEM, PQRYRES);
#endif // _CONSOLE
extern "C" int trace;
+extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
/* -------------- Implementation of the MYSQLDEF class --------------- */
@@ -75,9 +77,11 @@ MYSQLDEF::MYSQLDEF(void)
Hostname = NULL;
Database = NULL;
Tabname = NULL;
+ Srcdef = NULL;
Username = NULL;
Password = NULL;
Portnumber = 0;
+ Isview = FALSE;
Bind = FALSE;
Delayed = FALSE;
} // end of MYSQLDEF constructor
@@ -243,10 +247,13 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url)
if ((sport = strchr(Hostname, ':')))
*sport++ = 0;
- Portnumber = (sport && sport[0]) ? atoi(sport) : MYSQL_PORT;
+ Portnumber = (sport && sport[0]) ? atoi(sport) : mysqld_port;
+
+ if (Username[0] == 0)
+ Username = Cat->GetStringCatInfo(g, "User", "*");
if (Hostname[0] == 0)
- Hostname = "localhost";
+ Hostname = Cat->GetStringCatInfo(g, "Host", "localhost");
if (!Database || !*Database)
Database = Cat->GetStringCatInfo(g, "Database", "*");
@@ -276,20 +283,39 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Desc = "MySQL Table";
- if (!url || !*url) {
- // Not using the connection URL
- Hostname = Cat->GetStringCatInfo(g, "Host", "localhost");
+ if (stricmp(am, "MYPRX")) {
+ // Normal case of specific MYSQL table
+ if (!url || !*url) {
+ // Not using the connection URL
+ Hostname = Cat->GetStringCatInfo(g, "Host", "localhost");
+ Database = Cat->GetStringCatInfo(g, "Database", "*");
+ Tabname = Cat->GetStringCatInfo(g, "Name", Name); // Deprecated
+ Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname);
+ Username = Cat->GetStringCatInfo(g, "User", "*");
+ Password = Cat->GetStringCatInfo(g, "Password", NULL);
+ Portnumber = Cat->GetIntCatInfo("Port", mysqld_port);
+ } else if (ParseURL(g, url))
+ return TRUE;
+
+ Bind = !!Cat->GetIntCatInfo("Bind", 0);
+ Delayed = !!Cat->GetIntCatInfo("Delayed", 0);
+ } else {
+ // MYSQL access from a PROXY table, not using URL
Database = Cat->GetStringCatInfo(g, "Database", "*");
- Tabname = Cat->GetStringCatInfo(g, "Name", Name); // Deprecated
- Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname);
- Username = Cat->GetStringCatInfo(g, "User", "root");
+ Tabname = Name;
+ Isview = Cat->GetBoolCatInfo("View", FALSE);
+
+ // We must get connection parms from the calling table
+ Remove_tshp(Cat);
+ Hostname = Cat->GetStringCatInfo(g, "Host", "localhost");
+ Username = Cat->GetStringCatInfo(g, "User", "*");
Password = Cat->GetStringCatInfo(g, "Password", NULL);
- Portnumber = Cat->GetIntCatInfo("Port", MYSQL_PORT);
- } else if (ParseURL(g, url))
- return TRUE;
+ Portnumber = Cat->GetIntCatInfo("Port", mysqld_port);
+ } // endif am
+
+ if ((Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL)))
+ Isview = TRUE;
- Bind = !!Cat->GetIntCatInfo("Bind", 0);
- Delayed = !!Cat->GetIntCatInfo("Delayed", 0);
return FALSE;
} // end of DefineAM
@@ -316,18 +342,22 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
Host = tdp->GetHostname();
Database = tdp->GetDatabase();
Tabname = tdp->GetTabname();
+ Srcdef = tdp->GetSrcdef();
User = tdp->GetUsername();
Pwd = tdp->GetPassword();
Port = tdp->GetPortnumber();
+ Isview = tdp->Isview;
Prep = tdp->Bind;
Delayed = tdp->Delayed;
} else {
Host = NULL;
Database = NULL;
Tabname = NULL;
+ Srcdef = NULL;
User = NULL;
Pwd = NULL;
Port = 0;
+ Isview = FALSE;
Prep = FALSE;
Delayed = FALSE;
} // endif tdp
@@ -347,9 +377,11 @@ TDBMYSQL::TDBMYSQL(PGLOBAL g, PTDBMY tdbp) : TDBASE(tdbp)
Host = tdbp->Host;
Database = tdbp->Database;
Tabname = tdbp->Tabname;
+ Srcdef = tdbp->Srcdef;
User = tdbp->User;
Pwd = tdbp->Pwd;
Port = tdbp->Port;
+ Isview = tdbp->Isview;
Prep = tdbp->Prep;
Delayed = tdbp->Delayed;
Bind = NULL;
@@ -395,55 +427,54 @@ PCOL TDBMYSQL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/
bool TDBMYSQL::MakeSelect(PGLOBAL g)
{
- char *colist;
char *tk = "`";
- int len = 0, ncol = 0, rank = 0;
+ int rank = 0;
bool b = FALSE;
PCOL colp;
- PDBUSER dup = PlgGetUser(g);
+//PDBUSER dup = PlgGetUser(g);
if (Query)
return FALSE; // already done
- for (colp = Columns; colp; colp = colp->GetNext())
- ncol++;
+ if (Srcdef) {
+ Query = Srcdef;
+ return false;
+ } // endif Srcdef
- if (ncol) {
- colist = (char*)PlugSubAlloc(g, NULL, (NAM_LEN + 4) * ncol);
- *colist = '\0';
+ //Find the address of the suballocated query
+ Query = (char*)PlugSubAlloc(g, NULL, 0);
+ strcpy(Query, "SELECT ");
+ if (Columns) {
for (colp = Columns; colp; colp = colp->GetNext())
if (colp->IsSpecial()) {
strcpy(g->Message, MSG(NO_SPEC_COL));
return TRUE;
} else {
if (b)
- strcat(colist, ", ");
+ strcat(Query, ", ");
else
b = TRUE;
- strcat(strcat(strcat(colist, tk), colp->GetName()), tk);
+ strcat(strcat(strcat(Query, tk), colp->GetName()), tk);
((PMYCOL)colp)->Rank = rank++;
} // endif colp
} else {
- // ncol == 0 can occur for queries such as Query count(*) from...
- // for which we will count the rows from Query '*' from...
+ // ncol == 0 can occur for views or queries such as
+ // Query count(*) from... for which we will count the rows from
+ // Query '*' from...
// (the use of a char constant minimize the result storage)
- colist = (char*)PlugSubAlloc(g, NULL, 2);
- strcpy(colist, "'*'");
+ strcat(Query, (Isview) ? "*" : "'*'");
} // endif ncol
- // Below 32 is space to contain extra stuff
- len += (strlen(colist) + strlen(Tabname) + 32);
- len += (To_Filter ? strlen(To_Filter) + 7 : 0);
- Query = (char*)PlugSubAlloc(g, NULL, len);
- strcat(strcpy(Query, "SELECT "), colist);
strcat(strcat(strcat(strcat(Query, " FROM "), tk), Tabname), tk);
if (To_Filter)
strcat(strcat(Query, " WHERE "), To_Filter);
+ // Now we know how much to suballocate
+ PlugSubAlloc(g, NULL, strlen(Query) + 1);
return FALSE;
} // end of MakeSelect
@@ -728,7 +759,7 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
/* Table already open, just replace it at its beginning. */
/*******************************************************************/
Myc.Rewind();
- return FALSE;
+ return false;
} // endif use
/*********************************************************************/
@@ -740,7 +771,7 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
/*********************************************************************/
if (!Myc.Connected()) {
if (Myc.Open(g, Host, Database, User, Pwd, Port))
- return TRUE;
+ return true;
} // endif Connected
@@ -751,7 +782,24 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
if (!MakeSelect(g))
m_Rc = Myc.ExecSQL(g, Query);
+#if 0
+ if (!Myc.m_Res || !Myc.m_Fields) {
+ sprintf(g->Message, "%s result", (Myc.m_Res) ? "Void" : "No");
+ Myc.Close();
+ return true;
+ } // endif m_Res
+#endif // 0
+
+ if (!m_Rc && Srcdef)
+ if (SetColumnRanks(g))
+ return true;
+
} else if (Mode == MODE_INSERT) {
+ if (Srcdef) {
+ strcpy(g->Message, "No insert into anonym views");
+ return true;
+ } // endif Srcdef
+
if (!MakeInsert(g)) {
#if defined(MYSQL_PREPARED_STATEMENTS)
int n = (Prep) ? Myc.PrepareSQL(g, Query) : Nparm;
@@ -804,6 +852,78 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
} // end of OpenDB
/***********************************************************************/
+/* Set the rank of columns in the result set. */
+/***********************************************************************/
+bool TDBMYSQL::SetColumnRanks(PGLOBAL g)
+ {
+ for (PCOL colp = Columns; colp; colp = colp->GetNext())
+ if (((PMYCOL)colp)->FindRank(g))
+ return TRUE;
+
+ return FALSE;
+ } // end of SetColumnRanks
+
+/***********************************************************************/
+/* Called by Parent table to make the columns of a View. */
+/***********************************************************************/
+PCOL TDBMYSQL::MakeFieldColumn(PGLOBAL g, char *name)
+ {
+ int n;
+ MYSQL_FIELD *fld;
+ PCOL cp, colp = NULL;
+
+ for (n = 0; n < Myc.m_Fields; n++) {
+ fld = &Myc.m_Res->fields[n];
+
+ if (!stricmp(name, fld->name)) {
+ colp = new(g) MYSQLCOL(fld, this, n);
+
+ if (colp->InitValue(g))
+ return NULL;
+
+ if (!Columns)
+ Columns = colp;
+ else for (cp = Columns; cp; cp = cp->GetNext())
+ if (!cp->GetNext()) {
+ cp->SetNext(colp);
+ break;
+ } // endif Next
+
+ break;
+ } // endif name
+
+ } // endfor n
+
+ if (!colp)
+ sprintf(g->Message, "Column %s is not in view", name);
+
+ return colp;
+ } // end of MakeFieldColumn
+
+/***********************************************************************/
+/* Called by Pivot tables to find default column names in a View */
+/* as the name of last field not equal to the passed name. */
+/***********************************************************************/
+char *TDBMYSQL::FindFieldColumn(char *name)
+ {
+ int n;
+ MYSQL_FIELD *fld;
+ char *cp = NULL;
+
+ for (n = Myc.m_Fields - 1; n >= 0; n--) {
+ fld = &Myc.m_Res->fields[n];
+
+ if (!name || stricmp(name, fld->name)) {
+ cp = fld->name;
+ break;
+ } // endif name
+
+ } // endfor n
+
+ return cp;
+ } // end of FindFieldColumn
+
+/***********************************************************************/
/* Data Base read routine for MYSQL access method. */
/***********************************************************************/
int TDBMYSQL::ReadDB(PGLOBAL g)
@@ -916,7 +1036,7 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
tdbp->SetColumns(this);
} // endif cprec
- // Set additional Dos access method information for column.
+ // Set additional MySQL access method information for column.
Long = cdp->GetLong();
Bind = NULL;
To_Val = NULL;
@@ -929,6 +1049,33 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
} // end of MYSQLCOL constructor
/***********************************************************************/
+/* MYSQLCOL public constructor. */
+/***********************************************************************/
+MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am)
+ : COLBLK(NULL, tdbp, i)
+ {
+ Name = fld->name;
+ Opt = 0;
+ Long = fld->length;
+ Buf_Type = MYSQLtoPLG(fld->type);
+ strcpy(Format.Type, GetFormatType(Buf_Type));
+ Format.Length = Long;
+ Format.Prec = fld->decimals;
+ ColUse = U_P;
+ Nullable = !IS_NOT_NULL(fld->flags);
+
+ // Set additional MySQL access method information for column.
+ Bind = NULL;
+ To_Val = NULL;
+ Slen = 0;
+ Rank = i;
+
+ if (trace)
+ htrc(" making new %sCOL C%d %s at %p\n", am, Index, Name, this);
+
+ } // end of MYSQLCOL constructor
+
+/***********************************************************************/
/* MYSQLCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
@@ -942,6 +1089,24 @@ MYSQLCOL::MYSQLCOL(MYSQLCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
} // end of MYSQLCOL copy constructor
/***********************************************************************/
+/* FindRank: Find the rank of this column in the result set. */
+/***********************************************************************/
+bool MYSQLCOL::FindRank(PGLOBAL g)
+{
+ int n;
+ MYSQLC myc = ((PTDBMY)To_Tdb)->Myc;
+
+ for (n = 0; n < myc.m_Fields; n++)
+ if (!stricmp(Name, myc.m_Res->fields[n].name)) {
+ Rank = n;
+ return false;
+ } // endif Name
+
+ sprintf(g->Message, "Column %s not in result set", Name);
+ return true;
+} // end of FindRank
+
+/***********************************************************************/
/* SetBuffer: prepare a column block for write operation. */
/***********************************************************************/
bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
@@ -1026,11 +1191,6 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
int rc;
PTDBMY tdbp = (PTDBMY)To_Tdb;
- if (trace)
- htrc("MySQL ReadColumn: name=%s\n", Name);
-
- assert (Rank >= 0);
-
/*********************************************************************/
/* If physical fetching of the line was deferred, do it now. */
/*********************************************************************/
@@ -1043,14 +1203,17 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
} else
tdbp->Fetched = TRUE;
- if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank)))
+ if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank))) {
+ if (trace)
+ htrc("MySQL ReadColumn: name=%s buf=%s\n", Name, buf);
+
Value->SetValue_char(buf, Long);
- else {
+ } else {
if (Nullable)
Value->SetNull(true);
Value->Reset(); // Null value
- } // endelse
+ } // endif buf
} // end of ReadColumn
@@ -1098,5 +1261,5 @@ TDBMCL::TDBMCL(PMYDEF tdp) : TDBCAT(tdp)
/***********************************************************************/
PQRYRES TDBMCL::GetResult(PGLOBAL g)
{
- return MyColumns(g, Host, Db, User, Pwd, Tab, NULL, Port, false, false);
+ return MyColumns(g, Host, Db, User, Pwd, Tab, NULL, Port, false);
} // end of GetResult
diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h
index 56d21550df6..24f8c4cdef2 100644
--- a/storage/connect/tabmysql.h
+++ b/storage/connect/tabmysql.h
@@ -30,6 +30,7 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
inline PSZ GetHostname(void) {return Hostname;};
inline PSZ GetDatabase(void) {return Database;};
inline PSZ GetTabname(void) {return Tabname;}
+ inline PSZ GetSrcdef(void) {return Srcdef;}
inline PSZ GetUsername(void) {return Username;};
inline PSZ GetPassword(void) {return Password;};
inline int GetPortnumber(void) {return Portnumber;}
@@ -44,9 +45,11 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
PSZ Hostname; /* Host machine to use */
PSZ Database; /* Database to be used by server */
PSZ Tabname; /* External table name */
+ PSZ Srcdef; /* The source table SQL definition */
PSZ Username; /* User logon name */
PSZ Password; /* Password logon info */
int Portnumber; /* MySQL port number (0 = default) */
+ bool Isview; /* TRUE if this table is a MySQL view */
bool Bind; /* Use prepared statement on insert */
bool Delayed; /* Delayed insert */
}; // end of MYSQLDEF
@@ -72,6 +75,7 @@ class TDBMYSQL : public TDBASE {
virtual int GetProgMax(PGLOBAL g);
virtual void ResetDB(void) {N = 0;}
virtual int RowNumber(PGLOBAL g, bool b = FALSE);
+ virtual bool IsView(void) {return Isview;}
void SetDatabase(LPCSTR db) {Database = (char*)db;}
// Database routines
@@ -83,6 +87,11 @@ class TDBMYSQL : public TDBASE {
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
+ // Specific routines
+ bool SetColumnRanks(PGLOBAL g);
+ PCOL MakeFieldColumn(PGLOBAL g, char *name);
+ PSZ FindFieldColumn(char *name);
+
protected:
// Internal functions
bool MakeSelect(PGLOBAL g);
@@ -99,9 +108,11 @@ class TDBMYSQL : public TDBASE {
char *Pwd; // Password logon info
char *Database; // Database to be used by server
char *Tabname; // External table name
+ char *Srcdef; // The source table SQL definition
char *Query; // Points to SQL query
- char *Qbuf; // Used for not prepared insert
+ char *Qbuf; // Used for not prepared insert
bool Fetched; // True when fetch was done
+ bool Isview; // True if this table is a MySQL view
bool Prep; // Use prepared statement on insert
bool Delayed; // Use delayed insert
int m_Rc; // Return code from command
@@ -119,6 +130,7 @@ class MYSQLCOL : public COLBLK {
public:
// Constructors
MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "MYSQL");
+ MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am = "MYSQL");
MYSQLCOL(MYSQLCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
@@ -129,6 +141,7 @@ class MYSQLCOL : public COLBLK {
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
+ bool FindRank(PGLOBAL g);
protected:
// Default constructor not to be used
diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp
new file mode 100644
index 00000000000..065da269caa
--- /dev/null
+++ b/storage/connect/taboccur.cpp
@@ -0,0 +1,592 @@
+/************ TabOccur CPP Declares Source Code File (.CPP) ************/
+/* Name: TABOCCUR.CPP Version 1.1 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2013 */
+/* */
+/* OCCUR: Table that provides a view of a source table where the */
+/* contain of several columns of the source table is placed in only */
+/* one column, the OCCUR column, this resulting into several rows. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant section of system dependant header files. */
+/***********************************************************************/
+#include "my_global.h"
+#if defined(WIN32)
+#include <stdlib.h>
+#include <stdio.h>
+#if defined(__BORLANDC__)
+#define __MFC_COMPAT__ // To define min/max as macro
+#endif
+//#include <windows.h>
+#else
+#if defined(UNIX)
+#include <fnmatch.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "osutil.h"
+#else
+//#include <io.h>
+#endif
+//#include <fcntl.h>
+#endif
+
+/***********************************************************************/
+/* Include application header files: */
+/***********************************************************************/
+#include "table.h" // MySQL table definitions
+#include "global.h"
+#include "plgdbsem.h"
+#include "reldef.h"
+#include "filamtxt.h"
+#include "tabdos.h"
+#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"
+
+extern "C" int trace;
+
+/***********************************************************************/
+/* Prepare and count columns in the column list. */
+/***********************************************************************/
+int PrepareColist(char *colist)
+ {
+ char *p, *pn;
+ int n = 0;
+
+ // Count the number of columns and change separator into null char
+ for (pn = colist; ; pn += (strlen(pn) + 1))
+ // Separator can be ; if colist was specified in the option_list
+ if ((p = strchr(pn, ',')) || (p = strchr(pn, ';'))) {
+ *p++ = '\0';
+ n++;
+ } else {
+ if (*pn)
+ n++;
+
+ break;
+ } // endif p
+
+ return n;
+ } // end of PrepareColist
+
+/************************************************************************/
+/* OcrColumns: constructs the result blocks containing all the columns */
+/* of the object table that will be retrieved by GetData commands. */
+/************************************************************************/
+bool OcrColumns(PGLOBAL g, PQRYRES qrp, const char *col,
+ const char *ocr, const char *rank)
+ {
+ char *pn, *colist;
+ int i, k, m, n = 0, c = 0, j = qrp->Nblin;
+ bool rk, b = false;
+ PCOLRES crp;
+
+ if (!col || !*col) {
+ strcpy(g->Message, "Missing colist");
+ return true;
+ } // endif col
+
+ // Prepare the column list
+ colist = (char*)PlugSubAlloc(g, NULL, strlen(col) + 1);
+ strcpy(colist, col);
+ m = PrepareColist(colist);
+
+ if ((rk = (rank && *rank))) {
+ if (m == 1) {
+ strcpy(g->Message, "Cannot handle one column colist and rank");
+ return true;
+ } // endif m
+
+ for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1))
+ n = max(n, (signed)strlen(pn));
+
+ } // endif k
+
+ // Default occur column name is the 1st colist column name
+ if (!ocr || !*ocr)
+ ocr = colist;
+
+ /**********************************************************************/
+ /* Replace the columns of the colist by the rank and occur columns. */
+ /**********************************************************************/
+ for (i = 0; i < qrp->Nblin; i++) {
+ for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1))
+ if (!stricmp(pn, qrp->Colresp->Kdata->GetCharValue(i)))
+ break;
+
+ if (k < m) {
+ // This column belongs to colist
+ if (rk) {
+ // Place the rank column here
+ for (crp = qrp->Colresp; crp; crp = crp->Next)
+ switch (crp->Fld) {
+ case FLD_NAME: crp->Kdata->SetValue((char*)rank, i); break;
+ case FLD_TYPE: crp->Kdata->SetValue(TYPE_STRING, i); break;
+ case FLD_PREC: crp->Kdata->SetValue(n, i); break;
+ case FLD_SCALE: crp->Kdata->SetValue(0, i); break;
+ case FLD_NULL: crp->Kdata->SetValue(0, i); break;
+ case FLD_REM: crp->Kdata->Reset(i); break;
+ default: ; // Ignored by CONNECT
+ } // endswich Fld
+
+ rk = false;
+ } else if (!b) {
+ // First remaining listed column, will be the occur column
+ for (crp = qrp->Colresp; crp; crp = crp->Next)
+ switch (crp->Fld) {
+ case FLD_NAME: crp->Kdata->SetValue((char*)ocr, i); break;
+ case FLD_REM: crp->Kdata->Reset(i); break;
+ default: ; // Nothing to do
+ } // endswich Fld
+
+ b = true;
+ } else if (j == qrp->Nblin)
+ j = i; // Column to remove
+
+ c++;
+ } else if (j < i) {
+ // Move this column in empty spot
+ for (crp = qrp->Colresp; crp; crp = crp->Next)
+ crp->Kdata->Move(i, j);
+
+ j++;
+ } // endif k
+
+ } // endfor i
+
+ // Check whether all columns of the list where found
+ if (c < m) {
+ strcpy(g->Message, "Some colist columns are not in the source table");
+ return true;
+ } // endif crp
+
+ /**********************************************************************/
+ /* Set the number of columns of the table. */
+ /**********************************************************************/
+ qrp->Nblin = j;
+ return false;
+ } // end of OcrColumns
+
+/************************************************************************/
+/* OcrSrcCols: constructs the result blocks containing all the columns */
+/* of the object table that will be retrieved by GetData commands. */
+/************************************************************************/
+bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, const char *col,
+ const char *ocr, const char *rank)
+ {
+ char *pn, *colist;
+ int i, k, m, n = 0, c = 0;
+ bool rk, b = false;
+ PCOLRES crp, rcrp, *pcrp;
+
+ if (!col || !*col) {
+ strcpy(g->Message, "Missing colist");
+ return true;
+ } // endif col
+
+ // Prepare the column list
+ colist = (char*)PlugSubAlloc(g, NULL, strlen(col) + 1);
+ strcpy(colist, col);
+ m = PrepareColist(colist);
+
+ if ((rk = (rank && *rank)))
+ for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1))
+ n = max(n, (signed)strlen(pn));
+
+ // Default occur column name is the 1st colist column name
+ if (!ocr || !*ocr)
+ ocr = colist;
+
+ /**********************************************************************/
+ /* Replace the columns of the colist by the rank and occur columns. */
+ /**********************************************************************/
+ for (i = 0, pcrp = &qrp->Colresp; crp = *pcrp; ) {
+ for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1))
+ if (!stricmp(pn, crp->Name))
+ break;
+
+ if (k < m) {
+ // This column belongs to colist
+ c++;
+
+ if (!b) {
+ if (rk) {
+ // Add the rank column here
+ rcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
+ memset(rcrp, 0, sizeof(COLRES));
+ rcrp->Next = crp;
+ rcrp->Name = (char*)rank;
+ rcrp->Type = TYPE_STRING;
+ rcrp->Length = n;
+ rcrp->Ncol = ++i;
+ *pcrp = rcrp;
+ } // endif rk
+
+ // First remaining listed column, will be the occur column
+ crp->Name = (char*)ocr;
+ b = true;
+ } else {
+ *pcrp = crp->Next; // Remove this column
+ continue;
+ } // endif b
+
+ } // endif k
+
+ crp->Ncol = ++i;
+ pcrp = &crp->Next;
+ } // endfor pcrp
+
+ // Check whether all columns of the list where found
+ if (c < m) {
+ strcpy(g->Message, "Some colist columns are not in the source table");
+ return true;
+ } // endif crp
+
+ /**********************************************************************/
+ /* Set the number of columns of the table. */
+ /**********************************************************************/
+ qrp->Nblin = i;
+ return false;
+ } // end of OcrSrcCols
+
+/* -------------- Implementation of the OCCUR classes ---------------- */
+
+/***********************************************************************/
+/* DefineAM: define specific AM block values from OCCUR table. */
+/***********************************************************************/
+bool OCCURDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+ {
+ Rcol = Cat->GetStringCatInfo(g, "RankCol", "");
+ Colist = Cat->GetStringCatInfo(g, "Colist", "");
+ Xcol = Cat->GetStringCatInfo(g, "OccurCol", Colist);
+ return PRXDEF::DefineAM(g, am, poff);
+ } // end of DefineAM
+
+/***********************************************************************/
+/* GetTable: makes a new TDB of the proper type. */
+/***********************************************************************/
+PTDB OCCURDEF::GetTable(PGLOBAL g, MODE m)
+ {
+ if (Catfunc != FNC_COL)
+ return new(g) TDBOCCUR(this);
+ else
+ return new(g) TDBTBC(this);
+
+ } // end of GetTable
+
+/* ------------------------------------------------------------------- */
+
+/***********************************************************************/
+/* Implementation of the TDBOCCUR class. */
+/***********************************************************************/
+TDBOCCUR::TDBOCCUR(POCCURDEF tdp) : TDBPRX(tdp)
+ {
+//Tdbp = NULL; // Source table (in TDBPRX)
+ Tabname = tdp->Tablep->GetName(); // Name of source table
+ Colist = tdp->Colist; // List of source columns
+ Xcolumn = tdp->Xcol; // Occur column name
+ Rcolumn = tdp->Rcol; // Rank column name
+ Xcolp = NULL; // To the OCCURCOL column
+ Col = NULL; // To source column blocks array
+ Mult = PrepareColist(Colist); // Multiplication factor
+ N = 0; // The current table index
+ M = 0; // The occurence rank
+ RowFlag = 0; // 0: Ok, 1: Same, 2: Skip
+ } // end of TDBOCCUR constructor
+
+/***********************************************************************/
+/* Allocate OCCUR/SRC column description block. */
+/***********************************************************************/
+PCOL TDBOCCUR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
+ {
+ PCOL colp = NULL;
+
+ if (!stricmp(cdp->GetName(), Rcolumn)) {
+ // Allocate a RANK column
+ colp = new(g) RANKCOL(cdp, this, n);
+ } else if (!stricmp(cdp->GetName(), Xcolumn)) {
+ // Allocate the OCCUR column
+ colp = Xcolp = new(g) OCCURCOL(cdp, this, n);
+ } else
+ return new(g) PRXCOL(cdp, this, cprec, n);
+
+ if (cprec) {
+ colp->SetNext(cprec->GetNext());
+ cprec->SetNext(colp);
+ } else {
+ colp->SetNext(Columns);
+ Columns = colp;
+ } // endif cprec
+
+ return colp;
+ } // end of MakeCol
+
+/***********************************************************************/
+/* Initializes the table. */
+/***********************************************************************/
+bool TDBOCCUR::InitTable(PGLOBAL g)
+ {
+ if (!Tdbp)
+ // Get the table description block of this table
+ if (!(Tdbp = GetSubTable(g, ((POCCURDEF)To_Def)->Tablep, TRUE)))
+ return TRUE;
+
+ if (!Tdbp->IsView())
+ if (MakeColumnList(g))
+ return TRUE;
+
+ return FALSE;
+ } // end of InitTable
+
+/***********************************************************************/
+/* Allocate OCCUR column description block. */
+/***********************************************************************/
+bool TDBOCCUR::MakeColumnList(PGLOBAL g)
+ {
+ char *pn;
+ int i;
+ PCOL colp;
+
+ for (colp = Columns; colp; colp = colp->GetNext())
+ if (colp->GetAmType() == TYPE_AM_PRX)
+ if (((PPRXCOL)colp)->Init(g))
+ return true;
+
+ Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL));
+
+ for (i = 0, pn = Colist; i < Mult; i++, pn += (strlen(pn) + 1)) {
+ if (!(Col[i] = Tdbp->ColDB(g, pn, 0))) {
+ // Column not found in table
+ sprintf(g->Message, MSG(COL_ISNOT_TABLE), pn, Tabname);
+ return true;
+ } // endif Col
+
+ if (Col[i]->InitValue(g)) {
+ strcpy(g->Message, "OCCUR InitValue failed");
+ return true;
+ } // endif InitValue
+
+ } // endfor i
+
+ return false;
+ } // end of MakeColumnList
+
+/***********************************************************************/
+/* Allocate OCCUR column description block for a view. */
+/***********************************************************************/
+bool TDBOCCUR::ViewColumnList(PGLOBAL g)
+ {
+ char *pn;
+ int i;
+ PCOL colp, cp;
+ PTDBMY tdbp;
+
+ if (!Tdbp->IsView())
+ return false;
+
+ if (Tdbp->GetAmType() != TYPE_AM_MYSQL) {
+ strcpy(g->Message, "View is not MySQL");
+ return true;
+ } else
+ tdbp = (PTDBMY)Tdbp;
+
+ for (cp = Columns; cp; cp = cp->GetNext())
+ if (cp->GetAmType() == TYPE_AM_PRX) {
+ if ((colp = tdbp->MakeFieldColumn(g, cp->GetName()))) {
+ ((PPRXCOL)cp)->Colp = colp;
+ ((PPRXCOL)cp)->To_Val = colp->GetValue();
+ } else
+ return true;
+
+ } // endif Type
+
+ Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL));
+
+ for (i = 0, pn = Colist; i < Mult; i++, pn += (strlen(pn) + 1))
+ if (!(Col[i] = tdbp->MakeFieldColumn(g, pn))) {
+ // Column not found in table
+ sprintf(g->Message, MSG(COL_ISNOT_TABLE), pn, Tabname);
+ return true;
+ } // endif Col
+
+ return false;
+ } // end of ViewColumnList
+
+/***********************************************************************/
+/* OCCUR GetMaxSize: returns the maximum number of rows in the table. */
+/***********************************************************************/
+int TDBOCCUR::GetMaxSize(PGLOBAL g)
+ {
+ if (MaxSize < 0) {
+ if (!(Tdbp = GetSubTable(g, ((POCCURDEF)To_Def)->Tablep, TRUE)))
+ return 0;
+
+ MaxSize = Mult * Tdbp->GetMaxSize(g);
+ } // endif MaxSize
+
+ return MaxSize;
+ } // end of GetMaxSize
+
+/***********************************************************************/
+/* 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)
+ {
+ return (b) ? M : N;
+ } // end of RowNumber
+
+/***********************************************************************/
+/* OCCUR Access Method opening routine. */
+/***********************************************************************/
+bool TDBOCCUR::OpenDB(PGLOBAL g)
+ {
+ if (Use == USE_OPEN) {
+ /*******************************************************************/
+ /* Table already open, just replace it at its beginning. */
+ /*******************************************************************/
+ N = M = 0;
+ RowFlag = 0;
+
+ if (Xcolp)
+ Xcolp->Xreset();
+
+ return Tdbp->OpenDB(g);
+ } // endif use
+
+
+ if (Mode != MODE_READ) {
+ /*******************************************************************/
+ /* Currently OCCUR tables cannot be modified. */
+ /*******************************************************************/
+ strcpy(g->Message, "OCCUR tables are read only");
+ return TRUE;
+ } // endif Mode
+
+ /*********************************************************************/
+ /* Do it here if not done yet. */
+ /*********************************************************************/
+ if (InitTable(g))
+ return TRUE;
+
+ if (Xcolp)
+ // Lock this column so it is evaluated by its table only
+ Xcolp->AddStatus(BUF_READ);
+
+ if (To_Key_Col || To_Kindex) {
+ /*******************************************************************/
+ /* Direct access of OCCUR tables is not implemented yet. */
+ /*******************************************************************/
+ strcpy(g->Message, "No direct access to OCCUR tables");
+ return TRUE;
+ } // endif To_Key_Col
+
+ /*********************************************************************/
+ /* Do open the source table. */
+ /*********************************************************************/
+ if (Tdbp->OpenDB(g))
+ return TRUE;
+
+ return ViewColumnList(g);
+ } // end of OpenDB
+
+/***********************************************************************/
+/* Data Base read routine for OCCUR access method. */
+/***********************************************************************/
+int TDBOCCUR::ReadDB(PGLOBAL g)
+ {
+ int rc = RC_OK;
+
+ /*********************************************************************/
+ /* Now start the multi reading process. */
+ /*********************************************************************/
+ do {
+ if (RowFlag != 1)
+ if ((rc = Tdbp->ReadDB(g)) != RC_OK)
+ break;
+
+ if (Xcolp) {
+ RowFlag = 0;
+ Xcolp->ReadColumn(g);
+ M = Xcolp->GetI();
+ } // endif Xcolp
+
+ } while (RowFlag == 2);
+
+ N++;
+ return rc;
+ } // end of ReadDB
+
+// ------------------------ OCCURCOL functions ----------------------------
+
+/***********************************************************************/
+/* OCCURCOL public constructor. */
+/***********************************************************************/
+OCCURCOL::OCCURCOL(PCOLDEF cdp, PTDBOCCUR tdbp, int n)
+ : COLBLK(cdp, tdbp, n)
+ {
+ // Set additional OCCUR access method information for column.
+ I = 0;
+ } // end of OCCURCOL constructor
+
+/***********************************************************************/
+/* ReadColumn: what this routine does is to access the columns of */
+/* list, extract their value and convert it to buffer type. */
+/***********************************************************************/
+void OCCURCOL::ReadColumn(PGLOBAL g)
+ {
+ PTDBOCCUR tdbp = (PTDBOCCUR)To_Tdb;
+ PCOL *col = tdbp->Col;
+
+ for (; I < tdbp->Mult; I++) {
+ col[I]->ReadColumn(g);
+
+ if (Nullable || !col[I]->GetValue()->IsZero())
+ break;
+
+ } // endfor I
+
+ if (I == tdbp->Mult) {
+ // No more values, go to next source row
+ tdbp->RowFlag = 2;
+ I = 0;
+ return;
+ } // endif I
+
+ // Set the OCCUR column value from the Ith source column value
+ Value->SetValue_pval(col[I++]->GetValue());
+ tdbp->RowFlag = 1;
+ } // end of ReadColumn
+
+
+// ------------------------ RANKCOL functions ---------------------------
+
+/***********************************************************************/
+/* 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)
+ {
+ PTDBOCCUR tdbp = (PTDBOCCUR)To_Tdb;
+ PCOL *col = tdbp->Col;
+
+ // Set the RANK column value from the Mth source column name
+ if (tdbp->M)
+ Value->SetValue_psz(col[tdbp->M - 1]->GetName());
+ else {
+ Value->Reset();
+
+ if (Nullable)
+ Value->SetNull(true);
+
+ } // endelse
+
+ } // end of ReadColumn
diff --git a/storage/connect/taboccur.h b/storage/connect/taboccur.h
new file mode 100644
index 00000000000..10f94329703
--- /dev/null
+++ b/storage/connect/taboccur.h
@@ -0,0 +1,139 @@
+// TABOCCUR.H Olivier Bertrand 2013
+// Defines the OCCUR tables
+
+#include "tabutil.h"
+
+#define TYPE_AM_OCCUR (AMT)128
+
+typedef class OCCURDEF *POCCURDEF;
+typedef class TDBOCCUR *PTDBOCCUR;
+typedef class OCCURCOL *POCCURCOL;
+typedef class RANKCOL *PRANKCOL;
+
+/* -------------------------- OCCUR classes -------------------------- */
+
+/***********************************************************************/
+/* OCCUR: Table that provides a view of a source table where the */
+/* contain of several columns of the source table is placed in only */
+/* one column, the OCCUR column, this resulting into several rows. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* OCCUR table. */
+/***********************************************************************/
+class OCCURDEF : public PRXDEF { /* Logical table description */
+ friend class TDBOCCUR;
+ public:
+ // Constructor
+ OCCURDEF(void) {Pseudo = 3; Colist = Xcol = NULL;}
+
+ // Implementation
+ virtual const char *GetType(void) {return "OCCUR";}
+
+ // Methods
+ virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
+ virtual PTDB GetTable(PGLOBAL g, MODE m);
+
+ protected:
+ // Members
+ char *Colist; /* The source column list */
+ char *Xcol; /* The multiple occurence column */
+ char *Rcol; /* The rank column */
+ }; // end of OCCURDEF
+
+/***********************************************************************/
+/* This is the class declaration for the OCCUR table. */
+/***********************************************************************/
+class TDBOCCUR : public TDBPRX {
+ friend class OCCURCOL;
+ friend class RANKCOL;
+ public:
+ // Constructor
+ TDBOCCUR(POCCURDEF tdp);
+
+ // Implementation
+ virtual AMT GetAmType(void) {return TYPE_AM_OCCUR;}
+ void SetTdbp(PTDBASE tdbp) {Tdbp = tdbp;}
+
+ // Methods
+ virtual void ResetDB(void) {N = 0; Tdbp->ResetDB();}
+ virtual int RowNumber(PGLOBAL g, bool b = FALSE);
+ bool MakeColumnList(PGLOBAL g);
+ bool ViewColumnList(PGLOBAL g);
+
+ // Database routines
+ virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual bool InitTable(PGLOBAL g);
+ virtual int GetMaxSize(PGLOBAL g);
+ virtual bool OpenDB(PGLOBAL g);
+ virtual int ReadDB(PGLOBAL g);
+
+ protected:
+ // Members
+//PTDBASE Tdbp; // To the source table or view
+ LPCSTR Tabname; // Name of source table
+ char *Colist; // Source column list
+ char *Xcolumn; // Occurence column name
+ char *Rcolumn; // Rank column name
+ POCCURCOL Xcolp; // To the OCCURCOL column
+ PCOL *Col; // To source multiple columns
+ int Mult; // Multiplication factor
+ int N; // The current table index
+ int M; // The occurence rank
+ BYTE RowFlag; // 0: Ok, 1: Same, 2: Skip
+ }; // end of class TDBOCCUR
+
+/***********************************************************************/
+/* Class OCCURCOL: for the multiple occurence column. */
+/***********************************************************************/
+class OCCURCOL : public COLBLK {
+ public:
+ // Constructors
+ OCCURCOL(PCOLDEF cdp, PTDBOCCUR tdbp, int n);
+
+ // Implementation
+ virtual int GetAmType(void) {return TYPE_AM_OCCUR;}
+ int GetI(void) {return I;}
+
+ // Methods
+ virtual void Reset(void) {} // Evaluated only by TDBOCCUR
+ virtual void ReadColumn(PGLOBAL g);
+ void Xreset(void) {I = 0;};
+
+ protected:
+ // Default constructor not to be used
+ OCCURCOL(void) {}
+
+ // Members
+ int I;
+ }; // end of class OCCURCOL
+
+/***********************************************************************/
+/* Class RANKCOL: for the multiple occurence column ranking. */
+/***********************************************************************/
+class RANKCOL : public COLBLK {
+ public:
+ // Constructors
+ RANKCOL(PCOLDEF cdp, PTDBOCCUR tdbp, int n) : COLBLK(cdp, tdbp, n) {}
+
+ // Implementation
+ virtual int GetAmType(void) {return TYPE_AM_OCCUR;}
+
+ // Methods
+ virtual void ReadColumn(PGLOBAL g);
+
+ protected:
+ // Default constructor not to be used
+ RANKCOL(void) {}
+
+ // Members
+ }; // end of class RANKCOL
+
+/***********************************************************************/
+/* Definition of class XCOLDEF. */
+/* This class purpose is just to access COLDEF protected items! */
+/***********************************************************************/
+class XCOLDEF: public COLDEF {
+ friend class TDBOCCUR;
+ }; // end of class XCOLDEF
+
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index 5bbc9effa92..599f9c7e80f 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -75,7 +75,6 @@
#include "sql_string.h"
-extern "C" char *GetMsgid(int id);
extern "C" int trace;
/***********************************************************************/
@@ -896,7 +895,7 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
Value->SetValue_pval(To_Val, false); // Convert the inserted value
if (Buf_Type == TYPE_DATE) {
- struct tm *dbtime = ((DTVAL*)Value)->GetGmTime();
+ struct tm tm, *dbtime = ((DTVAL*)Value)->GetGmTime(&tm);
Sqlbuf->second = dbtime->tm_sec;
Sqlbuf->minute = dbtime->tm_min;
diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp
index fccd8338d8a..9beca56e773 100644
--- a/storage/connect/tabpivot.cpp
+++ b/storage/connect/tabpivot.cpp
@@ -1,11 +1,11 @@
/************ TabPivot C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABPIVOT */
/* ------------- */
-/* Version 1.3 */
+/* Version 1.6 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -41,10 +41,11 @@
#include "global.h"
#include "plgdbsem.h"
#include "xtable.h"
-#include "xindex.h"
+#include "tabcol.h"
#include "colblk.h"
#include "tabmysql.h"
#include "csort.h"
+#include "tabutil.h"
#include "tabpivot.h"
#include "valblk.h"
#include "ha_connect.h"
@@ -52,9 +53,196 @@
extern "C" int trace;
+/***********************************************************************/
+/* Make the Pivot table column list. */
+/***********************************************************************/
+PQRYRES PivotColumns(PGLOBAL g, const char *tab, const char *src,
+ const char *picol, const char *fncol,
+ const char *host, const char *db,
+ const char *user, const char *pwd,
+ int port)
+ {
+ PIVAID pvd(tab, src, picol, fncol, host, db, user, pwd, port);
+
+ return pvd.MakePivotColumns(g);
+ } // end of PivotColumns
+
+/* --------------- Implementation of the PIVAID classe --------------- */
+
+/***********************************************************************/
+/* PIVAID constructor. */
+/***********************************************************************/
+PIVAID::PIVAID(const char *tab, const char *src, const char *picol,
+ const char *fncol, const char *host, const char *db,
+ const char *user, const char *pwd, int port)
+ : CSORT(false)
+ {
+ Host = (char*)host;
+ User = (char*)user;
+ Pwd = (char*)pwd;
+ Qryp = NULL;
+ Database = (char*)db;
+ Tabname = (char*)tab;
+ Tabsrc = (char*)src;
+ Picol = (char*)picol;
+ Fncol = (char*)fncol;
+ Rblkp = NULL;
+ Port = (port) ? port : GetDefaultPort();
+ } // end of PIVAID constructor
+
+/***********************************************************************/
+/* Make the Pivot table column list. */
+/***********************************************************************/
+PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
+ {
+ char *query, *colname, buf[32];
+ int ndif, nblin, w = 0;
+ PVAL valp;
+ PCOLRES *pcrp, crp, fncrp = NULL;
+
+ if (!Tabsrc && Tabname) {
+ // Locate the query
+ query = (char*)PlugSubAlloc(g, NULL, strlen(Tabname) + 16);
+ sprintf(query, "SELECT * FROM %s", Tabname);
+ } else if (!Tabsrc) {
+ strcpy(g->Message, MSG(SRC_TABLE_UNDEF));
+ return NULL;
+ } else
+ query = Tabsrc;
+
+ // Open a MySQL connection for this table
+ if (Myc.Open(g, Host, Database, User, Pwd, Port))
+ return NULL;
+
+ // Send the source command to MySQL
+ if (Myc.ExecSQL(g, query, &w) == RC_FX) {
+ Myc.Close();
+ return NULL;
+ } // endif Exec
+
+ // We must have a storage query to get pivot column values
+ Qryp = Myc.GetResult(g);
+ Myc.Close();
+
+ if (!Fncol) {
+ for (crp = Qryp->Colresp; crp; crp = crp->Next)
+ if (!Picol || stricmp(Picol, crp->Name))
+ Fncol = crp->Name;
+
+ if (!Fncol) {
+ strcpy(g->Message, MSG(NO_DEF_FNCCOL));
+ return NULL;
+ } // endif Fncol
+
+ } // endif Fncol
+
+ if (!Picol) {
+ // Find default Picol as the last one not equal to Fncol
+ for (crp = Qryp->Colresp; crp; crp = crp->Next)
+ if (stricmp(Fncol, crp->Name))
+ Picol = crp->Name;
+
+ if (!Picol) {
+ strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
+ return NULL;
+ } // endif Picol
+
+ } // endif picol
+
+ // Prepare the column list
+ for (pcrp = &Qryp->Colresp; crp = *pcrp; )
+ if (!stricmp(Picol, crp->Name)) {
+ Rblkp = crp->Kdata;
+ *pcrp = crp->Next;
+ } else if (!stricmp(Fncol, crp->Name)) {
+ fncrp = crp;
+ *pcrp = crp->Next;
+ } else
+ pcrp = &crp->Next;
+
+ if (!Rblkp) {
+ strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
+ return NULL;
+ } else if (!fncrp) {
+ strcpy(g->Message, MSG(NO_DEF_FNCCOL));
+ return NULL;
+ } // endif
+
+ // Before calling sort, initialize all
+ nblin = Qryp->Nblin;
+
+ Index.Size = nblin * sizeof(int);
+ Index.Sub = TRUE; // Should be small enough
+
+ if (!PlgDBalloc(g, NULL, Index))
+ return NULL;
+
+ Offset.Size = (nblin + 1) * sizeof(int);
+ Offset.Sub = TRUE; // Should be small enough
+
+ if (!PlgDBalloc(g, NULL, Offset))
+ return NULL;
+
+ ndif = Qsort(g, nblin);
+
+ if (ndif < 0) // error
+ return NULL;
+
+ // Allocate the Value used to retieve column names
+ if (!(valp = AllocateValue(g, Rblkp->GetType(),
+ Rblkp->GetVlen(),
+ Rblkp->GetPrec())))
+ return NULL;
+
+ // Now make the functional columns
+ for (int i = 0; i < ndif; i++) {
+ if (i) {
+ crp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
+ memcpy(crp, fncrp, sizeof(COLRES));
+ } else
+ crp = fncrp;
+
+ // Get the value that will be the generated column name
+ valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]);
+ colname = valp->GetCharString(buf);
+ crp->Name = (char*)PlugSubAlloc(g, NULL, strlen(colname) + 1);
+ strcpy(crp->Name, colname);
+ crp->Flag = 1;
+
+ // Add this column
+ *pcrp = crp;
+ crp->Next = NULL;
+ pcrp = &crp->Next;
+ } // endfor i
+
+ // We added ndif columns and removed 2 (picol and fncol)
+ Qryp->Nbcol += (ndif - 2);
+ return Qryp;
+ } // end of MakePivotColumns
+
+/***********************************************************************/
+/* PIVAID: Compare routine for sorting pivot column values. */
+/***********************************************************************/
+int PIVAID::Qcompare(int *i1, int *i2)
+ {
+ // TODO: the actual comparison between pivot column result values.
+ return Rblkp->CompVal(*i1, *i2);
+ } // end of Qcompare
+
/* --------------- Implementation of the PIVOT classes --------------- */
/***********************************************************************/
+/* PIVOTDEF constructor. */
+/***********************************************************************/
+ PIVOTDEF::PIVOTDEF(void)
+ {
+ Host = User = Pwd = DB = NULL;
+ Tabname = Tabsrc = Picol = Fncol = Function = NULL;
+ GBdone = Accept = false;
+ Port = 0;
+ } // end of PIVOTDEF constructor
+
+/***********************************************************************/
/* DefineAM: define specific AM block values from PIVOT table. */
/***********************************************************************/
bool PIVOTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
@@ -62,14 +250,18 @@ bool PIVOTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
char *p1, *p2;
PHC hc = ((MYCAT*)Cat)->GetHandler();
- Host = Cat->GetStringCatInfo(g, Name, "Host", "localhost");
- User = Cat->GetStringCatInfo(g, Name, "User", "root");
- Pwd = Cat->GetStringCatInfo(g, Name, "Password", NULL);
- DB = Cat->GetStringCatInfo(g, Name, "Database", (PSZ)hc->GetDBName(NULL));
- Tabsrc = Cat->GetStringCatInfo(g, Name, "SrcDef", NULL);
- Tabname = Cat->GetStringCatInfo(g, Name, "Name", NULL);
- Picol = Cat->GetStringCatInfo(g, Name, "PivotCol", NULL);
- Fncol = Cat->GetStringCatInfo(g, Name, "FncCol", NULL);
+ if (PRXDEF::DefineAM(g, am, poff))
+ return TRUE;
+
+ Tabname = (char*)Tablep->GetName();
+ DB = (char*)Tablep->GetQualifier();
+ Tabsrc = (char*)Tablep->GetSrc();
+
+ Host = Cat->GetStringCatInfo(g, "Host", "localhost");
+ User = Cat->GetStringCatInfo(g, "User", "*");
+ Pwd = Cat->GetStringCatInfo(g, "Password", NULL);
+ Picol = Cat->GetStringCatInfo(g, "PivotCol", NULL);
+ Fncol = Cat->GetStringCatInfo(g, "FncCol", NULL);
// If fncol is like avg(colname), separate Fncol and Function
if (Fncol && (p1 = strchr(Fncol, '(')) && (p2 = strchr(p1, ')')) &&
@@ -78,11 +270,12 @@ bool PIVOTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Function = Fncol;
Fncol = p1;
} else
- Function = Cat->GetStringCatInfo(g, Name, "Function", "SUM");
+ Function = Cat->GetStringCatInfo(g, "Function", "SUM");
- GBdone = Cat->GetIntCatInfo(Name, "Groupby", 0) ? TRUE : FALSE;
- Port = Cat->GetIntCatInfo(Name, "Port", 3306);
- Desc = (*Tabname) ? Tabname : Tabsrc;
+ GBdone = Cat->GetBoolCatInfo("Groupby", false);
+ Accept = Cat->GetBoolCatInfo("Accept", false);
+ Port = Cat->GetIntCatInfo("Port", 3306);
+ Desc = (Tabsrc) ? Tabsrc : Tabname;
return FALSE;
} // end of DefineAM
@@ -99,15 +292,13 @@ PTDB PIVOTDEF::GetTable(PGLOBAL g, MODE m)
/***********************************************************************/
/* Implementation of the TDBPIVOT class. */
/***********************************************************************/
-TDBPIVOT::TDBPIVOT(PPIVOTDEF tdp) : TDBASE(tdp), CSORT(FALSE)
+TDBPIVOT::TDBPIVOT(PPIVOTDEF tdp) : TDBPRX(tdp)
{
- Tqrp = NULL;
Host = tdp->Host;
Database = tdp->DB;
User = tdp->User;
Pwd = tdp->Pwd;
Port = tdp->Port;
- Qryp = NULL;
Tabname = tdp->Tabname; // Name of source table
Tabsrc = tdp->Tabsrc; // SQL description of source table
Picol = tdp->Picol; // Pivot column name
@@ -117,7 +308,9 @@ TDBPIVOT::TDBPIVOT(PPIVOTDEF tdp) : TDBASE(tdp), CSORT(FALSE)
//Xresp = NULL; // To the pivot result column
//Rblkp = NULL; // The value block of the pivot column
Fcolp = NULL; // To the function column
+ Dcolp = NULL; // To the dump column
GBdone = tdp->GBdone;
+ Accept = tdp->Accept;
Mult = -1; // Estimated table size
N = 0; // The current table index
M = 0; // The occurence rank
@@ -125,438 +318,224 @@ TDBPIVOT::TDBPIVOT(PPIVOTDEF tdp) : TDBASE(tdp), CSORT(FALSE)
RowFlag = 0; // 0: Ok, 1: Same, 2: Skip
} // end of TDBPIVOT constructor
-#if 0
-TDBPIVOT::TDBPIVOT(PTDBPIVOT tdbp) : TDBASE(tdbp), CSORT(FALSE)
- {
- Tdbp = tdbp->Tdbp;
- Sqlp = tdbp->Sqlp;
- Qryp = tdbp->Qryp;
- Tabname = tdbp->Tabname;
- Tabsrc = tdbp->Tabsrc;
- Picol = tdbp->Picol;
- Fncol = tdbp->Fncol;
- Function = tdbp->Function;
- Xcolp = tdbp->Xcolp;
- Xresp = tdbp->Xresp;
- Rblkp = tdbp->Rblkp;
- Fcolp = tdbp->Fcolp;
- Mult = tdbp->Mult;
- N = tdbp->N;
- M = tdbp->M;
- FileStatus = tdbp->FileStatus;
- RowFlag = tdbp->RowFlag;
- } // end of TDBPIVOT copy constructor
-
-// Is this really useful ???
-PTDB TDBPIVOT::CopyOne(PTABS t)
- {
- PTDB tp = new(t->G) TDBPIVOT(this);
-
- tp->SetColumns(Columns);
- return tp;
- } // end of CopyOne
-#endif // 0
-
/***********************************************************************/
-/* Prepare the source table Query. */
+/* Allocate source column description block. */
/***********************************************************************/
-PQRYRES TDBPIVOT::GetSourceTable(PGLOBAL g)
+PCOL TDBPIVOT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
- if (Qryp)
- return Qryp; // Already done
-
- if (!Tabsrc && Tabname) {
- char *def, *colist;
- size_t len = 0;
- PCOL colp;
- PDBUSER dup = (PDBUSER)g->Activityp->Aptr;
+ PCOL colp;
- // Evaluate the length of the column list
- for (colp = Columns; colp; colp = colp->GetNext())
- len += (strlen(colp->GetName()) + 2);
+ if (cdp->GetOffset()) {
+ colp = new(g) FNCCOL(cdp, this, cprec, n);
- *(colist = (char*)PlugSubAlloc(g, NULL, len)) = 0;
+ if (cdp->GetOffset() > 1)
+ Dcolp = colp;
- // Locate the suballocated string (size is not known yet)
- def = (char*)PlugSubAlloc(g, NULL, 0);
- strcpy(def, "SELECT ");
-
- if (!Fncol) {
- for (colp = Columns; colp; colp = colp->GetNext())
- if (!Picol || stricmp(Picol, colp->GetName()))
- Fncol = colp->GetName();
+ } else
+ colp = new(g) SRCCOL(cdp, this, cprec, n);
- if (!Fncol) {
- strcpy(g->Message, MSG(NO_DEF_FNCCOL));
- return NULL;
- } // endif Fncol
+ return colp;
+ } // end of MakeCol
- } else if (!(ColDB(g, Fncol, 0))) {
- // Function column not found in table
- sprintf(g->Message, MSG(COL_ISNOT_TABLE), Fncol, Tabname);
- return NULL;
- } // endif Fcolp
+/***********************************************************************/
+/* Find default fonction and pivot columns. */
+/***********************************************************************/
+bool TDBPIVOT::FindDefaultColumns(PGLOBAL g)
+ {
+ PCOLDEF cdp;
+ PTABDEF defp = Tdbp->GetDef();
+ if (!Fncol) {
+ for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext())
+ if (!Picol || stricmp(Picol, cdp->GetName()))
+ Fncol = cdp->GetName();
+
+ if (!Fncol) {
+ strcpy(g->Message, MSG(NO_DEF_FNCCOL));
+ return true;
+ } // endif Fncol
+
+ } // endif Fncol
+
+ if (!Picol) {
+ // Find default Picol as the last one not equal to Fncol
+ for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext())
+ if (stricmp(Fncol, cdp->GetName()))
+ Picol = cdp->GetName();
+
if (!Picol) {
- // Find default Picol as the last one not equal to Fncol
- for (colp = Columns; colp; colp = colp->GetNext())
- if (!Fncol || stricmp(Fncol, colp->GetName()))
- Picol = colp->GetName();
-
- if (!Picol) {
- strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
- return NULL;
- } // endif Picol
-
- } else if (!(ColDB(g, Picol, 0))) {
- // Pivot column not found in table
- sprintf(g->Message, MSG(COL_ISNOT_TABLE), Picol, Tabname);
- return NULL;
- } // endif Xcolp
+ strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
+ return true;
+ } // endif Picol
+
+ } // endif Picol
+
+ return false;
+ } // end of FindDefaultColumns
- // Make the other column list
- for (colp = Columns; colp; colp = colp->GetNext())
- if (stricmp(Picol, colp->GetName()) &&
- stricmp(Fncol, colp->GetName()))
- strcat(strcat(colist, colp->GetName()), ", ");
+/***********************************************************************/
+/* Prepare the source table Query. */
+/***********************************************************************/
+bool TDBPIVOT::GetSourceTable(PGLOBAL g)
+ {
+ if (Tdbp)
+ return false; // Already done
- // Add the Pivot column at the end of the list
- strcat(strcat(def, strcat(colist, Picol)), ", ");
+ if (!Tabsrc && Tabname) {
+ // Get the table description block of this table
+ if (!(Tdbp = GetSubTable(g, ((PPIVOTDEF)To_Def)->Tablep, true)))
+ return true;
- // Continue making the definition
if (!GBdone) {
+ char *colist;
+ PCOLDEF cdp;
+
+ if (FindDefaultColumns(g))
+ return true;
+
+ // Locate the suballocated colist (size is not known yet)
+ *(colist = (char*)PlugSubAlloc(g, NULL, 0)) = 0;
+
+ // Make the column list
+ for (cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext())
+ if (!cdp->GetOffset())
+ strcat(strcat(colist, cdp->GetName()), ", ");
+
+ // Add the Pivot column at the end of the list
+ strcat(colist, Picol);
+
+ // Now we know how much was suballocated
+ PlugSubAlloc(g, NULL, strlen(colist));
+
+ // Locate the source string (size is not known yet)
+ Tabsrc = (char*)PlugSubAlloc(g, NULL, 0);
+
+ // Start making the definition
+ strcat(strcat(strcpy(Tabsrc, "SELECT "), colist), ", ");
+
// Make it suitable for Pivot by doing the group by
- strcat(strcat(def, Function), "(");
- strcat(strcat(strcat(def, Fncol), ") "), Fncol);
- strcat(strcat(def, " FROM "), Tabname);
- strcat(strcat(def, " GROUP BY "), colist);
- } else // Gbdone
- strcat(strcat(strcat(def, Fncol), " FROM "), Tabname);
-
- // Now we know how much was suballocated
- Tabsrc = (char*)PlugSubAlloc(g, NULL, strlen(def));
- } else {
- strcpy(g->Message, MSG(SRC_TABLE_UNDEF));
- return NULL;
- } // endif Tabsrc
+ strcat(strcat(Tabsrc, Function), "(");
+ strcat(strcat(strcat(Tabsrc, Fncol), ") "), Fncol);
+ strcat(strcat(Tabsrc, " FROM "), Tabname);
+ strcat(strcat(Tabsrc, " GROUP BY "), colist);
+
+ if (Tdbp->IsView()) // Until MariaDB bug is fixed
+ strcat(strcat(Tabsrc, " ORDER BY "), colist);
- int w;
+ // Now we know how much was suballocated
+ PlugSubAlloc(g, NULL, strlen(Tabsrc));
+ } // endif !GBdone
- // Open a MySQL connection for this table
- if (Myc.Open(g, Host, Database, User, Pwd, Port))
- return NULL;
+ } else if (!Tabsrc) {
+ strcpy(g->Message, MSG(SRC_TABLE_UNDEF));
+ return true;
+ } // endif
- // Send the source command to MySQL
- if (Myc.ExecSQL(g, Tabsrc, &w) == RC_FX) {
- Myc.Close();
- return NULL;
- } // endif Exec
+ if (Tabsrc) {
+ // Get the new table description block of this source table
+ PTABLE tablep = new(g) XTAB("whatever", Tabsrc);
- // We must have a storage query to get pivot column values
- Qryp = Myc.GetResult(g);
- Myc.Close();
- Tqrp = new(g) TDBQRS(Qryp);
- Tqrp->OpenDB(g);
+ tablep->SetQualifier(Database);
- if (MakePivotColumns(g) < 0)
- return NULL;
+ if (!(Tdbp = GetSubTable(g, tablep, true)))
+ return true;
- return Qryp;
+ } // endif Tabsrc
+
+ return false;
} // end of GetSourceTable
/***********************************************************************/
-/* Allocate PIVOT columns description block. */
+/* Make the required pivot columns. */
/***********************************************************************/
-int TDBPIVOT::MakePivotColumns(PGLOBAL g)
+bool TDBPIVOT::MakePivotColumns(PGLOBAL g)
{
- if (Mult < 0) {
- int ndif, n = 0, nblin = Qryp->Nblin;
- PVAL valp;
- PCOL cp;
- PSRCCOL colp;
- PFNCCOL cfnp;
-
- // Allocate all the source columns
- Tqrp->ColDB(g, NULL, 0);
- Columns = NULL; // Discard dummy columns blocks
-
- for (cp = Tqrp->GetColumns(); cp; cp = cp->GetNext()) {
- if (cp->InitValue(g))
- return -1;
-
- if (!stricmp(cp->GetName(), Picol)) {
- Xcolp = (PQRSCOL)cp;
- Xresp = Xcolp->GetCrp();
- Rblkp = Xresp->Kdata;
- } else if (!stricmp(cp->GetName(), Fncol)) {
- Fcolp = (PQRSCOL)cp;
- } else
- if ((colp = new(g) SRCCOL(cp, this, ++n))->Init(g, this))
- return -1;
-
- } // endfor cp
-
- if (!Xcolp) {
- sprintf(g->Message, MSG(COL_ISNOT_TABLE),
- Picol, Tabname ? Tabname : "TabSrc");
- return -1;
- } else if (!Fcolp) {
- sprintf(g->Message, MSG(COL_ISNOT_TABLE),
- Fncol, Tabname ? Tabname : "TabSrc");
- return -1;
- } // endif Fcolp
-
- // Before calling sort, initialize all
- Index.Size = nblin * sizeof(int);
- Index.Sub = TRUE; // Should be small enough
-
- if (!PlgDBalloc(g, NULL, Index))
- return -1;
-
- Offset.Size = (nblin + 1) * sizeof(int);
- Offset.Sub = TRUE; // Should be small enough
-
- if (!PlgDBalloc(g, NULL, Offset))
- return -2;
-
- ndif = Qsort(g, nblin);
-
- if (ndif < 0) { // error
- return -3;
- } else
- Ncol = ndif;
-
- // Now make the functional columns
- for (int i = 0; i < Ncol; i++) {
- // Allocate the Value used to retieve column names
- if (!(valp = AllocateValue(g, Xcolp->GetResultType(),
- Xcolp->GetLengthEx(), Xcolp->GetPrecision(),
- Xcolp->GetDomain(), Xcolp->GetTo_Tdb()->GetCat())))
- return -4;
-
- // Get the value that will be the generated column name
- valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]);
-
- // Copy the functional column with new Name and new Value
- cfnp = (PFNCCOL)new(g) FNCCOL(Fcolp, this);
+ if (!Tdbp->IsView()) {
+ // This was not done yet if GBdone is true
+ if (FindDefaultColumns(g))
+ return true;
+
+ // Now it is time to allocate the pivot and function columns
+ if (!(Fcolp = Tdbp->ColDB(g, Fncol, 0))) {
+ // Function column not found in table
+ sprintf(g->Message, MSG(COL_ISNOT_TABLE), Fncol, Tabname);
+ return true;
+ } else if (Fcolp->InitValue(g))
+ return true;
- // Initialize the generated column
- if (cfnp->InitColumn(g, valp))
- return -5;
+ if (!(Xcolp = Tdbp->ColDB(g, Picol, 0))) {
+ // Pivot column not found in table
+ sprintf(g->Message, MSG(COL_ISNOT_TABLE), Picol, Tabname);
+ return true;
+ } else if (Xcolp->InitValue(g))
+ return true;
- } // endfor i
+ // 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))
+ return TRUE;
- // Fields must be updated for ha_connect
-// if (UpdateTableFields(g, n + Ncol))
-// return -6;
+ } else if (cp->GetAmType() == TYPE_AM_FNC)
+ if (((PFNCCOL)cp)->InitColumn(g))
+ return TRUE;
- // This should be refined later
- Mult = nblin;
- } // endif Mult
+ } // endif isview
- return Mult;
+ return false;
} // end of MakePivotColumns
-#if 0
/***********************************************************************/
-/* Update fields in the MySQL table structure */
-/* Note: this does not work. Indeed the new rows are correctly made */
-/* but the final result still specify the unmodified table and the */
-/* returned table only contains the original column values. */
-/* In addition, a new query on the table, when it is into the cache, */
-/* specifies all the new columns and fails because they do not belong */
-/* to the original table. */
+/* Make the required pivot columns for an object view. */
/***********************************************************************/
-bool TDBPIVOT::UpdateTableFields(PGLOBAL g, int n)
+bool TDBPIVOT::MakeViewColumns(PGLOBAL g)
{
- uchar *trec, *srec, *tptr, *sptr;
- int i = 0, k = 0;
- uint len;
- uint32 nmp, lwm;
- size_t buffsize;
- PCOL colp;
- PHC hc = ((MYCAT*)((PIVOTDEF*)To_Def)->Cat)->GetHandler();
- TABLE *table = hc->GetTable();
- st_mem_root *tmr = &table->mem_root;
- st_mem_root *smr = &table->s->mem_root;
- Field* *field;
- Field *fp, *tfncp, *sfncp;
- Field* *ntf;
- Field* *nsf;
-//my_bitmap_map *org_bitmap;
- const MY_BITMAP *map;
-
- // When sorting read_set selects all columns, so we use def_read_set
- map= (const MY_BITMAP *)&table->def_read_set;
-
- // Find the function field
- for (field= table->field; *field; field++) {
- fp= *field;
-
- if (bitmap_is_set(map, fp->field_index))
- if (!stricmp(fp->field_name, Fncol)) {
- tfncp = fp;
- break;
- } // endif Name
-
- } // endfor field
-
- for (field= table->s->field; *field; field++) {
- fp= *field;
-
- if (bitmap_is_set(map, fp->field_index))
- if (!stricmp(fp->field_name, Fncol)) {
- sfncp = fp;
- break;
- } // endif Name
-
- } // endfor field
-
- // Calculate the new buffer size
- len = tfncp->max_data_length();
- buffsize = table->s->rec_buff_length + len * Ncol;
-
- // Allocate the new record space
- if (!(tptr = trec = (uchar*)alloc_root(tmr, 2 * buffsize)))
- return TRUE;
-
- if (!(sptr = srec = (uchar*)alloc_root(smr, 2 * buffsize)))
- return TRUE;
-
+ if (Tdbp->IsView()) {
+ // Tdbp is a view ColDB cannot be used
+ PCOL colp, cp;
+ PTDBMY tdbp;
- // Allocate the array of all new table field pointers
- if (!(ntf = (Field**)alloc_root(tmr, (uint)((n+1) * sizeof(Field*)))))
- return TRUE;
+ if (Tdbp->GetAmType() != TYPE_AM_MYSQL) {
+ strcpy(g->Message, "View is not MySQL");
+ return true;
+ } else
+ tdbp = (PTDBMY)Tdbp;
- // Allocate the array of all new table share field pointers
- if (!(nsf = (Field**)alloc_root(smr, (uint)((n+1) * sizeof(Field*)))))
- return TRUE;
+ if (!Fncol && !(Fncol = tdbp->FindFieldColumn(Picol))) {
+ strcpy(g->Message, MSG(NO_DEF_FNCCOL));
+ return true;
+ } // endif Fncol
- // First fields are the the ones of the source columns
- for (colp = Columns; colp; colp = colp->GetNext())
- if (colp->GetAmType() == TYPE_AM_SRC) {
- for (field= table->field; *field; field++) {
- fp= *field;
-
- if (bitmap_is_set(map, fp->field_index))
- if (!stricmp(colp->GetName(), fp->field_name)) {
- ntf[i] = fp;
- fp->field_index = i++;
- fp->ptr = tptr;
- tptr += fp->max_data_length();
- break;
- } // endif Name
-
- } // endfor field
-
- for (field= table->s->field; *field; field++) {
- fp= *field;
-
- if (bitmap_is_set(map, fp->field_index))
- if (!stricmp(colp->GetName(), fp->field_name)) {
- nsf[k] = fp;
- fp->field_index = k++;
- fp->ptr = srec;
- srec += fp->max_data_length();
- break;
- } // endif Name
-
- } // endfor field
-
- } // endif AmType
-
- // Now add the pivot generated columns
- for (colp = Columns; colp; colp = colp->GetNext())
- if (colp->GetAmType() == TYPE_AM_FNC) {
- if ((fp = (Field*)memdup_root(tmr, (char*)tfncp, tfncp->size_of()))) {
- ntf[i] = fp;
- fp->ptr = tptr;
- fp->field_name = colp->GetName();
- fp->field_index = i++;
- fp->vcol_info = NULL;
- fp->stored_in_db = TRUE;
- tptr += len;
- } else
- return TRUE;
-
- if ((fp = (Field*)memdup_root(smr, (char*)sfncp, sfncp->size_of()))) {
- nsf[i] = fp;
- fp->ptr = sptr;
- fp->field_name = colp->GetName();
- fp->field_index = k++;
- fp->vcol_info = NULL;
- fp->stored_in_db = TRUE;
- sptr += len;
- } else
- return TRUE;
-
- } // endif AM_FNC
-
- // Mark end of the list
- ntf[i] = NULL;
- nsf[k] = NULL;
-
- // Update the table fields
- nmp = (uint32)((1<<i) - 1);
- lwm = (uint32)((-1)<<i);
- table->field = ntf;
- table->used_fields = i;
- table->record[0] = trec;
- table->record[1] = trec + buffsize;
- *table->def_read_set.bitmap = nmp;
- *table->def_read_set.last_word_ptr = nmp;
- table->def_read_set.last_word_mask = lwm;
- table->def_read_set.n_bits = i;
- *table->read_set->bitmap = nmp;
- *table->read_set->last_word_ptr = nmp;
- table->read_set->last_word_mask = lwm;
- table->read_set->n_bits = i;
- table->write_set->n_bits = i;
- *table->vcol_set->bitmap = 0;
- table->vcol_set->n_bits = i;
-
- // and the share fields
- table->s->field = nsf;
- table->s->reclength = sptr - srec;
- table->s->stored_rec_length = sptr - srec;
- table->s->fields = k;
- table->s->stored_fields = k;
- table->s->rec_buff_length = buffsize;
-//table->s->varchar_fields = ???;
-//table->s->db_record_offset = ???;
-//table->s->null_field_first = ???;
- return FALSE;
- } // end of UpdateTableFields
-#endif // 0
+ if (!Picol && !(Picol = tdbp->FindFieldColumn(Fncol))) {
+ strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
+ return true;
+ } // endif Picol
-/***********************************************************************/
-/* Allocate source column description block. */
-/***********************************************************************/
-PCOL TDBPIVOT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
- {
- PCOL colp = NULL;
+ // Now it is time to allocate the pivot and function columns
+ if (!(Fcolp = tdbp->MakeFieldColumn(g, Fncol)))
+ return true;
-//if (stricmp(cdp->GetName(), Picol) && stricmp(cdp->GetName(), Fncol)) {
- colp = new(g) COLBLK(cdp, this, n);
+ if (!(Xcolp = tdbp->MakeFieldColumn(g, Picol)))
+ return true;
-// if (((PSRCCOL)colp)->Init(g, this))
-// return NULL;
+ // Check and initialize the subtable columns
+ for (cp = Columns; cp; cp = cp->GetNext())
+ if (cp->GetAmType() == TYPE_AM_SRC) {
+ if ((colp = tdbp->MakeFieldColumn(g, cp->GetName()))) {
+ ((PSRCCOL)cp)->Colp = colp;
+ ((PSRCCOL)cp)->To_Val = colp->GetValue();
+ cp->AddStatus(BUF_READ); // All is done here
+ } else
+ return true;
-//} else {
-// sprintf(g->Message, MSG(NO_MORE_COL), cdp->GetName());
-// return NULL;
-//} // endif Name
+ } else if (cp->GetAmType() == TYPE_AM_FNC)
+ if (((PFNCCOL)cp)->InitColumn(g))
+ return TRUE;
- if (cprec) {
- colp->SetNext(cprec->GetNext());
- cprec->SetNext(colp);
- } else {
- colp->SetNext(Columns);
- Columns = colp;
- } // endif cprec
+ } // endif isview
- return colp;
- } // end of MakeCol
+ return false;
+ } // end of MakeViewColumns
/***********************************************************************/
/* PIVOT GetMaxSize: returns the maximum number of rows in the table. */
@@ -569,7 +548,7 @@ int TDBPIVOT::GetMaxSize(PGLOBAL g)
return MaxSize;
#endif // 0
- return 0;
+ return 10;
} // end of GetMaxSize
/***********************************************************************/
@@ -586,8 +565,6 @@ int TDBPIVOT::RowNumber(PGLOBAL g, bool b)
/***********************************************************************/
bool TDBPIVOT::OpenDB(PGLOBAL g)
{
-//PDBUSER dup = (PDBUSER)g->Activityp->Aptr;
-
if (Use == USE_OPEN) {
/*******************************************************************/
/* Table already open, just replace it at its beginning. */
@@ -598,13 +575,6 @@ bool TDBPIVOT::OpenDB(PGLOBAL g)
return FALSE;
} // endif use
- /*********************************************************************/
- /* Do it here if not done yet (should not be the case). */
- /*********************************************************************/
-//if (MakePivotColumns(g) < 0)
- if (!(Qryp = GetSourceTable(g)))
- return TRUE;
-
if (Mode != MODE_READ) {
/*******************************************************************/
/* Currently PIVOT tables cannot be modified. */
@@ -621,7 +591,26 @@ bool TDBPIVOT::OpenDB(PGLOBAL g)
return TRUE;
} // endif To_Key_Col
- return FALSE;
+ /*********************************************************************/
+ /* Do it here if not done yet (should not be the case). */
+ /*********************************************************************/
+ if (GetSourceTable(g))
+ return TRUE;
+
+ // For tables, columns must be allocated before opening
+ if (MakePivotColumns(g))
+ return TRUE;
+
+ /*********************************************************************/
+ /* Physically open the object table. */
+ /*********************************************************************/
+ if (Tdbp->OpenDB(g))
+ return TRUE;
+
+ /*********************************************************************/
+ /* Make all required pivot columns for object views. */
+ /*********************************************************************/
+ return MakeViewColumns(g);
} // end of OpenDB
/***********************************************************************/
@@ -632,7 +621,6 @@ int TDBPIVOT::ReadDB(PGLOBAL g)
int rc = RC_OK;
bool newrow = FALSE;
PCOL colp;
- PVAL vp1, vp2;
if (FileStatus == 2)
return RC_EF;
@@ -652,7 +640,7 @@ int TDBPIVOT::ReadDB(PGLOBAL g)
/*********************************************************************/
do {
if (RowFlag != 1) {
- if ((rc = Tqrp->ReadDB(g)) != RC_OK) {
+ if ((rc = Tdbp->ReadDB(g)) != RC_OK) {
if (FileStatus && rc == RC_EF) {
// A prepared row remains to be sent
FileStatus = 2;
@@ -662,14 +650,16 @@ int TDBPIVOT::ReadDB(PGLOBAL g)
break;
} // endif rc
- for (colp = Tqrp->GetColumns(); colp; colp = colp->GetNext())
+ for (colp = Tdbp->GetColumns(); colp; colp = colp->GetNext())
colp->ReadColumn(g);
for (colp = Columns; colp; colp = colp->GetNext())
if (colp->GetAmType() == TYPE_AM_SRC)
if (FileStatus) {
- if (((PSRCCOL)colp)->CompareColumn())
+ if (((PSRCCOL)colp)->CompareLast()) {
newrow = (RowFlag) ? TRUE : FALSE;
+ break;
+ } // endif CompareLast
} else
((PSRCCOL)colp)->SetColumn();
@@ -683,21 +673,21 @@ int TDBPIVOT::ReadDB(PGLOBAL g)
} else
RowFlag = 2;
- vp1 = Xcolp->GetValue();
-
// Look for the column having this header
for (colp = Columns; colp; colp = colp->GetNext())
if (colp->GetAmType() == TYPE_AM_FNC) {
- vp2 = ((PFNCCOL)colp)->Hval;
-
- if (!vp1->CompareValue(vp2))
+ if (((PFNCCOL)colp)->CompareColumn())
break;
} // endif AmType
- if (!colp) {
- strcpy(g->Message, MSG(NO_MATCH_COL));
- return RC_FX;
+ if (!colp && !(colp = Dcolp)) {
+ if (!Accept) {
+ strcpy(g->Message, MSG(NO_MATCH_COL));
+ return RC_FX;
+ } else
+ continue;
+
} // endif colp
// Set the value of the matching column from the fonction value
@@ -731,131 +721,79 @@ int TDBPIVOT::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
void TDBPIVOT::CloseDB(PGLOBAL g)
{
-//Tdbp->CloseDB(g);
- } // end of CloseDB
+ if (Tdbp)
+ Tdbp->CloseDB(g);
-/***********************************************************************/
-/* TDBPIVOT: Compare routine for sorting pivot column values. */
-/***********************************************************************/
-int TDBPIVOT::Qcompare(int *i1, int *i2)
- {
- // TODO: the actual comparison between pivot column result values.
- return Rblkp->CompVal(*i1, *i2);
- } // end of Qcompare
+ } // end of CloseDB
// ------------------------ FNCCOL functions ----------------------------
/***********************************************************************/
/* FNCCOL public constructor. */
/***********************************************************************/
-FNCCOL::FNCCOL(PCOL col1, PTDBPIVOT tdbp)
- : COLBLK(col1, tdbp)
+FNCCOL::FNCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
+ : COLBLK(cdp, tdbp, i)
{
+ if (cprec) {
+ Next = cprec->GetNext();
+ cprec->SetNext(this);
+ } else {
+ Next = tdbp->GetColumns();
+ tdbp->SetColumns(this);
+ } // endif cprec
+
Value = NULL; // We'll get a new one later
- Hval = NULL; // The unconverted header value
+ Hval = NULL; // The unconverted header value
+ Xcolp = NULL;
} // end of FNCCOL constructor
/***********************************************************************/
-/* FNCCOL initialization function. */
+/* FNCCOL initialization function. */
/***********************************************************************/
-bool FNCCOL::InitColumn(PGLOBAL g, PVAL valp)
+bool FNCCOL::InitColumn(PGLOBAL g)
{
- char *p, buf[128];
- int len;
-
// Must have its own value block
if (InitValue(g))
return TRUE;
- // Convert header value to a null terminated character string
- Hval = valp;
- p = Hval->GetCharString(buf);
- len = strlen(p) + 1;
+ // Make a value from the column name
+ Hval = AllocateValue(g, Name, TYPE_STRING);
+ Hval->SetPrec(1); // Case insensitive
- if (len > (signed)sizeof(buf)) {
- strcpy(g->Message, MSG(COLNAM_TOO_LONG));
- return TRUE;
- } // endif buf
-
- // Set the name of the functional pivot column
- Name = (PSZ)PlugSubAlloc(g, NULL, len);
- strcpy(Name, p);
+ Xcolp = ((PTDBPIVOT)To_Tdb)->Xcolp;
AddStatus(BUF_READ); // All is done here
return FALSE;
} // end of InitColumn
-// ------------------------ SRCCOL functions ----------------------------
-
-#if 0
/***********************************************************************/
-/* SRCCOL public constructor. */
+/* CompareColumn: Compare column value with source column value. */
/***********************************************************************/
-SRCCOL::SRCCOL(PCOLDEF cdp, PTDBPIVOT tdbp, int n)
- : COLBLK(cdp, tdbp, n)
+bool FNCCOL::CompareColumn(void)
{
- // Set additional SRC access method information for column.
- Colp = NULL;
- Cnval = NULL;
- } // end of SRCCOL constructor
-#endif // 0
+ // Compare the unconverted values
+ return Hval->IsEqual(Xcolp->GetValue(), false);
+ } // end of CompareColumn
+
+// ------------------------ SRCCOL functions ----------------------------
/***********************************************************************/
/* SRCCOL public constructor. */
/***********************************************************************/
-SRCCOL::SRCCOL(PCOL cp, PTDBPIVOT tdbp, int n)
- : COLBLK(cp, tdbp)
+SRCCOL::SRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int n)
+ : PRXCOL(cdp, tdbp, cprec, n)
{
- Index = n;
-
- // Set additional SRC access method information for column.
- Colp = (PQRSCOL)cp;
-
- // Don't share Value with the source column so we can compare
- Cnval = Value = NULL;
} // end of SRCCOL constructor
-#if 0
-/***********************************************************************/
-/* SRCCOL constructor used for copying columns. */
-/* tdbp is the pointer to the new table descriptor. */
-/***********************************************************************/
-SRCCOL::SRCCOL(SRCCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
- {
- Colp = col1->Colp;
- } // end of SRCCOL copy constructor
-#endif // 0
-
/***********************************************************************/
/* Initialize the column as pointing to the source column. */
/***********************************************************************/
-bool SRCCOL::Init(PGLOBAL g, PTDBPIVOT tdbp)
+bool SRCCOL::Init(PGLOBAL g)
{
- // Currently we ignore the type of the create table column
- bool conv = FALSE;
-
-#if 0
- if (!Colp) {
- // Column was defined in the Create Table statement
- if (!(Colp = tdbp->ColDB(g, Name, 0)))
- return TRUE;
-
- // We can have a conversion problem converting from numeric to
- // character because GetCharValue does not exist for numeric types.
- conv = (IsTypeChar(Buf_Type) && IsTypeNum(Colp->GetResultType()));
- } else
-#endif // 0
- conv = FALSE;
-
- if (InitValue(g))
- return TRUE;
-
-//if (conv)
-// Cnval = AllocateValue(g, Colp->GetValue());
-//else
- Cnval = Value;
+ if (PRXCOL::Init(g))
+ return true;
AddStatus(BUF_READ); // All is done here
- return FALSE;
+ return false;
} // end of SRCCOL constructor
/***********************************************************************/
@@ -863,340 +801,16 @@ bool SRCCOL::Init(PGLOBAL g, PTDBPIVOT tdbp)
/***********************************************************************/
void SRCCOL::SetColumn(void)
{
-#if defined(_DEBUG)
- Cnval->SetValue_pval(Colp->GetValue(), TRUE);
-#else
- Cnval->SetValue_pval(Colp->GetValue());
-#endif // _DEBUG
-
- if (Value != Cnval)
- // Convert value
- Value->SetValue_pval(Cnval);
-
+ Value->SetValue_pval(To_Val);
} // end of SetColumn
/***********************************************************************/
/* SetColumn: Compare column value with source column value. */
/***********************************************************************/
-bool SRCCOL::CompareColumn(void)
+bool SRCCOL::CompareLast(void)
{
// Compare the unconverted values
- return Cnval->CompareValue(Colp->GetValue());
+ return !Value->IsEqual(To_Val, true);
} // end of CompareColumn
-
-/* ------------------------------------------------------------------- */
-
-/***********************************************************************/
-/* Implementation of the TDBQRS class. */
-/***********************************************************************/
-TDBQRS::TDBQRS(PTDBQRS tdbp) : TDBASE(tdbp)
- {
- Qrp = tdbp->Qrp;
- CurPos = tdbp->CurPos;
- } // end of TDBQRS copy constructor
-
-// Method
-PTDB TDBQRS::CopyOne(PTABS t)
- {
- PTDB tp;
- PQRSCOL cp1, cp2;
- PGLOBAL g = t->G; // Is this really useful ???
-
- tp = new(g) TDBQRS(this);
-
- for (cp1 = (PQRSCOL)Columns; cp1; cp1 = (PQRSCOL)cp1->GetNext()) {
- cp2 = new(g) QRSCOL(cp1, tp); // Make a copy
- NewPointer(t, cp1, cp2);
- } // endfor cp1
-
- return tp;
- } // end of CopyOne
-
-#if 0 // The TDBASE functions return NULL when To_Def is NULL
-/***********************************************************************/
-/* Return the pointer on the DB catalog this table belongs to. */
-/***********************************************************************/
-PCATLG TDBQRS::GetCat(void)
- {
- // To_Def is null for QRYRES tables
- return NULL;
- } // end of GetCat
-
-/***********************************************************************/
-/* Return the datapath of the DB this table belongs to. */
-/***********************************************************************/
-PSZ TDBQRS::GetPath(void)
- {
- // To_Def is null for QRYRES tables
- return NULL;
- } // end of GetPath
-#endif // 0
-
-/***********************************************************************/
-/* Initialize QRS column description block construction. */
-/* name is used to call columns by name. */
-/* num is used by LNA to construct columns by index number. */
-/* Note: name=Null and num=0 for constructing all columns (select *) */
-/***********************************************************************/
-PCOL TDBQRS::ColDB(PGLOBAL g, PSZ name, int num)
- {
- int i;
- PCOLRES crp;
- PCOL cp, colp = NULL, cprec = NULL;
-
- if (trace)
- htrc("QRS ColDB: colname=%s tabname=%s num=%d\n",
- SVP(name), Name, num);
-
- for (crp = Qrp->Colresp, i = 1; crp; crp = crp->Next, i++)
- if ((!name && !num) ||
- (name && !stricmp(crp->Name, name)) || num == i) {
- // Check for existence of desired column
- // Also find where to insert the new block
- for (cp = Columns; cp; cp = cp->GetNext())
- if (cp->GetIndex() < i)
- cprec = cp;
- else if (cp->GetIndex() == i)
- break;
-
- if (trace) {
- if (cp)
- htrc("cp(%d).Name=%s cp=%p\n", i, cp->GetName(), cp);
- else
- htrc("cp(%d) cp=%p\n", i, cp);
- } // endif trace
-
- // Now take care of Column Description Block
- if (cp)
- colp = cp;
- else
- colp = new(g) QRSCOL(g, crp, this, cprec, i);
-
- if (name || num)
- break;
- else
- cprec = colp;
-
- } // endif Name
-
- return (colp);
- } // end of ColDB
-
-/***********************************************************************/
-/* QRS GetMaxSize: returns maximum table size in number of lines. */
-/***********************************************************************/
-int TDBQRS::GetMaxSize(PGLOBAL g)
- {
- MaxSize = Qrp->Maxsize;
- return MaxSize;
- } // end of GetMaxSize
-
-/***********************************************************************/
-/* RowNumber: returns the current row ordinal number. */
-/***********************************************************************/
-int TDBQRS::RowNumber(PGLOBAL g, BOOL b)
- {
- return (CurPos + 1);
- } // end of RowNumber
-
-/***********************************************************************/
-/* QRS Access Method opening routine. */
-/* New method now that this routine is called recursively (last table */
-/* first in reverse order): index blocks are immediately linked to */
-/* join block of next table if it exists or else are discarted. */
-/***********************************************************************/
-bool TDBQRS::OpenDB(PGLOBAL g)
- {
- if (trace)
- htrc("QRS OpenDB: tdbp=%p tdb=R%d use=%d key=%p mode=%d\n",
- this, Tdb_No, Use, To_Key_Col, Mode);
-
- if (Mode != MODE_READ) {
- sprintf(g->Message, MSG(BAD_QUERY_OPEN), Mode);
- return TRUE;
- } // endif Mode
-
- CurPos = -1;
-
- if (Use == USE_OPEN) {
- /*******************************************************************/
- /* Table already open, just replace it at its beginning. */
- /*******************************************************************/
- if (To_Kindex)
- /*****************************************************************/
- /* Table is to be accessed through a sorted index table. */
- /*****************************************************************/
- To_Kindex->Reset();
-
- return FALSE;
- } // endif use
-
- /*********************************************************************/
- /* Open (retrieve data from) the query if not already open. */
- /*********************************************************************/
- Use = USE_OPEN; // Do it now in case we are recursively called
-
- return FALSE;
- } // end of OpenDB
-
-/***********************************************************************/
-/* GetRecpos: returns current position of next sequential read. */
-/***********************************************************************/
-int TDBQRS::GetRecpos(void)
- {
- return (CurPos);
- } // end of GetRecpos
-
-/***********************************************************************/
-/* ReadDB: Data Base read routine for QRS access method. */
-/***********************************************************************/
-int TDBQRS::ReadDB(PGLOBAL g)
- {
- int rc = RC_OK;
-
- if (trace)
- htrc("QRS ReadDB: R%d CurPos=%d key=%p link=%p Kindex=%p\n",
- GetTdb_No(), CurPos, To_Key_Col, To_Link, To_Kindex);
-
- if (To_Kindex) {
- /*******************************************************************/
- /* Reading is by an index table. */
- /*******************************************************************/
- int recpos = To_Kindex->Fetch(g);
-
- switch (recpos) {
- case -1: // End of file reached
- rc = RC_EF;
- break;
- case -2: // No match for join
- rc = RC_NF;
- break;
- case -3: // Same record as last non null one
- rc = RC_OK;
- break;
- default:
- /***************************************************************/
- /* Set the file position according to record to read. */
- /***************************************************************/
- CurPos = recpos;
- } // endswitch recpos
-
- if (trace)
- htrc("Position is now %d\n", CurPos);
-
- } else
- /*******************************************************************/
- /* !To_Kindex ---> sequential reading */
- /*******************************************************************/
- rc = (++CurPos < Qrp->Nblin) ? RC_OK : RC_EF;
-
- return rc;
- } // end of ReadDB
-
-/***********************************************************************/
-/* Dummy WriteDB: just send back an error return. */
-/***********************************************************************/
-int TDBQRS::WriteDB(PGLOBAL g)
- {
- strcpy(g->Message, MSG(QRY_READ_ONLY));
- return RC_FX;
- } // end of WriteDB
-
-/***********************************************************************/
-/* Dummy DeleteDB routine, just returns an error code. */
-/***********************************************************************/
-int TDBQRS::DeleteDB(PGLOBAL g, int irc)
- {
- strcpy(g->Message, MSG(NO_QRY_DELETE));
- return RC_FX;
- } // end of DeleteDB
-
-/***********************************************************************/
-/* Data Base close routine for QRS access method. */
-/***********************************************************************/
-void TDBQRS::CloseDB(PGLOBAL g)
- {
- if (To_Kindex) {
- To_Kindex->Close();
- To_Kindex = NULL;
- } // endif
-
- if (trace)
- htrc("Qryres CloseDB");
-
-//Qryp->Sqlp->CloseDB();
- } // end of CloseDB
-
-// ------------------------ QRSCOL functions ----------------------------
-
-/***********************************************************************/
-/* QRSCOL public constructor. */
-/***********************************************************************/
-QRSCOL::QRSCOL(PGLOBAL g, PCOLRES crp, PTDB tdbp, PCOL cprec, int i)
- : COLBLK(NULL, tdbp, i)
- {
- if (cprec) {
- Next = cprec->GetNext();
- cprec->SetNext(this);
- } else {
- Next = tdbp->GetColumns();
- tdbp->SetColumns(this);
- } // endif cprec
-
- // Set additional QRS access method information for column.
- Crp = crp;
- Name = Crp->Name;
- Long = Crp->Clen;
- Buf_Type = crp->Type;
- strcpy(Format.Type, GetFormatType(Buf_Type));
- Format.Length = (SHORT)Long;
- Format.Prec = (SHORT)Crp->Prec;
-
- if (trace) {
- htrc("Making new QRSCOL C%d %s at %p\n", Index, Name, this);
- htrc(" BufType=%d Long=%d length=%d clen=%d\n",
- Buf_Type, Long, Format.Length, Crp->Clen);
- } // endif trace
-
- } // end of QRSCOL constructor
-
-/***********************************************************************/
-/* QRSCOL constructor used for copying columns. */
-/* tdbp is the pointer to the new table descriptor. */
-/***********************************************************************/
-QRSCOL::QRSCOL(QRSCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
- {
- Crp = col1->Crp;
- } // end of QRSCOL copy constructor
-
-/***********************************************************************/
-/* ReadColumn: what this routine does is to extract the RESCOL block */
-/* current value and convert it to the column buffer type. */
-/***********************************************************************/
-void QRSCOL::ReadColumn(PGLOBAL g)
- {
- PTDBQRS tdbp = (PTDBQRS)To_Tdb;
-
- if (trace)
- htrc("QRS RC: col %s R%d type=%d CurPos=%d Len=%d\n",
- Name, tdbp->GetTdb_No(), Buf_Type, tdbp->CurPos, Crp->Clen);
-
- if (Crp->Kdata)
- Value->SetValue_pvblk(Crp->Kdata, tdbp->CurPos);
- else
- Value->Reset();
-
- } // end of ReadColumn
-
-/***********************************************************************/
-/* Make file output of a Dos column descriptor block. */
-/***********************************************************************/
-void QRSCOL::Print(PGLOBAL g, FILE *f, UINT n)
- {
- COLBLK::Print(g, f, n);
-
- fprintf(f, " Crp=%p\n", Crp);
- } // end of Print
-
/* --------------------- End of TabPivot/TabQrs ---------------------- */
diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h
index fb480b9abbf..170c6b67ea4 100644
--- a/storage/connect/tabpivot.h
+++ b/storage/connect/tabpivot.h
@@ -1,15 +1,48 @@
/************** TabPivot H Declares Source Code File (.H) **************/
-/* Name: TABPIVOT.H Version 1.3 */
+/* Name: TABPIVOT.H Version 1.5 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
/* */
/* This file contains the PIVOT classes declares. */
/***********************************************************************/
+typedef class PIVOTDEF *PPIVOTDEF;
typedef class TDBPIVOT *PTDBPIVOT;
typedef class FNCCOL *PFNCCOL;
typedef class SRCCOL *PSRCCOL;
-typedef class TDBQRS *PTDBQRS;
-typedef class QRSCOL *PQRSCOL;
+
+/***********************************************************************/
+/* This class is used to generate PIVOT table column definitions. */
+/***********************************************************************/
+class PIVAID : public CSORT {
+ friend class FNCCOL;
+ friend class SRCCOL;
+ public:
+ // Constructor
+ PIVAID(const char *tab, const char *src, const char *picol,
+ const char *fncol, const char *host, const char *db,
+ const char *user, const char *pwd, int port);
+
+ // Methods
+ PQRYRES MakePivotColumns(PGLOBAL g);
+
+ // The sorting function
+ virtual int Qcompare(int *, int *);
+
+ protected:
+ // Members
+ MYSQLC Myc; // MySQL connection class
+ char *Host; // Host machine to use
+ char *User; // User logon info
+ char *Pwd; // Password logon info
+ char *Database; // Database to be used by server
+ PQRYRES Qryp; // Points to Query result block
+ char *Tabname; // Name of source table
+ char *Tabsrc; // SQL of source table
+ char *Picol; // Pivot column name
+ char *Fncol; // Function column name
+ PVBLK Rblkp; // The value block of the pivot column
+ int Port; // MySQL port number
+ }; // end of class PIVAID
/* -------------------------- PIVOT classes -------------------------- */
@@ -22,13 +55,11 @@ typedef class QRSCOL *PQRSCOL;
/***********************************************************************/
/* PIVOT table. */
/***********************************************************************/
-//ass DllExport PIVOTDEF : public TABDEF {/* Logical table description */
-class PIVOTDEF : public TABDEF { /* Logical table description */
+class PIVOTDEF : public PRXDEF { /* Logical table description */
friend class TDBPIVOT;
public:
// Constructor
- PIVOTDEF(void) {Pseudo = 3;
- Tabname = Tabsrc = Picol = Fncol = Function = NULL;}
+ PIVOTDEF(void);
// Implementation
virtual const char *GetType(void) {return "PIVOT";}
@@ -39,38 +70,33 @@ class PIVOTDEF : public TABDEF { /* Logical table description */
protected:
// Members
- char *Host; /* Host machine to use */
- char *User; /* User logon info */
- char *Pwd; /* Password logon info */
- char *DB; /* Database to be used by server */
- char *Tabname; /* Name of source table */
+ char *Host; /* Host machine to use */
+ char *User; /* User logon info */
+ char *Pwd; /* Password logon info */
+ char *DB; /* Database to be used by server */
+ char *Tabname; /* Name of source table */
char *Tabsrc; /* The source table SQL description */
- char *Picol; /* The pivot column */
+ char *Picol; /* The pivot column */
char *Fncol; /* The function column */
char *Function; /* The function applying to group by */
bool GBdone; /* True if tabname as group by format */
- int Port; /* MySQL port number */
+ bool Accept; /* TRUE if no match is accepted */
+ int Port; /* MySQL port number */
}; // end of PIVOTDEF
/***********************************************************************/
/* This is the class declaration for the PIVOT table. */
/***********************************************************************/
-//ass DllExport TDBPIVOT : public TDBASE, public CSORT {
-class TDBPIVOT : public TDBASE, public CSORT {
+class TDBPIVOT : public TDBPRX {
friend class FNCCOL;
- friend class SRCCOL;
public:
// Constructor
TDBPIVOT(PPIVOTDEF tdp);
-//TDBPIVOT(PTDBPIVOT tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_PIVOT;}
-//virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBPIVOT(this);}
-// void SetTdbp(PTDB tdbp) {Tdbp = tdbp;}
// Methods
-//virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void) {return N;}
virtual void ResetDB(void) {N = 0;}
virtual int RowNumber(PGLOBAL g, bool b = FALSE);
@@ -84,40 +110,35 @@ class TDBPIVOT : public TDBASE, public CSORT {
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
- // The sorting function
- virtual int Qcompare(int *, int *);
-
protected:
- PQRYRES GetSourceTable(PGLOBAL g);
- int MakePivotColumns(PGLOBAL g);
- bool UpdateTableFields(PGLOBAL g, int n);
+ // Internal routines
+ bool FindDefaultColumns(PGLOBAL g);
+ bool GetSourceTable(PGLOBAL g);
+ bool MakePivotColumns(PGLOBAL g);
+ bool MakeViewColumns(PGLOBAL g);
// Members
- MYSQLC Myc; // MySQL connection class
- PTDBQRS Tqrp; // To the source table result
- char *Host; // Host machine to use
- char *User; // User logon info
- char *Pwd; // Password logon info
- char *Database; // Database to be used by server
- PQRYRES Qryp; // Points to Query result block
- char *Tabname; // Name of source table
- char *Tabsrc; // SQL of source table
- char *Picol; // Pivot column name
- char *Fncol; // Function column name
- char *Function; // The function applying to group by
- PQRSCOL Fcolp; // To the function column in source
- PQRSCOL Xcolp; // To the pivot column in source
- PCOLRES Xresp; // To the pivot result column
-//PCOLRES To_Sort; // Saved Qryp To_Sort pointer
- PVBLK Rblkp; // The value block of the pivot column
- bool GBdone; // True when subtable is "Group by"
- int Mult; // Multiplication factor
- int Ncol; // The number of generated columns
- int N; // The current table index
- int M; // The occurence rank
- int Port; // MySQL port number
- BYTE FileStatus; // 0: First 1: Rows 2: End-of-File
- BYTE RowFlag; // 0: Ok, 1: Same, 2: Skip
+ char *Host; // Host machine to use
+ char *User; // User logon info
+ char *Pwd; // Password logon info
+ char *Database; // Database to be used by server
+ char *Tabname; // Name of source table
+ char *Tabsrc; // SQL of source table
+ char *Picol; // Pivot column name
+ char *Fncol; // Function column name
+ char *Function; // The function applying to group by
+ PCOL Fcolp; // To the function column in source
+ PCOL Xcolp; // To the pivot column in source
+ PCOL Dcolp; // To the dump column
+ bool GBdone; // True when subtable is "Group by"
+ bool Accept; // TRUE if no match is accepted
+ int Mult; // Multiplication factor
+ int Ncol; // The number of generated columns
+ int N; // The current table index
+ int M; // The occurence rank
+ int Port; // MySQL port number
+ BYTE FileStatus; // 0: First 1: Rows 2: End-of-File
+ BYTE RowFlag; // 0: Ok, 1: Same, 2: Skip
}; // end of class TDBPIVOT
/***********************************************************************/
@@ -127,30 +148,30 @@ class FNCCOL : public COLBLK {
friend class TDBPIVOT;
public:
// Constructor
- FNCCOL(PCOL colp, PTDBPIVOT tdbp);
+ FNCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
// Implementation
virtual int GetAmType(void) {return TYPE_AM_FNC;}
// Methods
virtual void Reset(void) {}
- bool InitColumn(PGLOBAL g, PVAL valp);
+ bool InitColumn(PGLOBAL g);
+ bool CompareColumn(void);
protected:
// Member
- PVAL Hval; // The original value used to generate the header
+ PVAL Hval; // The value containing the header
+ PCOL Xcolp;
}; // end of class FNCCOL
/***********************************************************************/
/* Class SRCCOL: for other source columns. */
/***********************************************************************/
-class SRCCOL : public COLBLK {
+class SRCCOL : public PRXCOL {
friend class TDBPIVOT;
public:
// Constructors
-//SRCCOL(PCOLDEF cdp, PTDBPIVOT tdbp, int n);
- SRCCOL(PCOL cp, PTDBPIVOT tdbp, int n);
-//SRCCOL(SRCCOL *colp, PTDB tdbp); // Constructor used in copy process
+ SRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int n);
// Implementation
virtual int GetAmType(void) {return TYPE_AM_SRC;}
@@ -158,84 +179,12 @@ class SRCCOL : public COLBLK {
// Methods
virtual void Reset(void) {}
void SetColumn(void);
- bool Init(PGLOBAL g, PTDBPIVOT tdbp);
- bool CompareColumn(void);
+ bool Init(PGLOBAL g);
+ bool CompareLast(void);
protected:
// Default constructor not to be used
SRCCOL(void) {}
// Members
- PQRSCOL Colp;
- PVAL Cnval;
}; // end of class SRCCOL
-
-/***********************************************************************/
-/* TDBQRS: This is the Access Method class declaration for the Query */
-/* Result stored in memory in the current work area (volatil). */
-/***********************************************************************/
-class DllExport TDBQRS : public TDBASE {
- friend class QRSCOL;
- public:
- // Constructor
- TDBQRS(PQRYRES qrp) : TDBASE() {Qrp = qrp; CurPos = 0;}
- TDBQRS(PTDBQRS tdbp);
-
- // Implementation
- virtual AMT GetAmType(void) {return TYPE_AM_QRS;}
- virtual PTDB Duplicate(PGLOBAL g)
- {return (PTDB)new(g) TDBQRS(this);}
- PQRYRES GetQrp(void) {return Qrp;}
-
- // Methods
- virtual PTDB CopyOne(PTABS t);
- virtual int RowNumber(PGLOBAL g, BOOL b = FALSE);
- virtual int GetRecpos(void);
-//virtual PCATLG GetCat(void);
-//virtual PSZ GetPath(void);
- virtual int GetBadLines(void) {return Qrp->BadLines;}
-
- // Database routines
- virtual PCOL ColDB(PGLOBAL g, PSZ name, int num);
- 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);
-
- private:
- TDBQRS(void) : TDBASE() {} // Standard constructor not to be used
-
- protected:
- // Members
- PQRYRES Qrp; // Points to Query Result block
- int CurPos; // Current line position
- }; // end of class TDBQRS
-
-/***********************************************************************/
-/* Class QRSCOL: QRS access method column descriptor. */
-/***********************************************************************/
-class DllExport QRSCOL : public COLBLK {
- friend class TDBQRS;
- public:
- // Constructors
- QRSCOL(PGLOBAL g, PCOLRES crp, PTDB tdbp, PCOL cprec, int i);
- QRSCOL(QRSCOL *colp, PTDB tdbp); // Constructor used in copy process
-
- // Implementation
- virtual int GetAmType(void) {return TYPE_AM_QRS;}
- PCOLRES GetCrp(void) {return Crp;}
- void *GetQrsData(void) {return Crp->Kdata;}
-
- // Methods
- virtual void ReadColumn(PGLOBAL g);
- virtual void Print(PGLOBAL g, FILE *, UINT);
-
- protected:
- QRSCOL(void) {} // Default constructor not to be used
-
- // Members
- PCOLRES Crp;
- }; // end of class QRSCOL
-
diff --git a/storage/connect/tabsys.cpp b/storage/connect/tabsys.cpp
index 9f933e4e2b8..6434e011882 100644
--- a/storage/connect/tabsys.cpp
+++ b/storage/connect/tabsys.cpp
@@ -41,9 +41,7 @@
#include "tabdos.h"
#include "tabsys.h"
#include "tabmul.h"
-#if defined(UNIX)
-#include "osutil.h"
-#endif // UNIX
+#include "inihandl.h"
#define CSZ 36 // Column section name length
#define CDZ 256 // Column definition length
@@ -65,7 +63,6 @@ INIDEF::INIDEF(void)
Pseudo = 3;
Fn = NULL;
Xname = NULL;
- Subtype = '?';
Layout = '?';
Ln = 0;
} // end of INIDEF constructor
@@ -75,63 +72,23 @@ INIDEF::INIDEF(void)
/***********************************************************************/
bool INIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
- char buf[8], ds[2];
- void *memp = Cat->GetDescp();
-
- if (!stricmp(am, "SYS"))
- strcpy(ds, "T"); // SYS tables default to T(able)
- else
- strcpy(ds, "I"); // INI tables default to I(ni)
+ char buf[8];
Fn = Cat->GetStringCatInfo(g, "Filename", NULL);
- Cat->GetCharCatInfo("Subtype", ds, buf, sizeof(buf));
- Subtype = toupper(*buf);
Cat->GetCharCatInfo("Layout", "C", buf, sizeof(buf));
Layout = toupper(*buf);
- switch (Subtype) {
-#if 0
- case 'C':
- case 'T':
- // Restricted table
- Xname = Cat->GetStringCatInfo(g, "Name", "?");
-
- if (!strcmp(Xname, "?"))
- Xname = NULL;
-
- if (*Fn == '?')
- Fn = Cat->GetStringCatInfo(g, "Database", "?");
-
- if (*Fn != '?') {
- char *p = (char*)PlugSubAlloc(g, memp, _MAX_PATH);
-
- if (!PlgSetXdbPath(g, Fn, NULL, p, _MAX_PATH, NULL, 0))
- Fn = p;
-
- } else
- Fn = Cat->GetDescFile();
+ if (Fn) {
+ char *p = (char*)PlugSubAlloc(g, NULL, _MAX_PATH);
- Ln = GetIniSize("Database", "Tabsize", "2K", Fn);
- break;
-#endif // 0
- case 'I':
- if (*Fn != '?') {
- char *p = (char*)PlugSubAlloc(g, memp, _MAX_PATH);
-
- PlugSetPath(p, Fn, GetPath());
- Fn = p;
- } else {
- strcpy(g->Message, MSG(MISSING_FNAME));
- return true;
- } // endif Fn
-
- Ln = Cat->GetSizeCatInfo("Secsize", "8K");
- break;
- default:
- sprintf(g->Message, MSG(INV_SUBTYPE), buf);
- return true;
- } // endswitch Subtype
+ PlugSetPath(p, Fn, GetPath());
+ Fn = p;
+ } else {
+ strcpy(g->Message, MSG(MISSING_FNAME));
+ return true;
+ } // endif Fn
+ Ln = Cat->GetSizeCatInfo("Secsize", "8K");
Desc = Fn;
return false;
} // end of DefineAM
@@ -143,17 +100,10 @@ PTDB INIDEF::GetTable(PGLOBAL g, MODE m)
{
PTDBASE tdbp;
- switch (Subtype) {
- case 'I':
- if (Layout == 'C')
- tdbp = new(g) TDBINI(this);
- else
- tdbp = new(g) TDBXIN(this);
-
- break;
- default:
- return NULL;
- } // endswitch Subtype
+ if (Layout == 'C')
+ tdbp = new(g) TDBINI(this);
+ else
+ tdbp = new(g) TDBXIN(this);
if (Multiple)
tdbp = new(g) TDBMUL(tdbp); // No block optimization yet
@@ -163,7 +113,6 @@ PTDB INIDEF::GetTable(PGLOBAL g, MODE m)
/***********************************************************************/
/* DeleteTableFile: Delete INI table files using platform API. */
-/* SysTable and SysColumn tables are readonly and not erasable. */
/***********************************************************************/
bool INIDEF::DeleteTableFile(PGLOBAL g)
{
@@ -171,7 +120,7 @@ bool INIDEF::DeleteTableFile(PGLOBAL g)
bool rc;
// Delete the INI table file if not protected
- if (Subtype == 'I' && !IsReadOnly()) {
+ if (!IsReadOnly()) {
PlugSetPath(filename, Fn, GetPath());
#if defined(WIN32)
rc = !DeleteFile(filename);
diff --git a/storage/connect/tabsys.h b/storage/connect/tabsys.h
index ac8ae05aee9..2780eb3ca98 100644
--- a/storage/connect/tabsys.h
+++ b/storage/connect/tabsys.h
@@ -38,7 +38,6 @@ class DllExport INIDEF : public TABDEF { /* INI table description */
// Members
char *Fn; /* Path/Name of corresponding file */
char *Xname; /* The eventual table name */
- char Subtype; /* I: INI, T: Table, C: Column */
char Layout; /* R: Row, C: Column */
int Ln; /* Length of section list buffer */
}; // end of INIDEF
@@ -83,8 +82,8 @@ class TDBINI : public TDBASE {
// Members
char *Ifile; // The INI file
char *Seclist; // The section list
- char *Section; // The current section
- int Seclen; // Length of seclist buffer
+ char *Section; // The current section
+ int Seclen; // Length of seclist buffer
int N; // The current section index
}; // end of class TDBINI
diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp
index b194da3fc09..89acc53fd4a 100644
--- a/storage/connect/tabtbl.cpp
+++ b/storage/connect/tabtbl.cpp
@@ -1,7 +1,7 @@
/************* TabTbl C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABTBL */
/* ------------- */
-/* Version 1.4 */
+/* Version 1.6 */
/* */
/* COPYRIGHT: */
/* ---------- */
@@ -70,13 +70,23 @@
#include "filamtxt.h"
#include "tabcol.h"
#include "tabdos.h" // TDBDOS and DOSCOL class dcls
-#include "tabtbl.h" // TDBTBL and TBLCOL classes 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(__BORLANDC__)
+#define SYSEXIT void _USERENTRY
+#else
+#define SYSEXIT void
+#endif
+#else // !WIN32
+#define SYSEXIT void *
+#endif // !WIN32
+
extern "C" int trace;
/* ---------------------------- Class TBLDEF ---------------------------- */
@@ -86,7 +96,10 @@ extern "C" int trace;
/**************************************************************************/
TBLDEF::TBLDEF(void)
{
- To_Tables = NULL;
+//To_Tables = NULL;
+ Accept = false;
+ Thread = false;
+ Maxerr = 0;
Ntables = 0;
Pseudo = 3;
} // end of TBLDEF constructor
@@ -100,18 +113,18 @@ bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Desc = "Table list table";
tablist = Cat->GetStringCatInfo(g, "Tablist", "");
- dbname = Cat->GetStringCatInfo(g, "Database", NULL);
+ dbname = Cat->GetStringCatInfo(g, "Dbname", "*");
Ntables = 0;
if (*tablist) {
- char *p, *pn, *pdb;
- PTBL *ptbl = &To_Tables, tbl;
+ char *p, *pn, *pdb;
+ PTABLE tbl;
for (pdb = tablist; ;) {
if ((p = strchr(pdb, ',')))
*p = 0;
- // Analyze the table name, it has the format:
+ // Analyze the table name, it may have the format:
// [dbname.]tabname
if ((pn = strchr(pdb, '.'))) {
*pn++ = 0;
@@ -121,17 +134,18 @@ bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
} // endif p
// Allocate the TBLIST block for that table
- tbl = (PTBL)PlugSubAlloc(g, NULL, sizeof(TBLIST));
- tbl->Next = NULL;
- tbl->Name = pn;
- tbl->DB = pdb;
+ tbl = new(g) XTAB(pn);
+ tbl->SetQualifier(pdb);
if (trace)
- htrc("TBL: Name=%s db=%s\n", tbl->Name, SVP(tbl->DB));
+ htrc("TBL: Name=%s db=%s\n", tbl->GetName(), tbl->GetQualifier());
// Link the blocks
- *ptbl = tbl;
- ptbl = &tbl->Next;
+ if (Tablep)
+ Tablep->Link(tbl);
+ else
+ Tablep = tbl;
+
Ntables++;
if (p)
@@ -142,8 +156,9 @@ bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
} // endfor pdb
Maxerr = Cat->GetIntCatInfo("Maxerr", 0);
- Accept = (Cat->GetBoolCatInfo("Accept", 0) != 0);
- } // endif fsec || tablist
+ Accept = Cat->GetBoolCatInfo("Accept", false);
+ Thread = Cat->GetBoolCatInfo("Thread", false);
+ } // endif tablist
return FALSE;
} // end of DefineAM
@@ -153,15 +168,13 @@ bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
PTDB TBLDEF::GetTable(PGLOBAL g, MODE m)
{
- PTDB tdbp;
-
- /*********************************************************************/
- /* Allocate a TDB of the proper type. */
- /* Column blocks will be allocated only when needed. */
- /*********************************************************************/
- tdbp = new(g) TDBTBL(this);
+ if (Catfunc == FNC_COL)
+ return new(g) TDBTBC(this);
+ else if (Thread)
+ return new(g) TDBTBM(this);
+ else
+ return new(g) TDBTBL(this);
- return tdbp;
} // end of GetTable
/* ------------------------- Class TDBTBL ---------------------------- */
@@ -169,14 +182,14 @@ PTDB TBLDEF::GetTable(PGLOBAL g, MODE m)
/***********************************************************************/
/* TDBTBL constructors. */
/***********************************************************************/
-TDBTBL::TDBTBL(PTBLDEF tdp) : TDBASE(tdp)
+TDBTBL::TDBTBL(PTBLDEF tdp) : TDBPRX(tdp)
{
Tablist = NULL;
CurTable = NULL;
- Tdbp = NULL;
+//Tdbp = NULL;
Accept = tdp->Accept;
Maxerr = tdp->Maxerr;
- Nbf = 0;
+ Nbc = 0;
Rows = 0;
Crp = 0;
// NTables = 0;
@@ -188,7 +201,7 @@ TDBTBL::TDBTBL(PTBLDEF tdp) : TDBASE(tdp)
/***********************************************************************/
PCOL TDBTBL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
- return new(g) TBLCOL(cdp, this, cprec, n);
+ return new(g) PRXCOL(cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/
@@ -213,125 +226,38 @@ PCOL TDBTBL::InsertSpecialColumn(PGLOBAL g, PCOL scp)
} // end of InsertSpecialColumn
/***********************************************************************/
-/* Get the PTDB of a table of the list. */
-/***********************************************************************/
-PTDB TDBTBL::GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp)
- {
- char *db, key[256];
- uint k;
- PTDB tdbp = NULL;
- TABLE_SHARE *s;
- PCATLG cat = To_Def->GetCat();
- PHC hc = ((MYCAT*)cat)->GetHandler();
- THD *thd = (hc->GetTable())->in_use;
-
- if (!thd)
- return NULL; // Should not happen anymore
-
- if (tblp->DB)
- db = tblp->DB;
- else
- db = (char*)hc->GetDBName(NULL);
-
- k = sprintf(key, "%s", db) + 1;
- k += sprintf(key + k, "%s", tblp->Name);
- key[++k] = 0;
-
- if (!(s = alloc_table_share(db, tblp->Name, key, ++k))) {
- strcpy(g->Message, "Error allocating share\n");
- return NULL;
- } // endif s
-
- if (!open_table_def(thd, s)) {
- if (plugin_data(s->db_plugin, handlerton*) != connect_hton) {
-#if defined(MYSQL_SUPPORT)
- // Access sub-table via MySQL API
- if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYSQL"))) {
- sprintf(g->Message, "Cannot access %s.%s", db, tblp->Name);
- return NULL;
- } // endif Define
-
- if (tabp->GetQualifier())
- ((PTDBMY)tdbp)->SetDatabase(tabp->GetQualifier());
-
-#else // !MYSQL_SUPPORT
- sprintf(g->Message, "%s.%s is not a CONNECT table",
- db, tblp->Name);
- return NULL;
-#endif // MYSQL_SUPPORT
- } else {
- // Sub-table is a CONNECT table
- hc->tshp = s;
- tdbp = cat->GetTable(g, tabp);
- hc->tshp = NULL;
- } // endif plugin
-
- } else
- sprintf(g->Message, "Error %d opening share\n", s->error);
-
- if (trace && tdbp)
- htrc("Subtable %s in %s\n",
- tblp->Name, SVP(((PTDBASE)tdbp)->GetDef()->GetDB()));
-
- free_table_share(s);
- return tdbp;
- } // end of GetSubTable
-
-/***********************************************************************/
/* Initializes the table table list. */
/***********************************************************************/
bool TDBTBL::InitTableList(PGLOBAL g)
{
- char *colname;
- int n, colpos;
- PTBL tblp;
- PTABLE tabp;
- PTDB tdbp;
+ int n;
+ PTABLE tp, tabp;
PCOL colp;
PTBLDEF tdp = (PTBLDEF)To_Def;
// PlugSetPath(filename, Tdbp->GetFile(g), Tdbp->GetPath());
- for (n = 0, tblp = tdp->GetTables(); tblp; tblp = tblp->Next) {
- if (TestFil(g, To_Filter, tblp)) {
- // Table or named view
- tabp = new(g) XTAB(tblp->Name);
- tabp->SetQualifier(tblp->DB);
+ for (n = 0, tp = tdp->Tablep; tp; tp = tp->GetNext()) {
+ if (TestFil(g, To_Filter, tp)) {
+ tabp = new(g) XTAB(tp);
// Get the table description block of this table
- if (!(tdbp = GetSubTable(g, tblp, tabp))) {
- if (++Nbf > Maxerr)
+ if (!(Tdbp = GetSubTable(g, tabp))) {
+ if (++Nbc > Maxerr)
return TRUE; // Error return
else
continue; // Skip this table
- } // endif tdbp
+ } else
+ RemoveNext(tabp); // To avoid looping
// We must allocate subtable columns before GetMaxSize is called
// because some (PLG, ODBC?) need to have their columns attached.
// Real initialization will be done later.
- for (PCOL cp = Columns; cp; cp = cp->GetNext())
- if (!cp->IsSpecial()) {
- colname = cp->GetName();
- colpos = ((PTBLCOL)cp)->Colnum;
-
- // We try first to get the column by name
- if (!(colp = tdbp->ColDB(g, colname, 0)) && colpos)
- // When unsuccessful, if a column number was specified
- // try to get the column by its position in the table
- colp = tdbp->ColDB(g, NULL, colpos);
-
- if (!colp) {
- if (!Accept) {
- sprintf(g->Message, MSG(NO_MATCHING_COL),
- colname, tdbp->GetName());
- return TRUE; // Error return
- } // endif !Accept
-
- } else // this is needed in particular by PLG tables
- colp->SetColUse(cp->GetColUse());
-
- } // endif !special
+ for (colp = Columns; colp; colp = colp->GetNext())
+ if (!colp->IsSpecial())
+ if (((PPRXCOL)colp)->Init(g) && !Accept)
+ return TRUE;
if (Tablist)
Tablist->Link(tabp);
@@ -341,7 +267,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
n++;
} // endif filp
- } // endfor tblp
+ } // endfor tp
//NumTables = n;
To_Filter = NULL; // To avoid doing it several times
@@ -351,7 +277,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
/***********************************************************************/
/* Test the tablename against the pseudo "local" filter. */
/***********************************************************************/
-bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTBL tblp)
+bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTABLE tabp)
{
char *fil, op[8], tn[NAME_LEN];
bool neg;
@@ -374,7 +300,7 @@ bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTBL tblp)
if (sscanf(fil, "TABID = '%[^']'", tn) != 1)
return TRUE; // ignore invalid filter
- return !stricmp(tn, tblp->Name);
+ return !stricmp(tn, tabp->GetName());
} else if (!strcmp(op, "IN")) {
char *p, *tnl = (char*)PlugSubAlloc(g, NULL, strlen(fil) - 10);
int n;
@@ -393,7 +319,7 @@ bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTBL tblp)
if (sscanf(tnl, "'%[^']'", tn) != 1)
return TRUE; // ignore invalid filter
- else if (!stricmp(tn, tblp->Name))
+ else if (!stricmp(tn, tabp->GetName()))
return !neg; // Found
tnl = p;
@@ -406,84 +332,20 @@ bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTBL tblp)
} // end of TestFil
/***********************************************************************/
-/* TBL GetProgMax: get the max value for progress information. */
-/***********************************************************************/
-int TDBTBL::GetProgMax(PGLOBAL g)
- {
- PTABLE tblp;
- int n, pmx = 0;
-
- if (!Tablist && InitTableList(g))
- return -1;
-
- for (tblp = Tablist; tblp; tblp = tblp->GetNext())
- if ((n = tblp->GetTo_Tdb()->GetProgMax(g)) > 0)
- pmx += n;
-
- return pmx;
- } // end of GetProgMax
-
-/***********************************************************************/
-/* TBL GetProgCur: get the current value for progress information. */
-/***********************************************************************/
-int TDBTBL::GetProgCur(void)
- {
- return Crp + Tdbp->GetProgCur();
- } // end of GetProgCur
-
-#if 0
-/***********************************************************************/
-/* TBL Cardinality: returns table cardinality in number of rows. */
-/* This function can be called with a null argument to test the */
-/* availability of Cardinality implementation (1 yes, 0 no). */
-/* Can be used on Multiple FIX table only. */
-/***********************************************************************/
-int TDBTBL::Cardinality(PGLOBAL g)
- {
- if (!g)
- return Tdbp->Cardinality(g);
-
- if (!Tablist && InitTableList(g))
- return -1;
-
- int n, card = 0;
-
- for (int i = 0; i < NumFiles; i++) {
- Tdbp->SetFile(g, Filenames[i]);
- Tdbp->ResetSize();
-
- if ((n = Tdbp->Cardinality(g)) < 0) {
-// strcpy(g->Message, MSG(BAD_CARDINALITY));
- return -1;
- } // endif n
-
- card += n;
- } // endfor i
-
- return card;
- } // end of Cardinality
-#endif // 0
-
-/***********************************************************************/
/* Sum up the sizes of all sub-tables. */
/***********************************************************************/
int TDBTBL::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
- PTABLE tblp;
- int mxsz;
+ int mxsz;
if (!Tablist && InitTableList(g))
return 0; // Cannot be calculated at this stage
-// if (Use == USE_OPEN) {
-// strcpy(g->Message, MSG(MAXSIZE_ERROR));
-// return -1;
-// } else
- MaxSize = 0;
+ MaxSize = 0;
- for (tblp = Tablist; tblp; tblp = tblp->GetNext()) {
- if ((mxsz = tblp->GetTo_Tdb()->GetMaxSize(g)) < 0) {
+ for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext()) {
+ if ((mxsz = tabp->GetTo_Tdb()->GetMaxSize(g)) < 0) {
MaxSize = -1;
return mxsz;
} // endif mxsz
@@ -505,8 +367,8 @@ void TDBTBL::ResetDB(void)
if (colp->GetAmType() == TYPE_AM_TABID)
colp->COLBLK::Reset();
- for (PTABLE tblp = Tablist; tblp; tblp = tblp->GetNext())
- ((PTDBASE)tblp->GetTo_Tdb())->ResetDB();
+ for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext())
+ ((PTDBASE)tabp->GetTo_Tdb())->ResetDB();
Tdbp = (PTDBASE)Tablist->GetTo_Tdb();
Crp = 0;
@@ -538,23 +400,12 @@ bool TDBTBL::OpenDB(PGLOBAL g)
return Tdbp->OpenDB(g); // Re-open fist table
} // endif use
-#if 0
- /*********************************************************************/
- /* Direct access needed for join or sorting. */
- /*********************************************************************/
- if (NeedIndexing(g)) {
- // Direct access of TBL tables is not implemented yet
- strcpy(g->Message, MSG(NO_MUL_DIR_ACC));
- return TRUE;
- } // endif NeedIndexing
-#endif // 0
-
/*********************************************************************/
/* When GetMaxsize was called, To_Filter was not set yet. */
/*********************************************************************/
if (To_Filter && Tablist) {
Tablist = NULL;
- Nbf = 0;
+ Nbc = 0;
} // endif To_Filter
/*********************************************************************/
@@ -573,7 +424,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 (((PTBLCOL)cp)->Init(g))
+ else if (((PPRXCOL)cp)->Init(g) && !Accept)
return TRUE;
if (trace)
@@ -627,7 +478,7 @@ int TDBTBL::ReadDB(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
- else if (((PTBLCOL)cp)->Init(g))
+ else if (((PPRXCOL)cp)->Init(g) && !Accept)
return RC_FX;
if (trace)
@@ -648,154 +499,276 @@ int TDBTBL::ReadDB(PGLOBAL g)
return rc;
} // end of ReadDB
+/* ---------------------------- TBTBLK ------------------------------- */
+
/***********************************************************************/
-/* Data Base write routine for MUL access method. */
+/* ReadColumn: */
/***********************************************************************/
-int TDBTBL::WriteDB(PGLOBAL g)
+void TBTBLK::ReadColumn(PGLOBAL g)
{
- strcpy(g->Message, MSG(TABMUL_READONLY));
- return RC_FX; // NIY
- } // end of WriteDB
+ if (trace)
+ htrc("TBT ReadColumn: name=%s\n", Name);
+
+ Value->SetValue_psz((char*)((PTDBTBL)To_Tdb)->Tdbp->GetName());
+
+ } // end of ReadColumn
+
+/* ------------------------- Class TDBTBM ---------------------------- */
/***********************************************************************/
-/* Data Base delete line routine for MUL access method. */
+/* Thread routine that check and open one remote connection. */
/***********************************************************************/
-int TDBTBL::DeleteDB(PGLOBAL g, int irc)
+pthread_handler_t ThreadOpen(void *p)
{
- strcpy(g->Message, MSG(TABMUL_READONLY));
- return RC_FX; // NIY
- } // end of DeleteDB
+ PTBMT cmp = (PTBMT)p;
+
+ if (!my_thread_init()) {
+ set_current_thd(cmp->Thd);
+
+ // Try to open the connection
+ if (!cmp->Tap->GetTo_Tdb()->OpenDB(cmp->G)) {
+ cmp->Ready = true;
+ } else
+ cmp->Rc = RC_FX;
+
+ my_thread_end();
+ } else
+ cmp->Rc = RC_FX;
+
+ return NULL;
+ } // end of ThreadOpen
/***********************************************************************/
-/* Data Base close routine for MUL access method. */
+/* TDBTBM constructors. */
/***********************************************************************/
-void TDBTBL::CloseDB(PGLOBAL g)
+TDBTBM::TDBTBM(PTBLDEF tdp) : TDBTBL(tdp)
{
- if (Tdbp)
- Tdbp->CloseDB(g);
-
- } // end of CloseDB
-
-/* ---------------------------- TBLCOL ------------------------------- */
+ Tmp = NULL; // To data table TBMT structures
+ Cmp = NULL; // Current data table TBMT
+ Bmp = NULL; // To bad (unconnected) TBMT structures
+ Done = false; // TRUE after first GetAllResults
+ Nrc = 0; // Number of remote connections
+ Nlc = 0; // Number of local connections
+ } // end of TDBTBL standard constructor
/***********************************************************************/
-/* TBLCOL public constructor. */
+/* Reset read/write position values. */
/***********************************************************************/
-TBLCOL::TBLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
- : COLBLK(cdp, tdbp, i)
+void TDBTBM::ResetDB(void)
{
- if (cprec) {
- Next = cprec->GetNext();
- cprec->SetNext(this);
- } else {
- Next = tdbp->GetColumns();
- tdbp->SetColumns(this);
- } // endif cprec
-
- // Set additional Dos access method information for column.
- Long = cdp->GetLong(); // ???
-//strcpy(F_Date, cdp->F_Date);
- Colp = NULL;
- To_Val = NULL;
- Pseudo = FALSE;
- Colnum = cdp->GetOffset(); // If columns are retrieved by number
+ for (PCOL colp = Columns; colp; colp = colp->GetNext())
+ if (colp->GetAmType() == TYPE_AM_TABID)
+ colp->COLBLK::Reset();
- if (trace)
- htrc(" making new %sCOL C%d %s at %p\n", am, Index, Name, this);
+ for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext())
+ ((PTDBASE)tabp->GetTo_Tdb())->ResetDB();
- } // end of TBLCOL constructor
+ Tdbp = (PTDBASE)Tablist->GetTo_Tdb();
+ Crp = 0;
+ } // end of ResetDB
-#if 0
/***********************************************************************/
-/* TBLCOL public constructor. */
+/* Returns RowId if b is false or Rownum if b is true. */
/***********************************************************************/
-TBLCOL::TBLCOL(SPCBLK *scp, PTDB tdbp) : COLBLK(scp->GetName(), tdbp, 0)
+int TDBTBM::RowNumber(PGLOBAL g, bool b)
{
- // Set additional TBL access method information for pseudo column.
- Is_Key = Was_Key = scp->IsKey();
- Long = scp->GetLength();
- Buf_Type = scp->GetResultType();
- *Format.Type = (Buf_Type == TYPE_INT) ? 'N' : 'C';
- Format.Length = Long;
- Colp = NULL;
- To_Val = NULL;
- Pseudo = TRUE;
- } // end of TBLCOL constructor
-
-/***********************************************************************/
-/* TBLCOL constructor used for copying columns. */
-/* tdbp is the pointer to the new table descriptor. */
-/***********************************************************************/
-TBLCOL::TBLCOL(TBLCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
+ return Tdbp->RowNumber(g) + ((b) ? 0 : Rows);
+ } // end of RowNumber
+
+/***********************************************************************/
+/* Initialyze table parallel processing. */
+/***********************************************************************/
+bool TDBTBM::OpenTables(PGLOBAL g)
{
- Long = col1->Long;
- Colp = col1->Colp;
- To_Val = col1->To_Val;
- Pseudo = col1->Pseudo;
- } // end of TBLCOL copy constructor
-#endif
+ int k;
+ THD *thd = current_thd;
+ PTABLE tabp, *ptabp = &Tablist;
+ PTBMT tp, *ptp = &Tmp;
+
+ // Allocates the TBMT blocks for the tables
+ for (tabp = Tablist; tabp; tabp = tabp->Next)
+ if (tabp->GetTo_Tdb()->GetAmType() == TYPE_AM_MYSQL) {
+ // Remove remote table from the local list
+ *ptabp = tabp->Next;
+
+ // Make the remote table block
+ tp = (PTBMT)PlugSubAlloc(g, NULL, sizeof(TBMT));
+ memset(tp, 0, sizeof(TBMT));
+ tp->G = g;
+ tp->Tap = tabp;
+ tp->Thd = thd;
+
+ // Create the thread that will do the table opening.
+ pthread_attr_init(&tp->attr);
+// pthread_attr_setdetachstate(&tp->attr, PTHREAD_CREATE_JOINABLE);
+
+ if ((k = pthread_create(&tp->Tid, &tp->attr, ThreadOpen, tp))) {
+ sprintf(g->Message, "pthread_create error %d", k);
+ Nbc++;
+ continue;
+ } // endif k
+
+ // Add it to the remote list
+ *ptp = tp;
+ ptp = &tp->Next;
+ Nrc++; // Number of remote connections
+ } else {
+ ptabp = &tabp->Next;
+ Nlc++; // Number of local connections
+ } // endif Type
+
+ return false;
+ } // end of OpenTables
/***********************************************************************/
-/* TBLCOL initialization routine. */
-/* Look for the matching column in the current table. */
+/* TBL Access Method opening routine. */
+/* Open first file, other will be opened sequencially when reading. */
/***********************************************************************/
-bool TBLCOL::Init(PGLOBAL g)
+bool TDBTBM::OpenDB(PGLOBAL g)
{
- PTDBTBL tdbp = (PTDBTBL)To_Tdb;
+ if (trace)
+ htrc("TBM OpenDB: tdbp=%p tdb=R%d use=%d key=%p mode=%d\n",
+ this, Tdb_No, Use, To_Key_Col, Mode);
+
+ if (Use == USE_OPEN) {
+ /*******************************************************************/
+ /* Table already open, replace it at its beginning. */
+ /*******************************************************************/
+ ResetDB();
+ return Tdbp->OpenDB(g); // Re-open fist table
+ } // endif use
- To_Val = NULL;
+#if 0
+ /*********************************************************************/
+ /* When GetMaxsize was called, To_Filter was not set yet. */
+ /*********************************************************************/
+ if (To_Filter && Tablist) {
+ Tablist = NULL;
+ Nbc = 0;
+ } // endif To_Filter
+#endif // 0
- if (!(Colp = tdbp->Tdbp->ColDB(g, Name, 0)) && Colnum)
- Colp = tdbp->Tdbp->ColDB(g, NULL, Colnum);
+ /*********************************************************************/
+ /* Make the table list. */
+ /*********************************************************************/
+ if (/*!Tablist &&*/ InitTableList(g))
+ return TRUE;
- if (Colp) {
- Colp->InitValue(g); // May not have been done elsewhere
- To_Val = Colp->GetValue();
- } else if (!tdbp->Accept) {
- sprintf(g->Message, MSG(NO_MATCHING_COL), Name, tdbp->Tdbp->GetName());
+ /*********************************************************************/
+ /* Open all remote tables of the list. */
+ /*********************************************************************/
+ if (OpenTables(g))
return TRUE;
- } else {
- if (Nullable)
- Value->SetNull(true);
- Value->Reset();
- } // endif's
+ /*********************************************************************/
+ /* Proceed with local tables. */
+ /*********************************************************************/
+ if ((CurTable = Tablist)) {
+ Tdbp = (PTDBASE)CurTable->GetTo_Tdb();
+ Tdbp->SetMode(Mode);
+
+ // Check and initialize the subtable columns
+ for (PCOL cp = Columns; cp; cp = cp->GetNext())
+ if (cp->GetAmType() == TYPE_AM_TABID)
+ cp->COLBLK::Reset();
+ else if (((PPRXCOL)cp)->Init(g) && !Accept)
+ return TRUE;
+
+ if (trace)
+ htrc("Opening subtable %s\n", Tdbp->GetName());
+
+ // Now we can safely open the table
+ if (Tdbp->OpenDB(g))
+ return TRUE;
+
+ } // endif *Tablist
+ Use = USE_OPEN;
return FALSE;
- } // end of Init
+ } // end of OpenDB
/***********************************************************************/
-/* ReadColumn: */
+/* ReadDB: Data Base read routine for MUL access method. */
/***********************************************************************/
-void TBLCOL::ReadColumn(PGLOBAL g)
+int TDBTBM::ReadDB(PGLOBAL g)
{
- if (trace)
- htrc("TBL ReadColumn: name=%s\n", Name);
+ int rc;
- if (Colp) {
- Colp->ReadColumn(g);
- Value->SetValue_pval(To_Val);
+ if (!Done) {
+ // Get result from local tables
+ if ((rc = TDBTBL::ReadDB(g)) != RC_EF)
+ return rc;
+ else if ((rc = ReadNextRemote(g)) != RC_OK)
+ return rc;
- // Set null when applicable
- if (Nullable)
- Value->SetNull(Value->IsNull());
+ Done = true;
+ } // endif Done
- } // endif Colp
+ /*********************************************************************/
+ /* Now start the reading process of remote tables. */
+ /*********************************************************************/
+ retry:
+ rc = Tdbp->ReadDB(g);
- } // end of ReadColumn
+ if (rc == RC_EF) {
+ // Total number of rows met so far
+ Rows += Tdbp->RowNumber(g) - 1;
+ Crp += Tdbp->GetProgMax(g);
+ Cmp->Complete = true;
-/* ---------------------------- TBTBLK ------------------------------- */
+ if ((rc = ReadNextRemote(g)) == RC_OK)
+ goto retry;
+
+ } else if (rc == RC_FX)
+ strcat(strcat(strcat(g->Message, " ("), Tdbp->GetName()), ")");
+
+ return rc;
+ } // end of ReadDB
/***********************************************************************/
-/* ReadColumn: */
+/* ReadNext: Continue reading from next table. */
/***********************************************************************/
-void TBTBLK::ReadColumn(PGLOBAL g)
+int TDBTBM::ReadNextRemote(PGLOBAL g)
{
- if (trace)
- htrc("TBT ReadColumn: name=%s\n", Name);
+ bool b = false;
- Value->SetValue_psz((char*)((PTDBTBL)To_Tdb)->Tdbp->GetName());
+ if (Tdbp)
+ Tdbp->CloseDB(g);
- } // end of ReadColumn
+ Cmp = NULL;
+
+ retry:
+ // Search for a remote table having its result set
+ for (PTBMT tp = Tmp; tp; tp = tp->Next)
+ if (tp->Ready) {
+ if (!tp->Complete)
+ Cmp = tp;
+
+ } else
+ b = true;
+
+ if (!Cmp) {
+ if (b) { // more result to come
+// sleep(20);
+ goto retry;
+ } else
+ return RC_EF;
+
+ } // endif Curtable
+
+ Tdbp = (PTDBASE)Cmp->Tap->GetTo_Tdb();
+
+ // Check and initialize the subtable columns
+ for (PCOL cp = Columns; cp; cp = cp->GetNext())
+ if (cp->GetAmType() == TYPE_AM_TABID)
+ cp->COLBLK::Reset();
+ else if (((PPRXCOL)cp)->Init(g) && !Accept)
+ return RC_FX;
+
+ if (trace)
+ htrc("Reading subtable %s\n", Tdbp->GetName());
+
+ return RC_OK;
+ } // end of ReadNextRemote
/* ------------------------------------------------------------------- */
diff --git a/storage/connect/tabtbl.h b/storage/connect/tabtbl.h
index 07a20bb2867..7cc2ff0b92c 100644
--- a/storage/connect/tabtbl.h
+++ b/storage/connect/tabtbl.h
@@ -1,42 +1,51 @@
/*************** TabTbl H Declares Source Code File (.H) ***************/
-/* Name: TABTBL.H Version 1.2 */
+/* Name: TABTBL.H Version 1.3 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2008-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 2008-2013 */
/* */
/* This file contains the TDBTBL classes declares. */
/***********************************************************************/
-//#include "osutil.h"
#include "block.h"
#include "colblk.h"
+#include "tabutil.h"
typedef class TBLDEF *PTBLDEF;
typedef class TDBTBL *PTDBTBL;
-typedef class TBLCOL *PTBLCOL;
+typedef class TDBTBM *PTDBTBM;
+typedef class MYSQLC *PMYC;
/***********************************************************************/
-/* Defines the structure used for multiple tables. */
+/* Defines the structures used for distributed TBM tables. */
/***********************************************************************/
-typedef struct _tablist *PTBL;
-
-typedef struct _tablist {
- PTBL Next;
- char *Name;
- char *DB;
- } TBLIST;
+typedef struct _TBMtable *PTBMT;
+
+typedef struct _TBMtable {
+ PTBMT Next; // Points to next data table struct
+ PTABLE Tap; // Points to the sub table
+ PGLOBAL G; // Needed in thread routine
+ bool Complete; // TRUE when all results are read
+ bool Ready; // TRUE when results are there
+ int Rows; // Total number of rows read so far
+ int ProgCur; // Current pos
+ int ProgMax; // Max pos
+ int Rc; // Return code
+ THD *Thd;
+ pthread_attr_t attr; // ???
+ pthread_t Tid; // CheckOpen thread ID
+ } TBMT;
/***********************************************************************/
/* TBL table. */
/***********************************************************************/
-class DllExport TBLDEF : public TABDEF { /* Logical table description */
+class DllExport TBLDEF : public PRXDEF { /* Logical table description */
friend class TDBTBL;
+ friend class TDBTBC;
public:
// Constructor
TBLDEF(void);
// Implementation
virtual const char *GetType(void) {return "TBL";}
- PTBL GetTables(void) {return To_Tables;}
-//int GetNtables(void) {return Ntables;}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
@@ -44,8 +53,8 @@ class DllExport TBLDEF : public TABDEF { /* Logical table description */
protected:
// Members
- PTBL To_Tables; /* To the list of tables */
bool Accept; /* TRUE if bad tables are accepted */
+ bool Thread; /* Use thread for remote tables */
int Maxerr; /* Maximum number of bad tables */
int Ntables; /* Number of tables */
}; // end of TBLDEF
@@ -53,91 +62,44 @@ class DllExport TBLDEF : public TABDEF { /* Logical table description */
/***********************************************************************/
/* This is the TBL Access Method class declaration. */
/***********************************************************************/
-class DllExport TDBTBL : public TDBASE {
- friend class TBLCOL;
+class DllExport TDBTBL : public TDBPRX {
friend class TBTBLK;
- friend class TDBPLG;
public:
// Constructor
TDBTBL(PTBLDEF tdp = NULL);
-//TDBTBL(PTDBTBL tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_TBL;}
-//virtual PTDB Duplicate(PGLOBAL g)
-// {return (PTDB)new(g) TDBTBL(this);}
// Methods
virtual void ResetDB(void);
-//virtual PTABLE GetTablist(void) {return (PSZ)Tablist;}
-//virtual PTDB CopyOne(PTABS t);
- virtual int GetRecpos(void) {return Rows;}
- virtual int GetBadLines(void) {return (int)Nbf;}
+ virtual int GetRecpos(void) {return Rows;}
+ virtual int GetBadLines(void) {return (int)Nbc;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetMaxSize(PGLOBAL g);
- virtual int GetProgMax(PGLOBAL g);
- virtual int GetProgCur(void);
virtual int RowNumber(PGLOBAL g, bool b = FALSE);
virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL scp);
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:
// Internal functions
- PTDB GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp);
bool InitTableList(PGLOBAL g);
- bool TestFil(PGLOBAL g, PFIL filp, PTBL tblp);
+ bool TestFil(PGLOBAL g, PFIL filp, PTABLE tabp);
// Members
PTABLE Tablist; // Points to the table list
PTABLE CurTable; // Points to the current table
- PTDBASE Tdbp; // Current table PTDB
bool Accept; // TRUE if bad tables are accepted
int Maxerr; // Maximum number of bad tables
- int Nbf; // Number of bad connections
+ int Nbc; // Number of bad connections
int Rows; // Used for RowID
int Crp; // Used for CurPos
}; // end of class TDBTBL
/***********************************************************************/
-/* Class TBLCOL: TBL access method column descriptor. */
-/* This A.M. is used for TBL tables. */
-/***********************************************************************/
-class DllExport TBLCOL : public COLBLK {
- friend class TDBTBL;
- public:
- // Constructors
- TBLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "TBL");
- TBLCOL(TBLCOL *colp, PTDB tdbp); // Constructor used in copy process
-//TBLCOL(SPCBLK *colp, PTDB tdbp); // Constructor used for pseudo columns
-
- // Implementation
- virtual int GetAmType(void) {return TYPE_AM_TBL;}
-
- // Methods
- virtual bool IsSpecial(void) {return Pseudo;}
- virtual void ReadColumn(PGLOBAL g);
-//virtual void WriteColumn(PGLOBAL g);
-// void Print(PGLOBAL g, FILE *, UINT);
- bool Init(PGLOBAL g);
-
- protected:
- // Default constructor not to be used
- TBLCOL(void) {}
-
- // Members
- PCOL Colp; // Points to matching table column
- PVAL To_Val; // To the matching column value
- bool Pseudo; // TRUE for special columns
- int Colnum; // Used when retrieving columns by number
- }; // end of class TBLCOL
-
-/***********************************************************************/
/* Class TBTBLK: TDBPLG TABID special column descriptor. */
/***********************************************************************/
class TBTBLK : public TIDBLK {
@@ -160,3 +122,44 @@ class TBTBLK : public TIDBLK {
protected:
// Must not have additional members
}; // end of class TBTBLK
+
+/***********************************************************************/
+/* This is the TBM Access Method class declaration. */
+/***********************************************************************/
+class DllExport TDBTBM : public TDBTBL {
+ friend class TBTBLK;
+ public:
+ // Constructor
+ TDBTBM(PTBLDEF tdp = NULL);
+
+ // Implementation
+//virtual AMT GetAmType(void) {return TYPE_AM_TBL;}
+
+ // Methods
+ virtual void ResetDB(void);
+//virtual int GetRecpos(void) {return Rows;}
+//virtual int GetBadLines(void) {return (int)Nbc;}
+
+ // Database routines
+//virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual int GetMaxSize(PGLOBAL g) {return 10;} // Temporary
+ virtual int RowNumber(PGLOBAL g, bool b = FALSE);
+//virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL scp);
+ virtual bool OpenDB(PGLOBAL g);
+ virtual int ReadDB(PGLOBAL g);
+
+ protected:
+ // Internal functions
+//bool InitTableList(PGLOBAL g);
+//bool TestFil(PGLOBAL g, PFIL filp, PTABLE tabp);
+ bool OpenTables(PGLOBAL g);
+ int ReadNextRemote(PGLOBAL g);
+
+ // Members
+ PTBMT Tmp; // To data table TBMT structures
+ PTBMT Cmp; // Current data table PLGF (to move to TDBTBL)
+ PTBMT Bmp; // To bad (unconnected) PLGF structures
+ bool Done; // TRUE after first GetAllResults
+ int Nrc; // Number of remote connections
+ int Nlc; // Number of local connections
+ }; // end of class TDBTBM
diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp
new file mode 100644
index 00000000000..21dee4e1856
--- /dev/null
+++ b/storage/connect/tabutil.cpp
@@ -0,0 +1,624 @@
+/************* Tabutil cpp Declares Source Code File (.CPP) ************/
+/* Name: TABUTIL.CPP Version 1.0 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2013 */
+/* */
+/* Utility function used by the PROXY, XCOL, OCCUR, and TBL tables. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant section of system dependant header files. */
+/***********************************************************************/
+#include "my_global.h"
+#include "sql_class.h"
+#include "table.h"
+#include "field.h"
+#if defined(WIN32)
+#include <stdlib.h>
+#include <stdio.h>
+#if defined(__BORLANDC__)
+#define __MFC_COMPAT__ // To define min/max as macro
+#endif
+//#include <windows.h>
+#else
+#if defined(UNIX)
+#include <fnmatch.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "osutil.h"
+#else
+//#include <io.h>
+#endif
+//#include <fcntl.h>
+#endif
+
+/***********************************************************************/
+/* Include application header files: */
+/***********************************************************************/
+#include "table.h" // MySQL table definitions
+#include "global.h"
+#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 trace;
+
+/************************************************************************/
+/* Used by MYSQL tables to get MySQL parameters from the calling proxy */
+/* table (PROXY, TBL, XCL, or OCCUR) when used by one of these. */
+/************************************************************************/
+void Remove_tshp(PCATLG cat)
+{
+ ((MYCAT*)cat)->GetHandler()->tshp = NULL;
+} // end of Remove_thsp
+
+/************************************************************************/
+/* GetTableShare: allocates and open a table share. */
+/************************************************************************/
+TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
+ const char *name, bool& mysql)
+{
+ 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;
+
+ if (!(s = alloc_table_share(db, name, key, ++k))) {
+ strcpy(g->Message, "Error allocating share\n");
+ 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)
+ mysql = true;
+#else // !MYSQL_SUPPORT
+ sprintf(g->Message, "%s.%s is not a CONNECT table", db, name);
+ return NULL;
+#endif // MYSQL_SUPPORT
+ } else
+ mysql = false;
+
+ } else {
+ mysql = true;
+ } // endif is_view
+
+ } else {
+ sprintf(g->Message, "Error %d opening share\n", s->error);
+ free_table_share(s);
+ return NULL;
+ } // endif open_table_def
+
+ return s;
+} // end of GetTableShare
+
+/************************************************************************/
+/* TabColumns: constructs the result blocks containing all the columns */
+/* of the object table that will be retrieved by GetData commands. */
+/************************************************************************/
+PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
+ const char *name, bool& info)
+ {
+ static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
+ TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT,
+ TYPE_STRING, TYPE_STRING, TYPE_STRING};
+ static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
+ FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL,
+ FLD_REM, FLD_NO, FLD_CHARSET};
+ static unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 256, 32, 32};
+ char *fld, *fmt;
+ int i, n, ncol = sizeof(buftyp) / sizeof(int);
+ int len, type, prec;
+ bool mysql;
+ TABLE_SHARE *s;
+ Field* *field;
+ Field *fp;
+ PQRYRES qrp;
+ PCOLRES crp;
+
+ if (!info) {
+ if (!(s = GetTableShare(g, thd, db, name, mysql))) {
+ return NULL;
+ } else if (s->is_view) {
+ strcpy(g->Message, "Use MYSQL type to see columns from a view");
+ info = true; // To tell caller name is a view
+ free_table_share(s);
+ return NULL;
+ } else
+ n = s->fieldnames.count;
+
+ } else {
+ n = 0;
+ length[0] = 128;
+ } // endif info
+
+ /**********************************************************************/
+ /* Allocate the structures used to refer to the result set. */
+ /**********************************************************************/
+ qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
+ buftyp, fldtyp, length, true, true);
+
+ // Some columns must be renamed
+ for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
+ switch (++i) {
+ case 10: crp->Name = "Date_fmt"; break;
+ case 11: crp->Name = "Collation"; break;
+ } // endswitch i
+
+ if (info)
+ return qrp;
+
+ /**********************************************************************/
+ /* Now get the results into blocks. */
+ /**********************************************************************/
+ for (i = 0, field= s->field; *field; i++, field++) {
+ fp= *field;
+
+ // Get column name
+ crp = qrp->Colresp; // Column_Name
+ fld = (char *)fp->field_name;
+ crp->Kdata->SetValue(fld, i);
+
+ if ((type = MYSQLtoPLG(fp->type())) == TYPE_ERROR) {
+ sprintf(g->Message, "Unsupported column type %s", GetTypeName(type));
+ qrp = NULL;
+ break;
+ } // endif type
+
+ crp = crp->Next; // Data_Type
+ crp->Kdata->SetValue(type, i);
+ crp = crp->Next; // Type_Name
+ crp->Kdata->SetValue(GetTypeName(type), i);
+
+ if (type == TYPE_DATE) {
+ // When creating tables we do need info about date columns
+ if (mysql) {
+ fmt = MyDateFmt(fp->type());
+ len = strlen(fmt);
+ } else {
+ fmt = (char*)fp->option_struct->dateformat;
+ len = fp->field_length;
+ } // endif mysql
+
+ } else {
+ fmt = NULL;
+ len = fp->char_length();
+ } // endif type
+
+ crp = crp->Next; // Precision
+ crp->Kdata->SetValue(len, i);
+
+ crp = crp->Next; // Length
+ len = fp->field_length;
+ crp->Kdata->SetValue(len, i);
+
+ prec = (type == TYPE_FLOAT) ? fp->decimals() : 0;
+ crp = crp->Next; // Scale
+ crp->Kdata->SetValue(prec, i);
+
+ crp = crp->Next; // Radix
+ crp->Kdata->SetValue(0, i);
+
+ crp = crp->Next; // Nullable
+ crp->Kdata->SetValue((fp->null_ptr != 0) ? 1 : 0, i);
+
+ crp = crp->Next; // Remark
+ fld = fp->comment.str;
+ crp->Kdata->SetValue(fld, fp->comment.length, i);
+
+ crp = crp->Next; // New
+ crp->Kdata->SetValue((fmt) ? fmt : (char*) "", i);
+
+ crp = crp->Next; // New (charset)
+ fld = (char *)fp->charset()->name;
+ crp->Kdata->SetValue(fld, i);
+
+ // Add this item
+ qrp->Nblin++;
+ } // endfor field
+
+ /**********************************************************************/
+ /* Return the result pointer for use by GetData routines. */
+ /**********************************************************************/
+ free_table_share(s);
+ return qrp;
+ } // end of TabColumns
+
+/* -------------- Implementation of the PROXY classes ---------------- */
+
+/***********************************************************************/
+/* PRXDEF constructor. */
+/***********************************************************************/
+PRXDEF::PRXDEF(void)
+ {
+ Tablep = NULL;
+ Pseudo = 3;
+} // end of PRXDEF constructor
+
+/***********************************************************************/
+/* DefineAM: define specific AM block values from XCOL file. */
+/***********************************************************************/
+bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+ {
+ char *pn, *db, *tab, *def = NULL;
+
+ db = Cat->GetStringCatInfo(g, "Dbname", "*");
+ def = Cat->GetStringCatInfo(g, "Srcdef", NULL);
+
+ if (!(tab = Cat->GetStringCatInfo(g, "Tabname", NULL))) {
+ if (!def) {
+ strcpy(g->Message, "Missing object table definition");
+ return TRUE;
+ } else
+ tab = "Noname";
+
+ } else
+ // Analyze the table name, it may have the format: [dbname.]tabname
+ if ((pn = strchr(tab, '.'))) {
+ *pn++ = 0;
+ db = tab;
+ tab = pn;
+ } // endif pn
+
+ Tablep = new(g) XTAB(tab, def);
+ Tablep->SetQualifier(db);
+ return FALSE;
+ } // end of DefineAM
+
+/***********************************************************************/
+/* GetTable: makes a new TDB of the proper type. */
+/***********************************************************************/
+PTDB PRXDEF::GetTable(PGLOBAL g, MODE mode)
+ {
+ if (Catfunc == FNC_COL)
+ return new(g) TDBTBC(this);
+ else
+ return new(g) TDBPRX(this);
+
+ } // end of GetTable
+
+/* ------------------------------------------------------------------- */
+
+/***********************************************************************/
+/* Implementation of the TDBPRX class. */
+/***********************************************************************/
+TDBPRX::TDBPRX(PPRXDEF tdp) : TDBASE(tdp)
+ {
+ Tdbp = NULL; // The object table
+ } // end of TDBPRX constructor
+
+/***********************************************************************/
+/* Get the PTDB of the sub-table. */
+/***********************************************************************/
+PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b)
+ {
+ const char *sp;
+ char *db, *name;
+ bool mysql = true;
+ PTDB tdbp = NULL;
+ TABLE_SHARE *s = NULL;
+ Field* *fp;
+ PCATLG cat = To_Def->GetCat();
+ PHC hc = ((MYCAT*)cat)->GetHandler();
+ LPCSTR cdb, curdb = hc->GetDBName(NULL);
+ THD *thd = (hc->GetTable())->in_use;
+
+ db = (char*)tabp->GetQualifier();
+ name = (char*)tabp->GetName();
+
+ // Check for eventual loop
+ for (PTABLE tp = To_Table; tp; tp = tp->Next) {
+ cdb = (tp->Qualifier) ? tp->Qualifier : curdb;
+
+ if (!stricmp(name, tp->Name) && !stricmp(db, cdb)) {
+ sprintf(g->Message, "Table %s.%s pointing on itself", db, name);
+ return NULL;
+ } // endif
+
+ } // endfor tp
+
+ if (!tabp->GetSrc()) {
+ if (!(s = GetTableShare(g, thd, db, name, mysql)))
+ return NULL;
+
+ if (s->is_view && !b)
+ s->field = hc->get_table()->s->field;
+
+ hc->tshp = s;
+ } else if (b) {
+ // Don't use caller's columns
+ fp = hc->get_table()->field;
+ hc->get_table()->field = NULL;
+
+ // Make caller use the source definition
+ sp = hc->get_table()->s->option_struct->srcdef;
+ hc->get_table()->s->option_struct->srcdef = tabp->GetSrc();
+ } // endif srcdef
+
+ if (mysql) {
+#if defined(MYSQL_SUPPORT)
+ // Access sub-table via MySQL API
+ if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYPRX"))) {
+ sprintf(g->Message, "Cannot access %s.%s", db, name);
+ goto err;
+ } // endif Define
+
+ if (db)
+ ((PTDBMY)tdbp)->SetDatabase(tabp->GetQualifier());
+
+#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
+ tdbp = cat->GetTable(g, tabp);
+ } // endif mysql
+
+ if (s) {
+ if (s->is_view && !b)
+ s->field = NULL;
+
+ hc->tshp = NULL;
+ } else if (b) {
+ // Restore s structure that can be in cache
+ hc->get_table()->field = fp;
+ hc->get_table()->s->option_struct->srcdef = sp;
+ } // endif s
+
+ if (trace && tdbp)
+ htrc("Subtable %s in %s\n",
+ name, SVP(((PTDBASE)tdbp)->GetDef()->GetDB()));
+
+ err:
+ if (s)
+ free_table_share(s);
+
+ return (PTDBASE)tdbp;
+ } // end of GetSubTable
+
+/***********************************************************************/
+/* Initializes the table. */
+/***********************************************************************/
+bool TDBPRX::InitTable(PGLOBAL g)
+ {
+ if (!Tdbp) {
+ // Get the table description block of this table
+ if (!(Tdbp = GetSubTable(g, ((PPRXDEF)To_Def)->Tablep)))
+ return TRUE;
+
+ } // endif Tdbp
+
+ return FALSE;
+ } // end of InitTable
+
+/***********************************************************************/
+/* Allocate PRX column description block. */
+/***********************************************************************/
+PCOL TDBPRX::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
+ {
+ return new(g) PRXCOL(cdp, this, cprec, n);
+ } // end of MakeCol
+
+/***********************************************************************/
+/* PRX GetMaxSize: returns the maximum number of rows in the table. */
+/***********************************************************************/
+int TDBPRX::GetMaxSize(PGLOBAL g)
+ {
+ if (MaxSize < 0) {
+ if (InitTable(g))
+ return 0;
+
+ MaxSize = Tdbp->GetMaxSize(g);
+ } // endif MaxSize
+
+ return MaxSize;
+ } // end of GetMaxSize
+
+/***********************************************************************/
+/* In this sample, ROWID will be the (virtual) row number, */
+/* while ROWNUM will be the occurence rank in the multiple column. */
+/***********************************************************************/
+int TDBPRX::RowNumber(PGLOBAL g, bool b)
+ {
+ return Tdbp->RowNumber(g, b);
+ } // end of RowNumber
+
+/***********************************************************************/
+/* PROXY Access Method opening routine. */
+/***********************************************************************/
+bool TDBPRX::OpenDB(PGLOBAL g)
+ {
+ if (Use == USE_OPEN) {
+ /*******************************************************************/
+ /* Table already open, just replace it at its beginning. */
+ /*******************************************************************/
+ return Tdbp->OpenDB(g);
+ } // endif use
+
+ if (Mode != MODE_READ) {
+ /*******************************************************************/
+ /* Currently XCOL tables cannot be modified. */
+ /*******************************************************************/
+ strcpy(g->Message, "PROXY tables are read only");
+ return TRUE;
+ } // endif Mode
+
+ if (InitTable(g))
+ return TRUE;
+
+ /*********************************************************************/
+ /* Check and initialize the subtable columns. */
+ /*********************************************************************/
+ for (PCOL cp = Columns; cp; cp = cp->GetNext())
+ if (((PPRXCOL)cp)->Init(g))
+ return TRUE;
+
+ /*********************************************************************/
+ /* Physically open the object table. */
+ /*********************************************************************/
+ if (Tdbp->OpenDB(g))
+ return TRUE;
+
+ return FALSE;
+ } // end of OpenDB
+
+/***********************************************************************/
+/* Data Base read routine for PROY access method. */
+/***********************************************************************/
+int TDBPRX::ReadDB(PGLOBAL g)
+ {
+ /*********************************************************************/
+ /* Now start the reading process. */
+ /*********************************************************************/
+ return Tdbp->ReadDB(g);
+ } // end of ReadDB
+
+/***********************************************************************/
+/* WriteDB: Data Base write routine for PROXY access methods. */
+/***********************************************************************/
+int TDBPRX::WriteDB(PGLOBAL g)
+ {
+ sprintf(g->Message, "%s tables are read only", To_Def->GetType());
+ return RC_FX;
+ } // end of WriteDB
+
+/***********************************************************************/
+/* Data Base delete line routine for PROXY access methods. */
+/***********************************************************************/
+int TDBPRX::DeleteDB(PGLOBAL g, int irc)
+ {
+ sprintf(g->Message, "Delete not enabled for %s tables",
+ To_Def->GetType());
+ return RC_FX;
+ } // end of DeleteDB
+
+/***********************************************************************/
+/* Used by the TBL tables. */
+/***********************************************************************/
+void TDBPRX::RemoveNext(PTABLE tp)
+ {
+ tp->Next = NULL;
+ } // end of RemoveNext
+
+/* ---------------------------- PRXCOL ------------------------------- */
+
+/***********************************************************************/
+/* PRXCOL public constructor. */
+/***********************************************************************/
+PRXCOL::PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+ : COLBLK(cdp, tdbp, i)
+ {
+ if (cprec) {
+ Next = cprec->GetNext();
+ cprec->SetNext(this);
+ } else {
+ Next = tdbp->GetColumns();
+ tdbp->SetColumns(this);
+ } // endif cprec
+
+ // Set additional Dos access method information for column.
+ Long = cdp->GetLong(); // Useful ???
+//strcpy(F_Date, cdp->F_Date);
+ Colp = NULL;
+ To_Val = NULL;
+ Pseudo = FALSE;
+ Colnum = cdp->GetOffset(); // If columns are retrieved by number
+
+ if (trace)
+ htrc(" making new %sCOL C%d %s at %p\n", am, Index, Name, this);
+
+ } // end of PRXCOL constructor
+
+/***********************************************************************/
+/* PRXCOL initialization routine. */
+/* Look for the matching column in the object table. */
+/***********************************************************************/
+bool PRXCOL::Init(PGLOBAL g)
+ {
+ PTDBPRX tdbp = (PTDBPRX)To_Tdb;
+
+ if (!(Colp = tdbp->Tdbp->ColDB(g, Name, 0)) && Colnum)
+ Colp = tdbp->Tdbp->ColDB(g, NULL, Colnum);
+
+ if (Colp) {
+ // May not have been done elsewhere
+ Colp->InitValue(g);
+ To_Val = Colp->GetValue();
+
+ // this may be needed by some tables (which?)
+ Colp->SetColUse(ColUse);
+ } else {
+ sprintf(g->Message, MSG(NO_MATCHING_COL), Name, tdbp->Tdbp->GetName());
+ return TRUE;
+ } // endif Colp
+
+ return FALSE;
+ } // end of Init
+
+/***********************************************************************/
+/* ReadColumn: */
+/***********************************************************************/
+void PRXCOL::ReadColumn(PGLOBAL g)
+ {
+ if (trace)
+ htrc("PRX ReadColumn: name=%s\n", Name);
+
+ if (Colp) {
+ Colp->ReadColumn(g);
+ Value->SetValue_pval(To_Val);
+
+ // Set null when applicable
+ if (Nullable)
+ Value->SetNull(Value->IsNull());
+
+ } // endif Colp
+
+ } // end of ReadColumn
+
+/* ---------------------------TDBTBC class --------------------------- */
+
+/***********************************************************************/
+/* TDBTBC class constructor. */
+/***********************************************************************/
+TDBTBC::TDBTBC(PPRXDEF tdp) : TDBCAT(tdp)
+ {
+ Db = (PSZ)tdp->Tablep->GetQualifier();
+ Tab = (PSZ)tdp->Tablep->GetName();
+ } // end of TDBTBC constructor
+
+/***********************************************************************/
+/* GetResult: Get the list the MYSQL table columns. */
+/***********************************************************************/
+PQRYRES TDBTBC::GetResult(PGLOBAL g)
+ {
+ bool b = false;
+
+ return TabColumns(g, current_thd, Db, Tab, b);
+ } // end of GetResult
+
diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h
new file mode 100644
index 00000000000..ddf6c2eb601
--- /dev/null
+++ b/storage/connect/tabutil.h
@@ -0,0 +1,141 @@
+// TABUTIL.H Olivier Bertrand 2013
+// Defines the TAB catalog tables
+
+#ifndef TABUTIL
+#define TABUTIL 1
+
+//#include "tabtbl.h"
+
+#define TYPE_AM_PRX (AMT)129
+
+typedef class PRXDEF *PPRXDEF;
+typedef class TDBPRX *PTDBPRX;
+typedef class XXLCOL *PXXLCOL;
+typedef class PRXCOL *PPRXCOL;
+typedef class TBCDEF *PTBCDEF;
+typedef class TDBTBC *PTDBTBC;
+
+TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
+ const char *name, bool& mysql);
+PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
+ const char *name, bool& info);
+
+void Remove_tshp(PCATLG cat);
+
+/* -------------------------- PROXY classes -------------------------- */
+
+/***********************************************************************/
+/* PROXY: table based on another table. Can be used to have a */
+/* different view on an existing table. */
+/* However, its real use is to be the base of TBL and PRX tables. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* PRX table. */
+/***********************************************************************/
+class DllExport PRXDEF : public TABDEF { /* Logical table description */
+ friend class TDBPRX;
+ friend class TDBTBC;
+ public:
+ // Constructor
+ PRXDEF(void);
+
+ // Implementation
+ virtual const char *GetType(void) {return "PRX";}
+
+ // Methods
+ virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
+ virtual PTDB GetTable(PGLOBAL g, MODE mode);
+
+ protected:
+ // Members
+ PTABLE Tablep; /* The object table */
+ }; // end of PRXDEF
+
+/***********************************************************************/
+/* This is the class declaration for the XCSV table. */
+/***********************************************************************/
+class DllExport TDBPRX : public TDBASE {
+//friend class MULINDX;
+ friend class PRXDEF;
+ friend class PRXCOL;
+ public:
+ // Constructor
+ TDBPRX(PPRXDEF tdp);
+
+ // Implementation
+ virtual AMT GetAmType(void) {return TYPE_AM_PRX;}
+
+ // Methods
+ virtual int GetRecpos(void) {return Tdbp->GetRecpos();}
+ virtual void ResetDB(void) {Tdbp->ResetDB();}
+ virtual int RowNumber(PGLOBAL g, bool b = FALSE);
+
+ // Database routines
+ virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual bool InitTable(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) {if (Tdbp) Tdbp->CloseDB(g);}
+ PTDBASE GetSubTable(PGLOBAL g, PTABLE tabp, bool b = false);
+ void RemoveNext(PTABLE tp);
+
+ protected:
+ // Members
+ PTDBASE Tdbp; // The object table
+ }; // end of class TDBPRX
+
+/***********************************************************************/
+/* Class PRXCOL: PRX access method column descriptor. */
+/* This A.M. is used for PRX tables. */
+/***********************************************************************/
+class DllExport PRXCOL : public COLBLK {
+ friend class TDBPRX;
+ friend class TDBTBL;
+ friend class TDBOCCUR;
+ public:
+ // Constructors
+ PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "PRX");
+
+ // Implementation
+ virtual int GetAmType(void) {return TYPE_AM_PRX;}
+
+ // Methods
+ virtual bool IsSpecial(void) {return Pseudo;}
+ virtual void ReadColumn(PGLOBAL g);
+ bool Init(PGLOBAL g);
+
+ protected:
+ // Default constructor not to be used
+ PRXCOL(void) {}
+
+ // Members
+ PCOL Colp; // Points to matching table column
+ PVAL To_Val; // To the matching column value
+ bool Pseudo; // TRUE for special columns
+ int Colnum; // Used when retrieving columns by number
+ }; // end of class PRXCOL
+
+/***********************************************************************/
+/* This is the class declaration for the TBC column catalog table. */
+/***********************************************************************/
+class TDBTBC : public TDBCAT {
+ public:
+ // Constructors
+ TDBTBC(PPRXDEF tdp);
+//TDBTBC(PTBLDEF tdp);
+//TDBTBC(PXCLDEF tdp);
+
+ protected:
+ // Specific routines
+ virtual PQRYRES GetResult(PGLOBAL g);
+
+ // Members
+ PSZ Db; // Database of the table
+ PSZ Tab; // Table name
+ }; // end of class TDBMCL
+
+#endif // TABUTIL
diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp
index d89d61dc11c..dbd4330a2f9 100644
--- a/storage/connect/tabwmi.cpp
+++ b/storage/connect/tabwmi.cpp
@@ -135,14 +135,12 @@ PWMIUT InitWMI(PGLOBAL g, char *nsp, char *classname)
/***********************************************************************/
PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info)
{
- static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
- DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME,
FLD_PREC, FLD_LENGTH, FLD_SCALE};
static unsigned int len, length[] = {0, 6, 8, 10, 10, 6};
- int i = 0, n = 0, ncol = sizeof(dbtype) / sizeof(int);
+ int i = 0, n = 0, ncol = sizeof(buftyp) / sizeof(int);
int lng, typ, prec;
LONG low, upp;
BSTR propname;
@@ -213,7 +211,7 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info)
/* Allocate the structures used to refer to the result set. */
/*********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
- dbtype, buftyp, fldtyp, length, true, true);
+ buftyp, fldtyp, length, true, true);
if (info)
return qrp;
diff --git a/storage/connect/tabxcl.cpp b/storage/connect/tabxcl.cpp
new file mode 100644
index 00000000000..96da0571271
--- /dev/null
+++ b/storage/connect/tabxcl.cpp
@@ -0,0 +1,283 @@
+/************* TabXcl CPP Declares Source Code File (.CPP) *************/
+/* Name: TABXCL.CPP Version 1.0 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2013 */
+/* */
+/* XCOL: Table having one column containing several values */
+/* comma separated. When creating the table, the name of the X */
+/* column is given by the Name option. */
+/* This first version has one limitation: */
+/* - The X column has the same length than in the physical file. */
+/* This tables produces as many rows for a physical row than the */
+/* number of items in the X column (eventually 0). */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant section of system dependant header files. */
+/***********************************************************************/
+#include "my_global.h"
+#if defined(WIN32)
+#include <stdlib.h>
+#include <stdio.h>
+#if defined(__BORLANDC__)
+#define __MFC_COMPAT__ // To define min/max as macro
+#endif
+//#include <windows.h>
+#else
+#if defined(UNIX)
+#include <fnmatch.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "osutil.h"
+#else
+//#include <io.h>
+#endif
+//#include <fcntl.h>
+#endif
+
+/***********************************************************************/
+/* Include application header files: */
+/***********************************************************************/
+#include "table.h" // MySQL table definitions
+#include "global.h"
+#include "plgdbsem.h"
+#include "plgcnx.h" // For DB types
+#include "resource.h"
+#include "reldef.h"
+#include "filamtxt.h"
+#include "tabdos.h"
+#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"
+
+extern "C" int trace;
+
+/* -------------- Implementation of the XCOL classes ---------------- */
+
+/***********************************************************************/
+/* XCLDEF constructor. */
+/***********************************************************************/
+XCLDEF::XCLDEF(void)
+ {
+ Xcol = NULL;
+ Sep = ',';
+ Mult = 10;
+} // end of XCLDEF constructor
+
+/***********************************************************************/
+/* DefineAM: define specific AM block values from XCOL table. */
+/***********************************************************************/
+bool XCLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+ {
+ char buf[8];
+
+ Xcol = Cat->GetStringCatInfo(g, "Colname", "");
+ Cat->GetCharCatInfo("Separator", ",", buf, sizeof(buf));
+ Sep = (strlen(buf) == 2 && buf[0] == '\\' && buf[1] == 't') ? '\t' : *buf;
+ Mult = Cat->GetIntCatInfo("Mult", 10);
+ return PRXDEF::DefineAM(g, am, poff);
+ } // end of DefineAM
+
+/***********************************************************************/
+/* GetTable: makes a new TDB of the proper type. */
+/***********************************************************************/
+PTDB XCLDEF::GetTable(PGLOBAL g, MODE mode)
+ {
+ if (Catfunc == FNC_COL)
+ return new(g) TDBTBC(this);
+ else
+ return new(g) TDBXCL(this);
+
+ } // end of GetTable
+
+/* ------------------------------------------------------------------- */
+
+/***********************************************************************/
+/* Implementation of the TDBXCL class. */
+/***********************************************************************/
+TDBXCL::TDBXCL(PXCLDEF tdp) : TDBPRX(tdp)
+ {
+ Xcolumn = tdp->Xcol; // CSV column name
+ Xcolp = NULL; // To the XCLCOL column
+ Mult = tdp->Mult; // Multiplication factor
+ N = 0; // The current table index
+ M = 0; // The occurence rank
+ RowFlag = 0; // 0: Ok, 1: Same, 2: Skip
+ New = TRUE; // TRUE for new line
+ Sep = tdp->Sep; // The Xcol separator
+ } // end of TDBXCL constructor
+
+/***********************************************************************/
+/* Allocate XCL column description block. */
+/***********************************************************************/
+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);
+ colp = Xcolp;
+ } else
+ colp = new(g) PRXCOL(cdp, this, cprec, n);
+
+ return colp;
+ } // end of MakeCol
+
+/***********************************************************************/
+/* XCL GetMaxSize: returns the maximum number of rows in the table. */
+/***********************************************************************/
+int TDBXCL::GetMaxSize(PGLOBAL g)
+ {
+ if (MaxSize < 0) {
+ if (InitTable(g))
+ return 0;
+
+ MaxSize = Mult * Tdbp->GetMaxSize(g);
+ } // endif MaxSize
+
+ return MaxSize;
+ } // end of GetMaxSize
+
+/***********************************************************************/
+/* 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)
+ {
+ return (b) ? M : N;
+ } // end of RowNumber
+
+/***********************************************************************/
+/* XCL Access Method opening routine. */
+/***********************************************************************/
+bool TDBXCL::OpenDB(PGLOBAL g)
+ {
+ if (Use == USE_OPEN) {
+ /*******************************************************************/
+ /* Table already open, just replace it at its beginning. */
+ /*******************************************************************/
+ M = N = 0;
+ RowFlag = 0;
+ New = TRUE;
+ return Tdbp->OpenDB(g);
+ } // endif use
+
+ if (Mode != MODE_READ) {
+ /*******************************************************************/
+ /* Currently XCOL tables cannot be modified. */
+ /*******************************************************************/
+ strcpy(g->Message, "XCOL tables are read only");
+ return TRUE;
+ } // endif Mode
+
+ if (InitTable(g))
+ return TRUE;
+
+ /*********************************************************************/
+ /* Check and initialize the subtable columns. */
+ /*********************************************************************/
+ for (PCOL cp = Columns; cp; cp = cp->GetNext())
+ if (((PXCLCOL)cp)->Init(g))
+ return TRUE;
+
+ /*********************************************************************/
+ /* Physically open the object table. */
+ /*********************************************************************/
+ if (Tdbp->OpenDB(g))
+ return TRUE;
+
+ return FALSE;
+ } // end of OpenDB
+
+/***********************************************************************/
+/* Data Base read routine for XCL access method. */
+/***********************************************************************/
+int TDBXCL::ReadDB(PGLOBAL g)
+ {
+ int rc = RC_OK;
+
+ /*********************************************************************/
+ /* Now start the multi reading process. */
+ /*********************************************************************/
+ do {
+ if (RowFlag != 1) {
+ if ((rc = Tdbp->ReadDB(g)) != RC_OK)
+ break;
+
+ New = TRUE;
+ M = 1;
+ } else {
+ New = FALSE;
+ M++;
+ } // endif RowFlag
+
+ if (Xcolp) {
+ RowFlag = 0;
+ Xcolp->ReadColumn(g);
+ } // endif Xcolp
+
+ N++;
+ } while (RowFlag == 2);
+
+ return rc;
+ } // end of ReadDB
+
+
+// ------------------------ XCLCOL functions ----------------------------
+
+/***********************************************************************/
+/* XCLCOL public constructor. */
+/***********************************************************************/
+XCLCOL::XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
+ : PRXCOL(cdp, tdbp, cprec, i, "XCL")
+ {
+ // Set additional XXL access method information for column.
+ Cbuf = (char*)PlugSubAlloc(g, NULL, Long + 1);
+ Cp = NULL; // Pointer to current position in Cbuf
+ Sep = ((PTDBXCL)tdbp)->Sep;
+ AddStatus(BUF_READ); // Only evaluated from TDBXCL::ReadDB
+ } // end of XCLCOL constructor
+
+/***********************************************************************/
+/* What this routine does is to get the comma-separated string */
+/* from the source table column, extract the single values and */
+/* set the flag for the table ReadDB function. */
+/***********************************************************************/
+void XCLCOL::ReadColumn(PGLOBAL g)
+ {
+ if (((PTDBXCL)To_Tdb)->New) {
+ Colp->ReadColumn(g);
+ strcpy(Cbuf, To_Val->GetCharValue());
+ Cp = Cbuf;
+ } // endif New
+
+ if (*Cp) {
+ PSZ p;
+
+ // Trim left
+ for (p = Cp; *p == ' '; p++) ;
+
+ if ((Cp = strchr(Cp, Sep)))
+ // Separator is found
+ *Cp++ = '\0';
+
+ Value->SetValue_psz(p);
+ } else if (Nullable) {
+ Value->Reset();
+ Value->SetNull(true);
+ } else
+ // Skip that row
+ ((PTDBXCL)To_Tdb)->RowFlag = 2;
+
+ if (Cp && *Cp)
+ // More to come from the same row
+ ((PTDBXCL)To_Tdb)->RowFlag = 1;
+
+ } // end of ReadColumn
diff --git a/storage/connect/tabxcl.h b/storage/connect/tabxcl.h
new file mode 100644
index 00000000000..28fbf85d509
--- /dev/null
+++ b/storage/connect/tabxcl.h
@@ -0,0 +1,104 @@
+// TABXCL.H Olivier Bertrand 2013
+// Defines the XCOL tables
+
+#include "tabutil.h"
+
+#define TYPE_AM_XCOL (AMT)124
+
+typedef class XCLDEF *PXCLDEF;
+typedef class TDBXCL *PTDBXCL;
+typedef class XCLCOL *PXCLCOL;
+
+/* -------------------------- XCOL classes --------------------------- */
+
+/***********************************************************************/
+/* XCOL: table having one column containing several values comma */
+/* (or any other character) separated. When creating the table, the */
+/* name of the X column is given by the NAME option. */
+/* This sample has a limitation: */
+/* - The X column has the same length than in the physical file. */
+/* This tables produces as many rows for a physical row than the */
+/* number of items in the X column (eventually 0). */
+/***********************************************************************/
+
+/***********************************************************************/
+/* XCL table. */
+/***********************************************************************/
+class XCLDEF : public PRXDEF { /* Logical table description */
+ friend class TDBXCL;
+ public:
+ // Constructor
+ XCLDEF(void);
+
+ // Implementation
+ virtual const char *GetType(void) {return "XCL";}
+
+ // Methods
+ virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
+ virtual PTDB GetTable(PGLOBAL g, MODE mode);
+
+ protected:
+ // Members
+ char *Xcol; /* The column containing separated fields */
+ char Sep; /* The field separator, defaults to comma */
+ int Mult; /* Multiplication factor */
+ }; // end of XCLDEF
+
+/***********************************************************************/
+/* This is the class declaration for the XCOL table. */
+/***********************************************************************/
+class TDBXCL : public TDBPRX {
+ friend class XCLDEF;
+ friend class PRXCOL;
+ friend class XCLCOL;
+ public:
+ // Constructor
+ TDBXCL(PXCLDEF tdp);
+
+ // Implementation
+ virtual AMT GetAmType(void) {return TYPE_AM_XCOL;}
+
+ // Methods
+ virtual void ResetDB(void) {N = 0; Tdbp->ResetDB();}
+ virtual int RowNumber(PGLOBAL g, bool b = FALSE);
+
+ // Database routines
+ virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual int GetMaxSize(PGLOBAL g);
+ virtual bool OpenDB(PGLOBAL g);
+ virtual int ReadDB(PGLOBAL g);
+
+ protected:
+ // Members
+ char *Xcolumn; // Multiple column name
+ PXCLCOL Xcolp; // To the XCVCOL column
+ int Mult; // Multiplication factor
+ int N; // The current table index
+ int M; // The occurence rank
+ BYTE RowFlag; // 0: Ok, 1: Same, 2: Skip
+ bool New; // TRUE for new line
+ char Sep; // The Xcol separator
+ }; // end of class TDBXCL
+
+/***********************************************************************/
+/* Class XCLCOL: for the multiple CSV column. */
+/***********************************************************************/
+class XCLCOL : public PRXCOL {
+ friend class TDBXCL;
+ public:
+ // Constructors
+ XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
+
+ // Methods
+ virtual void Reset(void) {} // Evaluated only by TDBXCL
+ virtual void ReadColumn(PGLOBAL g);
+
+ protected:
+ // Default constructor not to be used
+ XCLCOL(void) {}
+
+ // Members
+ char *Cbuf; // The column buffer
+ char *Cp; // Pointer to current position
+ char Sep; // The separator
+ }; // end of class XCLCOL
diff --git a/storage/connect/user_connect.cc b/storage/connect/user_connect.cc
index 3fd3ac43e32..d85f11d1950 100644
--- a/storage/connect/user_connect.cc
+++ b/storage/connect/user_connect.cc
@@ -43,6 +43,7 @@
#include "osutil.h"
#include "global.h"
#include "plgdbsem.h"
+#include "connect.h"
#include "user_connect.h"
#include "mycat.h"
@@ -54,11 +55,6 @@ extern int xtrace;
/****************************************************************************/
PCONNECT user_connect::to_users= NULL;
-/****************************************************************************/
-/* CONNECT functions called externally. */
-/****************************************************************************/
-PGLOBAL CntExit(PGLOBAL g);
-
/* -------------------------- class user_connect -------------------------- */
/****************************************************************************/
diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp
index a56841d8980..a96dec2565c 100644
--- a/storage/connect/valblk.cpp
+++ b/storage/connect/valblk.cpp
@@ -266,7 +266,7 @@ char TYPBLK<char>::GetTypedValue(PVAL valp)
{return valp->GetTinyValue();}
/***********************************************************************/
-/* Set one value in a block. */
+/* Set one value in a block from a zero terminated string. */
/***********************************************************************/
template <class TYPE>
void TYPBLK<TYPE>::SetValue(PSZ p, int n)
@@ -295,6 +295,22 @@ template <>
char TYPBLK<char>::GetTypedValue(PSZ p) {return (char)atoi(p);}
/***********************************************************************/
+/* Set one value in a block from an array of characters. */
+/***********************************************************************/
+template <class TYPE>
+void TYPBLK<TYPE>::SetValue(char *sp, uint len, int n)
+ {
+ PGLOBAL& g = Global;
+ PSZ spz = (PSZ)PlugSubAlloc(g, NULL, 0); // Temporary
+
+ if (sp)
+ memcpy(spz, sp, len);
+
+ spz[len] = 0;
+ SetValue(spz, n);
+ } // end of SetValue
+
+/***********************************************************************/
/* Set one value in a block from a value in another block. */
/***********************************************************************/
template <class TYPE>
@@ -552,11 +568,19 @@ void CHRBLK::SetValue(PVAL valp, int n)
} // end of SetValue
/***********************************************************************/
-/* Set one value in a block. */
+/* Set one value in a block from a zero terminated string. */
/***********************************************************************/
void CHRBLK::SetValue(PSZ sp, int n)
{
- size_t len = (sp) ? strlen(sp) : 0;
+ uint len = (sp) ? strlen(sp) : 0;
+ SetValue(sp, len, n);
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block from an array of characters. */
+/***********************************************************************/
+void CHRBLK::SetValue(char *sp, uint len, int n)
+ {
char *p = Chrp + n * Long;
#if defined(_DEBUG) || defined(DEBTRACE)
@@ -568,15 +592,16 @@ void CHRBLK::SetValue(PSZ sp, int n)
#endif
if (sp)
- strncpy(p, sp, Long);
- else
- *p = '\0';
+ memcpy(p, sp, len);
- if (Blanks)
+ if (Blanks) {
// Suppress eventual ending zero and right fill with blanks
for (register int i = len; i < Long; i++)
p[i] = ' ';
+ } else if ((signed)len < Long)
+ p[len] = 0;
+
SetNull(n, false);
} // end of SetValue
@@ -801,12 +826,33 @@ void STRBLK::SetValue(PVAL valp, int n)
} // end of SetValue
/***********************************************************************/
-/* Set one value in a block. */
+/* Set one value in a block from a zero terminated string. */
/***********************************************************************/
void STRBLK::SetValue(PSZ p, int n)
{
- Strp[n] = (PSZ)PlugSubAlloc(Global, NULL, strlen(p) + 1);
- strcpy(Strp[n], p);
+ if (p) {
+ Strp[n] = (PSZ)PlugSubAlloc(Global, NULL, strlen(p) + 1);
+ strcpy(Strp[n], p);
+ } else
+ Strp[n] = NULL;
+
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block from an array of characters. */
+/***********************************************************************/
+void STRBLK::SetValue(char *sp, uint len, int n)
+ {
+ PSZ p;
+
+ if (sp) {
+ p = (PSZ)PlugSubAlloc(Global, NULL, len + 1);
+ memcpy(p, sp, len);
+ p[len] = 0;
+ } else
+ p = NULL;
+
+ Strp[n] = p;
} // end of SetValue
/***********************************************************************/
diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h
index 9a85577a104..d9286b72f9f 100644
--- a/storage/connect/valblk.h
+++ b/storage/connect/valblk.h
@@ -36,6 +36,7 @@ class VALBLK : public BLOCK {
void *GetValPointer(void) {return Blkp;}
void SetValPointer(void *mp) {Blkp = mp;}
int GetType(void) {return Type;}
+ int GetPrec(void) {return Prec;}
void SetCheck(bool b) {Check = b;}
void MoveNull(int i, int j)
{if (To_Nulls) To_Nulls[j] = To_Nulls[j];}
@@ -64,6 +65,7 @@ class VALBLK : public BLOCK {
virtual void SetValue(double fval, int n) {assert(false);}
virtual void SetValue(char 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(PVAL valp, int n) = 0;
virtual void SetValue(PVBLK pv, int n1, int n2) = 0;
#if 0
@@ -109,7 +111,7 @@ class TYPBLK : public VALBLK {
// Implementation
virtual void Init(PGLOBAL g, bool check);
- virtual int GetVlen(void) {return sizeof(int);}
+ virtual int GetVlen(void) {return sizeof(TYPE);}
//virtual PSZ GetCharValue(int n);
virtual short GetShortValue(int n) {return (short)Typp[n];}
virtual int GetIntValue(int n) {return (int)Typp[n];}
@@ -120,6 +122,7 @@ class TYPBLK : public VALBLK {
// Methods
virtual void SetValue(PSZ sp, int n);
+ virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(short sval, int n)
{Typp[n] = (TYPE)sval; SetNull(n, false);}
virtual void SetValue(int lval, int n)
@@ -175,6 +178,7 @@ class CHRBLK : public VALBLK {
// Methods
virtual void SetValue(PSZ sp, int n);
+ virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
//virtual void SetValues(PVBLK pv, int k, int n);
@@ -221,6 +225,7 @@ class STRBLK : public VALBLK {
// Methods
virtual void SetValue(PSZ sp, int n);
+ virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
//virtual void SetValues(PVBLK pv, int k, int n);
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index 9053658b461..e60f3889ef5 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -88,12 +88,13 @@ PSZ strlwr(PSZ s);
}
#endif // !WIN32
+#ifdef NOT_USED
/***********************************************************************/
/* Returns the bitmap representing the conditions that must not be */
/* met when returning from TestValue for a given operator. */
/* Bit one is EQ, bit 2 is LT, and bit 3 is GT. */
/***********************************************************************/
-BYTE OpBmp(PGLOBAL g, OPVAL opc)
+static BYTE OpBmp(PGLOBAL g, OPVAL opc)
{
BYTE bt;
@@ -113,6 +114,7 @@ BYTE OpBmp(PGLOBAL g, OPVAL opc)
return bt;
} // end of OpBmp
+#endif
/***********************************************************************/
/* GetTypeName: returns the PlugDB internal type name. */
@@ -155,46 +157,6 @@ int GetTypeSize(int type, int len)
} // end of GetTypeSize
/***********************************************************************/
-/* GetPLGType: returns the PlugDB type corresponding to a DB type. */
-/***********************************************************************/
-int GetPLGType(int type)
- {
- int tp;
-
- switch (type) {
- case DB_CHAR:
- case DB_STRING: tp = TYPE_STRING; break;
- case DB_SHORT: tp = TYPE_SHORT; break;
- case DB_INT: tp = TYPE_INT; break;
- case DB_DOUBLE: tp = TYPE_FLOAT; break;
- case DB_DATE: tp = TYPE_DATE; break;
- default: tp = TYPE_ERROR;
- } // endswitch type
-
- return tp;
- } // end of GetPLGType
-
-/***********************************************************************/
-/* GetDBType: returns the DB type corresponding to a PlugDB type. */
-/***********************************************************************/
-int GetDBType(int type)
- {
- int tp;
-
- switch (type) {
- case TYPE_STRING: tp = DB_CHAR; break;
- case TYPE_SHORT: tp = DB_SHORT; break;
- case TYPE_INT: tp = DB_INT; break;
- case TYPE_BIGINT:
- case TYPE_FLOAT: tp = DB_DOUBLE; break;
- case TYPE_DATE: tp = DB_DATE; break;
- default: tp = DB_ERROR;
- } // endswitch type
-
- return tp;
- } // end of GetPLGType
-
-/***********************************************************************/
/* GetFormatType: returns the FORMAT character(s) according to type. */
/***********************************************************************/
char *GetFormatType(int type)
@@ -606,7 +568,7 @@ void TYPVAL<TYPE>::SetValue_char(char *p, int n)
if (minus && Tval)
Tval = - Tval;
- if (trace)
+ if (trace > 1)
htrc(strcat(strcat(strcpy(buf, " setting %s to: "), Fmt), "\n"),
GetTypeName(Type), Tval);
@@ -625,7 +587,7 @@ void TYPVAL<double>::SetValue_char(char *p, int n)
buf[n] = '\0';
Tval = atof(buf);
- if (trace)
+ if (trace > 1)
htrc(" setting double: '%s' -> %lf\n", buf, Tval);
Null = false;
@@ -940,7 +902,7 @@ void TYPVAL<PSZ>::SetValue_char(char *p, int n)
*(++p) = '\0';
- if (trace)
+ if (trace > 1)
htrc(" Setting string to: '%s'\n", Strp);
Null = false;
@@ -1143,10 +1105,13 @@ bool TYPVAL<PSZ>::IsEqual(PVAL vp, bool chktype)
return false;
else if (Null || vp->IsNull())
return false;
- else if (Ci || vp->IsCi())
- return !stricmp(Strp, vp->GetCharValue());
+
+ char buf[32];
+
+ if (Ci || vp->IsCi())
+ return !stricmp(Strp, vp->GetCharString(buf));
else // (!Ci)
- return !strcmp(Strp, vp->GetCharValue());
+ return !strcmp(Strp, vp->GetCharString(buf));
} // end of IsEqual
@@ -1261,9 +1226,6 @@ void DTVAL::SetTimeShift(void)
/* though the gmtime C function. The purpose of this function is to */
/* extend the range of valid dates by accepting negative time values. */
/***********************************************************************/
-#define MYSQL_SERVER 1
-#include "tztime.h"
-#include "sql_priv.h"
#include "sql_class.h"
#include "sql_time.h"
@@ -1282,15 +1244,14 @@ static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime)
static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm)
{
MYSQL_TIME ltime;
- current_thd->variables.time_zone->gmt_sec_to_TIME(&ltime, (my_time_t) *timep);
+ thd_gmt_sec_to_TIME(current_thd, &ltime, (my_time_t) *timep);
TIME_to_localtime(tm, &ltime);
return tm;
}
-struct tm *DTVAL::GetGmTime(void)
+struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
{
- static struct tm tm_static; /* TODO: Move as a parameter to GetGmTime() */
struct tm *datm;
time_t t = (time_t)Tval;
@@ -1300,13 +1261,13 @@ struct tm *DTVAL::GetGmTime(void)
for (n = 0; t < 0; n += 4)
t += FOURYEARS;
- datm = gmtime_mysql(&t, &tm_static);
+ datm = gmtime_mysql(&t, tm_buffer);
if (datm)
datm->tm_year -= n;
} else
- datm = gmtime_mysql(&t, &tm_static);
+ datm = gmtime_mysql(&t, tm_buffer);
return datm;
} // end of GetGmTime
@@ -1332,7 +1293,7 @@ bool DTVAL::MakeTime(struct tm *ptm)
int n, y = ptm->tm_year;
time_t t = mktime_mysql(ptm);
- if (trace)
+ if (trace > 1)
htrc("MakeTime from (%d,%d,%d,%d,%d,%d)\n",
ptm->tm_year, ptm->tm_mon, ptm->tm_mday,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
@@ -1355,7 +1316,7 @@ bool DTVAL::MakeTime(struct tm *ptm)
}
Tval= (int) t;
- if (trace)
+ if (trace > 1)
htrc("MakeTime Ival=%d\n", Tval);
return false;
@@ -1375,7 +1336,7 @@ bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
datm.tm_mon=0;
datm.tm_year=70;
- if (trace)
+ if (trace > 1)
htrc("MakeDate from(%d,%d,%d,%d,%d,%d) nval=%d\n",
val[0], val[1], val[2], val[3], val[4], val[5], nval);
@@ -1439,7 +1400,7 @@ bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
} // endfor i
- if (trace)
+ if (trace > 1)
htrc("MakeDate datm=(%d,%d,%d,%d,%d,%d)\n",
datm.tm_year, datm.tm_mon, datm.tm_mday,
datm.tm_hour, datm.tm_min, datm.tm_sec);
@@ -1500,7 +1461,7 @@ void DTVAL::SetValue_char(char *p, int n)
ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
MakeDate(NULL, dval, ndv);
- if (trace)
+ if (trace > 1)
htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
Null = false;
@@ -1524,7 +1485,7 @@ void DTVAL::SetValue_psz(PSZ p)
ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
MakeDate(NULL, dval, ndv);
- if (trace)
+ if (trace > 1)
htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
Null = false;
@@ -1556,7 +1517,7 @@ char *DTVAL::GetCharString(char *p)
{
if (Pdtp) {
size_t n = 0;
- struct tm *ptm = GetGmTime();
+ struct tm tm, *ptm= GetGmTime(&tm);
if (ptm)
n = strftime(Sdate, Len + 1, Pdtp->OutFmt, ptm);
@@ -1582,7 +1543,7 @@ char *DTVAL::ShowValue(char *buf, int len)
if (Pdtp) {
char *p;
size_t m, n = 0;
- struct tm *ptm = GetGmTime();
+ struct tm tm, *ptm = GetGmTime(&tm);
if (Len < len) {
p = buf;
@@ -1612,7 +1573,7 @@ char *DTVAL::ShowValue(char *buf, int len)
bool DTVAL::GetTmMember(OPVAL op, int& mval)
{
bool rc = false;
- struct tm *ptm = GetGmTime();
+ struct tm tm, *ptm = GetGmTime(&tm);
switch (op) {
case OP_MDAY: mval = ptm->tm_mday; break;
@@ -1640,7 +1601,7 @@ bool DTVAL::WeekNum(PGLOBAL g, int& nval)
{
// w is the start of the week SUN=0, MON=1, etc.
int m, n, w = nval % 7;
- struct tm *ptm = GetGmTime();
+ struct tm tm, *ptm = GetGmTime(&tm);
// Which day is January 4th of this year?
m = (367 + ptm->tm_wday - ptm->tm_yday) % 7;
@@ -1664,7 +1625,7 @@ bool DTVAL::WeekNum(PGLOBAL g, int& nval)
bool DTVAL::FormatValue(PVAL vp, char *fmt)
{
char *buf = (char*)vp->GetTo_Val(); // Should be big enough
- struct tm *ptm = GetGmTime();
+ struct tm tm, *ptm = GetGmTime(&tm);
if (trace)
htrc("FormatValue: ptm=%p len=%d\n", ptm, vp->GetValLen());
diff --git a/storage/connect/value.h b/storage/connect/value.h
index 0f7b795c252..62b4ea4617a 100644
--- a/storage/connect/value.h
+++ b/storage/connect/value.h
@@ -38,7 +38,6 @@ typedef struct _datpar *PDTP; // For DTVAL
/***********************************************************************/
/* Utilities used to test types and to allocated values. */
/***********************************************************************/
-int GetPLGType(int);
PVAL AllocateValue(PGLOBAL, void *, short);
// Exported functions
@@ -50,7 +49,6 @@ DllExport int TranslateSQLType(int stp, int prec, int& len);
#endif
DllExport char *GetFormatType(int);
DllExport int GetFormatType(char);
-DllExport int GetDBType(int);
DllExport bool IsTypeChar(int type);
DllExport bool IsTypeNum(int type);
DllExport int ConvertType(int, int, CONV, bool match = false);
@@ -82,12 +80,12 @@ class DllExport VALUE : public BLOCK {
virtual longlong GetBigintValue(void) = 0;
virtual double GetFloatValue(void) = 0;
virtual void *GetTo_Val(void) = 0;
+ virtual void SetPrec(int prec) {Prec = prec;}
bool IsNull(void) {return Null;}
void SetNull(bool b) {Null = b;}
void SetNullable(bool b) {Nullable = b;}
int GetType(void) {return Type;}
int GetClen(void) {return Clen;}
- void SetPrec(int prec) {Prec = prec;}
void SetGlobal(PGLOBAL g) {Global = g;}
// Methods
@@ -217,6 +215,7 @@ class DllExport TYPVAL<PSZ>: public VALUE {
virtual longlong GetBigintValue(void) {return atoll(Strp);}
virtual double GetFloatValue(void) {return atof(Strp);}
virtual void *GetTo_Val(void) {return Strp;}
+ virtual void SetPrec(int prec) {Ci = prec != 0;}
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype);
@@ -289,7 +288,7 @@ class DllExport DTVAL : public TYPVAL<int> {
bool MakeDate(PGLOBAL g, int *val, int nval);
bool WeekNum(PGLOBAL g, int& nval);
- struct tm *GetGmTime(void);
+ struct tm *GetGmTime(struct tm *);
protected:
// Default constructor not to be used
diff --git a/storage/connect/xobject.h b/storage/connect/xobject.h
index c77fb703823..79325f155cf 100644
--- a/storage/connect/xobject.h
+++ b/storage/connect/xobject.h
@@ -71,7 +71,6 @@ class DllExport XOBJECT : public BLOCK {
virtual bool VerifyColumn(PTBX txp) {return false;}
virtual bool VerifyTdb(PTDB& tdbp) {return false;}
virtual bool IsColInside(PCOL colp) {return false;}
- virtual void MarkCol(ushort) {}
protected:
PVAL Value; // The current value of the object.
diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h
index 8475c46d52d..7ef2d26136c 100644
--- a/storage/connect/xtable.h
+++ b/storage/connect/xtable.h
@@ -173,6 +173,7 @@ class DllExport TDBASE : public TDB {
virtual int GetRecpos(void) = 0;
virtual bool SetRecpos(PGLOBAL g, int recpos);
virtual bool IsReadOnly(void) {return Read_Only;}
+ virtual bool IsView(void) {return FALSE;}
virtual CHARSET_INFO *data_charset()
{
/*
diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc
index c6c967ceb9d..aca5ad8c731 100644
--- a/storage/perfschema/ha_perfschema.cc
+++ b/storage/perfschema/ha_perfschema.cc
@@ -18,11 +18,9 @@
Performance schema storage engine (implementation).
*/
-#include "my_global.h"
+#include "sql_plugin.h"
#include "my_pthread.h"
#include "my_atomic.h"
-#include "sql_plugin.h"
-#include "mysql/plugin.h"
#include "ha_perfschema.h"
#include "pfs_engine_table.h"
#include "pfs_column_values.h"