Commit 056f35d0 authored by Olivier Bertrand's avatar Olivier Bertrand

- 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
parent f1325549
......@@ -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. */
/***********************************************************************/
......
......@@ -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;
......
......@@ -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
......
......@@ -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();
......@@ -778,6 +786,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. */
/***********************************************************************/
......
......@@ -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
......@@ -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
......
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;
......
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;
......
......@@ -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)";
......
/***********************************************************************/
/* 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
......@@ -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. */
......
......@@ -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);
......
......@@ -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 */
......
......@@ -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
......
......@@ -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
/***********************************************************************/
......
......@@ -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;
......
......@@ -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
/***********************************************************************/
......
......@@ -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
/***********************************************************************/
......
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
......
......@@ -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);
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment