summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2013-11-06 18:22:09 +0100
committerOlivier Bertrand <bertrandop@gmail.com>2013-11-06 18:22:09 +0100
commit056f35d0c136af4437344d4fbce80172e6d96817 (patch)
tree954befda500a4f7b1fb3b6d5b1e814a7077c3d96
parentf1325549e9eca1311435255854da0a93923eff9b (diff)
downloadmariadb-git-056f35d0c136af4437344d4fbce80172e6d96817.tar.gz
- Move all enum AMT definitions in one place (plgdbsem.h)
modified: storage/connect/filamtxt.h storage/connect/filamzip.h storage/connect/myconn.h storage/connect/plgdbsem.h storage/connect/taboccur.h storage/connect/tabutil.h storage/connect/tabxcl.h - Add the possibility to execute several commands in one query of an EXECSRC tables (using ...where command in (cmd list);) modified: storage/connect/ha_connect.cc storage/connect/odbconn.cpp storage/connect/odbconn.h storage/connect/tabmysql.cpp storage/connect/tabmysql.h storage/connect/tabodbc.cpp storage/connect/tabodbc.h storage/connect/tabtbl.cpp storage/connect/tabwmi.cpp storage/connect/xtable.h - Enhance retrieving column definitions in discovery: From SRCDEF adding LIMIT 0 to the executed query Testing if type, length, and precision are compatible Making the distinction between CHAR and VARCHAR modified: storage/connect/ha_connect.cc storage/connect/myconn.cpp storage/connect/mysql-test/connect/r/mysql.result storage/connect/mysql-test/connect/r/odbc_sqlite3.result storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result storage/connect/myutil.h storage/connect/myutil.h storage/connect/odbconn.cpp storage/connect/value.h
-rw-r--r--storage/connect/filamtxt.h2
-rw-r--r--storage/connect/filamzip.h3
-rw-r--r--storage/connect/ha_connect.cc118
-rw-r--r--storage/connect/myconn.cpp54
-rw-r--r--storage/connect/myconn.h5
-rw-r--r--storage/connect/mysql-test/connect/r/mysql.result4
-rw-r--r--storage/connect/mysql-test/connect/r/odbc_sqlite3.result2
-rw-r--r--storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result2
-rw-r--r--storage/connect/myutil.cpp10
-rw-r--r--storage/connect/myutil.h9
-rw-r--r--storage/connect/odbconn.cpp150
-rw-r--r--storage/connect/odbconn.h3
-rw-r--r--storage/connect/plgdbsem.h10
-rw-r--r--storage/connect/tabmysql.cpp135
-rw-r--r--storage/connect/tabmysql.h20
-rw-r--r--storage/connect/taboccur.h2
-rw-r--r--storage/connect/tabodbc.cpp72
-rw-r--r--storage/connect/tabodbc.h14
-rw-r--r--storage/connect/tabtbl.cpp9
-rw-r--r--storage/connect/tabutil.h2
-rw-r--r--storage/connect/tabwmi.cpp17
-rw-r--r--storage/connect/tabxcl.h2
-rw-r--r--storage/connect/value.h2
-rw-r--r--storage/connect/xtable.h34
24 files changed, 485 insertions, 196 deletions
diff --git a/storage/connect/filamtxt.h b/storage/connect/filamtxt.h
index 6a1093eaa06..a6105d0fe66 100644
--- a/storage/connect/filamtxt.h
+++ b/storage/connect/filamtxt.h
@@ -17,8 +17,6 @@ typedef class BLKFAM *PBLKFAM;
typedef class DOSDEF *PDOSDEF;
typedef class TDBDOS *PTDBDOS;
-#define TYPE_AM_BLK (AMT)160
-
/***********************************************************************/
/* This is the base class for all file access method classes. */
/***********************************************************************/
diff --git a/storage/connect/filamzip.h b/storage/connect/filamzip.h
index a83af78b19a..f6f28ca5315 100644
--- a/storage/connect/filamzip.h
+++ b/storage/connect/filamzip.h
@@ -10,9 +10,6 @@
#include "zlib.h"
-#define TYPE_AM_ZIP (AMT)150
-#define TYPE_AM_ZLIB (AMT)155
-
typedef class ZIPFAM *PZIPFAM;
typedef class ZBKFAM *PZBKFAM;
typedef class ZIXFAM *PZIXFAM;
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index bd02b8ab1d5..31d56dce7e2 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -1557,8 +1557,9 @@ const char *ha_connect::GetValStr(OPVAL vop, bool neg)
/***********************************************************************/
PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
{
+ char *body= filp->Body;
unsigned int i;
- bool ismul= false;
+ bool ismul= false, x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
PPARM pfirst= NULL, pprec= NULL, pp[2]= {NULL, NULL};
OPVAL vop= OP_XX;
@@ -1572,6 +1573,9 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
char *p1, *p2;
Item_cond *cond_item= (Item_cond *)cond;
+ if (x)
+ return NULL;
+
if (xtrace > 1)
printf("Cond: Ftype=%d name=%s\n", cond_item->functype(),
cond_item->func_name());
@@ -1586,7 +1590,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
List_iterator<Item> li(*arglist);
Item *subitem;
- p1= filp + strlen(filp);
+ p1= body + strlen(body);
strcpy(p1, "(");
p2= p1 + 1;
@@ -1615,7 +1619,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
} else if (cond->type() == COND::FUNC_ITEM) {
unsigned int i;
// int n;
- bool iscol, neg= FALSE;
+ bool iscol, neg= FALSE;
Item_func *condf= (Item_func *)cond;
Item* *args= condf->arguments();
@@ -1644,6 +1648,9 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
else if (ismul && tty == TYPE_AM_WMI)
return NULL; // Not supported by WQL
+ if (x && (neg || !(vop == OP_EQ || vop == OP_IN)))
+ return NULL;
+
for (i= 0; i < condf->argument_count(); i++) {
if (xtrace > 1)
printf("Argtype(%d)=%d\n", i, args[i]->type());
@@ -1660,6 +1667,9 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
ha_field_option_struct *fop;
Item_field *pField= (Item_field *)args[i];
+ if (x && i)
+ return NULL;
+
if (pField->field->table != table)
return NULL; // Field does not belong to this table
else
@@ -1685,10 +1695,10 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
if (i && ismul)
return NULL;
- strcat(filp, fnm);
+ strcat(body, fnm);
} else {
- char buff[256];
- String *res, tmp(buff,sizeof(buff), &my_charset_bin);
+ char buff[256];
+ String *res, tmp(buff, sizeof(buff), &my_charset_bin);
Item_basic_constant *pval= (Item_basic_constant *)args[i];
if ((res= pval->val_str(&tmp)) == NULL)
@@ -1698,26 +1708,46 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
printf("Value=%.*s\n", res->length(), res->ptr());
// IN and BETWEEN clauses should be col VOP list
- if (!i && ismul)
+ if (!i && (x || ismul))
return NULL;
- // Append the value to the filter
- if (args[i]->field_type() == MYSQL_TYPE_VARCHAR)
- strcat(strcat(strcat(filp, "'"), res->ptr()), "'");
- else
- strncat(filp, res->ptr(), res->length());
+ if (!x) {
+ // Append the value to the filter
+ if (args[i]->field_type() == MYSQL_TYPE_VARCHAR)
+ strcat(strcat(strcat(body, "'"), res->ptr()), "'");
+ else
+ strncat(body, res->ptr(), res->length());
+
+ } else {
+ if (args[i]->field_type() == MYSQL_TYPE_VARCHAR) {
+ // Add the command to the list
+ PCMD *ncp, cmdp= new(g) CMD(g, (char*)res->ptr());
+
+ for (ncp= &filp->Cmds; *ncp; ncp= &(*ncp)->Next) ;
+
+ *ncp= cmdp;
+ } else
+ return NULL;
+
+ } // endif x
} // endif
- if (!i)
- strcat(filp, GetValStr(vop, neg));
- else if (vop == OP_XX && i == 1)
- strcat(filp, " AND ");
- else if (vop == OP_IN)
- strcat(filp, (i == condf->argument_count() - 1) ? ")" : ",");
+ if (!x) {
+ if (!i)
+ strcat(body, GetValStr(vop, neg));
+ else if (vop == OP_XX && i == 1)
+ strcat(body, " AND ");
+ else if (vop == OP_IN)
+ strcat(body, (i == condf->argument_count() - 1) ? ")" : ",");
+
+ } // endif x
} // endfor i
+ if (x)
+ filp->Op= vop;
+
} else {
if (xtrace > 1)
printf("Unsupported condition\n");
@@ -1753,23 +1783,31 @@ const COND *ha_connect::cond_push(const COND *cond)
DBUG_ENTER("ha_connect::cond_push");
if (tdbp) {
- AMT tty= tdbp->GetAmType();
+ AMT tty= tdbp->GetAmType();
+ bool x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
if (tty == TYPE_AM_WMI || tty == TYPE_AM_ODBC ||
- tty == TYPE_AM_TBL || tty == TYPE_AM_MYSQL) {
+ tty == TYPE_AM_TBL || tty == TYPE_AM_MYSQL || x) {
PGLOBAL& g= xp->g;
- PFIL filp= (PFIL)PlugSubAlloc(g, NULL, 0);
+ PFIL filp= (PFIL)PlugSubAlloc(g, NULL, sizeof(FILTER));
- *filp= 0;
+ filp->Body= (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0);
+ *filp->Body= 0;
+ filp->Op= OP_XX;
+ filp->Cmds= NULL;
if (CheckCond(g, filp, tty, (Item *)cond)) {
if (xtrace)
- puts(filp);
+ puts(filp->Body);
+
+ if (!x)
+ PlugSubAlloc(g, NULL, strlen(filp->Body) + 1);
+ else
+ cond= NULL; // Does this work?
tdbp->SetFilter(filp);
-// cond= NULL; // This does not work anyway
- PlugSubAlloc(g, NULL, strlen(filp) + 1);
- } // endif filp
+ } else if (x && cond)
+ tdbp->SetFilter(filp); // Wrong filter
} // endif tty
@@ -3461,12 +3499,13 @@ static bool add_fields(PGLOBAL g,
DBUG_RETURN(0);
} // end of add_fields
#else // !NEW_WAY
-static bool add_field(String *sql, const char *field_name, int typ, int len,
- int dec, uint tm, const char *rem, int flag, bool dbf)
+static bool add_field(String *sql, const char *field_name, int typ,
+ int len, int dec, uint tm, const char *rem,
+ int flag, bool dbf, char v)
{
+ char var = (len > 255) ? 'V' : v;
bool error= false;
- const char *type= PLGtoMYSQLtype(typ, dbf);
-// type= PLGtoMYSQLtype(typ, true); ?????
+ const char *type= PLGtoMYSQLtype(typ, dbf, var);
error|= sql->append('`');
error|= sql->append(field_name);
@@ -3479,7 +3518,8 @@ static bool add_field(String *sql, const char *field_name, int typ, int len,
if (!strcmp(type, "DOUBLE")) {
error|= sql->append(',');
- error|= sql->append_ulonglong(dec);
+ // dec must be <= len and <= 31
+ error|= sql->append_ulonglong(min(dec, (len - 1)));
} // endif dec
error|= sql->append(')');
@@ -3518,6 +3558,8 @@ static int init_table_share(THD *thd,
HA_CREATE_INFO *create_info,
Alter_info *alter_info)
{
+ KEY *not_used_1;
+ uint not_used_2;
int rc= 0;
handler *file;
LEX_CUSTRING frm= {0,0};
@@ -3577,9 +3619,8 @@ static int init_table_share(THD *thd,
tmp_disable_binlog(thd);
file= mysql_create_frm_image(thd, table_s->db.str, table_s->table_name.str,
- create_info, alter_info,
-// &thd->lex->create_info, &thd->lex->alter_info,
- C_ORDINARY_CREATE, &frm);
+ create_info, alter_info, C_ORDINARY_CREATE,
+ &not_used_1, &not_used_2, &frm);
if (file)
delete file;
else
@@ -3777,7 +3818,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
//CHARSET_INFO *cs;
Alter_info alter_info;
#else // !NEW_WAY
- char buf[1024];
+ char v, buf[1024];
String sql(buf, sizeof(buf), system_charset_info);
sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info);
@@ -4097,7 +4138,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
NOT_NULL_FLAG, "", flg, dbf);
#else // !NEW_WAY
// Now add the field
- if (add_field(&sql, cnm, typ, len, dec, NOT_NULL_FLAG, 0, flg, dbf))
+ if (add_field(&sql, cnm, typ, len, dec, NOT_NULL_FLAG, 0, flg, dbf, 0))
rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY
} // endfor crp
@@ -4121,6 +4162,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
break;
case FLD_TYPE:
typ= crp->Kdata->GetIntValue(i);
+ v = (crp->Nulls) ? crp->Nulls[i] : 0;
break;
case FLD_PREC:
len= crp->Kdata->GetIntValue(i);
@@ -4151,7 +4193,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
int plgtyp;
// typ must be PLG type, not SQL type
- if (!(plgtyp= TranslateSQLType(typ, dec, len))) {
+ if (!(plgtyp= TranslateSQLType(typ, dec, len, v))) {
sprintf(g->Message, "Unsupported SQL type %d", typ);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return HA_ERR_INTERNAL_ERROR;
@@ -4176,7 +4218,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
rc= add_fields(g, thd, &alter_info, cnm, typ, len, dec,
tm, rem, 0, true);
#else // !NEW_WAY
- if (add_field(&sql, cnm, typ, len, dec, tm, rem, 0, true))
+ if (add_field(&sql, cnm, typ, len, dec, tm, rem, 0, true, v))
rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY
} // endfor i
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index e2de93e8fc8..d29c116756a 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -87,7 +87,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
FLD_KEY, FLD_SCALE, FLD_RADIX, FLD_NULL,
FLD_REM, FLD_NO, FLD_CHARSET};
static unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 256, 32, 32};
- char *fld, *fmt, cmd[128];
+ char *fld, *fmt, v, cmd[128];
int i, n, nf, ncol = sizeof(buftyp) / sizeof(int);
int len, type, prec, rc, k = 0;
PQRYRES qrp;
@@ -139,6 +139,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
// Some columns must be renamed
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
switch (++i) {
+ case 2: crp->Nulls = (char*)PlugSubAlloc(g, NULL, n); break;
case 4: crp->Name = "Length"; break;
case 5: crp->Name = "Key"; break;
case 10: crp->Name = "Date_fmt"; break;
@@ -166,7 +167,8 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
// Get type, type name, and precision
fld = myc.GetCharField(1);
prec = 0;
- len = 255; // Default for text or blob
+ len = 0;
+ v = 0;
if ((nf = sscanf(fld, "%[^(](%d,%d", cmd, &len, &prec)) < 1) {
sprintf(g->Message, MSG(BAD_FIELD_TYPE), fld);
@@ -175,14 +177,16 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
} else
qrp->Nblin++;
- if ((type = MYSQLtoPLG(cmd)) == TYPE_ERROR) {
+ if ((type = MYSQLtoPLG(cmd, &v)) == TYPE_ERROR) {
sprintf(g->Message, "Unsupported column type %s", cmd);
myc.Close();
return NULL;
- } // endif type
+ } else if (type == TYPE_STRING)
+ len = min(len, 255);
crp = crp->Next; // Data_Type
crp->Kdata->SetValue(type, i);
+ crp->Nulls[i] = v;
crp = crp->Next; // Type_Name
crp->Kdata->SetValue(cmd, i);
@@ -253,6 +257,7 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
const char *user, const char *pwd,
const char *srcdef, int port)
{
+ char *query;
int w;
MYSQLC myc;
PQRYRES qrp = NULL;
@@ -260,12 +265,15 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
if (!port)
port = mysqld_port;
+ query = (char *)PlugSubAlloc(g, NULL, strlen(srcdef) + 9);
+ strcat(strcpy(query, srcdef), " LIMIT 0");
+
// Open a MySQL connection for this table
if (myc.Open(g, host, db, user, pwd, port))
return NULL;
// Send the source command to MySQL
- if (myc.ExecSQL(g, srcdef, &w) == RC_OK)
+ if (myc.ExecSQL(g, query, &w) == RC_OK)
qrp = myc.GetResult(g);
myc.Close();
@@ -779,6 +787,42 @@ void MYSQLC::Rewind(void)
} // end of Rewind
/***********************************************************************/
+/* Exec the Select SQL command and return ncol or afrws (TDBMYEXC). */
+/***********************************************************************/
+int MYSQLC::ExecSQLcmd(PGLOBAL g, const char *query, int *w)
+ {
+ int rc = RC_OK;
+
+ if (!m_DB) {
+ strcpy(g->Message, "MySQL not connected");
+ return RC_FX;
+ } else
+ *w = 0;
+
+ if (!stricmp(query, "Warning") || !stricmp(query, "Note")
+ || !stricmp(query, "Error"))
+ return RC_INFO;
+ else
+ m_Afrw = 0;
+
+//if (mysql_query(m_DB, query) != 0) {
+ if (mysql_real_query(m_DB, query, strlen(query))) {
+ m_Afrw = (int)mysql_errno(m_DB);
+ sprintf(g->Message, "%s", mysql_error(m_DB));
+ rc = RC_FX;
+//} else if (!(m_Fields = mysql_field_count(m_DB))) {
+ } else if (!(m_Fields = (int)m_DB->field_count)) {
+// m_Afrw = (int)mysql_affected_rows(m_DB);
+ m_Afrw = (int)m_DB->affected_rows;
+ rc = RC_NF;
+ } // endif's
+
+//*w = mysql_warning_count(m_DB);
+ *w = m_DB->warning_count;
+ return rc;
+ } // end of ExecSQLcmd
+
+/***********************************************************************/
/* Close the connection. */
/***********************************************************************/
void MYSQLC::Close(void)
diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h
index 10ff76c3273..8a49239ec7a 100644
--- a/storage/connect/myconn.h
+++ b/storage/connect/myconn.h
@@ -26,7 +26,6 @@
#define DllItem
#endif // !WIN32
-//#define TYPE_AM_MYSQL (AMT)192
#define MYSQL_ENABLED 0x00000001
#define MYSQL_LOGON 0x00000002
@@ -75,9 +74,12 @@ class DllItem MYSQLC {
//const char *ServerInfo(void);
int KillQuery(ulong id);
int ExecSQL(PGLOBAL g, const char *query, int *w = NULL);
+ int ExecSQLcmd(PGLOBAL g, const char *query, int *w);
+#if defined(MYSQL_PREPARED_STATEMENTS)
int PrepareSQL(PGLOBAL g, const char *query);
int ExecStmt(PGLOBAL g);
int BindParams(PGLOBAL g, MYSQL_BIND *bind);
+#endif // MYSQL_PREPARED_STATEMENTS
PQRYRES GetResult(PGLOBAL g, bool pdb = FALSE);
int Fetch(PGLOBAL g, int pos);
char *GetCharField(int i);
@@ -99,5 +101,6 @@ class DllItem MYSQLC {
int m_Rows; // The number of rows of the result
int N;
int m_Fields; // The number of result fields
+ int m_Afrw; // The number of affected rows
}; // end of class MYSQLC
diff --git a/storage/connect/mysql-test/connect/r/mysql.result b/storage/connect/mysql-test/connect/r/mysql.result
index c0ef487c111..eb45e29c7f1 100644
--- a/storage/connect/mysql-test/connect/r/mysql.result
+++ b/storage/connect/mysql-test/connect/r/mysql.result
@@ -44,7 +44,7 @@ SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL,
- `b` varchar(10) DEFAULT NULL
+ `b` char(10) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
SELECT * FROM t2;
a b
@@ -176,7 +176,7 @@ t1 CREATE TABLE `t1` (
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `a` varchar(10) DEFAULT NULL
+ `a` char(10) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
SELECT * FROM t2;
a
diff --git a/storage/connect/mysql-test/connect/r/odbc_sqlite3.result b/storage/connect/mysql-test/connect/r/odbc_sqlite3.result
index 339dbb6a53d..3ff99791760 100644
--- a/storage/connect/mysql-test/connect/r/odbc_sqlite3.result
+++ b/storage/connect/mysql-test/connect/r/odbc_sqlite3.result
@@ -1,6 +1,6 @@
Table Create Table
t1 CREATE TABLE `t1` (
- `Description` varchar(128) NOT NULL,
+ `Description` char(128) NOT NULL,
`Attributes` varchar(256) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers'
SET NAMES utf8;
diff --git a/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result b/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result
index 87f7803166c..364f340eddf 100644
--- a/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result
+++ b/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result
@@ -1,6 +1,6 @@
Table Create Table
t1 CREATE TABLE `t1` (
- `Description` varchar(128) NOT NULL,
+ `Description` char(128) NOT NULL,
`Attributes` varchar(256) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers'
SET NAMES utf8;
diff --git a/storage/connect/myutil.cpp b/storage/connect/myutil.cpp
index b266b7b79c1..ecea6a0eada 100644
--- a/storage/connect/myutil.cpp
+++ b/storage/connect/myutil.cpp
@@ -29,7 +29,7 @@
/************************************************************************/
/* Convert from MySQL type name to PlugDB type number */
/************************************************************************/
-int MYSQLtoPLG(char *typname)
+int MYSQLtoPLG(char *typname, char *var)
{
int type;
@@ -56,6 +56,10 @@ int MYSQLtoPLG(char *typname)
else
type = TYPE_ERROR;
+ // This is to make the difference between CHAR and VARCHAR
+ if (var && type == TYPE_STRING && stricmp(typname, "char"))
+ *var = 'V';
+
return type;
} // end of MYSQLtoPLG
@@ -98,14 +102,14 @@ enum enum_field_types PLGtoMYSQL(int type, bool dbf)
/************************************************************************/
/* Convert from PlugDB type to MySQL type name */
/************************************************************************/
-const char *PLGtoMYSQLtype(int type, bool dbf)
+const char *PLGtoMYSQLtype(int type, bool dbf, char var)
{
switch (type) {
case TYPE_INT: return "INT";
case TYPE_SHORT: return "SMALLINT";
case TYPE_FLOAT: return "DOUBLE";
case TYPE_DATE: return dbf ? "DATE" : "DATETIME";
- case TYPE_STRING: return "VARCHAR";
+ case TYPE_STRING: return var ? "VARCHAR" : "CHAR";
case TYPE_BIGINT: return "BIGINT";
case TYPE_TINY: return "TINYINT";
default: return "CHAR(0)";
diff --git a/storage/connect/myutil.h b/storage/connect/myutil.h
index 7ddfcbe599c..46f060e3e17 100644
--- a/storage/connect/myutil.h
+++ b/storage/connect/myutil.h
@@ -1,9 +1,14 @@
/***********************************************************************/
/* Prototypes of Functions used externally. */
/***********************************************************************/
+#ifndef __MYUTIL__H
+#define __MYUTIL__H
+
enum enum_field_types PLGtoMYSQL(int type, bool dbf);
-const char *PLGtoMYSQLtype(int type, bool dbf);
-int MYSQLtoPLG(char *typname);
+const char *PLGtoMYSQLtype(int type, bool dbf, char var = NULL);
+int MYSQLtoPLG(char *typname, char *var = NULL);
int MYSQLtoPLG(int mytype);
char *MyDateFmt(int mytype);
char *MyDateFmt(char *typname);
+
+#endif // __MYUTIL__H
diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp
index 0a19d90a422..04ec147d91c 100644
--- a/storage/connect/odbconn.cpp
+++ b/storage/connect/odbconn.cpp
@@ -108,16 +108,18 @@ static int GetSQLCType(int type)
/***********************************************************************/
/* TranslateSQLType: translate a SQL Type to a PLG type. */
/***********************************************************************/
-int TranslateSQLType(int stp, int prec, int& len)
+int TranslateSQLType(int stp, int prec, int& len, char& v)
{
int type;
switch (stp) {
- case SQL_CHAR: // 1
case SQL_VARCHAR: // 12
+ v = 'V';
+ case SQL_CHAR: // 1
type = TYPE_STRING;
break;
case SQL_LONGVARCHAR: // (-1)
+ v = 'V';
type = TYPE_STRING;
len = min(abs(len), 255);
break;
@@ -889,7 +891,7 @@ bool ODBConn::Check(RETCODE rc)
{
switch (rc) {
case SQL_SUCCESS_WITH_INFO:
- if (trace > 1) {
+ if (trace) {
DBX x(rc);
x.BuildErrorMessage(this, m_hstmt);
@@ -1242,7 +1244,7 @@ void ODBConn::GetConnectInfo()
m_IDQuoteChar = ' ';
if (trace)
- htrc("DBMS: %s, Version: %s",
+ htrc("DBMS: %s, Version: %s\n",
GetStringInfo(SQL_DBMS_NAME), GetStringInfo(SQL_DBMS_VER));
} // end of GetConnectInfo
@@ -1511,14 +1513,16 @@ int ODBConn::PrepareSQL(char *sql)
hstmt = m_hstmt;
m_hstmt = NULL;
- ThrowDBX(MSG(SEQUENCE_ERROR));
- } else {
- rc = SQLAllocStmt(m_hdbc, &hstmt);
- if (!Check(rc))
- ThrowDBX(SQL_INVALID_HANDLE, "SQLAllocStmt");
+ if (m_Tdb->GetAmType() != TYPE_AM_XDBC)
+ ThrowDBX(MSG(SEQUENCE_ERROR));
- } // endif hstmt
+ } // endif m_hstmt
+
+ rc = SQLAllocStmt(m_hdbc, &hstmt);
+
+ if (!Check(rc))
+ ThrowDBX(SQL_INVALID_HANDLE, "SQLAllocStmt");
OnSetOptions(hstmt);
b = true;
@@ -1565,7 +1569,7 @@ int ODBConn::PrepareSQL(char *sql)
/***********************************************************************/
/* Execute a prepared statement. */
/***********************************************************************/
-int ODBConn::ExecuteSQL(bool x)
+int ODBConn::ExecuteSQL(void)
{
PGLOBAL& g = m_G;
SWORD ncol = 0;
@@ -1580,26 +1584,17 @@ int ODBConn::ExecuteSQL(bool x)
if (!Check(rc))
ThrowDBX(rc, "SQLExecute", m_hstmt);
- if (!Check(SQLNumResultCols(m_hstmt, &ncol)))
+ if (!Check(rc = SQLNumResultCols(m_hstmt, &ncol)))
ThrowDBX(rc, "SQLNumResultCols", m_hstmt);
if (ncol) {
- if (x) {
- afrw = ncol;
- strcpy(g->Message, "Result set column number");
- } else {
- // This should never happen while inserting
- strcpy(g->Message, "Logical error while inserting");
- } // endif ncol
-
+ // This should never happen while inserting
+ strcpy(g->Message, "Logical error while inserting");
} else {
// Insert, Update or Delete statement
- if (!Check(SQLRowCount(m_hstmt, &afrw)))
+ if (!Check(rc = SQLRowCount(m_hstmt, &afrw)))
ThrowDBX(rc, "SQLRowCount", m_hstmt);
- if (x)
- strcpy(g->Message, "Affected rows");
-
} // endif ncol
} catch(DBX *x) {
@@ -1613,6 +1608,7 @@ int ODBConn::ExecuteSQL(bool x)
m_Transact = false;
} // endif m_Transact
+ afrw = -1;
} // end try/catch
return (int)afrw;
@@ -1667,6 +1663,112 @@ bool ODBConn::BindParam(ODBCCOL *colp)
return false;
} // end of BindParam
+/***********************************************************************/
+/* Execute an SQL command. */
+/***********************************************************************/
+bool ODBConn::ExecSQLcommand(char *sql)
+ {
+ char cmd[16];
+ bool b, rcd = false;
+ UINT txn = 0;
+ PGLOBAL& g = m_G;
+ SWORD ncol = 0;
+ SQLLEN afrw;
+ RETCODE rc;
+ HSTMT hstmt;
+
+ try {
+ b = FALSE;
+
+ // Check whether we should use transaction
+ if (sscanf(sql, " %15s ", cmd) == 1) {
+ if (!stricmp(cmd, "INSERT") || !stricmp(cmd, "UPDATE") ||
+ !stricmp(cmd, "DELETE") || !stricmp(cmd, "REPLACE")) {
+ // Does the data source support transactions
+ rc = SQLGetInfo(m_hdbc, SQL_TXN_CAPABLE, &txn, 0, NULL);
+
+ if (Check(rc) && txn != SQL_TC_NONE) {
+ rc = SQLSetConnectAttr(m_hdbc, SQL_ATTR_AUTOCOMMIT,
+ SQL_AUTOCOMMIT_OFF, SQL_IS_UINTEGER);
+
+ if (!Check(rc))
+ ThrowDBX(SQL_INVALID_HANDLE, "SQLSetConnectAttr");
+
+ m_Transact = TRUE;
+ } // endif txn
+
+ } // endif cmd
+
+ } // endif sql
+
+ // Allocate the statement handle
+ rc = SQLAllocStmt(m_hdbc, &hstmt);
+
+ if (!Check(rc))
+ ThrowDBX(SQL_INVALID_HANDLE, "SQLAllocStmt");
+
+ OnSetOptions(hstmt);
+ b = true;
+
+ if (trace)
+ htrc("ExecSQLcommand hstmt=%p %.64s\n", hstmt, sql);
+
+ // Proceed with command execution
+ do {
+ rc = SQLExecDirect(hstmt, (PUCHAR)sql, SQL_NTS);
+ } while (rc == SQL_STILL_EXECUTING);
+
+ if (!Check(rc))
+ ThrowDBX(rc, "SQLExecDirect", hstmt);
+
+ // Check whether this is a query returning a result set
+ if (!Check(rc = SQLNumResultCols(hstmt, &ncol)))
+ ThrowDBX(rc, "SQLNumResultCols", hstmt);
+
+ if (!ncol) {
+ if (!Check(SQLRowCount(hstmt, &afrw)))
+ ThrowDBX(rc, "SQLRowCount", hstmt);
+
+ m_Tdb->AftRows = (int)afrw;
+ strcpy(g->Message, "Affected rows");
+ } else {
+ m_Tdb->AftRows = (int)ncol;
+ strcpy(g->Message, "Result set column number");
+ } // endif ncol
+
+ } catch(DBX *x) {
+ if (trace)
+ for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
+ htrc(x->m_ErrMsg[i]);
+
+ strcpy(g->Message, x->GetErrorMessage(0));
+
+ if (b)
+ SQLCancel(hstmt);
+
+ m_Tdb->AftRows = -1;
+ rcd = true;
+ } // end try/catch
+
+ if (!Check(rc = SQLFreeStmt(hstmt, SQL_CLOSE)))
+ sprintf(g->Message, "SQLFreeStmt: rc=%d", rc);
+
+ if (m_Transact) {
+ // Terminate the transaction
+ if (!Check(rc = SQLEndTran(SQL_HANDLE_DBC, m_hdbc,
+ (rcd) ? SQL_ROLLBACK : SQL_COMMIT)))
+ sprintf(g->Message, "SQLEndTran: rc=%d", rc);
+
+ if (!Check(rc = SQLSetConnectAttr(m_hdbc, SQL_ATTR_AUTOCOMMIT,
+ (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_IS_UINTEGER)))
+ sprintf(g->Message, "SQLSetConnectAttr: rc=%d", rc);
+
+ m_Transact = false;
+ } // endif m_Transact
+
+ return rcd;
+ } // end of ExecSQLcommand
+
/**************************************************************************/
/* GetMetaData: constructs the result blocks containing the */
/* description of all the columns of an SQL command. */
diff --git a/storage/connect/odbconn.h b/storage/connect/odbconn.h
index 448ce2d428f..b747a07f439 100644
--- a/storage/connect/odbconn.h
+++ b/storage/connect/odbconn.h
@@ -142,8 +142,9 @@ class ODBConn : public BLOCK {
int ExecDirectSQL(char *sql, ODBCCOL *tocols);
int Fetch(void);
int PrepareSQL(char *sql);
- int ExecuteSQL(bool x);
+ int ExecuteSQL(void);
bool BindParam(ODBCCOL *colp);
+ bool ExecSQLcommand(char *sql);
int GetCatInfo(CATPARM *cap);
bool GetDataSources(PQRYRES qrp);
bool GetDrivers(PQRYRES qrp);
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h
index 550153921a5..0b8c7122192 100644
--- a/storage/connect/plgdbsem.h
+++ b/storage/connect/plgdbsem.h
@@ -106,13 +106,20 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_DOM = 80, /* DOM access method type no */
TYPE_AM_DIR = 90, /* DIR access method type no */
TYPE_AM_ODBC = 100, /* ODBC access method type no */
+ TYPE_AM_XDBC = 101, /* XDBC access method type no */
TYPE_AM_OEM = 110, /* OEM access method type no */
TYPE_AM_TBL = 115, /* TBL access method type no */
TYPE_AM_PIVOT = 120, /* PIVOT access method type no */
TYPE_AM_SRC = 121, /* PIVOT multiple column type no */
TYPE_AM_FNC = 122, /* PIVOT source column type no */
+ TYPE_AM_XCOL = 124, /* XCOL access method type no */
TYPE_AM_XML = 127, /* XML access method type no */
+ TYPE_AM_OCCUR = 128, /* OCCUR access method type no */
+ TYPE_AM_PRX = 129, /* PROXY access method type no */
TYPE_AM_XTB = 130, /* SYS table access method type */
+ TYPE_AM_BLK = 131, /* BLK access method type no */
+ TYPE_AM_ZIP = 132, /* ZIP access method type no */
+ TYPE_AM_ZLIB = 133, /* ZLIB access method type no */
TYPE_AM_MAC = 137, /* MAC table access method type */
TYPE_AM_WMI = 139, /* WMI table access method type */
TYPE_AM_XCL = 140, /* SYS column access method type */
@@ -123,7 +130,8 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_DMY = 172, /* DMY Dummy tables am type no */
TYPE_AM_SET = 180, /* SET Set tables am type no */
TYPE_AM_MYSQL = 192, /* MYSQL access method type no */
- TYPE_AM_CAT = 193, /* Catalog access method type no */
+ TYPE_AM_MYX = 193, /* MYSQL EXEC access method type */
+ TYPE_AM_CAT = 195, /* Catalog access method type no */
TYPE_AM_OUT = 200}; /* Output relations (storage) */
enum RECFM {RECFM_NAF = -2, /* Not a file */
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index f37cb6d349e..d1f3d90fade 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -355,7 +355,9 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
if ((Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL)))
Isview = TRUE;
+ // Specific for command executing tables
Xsrc = Cat->GetBoolCatInfo("Execsrc", FALSE);
+ Mxr = Cat->GetIntCatInfo("Maxerr", 0);
return FALSE;
} // end of DefineAM
@@ -516,7 +518,7 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g)
strcat(strcat(strcat(strcat(Query, " FROM "), tk), Tabname), tk);
if (To_Filter)
- strcat(strcat(Query, " WHERE "), To_Filter);
+ strcat(strcat(Query, " WHERE "), To_Filter->Body);
if (trace)
htrc("Query=%s\n", Query);
@@ -1294,8 +1296,30 @@ void MYSQLCOL::WriteColumn(PGLOBAL g)
/* ------------------------------------------------------------------- */
/***********************************************************************/
-/* Implementation of the TDBMYSQL class. */
+/* Implementation of the TDBMYEXC class. */
/***********************************************************************/
+TDBMYEXC::TDBMYEXC(PMYDEF tdp) : TDBMYSQL(tdp)
+{
+ Cmdlist = NULL;
+ Cmdcol = NULL;
+ Shw = false;
+ Havew = false;
+ Isw = false;
+ Warnings = 0;
+ Mxr = tdp->Mxr;
+ Nerr = 0;
+} // end of TDBMYEXC constructor
+
+TDBMYEXC::TDBMYEXC(PGLOBAL g, PTDBMYX tdbp) : TDBMYSQL(g, tdbp)
+{
+ Cmdlist = tdbp->Cmdlist;
+ Cmdcol = tdbp->Cmdcol;
+ Shw = tdbp->Shw;
+ Havew = tdbp->Havew;
+ Isw = tdbp->Isw;
+ Mxr = tdbp->Mxr;
+ Nerr = tdbp->Nerr;
+} // end of TDBMYEXC copy constructor
// Is this really useful ???
PTDB TDBMYEXC::CopyOne(PTABS t)
@@ -1331,23 +1355,15 @@ PCOL TDBMYEXC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/
/* MakeCMD: make the SQL statement to send to MYSQL connection. */
/***********************************************************************/
-char *TDBMYEXC::MakeCMD(PGLOBAL g)
+PCMD TDBMYEXC::MakeCMD(PGLOBAL g)
{
- char *xcmd = NULL;
+ PCMD xcmd = NULL;
if (To_Filter) {
if (Cmdcol) {
- char col[128], cmd[1024];
- int n;
-
- memset(cmd, 0, sizeof(cmd));
- n = sscanf(To_Filter, "%s = '%1023c", col, cmd);
-
- if (n == 2 && !stricmp(col, Cmdcol)) {
- xcmd = (char*)PlugSubAlloc(g, NULL, strlen(cmd) + 1);
-
- strcpy(xcmd, cmd);
- xcmd[strlen(xcmd) - 1] = 0;
+ if (!stricmp(Cmdcol, To_Filter->Body) &&
+ (To_Filter->Op == OP_EQ || To_Filter->Op == OP_IN)) {
+ xcmd = To_Filter->Cmds;
} else
strcpy(g->Message, "Invalid command specification filter");
@@ -1357,7 +1373,7 @@ char *TDBMYEXC::MakeCMD(PGLOBAL g)
} else if (!Srcdef)
strcpy(g->Message, "No Srcdef default command");
else
- xcmd = Srcdef;
+ xcmd = new(g) CMD(g, Srcdef);
return xcmd;
} // end of MakeCMD
@@ -1368,7 +1384,7 @@ char *TDBMYEXC::MakeCMD(PGLOBAL g)
int TDBMYEXC::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
- MaxSize = 1;
+ MaxSize = 10; // a guess
} // endif MaxSize
return MaxSize;
@@ -1379,8 +1395,6 @@ int TDBMYEXC::GetMaxSize(PGLOBAL g)
/***********************************************************************/
bool TDBMYEXC::OpenDB(PGLOBAL g)
{
- int rc;
-
if (Use == USE_OPEN) {
strcpy(g->Message, "Multiple execution is not allowed");
return true;
@@ -1407,20 +1421,11 @@ bool TDBMYEXC::OpenDB(PGLOBAL g)
/*********************************************************************/
/* Get the command to execute. */
/*********************************************************************/
- if (!(Query = MakeCMD(g))) {
+ if (!(Cmdlist = MakeCMD(g))) {
Myc.Close();
return true;
} // endif Query
- if ((rc = Myc.ExecSQL(g, Query)) == RC_NF) {
- strcpy(g->Message, "Affected rows");
- AftRows = Myc.m_Rows;
- } else if (rc == RC_OK) {
- sprintf(g->Message, "Columns and %d rows", Myc.m_Rows);
- AftRows = Myc.m_Fields;
- } else
- return true;
-
return false;
} // end of OpenDB
@@ -1429,7 +1434,54 @@ bool TDBMYEXC::OpenDB(PGLOBAL g)
/***********************************************************************/
int TDBMYEXC::ReadDB(PGLOBAL g)
{
- return (++N) ? RC_EF : RC_OK;
+ if (Havew) {
+ // Process result set from SHOW WARNINGS
+ if (Myc.Fetch(g, -1) != RC_OK) {
+ Myc.FreeResult();
+ Havew = Isw = false;
+ } else {
+ N++;
+ Isw = true;
+ return RC_OK;
+ } // endif Fetch
+
+ } // endif m_Res
+
+ if (Cmdlist) {
+ // Process query to send
+ int rc;
+
+ do {
+ Query = Cmdlist->Cmd;
+
+ switch (rc = Myc.ExecSQLcmd(g, Query, &Warnings)) {
+ case RC_NF:
+ AftRows = Myc.m_Afrw;
+ strcpy(g->Message, "Affected rows");
+ break;
+ case RC_OK:
+ AftRows = Myc.m_Fields;
+ strcpy(g->Message, "Result set columns");
+ break;
+ case RC_FX:
+ AftRows = Myc.m_Afrw;
+ Nerr++;
+ break;
+ case RC_INFO:
+ Shw = true;
+ } // endswitch rc
+
+ Cmdlist = (Nerr > Mxr) ? NULL : Cmdlist->Next;
+ } while (rc == RC_INFO);
+
+ if (Shw && Warnings)
+ Havew = (Myc.ExecSQL(g, "SHOW WARNINGS") == RC_OK);
+
+ ++N;
+ return RC_OK;
+ } else
+ return RC_EF;
+
} // end of ReadDB
/***********************************************************************/
@@ -1480,12 +1532,23 @@ void MYXCOL::ReadColumn(PGLOBAL g)
{
PTDBMYX tdbp = (PTDBMYX)To_Tdb;
- switch (Flag) {
- case 0: Value->SetValue_psz(tdbp->Query); break;
- case 1: Value->SetValue(tdbp->AftRows); break;
- case 2: Value->SetValue_psz(g->Message); break;
- default: Value->SetValue_psz("Invalid Flag"); break;
- } // endswitch Flag
+ if (tdbp->Isw) {
+ char *buf = NULL;
+
+ if (Flag < 3) {
+ buf = tdbp->Myc.GetCharField(Flag);
+ Value->SetValue_psz(buf);
+ } else
+ Value->Reset();
+
+ } else
+ switch (Flag) {
+ case 0: Value->SetValue_psz(tdbp->Query); break;
+ case 1: Value->SetValue(tdbp->AftRows); break;
+ case 2: Value->SetValue_psz(g->Message); break;
+ case 3: Value->SetValue(tdbp->Warnings); break;
+ default: Value->SetValue_psz("Invalid Flag"); break;
+ } // endswitch Flag
} // end of ReadColumn
diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h
index bcac10dcaa7..70c75506470 100644
--- a/storage/connect/tabmysql.h
+++ b/storage/connect/tabmysql.h
@@ -20,6 +20,7 @@ typedef class MYSQLC *PMYC;
/***********************************************************************/
class MYSQLDEF : public TABDEF {/* Logical table description */
friend class TDBMYSQL;
+ friend class TDBMYEXC;
friend class TDBMCL;
friend class ha_connect;
public:
@@ -53,6 +54,7 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
PSZ Password; /* Password logon info */
PSZ Server; /* PServerID */
int Portnumber; /* MySQL port number (0 = default) */
+ int Mxr; /* Maxerr for an Exec table */
bool Isview; /* TRUE if this table is a MySQL view */
bool Bind; /* Use prepared statement on insert */
bool Delayed; /* Delayed insert */
@@ -167,13 +169,12 @@ class MYSQLCOL : public COLBLK {
class TDBMYEXC : public TDBMYSQL {
friend class MYXCOL;
public:
- // Constructor
- TDBMYEXC(PMYDEF tdp) : TDBMYSQL(tdp) {Cmdcol = NULL;}
- TDBMYEXC(PGLOBAL g, PTDBMYX tdbp) : TDBMYSQL(g, tdbp)
- {Cmdcol = tdbp->Cmdcol;}
+ // Constructors
+ TDBMYEXC(PMYDEF tdp);
+ TDBMYEXC(PGLOBAL g, PTDBMYX tdbp);
// Implementation
-//virtual AMT GetAmType(void) {return TYPE_AM_MYSQL;}
+ virtual AMT GetAmType(void) {return TYPE_AM_MYX;}
virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBMYEXC(g, this);}
// Methods
@@ -203,13 +204,20 @@ class TDBMYEXC : public TDBMYSQL {
protected:
// Internal functions
- char *MakeCMD(PGLOBAL g);
+ PCMD MakeCMD(PGLOBAL g);
//bool MakeSelect(PGLOBAL g);
//bool MakeInsert(PGLOBAL g);
//int BindColumns(PGLOBAL g);
// Members
+ PCMD Cmdlist; // The commands to execute
char *Cmdcol; // The name of the Xsrc command column
+ bool Shw; // Show warnings
+ bool Havew; // True when processing warnings
+ bool Isw; // True for warning lines
+ int Warnings; // Warnings number
+ int Mxr; // Maximum errors before closing
+ int Nerr; // Number of errors so far
}; // end of class TDBMYEXC
/***********************************************************************/
diff --git a/storage/connect/taboccur.h b/storage/connect/taboccur.h
index 6cfece5634e..0bee074234c 100644
--- a/storage/connect/taboccur.h
+++ b/storage/connect/taboccur.h
@@ -3,8 +3,6 @@
#include "tabutil.h"
-#define TYPE_AM_OCCUR (AMT)128
-
typedef class OCCURDEF *POCCURDEF;
typedef class TDBOCCUR *PTDBOCCUR;
typedef class OCCURCOL *POCCURCOL;
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index d9d794ef4e4..bf0216d52eb 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -110,6 +110,7 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Qchar = Cat->GetStringCatInfo(g, "Qchar", "");
Catver = Cat->GetIntCatInfo("Catver", 2);
Xsrc = Cat->GetBoolCatInfo("Execsrc", FALSE);
+ Mxr = Cat->GetIntCatInfo("Maxerr", 0);
Options = ODBConn::noOdbcDialog;
Pseudo = 2; // FILID is Ok but not ROWID
return false;
@@ -395,7 +396,7 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
// Below 14 is length of 'select ' + length of ' from ' + 1
len = (strlen(colist) + strlen(buf) + 14);
- len += (To_Filter ? strlen(To_Filter) + 7 : 0);
+ len += (To_Filter ? strlen(To_Filter->Body) + 7 : 0);
// if (tablep->GetQualifier()) This is used when using a table
// qualp = tablep->GetQualifier(); from anotherPlugDB database but
@@ -432,7 +433,7 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
strcat(sql, tabname);
if (To_Filter)
- strcat(strcat(sql, " WHERE "), To_Filter);
+ strcat(strcat(sql, " WHERE "), To_Filter->Body);
return sql;
} // end of MakeSQL
@@ -720,7 +721,7 @@ int TDBODBC::ReadDB(PGLOBAL g)
/***********************************************************************/
int TDBODBC::WriteDB(PGLOBAL g)
{
- int n = Ocp->ExecuteSQL(false);
+ int n = Ocp->ExecuteSQL();
if (n < 0) {
AftRows = n;
@@ -1004,6 +1005,22 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
/***********************************************************************/
/* Implementation of the TDBODBC class. */
/***********************************************************************/
+TDBXDBC::TDBXDBC(PODEF tdp) : TDBODBC(tdp)
+{
+ Cmdlist = NULL;
+ Cmdcol = NULL;
+ Mxr = tdp->Mxr;
+ Nerr = 0;
+} // end of TDBXDBC constructor
+
+TDBXDBC::TDBXDBC(PTDBXDBC tdbp) : TDBODBC(tdbp)
+{
+ Cmdlist = tdbp->Cmdlist;
+ Cmdcol = tdbp->Cmdcol;
+ Mxr = tdbp->Mxr;
+ Nerr = tdbp->Nerr;
+} // end of TDBXDBC copy constructor
+
PTDB TDBXDBC::CopyOne(PTABS t)
{
PTDB tp;
@@ -1036,23 +1053,15 @@ PCOL TDBXDBC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/
/* MakeCMD: make the SQL statement to send to ODBC connection. */
/***********************************************************************/
-char *TDBXDBC::MakeCMD(PGLOBAL g)
+PCMD TDBXDBC::MakeCMD(PGLOBAL g)
{
- char *xcmd = NULL;
+ PCMD xcmd = NULL;
if (To_Filter) {
if (Cmdcol) {
- char col[128], cmd[1024];
- int n;
-
- memset(cmd, 0, sizeof(cmd));
- n = sscanf(To_Filter, "%s = '%1023c", col, cmd);
-
- if (n == 2 && !stricmp(col, Cmdcol)) {
- xcmd = (char*)PlugSubAlloc(g, NULL, strlen(cmd) + 1);
-
- strcpy(xcmd, cmd);
- xcmd[strlen(xcmd) - 1] = 0;
+ if (!stricmp(Cmdcol, To_Filter->Body) &&
+ (To_Filter->Op == OP_EQ || To_Filter->Op == OP_IN)) {
+ xcmd = To_Filter->Cmds;
} else
strcpy(g->Message, "Invalid command specification filter");
@@ -1062,7 +1071,7 @@ char *TDBXDBC::MakeCMD(PGLOBAL g)
} else if (!Srcdef)
strcpy(g->Message, "No Srcdef default command");
else
- xcmd = Srcdef;
+ xcmd = new(g) CMD(g, Srcdef);
return xcmd;
} // end of MakeCMD
@@ -1088,12 +1097,12 @@ bool TDBXDBC::BindParameters(PGLOBAL g)
#endif // 0
/***********************************************************************/
-/* XDBC GetMaxSize: returns table size (always one row). */
+/* XDBC GetMaxSize: returns table size (not always one row). */
/***********************************************************************/
int TDBXDBC::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0)
- MaxSize = 1;
+ MaxSize = 10; // Just a guess
return MaxSize;
} // end of GetMaxSize
@@ -1142,19 +1151,12 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
/*********************************************************************/
/* Get the command to execute. */
/*********************************************************************/
- if (!(Query = MakeCMD(g))) {
+ if (!(Cmdlist = MakeCMD(g))) {
Ocp->Close();
return true;
} // endif Query
Rows = 1;
-
- if (Ocp->PrepareSQL(Query)) {
- strcpy(g->Message, "Parameters not supported");
- AftRows = -1;
- } else
- AftRows = 0;
-
return false;
} // end of OpenDB
@@ -1163,18 +1165,18 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
/***********************************************************************/
int TDBXDBC::ReadDB(PGLOBAL g)
{
- if (trace)
- htrc("XDBC ReadDB: query=%s\n", SVP(Query));
+ if (Cmdlist) {
+ Query = Cmdlist->Cmd;
- if (Rows--) {
- if (!AftRows)
- AftRows = Ocp->ExecuteSQL(true);
+ if (Ocp->ExecSQLcommand(Query))
+ Nerr++;
- } else
+ Fpos++; // Used for progress info
+ Cmdlist = (Nerr > Mxr) ? NULL : Cmdlist->Next;
+ return RC_OK;
+ } else
return RC_EF;
- Fpos++; // Used for progress info
- return RC_OK;
} // end of ReadDB
/***********************************************************************/
diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h
index b3577bce5be..f5a3098e843 100644
--- a/storage/connect/tabodbc.h
+++ b/storage/connect/tabodbc.h
@@ -52,6 +52,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
PSZ Qchar; /* Identifier quoting character */
int Catver; /* ODBC version for catalog functions */
int Options; /* Open connection options */
+ int Mxr; /* Maxerr for an Exec table */
bool Xsrc; /* Execution type */
}; // end of ODBCDEF
@@ -179,12 +180,12 @@ class TDBXDBC : public TDBODBC {
friend class XSRCCOL;
friend class ODBConn;
public:
- // Constructor
- TDBXDBC(PODEF tdp = NULL) : TDBODBC(tdp) {Cmdcol = NULL;}
- TDBXDBC(PTDBXDBC tdbp) : TDBODBC(tdbp) {Cmdcol = tdbp->Cmdcol;}
+ // Constructors
+ TDBXDBC(PODEF tdp = NULL);
+ TDBXDBC(PTDBXDBC tdbp);
// Implementation
-//virtual AMT GetAmType(void) {return TYPE_AM_ODBC;}
+ virtual AMT GetAmType(void) {return TYPE_AM_XDBC;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBXDBC(this);}
@@ -209,11 +210,14 @@ class TDBXDBC : public TDBODBC {
protected:
// Internal functions
- char *MakeCMD(PGLOBAL g);
+ PCMD MakeCMD(PGLOBAL g);
//bool BindParameters(PGLOBAL g);
// Members
+ PCMD Cmdlist; // The commands to execute
char *Cmdcol; // The name of the Xsrc command column
+ int Mxr; // Maximum errors before closing
+ int Nerr; // Number of errors so far
}; // end of class TDBXDBC
/***********************************************************************/
diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp
index 2ed6c150d85..56305871c69 100644
--- a/storage/connect/tabtbl.cpp
+++ b/storage/connect/tabtbl.cpp
@@ -295,15 +295,18 @@ bool TDBTBL::InitTableList(PGLOBAL g)
/***********************************************************************/
bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTABLE tabp)
{
- char *fil, op[8], tn[NAME_LEN];
+ char *body, *fil, op[8], tn[NAME_LEN];
bool neg;
if (!filp)
return TRUE;
- else if (strstr(filp, " OR ") || strstr(filp, " AND "))
+ else
+ body = filp->Body;
+
+ if (strstr(body, " OR ") || strstr(body, " AND "))
return TRUE; // Not handled yet
else
- fil = filp + (*filp == '(' ? 1 : 0);
+ fil = body + (*body == '(' ? 1 : 0);
if (sscanf(fil, "TABID %s", op) != 1)
return TRUE; // ignore invalid filter
diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h
index a6202950390..7b2161a4b8b 100644
--- a/storage/connect/tabutil.h
+++ b/storage/connect/tabutil.h
@@ -6,8 +6,6 @@
//#include "tabtbl.h"
-#define TYPE_AM_PRX (AMT)129
-
typedef class PRXDEF *PPRXDEF;
typedef class TDBPRX *PTDBPRX;
typedef class XXLCOL *PXXLCOL;
diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp
index 1c626a06256..7926505e672 100644
--- a/storage/connect/tabwmi.cpp
+++ b/storage/connect/tabwmi.cpp
@@ -480,18 +480,19 @@ bool TDBWMI::Initialize(PGLOBAL g)
/***********************************************************************/
void TDBWMI::DoubleSlash(PGLOBAL g)
{
- if (To_Filter && strchr(To_Filter, '\\')) {
- char *buf = (char*)PlugSubAlloc(g, NULL, strlen(To_Filter) * 2);
+ if (To_Filter && strchr(To_Filter->Body, '\\')) {
+ char *body = To_Filter->Body;
+ char *buf = (char*)PlugSubAlloc(g, NULL, strlen(body) * 2);
int i = 0, k = 0;
do {
- if (To_Filter[i] == '\\')
+ if (body[i] == '\\')
buf[k++] = '\\';
- buf[k++] = To_Filter[i];
- } while (To_Filter[i++]);
+ buf[k++] = body[i];
+ } while (body[i++]);
- To_Filter = buf;
+ To_Filter->Body = buf;
} // endif To_Filter
} // end of DoubleSlash
@@ -539,13 +540,13 @@ char *TDBWMI::MakeWQL(PGLOBAL g)
// Below 14 is length of 'select ' + length of ' from ' + 1
len = (strlen(colist) + strlen(Wclass) + 14);
- len += (To_Filter ? strlen(To_Filter) + 7 : 0);
+ len += (To_Filter ? strlen(To_Filter->Body) + 7 : 0);
wql = (char*)PlugSubAlloc(g, NULL, len);
strcat(strcat(strcpy(wql, "SELECT "), colist), " FROM ");
strcat(wql, Wclass);
if (To_Filter)
- strcat(strcat(wql, " WHERE "), To_Filter);
+ strcat(strcat(wql, " WHERE "), To_Filter->Body);
return wql;
} // end of MakeWQL
diff --git a/storage/connect/tabxcl.h b/storage/connect/tabxcl.h
index 0189775cd8d..24122573100 100644
--- a/storage/connect/tabxcl.h
+++ b/storage/connect/tabxcl.h
@@ -3,8 +3,6 @@
#include "tabutil.h"
-#define TYPE_AM_XCOL (AMT)124
-
typedef class XCLDEF *PXCLDEF;
typedef class TDBXCL *PTDBXCL;
typedef class XCLCOL *PXCLCOL;
diff --git a/storage/connect/value.h b/storage/connect/value.h
index d94c1da6920..13ce1436b39 100644
--- a/storage/connect/value.h
+++ b/storage/connect/value.h
@@ -45,7 +45,7 @@ DllExport PSZ GetTypeName(int);
DllExport int GetTypeSize(int, int);
#ifdef ODBC_SUPPORT
/* This function is exported for use in EOM table type DLLs */
-DllExport int TranslateSQLType(int stp, int prec, int& len);
+DllExport int TranslateSQLType(int stp, int prec, int& len, char& v);
#endif
DllExport char *GetFormatType(int);
DllExport int GetFormatType(char);
diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h
index 98c7305acd4..e308dedb3e1 100644
--- a/storage/connect/xtable.h
+++ b/storage/connect/xtable.h
@@ -18,8 +18,28 @@
#include "colblk.h"
#include "m_ctype.h"
-//pedef class INDEXDEF *PIXDEF;
-typedef char *PFIL; // Specific to CONNECT
+typedef class CMD *PCMD;
+
+// Commands executed by XDBC and MYX tables
+class CMD : public BLOCK {
+ public:
+ // Constructor
+ CMD(PGLOBAL g, char *cmd) {
+ Cmd = (char*)PlugSubAlloc(g, NULL, strlen(cmd) + 1);
+ strcpy(Cmd, cmd); Next = NULL; }
+
+ // Members
+ PCMD Next;
+ char *Cmd;
+}; // end of class CMD
+
+// Filter passed all tables
+typedef struct _filter {
+ char *Body;
+ OPVAL Op;
+ PCMD Cmds;
+} FILTER, *PFIL;
+
typedef class TDBCAT *PTDBCAT;
typedef class CATCOL *PCATCOL;
@@ -39,24 +59,16 @@ class DllExport TBX: public BLOCK { // Base class for OPJOIN and TDB classes.
inline PFIL GetFilter(void) {return To_Filter;}
inline void SetOrig(PTBX txp) {To_Orig = txp;}
inline void SetFilter(PFIL fp) {To_Filter = fp;}
-//inline JTYPE GetJtype(void) {return Jtype;}
-//inline void SetJtype(JTYPE jt) {Jtype = jt;}
-//inline PFIL GetNoleft(void) {return To_Noleft;}
-//inline void SetNoleft(PFIL fp) {To_Noleft = fp;}
// Methods
virtual bool IsSame(PTBX tp) {return tp == this;}
-//virtual bool Include(PTBX tbxp) = 0;
-//virtual bool CheckFilter(void) = 0;
virtual int GetTdb_No(void) = 0; // Convenience during conversion
virtual PTDB GetNext(void) = 0;
-//virtual int GetMaxSame(PGLOBAL) = 0;
virtual int Cardinality(PGLOBAL) = 0;
virtual int GetMaxSize(PGLOBAL) = 0;
virtual int GetProgMax(PGLOBAL) = 0;
virtual int GetProgCur(void) = 0;
virtual int GetBadLines(void) {return 0;}
-//virtual bool IsJoin(void) = 0;
virtual PTBX Copy(PTABS t) = 0;
protected:
@@ -66,8 +78,6 @@ class DllExport TBX: public BLOCK { // Base class for OPJOIN and TDB classes.
// Members
PTBX To_Orig; // Pointer to original if it is a copy
PFIL To_Filter;
-//PFIL To_Noleft; // To filter not involved in LEFT JOIN
-//JTYPE Jtype;
TUSE Use;
}; // end of class TBX