summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--storage/connect/CMakeLists.txt20
-rw-r--r--storage/connect/connect.cc69
-rw-r--r--storage/connect/connect.h2
-rw-r--r--storage/connect/filter.h1
-rw-r--r--storage/connect/ha_connect.cc68
-rw-r--r--storage/connect/inihandl.cpp2
-rw-r--r--storage/connect/jdbconn.cpp11
-rw-r--r--storage/connect/mycat.cc115
-rw-r--r--storage/connect/mycat.h4
-rw-r--r--storage/connect/myconn.cpp12
-rw-r--r--storage/connect/mysql-test/connect/disabled.def1
-rw-r--r--storage/connect/mysql-test/connect/r/grant.result174
-rw-r--r--storage/connect/mysql-test/connect/r/ini_grant.result26
-rw-r--r--storage/connect/mysql-test/connect/r/mysql_grant.result24
-rw-r--r--storage/connect/mysql-test/connect/r/xml2_grant.result30
-rw-r--r--storage/connect/mysql-test/connect/r/xml_grant.result30
-rw-r--r--storage/connect/mysql-test/connect/t/grant.inc30
-rw-r--r--storage/connect/mysql-test/connect/t/grant.test25
-rw-r--r--storage/connect/mysql-test/connect/t/grant2.test260
-rw-r--r--storage/connect/mysql-test/connect/t/ini_grant.result89
-rw-r--r--storage/connect/mysql-test/connect/t/ini_grant.test26
-rw-r--r--storage/connect/mysql-test/connect/t/mysql_grant.test24
-rw-r--r--storage/connect/plgdbsem.h29
-rw-r--r--storage/connect/reldef.cpp278
-rw-r--r--storage/connect/reldef.h9
-rw-r--r--storage/connect/restget.cpp42
-rw-r--r--storage/connect/tabcmg.cpp23
-rw-r--r--storage/connect/tabdos.cpp23
-rw-r--r--storage/connect/tabdos.h1
-rw-r--r--storage/connect/tabfix.cpp2
-rw-r--r--storage/connect/tabfmt.cpp5
-rw-r--r--storage/connect/tabjson.cpp44
-rw-r--r--storage/connect/tabmysql.cpp9
-rw-r--r--storage/connect/tabodbc.cpp6
-rw-r--r--storage/connect/tabrest.cpp142
-rw-r--r--storage/connect/tabrest.h21
-rw-r--r--storage/connect/tabutil.cpp16
-rw-r--r--storage/connect/tabutil.h3
-rw-r--r--storage/connect/tabvct.cpp3
-rw-r--r--storage/connect/tabxml.cpp4
-rw-r--r--storage/connect/valblk.cpp4
-rw-r--r--storage/connect/value.cpp583
-rw-r--r--storage/connect/xindex.cpp14
-rw-r--r--storage/connect/xtable.h5
44 files changed, 1299 insertions, 1010 deletions
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt
index 4ff9afd486b..92e2e53a61b 100644
--- a/storage/connect/CMakeLists.txt
+++ b/storage/connect/CMakeLists.txt
@@ -73,10 +73,6 @@ ELSE(NOT UNIX)
tabwmi.cpp tabwmi.h tabmac.cpp tabmac.h macutil.cpp macutil.h)
# Add exception handling to the CONNECT project)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
- SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
- SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
- SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD")
- SET(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MD")
SET(IPHLPAPI_LIBRARY iphlpapi.lib)
IF(MSVC AND (CMAKE_CXX_COMPILER_ID MATCHES Clang))
# Connect does not work with clang-cl
@@ -322,6 +318,9 @@ ENDIF(CONNECT_WITH_MONGO)
OPTION(CONNECT_WITH_REST "Compile CONNECT storage engine with REST support" ON)
IF(CONNECT_WITH_REST)
+ MESSAGE(STATUS "=====> REST support is ON")
+ SET(CONNECT_SOURCES ${CONNECT_SOURCES} tabrest.cpp tabrest.h)
+ add_definitions(-DREST_SUPPORT)
FIND_PACKAGE(cpprestsdk QUIET)
IF (cpprestsdk_FOUND)
IF(UNIX)
@@ -329,9 +328,18 @@ IF(CONNECT_WITH_REST)
# If needed edit next line to set the path to libcpprest.so
SET(REST_LIBRARY -lcpprest)
MESSAGE (STATUS ${REST_LIBRARY})
+ ELSE(NOT UNIX)
+# Next line sets debug compile mode matching cpprest_2_10d.dll
+# when it was binary installed (can be change later in Visual Studio)
+# Comment it out if not needed depending on your cpprestsdk installation.
+ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
ENDIF(UNIX)
- SET(CONNECT_SOURCES ${CONNECT_SOURCES} tabrest.cpp restget.cpp tabrest.h)
- add_definitions(-DREST_SUPPORT)
+# IF(REST_LIBRARY) why this? how about Windows
+ SET(CONNECT_SOURCES ${CONNECT_SOURCES} restget.cpp)
+ add_definitions(-DREST_SOURCE)
+# ENDIF()
+ ELSE(NOT cpprestsdk_FOUND)
+# MESSAGE(STATUS "=====> cpprestsdk package not found")
ENDIF (cpprestsdk_FOUND)
ENDIF(CONNECT_WITH_REST)
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index b1078de8eaa..dfc619cf4af 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
/***********************************************************************/
-/* Author Olivier BERTRAND bertrandop@gmail.com 2004-2017 */
+/* Author Olivier BERTRAND bertrandop@gmail.com 2004-2019 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -389,6 +389,9 @@ RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool reset, bool mrr)
try {
for (colp = tdbp->GetColumns(); rc == RC_OK && colp;
colp = colp->GetNext()) {
+ xtrc(2, "Going to read column %s of table %s\n",
+ colp->GetName(), tdbp->GetName());
+
if (reset)
colp->Reset();
@@ -563,7 +566,7 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
rc = tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine
} else if (tdbp->GetMode() == MODE_UPDATE && tdbp->IsIndexed())
- rc = ((PTDBDOX)tdbp)->Txfp->UpdateSortedRows(g);
+ rc = ((PTDBDOS)tdbp)->GetTxfp()->UpdateSortedRows(g);
switch (rc) {
case RC_FX:
@@ -590,7 +593,7 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
if (!tdbp->IsRemote()) {
// Make all the eventual indexes
- PTDBDOX tbxp = (PTDBDOX)tdbp;
+ PTDBDOS tbxp = (PTDBDOS)tdbp;
tbxp->ResetKindex(g, NULL);
tbxp->SetKey_Col(NULL);
rc = tbxp->ResetTableOpt(g, true, tbxp->GetDef()->Indexable() == 1);
@@ -619,8 +622,8 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted)
{
PIXDEF xdp;
- PTDBDOX tdbp;
- DOXDEF *dfp;
+ PTDBDOS tdbp;
+ DOSDEF *dfp;
if (!ptdb)
return -1;
@@ -630,9 +633,9 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted)
} else if (ptdb->GetDef()->Indexable() == 3) {
return 1;
} else
- tdbp= (PTDBDOX)ptdb;
+ tdbp= (PTDBDOS)ptdb;
- dfp= (DOXDEF*)tdbp->To_Def;
+ dfp= (DOSDEF*)tdbp->GetDef();
//if (!(k= colp->GetKey()))
// if (colp->GetOpt() >= 2) {
@@ -642,16 +645,16 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted)
// This is a pseudo indexed sorted block optimized column
// return 0;
- if (tdbp->To_Kindex)
- if (((XXBASE*)tdbp->To_Kindex)->GetID() == id) {
- tdbp->To_Kindex->Reset(); // Same index
- return (tdbp->To_Kindex->IsMul()) ? 2 : 1;
+ if (tdbp->GetKindex())
+ if (((XXBASE*)tdbp->GetKindex())->GetID() == id) {
+ tdbp->GetKindex()->Reset(); // Same index
+ return (tdbp->GetKindex()->IsMul()) ? 2 : 1;
} else {
- tdbp->To_Kindex->Close();
- tdbp->To_Kindex= NULL;
+ tdbp->GetKindex()->Close();
+ tdbp->SetKindex(NULL);
} // endif colp
- for (xdp= dfp->To_Indx; xdp; xdp= xdp->GetNext())
+ for (xdp= dfp->GetIndx(); xdp; xdp= xdp->GetNext())
if (xdp->GetID() == id)
break;
@@ -673,7 +676,7 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted)
if (tdbp->InitialyzeIndex(g, xdp, sorted))
return 0;
- return (tdbp->To_Kindex->IsMul()) ? 2 : 1;
+ return (tdbp->GetKindex()->IsMul()) ? 2 : 1;
} // end of CntIndexInit
#if defined(WORDS_BIGENDIAN)
@@ -707,7 +710,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
int n, x;
RCODE rc;
XXBASE *xbp;
- PTDBDOX tdbp;
+ PTDBDOS tdbp;
if (!ptdb)
return RC_FX;
@@ -733,12 +736,12 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
goto rnd;
} else
- tdbp= (PTDBDOX)ptdb;
+ tdbp= (PTDBDOS)ptdb;
// Set reference values and index operator
- if (!tdbp->To_Link || !tdbp->To_Kindex) {
+ if (!tdbp->GetLink() || !tdbp->GetKindex()) {
// if (!tdbp->To_Xdp) {
- sprintf(g->Message, "Index not initialized for table %s", tdbp->Name);
+ sprintf(g->Message, "Index not initialized for table %s", tdbp->GetName());
return RC_FX;
#if 0
} // endif !To_Xdp
@@ -751,7 +754,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
#endif // 0
} // endif !To_Kindex
- xbp= (XXBASE*)tdbp->To_Kindex;
+ xbp= (XXBASE*)tdbp->GetKindex();
if (kr) {
char *kp= (char*)kr->key;
@@ -761,13 +764,13 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
PVAL valp;
PCOL colp;
- for (n= 0; n < tdbp->Knum; n++) {
- colp= (PCOL)tdbp->To_Key_Col[n];
+ for (n= 0; n < tdbp->GetKnum(); n++) {
+ colp= (PCOL)tdbp->Key(n);
if (colp->GetColUse(U_NULLS))
kp++; // Skip null byte
- valp= tdbp->To_Link[n]->GetValue();
+ valp= tdbp->Link(n)->GetValue();
if (!valp->IsTypeNum()) {
if (colp->GetColUse(U_VAR)) {
@@ -837,7 +840,7 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
bool b, rcb;
PVAL valp;
PCOL colp;
- PTDBDOX tdbp;
+ PTDBDOS tdbp;
XXBASE *xbp;
if (!ptdb)
@@ -862,35 +865,35 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
return k[1] - k[0] + 1;
} else
- tdbp= (PTDBDOX)ptdb;
+ tdbp= (PTDBDOS)ptdb;
- if (!tdbp->To_Kindex || !tdbp->To_Link) {
- if (!tdbp->To_Xdp) {
- sprintf(g->Message, "Index not initialized for table %s", tdbp->Name);
+ if (!tdbp->GetKindex() || !tdbp->GetLink()) {
+ if (!tdbp->GetXdp()) {
+ sprintf(g->Message, "Index not initialized for table %s", tdbp->GetName());
DBUG_PRINT("Range", ("%s", g->Message));
return -1;
} else // Dynamic index
- return tdbp->To_Xdp->GetMaxSame(); // TODO a better estimate
+ return tdbp->GetXdp()->GetMaxSame(); // TODO a better estimate
} else
- xbp= (XXBASE*)tdbp->To_Kindex;
+ xbp= (XXBASE*)tdbp->GetKindex();
for (b= false, i= 0; i < 2; i++) {
p= kp= key[i];
if (kp) {
- for (n= 0; n < tdbp->Knum; n++) {
+ for (n= 0; n < tdbp->GetKnum(); n++) {
if (kmap[i] & (key_part_map)(1 << n)) {
if (b == true)
// Cannot do indexing with missing intermediate key
return -1;
- colp= (PCOL)tdbp->To_Key_Col[n];
+ colp= (PCOL)tdbp->Key(n);
if (colp->GetColUse(U_NULLS))
p++; // Skip null byte ???
- valp= tdbp->To_Link[n]->GetValue();
+ valp= tdbp->Link(n)->GetValue();
if (!valp->IsTypeNum()) {
if (colp->GetColUse(U_VAR)) {
diff --git a/storage/connect/connect.h b/storage/connect/connect.h
index 3a60cd40160..d1fc2ea592f 100644
--- a/storage/connect/connect.h
+++ b/storage/connect/connect.h
@@ -46,6 +46,7 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
bool *incl, key_part_map *kmap);
PGLOBAL CntExit(PGLOBAL g);
+#if 0
/***********************************************************************/
/* Definition of classes XKPDEF, DOXDEF, TDBDOX */
/* These classes purpose is chiefly to access protected items! */
@@ -76,3 +77,4 @@ class XKPDEF: public KPARTDEF {
public:
XKPDEF(const char *name, int n) : KPARTDEF((PSZ)name, n) {}
}; // end of class XKPDEF
+#endif // 0
diff --git a/storage/connect/filter.h b/storage/connect/filter.h
index b0fea3d69e0..c6ab8fddd35 100644
--- a/storage/connect/filter.h
+++ b/storage/connect/filter.h
@@ -48,7 +48,6 @@ class DllExport FILTER : public XOBJECT { /* Filter description block */
PVAL &Val(int i) {return Test[i].Value;}
bool &Conv(int i) {return Test[i].Conv;}
void SetNext(PFIL filp) {Next = filp;}
- bool MakeSelector(PGLOBAL g, PSTRG s);
// Methods
virtual void Reset(void);
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index a3ea363226e..a111082e786 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -170,9 +170,9 @@
#define JSONMAX 10 // JSON Default max grp size
extern "C" {
- char version[]= "Version 1.06.0010 June 01, 2019";
+ char version[]= "Version 1.07.0001 November 12, 2019";
#if defined(__WIN__)
- char compver[]= "Version 1.06.0010 " __DATE__ " " __TIME__;
+ char compver[]= "Version 1.07.0001 " __DATE__ " " __TIME__;
char slash= '\\';
#else // !__WIN__
char slash= '/';
@@ -1045,6 +1045,8 @@ TABTYPE ha_connect::GetRealType(PTOS pos)
case TAB_REST:
type = TAB_NIY;
break;
+ default:
+ break;
} // endswitch type
#endif // REST_SUPPORT
@@ -2964,10 +2966,12 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
case Item_func::LE_FUNC: vop= OP_LE; break;
case Item_func::GE_FUNC: vop= OP_GE; break;
case Item_func::GT_FUNC: vop= OP_GT; break;
+#if MYSQL_VERSION_ID > 100200
case Item_func::LIKE_FUNC:
- vop= OP_LIKE;
- neg= ((Item_func_opt_neg *)condf)->negated;
- break;
+ vop = OP_LIKE;
+ neg= ((Item_func_like*)condf)->negated;
+ break;
+#endif // VERSION_ID > 100200
case Item_func::ISNOTNULL_FUNC:
neg= true;
// fall through
@@ -3785,9 +3789,9 @@ int ha_connect::index_init(uint idx, bool sorted)
active_index= MAX_KEY;
rc= HA_ERR_INTERNAL_ERROR;
} else if (tdbp->GetKindex()) {
- if (((PTDBDOX)tdbp)->To_Kindex->GetNum_K()) {
+ if (((PTDBDOS)tdbp)->GetKindex()->GetNum_K()) {
if (tdbp->GetFtype() != RECFM_NAF)
- ((PTDBDOX)tdbp)->GetTxfp()->ResetBuffer(g);
+ ((PTDBDOS)tdbp)->GetTxfp()->ResetBuffer(g);
active_index= idx;
// } else { // Void table
@@ -4503,34 +4507,13 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
case TAB_DIR:
case TAB_ZIP:
case TAB_OEM:
-#ifdef NO_EMBEDDED_ACCESS_CHECKS
- return false;
- #endif
-
- /*
- Check FILE_ACL
- If table or table->mdl_ticket is NULL - it's a DLL, e.g. CREATE TABLE.
- if the table has an MDL_EXCLUSIVE lock - it's a DDL too, e.g. the
- insert step of CREATE ... SELECT.
-
- Otherwise it's a DML, the table was normally opened, locked,
- privilege were already checked, and table->grant.privilege is set.
- With SQL SECURITY DEFINER, table->grant.privilege has definer's privileges.
-
- Unless we're in prelocking mode, in this case table->grant.privilege
- is only checked in start_stmt(), not in external_lock().
- */
- if (!table || !table->mdl_ticket || table->mdl_ticket->get_type() == MDL_EXCLUSIVE)
- return check_access(thd, FILE_ACL, db, NULL, NULL, 0, 0);
-
- if ((!quick && thd->lex->requires_prelocking()) || table->grant.privilege & FILE_ACL)
- return false;
-
- status_var_increment(thd->status_var.access_denied_errors);
- my_error(access_denied_error_code(thd->password), MYF(0),
- thd->security_ctx->priv_user, thd->security_ctx->priv_host,
- (thd->password ? ER(ER_YES) : ER(ER_NO)));
- return true;
+ if (table && table->pos_in_table_list) // if SELECT
+ {
+ //Switch_to_definer_security_ctx backup_ctx(thd, table->pos_in_table_list);
+ return check_global_access(thd, FILE_ACL);
+ }
+ else
+ return check_global_access(thd, FILE_ACL);
case TAB_ODBC:
case TAB_JDBC:
case TAB_MONGO:
@@ -5653,6 +5636,8 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
case TAB_CSV:
ttp = TAB_REST;
break;
+ default:
+ break;
} // endswitch type
#endif // REST_SUPPORT
} // endif ttp
@@ -6062,7 +6047,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
} // endif !nblin
for (i= 0; !rc && i < qrp->Nblin; i++) {
- typ= len= prec= dec= 0;
+ typ= len= prec= dec= flg= 0;
tm= NOT_NULL_FLAG;
cnm= (char*)"noname";
dft= xtra= key= fmt= tn= NULL;
@@ -6103,6 +6088,9 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
tm= 0; // Nullable
break;
+ case FLD_FLAG:
+ flg = crp->Kdata->GetIntValue(i);
+ break;
case FLD_FORMAT:
fmt= (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL;
break;
@@ -6233,7 +6221,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
// Now add the field
if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra,
- fmt, 0, dbf, v))
+ fmt, flg, dbf, v))
rc= HA_ERR_OUT_OF_MEM;
} // endfor i
@@ -7379,14 +7367,14 @@ maria_declare_plugin(connect)
&connect_storage_engine,
"CONNECT",
"Olivier Bertrand",
- "Management of External Data (SQL/NOSQL/MED), including many file formats",
+ "Management of External Data (SQL/NOSQL/MED), including Rest query results",
PLUGIN_LICENSE_GPL,
connect_init_func, /* Plugin Init */
connect_done_func, /* Plugin Deinit */
- 0x0106, /* version number (1.06) */
+ 0x0107, /* version number (1.07) */
NULL, /* status variables */
connect_system_variables, /* system variables */
- "1.06.0010", /* string version */
+ "1.07.0001", /* string version */
MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
}
maria_declare_plugin_end;
diff --git a/storage/connect/inihandl.cpp b/storage/connect/inihandl.cpp
index dacab3c485c..8e79aeac7ef 100644
--- a/storage/connect/inihandl.cpp
+++ b/storage/connect/inihandl.cpp
@@ -194,7 +194,7 @@ static void PROFILE_Save( FILE *file, PROFILESECTION *section )
}
for (key = section->key; key; key = key->next)
- if (key->name[0]) {
+ if (key->name && key->name[0]) {
fprintf(file, "%s", SVP(key->name));
if (key->value)
diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp
index e0aca3333e6..2cb75e0adc1 100644
--- a/storage/connect/jdbconn.cpp
+++ b/storage/connect/jdbconn.cpp
@@ -1196,9 +1196,14 @@ int JDBConn::GetResultSize(PCSZ sql, PCOL colp)
if ((rc = ExecuteQuery(sql)) != RC_OK)
return -1;
- if ((rc = Fetch()) > 0)
- SetColumnValue(1, NULL, colp->GetValue());
- else
+ if ((rc = Fetch()) > 0) {
+ try {
+ SetColumnValue(1, NULL, colp->GetValue());
+ } catch (...) {
+ return -4;
+ } // end catch
+
+ } else
return -2;
if ((rc = Fetch()) != 0)
diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc
index 411e96e3dc8..f8b3dc03aa5 100644
--- a/storage/connect/mycat.cc
+++ b/storage/connect/mycat.cc
@@ -95,7 +95,7 @@
#endif // ZIP_SUPPORT
#if defined(REST_SUPPORT)
#include "tabrest.h"
-#endif // Rest_SUPPORT
+#endif // REST_SUPPORT
#include "mycat.h"
/***********************************************************************/
@@ -104,8 +104,9 @@
#if defined(__WIN__)
extern "C" HINSTANCE s_hModule; // Saved module handle
#endif // !__WIN__
-
-PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
+#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
+bool MongoEnabled(void);
+#endif // JAVA_SUPPORT || CMGO_SUPPORT
/***********************************************************************/
/* Get the plugin directory. */
@@ -347,100 +348,6 @@ uint GetFuncID(const char *func)
return fnc;
} // end of GetFuncID
-/***********************************************************************/
-/* OEMColumn: Get table column info for an OEM table. */
-/***********************************************************************/
-PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
- {
- typedef PQRYRES (__stdcall *XCOLDEF) (PGLOBAL, void*, char*, char*, bool);
- const char *module, *subtype;
- char c, soname[_MAX_PATH], getname[40] = "Col";
-#if defined(__WIN__)
- HANDLE hdll; /* Handle to the external DLL */
-#else // !__WIN__
- void *hdll; /* Handle for the loaded shared library */
-#endif // !__WIN__
- XCOLDEF coldef = NULL;
- PQRYRES qrp = NULL;
-
- module = topt->module;
- subtype = topt->subtype;
-
- if (!module || !subtype)
- return NULL;
-
- /*********************************************************************/
- /* Ensure that the .dll doesn't have a path. */
- /* This is done to ensure that only approved dll from the system */
- /* directories are used (to make this even remotely secure). */
- /*********************************************************************/
- if (check_valid_path(module, strlen(module))) {
- strcpy(g->Message, "Module cannot contain a path");
- return NULL;
- } else
- PlugSetPath(soname, module, GetPluginDir());
-
- // The exported name is always in uppercase
- for (int i = 0; ; i++) {
- c = subtype[i];
- getname[i + 3] = toupper(c);
- if (!c) break;
- } // endfor i
-
-#if defined(__WIN__)
- // Load the Dll implementing the table
- if (!(hdll = LoadLibrary(soname))) {
- char buf[256];
- DWORD rc = GetLastError();
-
- sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname);
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
- (LPTSTR)buf, sizeof(buf), NULL);
- strcat(strcat(g->Message, ": "), buf);
- return NULL;
- } // endif hDll
-
- // Get the function returning an instance of the external DEF class
- if (!(coldef = (XCOLDEF)GetProcAddress((HINSTANCE)hdll, getname))) {
- sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), getname);
- FreeLibrary((HMODULE)hdll);
- return NULL;
- } // endif coldef
-#else // !__WIN__
- const char *error = NULL;
-
- // Load the desired shared library
- if (!(hdll = dlopen(soname, RTLD_LAZY))) {
- error = dlerror();
- sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
- return NULL;
- } // endif Hdll
-
- // Get the function returning an instance of the external DEF class
- if (!(coldef = (XCOLDEF)dlsym(hdll, getname))) {
- error = dlerror();
- sprintf(g->Message, MSG(GET_FUNC_ERR), getname, SVP(error));
- dlclose(hdll);
- return NULL;
- } // endif coldef
-#endif // !__WIN__
-
- // Just in case the external Get function does not set error messages
- sprintf(g->Message, "Error getting column info from %s", subtype);
-
- // Get the table column definition
- qrp = coldef(g, topt, tab, db, info);
-
-#if defined(__WIN__)
- FreeLibrary((HMODULE)hdll);
-#else // !__WIN__
- dlclose(hdll);
-#endif // !__WIN__
-
- return qrp;
- } // end of OEMColumns
-
/* ------------------------- Class CATALOG --------------------------- */
/***********************************************************************/
@@ -481,10 +388,10 @@ void MYCAT::Reset(void)
/* GetTableDesc: retrieve a table descriptor. */
/* Look for a table descriptor matching the name and type. */
/***********************************************************************/
-PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep,
+PTABDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep,
LPCSTR type, PRELDEF *)
{
- PRELDEF tdp= NULL;
+ PTABDEF tdp= NULL;
if (trace(1))
htrc("GetTableDesc: name=%s am=%s\n", tablep->GetName(), SVP(type));
@@ -505,12 +412,12 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep,
/* MakeTableDesc: make a table/view description. */
/* Note: caller must check if name already exists before calling it. */
/***********************************************************************/
-PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
+PTABDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
{
TABTYPE tc;
LPCSTR name= (PSZ)PlugDup(g, tablep->GetName());
LPCSTR schema= (PSZ)PlugDup(g, tablep->GetSchema());
- PRELDEF tdp= NULL;
+ PTABDEF tdp= NULL;
if (trace(1))
htrc("MakeTableDesc: name=%s schema=%s am=%s\n",
@@ -578,8 +485,8 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
} // endswitch
// Do make the table/view definition
- if (tdp && tdp->Define(g, this, name, schema, am))
- tdp= NULL;
+ if (tdp && tdp->Define(g, this, name, schema, am))
+ tdp = NULL;
if (trace(1))
htrc("Table %s made\n", am);
@@ -592,7 +499,7 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
/***********************************************************************/
PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type)
{
- PRELDEF tdp;
+ PTABDEF tdp;
PTDB tdbp= NULL;
// LPCSTR name= tablep->GetName();
diff --git a/storage/connect/mycat.h b/storage/connect/mycat.h
index 818e535b32d..6473f7a5c11 100644
--- a/storage/connect/mycat.h
+++ b/storage/connect/mycat.h
@@ -102,14 +102,14 @@ class MYCAT : public CATALOG {
// Methods
void Reset(void);
bool StoreIndex(PGLOBAL, PTABDEF) {return false;} // Temporary
- PRELDEF GetTableDesc(PGLOBAL g, PTABLE tablep,
+ PTABDEF GetTableDesc(PGLOBAL g, PTABLE tablep,
LPCSTR type, PRELDEF *prp = NULL);
PTDB GetTable(PGLOBAL g, PTABLE tablep,
MODE mode = MODE_READ, LPCSTR type = NULL);
void ClearDB(PGLOBAL g);
protected:
- PRELDEF MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am);
+ PTABDEF MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am);
// Members
ha_connect *Hc; // The Connect handler
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index 253c42bb002..4303a9e191b 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -472,7 +472,7 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db,
int pt, const char *csname)
{
const char *pipe = NULL;
- uint cto = 10, nrt = 20;
+ //uint cto = 10, nrt = 20;
my_bool my_true= 1;
m_DB = mysql_init(NULL);
@@ -485,11 +485,11 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db,
if (trace(1))
htrc("MYSQLC Open: m_DB=%.4X size=%d\n", m_DB, (int)sizeof(*m_DB));
- // Removed to do like FEDERATED do
+ // Removed to do like FEDERATED does
//mysql_options(m_DB, MYSQL_READ_DEFAULT_GROUP, "client-mariadb");
- mysql_options(m_DB, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL);
- mysql_options(m_DB, MYSQL_OPT_CONNECT_TIMEOUT, &cto);
- mysql_options(m_DB, MYSQL_OPT_READ_TIMEOUT, &nrt);
+//mysql_options(m_DB, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL);
+//mysql_options(m_DB, MYSQL_OPT_CONNECT_TIMEOUT, &cto);
+//mysql_options(m_DB, MYSQL_OPT_READ_TIMEOUT, &nrt);
//mysql_options(m_DB, MYSQL_OPT_WRITE_TIMEOUT, ...);
#if defined(__WIN__)
@@ -879,7 +879,7 @@ MYSQL_FIELD *MYSQLC::GetNextField(void)
PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
{
PCSZ fmt;
- char *name, v;
+ char *name, v= 0;
int n;
bool uns;
PCOLRES *pcrp, crp;
diff --git a/storage/connect/mysql-test/connect/disabled.def b/storage/connect/mysql-test/connect/disabled.def
index 1de4deb0a60..a4d629fc3d1 100644
--- a/storage/connect/mysql-test/connect/disabled.def
+++ b/storage/connect/mysql-test/connect/disabled.def
@@ -20,4 +20,5 @@ mongo_c : Need MongoDB running and its C Driver installed
mongo_java_2 : Need MongoDB running and its Java Driver installed
mongo_java_3 : Need MongoDB running and its Java Driver installed
tbl_thread : Bug MDEV-9844,10179,14214 03/01/2018 OB Option THREAD removed
+grant2 : Until fixed
#vcol : Different error code on different versions
diff --git a/storage/connect/mysql-test/connect/r/grant.result b/storage/connect/mysql-test/connect/r/grant.result
index 4e64b983ea7..681442724e5 100644
--- a/storage/connect/mysql-test/connect/r/grant.result
+++ b/storage/connect/mysql-test/connect/r/grant.result
@@ -13,7 +13,7 @@ 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)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -30,19 +30,19 @@ SELECT user();
user()
user@localhost
SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
INSERT INTO t1 VALUES ();
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM t1 WHERE path='xxx';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE t1 SET path='yyy' WHERE path='xxx';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
# Testing a VIEW created with FILE privileges but accessed with no FILE
SELECT user();
user()
@@ -52,13 +52,13 @@ SELECT user();
user()
user@localhost
SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
INSERT INTO v1 VALUES (1,1,1,1);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE v1 SET path=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -101,7 +101,7 @@ 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)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -111,23 +111,23 @@ SELECT user();
user()
user@localhost
INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
# Testing a VIEW created with FILE privileges but accessed with no FILE
SELECT user();
user()
@@ -137,13 +137,13 @@ SELECT user();
user()
user@localhost
SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -157,7 +157,7 @@ SELECT user();
user()
user@localhost
ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
DROP USER user@localhost;
#
@@ -196,7 +196,7 @@ 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)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -206,23 +206,23 @@ SELECT user();
user()
user@localhost
INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
# Testing a VIEW created with FILE privileges but accessed with no FILE
SELECT user();
user()
@@ -232,13 +232,13 @@ SELECT user();
user()
user@localhost
SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -252,7 +252,7 @@ SELECT user();
user()
user@localhost
ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
DROP USER user@localhost;
#
@@ -291,7 +291,7 @@ 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)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -301,23 +301,23 @@ SELECT user();
user()
user@localhost
INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
# Testing a VIEW created with FILE privileges but accessed with no FILE
SELECT user();
user()
@@ -327,13 +327,13 @@ SELECT user();
user()
user@localhost
SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -347,7 +347,7 @@ SELECT user();
user()
user@localhost
ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
DROP USER user@localhost;
#
@@ -386,7 +386,7 @@ 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)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -396,23 +396,23 @@ SELECT user();
user()
user@localhost
INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
# Testing a VIEW created with FILE privileges but accessed with no FILE
SELECT user();
user()
@@ -422,13 +422,13 @@ SELECT user();
user()
user@localhost
SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -442,7 +442,7 @@ SELECT user();
user()
user@localhost
ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
DROP USER user@localhost;
#
@@ -481,7 +481,7 @@ 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)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -491,23 +491,23 @@ SELECT user();
user()
user@localhost
INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
# Testing a VIEW created with FILE privileges but accessed with no FILE
SELECT user();
user()
@@ -517,13 +517,13 @@ SELECT user();
user()
user@localhost
SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -537,7 +537,7 @@ SELECT user();
user()
user@localhost
ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
DROP USER user@localhost;
#
diff --git a/storage/connect/mysql-test/connect/r/ini_grant.result b/storage/connect/mysql-test/connect/r/ini_grant.result
index 68330278183..ce53b0ef5ca 100644
--- a/storage/connect/mysql-test/connect/r/ini_grant.result
+++ b/storage/connect/mysql-test/connect/r/ini_grant.result
@@ -32,7 +32,7 @@ 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)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -42,21 +42,21 @@ SELECT user();
user()
user@localhost
INSERT INTO t1 VALUES ('sec2','val2');
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE t1 SET val='val11';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
# Testing a VIEW created with FILE privileges but accessed with no FILE
SELECT user();
user()
@@ -66,13 +66,13 @@ SELECT user();
user()
user@localhost
SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
INSERT INTO v1 VALUES ('sec3','val3');
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE v1 SET val='val11';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP VIEW v1;
DROP TABLE t1;
DROP USER user@localhost;
diff --git a/storage/connect/mysql-test/connect/r/mysql_grant.result b/storage/connect/mysql-test/connect/r/mysql_grant.result
index 5f630834392..7bcae585425 100644
--- a/storage/connect/mysql-test/connect/r/mysql_grant.result
+++ b/storage/connect/mysql-test/connect/r/mysql_grant.result
@@ -9,7 +9,7 @@ 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)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -25,19 +25,19 @@ SELECT user();
user()
user@localhost
SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
INSERT INTO t1 VALUES ('xxx');
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM t1 WHERE a='xxx';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE t1 SET a='yyy' WHERE a='xxx';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
# Testing a VIEW created with FILE privileges but accessed with no FILE
SELECT user();
user()
@@ -47,13 +47,13 @@ SELECT user();
user()
user@localhost
SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
diff --git a/storage/connect/mysql-test/connect/r/xml2_grant.result b/storage/connect/mysql-test/connect/r/xml2_grant.result
index 9eb818bf32f..74f372f493c 100644
--- a/storage/connect/mysql-test/connect/r/xml2_grant.result
+++ b/storage/connect/mysql-test/connect/r/xml2_grant.result
@@ -33,7 +33,7 @@ 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)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -43,23 +43,23 @@ SELECT user();
user()
user@localhost
INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
# Testing a VIEW created with FILE privileges but accessed with no FILE
SELECT user();
user()
@@ -69,13 +69,13 @@ SELECT user();
user()
user@localhost
SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -89,7 +89,7 @@ SELECT user();
user()
user@localhost
ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
DROP USER user@localhost;
#
diff --git a/storage/connect/mysql-test/connect/r/xml_grant.result b/storage/connect/mysql-test/connect/r/xml_grant.result
index 9d8cb64b60a..d2a2e444e81 100644
--- a/storage/connect/mysql-test/connect/r/xml_grant.result
+++ b/storage/connect/mysql-test/connect/r/xml_grant.result
@@ -31,7 +31,7 @@ a
DROP VIEW v1;
DROP TABLE t1;
CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=domdoc,rownode=row' FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -41,23 +41,23 @@ SELECT user();
user()
user@localhost
INSERT INTO t1 VALUES (10);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE t1 SET a=20;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
TRUNCATE TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 READONLY=1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
ALTER TABLE t1 FILE_NAME='t2.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
CREATE VIEW v1 AS SELECT * FROM t1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
# Testing a VIEW created with FILE privileges but accessed with no FILE
SELECT user();
user()
@@ -67,13 +67,13 @@ SELECT user();
user()
user@localhost
SELECT * FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
INSERT INTO v1 VALUES (2);
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
UPDATE v1 SET a=123;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DELETE FROM v1;
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
SELECT user();
user()
root@localhost
@@ -87,7 +87,7 @@ SELECT user();
user()
user@localhost
ALTER TABLE t1 FILE_NAME='t1.EXT';
-ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
DROP TABLE t1;
DROP USER user@localhost;
#
diff --git a/storage/connect/mysql-test/connect/t/grant.inc b/storage/connect/mysql-test/connect/t/grant.inc
index 6580c845b56..ef6e0cec297 100644
--- a/storage/connect/mysql-test/connect/t/grant.inc
+++ b/storage/connect/mysql-test/connect/t/grant.inc
@@ -25,7 +25,7 @@ DROP TABLE t1;
# Making sure DROP erased the data file
--error 1
--remove_file $MYSQLD_DATADIR/test/t1.$FILE_EXT
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
--eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT $TABLE_OPTIONS FILE_NAME='t1.EXT'
--connection default
SELECT user();
@@ -33,23 +33,23 @@ SELECT user();
INSERT INTO t1 VALUES (10);
--connection user
SELECT user();
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO t1 VALUES (10);
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SELECT * FROM t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t1 SET a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE FROM t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
TRUNCATE TABLE t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 READONLY=1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 FILE_NAME='t2.EXT';
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DROP TABLE t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_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
@@ -57,13 +57,13 @@ SELECT user();
CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
--connection user
SELECT user();
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SELECT * FROM v1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO v1 VALUES (2);
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1 SET a=123;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE FROM v1;
--connection default
SELECT user();
@@ -74,7 +74,7 @@ DROP TABLE t1;
INSERT INTO t1 VALUES (10);
--connection user
SELECT user();
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 FILE_NAME='t1.EXT';
--connection default
DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/t/grant.test b/storage/connect/mysql-test/connect/t/grant.test
index 738f156d8a4..5e07b7af369 100644
--- a/storage/connect/mysql-test/connect/t/grant.test
+++ b/storage/connect/mysql-test/connect/t/grant.test
@@ -11,7 +11,7 @@ REVOKE FILE ON *.* FROM user@localhost;
--connect(user,localhost,user,,)
--connection user
SELECT user();
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
CREATE TABLE t1 (
path VARCHAR(256) NOT NULL flag=1,
fname VARCHAR(256) NOT NULL,
@@ -28,23 +28,24 @@ CREATE TABLE t1 (
) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*';
# "size>0" to skip directory names on Windows
--replace_result $MYSQLD_DATADIR DATADIR/
+--sorted_result
SELECT fname, ftype, size FROM t1 WHERE size>0;
--connection user
SELECT user();
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SELECT * FROM t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO t1 VALUES ();
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE FROM t1 WHERE path='xxx';
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t1 SET path='yyy' WHERE path='xxx';
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
TRUNCATE TABLE t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 READONLY=1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
CREATE VIEW v1 AS SELECT * FROM t1;
--echo # Testing a VIEW created with FILE privileges but accessed with no FILE
@@ -53,13 +54,13 @@ SELECT user();
CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
--connection user
SELECT user();
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SELECT * FROM v1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO v1 VALUES (1,1,1,1);
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1 SET path=123;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE FROM v1;
--disconnect user
diff --git a/storage/connect/mysql-test/connect/t/grant2.test b/storage/connect/mysql-test/connect/t/grant2.test
index 8e7d9453e70..351eb97f11a 100644
--- a/storage/connect/mysql-test/connect/t/grant2.test
+++ b/storage/connect/mysql-test/connect/t/grant2.test
@@ -23,13 +23,13 @@ CREATE DEFINER=user@localhost SQL SECURITY DEFINER VIEW v1_baddefiner AS SELECT
SELECT * FROM t1;
SELECT * FROM v1_invoker;
SELECT * FROM v1_definer;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SELECT * FROM v1_baddefiner;
--connect(user,localhost,user,,)
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SELECT * FROM t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SELECT * FROM v1_invoker;
SELECT * FROM v1_definer;
--connection default
@@ -47,9 +47,9 @@ UPDATE t1 SET a=11;
UPDATE v1_invoker SET a=12;
UPDATE v1_definer SET a=13;
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t1 SET a=21;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1_invoker SET a=22;
UPDATE v1_definer SET a=23;
--connection default
@@ -67,9 +67,9 @@ INSERT INTO t1 VALUES (11);
INSERT INTO v1_invoker VALUES (12);
INSERT INTO v1_definer VALUES (13);
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO t1 VALUES (21);
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO v1_invoker VALUES (22);
INSERT INTO v1_definer VALUES (23);
--connection default
@@ -79,7 +79,7 @@ DROP TABLE t1;
--echo # Testing SQLCOM_REPLACE
# REPLACE is not supported by ConnectSE, so we're testing the difference
-# between ER_ACCESS_DENIED_ERROR vs ER_NOT_ALLOWED_COMMAND
+# between ER_SPECIFIC_ACCESS_DENIED_ERROR vs ER_NOT_ALLOWED_COMMAND
--connection default
CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
INSERT INTO t1 VALUES (10);
@@ -92,9 +92,9 @@ REPLACE INTO v1_invoker VALUES (12);
--error ER_NOT_ALLOWED_COMMAND
REPLACE INTO v1_definer VALUES (13);
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
REPLACE INTO t1 VALUES (21);
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
REPLACE INTO v1_invoker VALUES (22);
--error ER_NOT_ALLOWED_COMMAND
REPLACE INTO v1_definer VALUES (23);
@@ -113,9 +113,9 @@ DELETE FROM t1 WHERE a=11;
DELETE FROM v1_invoker WHERE a=12;
DELETE FROM v1_definer WHERE a=13;
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE FROM t1 WHERE a=21;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE FROM v1_invoker WHERE a=22;
DELETE FROM v1_definer WHERE a=23;
--connection default
@@ -137,10 +137,10 @@ CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
--eval LOAD DATA LOCAL INFILE '$MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE v1_definer
--connection user
--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
--eval LOAD DATA LOCAL INFILE '$MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE t1
--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
--eval LOAD DATA LOCAL INFILE '$MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE v1_invoker
--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
--eval LOAD DATA LOCAL INFILE '$MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE v1_definer
@@ -156,7 +156,7 @@ INSERT INTO t1 VALUES (10);
TRUNCATE TABLE t1;
INSERT INTO t1 VALUES (11);
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
TRUNCATE TABLE t1;
--connection default
DROP TABLE t1;
@@ -168,7 +168,7 @@ DROP TABLE t1;
CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
INSERT INTO t1 VALUES (10);
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DROP TABLE t1;
--connection default
DROP TABLE t1;
@@ -193,7 +193,7 @@ DROP TABLE t1;
--echo # Testing SQLCOM_CREATE_TABLE
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
--connection default
@@ -216,13 +216,13 @@ UNLOCK TABLES;
LOCK TABLE v1_definer WRITE;
UNLOCK TABLES;
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
LOCK TABLE t1 READ;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
LOCK TABLE t1 WRITE;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
LOCK TABLE v1_invoker READ;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
LOCK TABLE v1_invoker WRITE;
LOCK TABLE v1_definer READ;
UNLOCK TABLES;
@@ -299,108 +299,108 @@ UPDATE v2_definer a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
--connection user
# All queries with t1 should fail
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t1 a1,t1 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t1 a1,t2 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t1 a1,t3 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t1 a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t1 a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t1 a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t1 a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
# All queries with t2 should fail
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t2 a1,t1 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t2 a1,t2 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t2 a1,t3 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t2 a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t2 a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t2 a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t2 a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
# t3 does not need FILE_ALC
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t3 a1,t1 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t3 a1,t2 a2 SET a1.a=50 WHERE a1.a=a2.a;
# This is OK:
UPDATE t3 a1,t3 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t3 a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
# This is OK:
UPDATE t3 a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t3 a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
# This is OK:
UPDATE t3 a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
# All queries with v1_invoker should fail
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1_invoker a1,t1 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1_invoker a1,t2 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1_invoker a1,t3 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1_invoker a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1_invoker a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1_invoker a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1_invoker a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
# v1_definer does not need FILE_ACL from the invoker
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1_definer a1,t1 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1_definer a1,t2 a2 SET a1.a=50 WHERE a1.a=a2.a;
UPDATE v1_definer a1,t3 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1_definer a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
UPDATE v1_definer a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1_definer a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
UPDATE v1_definer a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
# All queries with v2_invoker should fail
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v2_invoker a1,t1 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v2_invoker a1,t2 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v2_invoker a1,t3 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v2_invoker a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v2_invoker a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v2_invoker a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v2_invoker a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
# v2_definer does not need FILE_ACL from the invoker
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v2_definer a1,t1 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v2_definer a1,t2 a2 SET a1.a=50 WHERE a1.a=a2.a;
UPDATE v2_definer a1,t3 a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v2_definer a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
UPDATE v2_definer a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v2_definer a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
UPDATE v2_definer a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
@@ -476,108 +476,108 @@ DELETE a1 FROM v2_definer a1,v2_definer a2 WHERE a1.a=a2.a;
--connection user
# All queries with t1 should fail
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t1 a1,t1 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t1 a1,t2 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t1 a1,t3 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t1 a1,v1_invoker a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t1 a1,v1_definer a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t1 a1,v2_invoker a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t1 a1,v2_definer a2 WHERE a1.a=a2.a;
# All queries with t2 should fail
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t2 a1,t1 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t2 a1,t2 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t2 a1,t3 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t2 a1,v1_invoker a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t2 a1,v1_definer a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t2 a1,v2_invoker a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t2 a1,v2_definer a2 WHERE a1.a=a2.a;
# t3 does not need FILE_ALC
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t3 a1,t1 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t3 a1,t2 a2 WHERE a1.a=a2.a;
# This is OK:
DELETE a1 FROM t3 a1,t3 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t3 a1,v1_invoker a2 WHERE a1.a=a2.a;
# This is OK:
DELETE a1 FROM t3 a1,v1_definer a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM t3 a1,v2_invoker a2 WHERE a1.a=a2.a;
# This is OK:
DELETE a1 FROM t3 a1,v2_definer a2 WHERE a1.a=a2.a;
# All queries with v1_invoker should fail
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v1_invoker a1,t1 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v1_invoker a1,t2 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v1_invoker a1,t3 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v1_invoker a1,v1_invoker a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v1_invoker a1,v1_definer a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v1_invoker a1,v2_invoker a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v1_invoker a1,v2_definer a2 WHERE a1.a=a2.a;
# v1_definer does not need FILE_ACL from the invoker
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v1_definer a1,t1 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v1_definer a1,t2 a2 WHERE a1.a=a2.a;
DELETE a1 FROM v1_definer a1,t3 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v1_definer a1,v1_invoker a2 WHERE a1.a=a2.a;
DELETE a1 FROM v1_definer a1,v1_definer a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v1_definer a1,v2_invoker a2 WHERE a1.a=a2.a;
DELETE a1 FROM v1_definer a1,v2_definer a2 WHERE a1.a=a2.a;
# All queries with v2_invoker should fail
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v2_invoker a1,t1 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v2_invoker a1,t2 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v2_invoker a1,t3 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v2_invoker a1,v1_invoker a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v2_invoker a1,v1_definer a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v2_invoker a1,v2_invoker a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v2_invoker a1,v2_definer a2 WHERE a1.a=a2.a;
# v2_definer does not need FILE_ACL from the invoker
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v2_definer a1,t1 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v2_definer a1,t2 a2 WHERE a1.a=a2.a;
DELETE a1 FROM v2_definer a1,t3 a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v2_definer a1,v1_invoker a2 WHERE a1.a=a2.a;
DELETE a1 FROM v2_definer a1,v1_definer a2 WHERE a1.a=a2.a;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE a1 FROM v2_definer a1,v2_invoker a2 WHERE a1.a=a2.a;
DELETE a1 FROM v2_definer a1,v2_definer a2 WHERE a1.a=a2.a;
@@ -598,9 +598,9 @@ DROP VIEW v2;
CREATE VIEW v2 AS SELECT * FROM v1_definer;
DROP VIEW v2;
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
CREATE VIEW v2 AS SELECT * FROM t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
CREATE VIEW v2 AS SELECT * FROM v1_invoker;
CREATE VIEW v2 AS SELECT * FROM v1_definer;
DROP VIEW v2;
@@ -625,21 +625,21 @@ INSERT INTO v1_definer SELECT * FROM t1 WHERE a=20;
INSERT INTO v1_definer SELECT * FROM v1_invoker WHERE a=20;
INSERT INTO v1_definer SELECT * FROM v1_definer WHERE a=20;
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO t1 SELECT * FROM t1 WHERE a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO t1 SELECT * FROM v1_invoker WHERE a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO t1 SELECT * FROM v1_definer WHERE a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO v1_invoker SELECT * FROM t1 WHERE a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO v1_invoker SELECT * FROM v1_invoker WHERE a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO v1_invoker SELECT * FROM v1_definer WHERE a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO v1_definer SELECT * FROM t1 WHERE a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO v1_definer SELECT * FROM v1_invoker WHERE a=20;
# This is OK:
INSERT INTO v1_definer SELECT * FROM v1_definer WHERE a=20;
@@ -650,7 +650,7 @@ DROP TABLE t1;
--echo # Testing SQLCOM_REPLACE_SELECT
# REPLACE is not supported by CONNECT
-# so we're testing ER_NOT_ALLOWED_COMMAND vs ER_ACCESS_DENIED_ERROR here
+# so we're testing ER_NOT_ALLOWED_COMMAND vs ER_SPECIFIC_ACCESS_DENIED_ERROR here
--connection default
CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
INSERT INTO t1 VALUES (10);
@@ -676,17 +676,17 @@ REPLACE INTO v1_definer SELECT * FROM v1_invoker WHERE a=20;
REPLACE INTO v1_definer SELECT * FROM v1_definer WHERE a=20;
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
REPLACE INTO t1 SELECT * FROM t1 WHERE a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
REPLACE INTO t1 SELECT * FROM v1_invoker WHERE a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
REPLACE INTO t1 SELECT * FROM v1_definer WHERE a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
REPLACE INTO v1_invoker SELECT * FROM t1 WHERE a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
REPLACE INTO v1_invoker SELECT * FROM v1_invoker WHERE a=20;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
REPLACE INTO v1_invoker SELECT * FROM v1_definer WHERE a=20;
--error ER_NOT_ALLOWED_COMMAND
REPLACE INTO v1_definer SELECT * FROM t1 WHERE a=20;
@@ -708,7 +708,7 @@ SHOW CREATE TABLE t2;
RENAME TABLE t2 TO t1;
--connection user
# TODO: Perhaps FILE_ACL is needed for RENAME. Discuss with Oliver.
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
RENAME TABLE t1 TO t2;
--connection default
DROP TABLE t1;
@@ -723,7 +723,7 @@ SHOW CREATE TABLE t2;
ALTER TABLE t2 RENAME TO t1;
--connection user
# TODO: Perhaps FILE_ACL is not needed for ALTER..RENAME. Discuss with Olivier.
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 RENAME TO t2;
--connection default
DROP TABLE t1;
@@ -739,7 +739,7 @@ DROP TABLE t1;
CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
INSERT INTO t1 VALUES (10);
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 ENGINE=MyISAM;
--connection default
DROP TABLE t1;
@@ -756,7 +756,7 @@ DROP TABLE t1;
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (10);
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
--connection default
DROP TABLE t1;
@@ -779,7 +779,7 @@ CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
INSERT INTO t1 VALUES (10);
ALTER TABLE t1 ADD b INT;
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 ADD c INT;
--connection default
DROP TABLE t1;
@@ -791,7 +791,7 @@ CREATE TABLE t1 (a INT,b INT,c INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.
INSERT INTO t1 VALUES (10,10,10);
ALTER TABLE t1 DROP b;
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 DROP c;
--connection default
DROP TABLE t1;
@@ -803,7 +803,7 @@ CREATE TABLE t1 (a INT NOT NULL,b INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=fix FI
INSERT INTO t1 VALUES (10,10);
ALTER TABLE t1 ADD KEY(a);
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 ADD KEY(b);
--connection default
DROP TABLE t1;
@@ -816,7 +816,7 @@ CREATE TABLE t1 (a INT NOT NULL,b INT NOT NULL, KEY a(a), KEY b(b)) ENGINE=CONNE
INSERT INTO t1 VALUES (10,10);
ALTER TABLE t1 DROP KEY a;
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 DROP KEY b;
--connection default
DROP TABLE t1;
@@ -831,9 +831,9 @@ CREATE INDEX a ON t1 (a);
DROP INDEX a ON t1;
CREATE INDEX a ON t1 (a);
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
CREATE INDEX b ON t1 (b);
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DROP INDEX a ON t1;
--connection default
DROP TABLE t1;
@@ -852,11 +852,11 @@ CALL p_definer();
DROP TABLE t1;
CALL p_invoker();
DROP TABLE t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
CALL p_baddefiner();
--connection user
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
CALL p_invoker();
CALL p_definer();
diff --git a/storage/connect/mysql-test/connect/t/ini_grant.result b/storage/connect/mysql-test/connect/t/ini_grant.result
new file mode 100644
index 00000000000..96d5e192c7d
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/ini_grant.result
@@ -0,0 +1,89 @@
+#
+# Checking FILE privileges
+#
+set sql_mode="";
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+set sql_mode=default;
+connect user,localhost,user,,;
+connection user;
+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 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+connection default;
+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');
+connection user;
+SELECT user();
+user()
+user@localhost
+INSERT INTO t1 VALUES ('sec2','val2');
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+SELECT * FROM t1;
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+UPDATE t1 SET val='val11';
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+DELETE FROM t1;
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+TRUNCATE TABLE t1;
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+ALTER TABLE t1 READONLY=1;
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+DROP TABLE t1;
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+CREATE VIEW v1 AS SELECT * FROM t1;
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+# Testing a VIEW created with FILE privileges but accessed with no FILE
+connection default;
+SELECT user();
+user()
+root@localhost
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
+connection user;
+SELECT user();
+user()
+user@localhost
+SELECT * FROM v1;
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+INSERT INTO v1 VALUES ('sec3','val3');
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+UPDATE v1 SET val='val11';
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+DELETE FROM v1;
+ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
+disconnect user;
+connection default;
+DROP VIEW v1;
+DROP TABLE t1;
+DROP USER user@localhost;
+#
+# Checking FILE privileges: done
+#
diff --git a/storage/connect/mysql-test/connect/t/ini_grant.test b/storage/connect/mysql-test/connect/t/ini_grant.test
index b0ddcb57979..bbf85e5f794 100644
--- a/storage/connect/mysql-test/connect/t/ini_grant.test
+++ b/storage/connect/mysql-test/connect/t/ini_grant.test
@@ -29,7 +29,7 @@ DROP TABLE t1;
# Making sure DROP erased the data file
--error 1
--remove_file $MYSQLD_DATADIR/test/t1.ini
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_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();
@@ -37,21 +37,21 @@ CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CON
INSERT INTO t1 VALUES ('sec1','val1');
--connection user
SELECT user();
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO t1 VALUES ('sec2','val2');
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SELECT * FROM t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t1 SET val='val11';
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE FROM t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
TRUNCATE TABLE t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 READONLY=1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DROP TABLE t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_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
@@ -59,13 +59,13 @@ SELECT user();
CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
--connection user
SELECT user();
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SELECT * FROM v1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO v1 VALUES ('sec3','val3');
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1 SET val='val11';
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE FROM v1;
--disconnect user
--connection default
diff --git a/storage/connect/mysql-test/connect/t/mysql_grant.test b/storage/connect/mysql-test/connect/t/mysql_grant.test
index 7d3d05cb8fd..30737258a1f 100644
--- a/storage/connect/mysql-test/connect/t/mysql_grant.test
+++ b/storage/connect/mysql-test/connect/t/mysql_grant.test
@@ -27,7 +27,7 @@ set sql_mode=default;
--connection user
SELECT user();
--replace_result $PORT PORT
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_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();
@@ -38,19 +38,19 @@ INSERT INTO t1remote VALUES (10),(20),(30);
SELECT * FROM t1;
--connection user
SELECT user();
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SELECT * FROM t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO t1 VALUES ('xxx');
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE FROM t1 WHERE a='xxx';
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE t1 SET a='yyy' WHERE a='xxx';
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
TRUNCATE TABLE t1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
ALTER TABLE t1 READONLY=1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
CREATE VIEW v1 AS SELECT * FROM t1;
--echo # Testing a VIEW created with FILE privileges but accessed with no FILE
@@ -59,13 +59,13 @@ SELECT user();
CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
--connection user
SELECT user();
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SELECT * FROM v1;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
INSERT INTO v1 VALUES (2);
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
UPDATE v1 SET a=123;
---error ER_ACCESS_DENIED_ERROR
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
DELETE FROM v1;
--disconnect user
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h
index f10ae209e9d..a40e32bcfb2 100644
--- a/storage/connect/plgdbsem.h
+++ b/storage/connect/plgdbsem.h
@@ -149,16 +149,22 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_MGO = 194, /* MGO access method type no */
TYPE_AM_OUT = 200}; /* Output relations (storage) */
-enum RECFM {RECFM_NAF = -2, /* Not a file */
- RECFM_OEM = -1, /* OEM file access method */
- RECFM_VAR = 0, /* Varying length DOS files */
- RECFM_FIX = 1, /* Fixed length DOS files */
- RECFM_BIN = 2, /* Binary DOS files (also fixed) */
- RECFM_VCT = 3, /* VCT formatted files */
- RECFM_ODBC = 4, /* Table accessed via ODBC */
- RECFM_JDBC = 5, /* Table accessed via JDBC */
- RECFM_PLG = 6, /* Table accessed via PLGconn */
- RECFM_DBF = 7}; /* DBase formatted file */
+enum RECFM {RECFM_DFLT = 0, /* Default table type */
+ RECFM_NAF = 1, /* Not a file table */
+ RECFM_OEM = 2, /* OEM table */
+ RECFM_VAR = 3, /* Varying length DOS files */
+ RECFM_FIX = 4, /* Fixed length DOS files */
+ RECFM_BIN = 5, /* Binary DOS files (also fixed) */
+ RECFM_DBF = 6, /* DBase formatted file */
+ RECFM_CSV = 7, /* CSV file */
+ RECFM_FMT = 8, /* FMT formatted file */
+ RECFM_VCT = 9, /* VCT formatted files */
+ RECFM_XML = 10, /* XML formatted files */
+ RECFM_JASON = 11, /* JASON formatted files */
+ RECFM_DIR = 12, /* DIR table */
+ RECFM_ODBC = 13, /* Table accessed via ODBC */
+ RECFM_JDBC = 14, /* Table accessed via JDBC */
+ RECFM_PLG = 15}; /* Table accessed via PLGconn */
enum MISC {DB_TABNO = 1, /* DB routines in Utility Table */
MAX_MULT_KEY = 10, /* Max multiple key number */
@@ -537,7 +543,8 @@ enum XFLD {FLD_NO = 0, /* Not a field definition item */
FLD_FORMAT = 16, /* Field format */
FLD_CAT = 17, /* Table catalog */
FLD_SCHEM = 18, /* Table schema */
- FLD_TABNAME = 19}; /* Column Table name */
+ FLD_TABNAME = 19, /* Column Table name */
+ FLD_FLAG = 20}; /* Field flag (CONNECT specific) */
/***********************************************************************/
/* Result of last SQL noconv query. */
diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp
index 8ba8aac3621..2d3c6a6aacd 100644
--- a/storage/connect/reldef.cpp
+++ b/storage/connect/reldef.cpp
@@ -1,11 +1,11 @@
/************* RelDef CPP Program Source Code File (.CPP) **************/
/* PROGRAM NAME: RELDEF */
/* ------------- */
-/* Version 1.6 */
+/* Version 1.7 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2004-2016 */
+/* (C) Copyright to the author Olivier BERTRAND 2004-2019 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -20,7 +20,7 @@
#if defined(__WIN__)
#include <sqlext.h>
#else
-#include <dlfcn.h> // dlopen(), dlclose(), dlsym() ...
+//#include <dlfcn.h> // dlopen(), dlclose(), dlsym() ...
#include "osutil.h"
//#include "sqlext.h"
#endif
@@ -61,6 +61,102 @@ extern handlerton *connect_hton;
/***********************************************************************/
USETEMP UseTemp(void);
char *GetPluginDir(void);
+PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info);
+
+/***********************************************************************/
+/* OEMColumns: Get table column info for an OEM table. */
+/***********************************************************************/
+PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info)
+{
+ typedef PQRYRES(__stdcall* XCOLDEF) (PGLOBAL, void*, char*, char*, bool);
+ const char* module, * subtype;
+ char c, soname[_MAX_PATH], getname[40] = "Col";
+#if defined(__WIN__)
+ HANDLE hdll; /* Handle to the external DLL */
+#else // !__WIN__
+ void* hdll; /* Handle for the loaded shared library */
+#endif // !__WIN__
+ XCOLDEF coldef = NULL;
+ PQRYRES qrp = NULL;
+
+ module = topt->module;
+ subtype = topt->subtype;
+
+ if (!module || !subtype)
+ return NULL;
+
+ /*********************************************************************/
+ /* Ensure that the .dll doesn't have a path. */
+ /* This is done to ensure that only approved dll from the system */
+ /* directories are used (to make this even remotely secure). */
+ /*********************************************************************/
+ if (check_valid_path(module, strlen(module))) {
+ strcpy(g->Message, "Module cannot contain a path");
+ return NULL;
+ }
+ else
+ PlugSetPath(soname, module, GetPluginDir());
+
+ // The exported name is always in uppercase
+ for (int i = 0; ; i++) {
+ c = subtype[i];
+ getname[i + 3] = toupper(c);
+ if (!c) break;
+ } // endfor i
+
+#if defined(__WIN__)
+ // Load the Dll implementing the table
+ if (!(hdll = LoadLibrary(soname))) {
+ char buf[256];
+ DWORD rc = GetLastError();
+
+ sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname);
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
+ (LPTSTR)buf, sizeof(buf), NULL);
+ strcat(strcat(g->Message, ": "), buf);
+ return NULL;
+ } // endif hDll
+
+// Get the function returning an instance of the external DEF class
+ if (!(coldef = (XCOLDEF)GetProcAddress((HINSTANCE)hdll, getname))) {
+ sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), getname);
+ FreeLibrary((HMODULE)hdll);
+ return NULL;
+ } // endif coldef
+#else // !__WIN__
+ const char* error = NULL;
+
+ // Load the desired shared library
+ if (!(hdll = dlopen(soname, RTLD_LAZY))) {
+ error = dlerror();
+ sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
+ return NULL;
+ } // endif Hdll
+
+// Get the function returning an instance of the external DEF class
+ if (!(coldef = (XCOLDEF)dlsym(hdll, getname))) {
+ error = dlerror();
+ sprintf(g->Message, MSG(GET_FUNC_ERR), getname, SVP(error));
+ dlclose(hdll);
+ return NULL;
+ } // endif coldef
+#endif // !__WIN__
+
+ // Just in case the external Get function does not set error messages
+ sprintf(g->Message, "Error getting column info from %s", subtype);
+
+ // Get the table column definition
+ qrp = coldef(g, topt, tab, db, info);
+
+#if defined(__WIN__)
+ FreeLibrary((HMODULE)hdll);
+#else // !__WIN__
+ dlclose(hdll);
+#endif // !__WIN__
+
+ return qrp;
+} // end of OEMColumns
/* --------------------------- Class RELDEF -------------------------- */
@@ -208,6 +304,7 @@ TABDEF::TABDEF(void)
{
Schema = NULL;
Desc = NULL;
+ Recfm = RECFM_DFLT;
Catfunc = FNC_NO;
Card = 0;
Elemt = 0;
@@ -221,11 +318,38 @@ TABDEF::TABDEF(void)
} // end of TABDEF constructor
/***********************************************************************/
+/* Return the table format. */
+/***********************************************************************/
+RECFM TABDEF::GetTableFormat(const char* type)
+{
+ RECFM recfm = Recfm;
+
+ if (Catfunc != FNC_NO)
+ recfm = RECFM_NAF;
+ else if (recfm == RECFM_DFLT)
+ // Default format depends on the table type
+ switch (GetTypeID(type)) {
+ case TAB_DOS: recfm = RECFM_VAR; break;
+ case TAB_CSV: recfm = RECFM_CSV; break;
+ case TAB_FMT: recfm = RECFM_FMT; break;
+ case TAB_FIX: recfm = RECFM_FIX; break;
+ case TAB_BIN: recfm = RECFM_BIN; break;
+ case TAB_VEC: recfm = RECFM_VCT; break;
+ case TAB_DBF: recfm = RECFM_DBF; break;
+ case TAB_XML: recfm = RECFM_XML; break;
+ case TAB_DIR: recfm = RECFM_DIR; break;
+ default: recfm = RECFM_NAF; break;
+ } // endswitch type
+
+ return recfm;
+} // end of GetTableFormat
+
+/***********************************************************************/
/* Define: initialize the table definition block from XDB file. */
/***********************************************************************/
bool TABDEF::Define(PGLOBAL g, PCATLG cat,
LPCSTR name, LPCSTR schema, LPCSTR am)
- {
+{
int poff = 0;
Hc = ((MYCAT*)cat)->GetHandler();
@@ -243,13 +367,17 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat,
NULL;
csname = GetStringCatInfo(g, "Table_charset", NULL);
- // Get The column definitions
- if ((poff = GetColCatInfo(g)) < 0)
- return true;
+ // Do the definition of AM specific fields
+ if (DefineAM(g, am, 0))
+ return true;
- // Do the definition of AM specific fields
- return DefineAM(g, am, poff);
- } // end of Define
+ // Get The column definitions
+ if (stricmp(am, "OEM") && GetColCatInfo(g) < 0)
+ return true;
+
+ Hc->tshp = NULL; // TO BE CHECKED
+ return false;
+} // end of Define
/***********************************************************************/
/* This function returns the database data path. */
@@ -264,71 +392,71 @@ PCSZ TABDEF::GetPath(void)
/***********************************************************************/
int TABDEF::GetColCatInfo(PGLOBAL g)
{
- char *type= GetStringCatInfo(g, "Type", "*");
+ char *type = GetStringCatInfo(g, "Type", "*");
char c, fty, eds;
int i, n, loff, poff, nof, nlg;
- void *field= NULL;
- TABTYPE tc;
- PCOLDEF cdp, lcdp= NULL, tocols= NULL;
+ void *field = NULL;
+ RECFM trf;
+ PCOLDEF cdp, lcdp = NULL, tocols= NULL;
PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO));
memset(pcf, 0, sizeof(COLINFO));
- // Get a unique char identifier for type
- tc= (Catfunc == FNC_NO) ? GetTypeID(type) : TAB_PRX;
+ // Get the table format
+ trf = GetTableFormat(type);
// Take care of the column definitions
i= poff= nof= nlg= 0;
#if defined(__WIN__)
// Offsets of HTML and DIR tables start from 0, DBF at 1
- loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0;
+ loff= (trf == RECFM_DBF) ? 1 : (trf == RECFM_XML || trf == RECFM_DIR) ? -1 : 0;
#else // !__WIN__
// Offsets of HTML tables start from 0, DIR and DBF at 1
- loff = (tc == TAB_DBF || tc == TAB_DIR) ? 1 : (tc == TAB_XML) ? -1 : 0;
+ loff = (trf == RECFM_DBF || trf == RECFM_DIR) ? 1 : (trf == RECFM_XML) ? -1 : 0;
#endif // !__WIN__
while (true) {
- // Default Offset depends on table type
- switch (tc) {
- case TAB_DOS:
- case TAB_FIX:
- case TAB_BIN:
- case TAB_VEC:
- case TAB_DBF:
+ // Default Offset depends on table format
+ switch (trf ) {
+ case RECFM_VAR:
+ case RECFM_FIX:
+ case RECFM_BIN:
+ case RECFM_VCT:
+ case RECFM_DBF:
poff= loff + nof; // Default next offset
nlg= MY_MAX(nlg, poff); // Default lrecl
break;
- case TAB_CSV:
- case TAB_FMT:
+ case RECFM_CSV:
+ case RECFM_FMT:
nlg+= nof;
- case TAB_DIR:
- case TAB_XML:
+ case RECFM_DIR:
+ case RECFM_XML:
poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1);
break;
- case TAB_INI:
- case TAB_MAC:
- case TAB_TBL:
- case TAB_XCL:
- case TAB_OCCUR:
- case TAB_PRX:
- case TAB_OEM:
+ //case RECFM_INI:
+ //case RECFM_MAC:
+ //case RECFM_TBL:
+ //case RECFM_XCL:
+ //case RECFM_OCCUR:
+ //case RECFM_PRX:
+ case RECFM_OEM:
poff = 0; // Offset represents an independant flag
break;
- default: // VCT PLG ODBC JDBC MYSQL WMI...
+ default: // PLG ODBC JDBC MYSQL WMI...
poff = 0; // NA
break;
- } // endswitch tc
+ } // endswitch trf
// do {
field= Hc->GetColumnOption(g, field, pcf);
// } while (field && (*pcf->Name =='*' /*|| pcf->Flags & U_VIRTUAL*/));
- if (tc == TAB_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) {
+ if (trf == RECFM_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) {
// DBF date format defaults to 'YYYMMDD'
pcf->Datefmt= "YYYYMMDD";
pcf->Length= 8;
- } // endif tc
+ } // endif trf
if (!field)
break;
@@ -341,10 +469,10 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
else
loff= cdp->GetOffset();
- switch (tc) {
- case TAB_VEC:
+ switch (trf ) {
+ case RECFM_VCT:
cdp->SetOffset(0); // Not to have shift
- case TAB_BIN:
+ case RECFM_BIN:
// BIN/VEC are packed by default
if (nof) {
// Field width is the internal representation width
@@ -395,7 +523,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
default:
break;
- } // endswitch tc
+ } // endswitch trf
if (lcdp)
lcdp->SetNext(cdp);
@@ -413,21 +541,15 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
if (GetDefType() == TYPE_AM_DOS) {
int ending, recln= 0;
- // Was commented because sometimes ending is 0 even when
- // not specified (for instance if quoted is specified)
-// if ((ending= Hc->GetIntegerOption("Ending")) < 0) {
- if ((ending= Hc->GetIntegerOption("Ending")) <= 0) {
- ending= (tc == TAB_BIN || tc == TAB_VEC) ? 0 : CRLF;
- Hc->SetIntegerOption("Ending", ending);
- } // endif ending
+ ending = Hc->GetIntegerOption("Ending");
// Calculate the default record size
- switch (tc) {
- case TAB_FIX:
- case TAB_BIN:
+ switch (trf ) {
+ case RECFM_FIX:
+ case RECFM_BIN:
recln= nlg + ending; // + length of line ending
break;
- case TAB_VEC:
+ case RECFM_VCT:
recln= nlg;
// if ((k= (pak < 0) ? 8 : pak) > 1)
@@ -436,18 +558,18 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
// recln= ((recln + k - 1) / k) * k;
break;
- case TAB_DOS:
- case TAB_DBF:
+ case RECFM_VAR:
+ case RECFM_DBF:
recln= nlg;
break;
- case TAB_CSV:
- case TAB_FMT:
+ case RECFM_CSV:
+ case RECFM_FMT:
// The number of separators (assuming an extra one can exist)
// recln= poff * ((qotd) ? 3 : 1); to be investigated
recln= nlg + poff * 3; // To be safe
default:
break;
- } // endswitch tc
+ } // endswitch trf
// lrecl must be at least recln to avoid buffer overflow
if (trace(1))
@@ -461,7 +583,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
if (trace(1))
htrc("Lrecl set to %d\n", recln);
- } // endif Lrecl
+ } // endif TYPE
// Attach the column definition to the tabdef
SetCols(tocols);
@@ -500,7 +622,8 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
return NULL;
} else
// PlugSetPath(soname, Module, GetPluginDir()); // Crashes on Fedora
- strncat(strcpy(soname, GetPluginDir()), Module, _MAX_PATH);
+ strncat(strcpy(soname, GetPluginDir()), Module,
+ sizeof(soname) - strlen(soname) - 1);
#if defined(__WIN__)
// Is the DLL already loaded?
@@ -596,10 +719,6 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
cat->Cbuf = (char*)PlugSubAlloc(g, NULL, cat->Cblen);
} // endif Cbuf
- // Here "OEM" should be replace by a more useful value
- if (xdefp->Define(g, cat, Name, Schema, "OEM"))
- return NULL;
-
// Ok, return external block
return xdefp;
} // end of GetXdef
@@ -622,7 +741,7 @@ bool OEMDEF::DeleteTableFile(PGLOBAL g)
/***********************************************************************/
bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int)
{
- Module = GetStringCatInfo(g, "Module", "");
+ Module = GetStringCatInfo(g, "Module", "");
Subtype = GetStringCatInfo(g, "Subtype", Module);
if (!*Module)
@@ -632,7 +751,13 @@ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int)
+ strlen(Subtype) + 3);
sprintf(desc, "%s(%s)", Module, Subtype);
Desc = desc;
- return false;
+
+ // If define block not here yet, get it now
+ if (!Pxdef && !(Pxdef = GetXdef(g)))
+ return true; // Error
+
+ // Here "OEM" should be replace by a more useful value
+ return Pxdef->Define(g, Cat, Name, Schema, Subtype);
} // end of DefineAM
/***********************************************************************/
@@ -640,7 +765,6 @@ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int)
/***********************************************************************/
PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode)
{
- RECFM rfm;
PTDB tdbp = NULL;
// If define block not here yet, get it now
@@ -653,18 +777,10 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode)
/*********************************************************************/
if (!(tdbp = Pxdef->GetTable(g, mode)))
return NULL;
- else
- rfm = tdbp->GetFtype();
-
- if (rfm == RECFM_NAF)
- return tdbp;
- else if (rfm == RECFM_OEM) {
- if (Multiple)
- tdbp = new(g) TDBMUL(tdbp); // No block optimization yet
-
- return tdbp;
- } // endif OEM
+ else if (Multiple && tdbp->GetFtype() == RECFM_OEM)
+ tdbp = new(g) TDBMUL(tdbp); // No block optimization yet
+#if 0
/*********************************************************************/
/* The OEM table is based on a file type (currently DOS+ only) */
/*********************************************************************/
@@ -723,7 +839,7 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode)
if (Multiple)
tdbp = new(g) TDBMUL(tdbp);
-
+#endif // 0
return tdbp;
} // end of GetTable
diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h
index f8256a59b3d..73e178ed51c 100644
--- a/storage/connect/reldef.h
+++ b/storage/connect/reldef.h
@@ -84,10 +84,12 @@ public:
void SetNext(PTABDEF tdfp) {Next = tdfp;}
int GetMultiple(void) {return Multiple;}
int GetPseudo(void) {return Pseudo;}
- PCSZ GetPath(void);
+ RECFM GetRecfm(void) {return Recfm;}
+ PCSZ GetPath(void);
//PSZ GetPath(void)
// {return (Database) ? (PSZ)Database : Cat->GetDataPath();}
- bool SepIndex(void) {return GetBoolCatInfo("SepIndex", false);}
+ RECFM GetTableFormat(const char* type);
+ bool SepIndex(void) {return GetBoolCatInfo("SepIndex", false);}
bool IsReadOnly(void) {return Read_Only;}
virtual AMT GetDefType(void) {return TYPE_AM_TAB;}
virtual PIXDEF GetIndx(void) {return NULL;}
@@ -108,7 +110,8 @@ public:
// Members
PCSZ Schema; /* Table schema (for ODBC) */
PCSZ Desc; /* Table description */
- uint Catfunc; /* Catalog function ID */
+ RECFM Recfm; /* File or table format */
+ uint Catfunc; /* Catalog function ID */
int Card; /* (max) number of rows in table */
int Elemt; /* Number of rows in blocks or rowset */
int Sort; /* Table already sorted ??? */
diff --git a/storage/connect/restget.cpp b/storage/connect/restget.cpp
index 6b184ae6926..29dae230780 100644
--- a/storage/connect/restget.cpp
+++ b/storage/connect/restget.cpp
@@ -4,12 +4,6 @@
/***********************************************************************/
#include <cpprest/filestream.h>
#include <cpprest/http_client.h>
-#if defined(MARIADB)
-#include <my_global.h>
-#else
-#include "mini-global.h"
-#define _OS_H_INCLUDED // Prevent os.h to be called
-#endif
using namespace utility::conversions; // String conversions utilities
using namespace web; // Common features like URIs.
@@ -17,24 +11,26 @@ using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
-#include "global.h"
+typedef const char* PCSZ;
+
+extern "C" int restGetFile(char* m, bool xt, PCSZ http, PCSZ uri, PCSZ fn);
/***********************************************************************/
/* Make a local copy of the requested file. */
/***********************************************************************/
-int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn)
+int restGetFile(char *m, bool xt, PCSZ http, PCSZ uri, PCSZ fn)
{
int rc = 0;
- bool xt = trace(515);
auto fileStream = std::make_shared<ostream>();
if (!http || !fn) {
- strcpy(g->Message, "Missing http or filename");
- return 2;
+ //strcpy(g->Message, "Missing http or filename");
+ strcpy(m, "Missing http or filename");
+ return 2;
} // endif
if (xt)
- htrc("restGetFile: fn=%s\n", fn);
+ fprintf(stderr, "restGetFile: fn=%s\n", fn);
// Open stream to output file.
pplx::task<void> requestTask = fstream::open_ostream(to_string_t(fn))
@@ -42,7 +38,7 @@ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn)
*fileStream= outFile;
if (xt)
- htrc("Outfile isopen=%d\n", outFile.is_open());
+ fprintf(stderr, "Outfile isopen=%d\n", outFile.is_open());
// Create http_client to send the request.
http_client client(to_string_t(http));
@@ -58,8 +54,8 @@ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn)
// Handle response headers arriving.
.then([=](http_response response) {
if (xt)
- htrc("Received response status code:%u\n",
- response.status_code());
+ fprintf(stderr, "Received response status code:%u\n",
+ response.status_code());
// Write response body into the file.
return response.body().read_to_end(fileStream->streambuf());
@@ -68,27 +64,27 @@ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn)
// Close the file stream.
.then([=](size_t n) {
if (xt)
- htrc("Return size=%u\n", n);
+ fprintf(stderr, "Return size=%zu\n", n);
return fileStream->close();
});
// Wait for all the outstanding I/O to complete and handle any exceptions
try {
- requestTask.wait();
-
if (xt)
- htrc("In Wait\n");
+ fprintf(stderr, "Waiting\n");
+ requestTask.wait();
} catch (const std::exception &e) {
if (xt)
- htrc("Error exception: %s\n", e.what());
- sprintf(g->Message, "Error exception: %s", e.what());
- rc= 1;
+ fprintf(stderr, "Error exception: %s\n", e.what());
+
+ sprintf(m, "Error exception: %s", e.what());
+ rc= 1;
} // end try/catch
if (xt)
- htrc("restget done: rc=%d\n", rc);
+ fprintf(stderr, "restget done: rc=%d\n", rc);
return rc;
} // end of restGetFile
diff --git a/storage/connect/tabcmg.cpp b/storage/connect/tabcmg.cpp
index da1cfd34ac7..b9b7f6e4b60 100644
--- a/storage/connect/tabcmg.cpp
+++ b/storage/connect/tabcmg.cpp
@@ -53,25 +53,30 @@ bool CMGDISC::FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc,
{
if (!doc || bson_iter_init(iter, doc)) {
const char *key;
- char colname[65];
- char fmt[129];
- bool newcol;
+ char colname[65];
+ char fmt[129];
+ bool newcol;
+ size_t n;
while (bson_iter_next(iter)) {
key = bson_iter_key(iter);
newcol = true;
if (pcn) {
- strncpy(colname, pcn, 64);
- colname[64] = 0;
- strncat(strncat(colname, "_", 65), key, 65);
+ n = sizeof(colname) - 1;
+ strncpy(colname, pcn, n);
+ colname[n] = 0;
+ n -= strlen(colname);
+ strncat(strncat(colname, "_", n), key, n - 1);
} else
strcpy(colname, key);
if (pfmt) {
- strncpy(fmt, pfmt, 128);
- fmt[128] = 0;
- strncat(strncat(fmt, ".", 129), key, 129);
+ n = sizeof(fmt) - 1;
+ strncpy(fmt, pfmt, n);
+ fmt[n] = 0;
+ n -= strlen(fmt);
+ strncat(strncat(fmt, ".", n), key, n - 1);
} else
strcpy(fmt, key);
diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp
index 4f6e2c81744..8efe2aad702 100644
--- a/storage/connect/tabdos.cpp
+++ b/storage/connect/tabdos.cpp
@@ -45,7 +45,7 @@
#include "global.h"
#include "osutil.h"
#include "plgdbsem.h"
-#include "catalog.h"
+//#include "catalog.h"
#include "mycat.h"
#include "xindex.h"
#include "filamap.h"
@@ -161,7 +161,12 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
//Last = GetIntCatInfo("Last", 0);
Ending = GetIntCatInfo("Ending", CRLF);
- if (Recfm == RECFM_FIX || Recfm == RECFM_BIN) {
+ if (Ending <= 0) {
+ Ending = (Recfm == RECFM_BIN || Recfm == RECFM_VCT) ? 0 : CRLF;
+ SetIntCatInfo("Ending", Ending);
+ } // endif ending
+
+ if (Recfm == RECFM_FIX || Recfm == RECFM_BIN) {
Huge = GetBoolCatInfo("Huge", Cat->GetDefHuge());
Padded = GetBoolCatInfo("Padded", false);
Blksize = GetIntCatInfo("Blksize", 0);
@@ -191,7 +196,8 @@ bool DOSDEF::GetOptFileName(PGLOBAL g, char *filename)
case RECFM_FIX: ftype = ".fop"; break;
case RECFM_BIN: ftype = ".bop"; break;
case RECFM_VCT: ftype = ".vop"; break;
- case RECFM_DBF: ftype = ".dbp"; break;
+ case RECFM_CSV: ftype = ".cop"; break;
+ case RECFM_DBF: ftype = ".dbp"; break;
default:
sprintf(g->Message, MSG(INVALID_FTYPE), Recfm);
return true;
@@ -261,7 +267,8 @@ bool DOSDEF::DeleteIndexFile(PGLOBAL g, PIXDEF pxdf)
case RECFM_FIX: ftype = ".fnx"; break;
case RECFM_BIN: ftype = ".bnx"; break;
case RECFM_VCT: ftype = ".vnx"; break;
- case RECFM_DBF: ftype = ".dbx"; break;
+ case RECFM_CSV: ftype = ".cnx"; break;
+ case RECFM_DBF: ftype = ".dbx"; break;
default:
sprintf(g->Message, MSG(BAD_RECFM_VAL), Recfm);
return true;
@@ -2257,7 +2264,7 @@ int TDBDOS::ReadDB(PGLOBAL g)
/***********************************************************************/
bool TDBDOS::PrepareWriting(PGLOBAL)
{
- if (!Ftype && (Mode == MODE_INSERT || Txfp->GetUseTemp())) {
+ if (Ftype == RECFM_VAR && (Mode == MODE_INSERT || Txfp->GetUseTemp())) {
char *p;
/*******************************************************************/
@@ -2542,7 +2549,8 @@ void DOSCOL::ReadColumn(PGLOBAL g)
/*********************************************************************/
/* For a variable length file, check if the field exists. */
/*********************************************************************/
- if (tdbp->Ftype == RECFM_VAR && strlen(tdbp->To_Line) < (unsigned)Deplac)
+ if ((tdbp->Ftype == RECFM_VAR || tdbp->Ftype == RECFM_CSV)
+ && strlen(tdbp->To_Line) < (unsigned)Deplac)
field = 0;
else if (Dsp)
for(i = 0; i < field; i++)
@@ -2552,7 +2560,8 @@ void DOSCOL::ReadColumn(PGLOBAL g)
switch (tdbp->Ftype) {
case RECFM_VAR:
case RECFM_FIX: // Fixed length text file
- case RECFM_DBF: // Fixed length DBase file
+ case RECFM_CSV: // Variable length CSV or FMT file
+ case RECFM_DBF: // Fixed length DBase file
if (Nod) switch (Buf_Type) {
case TYPE_INT:
case TYPE_SHORT:
diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h
index bdde37adaad..207a1277fce 100644
--- a/storage/connect/tabdos.h
+++ b/storage/connect/tabdos.h
@@ -80,7 +80,6 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
PCSZ Entry; /* Zip entry name or pattern */
PCSZ Pwd; /* Zip password */
PIXDEF To_Indx; /* To index definitions blocks */
- RECFM Recfm; /* 0:VAR, 1:FIX, 2:BIN, 3:VCT, 6:DBF */
bool Mapped; /* 0: disk file, 1: memory mapped file */
bool Zipped; /* true for zipped table file */
bool Mulentries; /* true for multiple entries */
diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp
index 1969fd4465f..4a0a75460cd 100644
--- a/storage/connect/tabfix.cpp
+++ b/storage/connect/tabfix.cpp
@@ -84,7 +84,7 @@ PTDB TDBFIX::Clone(PTABS t)
tp = new(g) TDBFIX(g, this);
- if (Ftype < 2) {
+ if (Ftype == RECFM_VAR || Ftype == RECFM_FIX) {
// File is text
PDOSCOL cp1, cp2;
diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp
index 746382178fb..b395c49c95d 100644
--- a/storage/connect/tabfmt.cpp
+++ b/storage/connect/tabfmt.cpp
@@ -1,11 +1,11 @@
/************* TabFmt C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABFMT */
/* ------------- */
-/* Version 3.9.2 */
+/* Version 3.9.3 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2001 - 2017 */
+/* (C) Copyright to the author Olivier BERTRAND 2001 - 2019 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -477,6 +477,7 @@ bool CSVDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
if (DOSDEF::DefineAM(g, "CSV", poff))
return true;
+ Recfm = RECFM_CSV;
GetCharCatInfo("Separator", ",", buf, sizeof(buf));
Sep = (strlen(buf) == 2 && buf[0] == '\\' && buf[1] == 't') ? '\t' : *buf;
Quoted = GetIntCatInfo("Quoted", -1);
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index 0b282345c8a..7e8d6c8d9f0 100644
--- a/storage/connect/tabjson.cpp
+++ b/storage/connect/tabjson.cpp
@@ -394,10 +394,11 @@ err:
bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
{
- char *p, *pc = colname + strlen(colname);
- int ars;
- PJOB job;
- PJAR jar;
+ char *p, *pc = colname + strlen(colname);
+ int ars;
+ size_t n;
+ PJOB job;
+ PJAR jar;
if ((valp = jvp ? jvp->GetValue() : NULL)) {
jcol.Type = valp->GetType();
@@ -423,8 +424,10 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
PCSZ k = jrp->GetKey();
if (*k != '$') {
- strncat(strncat(fmt, sep, 128), k, 128);
- strncat(strncat(colname, "_", 64), k, 64);
+ n = sizeof(fmt) - strlen(fmt) -1;
+ strncat(strncat(fmt, sep, n), k, n - strlen(sep));
+ n = sizeof(colname) - strlen(colname) - 1;
+ strncat(strncat(colname, "_", n), k, n - 1);
} // endif Key
if (Find(g, jrp->GetVal(), k, j + 1))
@@ -443,19 +446,26 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
ars = MY_MIN(jar->GetSize(false), 1);
for (int k = 0; k < ars; k++) {
- if (!tdp->Xcol || stricmp(tdp->Xcol, key)) {
- sprintf(buf, "%d", k);
-
- if (tdp->Uri)
- strncat(strncat(fmt, sep, 128), buf, 128);
- else
- strncat(strncat(strncat(fmt, "[", 128), buf, 128), "]", 128);
+ n = sizeof(fmt) - (strlen(fmt) + 1);
- if (all)
- strncat(strncat(colname, "_", 64), buf, 64);
+ if (!tdp->Xcol || stricmp(tdp->Xcol, key)) {
+ sprintf(buf, "%d", k);
- } else
- strncat(fmt, (tdp->Uri ? sep : "[*]"), 128);
+ if (tdp->Uri) {
+ strncat(strncat(fmt, sep, n), buf, n - strlen(sep));
+ } else {
+ strncat(strncat(fmt, "[", n), buf, n - 1);
+ strncat(fmt, "]", n - (strlen(buf) + 1));
+ } // endif uri
+
+ if (all) {
+ n = sizeof(colname) - (strlen(colname) + 1);
+ strncat(strncat(colname, "_", n), buf, n - 1);
+ } // endif all
+
+ } else {
+ strncat(fmt, (tdp->Uri ? sep : "[*]"), n);
+ }
if (Find(g, jar->GetValue(k), "", j))
return true;
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index ceffafac02c..7e165fb5a80 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -342,11 +342,13 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
Delayed = !!GetIntCatInfo("Delayed", 0);
} else {
// MYSQL access from a PROXY table
- Tabschema = GetStringCatInfo(g, "Database", Tabschema ? Tabschema : PlugDup(g, "*"));
+ TABLE_SHARE* s;
+
+ Tabschema = GetStringCatInfo(g, "Database", Tabschema ? Tabschema : PlugDup(g, "*"));
Isview = GetBoolCatInfo("View", false);
// We must get other connection parms from the calling table
- Remove_tshp(Cat);
+ s = Remove_tshp(Cat);
url = GetStringCatInfo(g, "Connect", NULL);
if (!url || !*url) {
@@ -365,6 +367,9 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
} // endif url
Tabname = Name;
+
+ // Needed for column description
+ Restore_tshp(Cat, s);
} // endif am
if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL))) {
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index 0fa117c3d2f..ba5c65e2c94 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -605,8 +605,10 @@ bool TDBODBC::OpenDB(PGLOBAL g)
Cnp->InitValue(g);
if ((n = Ocp->GetResultSize(Query->GetStr(), Cnp)) < 0) {
- strcpy(g->Message, "Cannot get result size");
- return true;
+ char* msg = PlugDup(g, g->Message);
+
+ sprintf(g->Message, "Get result size: %s (rc=%d)", msg, n);
+ return true;
} else if (n) {
Ocp->m_Rows = n;
diff --git a/storage/connect/tabrest.cpp b/storage/connect/tabrest.cpp
index 9e1a643c89f..9c6b724973f 100644
--- a/storage/connect/tabrest.cpp
+++ b/storage/connect/tabrest.cpp
@@ -1,5 +1,5 @@
-/*************** Rest C++ Program Source Code File (.CPP) **************/
-/* PROGRAM NAME: Rest Version 1.5 */
+/************** tabrest C++ Program Source Code File (.CPP) ************/
+/* PROGRAM NAME: tabrest Version 1.7 */
/* (C) Copyright to the author Olivier BERTRAND 2018 - 2019 */
/* This program is the REST Web API support for MariaDB. */
/* When compiled without MARIADB defined, it is the EOM module code. */
@@ -9,13 +9,18 @@
/* Definitions needed by the included files. */
/***********************************************************************/
#if defined(MARIADB)
-#include <my_global.h> // All MariaDB stuff
+#include <my_global.h> // All MariaDB stuff
#else // !MARIADB OEM module
#include "mini-global.h"
#define _MAX_PATH 260
-#if !defined(__WIN__)
+#if !defined(REST_SOURCE)
+#if defined(__WIN__) || defined(_WINDOWS)
+#include <windows.h>
+#else // !__WIN__
#define __stdcall
+#include <dlfcn.h> // dlopen(), dlclose(), dlsym() ...
#endif // !__WIN__
+#endif // !REST_SOURCE
#define _OS_H_INCLUDED // Prevent os.h to be called
#endif // !MARIADB
@@ -23,7 +28,6 @@
/* Include application header files: */
/* global.h is header containing all global declarations. */
/* plgdbsem.h is header containing the DB application declarations. */
-/* (x)table.h is header containing the TDBASE declarations. */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
@@ -31,22 +35,14 @@
#include "filamtxt.h"
#include "tabdos.h"
#include "plgxml.h"
+#if defined(XML_SUPPORT)
#include "tabxml.h"
+#endif // XML_SUPPORT
#include "tabjson.h"
#include "tabfmt.h"
#include "tabrest.h"
-/***********************************************************************/
-/* Get the file from the Web. */
-/***********************************************************************/
-int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn);
-
-#if defined(__WIN__)
-static PCSZ slash = "\\";
-#else // !__WIN__
-static PCSZ slash = "/";
-#define stricmp strcasecmp
-#endif // !__WIN__
+static XGETREST getRestFnc = NULL;
#if !defined(MARIADB)
/***********************************************************************/
@@ -76,6 +72,74 @@ PTABDEF __stdcall GetREST(PGLOBAL g, void *memp)
#endif // !MARIADB
/***********************************************************************/
+/* GetREST: get the external TABDEF from OEM module. */
+/***********************************************************************/
+XGETREST GetRestFunction(PGLOBAL g)
+{
+ if (getRestFnc)
+ return getRestFnc;
+
+#if !defined(MARIADB) || !defined(REST_SOURCE)
+ if (trace(515))
+ htrc("Looking for GetRest library\n");
+
+#if defined(__WIN__) || defined(_WINDOWS)
+ HANDLE Hdll;
+ const char* soname = "GetRest.dll"; // Module name
+
+ if (!(Hdll = LoadLibrary(soname))) {
+ char buf[256];
+ DWORD rc = GetLastError();
+
+ sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname);
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
+ (LPTSTR)buf, sizeof(buf), NULL);
+ strcat(strcat(g->Message, ": "), buf);
+ return NULL;
+ } // endif Hdll
+
+// Get the function returning an instance of the external DEF class
+ if (!(getRestFnc = (XGETREST)GetProcAddress((HINSTANCE)Hdll, "restGetFile"))) {
+ char buf[256];
+ DWORD rc = GetLastError();
+
+ sprintf(g->Message, MSG(PROCADD_ERROR), rc, "restGetFile");
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
+ (LPTSTR)buf, sizeof(buf), NULL);
+ strcat(strcat(g->Message, ": "), buf);
+ FreeLibrary((HMODULE)Hdll);
+ return NULL;
+ } // endif getRestFnc
+#else // !__WIN__
+ void* Hso;
+ const char* error = NULL;
+ const char* soname = "GetRest.so"; // Module name
+
+ // Load the desired shared library
+ if (!(Hso = dlopen(soname, RTLD_LAZY))) {
+ error = dlerror();
+ sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
+ return NULL;
+ } // endif Hdll
+
+// Get the function returning an instance of the external DEF class
+ if (!(getRestFnc = (XGETREST)dlsym(Hso, "restGetFile"))) {
+ error = dlerror();
+ sprintf(g->Message, MSG(GET_FUNC_ERR), "restGetFile", SVP(error));
+ dlclose(Hso);
+ return NULL;
+ } // endif getdef
+#endif // !__WIN__
+#else
+ getRestFnc = restGetFile;
+#endif
+
+ return getRestFnc;
+} // end of GetRestFunction
+
+/***********************************************************************/
/* Return the columns definition to MariaDB. */
/***********************************************************************/
#if defined(MARIADB)
@@ -87,6 +151,10 @@ PQRYRES __stdcall ColREST(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
PQRYRES qrp= NULL;
char filename[_MAX_PATH + 1]; // MAX PATH ???
PCSZ http, uri, fn, ftype;
+ XGETREST grf = GetRestFunction(g);
+
+ if (!grf)
+ return NULL;
http = GetStringTableOption(g, tp, "Http", NULL);
uri = GetStringTableOption(g, tp, "Uri", NULL);
@@ -100,18 +168,20 @@ PQRYRES __stdcall ColREST(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
// We used the file name relative to recorded datapath
strcat(strcat(strcat(strcpy(filename, "."), slash), db), slash);
- strncat(filename, fn, _MAX_PATH);
+ strncat(filename, fn, _MAX_PATH - strlen(filename));
// Retrieve the file from the web and copy it locally
- if (http && restGetFile(g, http, uri, filename)) {
- // sprintf(g->Message, "Failed to get file at %s", http);
- } else if (!stricmp(ftype, "XML"))
- qrp = XMLColumns(g, db, tab, tp, info);
- else if (!stricmp(ftype, "JSON"))
+ if (http && grf(g->Message, trace(515), http, uri, filename)) {
+ // sprintf(g->Message, "Failed to get file at %s", http);
+ } else if (!stricmp(ftype, "JSON"))
qrp = JSONColumns(g, db, NULL, tp, info);
else if (!stricmp(ftype, "CSV"))
qrp = CSVColumns(g, NULL, tp, info);
- else
+#if defined(XML_SUPPORT)
+ else if (!stricmp(ftype, "XML"))
+ qrp = XMLColumns(g, db, tab, tp, info);
+#endif // XML_SUPPORT
+ else
sprintf(g->Message, "Usupported file type %s", ftype);
return qrp;
@@ -124,9 +194,14 @@ PQRYRES __stdcall ColREST(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
/***********************************************************************/
bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
- char filename[_MAX_PATH + 1];
+ char filename[_MAX_PATH + 1];
int rc = 0, n;
- LPCSTR ftype;
+ bool xt = trace(515);
+ LPCSTR ftype;
+ XGETREST grf = GetRestFunction(g);
+
+ if (!grf)
+ return true;
#if defined(MARIADB)
ftype = GetStringCatInfo(g, "Type", "JSON");
@@ -135,11 +210,13 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
ftype = GetStringCatInfo(g, "Ftype", "JSON");
#endif // !MARIADB
- if (trace(515))
+ if (xt)
htrc("ftype = %s am = %s\n", ftype, SVP(am));
n = (!stricmp(ftype, "JSON")) ? 1
+#if defined(XML_SUPPORT)
: (!stricmp(ftype, "XML")) ? 2
+#endif // XML_SUPPORT
: (!stricmp(ftype, "CSV")) ? 3 : 0;
if (n == 0) {
@@ -154,19 +231,22 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
// We used the file name relative to recorded datapath
//PlugSetPath(filename, Fn, GetPath());
- strncat(strcpy(filename, GetPath()), Fn, _MAX_PATH);
+ strcpy(filename, GetPath());
+ strncat(filename, Fn, _MAX_PATH - strlen(filename));
// Retrieve the file from the web and copy it locally
- rc = restGetFile(g, Http, Uri, filename);
+ rc = grf(g->Message, xt, Http, Uri, filename);
- if (trace(515))
+ if (xt)
htrc("Return from restGetFile: rc=%d\n", rc);
if (rc)
return true;
else switch (n) {
case 1: Tdp = new (g) JSONDEF; break;
- case 2: Tdp = new (g) XMLDEF; break;
+#if defined(XML_SUPPORT)
+ case 2: Tdp = new (g) XMLDEF; break;
+#endif // XML_SUPPORT
case 3: Tdp = new (g) CSVDEF; break;
default: Tdp = NULL;
} // endswitch n
@@ -175,7 +255,7 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
if (Tdp && Tdp->Define(g, Cat, Name, Schema, "REST"))
Tdp = NULL; // Error occured
- if (trace(515))
+ if (xt)
htrc("Tdp defined\n", rc);
// Return true in case of error
diff --git a/storage/connect/tabrest.h b/storage/connect/tabrest.h
index 1725f256079..9cf2d10a6b8 100644
--- a/storage/connect/tabrest.h
+++ b/storage/connect/tabrest.h
@@ -5,6 +5,27 @@
/***********************************************************************/
#pragma once
+#if defined(__WIN__)
+static PCSZ slash = "\\";
+#else // !__WIN__
+static PCSZ slash = "/";
+#define stricmp strcasecmp
+#endif // !__WIN__
+
+typedef int(__stdcall* XGETREST) (char*, bool, PCSZ, PCSZ, PCSZ);
+
+/***********************************************************************/
+/* Functions used by REST. */
+/***********************************************************************/
+XGETREST GetRestFunction(PGLOBAL g);
+#if defined(REST_SOURCE)
+extern "C" int restGetFile(char* m, bool xt, PCSZ http, PCSZ uri, PCSZ fn);
+#endif // REST_SOURCE
+#if defined(MARIADB)
+PQRYRES RESTColumns(PGLOBAL g, PTOS tp, char* tab, char* db, bool info);
+#endif // !MARIADB
+
+
/***********************************************************************/
/* Restest table. */
/***********************************************************************/
diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp
index 462a6fcd839..e187e6eaec5 100644
--- a/storage/connect/tabutil.cpp
+++ b/storage/connect/tabutil.cpp
@@ -59,12 +59,24 @@ int GetConvSize(void);
/* 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)
+TABLE_SHARE *Remove_tshp(PCATLG cat)
{
- ((MYCAT*)cat)->GetHandler()->tshp = NULL;
+ TABLE_SHARE *s = ((MYCAT*)cat)->GetHandler()->tshp;
+
+ ((MYCAT*)cat)->GetHandler()->tshp = NULL;
+ return s;
} // end of Remove_thsp
/************************************************************************/
+/* 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 Restore_tshp(PCATLG cat, TABLE_SHARE *s)
+{
+ ((MYCAT*)cat)->GetHandler()->tshp = s;
+} // end of Restore_thsp
+
+/************************************************************************/
/* GetTableShare: allocates and open a table share. */
/************************************************************************/
TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h
index 62678508ca1..c8e7e75106f 100644
--- a/storage/connect/tabutil.h
+++ b/storage/connect/tabutil.h
@@ -18,7 +18,8 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
const char *name, bool& info);
-void Remove_tshp(PCATLG cat);
+TABLE_SHARE *Remove_tshp(PCATLG cat);
+void Restore_tshp(PCATLG cat, TABLE_SHARE *s);
/* -------------------------- PROXY classes -------------------------- */
diff --git a/storage/connect/tabvct.cpp b/storage/connect/tabvct.cpp
index 40d020202ea..0ed466f6ffb 100644
--- a/storage/connect/tabvct.cpp
+++ b/storage/connect/tabvct.cpp
@@ -115,11 +115,14 @@ bool VCTDEF::DefineAM(PGLOBAL g, LPCSTR, int poff)
Recfm = RECFM_VCT;
+ // poff is no more in use; This will have to be revisited
+#if 0
// For packed files the logical record length is calculated in poff
if (poff != Lrecl) {
Lrecl = poff;
SetIntCatInfo("Lrecl", poff);
} // endif poff
+#endif // 0
Padded = false;
Blksize = 0;
diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp
index 19490d350e8..717090e9c5a 100644
--- a/storage/connect/tabxml.cpp
+++ b/storage/connect/tabxml.cpp
@@ -240,7 +240,9 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
more:
if (vp->atp) {
- strncpy(colname, vp->atp->GetName(g), sizeof(colname));
+ size_t z = sizeof(colname) - 1;
+ strncpy(colname, vp->atp->GetName(g), z);
+ colname[z] = 0;
strncat(xcol->Name, colname, XLEN(xcol->Name));
switch (vp->atp->GetText(g, buf, sizeof(buf))) {
diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp
index 5179fa654cf..b7c8c704e65 100644
--- a/storage/connect/valblk.cpp
+++ b/storage/connect/valblk.cpp
@@ -206,6 +206,7 @@ void VALBLK::ChkIndx(int n)
{
if (n < 0 || n >= Nval) {
PGLOBAL& g = Global;
+ xtrc(1, "ChkIndx: n=%d Nval=%d\n", n, Nval);
strcpy(g->Message, MSG(BAD_VALBLK_INDX));
throw Type;
} // endif n
@@ -216,7 +217,8 @@ void VALBLK::ChkTyp(PVAL v)
{
if (Check && (Type != v->GetType() || Unsigned != v->IsUnsigned())) {
PGLOBAL& g = Global;
- strcpy(g->Message, MSG(VALTYPE_NOMATCH));
+ xtrc(1, "ChkTyp: Type=%d valType=%d\n", Type, v->GetType());
+ strcpy(g->Message, MSG(VALTYPE_NOMATCH));
throw Type;
} // endif Type
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index d9330a68a15..df75722d0e8 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -123,7 +123,7 @@ ulonglong CharToNumber(const char *p, int n, ulonglong maxval,
case '+':
p++;
break;
- } // endswitch *p
+ } // endswitch *p
for (val = 0; p < p2 && (c = (uchar)(*p - '0')) < 10; p++)
if (val > (maxval - c) / 10) {
@@ -140,7 +140,7 @@ ulonglong CharToNumber(const char *p, int n, ulonglong maxval,
/* GetTypeName: returns the PlugDB internal type name. */
/***********************************************************************/
PCSZ GetTypeName(int type)
- {
+{
PCSZ name;
switch (type) {
@@ -155,17 +155,17 @@ PCSZ GetTypeName(int type)
case TYPE_BIN: name = "BINARY"; break;
case TYPE_PCHAR: name = "PCHAR"; break;
default: name = "UNKNOWN"; break;
- } // endswitch type
+ } // endswitch type
return name;
- } // end of GetTypeName
+} // end of GetTypeName
/***********************************************************************/
/* GetTypeSize: returns the PlugDB internal type size. */
/***********************************************************************/
int GetTypeSize(int type, int len)
{
- switch (type) {
+ switch (type) {
case TYPE_DECIM:
case TYPE_BIN:
case TYPE_STRING: len = len * sizeof(char); break;
@@ -177,16 +177,16 @@ int GetTypeSize(int type, int len)
case TYPE_TINY: len = sizeof(char); break;
case TYPE_PCHAR: len = sizeof(char*); break;
default: len = -1;
- } // endswitch type
+ } // endswitch type
return len;
- } // end of GetTypeSize
+} // end of GetTypeSize
/***********************************************************************/
/* GetFormatType: returns the FORMAT character(s) according to type. */
/***********************************************************************/
const char *GetFormatType(int type)
- {
+{
const char *c = "X";
switch (type) {
@@ -200,16 +200,16 @@ const char *GetFormatType(int type)
case TYPE_DECIM: c = "M"; break;
case TYPE_BIN: c = "B"; break;
case TYPE_PCHAR: c = "P"; break;
- } // endswitch type
+ } // endswitch type
return c;
- } // end of GetFormatType
+} // end of GetFormatType
/***********************************************************************/
/* GetFormatType: returns the FORMAT type according to character. */
/***********************************************************************/
int GetFormatType(char c)
- {
+{
int type = TYPE_ERROR;
switch (c) {
@@ -223,31 +223,31 @@ int GetFormatType(char c)
case 'M': type = TYPE_DECIM; break;
case 'B': type = TYPE_BIN; break;
case 'P': type = TYPE_PCHAR; break;
- } // endswitch type
+ } // endswitch type
return type;
- } // end of GetFormatType
+} // end of GetFormatType
/***********************************************************************/
/* IsTypeChar: returns true for character type(s). */
/***********************************************************************/
bool IsTypeChar(int type)
- {
+{
switch (type) {
case TYPE_STRING:
case TYPE_DECIM:
case TYPE_BIN:
return true;
- } // endswitch type
+ } // endswitch type
return false;
- } // end of IsTypeChar
+} // end of IsTypeChar
/***********************************************************************/
/* IsTypeNum: returns true for numeric types. */
/***********************************************************************/
bool IsTypeNum(int type)
- {
+{
switch (type) {
case TYPE_INT:
case TYPE_BIGINT:
@@ -258,16 +258,16 @@ bool IsTypeNum(int type)
case TYPE_TINY:
case TYPE_DECIM:
return true;
- } // endswitch type
+ } // endswitch type
return false;
- } // end of IsTypeNum
+} // end of IsTypeNum
/***********************************************************************/
/* GetFmt: returns the format to use with a typed value. */
/***********************************************************************/
const char *GetFmt(int type, bool un)
- {
+{
const char *fmt;
switch (type) {
@@ -278,10 +278,10 @@ const char *GetFmt(int type, bool un)
case TYPE_DOUBLE: fmt = "%.*lf"; break;
case TYPE_BIN: fmt = "%*x"; break;
default: fmt = (un) ? "%u" : "%d"; break;
- } // endswitch Type
+ } // endswitch Type
return fmt;
- } // end of GetFmt
+} // end of GetFmt
/***********************************************************************/
/* ConvertType: what this function does is to determine the type to */
@@ -293,7 +293,7 @@ const char *GetFmt(int type, bool un)
/* IsType... functions so match does not prevent correct setting. */
/***********************************************************************/
int ConvertType(int target, int type, CONV kind, bool match)
- {
+{
switch (kind) {
case CNV_CHAR:
if (match && (!IsTypeChar(target) || !IsTypeChar(type)))
@@ -326,15 +326,15 @@ int ConvertType(int target, int type, CONV kind, bool match)
: (target == TYPE_STRING || type == TYPE_STRING) ? TYPE_STRING
: (target == TYPE_TINY || type == TYPE_TINY) ? TYPE_TINY
: TYPE_ERROR;
- } // endswitch kind
+ } // endswitch kind
- } // end of ConvertType
+} // end of ConvertType
/***********************************************************************/
/* AllocateConstant: allocates a constant Value. */
/***********************************************************************/
PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec)
- {
+{
PVAL valp;
if (trace(1))
@@ -362,18 +362,18 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec)
default:
sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
return NULL;
- } // endswitch Type
+ } // endswitch Type
valp->SetGlobal(g);
return valp;
- } // end of AllocateValue
+} // end of AllocateValue
/***********************************************************************/
/* Allocate a variable Value according to type, length and precision. */
/***********************************************************************/
PVAL AllocateValue(PGLOBAL g, int type, int len, int prec,
bool uns, PCSZ fmt)
- {
+{
PVAL valp;
switch (type) {
@@ -423,18 +423,18 @@ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec,
default:
sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
return NULL;
- } // endswitch type
+ } // endswitch type
valp->SetGlobal(g);
return valp;
- } // end of AllocateValue
+} // end of AllocateValue
/***********************************************************************/
/* Allocate a constant Value converted to newtype. */
/* Can also be used to copy a Value eventually converted. */
/***********************************************************************/
PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
- {
+{
PSZ p, sp;
bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned();
PVAL vp;
@@ -495,13 +495,13 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
default:
sprintf(g->Message, MSG(BAD_VALUE_TYPE), newtype);
return NULL;
- } // endswitch type
+ } // endswitch type
vp->SetNullable(valp->GetNullable());
vp->SetNull(valp->IsNull());
vp->SetGlobal(g);
return vp;
- } // end of AllocateValue
+} // end of AllocateValue
/* -------------------------- Class VALUE ---------------------------- */
@@ -509,7 +509,7 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
/* Class VALUE protected constructor. */
/***********************************************************************/
VALUE::VALUE(int type, bool un) : Type(type)
- {
+{
Null = false;
Nullable = false;
Unsigned = un;
@@ -517,13 +517,13 @@ VALUE::VALUE(int type, bool un) : Type(type)
Prec = 0;
Fmt = GetFmt(Type, Unsigned);
Xfmt = GetXfmt();
- } // end of VALUE constructor
+} // end of VALUE constructor
/***********************************************************************/
/* VALUE GetXfmt: returns the extended format to use with typed value. */
/***********************************************************************/
const char *VALUE::GetXfmt(void)
- {
+{
const char *fmt;
switch (Type) {
@@ -537,7 +537,7 @@ const char *VALUE::GetXfmt(void)
} // endswitch Type
return fmt;
- } // end of GetFmt
+} // end of GetXFmt
/***********************************************************************/
/* Returns a BYTE indicating the comparison between two values. */
@@ -545,20 +545,20 @@ const char *VALUE::GetXfmt(void)
/* More than 1 bit can be set only in the case of TYPE_LIST. */
/***********************************************************************/
BYTE VALUE::TestValue(PVAL vp)
- {
+{
int n = CompareValue(vp);
return (n > 0) ? 0x04 : (n < 0) ? 0x02 : 0x01;
- } // end of TestValue
+} // end of TestValue
/***********************************************************************/
/* Compute a function on a string. */
/***********************************************************************/
bool VALUE::Compute(PGLOBAL g, PVAL *, int, OPVAL)
- {
+{
strcpy(g->Message, "Compute not implemented for this value type");
return true;
- } // end of Compute
+} // end of Compute
/***********************************************************************/
/* Make file output of an object value. */
@@ -600,11 +600,11 @@ void VALUE::Prints(PGLOBAL g, char *ps, uint z)
template <class TYPE>
TYPVAL<TYPE>::TYPVAL(TYPE n, int type, int prec, bool un)
: VALUE(type, un)
- {
+{
Tval = n;
Clen = sizeof(TYPE);
Prec = prec;
- } // end of TYPVAL constructor
+} // end of TYPVAL constructor
/***********************************************************************/
/* Return unsigned max value for the type. */
@@ -641,19 +641,19 @@ ulonglong TYPVAL<ulonglong>::MaxVal(void) {return ULONGLONG_MAX;}
/***********************************************************************/
template <class TYPE>
int TYPVAL<TYPE>::GetValLen(void)
- {
+{
char c[32];
- return sprintf(c, Fmt, Tval);
- } // end of GetValLen
+ return snprintf(c, 32, Fmt, Tval);
+} // end of GetValLen
template <>
int TYPVAL<double>::GetValLen(void)
- {
+{
char c[32];
- return sprintf(c, Fmt, Prec, Tval);
- } // end of GetValLen
+ return snprintf(c, 32, Fmt, Prec, Tval);
+} // end of GetValLen
/***********************************************************************/
/* TYPVAL SetValue: copy the value of another Value object. */
@@ -661,7 +661,7 @@ int TYPVAL<double>::GetValLen(void)
/***********************************************************************/
template <class TYPE>
bool TYPVAL<TYPE>::SetValue_pval(PVAL valp, bool chktype)
- {
+{
if (valp != this) {
if (chktype && Type != valp->GetType())
return true;
@@ -671,10 +671,10 @@ bool TYPVAL<TYPE>::SetValue_pval(PVAL valp, bool chktype)
else
Reset();
- } // endif valp
+ } // endif valp
return false;
- } // end of SetValue
+} // end of SetValue
template <>
short TYPVAL<short>::GetTypedValue(PVAL valp)
@@ -717,7 +717,7 @@ uchar TYPVAL<uchar>::GetTypedValue(PVAL valp)
/***********************************************************************/
template <class TYPE>
bool TYPVAL<TYPE>::SetValue_char(const char *p, int n)
- {
+{
bool rc, minus;
ulonglong maxval = MaxVal();
ulonglong val = CharToNumber(p, n, maxval, Unsigned, &minus, &rc);
@@ -731,15 +731,15 @@ bool TYPVAL<TYPE>::SetValue_char(const char *p, int n)
char buf[64];
htrc(strcat(strcat(strcpy(buf, " setting %s to: "), Fmt), "\n"),
GetTypeName(Type), Tval);
- } // endif trace
+ } // endif trace
Null = false;
return rc;
- } // end of SetValue
+} // end of SetValue
template <>
bool TYPVAL<double>::SetValue_char(const char *p, int n)
- {
+{
if (p && n > 0) {
char buf[64];
@@ -760,14 +760,14 @@ bool TYPVAL<double>::SetValue_char(const char *p, int n)
} // endif p
return false;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* TYPVAL SetValue: fill a typed value from a string. */
/***********************************************************************/
template <class TYPE>
void TYPVAL<TYPE>::SetValue_psz(PCSZ s)
- {
+{
if (s) {
SetValue_char(s, (int)strlen(s));
Null = false;
@@ -776,17 +776,17 @@ void TYPVAL<TYPE>::SetValue_psz(PCSZ s)
Null = Nullable;
} // endif p
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* TYPVAL SetValue: set value with a TYPE extracted from a block. */
/***********************************************************************/
template <class TYPE>
void TYPVAL<TYPE>::SetValue_pvblk(PVBLK blk, int n)
- {
+{
Tval = GetTypedValue(blk, n);
Null = false;
- } // end of SetValue
+} // end of SetValue
template <>
int TYPVAL<int>::GetTypedValue(PVBLK blk, int n)
@@ -852,7 +852,7 @@ void TYPVAL<TYPE>::SetBinValue(void *p)
/***********************************************************************/
template <class TYPE>
bool TYPVAL<TYPE>::GetBinValue(void *buf, int buflen, bool go)
- {
+{
// Test on length was removed here until a variable in column give the
// real field length. For BIN files the field length logically cannot
// be different from the variable length because no conversion is done.
@@ -876,40 +876,41 @@ bool TYPVAL<TYPE>::GetBinValue(void *buf, int buflen, bool go)
Null = false;
return false;
- } // end of GetBinValue
+} // end of GetBinValue
/***********************************************************************/
/* TYPVAL ShowValue: get string representation of a typed value. */
/***********************************************************************/
template <class TYPE>
int TYPVAL<TYPE>::ShowValue(char *buf, int len)
- {
+{
return snprintf(buf, len + 1, Xfmt, len, Tval);
- } // end of ShowValue
+} // end of ShowValue
template <>
int TYPVAL<double>::ShowValue(char *buf, int len)
- {
+{
// TODO: use a more appropriate format to avoid possible truncation
return snprintf(buf, len + 1, Xfmt, len, Prec, Tval);
- } // end of ShowValue
+} // end of ShowValue
/***********************************************************************/
/* TYPVAL GetCharString: get string representation of a typed value. */
/***********************************************************************/
template <class TYPE>
char *TYPVAL<TYPE>::GetCharString(char *p)
- {
+{
sprintf(p, Fmt, Tval);
return p;
- } // end of GetCharString
+} // end of GetCharString
template <>
char *TYPVAL<double>::GetCharString(char *p)
- {
- sprintf(p, Fmt, Prec, Tval);
+{
+ // Most callers use a 32 long buffer
+ snprintf(p, 32, Fmt, Prec, Tval);
return p;
- } // end of GetCharString
+} // end of GetCharString
#if 0
/***********************************************************************/
@@ -917,50 +918,50 @@ char *TYPVAL<double>::GetCharString(char *p)
/***********************************************************************/
template <class TYPE>
char *TYPVAL<TYPE>::GetShortString(char *p, int n)
- {
+{
sprintf(p, "%*hd", n, (short)Tval);
return p;
- } // end of GetShortString
+} // end of GetShortString
/***********************************************************************/
/* TYPVAL GetIntString: get int representation of a typed value. */
/***********************************************************************/
template <class TYPE>
char *TYPVAL<TYPE>::GetIntString(char *p, int n)
- {
+{
sprintf(p, "%*d", n, (int)Tval);
return p;
- } // end of GetIntString
+} // end of GetIntString
/***********************************************************************/
/* TYPVAL GetBigintString: get big int representation of a TYPE value.*/
/***********************************************************************/
template <class TYPE>
char *TYPVAL<TYPE>::GetBigintString(char *p, int n)
- {
+{
sprintf(p, "%*lld", n, (longlong)Tval);
return p;
- } // end of GetBigintString
+} // end of GetBigintString
/***********************************************************************/
/* TYPVAL GetFloatString: get double representation of a typed value. */
/***********************************************************************/
template <class TYPE>
char *TYPVAL<TYPE>::GetFloatString(char *p, int n, int prec)
- {
+{
sprintf(p, "%*.*lf", n, (prec < 0) ? 2 : prec, (double)Tval);
return p;
- } // end of GetFloatString
+} // end of GetFloatString
/***********************************************************************/
/* TYPVAL GetTinyString: get char representation of a typed value. */
/***********************************************************************/
template <class TYPE>
char *TYPVAL<TYPE>::GetTinyString(char *p, int n)
- {
+{
sprintf(p, "%*d", n, (int)(char)Tval);
return p;
- } // end of GetIntString
+} // end of GetIntString
#endif // 0
/***********************************************************************/
@@ -968,7 +969,7 @@ char *TYPVAL<TYPE>::GetTinyString(char *p, int n)
/***********************************************************************/
template <class TYPE>
bool TYPVAL<TYPE>::IsEqual(PVAL vp, bool chktype)
- {
+{
if (this == vp)
return true;
else if (chktype && Type != vp->GetType())
@@ -980,7 +981,7 @@ bool TYPVAL<TYPE>::IsEqual(PVAL vp, bool chktype)
else
return (Tval == GetTypedValue(vp));
- } // end of IsEqual
+} // end of IsEqual
/***********************************************************************/
/* Compare values and returns 1, 0 or -1 according to comparison. */
@@ -988,7 +989,7 @@ bool TYPVAL<TYPE>::IsEqual(PVAL vp, bool chktype)
/***********************************************************************/
template <class TYPE>
int TYPVAL<TYPE>::CompareValue(PVAL vp)
- {
+{
//assert(vp->GetType() == Type);
// Process filtering on numeric values.
@@ -998,7 +999,7 @@ int TYPVAL<TYPE>::CompareValue(PVAL vp)
// htrc(" Comparing: val=%d,%d\n", Tval, n);
return (Tval > n) ? 1 : (Tval < n) ? (-1) : 0;
- } // end of CompareValue
+} // end of CompareValue
/***********************************************************************/
/* Return max type value if b is true, else min type value. */
@@ -1044,7 +1045,7 @@ uchar TYPVAL<uchar>::MinMaxVal(bool b)
/***********************************************************************/
template <class TYPE>
TYPE TYPVAL<TYPE>::SafeAdd(TYPE n1, TYPE n2)
- {
+{
PGLOBAL& g = Global;
TYPE n = n1 + n2;
@@ -1059,20 +1060,20 @@ TYPE TYPVAL<TYPE>::SafeAdd(TYPE n1, TYPE n2)
} // endif's n2
return n;
- } // end of SafeAdd
+} // end of SafeAdd
template <>
inline double TYPVAL<double>::SafeAdd(double n1, double n2)
- {
+{
return n1 + n2;
- } // end of SafeAdd
+} // end of SafeAdd
/***********************************************************************/
/* SafeMult: multiply values and test whether overflow occurred. */
/***********************************************************************/
template <class TYPE>
TYPE TYPVAL<TYPE>::SafeMult(TYPE n1, TYPE n2)
- {
+{
PGLOBAL& g = Global;
double n = (double)n1 * (double)n2;
@@ -1087,20 +1088,20 @@ TYPE TYPVAL<TYPE>::SafeMult(TYPE n1, TYPE n2)
} // endif's n2
return (TYPE)n;
- } // end of SafeMult
+} // end of SafeMult
template <>
inline double TYPVAL<double>::SafeMult(double n1, double n2)
- {
+{
return n1 * n2;
- } // end of SafeMult
+} // end of SafeMult
/***********************************************************************/
/* Compute defined functions for the type. */
/***********************************************************************/
template <class TYPE>
bool TYPVAL<TYPE>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
- {
+{
bool rc = false;
TYPE val[2];
@@ -1127,14 +1128,14 @@ bool TYPVAL<TYPE>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
default:
rc = Compall(g, vp, np, op);
break;
- } // endswitch op
+ } // endswitch op
return rc;
- } // end of Compute
+} // end of Compute
template <>
bool TYPVAL<double>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
- {
+{
bool rc = false;
double val[2];
@@ -1152,17 +1153,17 @@ bool TYPVAL<double>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
break;
default:
rc = Compall(g, vp, np, op);
- } // endswitch op
+ } // endswitch op
return rc;
- } // end of Compute
+} // end of Compute
/***********************************************************************/
/* Compute a function for all types. */
/***********************************************************************/
template <class TYPE>
bool TYPVAL<TYPE>::Compall(PGLOBAL g, PVAL *vp, int np, OPVAL op)
- {
+{
TYPE val[2];
for (int i = 0; i < np; i++)
@@ -1191,10 +1192,10 @@ bool TYPVAL<TYPE>::Compall(PGLOBAL g, PVAL *vp, int np, OPVAL op)
// sprintf(g->Message, MSG(BAD_EXP_OPER), op);
strcpy(g->Message, "Function not supported");
return true;
- } // endswitch op
+ } // endswitch op
return false;
- } // end of Compall
+} // end of Compall
/***********************************************************************/
/* FormatValue: This function set vp (a STRING value) to the string */
@@ -1203,26 +1204,28 @@ bool TYPVAL<TYPE>::Compall(PGLOBAL g, PVAL *vp, int np, OPVAL op)
/***********************************************************************/
template <class TYPE>
bool TYPVAL<TYPE>::FormatValue(PVAL vp, PCSZ fmt)
- {
- char *buf = (char*)vp->GetTo_Val(); // Should be big enough
+{
+ // This function is wrong and should never be called
+ assert(false);
+ char *buf = (char*)vp->GetTo_Val(); // Not big enough
int n = sprintf(buf, fmt, Tval);
return (n > vp->GetValLen());
- } // end of FormatValue
+} // end of FormatValue
/***********************************************************************/
/* TYPVAL SetFormat function (used to set SELECT output format). */
/***********************************************************************/
template <class TYPE>
bool TYPVAL<TYPE>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
- {
+{
char c[32];
fmt.Type[0] = *GetFormatType(Type);
fmt.Length = sprintf(c, Fmt, Tval);
fmt.Prec = Prec;
return false;
- } // end of SetConstFormat
+} // end of SetConstFormat
/* -------------------------- Class STRING --------------------------- */
@@ -1230,19 +1233,19 @@ bool TYPVAL<TYPE>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
/* STRING public constructor from a constant string. */
/***********************************************************************/
TYPVAL<PSZ>::TYPVAL(PSZ s, short c) : VALUE(TYPE_STRING)
- {
+{
Strp = s;
Len = strlen(s);
Clen = Len;
Ci = (c == 1);
- } // end of STRING constructor
+} // end of STRING constructor
/***********************************************************************/
/* STRING public constructor from char. */
/***********************************************************************/
TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
: VALUE(TYPE_STRING)
- {
+{
Len = (g) ? n : (s) ? strlen(s) : 0;
if (!s) {
@@ -1260,89 +1263,89 @@ TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
Clen = Len;
Ci = (c != 0);
- } // end of STRING constructor
+} // end of STRING constructor
/***********************************************************************/
/* Get the tiny value represented by the Strp string. */
/***********************************************************************/
char TYPVAL<PSZ>::GetTinyValue(void)
- {
+{
bool m;
ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX8, false, &m);
return (m && val < INT_MAX8) ? (char)(-(signed)val) : (char)val;
- } // end of GetTinyValue
+} // end of GetTinyValue
/***********************************************************************/
/* Get the unsigned tiny value represented by the Strp string. */
/***********************************************************************/
uchar TYPVAL<PSZ>::GetUTinyValue(void)
- {
+{
return (uchar)CharToNumber(Strp, strlen(Strp), UINT_MAX8, true);
- } // end of GetUTinyValue
+} // end of GetUTinyValue
/***********************************************************************/
/* Get the short value represented by the Strp string. */
/***********************************************************************/
short TYPVAL<PSZ>::GetShortValue(void)
- {
+{
bool m;
ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX16, false, &m);
return (m && val < INT_MAX16) ? (short)(-(signed)val) : (short)val;
- } // end of GetShortValue
+} // end of GetShortValue
/***********************************************************************/
/* Get the unsigned short value represented by the Strp string. */
/***********************************************************************/
ushort TYPVAL<PSZ>::GetUShortValue(void)
- {
+{
return (ushort)CharToNumber(Strp, strlen(Strp), UINT_MAX16, true);
- } // end of GetUshortValue
+} // end of GetUshortValue
/***********************************************************************/
/* Get the integer value represented by the Strp string. */
/***********************************************************************/
int TYPVAL<PSZ>::GetIntValue(void)
- {
+{
bool m;
ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX32, false, &m);
return (m && val < INT_MAX32) ? (int)(-(signed)val) : (int)val;
- } // end of GetIntValue
+} // end of GetIntValue
/***********************************************************************/
/* Get the unsigned integer value represented by the Strp string. */
/***********************************************************************/
uint TYPVAL<PSZ>::GetUIntValue(void)
- {
+{
return (uint)CharToNumber(Strp, strlen(Strp), UINT_MAX32, true);
- } // end of GetUintValue
+} // end of GetUintValue
/***********************************************************************/
/* Get the big integer value represented by the Strp string. */
/***********************************************************************/
longlong TYPVAL<PSZ>::GetBigintValue(void)
- {
+{
bool m;
ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX64, false, &m);
return (m && val < INT_MAX64) ? (-(signed)val) : (longlong)val;
- } // end of GetBigintValue
+} // end of GetBigintValue
/***********************************************************************/
/* Get the unsigned big integer value represented by the Strp string. */
/***********************************************************************/
ulonglong TYPVAL<PSZ>::GetUBigintValue(void)
- {
+{
return CharToNumber(Strp, strlen(Strp), ULONGLONG_MAX, true);
- } // end of GetUBigintValue
+} // end of GetUBigintValue
/***********************************************************************/
/* STRING SetValue: copy the value of another Value object. */
/***********************************************************************/
bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype)
- {
+{
if (valp != this) {
if (chktype && (valp->GetType() != Type || valp->GetSize() > Len))
return true;
@@ -1354,16 +1357,16 @@ bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype)
else
Reset();
- } // endif valp
+ } // endif valp
return false;
- } // end of SetValue_pval
+} // end of SetValue_pval
/***********************************************************************/
/* STRING SetValue: fill string with chars extracted from a line. */
/***********************************************************************/
bool TYPVAL<PSZ>::SetValue_char(const char *cp, int n)
- {
+{
bool rc = false;
if (!cp || n == 0) {
@@ -1389,16 +1392,16 @@ bool TYPVAL<PSZ>::SetValue_char(const char *cp, int n)
Reset();
Null = false;
- } // endif p
+ } // endif cp
return rc;
- } // end of SetValue_char
+} // end of SetValue_char
/***********************************************************************/
/* STRING SetValue: fill string with another string. */
/***********************************************************************/
void TYPVAL<PSZ>::SetValue_psz(PCSZ s)
- {
+{
if (!s) {
Reset();
Null = Nullable;
@@ -1407,26 +1410,26 @@ void TYPVAL<PSZ>::SetValue_psz(PCSZ s)
Null = false;
} // endif s
- } // end of SetValue_psz
+} // end of SetValue_psz
/***********************************************************************/
/* STRING SetValue: fill string with a string extracted from a block. */
/***********************************************************************/
void TYPVAL<PSZ>::SetValue_pvblk(PVBLK blk, int n)
- {
+{
// STRBLK's can return a NULL pointer
PSZ vp = blk->GetCharString(Strp, n);
if (vp != Strp)
SetValue_psz(vp);
- } // end of SetValue_pvblk
+} // end of SetValue_pvblk
/***********************************************************************/
/* STRING SetValue: get the character representation of an integer. */
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(int n)
- {
+{
char buf[16];
PGLOBAL& g = Global;
int k = sprintf(buf, "%d", n);
@@ -1438,13 +1441,13 @@ void TYPVAL<PSZ>::SetValue(int n)
SetValue_psz(buf);
Null = false;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* STRING SetValue: get the character representation of an uint. */
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(uint n)
- {
+{
char buf[16];
PGLOBAL& g = Global;
int k = sprintf(buf, "%u", n);
@@ -1456,31 +1459,31 @@ void TYPVAL<PSZ>::SetValue(uint n)
SetValue_psz(buf);
Null = false;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* STRING SetValue: get the character representation of a short int. */
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(short i)
- {
+{
SetValue((int)i);
Null = false;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* STRING SetValue: get the character representation of a ushort int. */
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(ushort i)
- {
+{
SetValue((uint)i);
Null = false;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* STRING SetValue: get the character representation of a big integer.*/
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(longlong n)
- {
+{
char buf[24];
PGLOBAL& g = Global;
int k = sprintf(buf, "%lld", n);
@@ -1492,13 +1495,13 @@ void TYPVAL<PSZ>::SetValue(longlong n)
SetValue_psz(buf);
Null = false;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* STRING SetValue: get the character representation of a big integer.*/
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(ulonglong n)
- {
+{
char buf[24];
PGLOBAL& g = Global;
int k = sprintf(buf, "%llu", n);
@@ -1510,13 +1513,13 @@ void TYPVAL<PSZ>::SetValue(ulonglong n)
SetValue_psz(buf);
Null = false;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* STRING SetValue: get the character representation of a double. */
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(double f)
- {
+{
char *p, buf[64];
PGLOBAL& g = Global;
int k = sprintf(buf, "%lf", f);
@@ -1535,33 +1538,33 @@ void TYPVAL<PSZ>::SetValue(double f)
SetValue_psz(buf);
Null = false;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* STRING SetValue: get the character representation of a tiny int. */
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(char c)
- {
+{
SetValue((int)c);
Null = false;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* STRING SetValue: get the character representation of a tiny int. */
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(uchar c)
- {
+{
SetValue((uint)c);
Null = false;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* STRING SetBinValue: fill string with chars extracted from a line. */
/***********************************************************************/
void TYPVAL<PSZ>::SetBinValue(void *p)
- {
+{
SetValue_char((const char *)p, Len);
- } // end of SetBinValue
+} // end of SetBinValue
/***********************************************************************/
/* GetBinValue: fill a buffer with the internal binary value. */
@@ -1570,7 +1573,7 @@ void TYPVAL<PSZ>::SetBinValue(void *p)
/* Currently used by WriteColumn of binary files. */
/***********************************************************************/
bool TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go)
- {
+{
int len = (Null) ? 0 : strlen(Strp);
if (len > buflen)
@@ -1581,7 +1584,7 @@ bool TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go)
} // endif go
return false;
- } // end of GetBinValue
+} // end of GetBinValue
/***********************************************************************/
/* STRING ShowValue: get string representation of a char value. */
@@ -1591,7 +1594,7 @@ int TYPVAL<PSZ>::ShowValue(char *buf, int buflen)
int len = (Null) ? 0 : strlen(Strp);
if (buf && buf != Strp) {
- memset(buf, ' ', buflen + 1);
+ memset(buf, ' ', (size_t)buflen + 1);
memcpy(buf, Strp, MY_MIN(len, buflen));
} // endif buf
@@ -1602,15 +1605,15 @@ int TYPVAL<PSZ>::ShowValue(char *buf, int buflen)
/* STRING GetCharString: get string representation of a char value. */
/***********************************************************************/
char *TYPVAL<PSZ>::GetCharString(char *)
- {
+{
return Strp;
- } // end of GetCharString
+} // end of GetCharString
/***********************************************************************/
/* STRING compare value with another Value. */
/***********************************************************************/
bool TYPVAL<PSZ>::IsEqual(PVAL vp, bool chktype)
- {
+{
if (this == vp)
return true;
else if (chktype && Type != vp->GetType())
@@ -1625,14 +1628,14 @@ bool TYPVAL<PSZ>::IsEqual(PVAL vp, bool chktype)
else // (!Ci)
return !strcmp(Strp, vp->GetCharString(buf));
- } // end of IsEqual
+} // end of IsEqual
/***********************************************************************/
/* Compare values and returns 1, 0 or -1 according to comparison. */
/* This function is used for evaluation of numeric filters. */
/***********************************************************************/
int TYPVAL<PSZ>::CompareValue(PVAL vp)
- {
+{
int n;
//assert(vp->GetType() == Type);
@@ -1651,13 +1654,13 @@ int TYPVAL<PSZ>::CompareValue(PVAL vp)
#endif // __WIN__
return (n > 0) ? 1 : (n < 0) ? -1 : 0;
- } // end of CompareValue
+} // end of CompareValue
/***********************************************************************/
/* Compute a function on a string. */
/***********************************************************************/
bool TYPVAL<PSZ>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
- {
+{
char *p[2], val[2][32];
int i;
@@ -1704,7 +1707,7 @@ bool TYPVAL<PSZ>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
Null = false;
return false;
- } // end of Compute
+} // end of Compute
/***********************************************************************/
/* FormatValue: This function set vp (a STRING value) to the string */
@@ -1712,23 +1715,23 @@ bool TYPVAL<PSZ>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
/* This function assumes that the format matches the value type. */
/***********************************************************************/
bool TYPVAL<PSZ>::FormatValue(PVAL vp, PCSZ fmt)
- {
+{
char *buf = (char*)vp->GetTo_Val(); // Should be big enough
int n = sprintf(buf, fmt, Strp);
return (n > vp->GetValLen());
- } // end of FormatValue
+} // end of FormatValue
/***********************************************************************/
/* STRING SetFormat function (used to set SELECT output format). */
/***********************************************************************/
bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL, FORMAT& fmt)
- {
+{
fmt.Type[0] = 'C';
fmt.Length = Len;
fmt.Prec = 0;
return false;
- } // end of SetConstFormat
+} // end of SetConstFormat
/***********************************************************************/
/* Make string output of an object value. */
@@ -1748,38 +1751,38 @@ void TYPVAL<PSZ>::Prints(PGLOBAL g, char *ps, uint z)
/* DECIMAL public constructor from a constant string. */
/***********************************************************************/
DECVAL::DECVAL(PSZ s) : TYPVAL<PSZ>(s)
- {
+{
if (s) {
char *p = strchr(Strp, '.');
Prec = (p) ? (int)(Len - (p - Strp)) : 0;
- } // endif s
+ } // endif s
Type = TYPE_DECIM;
- } // end of DECVAL constructor
+} // end of DECVAL constructor
/***********************************************************************/
/* DECIMAL public constructor from char. */
/***********************************************************************/
DECVAL::DECVAL(PGLOBAL g, PSZ s, int n, int prec, bool uns)
: TYPVAL<PSZ>(g, s, n + (prec ? 1 : 0) + (uns ? 0 : 1), 0)
- {
+{
Prec = prec;
Unsigned = uns;
Type = TYPE_DECIM;
- } // end of DECVAL constructor
+} // end of DECVAL constructor
/***********************************************************************/
/* DECIMAL: Check whether the numerica value is equal to 0. */
/***********************************************************************/
bool DECVAL::IsZero(void)
- {
+{
for (int i = 0; Strp[i]; i++)
if (!strchr("0 +-.", Strp[i]))
return false;
return true;
- } // end of IsZero
+} // end of IsZero
/***********************************************************************/
/* DECIMAL: Reset value to zero. */
@@ -1797,7 +1800,7 @@ void DECVAL::Reset(void)
Strp[i++] = '0';
} while (i < Prec + 2);
- } // endif Prec
+ } // endif Prec
Strp[i] = 0;
} // end of Reset
@@ -1806,9 +1809,9 @@ void DECVAL::Reset(void)
/* DECIMAL ShowValue: get string representation right justified. */
/***********************************************************************/
int DECVAL::ShowValue(char *buf, int len)
- {
+{
return snprintf(buf, len + 1, Xfmt, len, Strp);
- } // end of ShowValue
+} // end of ShowValue
/***********************************************************************/
/* GetBinValue: fill a buffer with the internal binary value. */
@@ -1817,7 +1820,7 @@ int DECVAL::ShowValue(char *buf, int len)
/* Currently used by WriteColumn of binary files. */
/***********************************************************************/
bool DECVAL::GetBinValue(void *buf, int buflen, bool go)
- {
+{
int len = (Null) ? 0 : strlen(Strp);
if (len > buflen)
@@ -1825,16 +1828,16 @@ bool DECVAL::GetBinValue(void *buf, int buflen, bool go)
else if (go) {
memset(buf, ' ', buflen - len);
memcpy((char*)buf + buflen - len, Strp, len);
- } // endif go
+ } // endif go
return false;
- } // end of GetBinValue
+} // end of GetBinValue
/***********************************************************************/
/* DECIMAL compare value with another Value. */
/***********************************************************************/
bool DECVAL::IsEqual(PVAL vp, bool chktype)
- {
+{
if (this == vp)
return true;
else if (chktype && Type != vp->GetType())
@@ -1845,14 +1848,14 @@ bool DECVAL::IsEqual(PVAL vp, bool chktype)
char buf[64];
return !strcmp(Strp, vp->GetCharString(buf));
- } // end of IsEqual
+} // end of IsEqual
/***********************************************************************/
/* Compare values and returns 1, 0 or -1 according to comparison. */
/* This function is used for evaluation of numeric filters. */
/***********************************************************************/
int DECVAL::CompareValue(PVAL vp)
- {
+{
//assert(vp->GetType() == Type);
// Process filtering on numeric values.
@@ -1862,7 +1865,7 @@ int DECVAL::CompareValue(PVAL vp)
// htrc(" Comparing: val=%d,%d\n", f, n);
return (f > n) ? 1 : (f < n) ? (-1) : 0;
- } // end of CompareValue
+} // end of CompareValue
/* -------------------------- Class BINVAL --------------------------- */
@@ -1870,7 +1873,7 @@ int DECVAL::CompareValue(PVAL vp)
/* BINVAL public constructor from bytes. */
/***********************************************************************/
BINVAL::BINVAL(PGLOBAL g, void *p, int cl, int n) : VALUE(TYPE_BIN)
- {
+{
assert(g);
Len = n;
Clen = cl;
@@ -1881,19 +1884,19 @@ BINVAL::BINVAL(PGLOBAL g, void *p, int cl, int n) : VALUE(TYPE_BIN)
memcpy(Binp, p, MY_MIN(Len,Clen));
Chrp = NULL;
- } // end of BINVAL constructor
+} // end of BINVAL constructor
/***********************************************************************/
/* BINVAL: Check whether the hexadecimal value is equal to 0. */
/***********************************************************************/
bool BINVAL::IsZero(void)
- {
+{
for (int i = 0; i < Len; i++)
if (((char*)Binp)[i] != 0)
return false;
return true;
- } // end of IsZero
+} // end of IsZero
/***********************************************************************/
/* BINVAL: Reset value to zero. */
@@ -1908,77 +1911,77 @@ void BINVAL::Reset(void)
/* Get the tiny value pointed by Binp. */
/***********************************************************************/
char BINVAL::GetTinyValue(void)
- {
+{
return *(char*)Binp;
- } // end of GetTinyValue
+} // end of GetTinyValue
/***********************************************************************/
/* Get the unsigned tiny value pointed by Binp. */
/***********************************************************************/
uchar BINVAL::GetUTinyValue(void)
- {
+{
return *(uchar*)Binp;
- } // end of GetUTinyValue
+} // end of GetUTinyValue
/***********************************************************************/
/* Get the short value pointed by Binp. */
/***********************************************************************/
short BINVAL::GetShortValue(void)
- {
+{
if (Len >= 2)
return *(short*)Binp;
else
return (short)GetTinyValue();
- } // end of GetShortValue
+} // end of GetShortValue
/***********************************************************************/
/* Get the unsigned short value pointed by Binp. */
/***********************************************************************/
ushort BINVAL::GetUShortValue(void)
- {
+{
return (ushort)GetShortValue();
- } // end of GetUshortValue
+} // end of GetUshortValue
/***********************************************************************/
/* Get the integer value pointed by Binp. */
/***********************************************************************/
int BINVAL::GetIntValue(void)
- {
+{
if (Len >= 4)
return *(int*)Binp;
else
return (int)GetShortValue();
- } // end of GetIntValue
+} // end of GetIntValue
/***********************************************************************/
/* Get the unsigned integer value pointed by Binp. */
/***********************************************************************/
uint BINVAL::GetUIntValue(void)
- {
+{
return (uint)GetIntValue();
- } // end of GetUintValue
+} // end of GetUintValue
/***********************************************************************/
/* Get the big integer value pointed by Binp. */
/***********************************************************************/
longlong BINVAL::GetBigintValue(void)
- {
+{
if (Len >= 8)
return *(longlong*)Binp;
else
return (longlong)GetIntValue();
- } // end of GetBigintValue
+} // end of GetBigintValue
/***********************************************************************/
/* Get the unsigned big integer value pointed by Binp. */
/***********************************************************************/
ulonglong BINVAL::GetUBigintValue(void)
- {
+{
return (ulonglong)GetBigintValue();
- } // end of GetUBigintValue
+} // end of GetUBigintValue
/***********************************************************************/
/* Get the double value pointed by Binp. */
@@ -1998,7 +2001,7 @@ double BINVAL::GetFloatValue(void)
/* BINVAL SetValue: copy the value of another Value object. */
/***********************************************************************/
bool BINVAL::SetValue_pval(PVAL valp, bool chktype)
- {
+{
bool rc = false;
if (valp != this) {
@@ -2018,16 +2021,16 @@ bool BINVAL::SetValue_pval(PVAL valp, bool chktype)
} else
Reset();
- } // endif valp
+ } // endif valp
return rc;
- } // end of SetValue_pval
+} // end of SetValue_pval
/***********************************************************************/
/* BINVAL SetValue: fill value with chars extracted from a line. */
/***********************************************************************/
bool BINVAL::SetValue_char(const char *p, int n)
- {
+{
bool rc;
if (p && n > 0) {
@@ -2047,13 +2050,13 @@ bool BINVAL::SetValue_char(const char *p, int n)
} // endif p
return rc;
- } // end of SetValue_char
+} // end of SetValue_char
/***********************************************************************/
/* BINVAL SetValue: fill value with another string. */
/***********************************************************************/
void BINVAL::SetValue_psz(PCSZ s)
- {
+{
if (s) {
int len = Len;
@@ -2068,13 +2071,13 @@ void BINVAL::SetValue_psz(PCSZ s)
Null = Nullable;
} // endif s
- } // end of SetValue_psz
+} // end of SetValue_psz
/***********************************************************************/
/* BINVAL SetValue: fill value with bytes extracted from a block. */
/***********************************************************************/
void BINVAL::SetValue_pvblk(PVBLK blk, int n)
- {
+{
// STRBLK's can return a NULL pointer
void *vp = blk->GetValPtrEx(n);
@@ -2097,13 +2100,13 @@ void BINVAL::SetValue_pvblk(PVBLK blk, int n)
Null = false;
} // endif vp
- } // end of SetValue_pvblk
+} // end of SetValue_pvblk
/***********************************************************************/
/* BINVAL SetValue: get the binary representation of an integer. */
/***********************************************************************/
void BINVAL::SetValue(int n)
- {
+{
if (Clen >= 4) {
if (Len > 4)
memset(Binp, 0, Len);
@@ -2113,13 +2116,13 @@ void BINVAL::SetValue(int n)
} else
SetValue((short)n);
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* BINVAL SetValue: get the binary representation of an uint. */
/***********************************************************************/
void BINVAL::SetValue(uint n)
- {
+{
if (Clen >= 4) {
if (Len > 4)
memset(Binp, 0, Len);
@@ -2129,13 +2132,13 @@ void BINVAL::SetValue(uint n)
} else
SetValue((ushort)n);
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* BINVAL SetValue: get the binary representation of a short int. */
/***********************************************************************/
void BINVAL::SetValue(short i)
- {
+{
if (Clen >= 2) {
if (Len > 2)
memset(Binp, 0, Len);
@@ -2145,13 +2148,13 @@ void BINVAL::SetValue(short i)
} else
SetValue((char)i);
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* BINVAL SetValue: get the binary representation of a ushort int. */
/***********************************************************************/
void BINVAL::SetValue(ushort i)
- {
+{
if (Clen >= 2) {
if (Len > 2)
memset(Binp, 0, Len);
@@ -2161,13 +2164,13 @@ void BINVAL::SetValue(ushort i)
} else
SetValue((uchar)i);
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* BINVAL SetValue: get the binary representation of a big integer. */
/***********************************************************************/
void BINVAL::SetValue(longlong n)
- {
+{
if (Clen >= 8) {
if (Len > 8)
memset(Binp, 0, Len);
@@ -2177,13 +2180,13 @@ void BINVAL::SetValue(longlong n)
} else
SetValue((int)n);
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* BINVAL SetValue: get the binary representation of a big integer. */
/***********************************************************************/
void BINVAL::SetValue(ulonglong n)
- {
+{
if (Clen >= 8) {
if (Len > 8)
memset(Binp, 0, Len);
@@ -2192,13 +2195,14 @@ void BINVAL::SetValue(ulonglong n)
Len = 8;
} else
SetValue((uint)n);
- } // end of SetValue
+
+} // end of SetValue
/***********************************************************************/
/* BINVAL SetValue: get the binary representation of a double. */
/***********************************************************************/
void BINVAL::SetValue(double n)
- {
+{
if (Len > 8)
memset(Binp, 0, Len);
@@ -2211,40 +2215,40 @@ void BINVAL::SetValue(double n)
} else
Len = 0;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* BINVAL SetValue: get the character binary of a tiny int. */
/***********************************************************************/
void BINVAL::SetValue(char c)
- {
+{
if (Len > 1)
memset(Binp, 0, Len);
*((char*)Binp) = c;
Len = 1;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* BINVAL SetValue: get the binary representation of a tiny int. */
/***********************************************************************/
void BINVAL::SetValue(uchar c)
- {
+{
if (Len > 1)
memset(Binp, 0, Len);
*((uchar*)Binp) = c;
Len = 1;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* BINVAL SetBinValue: fill string with bytes extracted from a line. */
/***********************************************************************/
void BINVAL::SetBinValue(void *p)
- {
+{
memcpy(Binp, p, Clen);
Len = Clen;
- } // end of SetBinValue
+} // end of SetBinValue
/***********************************************************************/
/* GetBinValue: fill a buffer with the internal binary value. */
@@ -2253,7 +2257,7 @@ void BINVAL::SetBinValue(void *p)
/* Currently used by WriteColumn of binary files. */
/***********************************************************************/
bool BINVAL::GetBinValue(void *buf, int buflen, bool go)
- {
+{
if (Len > buflen)
return true;
else if (go) {
@@ -2262,7 +2266,7 @@ bool BINVAL::GetBinValue(void *buf, int buflen, bool go)
} // endif go
return false;
- } // end of GetBinValue
+} // end of GetBinValue
/***********************************************************************/
/* BINVAL ShowValue: get string representation of a binary value. */
@@ -2278,19 +2282,19 @@ int BINVAL::ShowValue(char *buf, int len)
/* BINVAL GetCharString: get string representation of a binary value. */
/***********************************************************************/
char *BINVAL::GetCharString(char *)
- {
+{
if (!Chrp)
Chrp = (char*)PlugSubAlloc(Global, NULL, Clen * 2 + 1);
sprintf(Chrp, GetXfmt(), Len, Binp);
return Chrp;
- } // end of GetCharString
+} // end of GetCharString
/***********************************************************************/
/* BINVAL compare value with another Value. */
/***********************************************************************/
bool BINVAL::IsEqual(PVAL vp, bool chktype)
- {
+{
if (this == vp)
return true;
else if (chktype && Type != vp->GetType())
@@ -2308,7 +2312,7 @@ bool BINVAL::IsEqual(PVAL vp, bool chktype)
return false;
return true;
- } // end of IsEqual
+} // end of IsEqual
/***********************************************************************/
/* FormatValue: This function set vp (a STRING value) to the string */
@@ -2316,23 +2320,23 @@ bool BINVAL::IsEqual(PVAL vp, bool chktype)
/* This function assumes that the format matches the value type. */
/***********************************************************************/
bool BINVAL::FormatValue(PVAL vp, PCSZ fmt)
- {
+{
char *buf = (char*)vp->GetTo_Val(); // Should be big enough
int n = sprintf(buf, fmt, Len, Binp);
return (n > vp->GetValLen());
- } // end of FormatValue
+} // end of FormatValue
/***********************************************************************/
/* BINVAL SetFormat function (used to set SELECT output format). */
/***********************************************************************/
bool BINVAL::SetConstFormat(PGLOBAL, FORMAT& fmt)
- {
+{
fmt.Type[0] = 'B';
fmt.Length = Clen;
fmt.Prec = 0;
return false;
- } // end of SetConstFormat
+} // end of SetConstFormat
/* -------------------------- Class DTVAL ---------------------------- */
@@ -2341,7 +2345,7 @@ bool BINVAL::SetConstFormat(PGLOBAL, FORMAT& fmt)
/***********************************************************************/
DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt)
: TYPVAL<int>((int)0, TYPE_DATE)
- {
+{
if (!fmt) {
Pdtp = NULL;
Sdate = NULL;
@@ -2351,37 +2355,37 @@ DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt)
SetFormat(g, fmt, n, prec);
//Type = TYPE_DATE;
- } // end of DTVAL constructor
+} // end of DTVAL constructor
/***********************************************************************/
/* DTVAL public constructor from int. */
/***********************************************************************/
DTVAL::DTVAL(int n) : TYPVAL<int>(n, TYPE_DATE)
- {
+{
Pdtp = NULL;
Len = 19;
//Type = TYPE_DATE;
Sdate = NULL;
DefYear = 0;
- } // end of DTVAL constructor
+} // end of DTVAL constructor
/***********************************************************************/
/* Set format so formatted dates can be converted on input/output. */
/***********************************************************************/
bool DTVAL::SetFormat(PGLOBAL g, PCSZ fmt, int len, int year)
- {
+{
Pdtp = MakeDateFormat(g, fmt, true, true, (year > 9999) ? 1 : 0);
Sdate = (char*)PlugSubAlloc(g, NULL, len + 1);
DefYear = (int)((year > 9999) ? (year - 10000) : year);
Len = len;
return false;
- } // end of SetFormat
+} // end of SetFormat
/***********************************************************************/
/* Set format from the format of another date value. */
/***********************************************************************/
bool DTVAL::SetFormat(PGLOBAL g, PVAL valp)
- {
+{
DTVAL *vp;
if (valp->GetType() != TYPE_DATE) {
@@ -2395,14 +2399,14 @@ bool DTVAL::SetFormat(PGLOBAL g, PVAL valp)
Sdate = (char*)PlugSubAlloc(g, NULL, Len + 1);
DefYear = vp->DefYear;
return false;
- } // end of SetFormat
+} // end of SetFormat
/***********************************************************************/
/* We need TimeShift because the mktime C function does a correction */
/* for local time zone that we want to override for DB operations. */
/***********************************************************************/
void DTVAL::SetTimeShift(void)
- {
+{
struct tm dtm;
memset(&dtm, 0, sizeof(dtm));
dtm.tm_mday=2;
@@ -2414,7 +2418,7 @@ void DTVAL::SetTimeShift(void)
if (trace(1))
htrc("DTVAL Shift=%d\n", Shift);
- } // end of SetTimeShift
+} // end of SetTimeShift
// Added by Alexander Barkov
static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime)
@@ -2444,7 +2448,7 @@ static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm)
/* extend the range of valid dates by accepting negative time values. */
/***********************************************************************/
struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
- {
+{
struct tm *datm;
time_t t = (time_t)Tval;
@@ -2463,7 +2467,7 @@ struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
datm = gmtime_mysql(&t, tm_buffer);
return datm;
- } // end of GetGmTime
+} // end of GetGmTime
// Added by Alexander Barkov
static time_t mktime_mysql(struct tm *ptm)
@@ -2482,7 +2486,7 @@ static time_t mktime_mysql(struct tm *ptm)
/* range of valid dates by accepting to set negative time values. */
/***********************************************************************/
bool DTVAL::MakeTime(struct tm *ptm)
- {
+{
int n, y = ptm->tm_year;
time_t t = mktime_mysql(ptm);
@@ -2498,7 +2502,7 @@ bool DTVAL::MakeTime(struct tm *ptm)
for (n = 0; t == -1 && n < 20; n++) {
ptm->tm_year += 4;
t = mktime_mysql(ptm);
- } // endfor t
+ } // endfor t
if (t == -1)
return true;
@@ -2506,20 +2510,21 @@ bool DTVAL::MakeTime(struct tm *ptm)
if ((t -= (n * FOURYEARS)) > 2000000000)
return true;
- }
+ } // endif t
+
Tval= (int) t;
if (trace(2))
htrc("MakeTime Ival=%d\n", Tval);
return false;
- } // end of MakeTime
+} // end of MakeTime
/***********************************************************************/
/* Make a time_t datetime from its components (YY, MM, DD, hh, mm, ss) */
/***********************************************************************/
bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
- {
+{
int i, m;
int n;
bool rc = false;
@@ -2589,9 +2594,9 @@ bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
case 3: datm.tm_hour = n; break;
case 4: datm.tm_min = n; break;
case 5: datm.tm_sec = n; break;
- } // endswitch i
+ } // endswitch i
- } // endfor i
+ } // endfor i
if (trace(2))
htrc("MakeDate datm=(%d,%d,%d,%d,%d,%d)\n",
@@ -2607,14 +2612,14 @@ bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
Tval = 0;
return rc;
- } // end of MakeDate
+} // end of MakeDate
/***********************************************************************/
/* DTVAL SetValue: copy the value of another Value object. */
/* This function allows conversion if chktype is false. */
/***********************************************************************/
bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
- {
+{
if (valp != this) {
if (chktype && Type != valp->GetType())
return true;
@@ -2636,16 +2641,16 @@ bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
} else
Reset();
- } // endif valp
+ } // endif valp
return false;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* SetValue: convert chars extracted from a line to date value. */
/***********************************************************************/
bool DTVAL::SetValue_char(const char *p, int n)
- {
+{
bool rc= 0;
if (Pdtp) {
@@ -2661,7 +2666,7 @@ bool DTVAL::SetValue_char(const char *p, int n)
n = Len;
memcpy(Sdate, p, n);
- } // endif n
+ } // endif n
Sdate[n] = '\0';
@@ -2678,13 +2683,13 @@ bool DTVAL::SetValue_char(const char *p, int n)
} // endif Pdtp
return rc;
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* SetValue: convert a char string to date value. */
/***********************************************************************/
void DTVAL::SetValue_psz(PCSZ p)
- {
+{
if (Pdtp) {
int ndv;
int dval[6];
@@ -2704,13 +2709,13 @@ void DTVAL::SetValue_psz(PCSZ p)
Null = (Nullable && Tval == 0);
} // endif Pdtp
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* DTVAL SetValue: set value with a value extracted from a block. */
/***********************************************************************/
void DTVAL::SetValue_pvblk(PVBLK blk, int n)
- {
+{
if (Pdtp && !::IsTypeNum(blk->GetType())) {
int ndv;
int dval[6];
@@ -2720,13 +2725,13 @@ void DTVAL::SetValue_pvblk(PVBLK blk, int n)
} else
Tval = blk->GetIntValue(n);
- } // end of SetValue
+} // end of SetValue
/***********************************************************************/
/* DTVAL GetCharString: get string representation of a date value. */
/***********************************************************************/
char *DTVAL::GetCharString(char *p)
- {
+{
if (Pdtp) {
size_t n = 0;
struct tm tm, *ptm= GetGmTime(&tm);
@@ -2745,7 +2750,7 @@ char *DTVAL::GetCharString(char *p)
//Null = false; ??????????????
return p;
- } // end of GetCharString
+} // end of GetCharString
/***********************************************************************/
/* DTVAL ShowValue: get string representation of a date value. */
@@ -2783,7 +2788,7 @@ int DTVAL::ShowValue(char *buf, int len)
/* Returns a member of the struct tm representation of the date. */
/***********************************************************************/
bool DTVAL::GetTmMember(OPVAL op, int& mval)
- {
+{
bool rc = false;
struct tm tm, *ptm = GetGmTime(&tm);
@@ -2796,10 +2801,10 @@ bool DTVAL::GetTmMember(OPVAL op, int& mval)
case OP_QUART: mval = ptm->tm_mon / 3 + 1; break;
default:
rc = true;
- } // endswitch op
+ } // endswitch op
return rc;
- } // end of GetTmMember
+} // end of GetTmMember
/***********************************************************************/
/* Calculates the week number of the year for the internal date value.*/
@@ -2810,7 +2815,7 @@ bool DTVAL::GetTmMember(OPVAL op, int& mval)
/* the week that contains the January 4th. */
/***********************************************************************/
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 tm, *ptm = GetGmTime(&tm);
@@ -2827,7 +2832,7 @@ bool DTVAL::WeekNum(PGLOBAL g, int& nval)
// Everything should be Ok
return false;
- } // end of WeekNum
+} // end of WeekNum
#endif // 0
/***********************************************************************/
@@ -2836,7 +2841,7 @@ bool DTVAL::WeekNum(PGLOBAL g, int& nval)
/* This function assumes that the format matches the value type. */
/***********************************************************************/
bool DTVAL::FormatValue(PVAL vp, PCSZ fmt)
- {
+{
char *buf = (char*)vp->GetTo_Val(); // Should be big enough
struct tm tm, *ptm = GetGmTime(&tm);
@@ -2853,6 +2858,6 @@ bool DTVAL::FormatValue(PVAL vp, PCSZ fmt)
} else
return true;
- } // end of FormatValue
+} // end of FormatValue
/* -------------------------- End of Value --------------------------- */
diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp
index db4d6cbb00d..95f038d494c 100644
--- a/storage/connect/xindex.cpp
+++ b/storage/connect/xindex.cpp
@@ -659,7 +659,7 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
/* Not true for DBF tables because of eventual soft deleted lines. */
/* Note: for Num_K = 1 any non null value is Ok. */
/*********************************************************************/
- if (Srtd && !filp && Tdbp->Ftype != RECFM_VAR
+ if (Srtd && !filp && Tdbp->Ftype != RECFM_VAR && Tdbp->Ftype != RECFM_CSV
&& Tdbp->Txfp->GetAmType() != TYPE_AM_DBF) {
Incr = (Num_K > 1) ? To_Rec[1] : Num_K;
PlgDBfree(Record);
@@ -837,7 +837,8 @@ bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp)
case RECFM_FIX: ftype = ".fnx"; break;
case RECFM_BIN: ftype = ".bnx"; break;
case RECFM_VCT: ftype = ".vnx"; break;
- case RECFM_DBF: ftype = ".dbx"; break;
+ case RECFM_CSV: ftype = ".cnx"; break;
+ case RECFM_DBF: ftype = ".dbx"; break;
default:
sprintf(g->Message, MSG(INVALID_FTYPE), Tdbp->Ftype);
return true;
@@ -990,7 +991,8 @@ bool XINDEX::Init(PGLOBAL g)
case RECFM_FIX: ftype = ".fnx"; break;
case RECFM_BIN: ftype = ".bnx"; break;
case RECFM_VCT: ftype = ".vnx"; break;
- case RECFM_DBF: ftype = ".dbx"; break;
+ case RECFM_CSV: ftype = ".cnx"; break;
+ case RECFM_DBF: ftype = ".dbx"; break;
default:
sprintf(g->Message, MSG(INVALID_FTYPE), Tdbp->Ftype);
return true;
@@ -1243,7 +1245,8 @@ bool XINDEX::MapInit(PGLOBAL g)
case RECFM_FIX: ftype = ".fnx"; break;
case RECFM_BIN: ftype = ".bnx"; break;
case RECFM_VCT: ftype = ".vnx"; break;
- case RECFM_DBF: ftype = ".dbx"; break;
+ case RECFM_CSV: ftype = ".cnx"; break;
+ case RECFM_DBF: ftype = ".dbx"; break;
default:
sprintf(g->Message, MSG(INVALID_FTYPE), Tdbp->Ftype);
return true;
@@ -1457,7 +1460,8 @@ bool XINDEX::GetAllSizes(PGLOBAL g,/* int &ndif,*/ int &numk)
case RECFM_FIX: ftype = ".fnx"; break;
case RECFM_BIN: ftype = ".bnx"; break;
case RECFM_VCT: ftype = ".vnx"; break;
- case RECFM_DBF: ftype = ".dbx"; break;
+ case RECFM_CSV: ftype = ".cnx"; break;
+ case RECFM_DBF: ftype = ".dbx"; break;
default:
sprintf(g->Message, MSG(INVALID_FTYPE), Tdbp->Ftype);
return true;
diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h
index bc9265e0223..1b499e09047 100644
--- a/storage/connect/xtable.h
+++ b/storage/connect/xtable.h
@@ -173,9 +173,12 @@ class DllExport TDBASE : public TDB {
inline void SetKindex(PKXBASE kxp) {To_Kindex = kxp;}
// Properties
- virtual PKXBASE GetKindex(void) {return To_Kindex;}
+ PKXBASE GetKindex(void) {return To_Kindex;}
+ PXOB *GetLink(void) {return To_Link;}
+ PIXDEF GetXdp(void) {return To_Xdp;}
void ResetKindex(PGLOBAL g, PKXBASE kxp);
PCOL Key(int i) {return (To_Key_Col) ? To_Key_Col[i] : NULL;}
+ PXOB Link(int i) { return (To_Link) ? To_Link[i] : NULL; }
// Methods
virtual bool IsUsingTemp(PGLOBAL) {return false;}