mirror of
https://github.com/MariaDB/server.git
synced 2025-03-29 18:35:35 +01:00
- 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
This commit is contained in:
parent
f1325549e9
commit
056f35d0c1
24 changed files with 485 additions and 196 deletions
|
@ -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,
|
||||
¬_used_1, ¬_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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue