1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

Merge 10.0-connect -> 10.0

This commit is contained in:
Alexander Barkov
2013-12-03 14:12:53 +04:00
69 changed files with 3392 additions and 1765 deletions

View File

@@ -166,6 +166,7 @@ my $DEFAULT_SUITES= join(',', map { "$_-" } qw(
main main
archive archive
binlog binlog
connect
csv csv
federated federated
funcs_1 funcs_1
@@ -380,7 +381,6 @@ sub main {
mtr_report("Logging: $0 ", join(" ", @ARGV)); mtr_report("Logging: $0 ", join(" ", @ARGV));
$DEFAULT_SUITES.= ',' . join(',', qw( $DEFAULT_SUITES.= ',' . join(',', qw(
connect
query_response_time query_response_time
sequence sequence
spider spider

View File

@@ -264,6 +264,19 @@ int main() {
ENDIF(UNIX) ENDIF(UNIX)
ENDIF(CONNECT_WITH_ODBC) ENDIF(CONNECT_WITH_ODBC)
#
# Installing tests
#
IF(INSTALL_MYSQLTESTDIR)
INSTALL(
DIRECTORY mysql-test/connect
DESTINATION ${INSTALL_MYSQLTESTDIR}/suite
USE_SOURCE_PERMISSIONS
COMPONENT Test
PATTERN "*~" EXCLUDE
)
ENDIF()
# #
# Plugin definition # Plugin definition

View File

@@ -164,8 +164,7 @@ bool COLBLK::CheckSort(PTDB tdbp)
/* Now we use Format.Length for the len parameter to avoid strings */ /* Now we use Format.Length for the len parameter to avoid strings */
/* to be truncated when converting from string to coded string. */ /* to be truncated when converting from string to coded string. */
/* Added in version 1.5 is the arguments GetPrecision() and Domain */ /* Added in version 1.5 is the arguments GetPrecision() and Domain */
/* in calling AllocateValue. Domain is used for TYPE_TOKEN only, */ /* in calling AllocateValue. Domain is used for TYPE_DATE only. */
/* but why was GetPrecision() not specified ? To be checked. */
/***********************************************************************/ /***********************************************************************/
bool COLBLK::InitValue(PGLOBAL g) bool COLBLK::InitValue(PGLOBAL g)
{ {
@@ -174,8 +173,7 @@ bool COLBLK::InitValue(PGLOBAL g)
// Allocate a Value object // Allocate a Value object
if (!(Value = AllocateValue(g, Buf_Type, Format.Length, if (!(Value = AllocateValue(g, Buf_Type, Format.Length,
GetPrecision(), GetDomain(), GetPrecision(), GetDomain())))
(To_Tdb) ? To_Tdb->GetCat() : NULL)))
return true; return true;
AddStatus(BUF_READY); AddStatus(BUF_READY);

View File

@@ -251,7 +251,7 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
return true; return true;
} // endif tdbp } // endif tdbp
tdbp->SetMode(mode); //tdbp->SetMode(mode); done in ha_connect::GetTDB
if (!c1) { if (!c1) {
if (mode == MODE_INSERT) if (mode == MODE_INSERT)
@@ -498,8 +498,8 @@ RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all)
if (!tdbp || tdbp->GetMode() != MODE_DELETE) if (!tdbp || tdbp->GetMode() != MODE_DELETE)
return RC_FX; return RC_FX;
// else else if (tdbp->IsReadOnly())
// ((PTDBDOX)tdbp)->SetModified(true); return RC_NF;
if (((PTDBASE)tdbp)->GetDef()->Indexable() && all) if (((PTDBASE)tdbp)->GetDef()->Indexable() && all)
((PTDBDOS)tdbp)->Cardinal= 0; ((PTDBDOS)tdbp)->Cardinal= 0;
@@ -518,17 +518,13 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp)
int rc= RC_OK; int rc= RC_OK;
TDBDOX *tbxp= NULL; TDBDOX *tbxp= NULL;
if (!tdbp) if (!tdbp || tdbp->GetUse() != USE_OPEN)
return rc; // Already done return rc; // Nothing to do
if (xtrace) if (xtrace)
printf("CntCloseTable: tdbp=%p mode=%d\n", tdbp, tdbp->GetMode()); printf("CntCloseTable: tdbp=%p mode=%d\n", tdbp, tdbp->GetMode());
/*********************************************************************/ if (tdbp->GetMode() == MODE_DELETE && tdbp->GetUse() == USE_OPEN)
/* This will close the table file(s) and also finalize write */
/* operations such as Insert, Update, or Delete. */
/*********************************************************************/
if (tdbp->GetMode() == MODE_DELETE)
rc= tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine rc= tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine
// Prepare error return // Prepare error return
@@ -543,6 +539,8 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp)
goto err; goto err;
} // endif } // endif
// This will close the table file(s) and also finalize write
// operations such as Insert, Update, or Delete.
tdbp->CloseDB(g); tdbp->CloseDB(g);
g->jump_level--; g->jump_level--;

View File

@@ -17,8 +17,6 @@ typedef class BLKFAM *PBLKFAM;
typedef class DOSDEF *PDOSDEF; typedef class DOSDEF *PDOSDEF;
typedef class TDBDOS *PTDBDOS; typedef class TDBDOS *PTDBDOS;
#define TYPE_AM_BLK (AMT)160
/***********************************************************************/ /***********************************************************************/
/* This is the base class for all file access method classes. */ /* This is the base class for all file access method classes. */
/***********************************************************************/ /***********************************************************************/

View File

@@ -91,7 +91,7 @@ typedef struct _vecheader {
/* Conversion of block values allowed conditionally for insert only. */ /* Conversion of block values allowed conditionally for insert only. */
/***********************************************************************/ /***********************************************************************/
PVBLK AllocValBlock(PGLOBAL, void *, int, int, int, int, PVBLK AllocValBlock(PGLOBAL, void *, int, int, int, int,
bool check = true, bool blank = true); bool check = true, bool blank = true, bool un = false);
/* -------------------------- Class VCTFAM --------------------------- */ /* -------------------------- Class VCTFAM --------------------------- */

View File

@@ -10,9 +10,6 @@
#include "zlib.h" #include "zlib.h"
#define TYPE_AM_ZIP (AMT)150
#define TYPE_AM_ZLIB (AMT)155
typedef class ZIPFAM *PZIPFAM; typedef class ZIPFAM *PZIPFAM;
typedef class ZBKFAM *PZBKFAM; typedef class ZBKFAM *PZBKFAM;
typedef class ZIXFAM *PZIXFAM; typedef class ZIXFAM *PZIXFAM;

View File

@@ -165,7 +165,7 @@ extern "C" char nmfile[];
extern "C" char pdebug[]; extern "C" char pdebug[];
extern "C" { extern "C" {
char version[]= "Version 1.01.0008 August 18, 2013"; char version[]= "Version 1.01.0009 October 29, 2013";
#if defined(XMSG) #if defined(XMSG)
char msglang[]; // Default message language char msglang[]; // Default message language
@@ -183,7 +183,7 @@ ulong ha_connect::num= 0;
//int DTVAL::Shift= 0; //int DTVAL::Shift= 0;
static PCONNECT GetUser(THD *thd, PCONNECT xp); static PCONNECT GetUser(THD *thd, PCONNECT xp);
static PGLOBAL GetPlug(THD *thd, PCONNECT lxp); static PGLOBAL GetPlug(THD *thd, PCONNECT& lxp);
static handler *connect_create_handler(handlerton *hton, static handler *connect_create_handler(handlerton *hton,
TABLE_SHARE *table, TABLE_SHARE *table,
@@ -258,17 +258,21 @@ ha_create_table_option connect_field_option_list[]=
/***********************************************************************/ /***********************************************************************/
/* Push G->Message as a MySQL warning. */ /* Push G->Message as a MySQL warning. */
/***********************************************************************/ /***********************************************************************/
bool PushWarning(PGLOBAL g, PTDBASE tdbp) bool PushWarning(PGLOBAL g, PTDBASE tdbp, int level)
{ {
PHC phc; PHC phc;
THD *thd; THD *thd;
MYCAT *cat= (MYCAT*)tdbp->GetDef()->GetCat(); MYCAT *cat= (MYCAT*)tdbp->GetDef()->GetCat();
Sql_condition::enum_warning_level wlvl;
if (!cat || !(phc= cat->GetHandler()) || !phc->GetTable() || if (!cat || !(phc= cat->GetHandler()) || !phc->GetTable() ||
!(thd= (phc->GetTable())->in_use)) !(thd= (phc->GetTable())->in_use))
return true; return true;
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); //push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
wlvl= (Sql_condition::enum_warning_level)level;
push_warning(thd, wlvl, 0, g->Message);
return false; return false;
} // end of PushWarning } // end of PushWarning
@@ -552,7 +556,7 @@ static PCONNECT GetUser(THD *thd, PCONNECT xp)
/****************************************************************************/ /****************************************************************************/
/* Get the global pointer of the user of this handler. */ /* Get the global pointer of the user of this handler. */
/****************************************************************************/ /****************************************************************************/
static PGLOBAL GetPlug(THD *thd, PCONNECT lxp) static PGLOBAL GetPlug(THD *thd, PCONNECT& lxp)
{ {
lxp= GetUser(thd, lxp); lxp= GetUser(thd, lxp);
return (lxp) ? lxp->g : NULL; return (lxp) ? lxp->g : NULL;
@@ -659,6 +663,8 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
opval= (char*)options->colist; opval= (char*)options->colist;
else if (!stricmp(opname, "Data_charset")) else if (!stricmp(opname, "Data_charset"))
opval= (char*)options->data_charset; opval= (char*)options->data_charset;
else if (!stricmp(opname, "Query_String"))
opval= thd_query_string(table->in_use)->str;
if (!opval && options && options->oplist) if (!opval && options && options->oplist)
opval= GetListOption(xp->g, opname, options->oplist); opval= GetListOption(xp->g, opname, options->oplist);
@@ -1096,19 +1102,20 @@ PTDB ha_connect::GetTDB(PGLOBAL g)
&& (tdbp->GetMode() == xmod && (tdbp->GetMode() == xmod
|| tdbp->GetAmType() == TYPE_AM_XML)) { || tdbp->GetAmType() == TYPE_AM_XML)) {
tp= tdbp; tp= tdbp;
tp->SetMode(xmod); // tp->SetMode(xmod);
} else if ((tp= CntGetTDB(g, table_name, xmod, this))) } else if ((tp= CntGetTDB(g, table_name, xmod, this)))
valid_query_id= xp->last_query_id; valid_query_id= xp->last_query_id;
else else
printf("GetTDB: %s\n", g->Message); printf("GetTDB: %s\n", g->Message);
tp->SetMode(xmod);
return tp; return tp;
} // end of GetTDB } // end of GetTDB
/****************************************************************************/ /****************************************************************************/
/* Open a CONNECT table, restricting column list if cols is true. */ /* Open a CONNECT table, restricting column list if cols is true. */
/****************************************************************************/ /****************************************************************************/
bool ha_connect::OpenTable(PGLOBAL g, bool del) int ha_connect::OpenTable(PGLOBAL g, bool del)
{ {
bool rc= false; bool rc= false;
char *c1= NULL, *c2=NULL; char *c1= NULL, *c2=NULL;
@@ -1116,11 +1123,11 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del)
// Double test to be on the safe side // Double test to be on the safe side
if (!g || !table) { if (!g || !table) {
printf("OpenTable logical error; g=%p table=%p\n", g, table); printf("OpenTable logical error; g=%p table=%p\n", g, table);
return true; return HA_ERR_INITIALIZATION;
} // endif g } // endif g
if (!(tdbp= GetTDB(g))) if (!(tdbp= GetTDB(g)))
return true; return RC_FX;
else if (tdbp->IsReadOnly()) else if (tdbp->IsReadOnly())
switch (xmod) { switch (xmod) {
case MODE_WRITE: case MODE_WRITE:
@@ -1128,7 +1135,7 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del)
case MODE_UPDATE: case MODE_UPDATE:
case MODE_DELETE: case MODE_DELETE:
strcpy(g->Message, MSG(READ_ONLY)); strcpy(g->Message, MSG(READ_ONLY));
return true; return HA_ERR_TABLE_READONLY;
default: default:
break; break;
} // endswitch xmode } // endswitch xmode
@@ -1205,7 +1212,7 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del)
valid_info= false; valid_info= false;
} // endif rc } // endif rc
return rc; return (rc) ? HA_ERR_INITIALIZATION : 0;
} // end of OpenTable } // end of OpenTable
@@ -1239,15 +1246,16 @@ int ha_connect::CloseTable(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
int ha_connect::MakeRecord(char *buf) int ha_connect::MakeRecord(char *buf)
{ {
char *p, *fmt, val[32]; char *p, *fmt, val[32];
int rc= 0; int rc= 0;
Field* *field; Field* *field;
Field *fp; Field *fp;
my_bitmap_map *org_bitmap; my_bitmap_map *org_bitmap;
CHARSET_INFO *charset= tdbp->data_charset(); CHARSET_INFO *charset= tdbp->data_charset();
const MY_BITMAP *map; //MY_BITMAP readmap;
PVAL value; MY_BITMAP *map;
PCOL colp= NULL; PVAL value;
PCOL colp= NULL;
DBUG_ENTER("ha_connect::MakeRecord"); DBUG_ENTER("ha_connect::MakeRecord");
if (xtrace > 1) if (xtrace > 1)
@@ -1263,7 +1271,7 @@ int ha_connect::MakeRecord(char *buf)
memset(buf, 0, table->s->null_bytes); memset(buf, 0, table->s->null_bytes);
// When sorting read_set selects all columns, so we use def_read_set // When sorting read_set selects all columns, so we use def_read_set
map= (const MY_BITMAP *)&table->def_read_set; map= (MY_BITMAP *)&table->def_read_set;
// Make the pseudo record from field values // Make the pseudo record from field values
for (field= table->field; *field && !rc; field++) { for (field= table->field; *field && !rc; field++) {
@@ -1300,6 +1308,9 @@ int ha_connect::MakeRecord(char *buf)
case MYSQL_TYPE_TIME: case MYSQL_TYPE_TIME:
fmt= "%H:%M:%S"; fmt= "%H:%M:%S";
break; break;
case MYSQL_TYPE_YEAR:
fmt= "%Y";
break;
default: default:
fmt= "%Y-%m-%d %H:%M:%S"; fmt= "%Y-%m-%d %H:%M:%S";
break; break;
@@ -1401,24 +1412,25 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *buf)
value->SetValue(fp->val_real()); value->SetValue(fp->val_real());
break; break;
case TYPE_DATE: case TYPE_DATE:
if (!sdvalin) { if (!sdvalin)
sdvalin= (DTVAL*)AllocateValue(xp->g, TYPE_DATE, 19); sdvalin= (DTVAL*)AllocateValue(xp->g, TYPE_DATE, 19);
// Get date in the format produced by MySQL fields // Get date in the format produced by MySQL fields
switch (fp->type()) { switch (fp->type()) {
case MYSQL_TYPE_DATE: case MYSQL_TYPE_DATE:
fmt= "YYYY-MM-DD"; fmt= "YYYY-MM-DD";
break; break;
case MYSQL_TYPE_TIME: case MYSQL_TYPE_TIME:
fmt= "hh:mm:ss"; fmt= "hh:mm:ss";
break; break;
default: case MYSQL_TYPE_YEAR:
fmt= "YYYY-MM-DD hh:mm:ss"; fmt= "YYYY";
} // endswitch type break;
default:
((DTVAL*)sdvalin)->SetFormat(g, fmt, strlen(fmt)); fmt= "YYYY-MM-DD hh:mm:ss";
} // endif sdvalin } // endswitch type
((DTVAL*)sdvalin)->SetFormat(g, fmt, strlen(fmt));
fp->val_str(&attribute); fp->val_str(&attribute);
sdvalin->SetValue_psz(attribute.c_ptr_safe()); sdvalin->SetValue_psz(attribute.c_ptr_safe());
value->SetValue_pval(sdvalin); value->SetValue_pval(sdvalin);
@@ -1557,8 +1569,9 @@ const char *ha_connect::GetValStr(OPVAL vop, bool neg)
/***********************************************************************/ /***********************************************************************/
PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond) PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
{ {
char *body= filp->Body;
unsigned int i; 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}; PPARM pfirst= NULL, pprec= NULL, pp[2]= {NULL, NULL};
OPVAL vop= OP_XX; OPVAL vop= OP_XX;
@@ -1572,6 +1585,9 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
char *p1, *p2; char *p1, *p2;
Item_cond *cond_item= (Item_cond *)cond; Item_cond *cond_item= (Item_cond *)cond;
if (x)
return NULL;
if (xtrace > 1) if (xtrace > 1)
printf("Cond: Ftype=%d name=%s\n", cond_item->functype(), printf("Cond: Ftype=%d name=%s\n", cond_item->functype(),
cond_item->func_name()); cond_item->func_name());
@@ -1586,7 +1602,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
List_iterator<Item> li(*arglist); List_iterator<Item> li(*arglist);
Item *subitem; Item *subitem;
p1= filp + strlen(filp); p1= body + strlen(body);
strcpy(p1, "("); strcpy(p1, "(");
p2= p1 + 1; p2= p1 + 1;
@@ -1615,7 +1631,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
} else if (cond->type() == COND::FUNC_ITEM) { } else if (cond->type() == COND::FUNC_ITEM) {
unsigned int i; unsigned int i;
// int n; // int n;
bool iscol, neg= FALSE; bool iscol, neg= FALSE;
Item_func *condf= (Item_func *)cond; Item_func *condf= (Item_func *)cond;
Item* *args= condf->arguments(); Item* *args= condf->arguments();
@@ -1644,6 +1660,9 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
else if (ismul && tty == TYPE_AM_WMI) else if (ismul && tty == TYPE_AM_WMI)
return NULL; // Not supported by WQL 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++) { for (i= 0; i < condf->argument_count(); i++) {
if (xtrace > 1) if (xtrace > 1)
printf("Argtype(%d)=%d\n", i, args[i]->type()); printf("Argtype(%d)=%d\n", i, args[i]->type());
@@ -1660,6 +1679,9 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
ha_field_option_struct *fop; ha_field_option_struct *fop;
Item_field *pField= (Item_field *)args[i]; Item_field *pField= (Item_field *)args[i];
if (x && i)
return NULL;
if (pField->field->table != table) if (pField->field->table != table)
return NULL; // Field does not belong to this table return NULL; // Field does not belong to this table
else else
@@ -1685,10 +1707,10 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
if (i && ismul) if (i && ismul)
return NULL; return NULL;
strcat(filp, fnm); strcat(body, fnm);
} else { } else {
char buff[256]; char buff[256];
String *res, tmp(buff,sizeof(buff), &my_charset_bin); String *res, tmp(buff, sizeof(buff), &my_charset_bin);
Item_basic_constant *pval= (Item_basic_constant *)args[i]; Item_basic_constant *pval= (Item_basic_constant *)args[i];
if ((res= pval->val_str(&tmp)) == NULL) if ((res= pval->val_str(&tmp)) == NULL)
@@ -1698,26 +1720,46 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
printf("Value=%.*s\n", res->length(), res->ptr()); printf("Value=%.*s\n", res->length(), res->ptr());
// IN and BETWEEN clauses should be col VOP list // IN and BETWEEN clauses should be col VOP list
if (!i && ismul) if (!i && (x || ismul))
return NULL; return NULL;
// Append the value to the filter if (!x) {
if (args[i]->type() == COND::STRING_ITEM) // Append the value to the filter
strcat(strcat(strcat(filp, "'"), res->ptr()), "'"); if (args[i]->field_type() == MYSQL_TYPE_VARCHAR)
else strcat(strcat(strcat(body, "'"), res->ptr()), "'");
strncat(filp, res->ptr(), res->length()); 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 } // endif
if (!i) if (!x) {
strcat(filp, GetValStr(vop, neg)); if (!i)
else if (vop == OP_XX && i == 1) strcat(body, GetValStr(vop, neg));
strcat(filp, " AND "); else if (vop == OP_XX && i == 1)
else if (vop == OP_IN) strcat(body, " AND ");
strcat(filp, (i == condf->argument_count() - 1) ? ")" : ","); else if (vop == OP_IN)
strcat(body, (i == condf->argument_count() - 1) ? ")" : ",");
} // endif x
} // endfor i } // endfor i
if (x)
filp->Op= vop;
} else { } else {
if (xtrace > 1) if (xtrace > 1)
printf("Unsupported condition\n"); printf("Unsupported condition\n");
@@ -1753,23 +1795,31 @@ const COND *ha_connect::cond_push(const COND *cond)
DBUG_ENTER("ha_connect::cond_push"); DBUG_ENTER("ha_connect::cond_push");
if (tdbp) { 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 || 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; 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 (CheckCond(g, filp, tty, (Item *)cond)) {
if (xtrace) 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); tdbp->SetFilter(filp);
// cond= NULL; // This does not work anyway } else if (x && cond)
PlugSubAlloc(g, NULL, strlen(filp) + 1); tdbp->SetFilter(filp); // Wrong filter
} // endif filp
} // endif tty } // endif tty
@@ -1965,14 +2015,8 @@ int ha_connect::write_row(uchar *buf)
if (IsOpened()) if (IsOpened())
CloseTable(g); CloseTable(g);
if (OpenTable(g)) { if ((rc= OpenTable(g)))
if (strstr(g->Message, "read only"))
rc= HA_ERR_TABLE_READONLY;
else
rc= HA_ERR_INITIALIZATION;
DBUG_RETURN(rc); DBUG_RETURN(rc);
} // endif tdbp
} // endif isopened } // endif isopened
@@ -2337,6 +2381,7 @@ int ha_connect::index_next_same(uchar *buf, const uchar *key, uint keylen)
*/ */
int ha_connect::rnd_init(bool scan) int ha_connect::rnd_init(bool scan)
{ {
int rc;
PGLOBAL g= ((table && table->in_use) ? GetPlug(table->in_use, xp) : PGLOBAL g= ((table && table->in_use) ? GetPlug(table->in_use, xp) :
(xp) ? xp->g : NULL); (xp) ? xp->g : NULL);
DBUG_ENTER("ha_connect::rnd_init"); DBUG_ENTER("ha_connect::rnd_init");
@@ -2344,18 +2389,21 @@ int ha_connect::rnd_init(bool scan)
if (xtrace) if (xtrace)
printf("%p in rnd_init: scan=%d\n", this, scan); printf("%p in rnd_init: scan=%d\n", this, scan);
if (g) { if (!g || !table || xmod == MODE_INSERT)
if (!table || xmod == MODE_INSERT) DBUG_RETURN(HA_ERR_INITIALIZATION);
DBUG_RETURN(HA_ERR_INITIALIZATION);
// Close the table if it was opened yet (locked?) // Close the table if it was opened yet (locked?)
if (IsOpened()) if (IsOpened())
CloseTable(g); CloseTable(g);
if (OpenTable(g, xmod == MODE_DELETE)) // When updating, to avoid skipped update, force the table
DBUG_RETURN(HA_ERR_INITIALIZATION); // handler to retrieve write-only fields to be able to compare
// records and detect data change.
if (xmod == MODE_UPDATE)
bitmap_union(table->read_set, table->write_set);
} // endif g if ((rc= OpenTable(g, xmod == MODE_DELETE)))
DBUG_RETURN(rc);
xp->nrd= xp->fnd= xp->nfd= 0; xp->nrd= xp->fnd= xp->nfd= 0;
xp->tb1= my_interval_timer(); xp->tb1= my_interval_timer();
@@ -2566,7 +2614,6 @@ int ha_connect::info(uint flag)
xp->CheckCleanup(); xp->CheckCleanup();
} // endif xmod } // endif xmod
// tdbp= OpenTable(g, xmod == MODE_DELETE);
tdbp= GetTDB(g); tdbp= GetTDB(g);
} // endif tdbp } // endif tdbp
@@ -2661,18 +2708,19 @@ int ha_connect::delete_all_rows()
PGLOBAL g= xp->g; PGLOBAL g= xp->g;
DBUG_ENTER("ha_connect::delete_all_rows"); DBUG_ENTER("ha_connect::delete_all_rows");
if (tdbp && tdbp->GetAmType() != TYPE_AM_XML) if (tdbp && tdbp->GetUse() == USE_OPEN &&
tdbp->GetAmType() != TYPE_AM_XML &&
((PTDBASE)tdbp)->GetFtype() != RECFM_NAF)
// Close and reopen the table so it will be deleted // Close and reopen the table so it will be deleted
rc= CloseTable(g); rc= CloseTable(g);
if (!(OpenTable(g))) { if (!(rc= OpenTable(g))) {
if (CntDeleteRow(g, tdbp, true)) { if (CntDeleteRow(g, tdbp, true)) {
printf("%s\n", g->Message); printf("%s\n", g->Message);
rc= HA_ERR_INTERNAL_ERROR; rc= HA_ERR_INTERNAL_ERROR;
} // endif } // endif
} else } // endif rc
rc= HA_ERR_INITIALIZATION;
DBUG_RETURN(rc); DBUG_RETURN(rc);
} // end of delete_all_rows } // end of delete_all_rows
@@ -3461,12 +3509,13 @@ static bool add_fields(PGLOBAL g,
DBUG_RETURN(0); DBUG_RETURN(0);
} // end of add_fields } // end of add_fields
#else // !NEW_WAY #else // !NEW_WAY
static bool add_field(String *sql, const char *field_name, int typ, int len, static bool add_field(String *sql, const char *field_name, int typ,
int dec, uint tm, const char *rem, int flag, bool dbf) int len, int dec, uint tm, const char *rem,
int flag, bool dbf, char v)
{ {
char var = (len > 255) ? 'V' : v;
bool error= false; bool error= false;
const char *type= PLGtoMYSQLtype(typ, dbf); const char *type= PLGtoMYSQLtype(typ, dbf, var);
// type= PLGtoMYSQLtype(typ, true); ?????
error|= sql->append('`'); error|= sql->append('`');
error|= sql->append(field_name); error|= sql->append(field_name);
@@ -3479,7 +3528,8 @@ static bool add_field(String *sql, const char *field_name, int typ, int len,
if (!strcmp(type, "DOUBLE")) { if (!strcmp(type, "DOUBLE")) {
error|= sql->append(','); error|= sql->append(',');
error|= sql->append_ulonglong(dec); // dec must be <= len and <= 31
error|= sql->append_ulonglong(min(dec, (len - 1)));
} // endif dec } // endif dec
error|= sql->append(')'); error|= sql->append(')');
@@ -3518,6 +3568,8 @@ static int init_table_share(THD *thd,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
Alter_info *alter_info) Alter_info *alter_info)
{ {
KEY *not_used_1;
uint not_used_2;
int rc= 0; int rc= 0;
handler *file; handler *file;
LEX_CUSTRING frm= {0,0}; LEX_CUSTRING frm= {0,0};
@@ -3577,9 +3629,8 @@ static int init_table_share(THD *thd,
tmp_disable_binlog(thd); tmp_disable_binlog(thd);
file= mysql_create_frm_image(thd, table_s->db.str, table_s->table_name.str, file= mysql_create_frm_image(thd, table_s->db.str, table_s->table_name.str,
create_info, alter_info, create_info, alter_info, C_ORDINARY_CREATE,
// &thd->lex->create_info, &thd->lex->alter_info, &not_used_1, &not_used_2, &frm);
C_ORDINARY_CREATE, &frm);
if (file) if (file)
delete file; delete file;
else else
@@ -3772,13 +3823,14 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
TABTYPE ttp= TAB_UNDEF; TABTYPE ttp= TAB_UNDEF;
PQRYRES qrp= NULL; PQRYRES qrp= NULL;
PCOLRES crp; PCOLRES crp;
PGLOBAL g= GetPlug(thd, NULL); PCONNECT xp= NULL;
PGLOBAL g= GetPlug(thd, xp);
PTOS topt= table_s->option_struct; PTOS topt= table_s->option_struct;
#if defined(NEW_WAY) #if defined(NEW_WAY)
//CHARSET_INFO *cs; //CHARSET_INFO *cs;
Alter_info alter_info; Alter_info alter_info;
#else // !NEW_WAY #else // !NEW_WAY
char buf[1024]; char v, buf[1024];
String sql(buf, sizeof(buf), system_charset_info); String sql(buf, sizeof(buf), system_charset_info);
sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info); sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info);
@@ -3821,7 +3873,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
#endif // WIN32 #endif // WIN32
port= atoi(GetListOption(g, "port", topt->oplist, "0")); port= atoi(GetListOption(g, "port", topt->oplist, "0"));
mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0")); mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
#if defined(PROMPT_OK)
cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0")); cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0"));
#endif // PROMPT_OK
} else { } else {
host= "localhost"; host= "localhost";
user= "root"; user= "root";
@@ -3879,14 +3933,16 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
case TAB_ODBC: case TAB_ODBC:
dsn= create_info->connect_string.str; dsn= create_info->connect_string.str;
if (fnc & (FNC_DSN | FNC_DRIVER)) if (fnc & (FNC_DSN | FNC_DRIVER)) {
ok= true; ok= true;
else if (!stricmp(thd->main_security_ctx.host, "localhost") #if defined(PROMPT_OK)
} else if (!stricmp(thd->main_security_ctx.host, "localhost")
&& cop == 1) { && cop == 1) {
if ((dsn = ODBCCheckConnection(g, dsn, cop)) != NULL) { if ((dsn = ODBCCheckConnection(g, dsn, cop)) != NULL) {
thd->make_lex_string(&create_info->connect_string, dsn, strlen(dsn)); thd->make_lex_string(&create_info->connect_string, dsn, strlen(dsn));
ok= true; ok= true;
} // endif dsn } // endif dsn
#endif // PROMPT_OK
} else if (!dsn) } else if (!dsn)
sprintf(g->Message, "Missing %s connection string", topt->type); sprintf(g->Message, "Missing %s connection string", topt->type);
@@ -4098,7 +4154,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
NOT_NULL_FLAG, "", flg, dbf); NOT_NULL_FLAG, "", flg, dbf);
#else // !NEW_WAY #else // !NEW_WAY
// Now add the field // 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; rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY #endif // !NEW_WAY
} // endfor crp } // endfor crp
@@ -4122,6 +4178,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
break; break;
case FLD_TYPE: case FLD_TYPE:
typ= crp->Kdata->GetIntValue(i); typ= crp->Kdata->GetIntValue(i);
v = (crp->Nulls) ? crp->Nulls[i] : 0;
break; break;
case FLD_PREC: case FLD_PREC:
len= crp->Kdata->GetIntValue(i); len= crp->Kdata->GetIntValue(i);
@@ -4152,7 +4209,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
int plgtyp; int plgtyp;
// typ must be PLG type, not SQL type // 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); sprintf(g->Message, "Unsupported SQL type %d", typ);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return HA_ERR_INTERNAL_ERROR; return HA_ERR_INTERNAL_ERROR;
@@ -4177,7 +4234,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
rc= add_fields(g, thd, &alter_info, cnm, typ, len, dec, rc= add_fields(g, thd, &alter_info, cnm, typ, len, dec,
tm, rem, 0, true); tm, rem, 0, true);
#else // !NEW_WAY #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, dbf, v))
rc= HA_ERR_OUT_OF_MEM; rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY #endif // !NEW_WAY
} // endfor i } // endfor i
@@ -4671,6 +4728,6 @@ maria_declare_plugin(connect)
NULL, /* status variables */ NULL, /* status variables */
NULL, /* system variables */ NULL, /* system variables */
"0.1", /* string version */ "0.1", /* string version */
MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */ MariaDB_PLUGIN_MATURITY_ALPHA /* maturity */
} }
maria_declare_plugin_end; maria_declare_plugin_end;

View File

@@ -174,7 +174,7 @@ public:
bool IsSameIndex(PIXDEF xp1, PIXDEF xp2); bool IsSameIndex(PIXDEF xp1, PIXDEF xp2);
PTDB GetTDB(PGLOBAL g); PTDB GetTDB(PGLOBAL g);
bool OpenTable(PGLOBAL g, bool del= false); int OpenTable(PGLOBAL g, bool del= false);
bool IsOpened(void); bool IsOpened(void);
int CloseTable(PGLOBAL g); int CloseTable(PGLOBAL g);
int MakeRecord(char *buf); int MakeRecord(char *buf);

View File

@@ -8,6 +8,9 @@
#include <libxml/tree.h> #include <libxml/tree.h>
#include <libxml/xpath.h> #include <libxml/xpath.h>
#include <libxml/xpathInternals.h> #include <libxml/xpathInternals.h>
#include <libxml/catalog.h>
#include <libxml/xmlschemastypes.h>
#include <libxml/relaxng.h>
//#if defined(WIN32) //#if defined(WIN32)
//#include <windows.h> //#include <windows.h>
//#else // !WIN32 //#else // !WIN32
@@ -290,10 +293,46 @@ if (!rc)
/******************************************************************/ /******************************************************************/
/* XML library cleanup function. */ /* XML library cleanup function. */
/******************************************************************/ /******************************************************************/
/*
This is a copy of xmlCleanupParser() from the libxml2 sources
with xmlResetLastError() commented.
xmlResetLastError() called from the original xmlCleanupParser() causes
valgrind to report memory leaks. This happens because
ha_initialize_handlerton() is called from the main thread in mysqld.cc,
while ha_finalize_handlerton() is called from a non-main thread.
libxml2 gets confused because of xmlInitParser() and xmlCleanupParser()
being called from the different threads.
Perhaps the code in mysqld.cc should eventually be modified
to shutdown plugins from the main thread.
*/
static void
xmlCleanupParser_replacement(void)
{
xmlCleanupCharEncodingHandlers();
#ifdef LIBXML_CATALOG_ENABLED
xmlCatalogCleanup();
#endif
xmlDictCleanup();
xmlCleanupInputCallbacks();
#ifdef LIBXML_OUTPUT_ENABLED
xmlCleanupOutputCallbacks();
#endif
#ifdef LIBXML_SCHEMAS_ENABLED
xmlSchemaCleanupTypes();
xmlRelaxNGCleanupTypes();
#endif
//xmlResetLastError();
xmlCleanupGlobals();
xmlCleanupThreads(); /* must be last if called not from the main thread */
xmlCleanupMemory();
}
void XmlCleanupParserLib(void) void XmlCleanupParserLib(void)
{ {
xmlCleanupParser(); xmlCleanupParser_replacement();
xmlMemoryDump();
} // end of XmlCleanupParserLib } // end of XmlCleanupParserLib
/******************************************************************/ /******************************************************************/

View File

@@ -87,7 +87,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
FLD_KEY, FLD_SCALE, FLD_RADIX, FLD_NULL, FLD_KEY, FLD_SCALE, FLD_RADIX, FLD_NULL,
FLD_REM, FLD_NO, FLD_CHARSET}; FLD_REM, FLD_NO, FLD_CHARSET};
static unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 256, 32, 32}; 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 i, n, nf, ncol = sizeof(buftyp) / sizeof(int);
int len, type, prec, rc, k = 0; int len, type, prec, rc, k = 0;
PQRYRES qrp; PQRYRES qrp;
@@ -139,6 +139,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
// Some columns must be renamed // Some columns must be renamed
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
switch (++i) { switch (++i) {
case 2: crp->Nulls = (char*)PlugSubAlloc(g, NULL, n); break;
case 4: crp->Name = "Length"; break; case 4: crp->Name = "Length"; break;
case 5: crp->Name = "Key"; break; case 5: crp->Name = "Key"; break;
case 10: crp->Name = "Date_fmt"; 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 // Get type, type name, and precision
fld = myc.GetCharField(1); fld = myc.GetCharField(1);
prec = 0; prec = 0;
len = 255; // Default for text or blob len = 0;
v = 0;
if ((nf = sscanf(fld, "%[^(](%d,%d", cmd, &len, &prec)) < 1) { if ((nf = sscanf(fld, "%[^(](%d,%d", cmd, &len, &prec)) < 1) {
sprintf(g->Message, MSG(BAD_FIELD_TYPE), fld); sprintf(g->Message, MSG(BAD_FIELD_TYPE), fld);
@@ -175,14 +177,16 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
} else } else
qrp->Nblin++; qrp->Nblin++;
if ((type = MYSQLtoPLG(cmd)) == TYPE_ERROR) { if ((type = MYSQLtoPLG(cmd, &v)) == TYPE_ERROR) {
sprintf(g->Message, "Unsupported column type %s", cmd); sprintf(g->Message, "Unsupported column type %s", cmd);
myc.Close(); myc.Close();
return NULL; return NULL;
} // endif type } else if (type == TYPE_STRING)
len = min(len, 4096);
crp = crp->Next; // Data_Type crp = crp->Next; // Data_Type
crp->Kdata->SetValue(type, i); crp->Kdata->SetValue(type, i);
crp->Nulls[i] = v;
crp = crp->Next; // Type_Name crp = crp->Next; // Type_Name
crp->Kdata->SetValue(cmd, i); 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 *user, const char *pwd,
const char *srcdef, int port) const char *srcdef, int port)
{ {
char *query;
int w; int w;
MYSQLC myc; MYSQLC myc;
PQRYRES qrp = NULL; PQRYRES qrp = NULL;
@@ -260,12 +265,15 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
if (!port) if (!port)
port = mysqld_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 // Open a MySQL connection for this table
if (myc.Open(g, host, db, user, pwd, port)) if (myc.Open(g, host, db, user, pwd, port))
return NULL; return NULL;
// Send the source command to MySQL // 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); qrp = myc.GetResult(g);
myc.Close(); myc.Close();
@@ -701,7 +709,7 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
crp->Clen = GetTypeSize(crp->Type, crp->Length); crp->Clen = GetTypeSize(crp->Type, crp->Length);
if (!(crp->Kdata = AllocValBlock(g, NULL, crp->Type, m_Rows, if (!(crp->Kdata = AllocValBlock(g, NULL, crp->Type, m_Rows,
crp->Clen, 0, FALSE, TRUE))) { crp->Clen, 0, FALSE, TRUE, FALSE))) {
sprintf(g->Message, MSG(INV_RESULT_TYPE), sprintf(g->Message, MSG(INV_RESULT_TYPE),
GetFormatType(crp->Type)); GetFormatType(crp->Type));
return NULL; return NULL;
@@ -778,6 +786,42 @@ void MYSQLC::Rewind(void)
} // end of Rewind } // 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, "Remote: %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. */ /* Close the connection. */
/***********************************************************************/ /***********************************************************************/

View File

@@ -26,7 +26,6 @@
#define DllItem #define DllItem
#endif // !WIN32 #endif // !WIN32
//#define TYPE_AM_MYSQL (AMT)192
#define MYSQL_ENABLED 0x00000001 #define MYSQL_ENABLED 0x00000001
#define MYSQL_LOGON 0x00000002 #define MYSQL_LOGON 0x00000002
@@ -75,9 +74,12 @@ class DllItem MYSQLC {
//const char *ServerInfo(void); //const char *ServerInfo(void);
int KillQuery(ulong id); int KillQuery(ulong id);
int ExecSQL(PGLOBAL g, const char *query, int *w = NULL); 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 PrepareSQL(PGLOBAL g, const char *query);
int ExecStmt(PGLOBAL g); int ExecStmt(PGLOBAL g);
int BindParams(PGLOBAL g, MYSQL_BIND *bind); int BindParams(PGLOBAL g, MYSQL_BIND *bind);
#endif // MYSQL_PREPARED_STATEMENTS
PQRYRES GetResult(PGLOBAL g, bool pdb = FALSE); PQRYRES GetResult(PGLOBAL g, bool pdb = FALSE);
int Fetch(PGLOBAL g, int pos); int Fetch(PGLOBAL g, int pos);
char *GetCharField(int i); char *GetCharField(int i);
@@ -99,5 +101,6 @@ class DllItem MYSQLC {
int m_Rows; // The number of rows of the result int m_Rows; // The number of rows of the result
int N; int N;
int m_Fields; // The number of result fields int m_Fields; // The number of result fields
int m_Afrw; // The number of affected rows
}; // end of class MYSQLC }; // end of class MYSQLC

View File

@@ -0,0 +1,15 @@
# Use default setting for mysqld processes
!include include/default_mysqld.cnf
!include include/default_client.cnf
[mysqld.1]
#log-bin= master-bin
[mysqld.2]
[ENV]
MASTER_MYPORT= @mysqld.1.port
MASTER_MYSOCK= @mysqld.1.socket
SLAVE_MYPORT= @mysqld.2.port
SLAVE_MYSOCK= @mysqld.2.socket

View File

@@ -48,7 +48,7 @@ salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
dept INT(4) NOT NULL FIELD_FORMAT='S' dept INT(4) NOT NULL FIELD_FORMAT='S'
) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat'; ) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat';
INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777); INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
ALTER TABLE t1 READONLY=NO; ALTER TABLE t1 READONLY=NO;
Warnings: Warnings:
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
@@ -84,7 +84,7 @@ t1 CREATE TABLE `t1` (
`dept` int(4) NOT NULL `FIELD_FORMAT`='S' `dept` int(4) NOT NULL `FIELD_FORMAT`='S'
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=BIN `FILE_NAME`='Testbal.dat' `READONLY`=YES ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=BIN `FILE_NAME`='Testbal.dat' `READONLY`=YES
INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777); INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
DROP TABLE t1; DROP TABLE t1;
# #
# Testing that the underlying file is created # Testing that the underlying file is created

View File

@@ -50,13 +50,13 @@ children SMALLINT(2) NOT NULL
) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='people.csv' ) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='people.csv'
HEADER=1 SEP_CHAR=';' QUOTED=1 READONLY=yes; HEADER=1 SEP_CHAR=';' QUOTED=1 READONLY=yes;
INSERT INTO t1 VALUES ('BILL','1973-06-30',5); INSERT INTO t1 VALUES ('BILL','1973-06-30',5);
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
UPDATE t1 SET children=6 WHERE name='BILL'; UPDATE t1 SET children=6 WHERE name='BILL';
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
DELETE FROM t1 WHERE name='BILL'; DELETE FROM t1 WHERE name='BILL';
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
SELECT * FROM t1; SELECT * FROM t1;
name birth children name birth children
Archibald 2001-05-17 3 Archibald 2001-05-17 3
@@ -90,7 +90,7 @@ t1 CREATE TABLE `t1` (
`children` smallint(2) NOT NULL `children` smallint(2) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=CSV `FILE_NAME`='people.csv' `HEADER`=1 `SEP_CHAR`=';' `QUOTED`=1 `READONLY`=1 ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=CSV `FILE_NAME`='people.csv' `HEADER`=1 `SEP_CHAR`=';' `QUOTED`=1 `READONLY`=1
INSERT INTO t1 VALUES ('BILL','1973-06-30',5); INSERT INTO t1 VALUES ('BILL','1973-06-30',5);
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
SELECT * FROM t1; SELECT * FROM t1;
name birth children name birth children
Archibald 2001-05-17 3 Archibald 2001-05-17 3

View File

@@ -77,13 +77,13 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL `a` int(11) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=DBF `FILE_NAME`='t1.dbf' `READONLY`=Yes ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=DBF `FILE_NAME`='t1.dbf' `READONLY`=Yes
INSERT INTO t1 VALUES (30); INSERT INTO t1 VALUES (30);
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
UPDATE t1 SET a=30 WHERE a=10; UPDATE t1 SET a=30 WHERE a=10;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
DELETE FROM t1 WHERE a=10; DELETE FROM t1 WHERE a=10;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
ALTER TABLE t1 READONLY=NO; ALTER TABLE t1 READONLY=NO;
Warnings: Warnings:
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk

View File

@@ -30,13 +30,13 @@ t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL `id` int(11) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=FIX `FILE_NAME`='t1.txt' `READONLY`=1 ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=FIX `FILE_NAME`='t1.txt' `READONLY`=1
INSERT INTO t1 VALUES (20); INSERT INTO t1 VALUES (20);
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
UPDATE t1 SET id=20 WHERE id=10; UPDATE t1 SET id=20 WHERE id=10;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
DELETE FROM t1 WHERE id=10; DELETE FROM t1 WHERE id=10;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
ALTER TABLE t1 READONLY=0; ALTER TABLE t1 READONLY=0;
Warnings: Warnings:
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk

View File

@@ -194,13 +194,13 @@ t1 CREATE TABLE `t1` (
`c2` char(60) DEFAULT NULL `c2` char(60) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=INI `FILE_NAME`='t1.ini' `READONLY`=1 ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=INI `FILE_NAME`='t1.ini' `READONLY`=1
INSERT INTO t1 VALUES ('US',40); INSERT INTO t1 VALUES ('US',40);
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
UPDATE t1 SET c2=20 WHERE c2=10; UPDATE t1 SET c2=20 WHERE c2=10;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
DELETE FROM t1 WHERE c2=10; DELETE FROM t1 WHERE c2=10;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
ALTER TABLE t1 READONLY=0; ALTER TABLE t1 READONLY=0;
Warnings: Warnings:
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk

View File

@@ -44,7 +44,7 @@ SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL, `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' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
SELECT * FROM t2; SELECT * FROM t2;
a b a b
@@ -176,7 +176,7 @@ t1 CREATE TABLE `t1` (
SHOW CREATE TABLE t2; SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( 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' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
SELECT * FROM t2; SELECT * FROM t2;
a a

View File

@@ -0,0 +1,42 @@
CREATE DATABASE connect;
CREATE DATABASE connect;
CREATE TABLE t1 (
`id` int(20) primary key,
`group` int NOT NULL default 1,
`a\\b` int NOT NULL default 2,
`a\\` int unsigned,
`name` varchar(32) default 'name')
DEFAULT CHARSET=latin1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(20) NOT NULL,
`group` int(11) NOT NULL,
`a\\b` int(11) NOT NULL,
`a\\` int(10) DEFAULT NULL,
`name` varchar(32) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1' `TABLE_TYPE`='MYSQL'
INSERT INTO t1 (id, name) VALUES (1, 'foo');
Warnings:
Warning 1364 Field 'group' doesn't have a default value
Warning 1364 Field 'a\\b' doesn't have a default value
INSERT INTO t1 (id, name) VALUES (2, 'fee');
Warnings:
Warning 1364 Field 'group' doesn't have a default value
Warning 1364 Field 'a\\b' doesn't have a default value
SELECT * FROM t1;
id group a\\b a\\ name
1 1 2 NULL foo
2 1 2 NULL fee
DROP TABLE t1;
SELECT * FROM t1;
id group a\\b a\\ name
1 1 2 NULL foo
2 1 2 NULL fee
DROP TABLE t1;
DROP TABLE IF EXISTS connect.t1;
DROP DATABASE IF EXISTS connect;
DROP TABLE IF EXISTS connect.t1;
DROP DATABASE IF EXISTS connect;

View File

@@ -0,0 +1,62 @@
CREATE DATABASE connect;
CREATE DATABASE connect;
#
# Checking Sending Commands
#
CREATE TABLE t1 (
command VARCHAR(128) NOT NULL,
warnings INT(4) NOT NULL FLAG=3,
number INT(5) NOT NULL FLAG=1,
message VARCHAR(255) FLAG=2)
ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test' OPTION_LIST='Execsrc=1,maxerr=2';
SELECT * FROM t1 WHERE command IN ('Warning','Note',
'drop table if exists t1',
'create table t1 (id int key auto_increment, msg varchar(32) not null)',
"insert into t1(msg) values('One'),(NULL),('Three')",
"insert into t1 values(2,'Deux') on duplicate key update msg = 'Two'",
"insert into t1(message) values('Four'),('Five'),('Six')",
'insert into t1(id) values(NULL)',
"update t1 set msg = 'Four' where id = 4",
'select * from t1');
command warnings number message
drop table if exists t1 1 0 Affected rows
Note 0 1051 Unknown table 'test.t1'
create table t1 (id int key auto_increment, msg varchar(32) not null) 0 0 Affected rows
insert into t1(msg) values('One'),(NULL),('Three') 1 3 Affected rows
Warning 0 1048 Column 'msg' cannot be null
insert into t1 values(2,'Deux') on duplicate key update msg = 'Two' 0 2 Affected rows
insert into t1(message) values('Four'),('Five'),('Six') 0 1054 Remote: Unknown column 'message' in 'field list'
insert into t1(id) values(NULL) 1 1 Affected rows
Warning 0 1364 Field 'msg' doesn't have a default value
update t1 set msg = 'Four' where id = 4 0 1 Affected rows
select * from t1 0 2 Result set columns
#
# Checking Using Procedure
#
DROP PROCEDURE IF EXISTS p1;
Warnings:
Note 1305 PROCEDURE test.p1 does not exist
CREATE PROCEDURE p1(cmd varchar(512))
READS SQL DATA
SELECT * FROM t1 WHERE command IN ('Warning','Note',cmd);
CALL p1('insert into t1(id) values(NULL)');
command warnings number message
insert into t1(id) values(NULL) 1 1 Affected rows
Warning 0 1364 Field 'msg' doesn't have a default value
CALL p1('update t1 set msg = "Five" where id = 5');
command warnings number message
update t1 set msg = "Five" where id = 5 0 1 Affected rows
DROP PROCEDURE p1;
DROP TABLE t1;
SELECT * FROM t1;
id msg
1 One
2 Two
3 Three
4 Four
5 Five
DROP TABLE t1;
DROP TABLE IF EXISTS connect.t1;
DROP DATABASE IF EXISTS connect;
DROP TABLE IF EXISTS connect.t1;
DROP DATABASE IF EXISTS connect;

View File

@@ -0,0 +1,218 @@
CREATE DATABASE connect;
CREATE DATABASE connect;
CREATE TABLE t1 (a int, b char(10));
INSERT INTO t1 VALUES (NULL,NULL),(0,'test00'),(1,'test01'),(2,'test02'),(3,'test03');
SELECT * FROM t1;
a b
NULL NULL
0 test00
1 test01
2 test02
3 test03
#
# Testing errors
#
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://unknown@127.0.0.1:SLAVE_PORT/test/t1';
ERROR HY000: (1045) Access denied for user 'unknown'@'localhost' (using password: NO)
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/unknown/t1';
ERROR HY000: (1049) Unknown database 'unknown'
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
OPTION_LIST='host=127.0.0.1,user=root,port=SLAVE_PORT' DBNAME='unknown' TABNAME='t1';
ERROR HY000: (1049) Unknown database 'unknown'
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/unknown';
ERROR HY000: (1146) Table 'test.unknown' doesn't exist [SHOW FULL COLUMNS FROM unknown FROM test]
SHOW CREATE TABLE t1;
ERROR 42S02: Table 'test.t1' doesn't exist
CREATE TABLE t1 (x int, y char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`x` int(11) DEFAULT NULL,
`y` char(10) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1' `TABLE_TYPE`=MYSQL
SELECT * FROM t1;
ERROR HY000: Got error 174 '(1054) Unknown column 'x' in 'field list' [SELECT `x`, `y` FROM `t1`]' from CONNECT
DROP TABLE t1;
CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1';
ALTER TABLE t1 RENAME t1backup;
SELECT * FROM t1;
ERROR HY000: Got error 174 '(1146) Table 'test.t1' doesn't exist [SELECT `a`, `b` FROM `t1`]' from CONNECT
ALTER TABLE t1backup RENAME t1;
DROP TABLE t1;
#
# Testing SELECT, etc.
#
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` char(10) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1' `TABLE_TYPE`='MYSQL'
SELECT * FROM t1;
a b
NULL NULL
0 test00
1 test01
2 test02
3 test03
DROP TABLE t1;
CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1'
OPTION_LIST='host=127.0.0.1,user=root,port=SLAVE_PORT';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` char(10) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=MYSQL `TABNAME`='t1' `OPTION_LIST`='host=127.0.0.1,user=root,port=SLAVE_PORT'
SELECT * FROM t1;
a b
NULL NULL
0 test00
1 test01
2 test02
3 test03
DROP TABLE t1;
CREATE TABLE t1 (a INT NOT NULL, b CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=MYSQL
OPTION_LIST='host=127.0.0.1,user=root,port=SLAVE_PORT';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` char(10) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=MYSQL `OPTION_LIST`='host=127.0.0.1,user=root,port=SLAVE_PORT'
SELECT * FROM t1;
a b
0
0 test00
1 test01
2 test02
3 test03
DROP TABLE t1;
CREATE TABLE t1 (a char(10), b int) ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(10) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1' `TABLE_TYPE`=MYSQL
SELECT * FROM t1;
a b
NULL NULL
0 0
1 0
2 0
3 0
DROP TABLE t1;
DROP TABLE t1;
#
# Testing numeric data types
#
CREATE TABLE t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float, g double, h decimal(20,5));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` tinyint(4) DEFAULT NULL,
`b` smallint(6) DEFAULT NULL,
`c` mediumint(9) DEFAULT NULL,
`d` int(11) DEFAULT NULL,
`e` bigint(20) DEFAULT NULL,
`f` float DEFAULT NULL,
`g` double DEFAULT NULL,
`h` decimal(20,5) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES(100,3333,41235,1234567890,235000000000,3.14159265,3.14159265,3141.59265);
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
OPTION_LIST='host=127.0.0.1,user=root,port=SLAVE_PORT';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` tinyint(4) DEFAULT NULL,
`b` smallint(6) DEFAULT NULL,
`c` int(9) DEFAULT NULL,
`d` int(11) DEFAULT NULL,
`e` bigint(20) DEFAULT NULL,
`f` double DEFAULT NULL,
`g` double DEFAULT NULL,
`h` double(20,5) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `OPTION_LIST`='host=127.0.0.1,user=root,port=SLAVE_PORT'
SELECT * FROM t1;
a b c d e f g h
100 3333 41235 1234567890 235000000000 3.14159 3.14159265 3141.59265
DROP TABLE t1;
DROP TABLE t1;
#
# Testing character data types
#
CREATE TABLE t1 (a char(12), b varchar(12));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(12) DEFAULT NULL,
`b` varchar(12) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES('Welcome','Hello, World');
SELECT * FROM t1;
a b
Welcome Hello, World
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(12) DEFAULT NULL,
`b` varchar(12) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT' `TABLE_TYPE`='MYSQL'
SELECT * FROM t1;
a b
Welcome Hello, World
DROP TABLE t1;
DROP TABLE t1;
#
# Testing temporal data types
#
CREATE TABLE t1 (a date, b datetime, c time, d timestamp, e year);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` date DEFAULT NULL,
`b` datetime DEFAULT NULL,
`c` time DEFAULT NULL,
`d` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`e` year(4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES('2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23');
Warnings:
Note 1265 Data truncated for column 'a' at row 1
Note 1265 Data truncated for column 'c' at row 1
Warning 1265 Data truncated for column 'e' at row 1
SELECT * FROM t1;
a b c d e
2003-05-27 2003-05-27 10:45:23 10:45:23 2003-05-27 10:45:23 2003
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` date DEFAULT NULL,
`b` datetime DEFAULT NULL,
`c` time DEFAULT NULL,
`d` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`e` year(4) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT' `TABLE_TYPE`='MYSQL'
SELECT * FROM t1;
a b c d e
2003-05-27 2003-05-27 10:45:23 10:45:23 2003-05-27 10:45:23 2003
DROP TABLE t1;
DROP TABLE t1;
DROP TABLE IF EXISTS connect.t1;
DROP DATABASE IF EXISTS connect;
DROP TABLE IF EXISTS connect.t1;
DROP DATABASE IF EXISTS connect;

View File

@@ -1,6 +1,6 @@
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`Description` varchar(128) NOT NULL, `Description` char(128) NOT NULL,
`Attributes` varchar(256) NOT NULL `Attributes` varchar(256) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers'
SET NAMES utf8; SET NAMES utf8;
@@ -41,3 +41,13 @@ test2
ÆÇÈÉË ÆÇÈÉË
DROP VIEW v1; DROP VIEW v1;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;
SELECT * FROM t1;
Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks
t1 a 12 varchar(64) 64 64 10 0 1
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;
SELECT * FROM t1;
Table_Qualifier Table_Owner Table_Name Table_Type Remark
t1 TABLE
DROP TABLE t1;

View File

@@ -1,6 +1,6 @@
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`Description` varchar(128) NOT NULL, `Description` char(128) NOT NULL,
`Attributes` varchar(256) NOT NULL `Attributes` varchar(256) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers'
SET NAMES utf8; SET NAMES utf8;

View File

@@ -13,3 +13,14 @@ Thomas Dominique NULL
Lemonnier Nathalie Directeur Marketing Client Lemonnier Nathalie Directeur Marketing Client
Menseau Eric NULL Menseau Eric NULL
DROP TABLE contact; DROP TABLE contact;
CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineXLS;DBQ=DATADIR/test/contacts.xls' CHARSET=utf8 DATA_CHARSET=latin1;;
SELECT * FROM t1 WHERE Table_name='CONTACT';
Table_Qualifier Table_Owner Table_Name Table_Type Remark
DATADIR/test/contacts CONTACT TABLE
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineXLS;DBQ=DATADIR/test/contacts.xls' CHARSET=utf8 DATA_CHARSET=latin1;;
SELECT * FROM t1 WHERE Table_name='CONTACT' AND Column_name IN ('Nom','Fonction');
Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks
DATADIR/test/contacts CONTACT Nom 12 VARCHAR 255 510 0 0 1
DATADIR/test/contacts CONTACT Fonction 12 VARCHAR 255 510 0 0 1
DROP TABLE t1;

View File

@@ -103,13 +103,13 @@ t1 CREATE TABLE `t1` (
`b` char(10) NOT NULL `b` char(10) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 MAX_ROWS=10 `TABLE_TYPE`=VEC `FILE_NAME`='t1vec' `READONLY`=yes ) ENGINE=CONNECT DEFAULT CHARSET=latin1 MAX_ROWS=10 `TABLE_TYPE`=VEC `FILE_NAME`='t1vec' `READONLY`=yes
INSERT INTO t1 VALUES (4,'test04'); INSERT INTO t1 VALUES (4,'test04');
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
UPDATE t1 SET b='test04' WHERE a=3; UPDATE t1 SET b='test04' WHERE a=3;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
DELETE FROM t1 WHERE a=3; DELETE FROM t1 WHERE a=3;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT ERROR HY000: Table 't1' is read only
ALTER TABLE t1 READONLY=no; ALTER TABLE t1 READONLY=no;
Warnings: Warnings:
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk

View File

@@ -413,7 +413,7 @@ DROP TABLE t1;
SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml'); SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml');
SELECT CAST(@a AS CHAR CHARACTER SET latin1); SELECT CAST(@a AS CHAR CHARACTER SET latin1);
CAST(@a AS CHAR CHARACTER SET latin1) <?xml version="1.0" encoding="iso-8859-1"?> CAST(@a AS CHAR CHARACTER SET latin1) <?xml version="1.0" encoding="iso-8859-1"?>
<!-- Created by CONNECT Version 1.01.0008 August 18, 2013 --> <!-- Created by CONNECT Version 1.01.0009 October 29, 2013 -->
<t1> <t1>
<line> <line>
<node>ÀÁÂÃ</node> <node>ÀÁÂÃ</node>

View File

@@ -46,7 +46,7 @@ CREATE TABLE t1
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F', salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
dept INT(4) NOT NULL FIELD_FORMAT='S' dept INT(4) NOT NULL FIELD_FORMAT='S'
) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat'; ) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat';
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777); INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
ALTER TABLE t1 READONLY=NO; ALTER TABLE t1 READONLY=NO;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
@@ -54,7 +54,7 @@ INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
SELECT * FROM t1; SELECT * FROM t1;
ALTER TABLE t1 READONLY=YES; ALTER TABLE t1 READONLY=YES;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777); INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
DROP TABLE t1; DROP TABLE t1;

View File

@@ -45,13 +45,13 @@ CREATE TABLE t1
children SMALLINT(2) NOT NULL children SMALLINT(2) NOT NULL
) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='people.csv' ) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='people.csv'
HEADER=1 SEP_CHAR=';' QUOTED=1 READONLY=yes; HEADER=1 SEP_CHAR=';' QUOTED=1 READONLY=yes;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES ('BILL','1973-06-30',5); INSERT INTO t1 VALUES ('BILL','1973-06-30',5);
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
UPDATE t1 SET children=6 WHERE name='BILL'; UPDATE t1 SET children=6 WHERE name='BILL';
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
DELETE FROM t1 WHERE name='BILL'; DELETE FROM t1 WHERE name='BILL';
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
SELECT * FROM t1; SELECT * FROM t1;
ALTER TABLE t1 READONLY=no; ALTER TABLE t1 READONLY=no;
@@ -60,7 +60,7 @@ INSERT INTO t1 VALUES ('BILL','1973-06-30',5);
SELECT * FROM t1; SELECT * FROM t1;
ALTER TABLE t1 READONLY=1; ALTER TABLE t1 READONLY=1;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES ('BILL','1973-06-30',5); INSERT INTO t1 VALUES ('BILL','1973-06-30',5);
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;

View File

@@ -66,13 +66,13 @@ INSERT INTO t1 VALUES (10),(20);
SELECT * FROM t1; SELECT * FROM t1;
ALTER TABLE t1 READONLY=Yes; ALTER TABLE t1 READONLY=Yes;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES (30); INSERT INTO t1 VALUES (30);
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
UPDATE t1 SET a=30 WHERE a=10; UPDATE t1 SET a=30 WHERE a=10;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
DELETE FROM t1 WHERE a=10; DELETE FROM t1 WHERE a=10;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ALTER TABLE t1 READONLY=NO; ALTER TABLE t1 READONLY=NO;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;

View File

@@ -28,13 +28,13 @@ INSERT INTO t1 VALUES (10);
SELECT * FROM t1; SELECT * FROM t1;
ALTER TABLE t1 READONLY=1; ALTER TABLE t1 READONLY=1;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES (20); INSERT INTO t1 VALUES (20);
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
UPDATE t1 SET id=20 WHERE id=10; UPDATE t1 SET id=20 WHERE id=10;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
DELETE FROM t1 WHERE id=10; DELETE FROM t1 WHERE id=10;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ALTER TABLE t1 READONLY=0; ALTER TABLE t1 READONLY=0;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;

View File

@@ -99,13 +99,13 @@ INSERT INTO t1 VALUES ('UK',10),('FR',20),('RU',30);
SELECT * FROM t1; SELECT * FROM t1;
ALTER TABLE t1 READONLY=1; ALTER TABLE t1 READONLY=1;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES ('US',40); INSERT INTO t1 VALUES ('US',40);
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
UPDATE t1 SET c2=20 WHERE c2=10; UPDATE t1 SET c2=20 WHERE c2=10;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
DELETE FROM t1 WHERE c2=10; DELETE FROM t1 WHERE c2=10;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ALTER TABLE t1 READONLY=0; ALTER TABLE t1 READONLY=0;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;

View File

@@ -0,0 +1,27 @@
--source include/not_embedded.inc
let $PORT= `select @@port`;
--disable_query_log
--replace_result $PORT PORT
--error 0,ER_UNKNOWN_ERROR
eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/tx1';
if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
AND ENGINE='CONNECT'
AND CREATE_OPTIONS LIKE '%`table_type`=MySQL%'`)
{
Skip Need MySQL support;
}
DROP TABLE t1;
--enable_query_log
connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,);
connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,);
connection master;
CREATE DATABASE connect;
connection slave;
CREATE DATABASE connect;

View File

@@ -0,0 +1,9 @@
connection master;
--disable_warnings
DROP TABLE IF EXISTS connect.t1;
DROP DATABASE IF EXISTS connect;
connection slave;
DROP TABLE IF EXISTS connect.t1;
DROP DATABASE IF EXISTS connect;
--enable_warnings

View File

@@ -0,0 +1,33 @@
-- source myconn.inc
connection slave;
CREATE TABLE t1 (
`id` int(20) primary key,
`group` int NOT NULL default 1,
`a\\b` int NOT NULL default 2,
`a\\` int unsigned,
`name` varchar(32) default 'name')
DEFAULT CHARSET=latin1;
connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
--replace_result $SLAVE_MYPORT SLAVE_PORT
SHOW CREATE TABLE t1;
INSERT INTO t1 (id, name) VALUES (1, 'foo');
INSERT INTO t1 (id, name) VALUES (2, 'fee');
--sorted_result
SELECT * FROM t1;
DROP TABLE t1;
connection slave;
--sorted_result
SELECT * FROM t1;
DROP TABLE t1;
-- source myconn_cleanup.inc

View File

@@ -0,0 +1,45 @@
-- source myconn.inc
--echo #
--echo # Checking Sending Commands
--echo #
connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE t1 (
command VARCHAR(128) NOT NULL,
warnings INT(4) NOT NULL FLAG=3,
number INT(5) NOT NULL FLAG=1,
message VARCHAR(255) FLAG=2)
ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test' OPTION_LIST='Execsrc=1,maxerr=2';
SELECT * FROM t1 WHERE command IN ('Warning','Note',
'drop table if exists t1',
'create table t1 (id int key auto_increment, msg varchar(32) not null)',
"insert into t1(msg) values('One'),(NULL),('Three')",
"insert into t1 values(2,'Deux') on duplicate key update msg = 'Two'",
"insert into t1(message) values('Four'),('Five'),('Six')",
'insert into t1(id) values(NULL)',
"update t1 set msg = 'Four' where id = 4",
'select * from t1');
--echo #
--echo # Checking Using Procedure
--echo #
DROP PROCEDURE IF EXISTS p1;
CREATE PROCEDURE p1(cmd varchar(512))
READS SQL DATA
SELECT * FROM t1 WHERE command IN ('Warning','Note',cmd);
CALL p1('insert into t1(id) values(NULL)');
CALL p1('update t1 set msg = "Five" where id = 5');
DROP PROCEDURE p1;
DROP TABLE t1;
connection slave;
--sorted_result
SELECT * FROM t1;
DROP TABLE t1;
-- source myconn_cleanup.inc

View File

@@ -0,0 +1,325 @@
-- source myconn.inc
#
# This test is run against a remote MySQL server
#
connection slave;
CREATE TABLE t1 (a int, b char(10));
INSERT INTO t1 VALUES (NULL,NULL),(0,'test00'),(1,'test01'),(2,'test02'),(3,'test03');
SELECT * FROM t1;
--echo #
--echo # Testing errors
--echo #
connection master;
# Bad user name
# Suppress "mysql_real_connect failed:" (printed in _DEBUG build)
--replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " ""
--error ER_UNKNOWN_ERROR
eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://unknown@127.0.0.1:$SLAVE_MYPORT/test/t1';
# Bad database name
--replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " ""
--error ER_UNKNOWN_ERROR
eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/unknown/t1';
# Bad database name, with OPTION_LIST going first.
--replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " ""
--error ER_UNKNOWN_ERROR
eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT' DBNAME='unknown' TABNAME='t1';
# Bad table name
--replace_result $SLAVE_MYPORT SLAVE_PORT
--error ER_UNKNOWN_ERROR
eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/unknown';
--error ER_NO_SUCH_TABLE
SHOW CREATE TABLE t1;
# Bad column name
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE t1 (x int, y char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
--replace_result $SLAVE_MYPORT SLAVE_PORT
SHOW CREATE TABLE t1;
--error ER_GET_ERRMSG
SELECT * FROM t1;
DROP TABLE t1;
# The remote table disappeared
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
connection slave;
ALTER TABLE t1 RENAME t1backup;
connection master;
--error ER_GET_ERRMSG
SELECT * FROM t1;
connection slave;
ALTER TABLE t1backup RENAME t1;
connection master;
DROP TABLE t1;
--echo #
--echo # Testing SELECT, etc.
--echo #
# Automatic table structure
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
--replace_result $SLAVE_MYPORT SLAVE_PORT
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
# Explicit table structure
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1'
OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT';
--replace_result $SLAVE_MYPORT SLAVE_PORT
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
# Explicit table structure: remote NULL, local NOT NULL
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE t1 (a INT NOT NULL, b CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=MYSQL
OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT';
--replace_result $SLAVE_MYPORT SLAVE_PORT
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
# Explicit table structure with wrong column types
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE t1 (a char(10), b int) ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
--replace_result $SLAVE_MYPORT SLAVE_PORT
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
connection slave;
DROP TABLE t1;
--echo #
--echo # Testing numeric data types
--echo #
# TODO: mediumint is converted to int, float is converted to double, decimal is converted to double
CREATE TABLE t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float, g double, h decimal(20,5));
SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES(100,3333,41235,1234567890,235000000000,3.14159265,3.14159265,3141.59265);
connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT';
--replace_result $SLAVE_MYPORT SLAVE_PORT
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
connection slave;
DROP TABLE t1;
# TODO: unsigned does not work
#CREATE TABLE t1 (a tinyint unsigned);
#SHOW CREATE TABLE t1;
#connection master;
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT';
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#SELECT * FROM t1;
#DROP TABLE t1;
#connection slave;
#DROP TABLE t1;
# TODO: add test for BIT
--echo #
--echo # Testing character data types
--echo #
CREATE TABLE t1 (a char(12), b varchar(12));
SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES('Welcome','Hello, World');
SELECT * FROM t1;
connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT';
--replace_result $SLAVE_MYPORT SLAVE_PORT
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
connection slave;
DROP TABLE t1;
# TODO: ERROR 1105: Unsupported column type tinytext
#CREATE TABLE t1 (a tinytext);
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#SELECT * FROM t1;
#DROP TABLE t1, t1;
# TODO: ERROR 1105: Unsupported column type mediumtext
#CREATE TABLE t1 (a mediumtext);
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#SELECT * FROM t1;
#DROP TABLE t1, t1;
# TODO: text is converted to varchar(256)
#CREATE TABLE t1 (a text);
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#SELECT * FROM t1;
#DROP TABLE t1, t1;
# TODO: ERROR 1105: Unsupported column type longtext
#CREATE TABLE t1 (a longtext);
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#SELECT * FROM t1;
#DROP TABLE t1, t1;
#TODO: add tests for ENUM
#TODO: add tests for SET
#--echo #
#--echo # Testing binary data types
#--echo #
# TODO: ERROR 1105: Unsupported column type binary
#CREATE TABLE t1 (a binary(10));
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#SELECT * FROM t1;
#DROP TABLE t1, t1;
# TODO: ERROR 1105: Unsupported column type varbinary
#CREATE TABLE t1 (a varbinary(10));
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#SELECT * FROM t1;
#DROP TABLE t1, t1;
# TODO: ERROR 1105: Unsupported column type tinyblob
#CREATE TABLE t1 (a tinyblob);
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#SELECT * FROM t1;
#DROP TABLE t1, t1;
# TODO: ERROR 1105: Unsupported column type mediumblob
#CREATE TABLE t1 (a mediumblob);
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#SELECT * FROM t1;
#DROP TABLE t1, t1;
# TODO: blob is converted to varchar(256)
#CREATE TABLE t1 (a blob);
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#SELECT * FROM t1;
#DROP TABLE t1, t1;
# TODO: ERROR 1105: Unsupported column type longblob
#CREATE TABLE t1 (a longblob);
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#SELECT * FROM t1;
#DROP TABLE t1, t1;
# TODO: ERROR 1105: Unsupported column type geometry
#CREATE TABLE t1 (a geometry);
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=127.0.0.1,user=root,port=$SLAVE_MYPORT'
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#--replace_result $SLAVE_MYPORT SLAVE_PORT
#SHOW CREATE TABLE t1;
#SELECT * FROM t1;
#DROP TABLE t1, t1;
--echo #
--echo # Testing temporal data types
--echo #
CREATE TABLE t1 (a date, b datetime, c time, d timestamp, e year);
SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES('2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23');
SELECT * FROM t1;
connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT';
--replace_result $SLAVE_MYPORT SLAVE_PORT
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
connection slave;
DROP TABLE t1;
-- source myconn_cleanup.inc

View File

@@ -67,3 +67,13 @@ SELECT * FROM v1;
DROP VIEW v1; DROP VIEW v1;
DROP TABLE t1; DROP TABLE t1;
--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
--eval CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8
SELECT * FROM t1;
DROP TABLE t1;
--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
--eval CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8
SELECT * FROM t1;
DROP TABLE t1;

View File

@@ -23,4 +23,17 @@ let $MYSQLD_DATADIR= `select @@datadir`;
SELECT Nom, Fonction FROM contact WHERE Repertoire='ascii'; SELECT Nom, Fonction FROM contact WHERE Repertoire='ascii';
DROP TABLE contact; DROP TABLE contact;
--replace_result $MYSQLD_DATADIR DATADIR
--eval CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineXLS;DBQ=$MYSQLD_DATADIR/test/contacts.xls' CHARSET=utf8 DATA_CHARSET=latin1;
--replace_result $MYSQLD_DATADIR DATADIR
SELECT * FROM t1 WHERE Table_name='CONTACT';
DROP TABLE t1;
--replace_result $MYSQLD_DATADIR DATADIR
--eval CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineXLS;DBQ=$MYSQLD_DATADIR/test/contacts.xls' CHARSET=utf8 DATA_CHARSET=latin1;
--replace_result $MYSQLD_DATADIR DATADIR
SELECT * FROM t1 WHERE Table_name='CONTACT' AND Column_name IN ('Nom','Fonction');
DROP TABLE t1;
--remove_file $MYSQLD_DATADIR/test/contacts.xls --remove_file $MYSQLD_DATADIR/test/contacts.xls

View File

@@ -52,13 +52,13 @@ SELECT fname, ftype, size FROM dir1 ORDER BY fname, ftype;
--echo # --echo #
ALTER TABLE t1 READONLY=yes; ALTER TABLE t1 READONLY=yes;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES (4,'test04'); INSERT INTO t1 VALUES (4,'test04');
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
UPDATE t1 SET b='test04' WHERE a=3; UPDATE t1 SET b='test04' WHERE a=3;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
DELETE FROM t1 WHERE a=3; DELETE FROM t1 WHERE a=3;
--error ER_GET_ERRMSG --error ER_OPEN_AS_READONLY
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ALTER TABLE t1 READONLY=no; ALTER TABLE t1 READONLY=no;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;

View File

@@ -29,7 +29,7 @@
/************************************************************************/ /************************************************************************/
/* Convert from MySQL type name to PlugDB type number */ /* Convert from MySQL type name to PlugDB type number */
/************************************************************************/ /************************************************************************/
int MYSQLtoPLG(char *typname) int MYSQLtoPLG(char *typname, char *var)
{ {
int type; int type;
@@ -56,6 +56,28 @@ int MYSQLtoPLG(char *typname)
else else
type = TYPE_ERROR; type = TYPE_ERROR;
if (var) {
// This is to make the difference between CHAR and VARCHAR
if (type == TYPE_STRING && stricmp(typname, "char"))
*var = 'V';
// This is to make the difference between temporal values
if (type == TYPE_DATE) {
if (!stricmp(typname, "date"))
*var = 'D';
else if (!stricmp(typname, "datetime"))
*var = 'A';
else if (!stricmp(typname, "timestamp"))
*var = 'S';
else if (!stricmp(typname, "time"))
*var = 'T';
else if (!stricmp(typname, "year"))
*var = 'Y';
} // endif type
} // endif var
return type; return type;
} // end of MYSQLtoPLG } // end of MYSQLtoPLG
@@ -98,14 +120,18 @@ enum enum_field_types PLGtoMYSQL(int type, bool dbf)
/************************************************************************/ /************************************************************************/
/* Convert from PlugDB type to MySQL type name */ /* Convert from PlugDB type to MySQL type name */
/************************************************************************/ /************************************************************************/
const char *PLGtoMYSQLtype(int type, bool dbf) const char *PLGtoMYSQLtype(int type, bool dbf, char v)
{ {
switch (type) { switch (type) {
case TYPE_INT: return "INT"; case TYPE_INT: return "INT";
case TYPE_SHORT: return "SMALLINT"; case TYPE_SHORT: return "SMALLINT";
case TYPE_FLOAT: return "DOUBLE"; case TYPE_FLOAT: return "DOUBLE";
case TYPE_DATE: return dbf ? "DATE" : "DATETIME"; case TYPE_DATE: return dbf ? "DATE" :
case TYPE_STRING: return "VARCHAR"; (v == 'S') ? "TIMESTAMP" :
(v == 'D') ? "DATE" :
(v == 'T') ? "TIME" :
(v == 'Y') ? "YEAR" : "DATETIME";
case TYPE_STRING: return v ? "VARCHAR" : "CHAR";
case TYPE_BIGINT: return "BIGINT"; case TYPE_BIGINT: return "BIGINT";
case TYPE_TINY: return "TINYINT"; case TYPE_TINY: return "TINYINT";
default: return "CHAR(0)"; default: return "CHAR(0)";

View File

@@ -1,9 +1,14 @@
/***********************************************************************/ /***********************************************************************/
/* Prototypes of Functions used externally. */ /* Prototypes of Functions used externally. */
/***********************************************************************/ /***********************************************************************/
#ifndef __MYUTIL__H
#define __MYUTIL__H
enum enum_field_types PLGtoMYSQL(int type, bool dbf); enum enum_field_types PLGtoMYSQL(int type, bool dbf);
const char *PLGtoMYSQLtype(int type, bool dbf); const char *PLGtoMYSQLtype(int type, bool dbf, char var = NULL);
int MYSQLtoPLG(char *typname); int MYSQLtoPLG(char *typname, char *var = NULL);
int MYSQLtoPLG(int mytype); int MYSQLtoPLG(int mytype);
char *MyDateFmt(int mytype); char *MyDateFmt(int mytype);
char *MyDateFmt(char *typname); char *MyDateFmt(char *typname);
#endif // __MYUTIL__H

View File

@@ -1,7 +1,9 @@
/***********************************************************************/ /***********************************************************************/
/* ODBC catalog function prototypes. */ /* ODBC catalog function prototypes. */
/***********************************************************************/ /***********************************************************************/
#if defined(PROMPT_OK)
char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop); char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop);
#endif // PROMPT_OK
PQRYRES ODBCDataSources(PGLOBAL g, bool info); PQRYRES ODBCDataSources(PGLOBAL g, bool info);
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
char *colpat, bool info); char *colpat, bool info);

View File

@@ -108,16 +108,18 @@ static int GetSQLCType(int type)
/***********************************************************************/ /***********************************************************************/
/* TranslateSQLType: translate a SQL Type to a PLG 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; int type;
switch (stp) { switch (stp) {
case SQL_CHAR: // 1
case SQL_VARCHAR: // 12 case SQL_VARCHAR: // 12
v = 'V';
case SQL_CHAR: // 1
type = TYPE_STRING; type = TYPE_STRING;
break; break;
case SQL_LONGVARCHAR: // (-1) case SQL_LONGVARCHAR: // (-1)
v = 'V';
type = TYPE_STRING; type = TYPE_STRING;
len = min(abs(len), 255); len = min(abs(len), 255);
break; break;
@@ -172,6 +174,7 @@ int TranslateSQLType(int stp, int prec, int& len)
return type; return type;
} // end of TranslateSQLType } // end of TranslateSQLType
#if defined(PROMPT_OK)
/***********************************************************************/ /***********************************************************************/
/* ODBCCheckConnection: Check completeness of connection string. */ /* ODBCCheckConnection: Check completeness of connection string. */
/***********************************************************************/ /***********************************************************************/
@@ -203,6 +206,7 @@ char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop)
ocp->Close(); ocp->Close();
return newdsn; // Return complete connection string return newdsn; // Return complete connection string
} // end of ODBCCheckConnection } // end of ODBCCheckConnection
#endif // PROMPT_OK
/***********************************************************************/ /***********************************************************************/
/* Allocate the structure used to refer to the result set. */ /* Allocate the structure used to refer to the result set. */
@@ -871,7 +875,8 @@ ODBConn::ODBConn(PGLOBAL g, TDBODBC *tdbp)
m_Connect = NULL; m_Connect = NULL;
m_Updatable = true; m_Updatable = true;
m_Transact = false; m_Transact = false;
m_IDQuoteChar = '\''; m_IDQuoteChar[0] = '"';
m_IDQuoteChar[1] = 0;
//*m_ErrMsg = '\0'; //*m_ErrMsg = '\0';
} // end of ODBConn } // end of ODBConn
@@ -889,7 +894,7 @@ bool ODBConn::Check(RETCODE rc)
{ {
switch (rc) { switch (rc) {
case SQL_SUCCESS_WITH_INFO: case SQL_SUCCESS_WITH_INFO:
if (trace > 1) { if (trace) {
DBX x(rc); DBX x(rc);
x.BuildErrorMessage(this, m_hstmt); x.BuildErrorMessage(this, m_hstmt);
@@ -1113,7 +1118,7 @@ bool ODBConn::Connect(DWORD Options)
if (hWnd == NULL) if (hWnd == NULL)
hWnd = GetDesktopWindow(); hWnd = GetDesktopWindow();
#else // !WIN32 #else // !WIN32
HWND hWnd = 1; HWND hWnd = (HWND)1;
#endif // !WIN32 #endif // !WIN32
PGLOBAL& g = m_G; PGLOBAL& g = m_G;
PDBUSER dup = PlgGetUser(g); PDBUSER dup = PlgGetUser(g);
@@ -1230,20 +1235,13 @@ void ODBConn::GetConnectInfo()
SQL_MODE_READ_ONLY); SQL_MODE_READ_ONLY);
#endif // 0 #endif // 0
// Cache the quote char to use when constructing SQL // Get the quote char to use when constructing SQL
char QuoteChar[2];
rc = SQLGetInfo(m_hdbc, SQL_IDENTIFIER_QUOTE_CHAR, rc = SQLGetInfo(m_hdbc, SQL_IDENTIFIER_QUOTE_CHAR,
QuoteChar, sizeof(QuoteChar), &nResult); m_IDQuoteChar, sizeof(m_IDQuoteChar), &nResult);
if (Check(rc) && nResult == 1)
m_IDQuoteChar = QuoteChar[0];
else
m_IDQuoteChar = ' ';
if (trace) if (trace)
htrc("DBMS: %s, Version: %s", htrc("DBMS: %s, Version: %s, rc=%d\n",
GetStringInfo(SQL_DBMS_NAME), GetStringInfo(SQL_DBMS_VER)); GetStringInfo(SQL_DBMS_NAME), GetStringInfo(SQL_DBMS_VER), rc);
} // end of GetConnectInfo } // end of GetConnectInfo
@@ -1511,14 +1509,16 @@ int ODBConn::PrepareSQL(char *sql)
hstmt = m_hstmt; hstmt = m_hstmt;
m_hstmt = NULL; m_hstmt = NULL;
ThrowDBX(MSG(SEQUENCE_ERROR));
} else {
rc = SQLAllocStmt(m_hdbc, &hstmt);
if (!Check(rc)) if (m_Tdb->GetAmType() != TYPE_AM_XDBC)
ThrowDBX(SQL_INVALID_HANDLE, "SQLAllocStmt"); ThrowDBX(MSG(SEQUENCE_ERROR));
} // endif hstmt } // endif m_hstmt
rc = SQLAllocStmt(m_hdbc, &hstmt);
if (!Check(rc))
ThrowDBX(SQL_INVALID_HANDLE, "SQLAllocStmt");
OnSetOptions(hstmt); OnSetOptions(hstmt);
b = true; b = true;
@@ -1565,7 +1565,7 @@ int ODBConn::PrepareSQL(char *sql)
/***********************************************************************/ /***********************************************************************/
/* Execute a prepared statement. */ /* Execute a prepared statement. */
/***********************************************************************/ /***********************************************************************/
int ODBConn::ExecuteSQL(bool x) int ODBConn::ExecuteSQL(void)
{ {
PGLOBAL& g = m_G; PGLOBAL& g = m_G;
SWORD ncol = 0; SWORD ncol = 0;
@@ -1580,26 +1580,17 @@ int ODBConn::ExecuteSQL(bool x)
if (!Check(rc)) if (!Check(rc))
ThrowDBX(rc, "SQLExecute", m_hstmt); ThrowDBX(rc, "SQLExecute", m_hstmt);
if (!Check(SQLNumResultCols(m_hstmt, &ncol))) if (!Check(rc = SQLNumResultCols(m_hstmt, &ncol)))
ThrowDBX(rc, "SQLNumResultCols", m_hstmt); ThrowDBX(rc, "SQLNumResultCols", m_hstmt);
if (ncol) { if (ncol) {
if (x) { // This should never happen while inserting
afrw = ncol; strcpy(g->Message, "Logical error while inserting");
strcpy(g->Message, "Result set column number");
} else {
// This should never happen while inserting
strcpy(g->Message, "Logical error while inserting");
} // endif ncol
} else { } else {
// Insert, Update or Delete statement // Insert, Update or Delete statement
if (!Check(SQLRowCount(m_hstmt, &afrw))) if (!Check(rc = SQLRowCount(m_hstmt, &afrw)))
ThrowDBX(rc, "SQLRowCount", m_hstmt); ThrowDBX(rc, "SQLRowCount", m_hstmt);
if (x)
strcpy(g->Message, "Affected rows");
} // endif ncol } // endif ncol
} catch(DBX *x) { } catch(DBX *x) {
@@ -1613,6 +1604,7 @@ int ODBConn::ExecuteSQL(bool x)
m_Transact = false; m_Transact = false;
} // endif m_Transact } // endif m_Transact
afrw = -1;
} // end try/catch } // end try/catch
return (int)afrw; return (int)afrw;
@@ -1667,6 +1659,112 @@ bool ODBConn::BindParam(ODBCCOL *colp)
return false; return false;
} // end of BindParam } // 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]);
sprintf(g->Message, "Remote: %s", 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 */ /* GetMetaData: constructs the result blocks containing the */
/* description of all the columns of an SQL command. */ /* description of all the columns of an SQL command. */

View File

@@ -127,7 +127,7 @@ class ODBConn : public BLOCK {
// Attributes // Attributes
public: public:
char GetQuoteChar(void) {return m_IDQuoteChar;} char *GetQuoteChar(void) {return m_IDQuoteChar;}
// Database successfully opened? // Database successfully opened?
bool IsOpen(void) {return m_hdbc != SQL_NULL_HDBC;} bool IsOpen(void) {return m_hdbc != SQL_NULL_HDBC;}
PSZ GetStringInfo(ushort infotype); PSZ GetStringInfo(ushort infotype);
@@ -142,8 +142,9 @@ class ODBConn : public BLOCK {
int ExecDirectSQL(char *sql, ODBCCOL *tocols); int ExecDirectSQL(char *sql, ODBCCOL *tocols);
int Fetch(void); int Fetch(void);
int PrepareSQL(char *sql); int PrepareSQL(char *sql);
int ExecuteSQL(bool x); int ExecuteSQL(void);
bool BindParam(ODBCCOL *colp); bool BindParam(ODBCCOL *colp);
bool ExecSQLcommand(char *sql);
int GetCatInfo(CATPARM *cap); int GetCatInfo(CATPARM *cap);
bool GetDataSources(PQRYRES qrp); bool GetDataSources(PQRYRES qrp);
bool GetDrivers(PQRYRES qrp); bool GetDrivers(PQRYRES qrp);
@@ -183,9 +184,9 @@ class ODBConn : public BLOCK {
DWORD m_QueryTimeout; DWORD m_QueryTimeout;
DWORD m_UpdateOptions; DWORD m_UpdateOptions;
DWORD m_RowsetSize; DWORD m_RowsetSize;
char m_IDQuoteChar[2];
int m_Catver; int m_Catver;
PSZ m_Connect; PSZ m_Connect;
bool m_Updatable; bool m_Updatable;
bool m_Transact; bool m_Transact;
char m_IDQuoteChar;
}; // end of ODBConn class definition }; // end of ODBConn class definition

View File

@@ -106,13 +106,20 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_DOM = 80, /* DOM access method type no */ TYPE_AM_DOM = 80, /* DOM access method type no */
TYPE_AM_DIR = 90, /* DIR access method type no */ TYPE_AM_DIR = 90, /* DIR access method type no */
TYPE_AM_ODBC = 100, /* ODBC 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_OEM = 110, /* OEM access method type no */
TYPE_AM_TBL = 115, /* TBL access method type no */ TYPE_AM_TBL = 115, /* TBL access method type no */
TYPE_AM_PIVOT = 120, /* PIVOT access method type no */ TYPE_AM_PIVOT = 120, /* PIVOT access method type no */
TYPE_AM_SRC = 121, /* PIVOT multiple column type no */ TYPE_AM_SRC = 121, /* PIVOT multiple column type no */
TYPE_AM_FNC = 122, /* PIVOT source 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_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_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_MAC = 137, /* MAC table access method type */
TYPE_AM_WMI = 139, /* WMI table access method type */ TYPE_AM_WMI = 139, /* WMI table access method type */
TYPE_AM_XCL = 140, /* SYS column 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_DMY = 172, /* DMY Dummy tables am type no */
TYPE_AM_SET = 180, /* SET Set 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_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) */ TYPE_AM_OUT = 200}; /* Output relations (storage) */
enum RECFM {RECFM_NAF = -2, /* Not a file */ enum RECFM {RECFM_NAF = -2, /* Not a file */
@@ -585,4 +593,4 @@ int global_open(GLOBAL *g, int msgid, const char *filename, int flags, int mode)
DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR name, LPCSTR dir); DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR name, LPCSTR dir);
char *MakeEscape(PGLOBAL g, char* str, char q); char *MakeEscape(PGLOBAL g, char* str, char q);
bool PushWarning(PGLOBAL, PTDBASE); bool PushWarning(PGLOBAL, PTDBASE, int level = 1);

View File

@@ -330,7 +330,7 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
// Allocate the Value Block that will contain data // Allocate the Value Block that will contain data
if (crp->Length || nonull) if (crp->Length || nonull)
crp->Kdata = AllocValBlock(g, NULL, crp->Type, maxres, crp->Kdata = AllocValBlock(g, NULL, crp->Type, maxres,
crp->Length, 0, true, blank); crp->Length, 0, true, blank, false);
else else
crp->Kdata = NULL; crp->Kdata = NULL;

View File

@@ -77,7 +77,7 @@ extern "C" int trace;
/* No conversion of block values (check = true). */ /* No conversion of block values (check = true). */
/***********************************************************************/ /***********************************************************************/
PVBLK AllocValBlock(PGLOBAL, void *, int, int, int len = 0, int prec = 0, PVBLK AllocValBlock(PGLOBAL, void *, int, int, int len = 0, int prec = 0,
bool check = true, bool blank = false); bool check = true, bool blank = false, bool un = false);
/* --------------------------- Class DOSDEF -------------------------- */ /* --------------------------- Class DOSDEF -------------------------- */

View File

@@ -524,6 +524,7 @@ bool TDBCAT::OpenDB(PGLOBAL g)
if (Initialize(g)) if (Initialize(g))
return true; return true;
Use = USE_OPEN;
return InitCol(g); return InitCol(g);
} // end of OpenDB } // end of OpenDB

View File

@@ -321,7 +321,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Portnumber = Cat->GetIntCatInfo("Port", GetDefaultPort()); Portnumber = Cat->GetIntCatInfo("Port", GetDefaultPort());
Server = Hostname; Server = Hostname;
} else if (ParseURL(g, url)) } else if (ParseURL(g, url))
return TRUE; return true;
Bind = !!Cat->GetIntCatInfo("Bind", 0); Bind = !!Cat->GetIntCatInfo("Bind", 0);
Delayed = !!Cat->GetIntCatInfo("Delayed", 0); Delayed = !!Cat->GetIntCatInfo("Delayed", 0);
@@ -344,7 +344,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
char *locdb = Database; char *locdb = Database;
if (ParseURL(g, url)) if (ParseURL(g, url))
return TRUE; return true;
Database = locdb; Database = locdb;
} // endif url } // endif url
@@ -353,9 +353,15 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
} // endif am } // endif am
if ((Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL))) if ((Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL)))
Isview = TRUE; Isview = true;
Xsrc = Cat->GetBoolCatInfo("Execsrc", FALSE); // Used for Update and Delete
Qrystr = Cat->GetStringCatInfo(g, "Query_String", "?");
Quoted = Cat->GetIntCatInfo("Quoted", 0);
// Specific for command executing tables
Xsrc = Cat->GetBoolCatInfo("Execsrc", false);
Mxr = Cat->GetIntCatInfo("Maxerr", 0);
return FALSE; return FALSE;
} // end of DefineAM } // end of DefineAM
@@ -388,6 +394,8 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
User = tdp->Username; User = tdp->Username;
Pwd = tdp->Password; Pwd = tdp->Password;
Server = tdp->Server; Server = tdp->Server;
Qrystr = tdp->Qrystr;
Quoted = max(0, tdp->Quoted);
Port = tdp->Portnumber; Port = tdp->Portnumber;
Isview = tdp->Isview; Isview = tdp->Isview;
Prep = tdp->Bind; Prep = tdp->Bind;
@@ -400,6 +408,8 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
User = NULL; User = NULL;
Pwd = NULL; Pwd = NULL;
Server = NULL; Server = NULL;
Qrystr = NULL;
Quoted = 0;
Port = 0; Port = 0;
Isview = FALSE; Isview = FALSE;
Prep = FALSE; Prep = FALSE;
@@ -424,6 +434,8 @@ TDBMYSQL::TDBMYSQL(PGLOBAL g, PTDBMY tdbp) : TDBASE(tdbp)
Srcdef = tdbp->Srcdef; Srcdef = tdbp->Srcdef;
User = tdbp->User; User = tdbp->User;
Pwd = tdbp->Pwd; Pwd = tdbp->Pwd;
Qrystr = tdbp->Qrystr;
Quoted = tdbp->Quoted;
Port = tdbp->Port; Port = tdbp->Port;
Isview = tdbp->Isview; Isview = tdbp->Isview;
Prep = tdbp->Prep; Prep = tdbp->Prep;
@@ -516,7 +528,7 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g)
strcat(strcat(strcat(strcat(Query, " FROM "), tk), Tabname), tk); strcat(strcat(strcat(strcat(Query, " FROM "), tk), Tabname), tk);
if (To_Filter) if (To_Filter)
strcat(strcat(Query, " WHERE "), To_Filter); strcat(strcat(Query, " WHERE "), To_Filter->Body);
if (trace) if (trace)
htrc("Query=%s\n", Query); htrc("Query=%s\n", Query);
@@ -610,118 +622,109 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
return FALSE; return FALSE;
} // end of MakeInsert } // end of MakeInsert
/***********************************************************************/
/* MakeCommand: make the Update or Delete statement to send to the */
/* MySQL server. Limited to remote values and filtering. */
/***********************************************************************/
int TDBMYSQL::MakeCommand(PGLOBAL g)
{
Query = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
if (Quoted > 0 || stricmp(Name, Tabname)) {
char *p, *qrystr, name[68];
bool qtd = Quoted > 0;
// Make a lower case copy of the originale query
qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1);
strlwr(strcpy(qrystr, Qrystr));
// Check whether the table name is equal to a keyword
// If so, it must be quoted in the original query
strlwr(strcat(strcat(strcpy(name, "`"), Name), "`"));
if (!strstr("`update`delete`low_priority`ignore`quick`from`", name))
strlwr(strcpy(name, Name)); // Not a keyword
if ((p = strstr(qrystr, name))) {
memcpy(Query, Qrystr, p - qrystr);
Query[p - qrystr] = 0;
if (qtd && *(p-1) == ' ')
strcat(strcat(strcat(Query, "`"), Tabname), "`");
else
strcat(Query, Tabname);
strcat(Query, Qrystr + (p - qrystr) + strlen(name));
} else {
sprintf(g->Message, "Cannot use this %s command",
(Mode == MODE_UPDATE) ? "UPDATE" : "DELETE");
return RC_FX;
} // endif p
} else
strcpy(Query, Qrystr);
return RC_OK;
} // end of MakeCommand
#if 0 #if 0
/***********************************************************************/ /***********************************************************************/
/* MakeUpdate: make the Update statement use with MySQL connection. */ /* MakeUpdate: make the Update statement use with MySQL connection. */
/* Note: currently limited to local values and filtering. */ /* Limited to remote values and filtering. */
/***********************************************************************/ /***********************************************************************/
bool TDBMYSQL::MakeUpdate(PGLOBAL g, PSELECT selist) int TDBMYSQL::MakeUpdate(PGLOBAL g)
{ {
char *setlist, *colname, *where = NULL, *tk = "`"; char *qc, cmd[8], tab[96], end[1024];
int len = 0, nset = 0;
bool b = FALSE;
PXOB xp;
PSELECT selp;
if (Query) Query = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
return FALSE; // already done memset(end, 0, sizeof(end));
if (To_Filter) if (sscanf(Qrystr, "%s `%[^`]`%1023c", cmd, tab, end) > 2 ||
if (To_Filter->CheckLocal(this)) { sscanf(Qrystr, "%s \"%[^\"]\"%1023c", cmd, tab, end) > 2)
where = (char*)PlugSubAlloc(g, NULL, 512); // Should be enough qc = "`";
*where = '\0'; else if (sscanf(Qrystr, "%s %s%1023c", cmd, tab, end) > 2
&& !stricmp(tab, Name))
qc = (Quoted) ? "`" : "";
else {
strcpy(g->Message, "Cannot use this UPDATE command");
return RC_FX;
} // endif sscanf
if (!PlugRephraseSQL(g, where, To_Filter, TYPE_FILTER, tk)) assert(!stricmp(cmd, "update"));
return TRUE; strcat(strcat(strcat(strcpy(Query, "UPDATE "), qc), Tabname), qc);
strcat(Query, end);
To_Filter = NULL; return RC_OK;
len = strlen(where);
} else {
strcpy(g->Message, MSG(NO_REF_UPDATE));
return TRUE;
} // endif Local
for (selp = selist; selp; selp = selp->GetNext_Proj())
nset++;
assert(nset);
// Allocate a pretty big buffer
setlist = (char*)PlugSubAlloc(g, NULL, 256 * nset);
*setlist = '\0';
for (selp = selist; selp; selp = selp->GetNext_Proj()) {
if (selp->GetSetType() == TYPE_COLBLK) {
colname = selp->GetSetCol()->GetName();
} else if (selp->GetSetType() == TYPE_COLUMN) {
colname = (char*)((PCOLUMN)selp->GetSetCol())->GetName();
} else {
sprintf(g->Message, MSG(BAD_SET_TYPE), selp->GetSetType());
return TRUE;
} // endif Type
if (b)
strcat(setlist, ", ");
else
b = TRUE;
strcat(strcat(strcat(strcat(setlist, tk), colname), tk), " = ");
xp = selp->GetObject();
if (!xp->CheckLocal(this)) {
strcpy(g->Message, MSG(NO_REF_UPDATE));
return TRUE;
} else if (xp->GetType() == TYPE_SUBQ)
// Cannot be correlated because CheckLocal would have failed
xp = new(g) CONSTANT(xp->GetValue());
if (!PlugRephraseSQL(g, setlist + strlen(setlist),
xp, TYPE_XOBJECT, tk))
return TRUE;
} // endfor selp
// Below 16 is enough to take care of the fixed part of the query
len += (strlen(setlist) + strlen(Tabname) + 16);
Query = (char*)PlugSubAlloc(g, NULL, len);
strcat(strcat(strcat(strcpy(Query, "UPDATE "), tk), Tabname), tk);
strcat(strcat(Query, " SET "), setlist);
if (where)
strcat(Query, where);
return FALSE;
} // end of MakeUpdate } // end of MakeUpdate
/***********************************************************************/ /***********************************************************************/
/* MakeDelete: make the Delete statement use with MySQL connection. */ /* MakeDelete: make the Delete statement used with MySQL connection. */
/* If no filtering Truncate is used because it is faster than Delete. */ /* Limited to remote filtering. */
/* However, the number of deleted lines is not returned by MySQL. */
/* Note: currently limited to local filtering. */
/***********************************************************************/ /***********************************************************************/
bool TDBMYSQL::MakeDelete(PGLOBAL g) int TDBMYSQL::MakeDelete(PGLOBAL g)
{ {
char *tk = "`"; char *qc, cmd[8], from[8], tab[96], end[512];
int len = 0;
if (Query) Query = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
return FALSE; // already done memset(end, 0, sizeof(end));
if (!To_Filter) if (sscanf(Qrystr, "%s %s `%[^`]`%511c", cmd, from, tab, end) > 2 ||
AftRows = -1; // Means "all lines deleted" sscanf(Qrystr, "%s %s \"%[^\"]\"%511c", cmd, from, tab, end) > 2)
qc = "`";
else if (sscanf(Qrystr, "%s %s %s%511c", cmd, from, tab, end) > 2)
qc = (Quoted) ? "`" : "";
else {
strcpy(g->Message, "Cannot use this DELETE command");
return RC_FX;
} // endif sscanf
// Below 16 is more than length of 'delete from ' + 3 assert(!stricmp(cmd, "delete") && !stricmp(from, "from"));
len += (strlen(Tabname) + 16); strcat(strcat(strcat(strcpy(Query, "DELETE FROM "), qc), Tabname), qc);
len += (To_Filter ? strlen(To_Filter) + 7 : 0);
Query = (char*)PlugSubAlloc(g, NULL, len);
strcpy(Query, (To_Filter) ? "DELETE FROM " : "TRUNCATE ");
strcat(strcat(strcat(Query, tk), Tabname), tk);
if (To_Filter) if (*end)
strcat(strcat(Query, " WHERE "), To_Filter); strcat(Query, end);
return FALSE; return RC_OK;
} // end of MakeDelete } // end of MakeDelete
#endif // 0 #endif // 0
@@ -751,7 +754,8 @@ int TDBMYSQL::GetMaxSize(PGLOBAL g)
Query = NULL; // Must be remade when columns are known Query = NULL; // Must be remade when columns are known
#endif // 0 #endif // 0
MaxSize = 10; // To make MySQL happy // Return 0 in mode DELETE in case of delete all.
MaxSize = (Mode == MODE_DELETE) ? 0 : 10; // To make MySQL happy
} // endif MaxSize } // endif MaxSize
return MaxSize; return MaxSize;
@@ -766,12 +770,11 @@ int TDBMYSQL::RowNumber(PGLOBAL g, bool b)
} // end of RowNumber } // end of RowNumber
/***********************************************************************/ /***********************************************************************/
/* Return 0 in mode DELETE to tell that the delete is done. */ /* Return 0 in mode UPDATE to tell that the update is done. */
/***********************************************************************/ /***********************************************************************/
int TDBMYSQL::GetProgMax(PGLOBAL g) int TDBMYSQL::GetProgMax(PGLOBAL g)
{ {
return (Mode == MODE_DELETE || Mode == MODE_UPDATE) ? 0 return (Mode == MODE_UPDATE) ? 0 : GetMaxSize(g);
: GetMaxSize(g);
} // end of GetProgMax } // end of GetProgMax
/***********************************************************************/ /***********************************************************************/
@@ -874,33 +877,17 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
m_Rc = Myc.ExecSQL(g, cmd, &w); m_Rc = Myc.ExecSQL(g, cmd, &w);
} // endif m_Rc } // endif m_Rc
#if 0 } else
} else if (Next) { // m_Rc = (Mode == MODE_DELETE) ? MakeDelete(g) : MakeUpdate(g);
strcpy(g->Message, MSG(NO_JOIN_UPDEL)); m_Rc = MakeCommand(g);
} else if (Mode == MODE_DELETE) {
strcpy(g->Message, "MySQL table delete not implemented yet\n");
bool rc = MakeDelete(g);
if (!rc && Myc.ExecSQL(g, Query) == RC_NF) {
if (!AftRows)
AftRows = Myc.GetRows();
m_Rc = RC_OK;
} // endif ExecSQL
#endif // 0
} else {
// bool rc = MakeUpdate(g, sqlp->GetProj());
strcpy(g->Message, "MySQL table delete/update not implemented yet\n");
} // endelse
if (m_Rc == RC_FX) { if (m_Rc == RC_FX) {
Myc.Close(); Myc.Close();
return TRUE; return true;
} // endif rc } // endif rc
Use = USE_OPEN; // Do it now in case we are recursively called Use = USE_OPEN;
return FALSE; return false;
} // end of OpenDB } // end of OpenDB
/***********************************************************************/ /***********************************************************************/
@@ -975,6 +962,38 @@ char *TDBMYSQL::FindFieldColumn(char *name)
return cp; return cp;
} // end of FindFieldColumn } // end of FindFieldColumn
/***********************************************************************/
/* Send an UPDATE or DELETE command to the remote server. */
/***********************************************************************/
int TDBMYSQL::SendCommand(PGLOBAL g)
{
int w;
if (Myc.ExecSQLcmd(g, Query, &w) == RC_NF) {
AftRows = Myc.m_Afrw;
sprintf(g->Message, "%s: %d affected rows", Tabname, AftRows);
PushWarning(g, this, 0); // 0 means a Note
if (trace)
htrc("%s\n", g->Message);
if (w && Myc.ExecSQL(g, "SHOW WARNINGS") == RC_OK) {
// We got warnings from the remote server
while (Myc.Fetch(g, -1) == RC_OK) {
sprintf(g->Message, "%s: (%s) %s", Tabname,
Myc.GetCharField(1), Myc.GetCharField(2));
PushWarning(g, this);
} // endwhile Fetch
Myc.FreeResult();
} // endif w
return RC_EF; // Nothing else to do
} else
return RC_FX; // Error
} // end of SendCommand
/***********************************************************************/ /***********************************************************************/
/* Data Base read routine for MYSQL access method. */ /* Data Base read routine for MYSQL access method. */
/***********************************************************************/ /***********************************************************************/
@@ -986,6 +1005,9 @@ int TDBMYSQL::ReadDB(PGLOBAL g)
htrc("MySQL ReadDB: R%d Mode=%d key=%p link=%p Kindex=%p\n", htrc("MySQL ReadDB: R%d Mode=%d key=%p link=%p Kindex=%p\n",
GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex); GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
if (Mode == MODE_UPDATE || Mode == MODE_DELETE)
return SendCommand(g);
/*********************************************************************/ /*********************************************************************/
/* Now start the reading process. */ /* Now start the reading process. */
/* Here is the place to fetch the line. */ /* Here is the place to fetch the line. */
@@ -1041,12 +1063,16 @@ int TDBMYSQL::WriteDB(PGLOBAL g)
} // end of WriteDB } // end of WriteDB
/***********************************************************************/ /***********************************************************************/
/* Data Base delete line routine for MYSQL access methods. */ /* Data Base delete all routine for MYSQL access methods. */
/***********************************************************************/ /***********************************************************************/
int TDBMYSQL::DeleteDB(PGLOBAL g, int irc) int TDBMYSQL::DeleteDB(PGLOBAL g, int irc)
{ {
strcpy(g->Message, MSG(NO_MYSQL_DELETE)); if (irc == RC_FX)
return RC_FX; // Send the DELETE (all) command to the remote table
return (SendCommand(g) == RC_FX) ? RC_FX : RC_OK;
else
return RC_OK; // Ignore
} // end of DeleteDB } // end of DeleteDB
/***********************************************************************/ /***********************************************************************/
@@ -1237,7 +1263,7 @@ void MYSQLCOL::InitBind(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
void MYSQLCOL::ReadColumn(PGLOBAL g) void MYSQLCOL::ReadColumn(PGLOBAL g)
{ {
char *buf; char *p, *buf, tim[20];
int rc; int rc;
PTDBMY tdbp = (PTDBMY)To_Tdb; PTDBMY tdbp = (PTDBMY)To_Tdb;
@@ -1257,7 +1283,14 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
if (trace) if (trace)
htrc("MySQL ReadColumn: name=%s buf=%s\n", Name, buf); htrc("MySQL ReadColumn: name=%s buf=%s\n", Name, buf);
Value->SetValue_char(buf, min((unsigned)Long, strlen(buf))); // TODO: have a true way to differenciate temporal values
if (strlen(buf) == 8)
// This is a TIME value
p = strcat(strcpy(tim, "1970-01-01 "), buf);
else
p = buf;
Value->SetValue_char(p, strlen(p));
} else { } else {
if (Nullable) if (Nullable)
Value->SetNull(true); Value->SetNull(true);
@@ -1294,8 +1327,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 ??? // Is this really useful ???
PTDB TDBMYEXC::CopyOne(PTABS t) PTDB TDBMYEXC::CopyOne(PTABS t)
@@ -1331,23 +1386,15 @@ PCOL TDBMYEXC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/ /***********************************************************************/
/* MakeCMD: make the SQL statement to send to MYSQL connection. */ /* 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 (To_Filter) {
if (Cmdcol) { if (Cmdcol) {
char col[128], cmd[1024]; if (!stricmp(Cmdcol, To_Filter->Body) &&
int n; (To_Filter->Op == OP_EQ || To_Filter->Op == OP_IN)) {
xcmd = To_Filter->Cmds;
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;
} else } else
strcpy(g->Message, "Invalid command specification filter"); strcpy(g->Message, "Invalid command specification filter");
@@ -1357,7 +1404,7 @@ char *TDBMYEXC::MakeCMD(PGLOBAL g)
} else if (!Srcdef) } else if (!Srcdef)
strcpy(g->Message, "No Srcdef default command"); strcpy(g->Message, "No Srcdef default command");
else else
xcmd = Srcdef; xcmd = new(g) CMD(g, Srcdef);
return xcmd; return xcmd;
} // end of MakeCMD } // end of MakeCMD
@@ -1368,7 +1415,7 @@ char *TDBMYEXC::MakeCMD(PGLOBAL g)
int TDBMYEXC::GetMaxSize(PGLOBAL g) int TDBMYEXC::GetMaxSize(PGLOBAL g)
{ {
if (MaxSize < 0) { if (MaxSize < 0) {
MaxSize = 1; MaxSize = 10; // a guess
} // endif MaxSize } // endif MaxSize
return MaxSize; return MaxSize;
@@ -1379,8 +1426,6 @@ int TDBMYEXC::GetMaxSize(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
bool TDBMYEXC::OpenDB(PGLOBAL g) bool TDBMYEXC::OpenDB(PGLOBAL g)
{ {
int rc;
if (Use == USE_OPEN) { if (Use == USE_OPEN) {
strcpy(g->Message, "Multiple execution is not allowed"); strcpy(g->Message, "Multiple execution is not allowed");
return true; return true;
@@ -1407,20 +1452,11 @@ bool TDBMYEXC::OpenDB(PGLOBAL g)
/*********************************************************************/ /*********************************************************************/
/* Get the command to execute. */ /* Get the command to execute. */
/*********************************************************************/ /*********************************************************************/
if (!(Query = MakeCMD(g))) { if (!(Cmdlist = MakeCMD(g))) {
Myc.Close(); Myc.Close();
return true; return true;
} // endif Query } // 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; return false;
} // end of OpenDB } // end of OpenDB
@@ -1429,7 +1465,54 @@ bool TDBMYEXC::OpenDB(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
int TDBMYEXC::ReadDB(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 } // end of ReadDB
/***********************************************************************/ /***********************************************************************/
@@ -1480,12 +1563,23 @@ void MYXCOL::ReadColumn(PGLOBAL g)
{ {
PTDBMYX tdbp = (PTDBMYX)To_Tdb; PTDBMYX tdbp = (PTDBMYX)To_Tdb;
switch (Flag) { if (tdbp->Isw) {
case 0: Value->SetValue_psz(tdbp->Query); break; char *buf = NULL;
case 1: Value->SetValue(tdbp->AftRows); break;
case 2: Value->SetValue_psz(g->Message); break; if (Flag < 3) {
default: Value->SetValue_psz("Invalid Flag"); break; buf = tdbp->Myc.GetCharField(Flag);
} // endswitch 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 } // end of ReadColumn

View File

@@ -20,6 +20,7 @@ typedef class MYSQLC *PMYC;
/***********************************************************************/ /***********************************************************************/
class MYSQLDEF : public TABDEF {/* Logical table description */ class MYSQLDEF : public TABDEF {/* Logical table description */
friend class TDBMYSQL; friend class TDBMYSQL;
friend class TDBMYEXC;
friend class TDBMCL; friend class TDBMCL;
friend class ha_connect; friend class ha_connect;
public: public:
@@ -52,7 +53,10 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
PSZ Username; /* User logon name */ PSZ Username; /* User logon name */
PSZ Password; /* Password logon info */ PSZ Password; /* Password logon info */
PSZ Server; /* PServerID */ PSZ Server; /* PServerID */
PSZ Qrystr; /* The original query */
int Portnumber; /* MySQL port number (0 = default) */ int Portnumber; /* MySQL port number (0 = default) */
int Mxr; /* Maxerr for an Exec table */
int Quoted; /* Identifier quoting level */
bool Isview; /* TRUE if this table is a MySQL view */ bool Isview; /* TRUE if this table is a MySQL view */
bool Bind; /* Use prepared statement on insert */ bool Bind; /* Use prepared statement on insert */
bool Delayed; /* Delayed insert */ bool Delayed; /* Delayed insert */
@@ -102,9 +106,11 @@ class TDBMYSQL : public TDBASE {
// Internal functions // Internal functions
bool MakeSelect(PGLOBAL g); bool MakeSelect(PGLOBAL g);
bool MakeInsert(PGLOBAL g); bool MakeInsert(PGLOBAL g);
//bool MakeUpdate(PGLOBAL g);
//bool MakeDelete(PGLOBAL g);
int BindColumns(PGLOBAL g); int BindColumns(PGLOBAL g);
int MakeCommand(PGLOBAL g);
//int MakeUpdate(PGLOBAL g);
//int MakeDelete(PGLOBAL g);
int SendCommand(PGLOBAL g);
// Members // Members
MYSQLC Myc; // MySQL connection class MYSQLC Myc; // MySQL connection class
@@ -118,6 +124,7 @@ class TDBMYSQL : public TDBASE {
char *Server; // The server ID char *Server; // The server ID
char *Query; // Points to SQL query char *Query; // Points to SQL query
char *Qbuf; // Used for not prepared insert char *Qbuf; // Used for not prepared insert
char *Qrystr; // The original query
bool Fetched; // True when fetch was done bool Fetched; // True when fetch was done
bool Isview; // True if this table is a MySQL view bool Isview; // True if this table is a MySQL view
bool Prep; // Use prepared statement on insert bool Prep; // Use prepared statement on insert
@@ -127,6 +134,7 @@ class TDBMYSQL : public TDBASE {
int N; // The current table index int N; // The current table index
int Port; // MySQL port number (0 = default) int Port; // MySQL port number (0 = default)
int Nparm; // The number of statement parameters int Nparm; // The number of statement parameters
int Quoted; // The identifier quoting level
}; // end of class TDBMYSQL }; // end of class TDBMYSQL
/***********************************************************************/ /***********************************************************************/
@@ -167,13 +175,12 @@ class MYSQLCOL : public COLBLK {
class TDBMYEXC : public TDBMYSQL { class TDBMYEXC : public TDBMYSQL {
friend class MYXCOL; friend class MYXCOL;
public: public:
// Constructor // Constructors
TDBMYEXC(PMYDEF tdp) : TDBMYSQL(tdp) {Cmdcol = NULL;} TDBMYEXC(PMYDEF tdp);
TDBMYEXC(PGLOBAL g, PTDBMYX tdbp) : TDBMYSQL(g, tdbp) TDBMYEXC(PGLOBAL g, PTDBMYX tdbp);
{Cmdcol = tdbp->Cmdcol;}
// Implementation // 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);} virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBMYEXC(g, this);}
// Methods // Methods
@@ -203,13 +210,20 @@ class TDBMYEXC : public TDBMYSQL {
protected: protected:
// Internal functions // Internal functions
char *MakeCMD(PGLOBAL g); PCMD MakeCMD(PGLOBAL g);
//bool MakeSelect(PGLOBAL g); //bool MakeSelect(PGLOBAL g);
//bool MakeInsert(PGLOBAL g); //bool MakeInsert(PGLOBAL g);
//int BindColumns(PGLOBAL g); //int BindColumns(PGLOBAL g);
// Members // Members
PCMD Cmdlist; // The commands to execute
char *Cmdcol; // The name of the Xsrc command column 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 }; // end of class TDBMYEXC
/***********************************************************************/ /***********************************************************************/

View File

@@ -495,6 +495,7 @@ bool TDBOCCUR::OpenDB(PGLOBAL g)
if (Tdbp->OpenDB(g)) if (Tdbp->OpenDB(g))
return TRUE; return TRUE;
Use = USE_OPEN;
return ViewColumnList(g); return ViewColumnList(g);
} // end of OpenDB } // end of OpenDB

View File

@@ -3,8 +3,6 @@
#include "tabutil.h" #include "tabutil.h"
#define TYPE_AM_OCCUR (AMT)128
typedef class OCCURDEF *POCCURDEF; typedef class OCCURDEF *POCCURDEF;
typedef class TDBOCCUR *PTDBOCCUR; typedef class TDBOCCUR *PTDBOCCUR;
typedef class OCCURCOL *POCCURCOL; typedef class OCCURCOL *POCCURCOL;

View File

@@ -90,8 +90,8 @@ extern int num_read, num_there, num_eq[2]; // Statistics
/***********************************************************************/ /***********************************************************************/
ODBCDEF::ODBCDEF(void) ODBCDEF::ODBCDEF(void)
{ {
Connect = Tabname = Tabowner = Tabqual = Srcdef = Qchar = NULL; Connect = Tabname = Tabowner = Tabqual = Srcdef = Qrystr = NULL;
Catver = Options = 0; Catver = Options = Quoted = 0;
Xsrc = false; Xsrc = false;
} // end of ODBCDEF constructor } // end of ODBCDEF constructor
@@ -107,9 +107,11 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Tabowner = Cat->GetStringCatInfo(g, "Owner", ""); Tabowner = Cat->GetStringCatInfo(g, "Owner", "");
Tabqual = Cat->GetStringCatInfo(g, "Qualifier", ""); Tabqual = Cat->GetStringCatInfo(g, "Qualifier", "");
Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL); Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL);
Qchar = Cat->GetStringCatInfo(g, "Qchar", ""); Qrystr = Cat->GetStringCatInfo(g, "Query_String", "?");
Catver = Cat->GetIntCatInfo("Catver", 2); Catver = Cat->GetIntCatInfo("Catver", 2);
Xsrc = Cat->GetBoolCatInfo("Execsrc", FALSE); Xsrc = Cat->GetBoolCatInfo("Execsrc", FALSE);
Mxr = Cat->GetIntCatInfo("Maxerr", 0);
Quoted = Cat->GetIntCatInfo("Quoted", 0);
Options = ODBConn::noOdbcDialog; Options = ODBConn::noOdbcDialog;
Pseudo = 2; // FILID is Ok but not ROWID Pseudo = 2; // FILID is Ok but not ROWID
return false; return false;
@@ -169,8 +171,9 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
Owner = tdp->Tabowner; Owner = tdp->Tabowner;
Qualifier = tdp->Tabqual; Qualifier = tdp->Tabqual;
Srcdef = tdp->Srcdef; Srcdef = tdp->Srcdef;
Quote = tdp->GetQchar(); Qrystr = tdp->Qrystr;
Options = tdp->Options; Options = tdp->Options;
Quoted = max(0, tdp->GetQuoted());
Rows = tdp->GetElemt(); Rows = tdp->GetElemt();
Catver = tdp->Catver; Catver = tdp->Catver;
} else { } else {
@@ -179,12 +182,14 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
Owner = NULL; Owner = NULL;
Qualifier = NULL; Qualifier = NULL;
Srcdef = NULL; Srcdef = NULL;
Quote = NULL; Qrystr = NULL;
Options = 0; Options = 0;
Quoted = 0;
Rows = 0; Rows = 0;
Catver = 0; Catver = 0;
} // endif tdp } // endif tdp
Quote = NULL;
Query = NULL; Query = NULL;
Count = NULL; Count = NULL;
//Where = NULL; //Where = NULL;
@@ -207,6 +212,7 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
Owner = tdbp->Owner; Owner = tdbp->Owner;
Qualifier = tdbp->Qualifier; Qualifier = tdbp->Qualifier;
Srcdef = tdbp->Srcdef; Srcdef = tdbp->Srcdef;
Qrystr = tdbp->Qrystr;
Quote = tdbp->Quote; Quote = tdbp->Quote;
Query = tdbp->Query; Query = tdbp->Query;
Count = tdbp->Count; Count = tdbp->Count;
@@ -214,6 +220,7 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
MulConn = tdbp->MulConn; MulConn = tdbp->MulConn;
DBQ = tdbp->DBQ; DBQ = tdbp->DBQ;
Options = tdbp->Options; Options = tdbp->Options;
Quoted = tdbp->Quoted;
Rows = tdbp->Rows; Rows = tdbp->Rows;
Fpos = tdbp->Fpos; Fpos = tdbp->Fpos;
AftRows = tdbp->AftRows; AftRows = tdbp->AftRows;
@@ -395,7 +402,7 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
// Below 14 is length of 'select ' + length of ' from ' + 1 // Below 14 is length of 'select ' + length of ' from ' + 1
len = (strlen(colist) + strlen(buf) + 14); 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 // if (tablep->GetQualifier()) This is used when using a table
// qualp = tablep->GetQualifier(); from anotherPlugDB database but // qualp = tablep->GetQualifier(); from anotherPlugDB database but
@@ -432,7 +439,7 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
strcat(sql, tabname); strcat(sql, tabname);
if (To_Filter) if (To_Filter)
strcat(strcat(sql, " WHERE "), To_Filter); strcat(strcat(sql, " WHERE "), To_Filter->Body);
return sql; return sql;
} // end of MakeSQL } // end of MakeSQL
@@ -440,21 +447,18 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
/***********************************************************************/ /***********************************************************************/
/* MakeInsert: make the Insert statement used with ODBC connection. */ /* MakeInsert: make the Insert statement used with ODBC connection. */
/***********************************************************************/ /***********************************************************************/
bool TDBODBC::MakeInsert(PGLOBAL g) char *TDBODBC::MakeInsert(PGLOBAL g)
{ {
char *colist, *valist; char *stmt, *colist, *valist;
// char *tk = "`"; // char *tk = "`";
int len = 0; int len = 0;
bool b = FALSE; bool b = FALSE;
PCOL colp; PCOL colp;
if (Query)
return false; // already done
for (colp = Columns; colp; colp = colp->GetNext()) for (colp = Columns; colp; colp = colp->GetNext())
if (colp->IsSpecial()) { if (colp->IsSpecial()) {
strcpy(g->Message, MSG(NO_ODBC_SPECOL)); strcpy(g->Message, MSG(NO_ODBC_SPECOL));
return true; return NULL;
} else { } else {
len += (strlen(colp->GetName()) + 4); len += (strlen(colp->GetName()) + 4);
((PODBCCOL)colp)->Rank = ++Nparm; ((PODBCCOL)colp)->Rank = ++Nparm;
@@ -482,18 +486,18 @@ bool TDBODBC::MakeInsert(PGLOBAL g)
// Below 32 is enough to contain the fixed part of the query // Below 32 is enough to contain the fixed part of the query
len = (strlen(TableName) + strlen(colist) + strlen(valist) + 32); len = (strlen(TableName) + strlen(colist) + strlen(valist) + 32);
Query = (char*)PlugSubAlloc(g, NULL, len); stmt = (char*)PlugSubAlloc(g, NULL, len);
strcpy(Query, "INSERT INTO "); strcpy(stmt, "INSERT INTO ");
if (Quote) if (Quote)
strcat(strcat(strcat(Query, Quote), TableName), Quote); strcat(strcat(strcat(stmt, Quote), TableName), Quote);
else else
strcat(Query, TableName); strcat(stmt, TableName);
strcat(strcat(strcat(Query, " ("), colist), ") VALUES ("); strcat(strcat(strcat(stmt, " ("), colist), ") VALUES (");
strcat(strcat(Query, valist), ")"); strcat(strcat(stmt, valist), ")");
return false; return stmt;
} // end of MakeInsert } // end of MakeInsert
/***********************************************************************/ /***********************************************************************/
@@ -514,6 +518,127 @@ bool TDBODBC::BindParameters(PGLOBAL g)
return false; return false;
} // end of BindParameters } // end of BindParameters
/***********************************************************************/
/* MakeCommand: make the Update or Delete statement to send to the */
/* MySQL server. Limited to remote values and filtering. */
/***********************************************************************/
char *TDBODBC::MakeCommand(PGLOBAL g)
{
char *p, name[68], *qc = Ocp->GetQuoteChar();
char *stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1);
bool qtd = Quoted > 0;
int i = 0, k = 0;
// Make a lower case copy of the originale query and change
// back ticks to the data source identifier quoting character
do {
qrystr[i] = (Qrystr[i] == '`') ? *qc : tolower(Qrystr[i]);
} while (Qrystr[i++]);
// Check whether the table name is equal to a keyword
// If so, it must be quoted in the original query
strlwr(strcat(strcat(strcpy(name, " "), Name), " "));
if (!strstr(" update delete low_priority ignore quick from ", name))
strlwr(strcpy(name, Name)); // Not a keyword
else
strlwr(strcat(strcat(strcpy(name, qc), Name), qc));
if ((p = strstr(qrystr, name))) {
for (i = 0; i < p - qrystr; i++)
stmt[i] = (Qrystr[i] == '`') ? *qc : Qrystr[i];
stmt[i] = 0;
k = i + (int)strlen(Name);
if (qtd && *(p-1) == ' ')
strcat(strcat(strcat(stmt, qc), TableName), qc);
else
strcat(stmt, TableName);
i = (int)strlen(stmt);
do {
stmt[i++] = (Qrystr[k] == '`') ? *qc : Qrystr[k];
} while (Qrystr[k++]);
} else {
sprintf(g->Message, "Cannot use this %s command",
(Mode == MODE_UPDATE) ? "UPDATE" : "DELETE");
return NULL;
} // endif p
return stmt;
} // end of MakeCommand
#if 0
/***********************************************************************/
/* MakeUpdate: make the SQL statement to send to ODBC connection. */
/***********************************************************************/
char *TDBODBC::MakeUpdate(PGLOBAL g)
{
char *qc, *stmt = NULL, cmd[8], tab[96], end[1024];
stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
memset(end, 0, sizeof(end));
if (sscanf(Qrystr, "%s `%[^`]`%1023c", cmd, tab, end) > 2 ||
sscanf(Qrystr, "%s \"%[^\"]\"%1023c", cmd, tab, end) > 2)
qc = Ocp->GetQuoteChar();
else if (sscanf(Qrystr, "%s %s%1023c", cmd, tab, end) > 2)
qc = (Quoted) ? Quote : "";
else {
strcpy(g->Message, "Cannot use this UPDATE command");
return NULL;
} // endif sscanf
assert(!stricmp(cmd, "update"));
strcat(strcat(strcat(strcpy(stmt, "UPDATE "), qc), TableName), qc);
for (int i = 0; end[i]; i++)
if (end[i] == '`')
end[i] = *qc;
strcat(stmt, end);
return stmt;
} // end of MakeUpdate
/***********************************************************************/
/* MakeDelete: make the SQL statement to send to ODBC connection. */
/***********************************************************************/
char *TDBODBC::MakeDelete(PGLOBAL g)
{
char *qc, *stmt = NULL, cmd[8], from[8], tab[96], end[512];
stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
memset(end, 0, sizeof(end));
if (sscanf(Qrystr, "%s %s `%[^`]`%511c", cmd, from, tab, end) > 2 ||
sscanf(Qrystr, "%s %s \"%[^\"]\"%511c", cmd, from, tab, end) > 2)
qc = Ocp->GetQuoteChar();
else if (sscanf(Qrystr, "%s %s %s%511c", cmd, from, tab, end) > 2)
qc = (Quoted) ? Quote : "";
else {
strcpy(g->Message, "Cannot use this DELETE command");
return NULL;
} // endif sscanf
assert(!stricmp(cmd, "delete") && !stricmp(from, "from"));
strcat(strcat(strcat(strcpy(stmt, "DELETE FROM "), qc), TableName), qc);
if (*end) {
for (int i = 0; end[i]; i++)
if (end[i] == '`')
end[i] = *qc;
strcat(stmt, end);
} // endif end
return stmt;
} // end of MakeDelete
#endif // 0
/***********************************************************************/ /***********************************************************************/
/* ResetSize: call by TDBMUL when calculating size estimate. */ /* ResetSize: call by TDBMUL when calculating size estimate. */
/***********************************************************************/ /***********************************************************************/
@@ -533,7 +658,7 @@ int TDBODBC::GetMaxSize(PGLOBAL g)
{ {
if (MaxSize < 0) { if (MaxSize < 0) {
// Make MariaDB happy // Make MariaDB happy
MaxSize = 100; MaxSize = (Mode == MODE_DELETE) ? 0 : 10;
#if 0 #if 0
// This is unuseful and takes time // This is unuseful and takes time
if (Srcdef) { if (Srcdef) {
@@ -616,51 +741,40 @@ bool TDBODBC::OpenDB(PGLOBAL g)
if (Ocp->Open(Connect, Options) < 1) if (Ocp->Open(Connect, Options) < 1)
return true; return true;
else if (Quoted)
Quote = Ocp->GetQuoteChar();
Use = USE_OPEN; // Do it now in case we are recursively called Use = USE_OPEN; // Do it now in case we are recursively called
/*********************************************************************/ /*********************************************************************/
/* Allocate whatever is used for getting results. */ /* Make the command and allocate whatever is used for getting results. */
/*********************************************************************/ /*********************************************************************/
if (Mode == MODE_READ) { if (Mode == MODE_READ) {
/*******************************************************************/ if ((Query = MakeSQL(g, false))) {
/* The issue here is that if max result size is needed, it must be */ for (PODBCCOL colp = (PODBCCOL)Columns; colp;
/* calculated before the result set for the final data retrieval is*/ colp = (PODBCCOL)colp->GetNext())
/* allocated and the final statement prepared so we call GetMaxSize*/ if (!colp->IsSpecial())
/* here. It can be a waste of time if the max size is not needed */ colp->AllocateBuffers(g, Rows);
/* but currently we always are asking for it (for progress info). */
/*******************************************************************/
GetMaxSize(g); // Will be set for next call
if (!Query) rc = ((Rows = Ocp->ExecDirectSQL(Query, (PODBCCOL)Columns)) < 0);
if ((Query = MakeSQL(g, false))) {
for (PODBCCOL colp = (PODBCCOL)Columns;
colp; colp = (PODBCCOL)colp->GetNext())
if (!colp->IsSpecial())
colp->AllocateBuffers(g, Rows);
} else {
Ocp->Close();
return true;
} // endif Query } // endif Query
if (!rc)
rc = ((Rows = Ocp->ExecDirectSQL(Query, (PODBCCOL)Columns)) < 0);
} else if (Mode == MODE_INSERT) { } else if (Mode == MODE_INSERT) {
if (!(rc = MakeInsert(g))) if ((Query = MakeInsert(g))) {
if (Nparm != Ocp->PrepareSQL(Query)) { if (Nparm != Ocp->PrepareSQL(Query)) {
strcpy(g->Message, MSG(PARM_CNT_MISS)); strcpy(g->Message, MSG(PARM_CNT_MISS));
rc = true; rc = true;
} else } else
rc = BindParameters(g); rc = BindParameters(g);
} else { } // endif Query
strcpy(g->Message, "No DELETE/UPDATE of ODBC tablesd");
return true;
} // endelse
if (rc) { } else if (Mode == MODE_UPDATE || Mode == MODE_DELETE)
Query = MakeCommand(g);
else
sprintf(g->Message, "Invalid mode %d", Mode);
if (!Query || rc) {
Ocp->Close(); Ocp->Close();
return true; return true;
} // endif rc } // endif rc
@@ -691,6 +805,21 @@ int TDBODBC::ReadDB(PGLOBAL g)
htrc("ODBC ReadDB: R%d Mode=%d key=%p link=%p Kindex=%p\n", htrc("ODBC ReadDB: R%d Mode=%d key=%p link=%p Kindex=%p\n",
GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex); GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
// Send the UPDATE/DELETE command to the remote table
if (!Ocp->ExecSQLcommand(Query)) {
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
if (trace)
htrc("%s\n", g->Message);
PushWarning(g, this, 0); // 0 means a Note
return RC_EF; // Nothing else to do
} else
return RC_FX; // Error
} // endif Mode
if (To_Kindex) { if (To_Kindex) {
// Direct access of ODBC tables is not implemented yet // Direct access of ODBC tables is not implemented yet
strcpy(g->Message, MSG(NO_ODBC_DIRECT)); strcpy(g->Message, MSG(NO_ODBC_DIRECT));
@@ -720,7 +849,7 @@ int TDBODBC::ReadDB(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
int TDBODBC::WriteDB(PGLOBAL g) int TDBODBC::WriteDB(PGLOBAL g)
{ {
int n = Ocp->ExecuteSQL(false); int n = Ocp->ExecuteSQL();
if (n < 0) { if (n < 0) {
AftRows = n; AftRows = n;
@@ -736,8 +865,22 @@ int TDBODBC::WriteDB(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
int TDBODBC::DeleteDB(PGLOBAL g, int irc) int TDBODBC::DeleteDB(PGLOBAL g, int irc)
{ {
strcpy(g->Message, MSG(NO_ODBC_DELETE)); if (irc == RC_FX) {
return RC_FX; // Send the DELETE (all) command to the remote table
if (!Ocp->ExecSQLcommand(Query)) {
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
if (trace)
htrc("%s\n", g->Message);
PushWarning(g, this, 0); // 0 means a Note
return RC_OK; // This is a delete all
} else
return RC_FX; // Error
} else
return RC_OK; // Ignore
} // end of DeleteDB } // end of DeleteDB
/***********************************************************************/ /***********************************************************************/
@@ -751,6 +894,7 @@ void TDBODBC::CloseDB(PGLOBAL g)
// } // endif // } // endif
if (Ocp) if (Ocp)
Ocp->Close(); Ocp->Close();
if (trace) if (trace)
@@ -934,7 +1078,7 @@ void ODBCCOL::AllocateBuffers(PGLOBAL g, int rows)
if (Buf_Type == TYPE_DATE) if (Buf_Type == TYPE_DATE)
Bufp = PlugSubAlloc(g, NULL, rows * sizeof(TIMESTAMP_STRUCT)); Bufp = PlugSubAlloc(g, NULL, rows * sizeof(TIMESTAMP_STRUCT));
else { else {
Blkp = AllocValBlock(g, NULL, Buf_Type, rows, Long+1, 0, true, false); Blkp = AllocValBlock(g, NULL, Buf_Type, rows, Long+1, 0, true, false, false);
Bufp = Blkp->GetValPointer(); Bufp = Blkp->GetValPointer();
} // endelse } // endelse
@@ -1004,6 +1148,22 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
/* Implementation of the TDBODBC class. */ /* 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 TDBXDBC::CopyOne(PTABS t)
{ {
PTDB tp; PTDB tp;
@@ -1036,23 +1196,15 @@ PCOL TDBXDBC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/ /***********************************************************************/
/* MakeCMD: make the SQL statement to send to ODBC connection. */ /* 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 (To_Filter) {
if (Cmdcol) { if (Cmdcol) {
char col[128], cmd[1024]; if (!stricmp(Cmdcol, To_Filter->Body) &&
int n; (To_Filter->Op == OP_EQ || To_Filter->Op == OP_IN)) {
xcmd = To_Filter->Cmds;
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;
} else } else
strcpy(g->Message, "Invalid command specification filter"); strcpy(g->Message, "Invalid command specification filter");
@@ -1062,7 +1214,7 @@ char *TDBXDBC::MakeCMD(PGLOBAL g)
} else if (!Srcdef) } else if (!Srcdef)
strcpy(g->Message, "No Srcdef default command"); strcpy(g->Message, "No Srcdef default command");
else else
xcmd = Srcdef; xcmd = new(g) CMD(g, Srcdef);
return xcmd; return xcmd;
} // end of MakeCMD } // end of MakeCMD
@@ -1088,12 +1240,12 @@ bool TDBXDBC::BindParameters(PGLOBAL g)
#endif // 0 #endif // 0
/***********************************************************************/ /***********************************************************************/
/* XDBC GetMaxSize: returns table size (always one row). */ /* XDBC GetMaxSize: returns table size (not always one row). */
/***********************************************************************/ /***********************************************************************/
int TDBXDBC::GetMaxSize(PGLOBAL g) int TDBXDBC::GetMaxSize(PGLOBAL g)
{ {
if (MaxSize < 0) if (MaxSize < 0)
MaxSize = 1; MaxSize = 10; // Just a guess
return MaxSize; return MaxSize;
} // end of GetMaxSize } // end of GetMaxSize
@@ -1142,19 +1294,12 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
/*********************************************************************/ /*********************************************************************/
/* Get the command to execute. */ /* Get the command to execute. */
/*********************************************************************/ /*********************************************************************/
if (!(Query = MakeCMD(g))) { if (!(Cmdlist = MakeCMD(g))) {
Ocp->Close(); Ocp->Close();
return true; return true;
} // endif Query } // endif Query
Rows = 1; Rows = 1;
if (Ocp->PrepareSQL(Query)) {
strcpy(g->Message, "Parameters not supported");
AftRows = -1;
} else
AftRows = 0;
return false; return false;
} // end of OpenDB } // end of OpenDB
@@ -1163,18 +1308,18 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
int TDBXDBC::ReadDB(PGLOBAL g) int TDBXDBC::ReadDB(PGLOBAL g)
{ {
if (trace) if (Cmdlist) {
htrc("XDBC ReadDB: query=%s\n", SVP(Query)); Query = Cmdlist->Cmd;
if (Rows--) { if (Ocp->ExecSQLcommand(Query))
if (!AftRows) Nerr++;
AftRows = Ocp->ExecuteSQL(true);
Fpos++; // Used for progress info
Cmdlist = (Nerr > Mxr) ? NULL : Cmdlist->Next;
return RC_OK;
} else } else
return RC_EF; return RC_EF;
Fpos++; // Used for progress info
return RC_OK;
} // end of ReadDB } // end of ReadDB
/***********************************************************************/ /***********************************************************************/
@@ -1186,6 +1331,15 @@ int TDBXDBC::WriteDB(PGLOBAL g)
return RC_FX; return RC_FX;
} // end of DeleteDB } // end of DeleteDB
/***********************************************************************/
/* Data Base delete line routine for ODBC access method. */
/***********************************************************************/
int TDBXDBC::DeleteDB(PGLOBAL g, int irc)
{
strcpy(g->Message, MSG(NO_ODBC_DELETE));
return RC_FX;
} // end of DeleteDB
/* --------------------------- XSRCCOL ------------------------------- */ /* --------------------------- XSRCCOL ------------------------------- */
/***********************************************************************/ /***********************************************************************/

View File

@@ -34,7 +34,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
PSZ GetTabowner(void) {return Tabowner;} PSZ GetTabowner(void) {return Tabowner;}
PSZ GetTabqual(void) {return Tabqual;} PSZ GetTabqual(void) {return Tabqual;}
PSZ GetSrcdef(void) {return Srcdef;} PSZ GetSrcdef(void) {return Srcdef;}
PSZ GetQchar(void) {return (Qchar && *Qchar) ? Qchar : NULL;} int GetQuoted(void) {return Quoted;}
int GetCatver(void) {return Catver;} int GetCatver(void) {return Catver;}
int GetOptions(void) {return Options;} int GetOptions(void) {return Options;}
@@ -50,8 +50,11 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
PSZ Tabqual; /* External table qualifier */ PSZ Tabqual; /* External table qualifier */
PSZ Srcdef; /* The source table SQL definition */ PSZ Srcdef; /* The source table SQL definition */
PSZ Qchar; /* Identifier quoting character */ PSZ Qchar; /* Identifier quoting character */
PSZ Qrystr; /* The original query */
int Catver; /* ODBC version for catalog functions */ int Catver; /* ODBC version for catalog functions */
int Options; /* Open connection options */ int Options; /* Open connection options */
int Quoted; /* Identifier quoting level */
int Mxr; /* Maxerr for an Exec table */
bool Xsrc; /* Execution type */ bool Xsrc; /* Execution type */
}; // end of ODBCDEF }; // end of ODBCDEF
@@ -96,13 +99,14 @@ class TDBODBC : public TDBASE {
protected: protected:
// Internal functions // Internal functions
int Decode(char *utf, char *buf, size_t n); int Decode(char *utf, char *buf, size_t n);
char *MakeSQL(PGLOBAL g, bool cnt); char *MakeSQL(PGLOBAL g, bool cnt);
//bool MakeUpdate(PGLOBAL g, PSELECT selist); char *MakeInsert(PGLOBAL g);
bool MakeInsert(PGLOBAL g); char *MakeCommand(PGLOBAL g);
//bool MakeDelete(PGLOBAL g);
//bool MakeFilter(PGLOBAL g, bool c); //bool MakeFilter(PGLOBAL g, bool c);
bool BindParameters(PGLOBAL g); bool BindParameters(PGLOBAL g);
//char *MakeUpdate(PGLOBAL g);
//char *MakeDelete(PGLOBAL g);
// Members // Members
ODBConn *Ocp; // Points to an ODBC connection class ODBConn *Ocp; // Points to an ODBC connection class
@@ -118,7 +122,9 @@ class TDBODBC : public TDBASE {
char *Quote; // The identifier quoting character char *Quote; // The identifier quoting character
char *MulConn; // Used for multiple ODBC tables char *MulConn; // Used for multiple ODBC tables
char *DBQ; // The address part of Connect string char *DBQ; // The address part of Connect string
char *Qrystr; // The original query
int Options; // Connect options int Options; // Connect options
int Quoted; // The identifier quoting level
int Fpos; // Position of last read record int Fpos; // Position of last read record
int AftRows; // The number of affected rows int AftRows; // The number of affected rows
int Rows; // Rowset size int Rows; // Rowset size
@@ -179,12 +185,12 @@ class TDBXDBC : public TDBODBC {
friend class XSRCCOL; friend class XSRCCOL;
friend class ODBConn; friend class ODBConn;
public: public:
// Constructor // Constructors
TDBXDBC(PODEF tdp = NULL) : TDBODBC(tdp) {Cmdcol = NULL;} TDBXDBC(PODEF tdp = NULL);
TDBXDBC(PTDBXDBC tdbp) : TDBODBC(tdbp) {Cmdcol = tdbp->Cmdcol;} TDBXDBC(PTDBXDBC tdbp);
// Implementation // Implementation
//virtual AMT GetAmType(void) {return TYPE_AM_ODBC;} virtual AMT GetAmType(void) {return TYPE_AM_XDBC;}
virtual PTDB Duplicate(PGLOBAL g) virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBXDBC(this);} {return (PTDB)new(g) TDBXDBC(this);}
@@ -204,16 +210,19 @@ class TDBXDBC : public TDBODBC {
virtual bool OpenDB(PGLOBAL g); virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g); virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g); virtual int WriteDB(PGLOBAL g);
//virtual int DeleteDB(PGLOBAL g, int irc); virtual int DeleteDB(PGLOBAL g, int irc);
//virtual void CloseDB(PGLOBAL g); //virtual void CloseDB(PGLOBAL g);
protected: protected:
// Internal functions // Internal functions
char *MakeCMD(PGLOBAL g); PCMD MakeCMD(PGLOBAL g);
//bool BindParameters(PGLOBAL g); //bool BindParameters(PGLOBAL g);
// Members // Members
PCMD Cmdlist; // The commands to execute
char *Cmdcol; // The name of the Xsrc command column 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 }; // end of class TDBXDBC
/***********************************************************************/ /***********************************************************************/

View File

@@ -607,6 +607,8 @@ bool TDBPIVOT::OpenDB(PGLOBAL g)
if (Tdbp->OpenDB(g)) if (Tdbp->OpenDB(g))
return TRUE; return TRUE;
Use = USE_OPEN; // Do it now in case we are recursively called
/*********************************************************************/ /*********************************************************************/
/* Make all required pivot columns for object views. */ /* Make all required pivot columns for object views. */
/*********************************************************************/ /*********************************************************************/

View File

@@ -295,15 +295,18 @@ bool TDBTBL::InitTableList(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTABLE tabp) 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; bool neg;
if (!filp) if (!filp)
return TRUE; 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 return TRUE; // Not handled yet
else else
fil = filp + (*filp == '(' ? 1 : 0); fil = body + (*body == '(' ? 1 : 0);
if (sscanf(fil, "TABID %s", op) != 1) if (sscanf(fil, "TABID %s", op) != 1)
return TRUE; // ignore invalid filter return TRUE; // ignore invalid filter

View File

@@ -495,6 +495,7 @@ bool TDBPRX::OpenDB(PGLOBAL g)
if (Tdbp->OpenDB(g)) if (Tdbp->OpenDB(g))
return TRUE; return TRUE;
Use = USE_OPEN;
return FALSE; return FALSE;
} // end of OpenDB } // end of OpenDB

View File

@@ -6,8 +6,6 @@
//#include "tabtbl.h" //#include "tabtbl.h"
#define TYPE_AM_PRX (AMT)129
typedef class PRXDEF *PPRXDEF; typedef class PRXDEF *PPRXDEF;
typedef class TDBPRX *PTDBPRX; typedef class TDBPRX *PTDBPRX;
typedef class XXLCOL *PXXLCOL; typedef class XXLCOL *PXXLCOL;

View File

@@ -81,7 +81,7 @@ char *strerror(int num);
/* Conversion of block values allowed conditionally for insert only. */ /* Conversion of block values allowed conditionally for insert only. */
/***********************************************************************/ /***********************************************************************/
PVBLK AllocValBlock(PGLOBAL, void *, int, int, int, int, PVBLK AllocValBlock(PGLOBAL, void *, int, int, int, int,
bool check = true, bool blank = true); bool check = true, bool blank = true, bool un = false);
/* --------------------------- Class VCTDEF -------------------------- */ /* --------------------------- Class VCTDEF -------------------------- */

View File

@@ -480,18 +480,19 @@ bool TDBWMI::Initialize(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
void TDBWMI::DoubleSlash(PGLOBAL g) void TDBWMI::DoubleSlash(PGLOBAL g)
{ {
if (To_Filter && strchr(To_Filter, '\\')) { if (To_Filter && strchr(To_Filter->Body, '\\')) {
char *buf = (char*)PlugSubAlloc(g, NULL, strlen(To_Filter) * 2); char *body = To_Filter->Body;
char *buf = (char*)PlugSubAlloc(g, NULL, strlen(body) * 2);
int i = 0, k = 0; int i = 0, k = 0;
do { do {
if (To_Filter[i] == '\\') if (body[i] == '\\')
buf[k++] = '\\'; buf[k++] = '\\';
buf[k++] = To_Filter[i]; buf[k++] = body[i];
} while (To_Filter[i++]); } while (body[i++]);
To_Filter = buf; To_Filter->Body = buf;
} // endif To_Filter } // endif To_Filter
} // end of DoubleSlash } // end of DoubleSlash
@@ -539,13 +540,13 @@ char *TDBWMI::MakeWQL(PGLOBAL g)
// Below 14 is length of 'select ' + length of ' from ' + 1 // Below 14 is length of 'select ' + length of ' from ' + 1
len = (strlen(colist) + strlen(Wclass) + 14); 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); wql = (char*)PlugSubAlloc(g, NULL, len);
strcat(strcat(strcpy(wql, "SELECT "), colist), " FROM "); strcat(strcat(strcpy(wql, "SELECT "), colist), " FROM ");
strcat(wql, Wclass); strcat(wql, Wclass);
if (To_Filter) if (To_Filter)
strcat(strcat(wql, " WHERE "), To_Filter); strcat(strcat(wql, " WHERE "), To_Filter->Body);
return wql; return wql;
} // end of MakeWQL } // end of MakeWQL
@@ -666,6 +667,8 @@ bool TDBWMI::OpenDB(PGLOBAL g)
} else } else
DoubleSlash(g); DoubleSlash(g);
Use = USE_OPEN; // Do it now in case we are recursively called
/*********************************************************************/ /*********************************************************************/
/* Initialize the WMI processing. */ /* Initialize the WMI processing. */
/*********************************************************************/ /*********************************************************************/

View File

@@ -193,6 +193,7 @@ bool TDBXCL::OpenDB(PGLOBAL g)
if (Tdbp->OpenDB(g)) if (Tdbp->OpenDB(g))
return TRUE; return TRUE;
Use = USE_OPEN;
return FALSE; return FALSE;
} // end of OpenDB } // end of OpenDB

View File

@@ -3,8 +3,6 @@
#include "tabutil.h" #include "tabutil.h"
#define TYPE_AM_XCOL (AMT)124
typedef class XCLDEF *PXCLDEF; typedef class XCLDEF *PXCLDEF;
typedef class TDBXCL *PTDBXCL; typedef class TDBXCL *PTDBXCL;
typedef class XCLCOL *PXCLCOL; typedef class XCLCOL *PXCLCOL;

View File

@@ -1,5 +1,5 @@
/************ Valblk C++ Functions Source Code File (.CPP) *************/ /************ Valblk C++ Functions Source Code File (.CPP) *************/
/* Name: VALBLK.CPP Version 1.7 */ /* Name: VALBLK.CPP Version 2.0 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */ /* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
/* */ /* */
@@ -16,7 +16,7 @@
/* types of objects, we shall have more classes to update. */ /* types of objects, we shall have more classes to update. */
/* This is why we are now using a template class for many types. */ /* This is why we are now using a template class for many types. */
/* Currently the only implemented types are PSZ, chars, int, short, */ /* Currently the only implemented types are PSZ, chars, int, short, */
/* DATE, longlong, and double. Shortly we should add more types. */ /* DATE, longlong, double and tiny. Fix numeric ones can be unsigned. */
/***********************************************************************/ /***********************************************************************/
/***********************************************************************/ /***********************************************************************/
@@ -46,7 +46,7 @@
/* AllocValBlock: allocate a VALBLK according to type. */ /* AllocValBlock: allocate a VALBLK according to type. */
/***********************************************************************/ /***********************************************************************/
PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len, PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
int prec, bool check, bool blank) int prec, bool check, bool blank, bool un)
{ {
PVBLK blkp; PVBLK blkp;
@@ -64,22 +64,38 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
break; break;
case TYPE_SHORT: case TYPE_SHORT:
blkp = new(g) TYPBLK<short>(mp, nval, type); if (un)
blkp = new(g) TYPBLK<ushort>(mp, nval, type, 0, true);
else
blkp = new(g) TYPBLK<short>(mp, nval, type);
break; break;
case TYPE_INT: case TYPE_INT:
blkp = new(g) TYPBLK<int>(mp, nval, type); if (un)
blkp = new(g) TYPBLK<uint>(mp, nval, type, 0, true);
else
blkp = new(g) TYPBLK<int>(mp, nval, type);
break; break;
case TYPE_DATE: // ????? case TYPE_DATE: // ?????
blkp = new(g) DATBLK(mp, nval); blkp = new(g) DATBLK(mp, nval);
break; break;
case TYPE_BIGINT: case TYPE_BIGINT:
blkp = new(g) TYPBLK<longlong>(mp, nval, type); if (un)
blkp = new(g) TYPBLK<ulonglong>(mp, nval, type, 0, true);
else
blkp = new(g) TYPBLK<longlong>(mp, nval, type);
break; break;
case TYPE_FLOAT: case TYPE_FLOAT:
blkp = new(g) TYPBLK<double>(mp, nval, prec, type); blkp = new(g) TYPBLK<double>(mp, nval, type, prec);
break; break;
case TYPE_TINY: case TYPE_TINY:
blkp = new(g) TYPBLK<char>(mp, nval, type); if (un)
blkp = new(g) TYPBLK<uchar>(mp, nval, type, 0, true);
else
blkp = new(g) TYPBLK<char>(mp, nval, type);
break; break;
default: default:
sprintf(g->Message, MSG(BAD_VALBLK_TYPE), type); sprintf(g->Message, MSG(BAD_VALBLK_TYPE), type);
@@ -95,12 +111,13 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
/***********************************************************************/ /***********************************************************************/
/* Constructor. */ /* Constructor. */
/***********************************************************************/ /***********************************************************************/
VALBLK::VALBLK(void *mp, int type, int nval) VALBLK::VALBLK(void *mp, int type, int nval, bool un)
{ {
Blkp = mp; Blkp = mp;
To_Nulls = NULL; To_Nulls = NULL;
Check = true; Check = true;
Nullable = false; Nullable = false;
Unsigned = un;
Type = type; Type = type;
Nval = nval; Nval = nval;
Prec = 0; Prec = 0;
@@ -195,23 +212,15 @@ void VALBLK::ChkTyp(PVBLK vb)
/* -------------------------- Class TYPBLK --------------------------- */ /* -------------------------- Class TYPBLK --------------------------- */
/***********************************************************************/ /***********************************************************************/
/* Constructors. */ /* Constructor. */
/***********************************************************************/ /***********************************************************************/
template <class TYPE> template <class TYPE>
TYPBLK<TYPE>::TYPBLK(void *mp, int nval, int type) TYPBLK<TYPE>::TYPBLK(void *mp, int nval, int type, int prec, bool un)
: VALBLK(mp, type, nval), Typp((TYPE*&)Blkp) : VALBLK(mp, type, nval, un), Typp((TYPE*&)Blkp)
{ {
Fmt = GetFmt(Type);
} // end of TYPBLK constructor
template <class TYPE>
TYPBLK<TYPE>::TYPBLK(void *mp, int nval, int prec, int type)
: VALBLK(mp, type, nval), Typp((TYPE*&)Blkp)
{
DBUG_ASSERT(Type == TYPE_FLOAT);
Prec = prec; Prec = prec;
Fmt = GetFmt(Type); Fmt = GetFmt(Type);
} // end of DBLBLK constructor } // end of TYPBLK constructor
/***********************************************************************/ /***********************************************************************/
/* Initialization routine. */ /* Initialization routine. */
@@ -249,14 +258,26 @@ template <>
int TYPBLK<int>::GetTypedValue(PVAL valp) int TYPBLK<int>::GetTypedValue(PVAL valp)
{return valp->GetIntValue();} {return valp->GetIntValue();}
template <>
uint TYPBLK<uint>::GetTypedValue(PVAL valp)
{return valp->GetUIntValue();}
template <> template <>
short TYPBLK<short>::GetTypedValue(PVAL valp) short TYPBLK<short>::GetTypedValue(PVAL valp)
{return valp->GetShortValue();} {return valp->GetShortValue();}
template <>
ushort TYPBLK<ushort>::GetTypedValue(PVAL valp)
{return valp->GetUShortValue();}
template <> template <>
longlong TYPBLK<longlong>::GetTypedValue(PVAL valp) longlong TYPBLK<longlong>::GetTypedValue(PVAL valp)
{return valp->GetBigintValue();} {return valp->GetBigintValue();}
template <>
ulonglong TYPBLK<ulonglong>::GetTypedValue(PVAL valp)
{return valp->GetUBigintValue();}
template <> template <>
double TYPBLK<double>::GetTypedValue(PVAL valp) double TYPBLK<double>::GetTypedValue(PVAL valp)
{return valp->GetFloatValue();} {return valp->GetFloatValue();}
@@ -265,6 +286,10 @@ template <>
char TYPBLK<char>::GetTypedValue(PVAL valp) char TYPBLK<char>::GetTypedValue(PVAL valp)
{return valp->GetTinyValue();} {return valp->GetTinyValue();}
template <>
uchar TYPBLK<uchar>::GetTypedValue(PVAL valp)
{return valp->GetUTinyValue();}
/***********************************************************************/ /***********************************************************************/
/* Set one value in a block from a zero terminated string. */ /* Set one value in a block from a zero terminated string. */
/***********************************************************************/ /***********************************************************************/
@@ -286,13 +311,21 @@ void TYPBLK<TYPE>::SetValue(PSZ p, int n)
template <> template <>
int TYPBLK<int>::GetTypedValue(PSZ p) {return atol(p);} int TYPBLK<int>::GetTypedValue(PSZ p) {return atol(p);}
template <> template <>
uint TYPBLK<uint>::GetTypedValue(PSZ p) {return (unsigned)atol(p);}
template <>
short TYPBLK<short>::GetTypedValue(PSZ p) {return (short)atoi(p);} short TYPBLK<short>::GetTypedValue(PSZ p) {return (short)atoi(p);}
template <> template <>
ushort TYPBLK<ushort>::GetTypedValue(PSZ p) {return (ushort)atoi(p);}
template <>
longlong TYPBLK<longlong>::GetTypedValue(PSZ p) {return atoll(p);} longlong TYPBLK<longlong>::GetTypedValue(PSZ p) {return atoll(p);}
template <> template <>
ulonglong TYPBLK<ulonglong>::GetTypedValue(PSZ p) {return (unsigned)atoll(p);}
template <>
double TYPBLK<double>::GetTypedValue(PSZ p) {return atof(p);} double TYPBLK<double>::GetTypedValue(PSZ p) {return atof(p);}
template <> template <>
char TYPBLK<char>::GetTypedValue(PSZ p) {return (char)atoi(p);} char TYPBLK<char>::GetTypedValue(PSZ p) {return (char)atoi(p);}
template <>
uchar TYPBLK<uchar>::GetTypedValue(PSZ p) {return (uchar)atoi(p);}
/***********************************************************************/ /***********************************************************************/
/* Set one value in a block from an array of characters. */ /* Set one value in a block from an array of characters. */
@@ -333,14 +366,26 @@ template <>
int TYPBLK<int>::GetTypedValue(PVBLK blk, int n) int TYPBLK<int>::GetTypedValue(PVBLK blk, int n)
{return blk->GetIntValue(n);} {return blk->GetIntValue(n);}
template <>
uint TYPBLK<uint>::GetTypedValue(PVBLK blk, int n)
{return blk->GetUIntValue(n);}
template <> template <>
short TYPBLK<short>::GetTypedValue(PVBLK blk, int n) short TYPBLK<short>::GetTypedValue(PVBLK blk, int n)
{return blk->GetShortValue(n);} {return blk->GetShortValue(n);}
template <>
ushort TYPBLK<ushort>::GetTypedValue(PVBLK blk, int n)
{return blk->GetUShortValue(n);}
template <> template <>
longlong TYPBLK<longlong>::GetTypedValue(PVBLK blk, int n) longlong TYPBLK<longlong>::GetTypedValue(PVBLK blk, int n)
{return blk->GetBigintValue(n);} {return blk->GetBigintValue(n);}
template <>
ulonglong TYPBLK<ulonglong>::GetTypedValue(PVBLK blk, int n)
{return blk->GetUBigintValue(n);}
template <> template <>
double TYPBLK<double>::GetTypedValue(PVBLK blk, int n) double TYPBLK<double>::GetTypedValue(PVBLK blk, int n)
{return blk->GetFloatValue(n);} {return blk->GetFloatValue(n);}
@@ -349,6 +394,10 @@ template <>
char TYPBLK<char>::GetTypedValue(PVBLK blk, int n) char TYPBLK<char>::GetTypedValue(PVBLK blk, int n)
{return blk->GetTinyValue(n);} {return blk->GetTinyValue(n);}
template <>
uchar TYPBLK<uchar>::GetTypedValue(PVBLK blk, int n)
{return blk->GetUTinyValue(n);}
#if 0 #if 0
/***********************************************************************/ /***********************************************************************/
/* Set many values in a block from values in another block. */ /* Set many values in a block from values in another block. */
@@ -516,6 +565,14 @@ short CHRBLK::GetShortValue(int n)
return (short)atoi((char *)GetValPtrEx(n)); return (short)atoi((char *)GetValPtrEx(n));
} // end of GetShortValue } // end of GetShortValue
/***********************************************************************/
/* Return the value of the nth element converted to ushort. */
/***********************************************************************/
ushort CHRBLK::GetUShortValue(int n)
{
return (ushort)atoi((char *)GetValPtrEx(n));
} // end of GetShortValue
/***********************************************************************/ /***********************************************************************/
/* Return the value of the nth element converted to int. */ /* Return the value of the nth element converted to int. */
/***********************************************************************/ /***********************************************************************/
@@ -524,6 +581,14 @@ int CHRBLK::GetIntValue(int n)
return atol((char *)GetValPtrEx(n)); return atol((char *)GetValPtrEx(n));
} // end of GetIntValue } // end of GetIntValue
/***********************************************************************/
/* Return the value of the nth element converted to uint. */
/***********************************************************************/
uint CHRBLK::GetUIntValue(int n)
{
return (unsigned)atol((char *)GetValPtrEx(n));
} // end of GetIntValue
/***********************************************************************/ /***********************************************************************/
/* Return the value of the nth element converted to big int. */ /* Return the value of the nth element converted to big int. */
/***********************************************************************/ /***********************************************************************/
@@ -532,6 +597,14 @@ longlong CHRBLK::GetBigintValue(int n)
return atoll((char *)GetValPtrEx(n)); return atoll((char *)GetValPtrEx(n));
} // end of GetBigintValue } // end of GetBigintValue
/***********************************************************************/
/* Return the value of the nth element converted to unsigned big int. */
/***********************************************************************/
ulonglong CHRBLK::GetUBigintValue(int n)
{
return (unsigned)atoll((char *)GetValPtrEx(n));
} // end of GetBigintValue
/***********************************************************************/ /***********************************************************************/
/* Return the value of the nth element converted to double. */ /* Return the value of the nth element converted to double. */
/***********************************************************************/ /***********************************************************************/
@@ -548,6 +621,14 @@ char CHRBLK::GetTinyValue(int n)
return (char)atoi((char *)GetValPtrEx(n)); return (char)atoi((char *)GetValPtrEx(n));
} // end of GetTinyValue } // end of GetTinyValue
/***********************************************************************/
/* Return the value of the nth element converted to unsigned tiny int.*/
/***********************************************************************/
uchar CHRBLK::GetUTinyValue(int n)
{
return (uchar)atoi((char *)GetValPtrEx(n));
} // end of GetTinyValue
/***********************************************************************/ /***********************************************************************/
/* Set one value in a block. */ /* Set one value in a block. */
/***********************************************************************/ /***********************************************************************/

View File

@@ -1,5 +1,5 @@
/*************** Valblk H Declares Source Code File (.H) ***************/ /*************** Valblk H Declares Source Code File (.H) ***************/
/* Name: VALBLK.H Version 1.9 */ /* Name: VALBLK.H Version 2.0 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */ /* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
/* */ /* */
@@ -18,8 +18,9 @@
/***********************************************************************/ /***********************************************************************/
/* Utility used to allocate value blocks. */ /* Utility used to allocate value blocks. */
/***********************************************************************/ /***********************************************************************/
DllExport PVBLK AllocValBlock(PGLOBAL, void*, int, int, int, int, bool, bool); DllExport PVBLK AllocValBlock(PGLOBAL, void*, int, int, int, int,
const char *GetFmt(int type); bool, bool, bool);
const char *GetFmt(int type, bool un = false);
/***********************************************************************/ /***********************************************************************/
/* Class VALBLK represent a base class for variable blocks. */ /* Class VALBLK represent a base class for variable blocks. */
@@ -28,7 +29,7 @@ class VALBLK : public BLOCK {
//friend void SemColData(PGLOBAL g, PSEM semp); //friend void SemColData(PGLOBAL g, PSEM semp);
public: public:
// Constructors // Constructors
VALBLK(void *mp, int type, int nval); VALBLK(void *mp, int type, int nval, bool un = false);
// Implementation // Implementation
int GetNval(void) {return Nval;} int GetNval(void) {return Nval;}
@@ -48,10 +49,14 @@ class VALBLK : public BLOCK {
virtual int GetVlen(void) = 0; virtual int GetVlen(void) = 0;
virtual PSZ GetCharValue(int n); virtual PSZ GetCharValue(int n);
virtual short GetShortValue(int n) = 0; virtual short GetShortValue(int n) = 0;
virtual ushort GetUShortValue(int n) = 0;
virtual int GetIntValue(int n) = 0; virtual int GetIntValue(int n) = 0;
virtual uint GetUIntValue(int n) = 0;
virtual longlong GetBigintValue(int n) = 0; virtual longlong GetBigintValue(int n) = 0;
virtual ulonglong GetUBigintValue(int n) = 0;
virtual double GetFloatValue(int n) = 0; virtual double GetFloatValue(int n) = 0;
virtual char GetTinyValue(int n) = 0; virtual char GetTinyValue(int n) = 0;
virtual uchar GetUTinyValue(int n) = 0;
virtual void ReAlloc(void *mp, int n) {Blkp = mp; Nval = n;} virtual void ReAlloc(void *mp, int n) {Blkp = mp; Nval = n;}
virtual void Reset(int n) = 0; virtual void Reset(int n) = 0;
virtual bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0); virtual bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
@@ -60,10 +65,14 @@ class VALBLK : public BLOCK {
// Methods // Methods
virtual void SetValue(short sval, int n) {assert(false);} virtual void SetValue(short sval, int n) {assert(false);}
virtual void SetValue(ushort sval, int n) {assert(false);}
virtual void SetValue(int lval, int n) {assert(false);} virtual void SetValue(int lval, int n) {assert(false);}
virtual void SetValue(uint lval, int n) {assert(false);}
virtual void SetValue(longlong lval, int n) {assert(false);} virtual void SetValue(longlong lval, int n) {assert(false);}
virtual void SetValue(ulonglong lval, int n) {assert(false);}
virtual void SetValue(double fval, int n) {assert(false);} virtual void SetValue(double fval, int n) {assert(false);}
virtual void SetValue(char cval, int n) {assert(false);} virtual void SetValue(char cval, int n) {assert(false);}
virtual void SetValue(uchar cval, int n) {assert(false);}
virtual void SetValue(PSZ sp, int n) {assert(false);} virtual void SetValue(PSZ sp, int n) {assert(false);}
virtual void SetValue(char *sp, uint len, int n) {assert(false);} virtual void SetValue(char *sp, uint len, int n) {assert(false);}
virtual void SetValue(PVAL valp, int n) = 0; virtual void SetValue(PVAL valp, int n) = 0;
@@ -94,6 +103,7 @@ class VALBLK : public BLOCK {
void *Blkp; // To value block void *Blkp; // To value block
bool Check; // If true SetValue types must match bool Check; // If true SetValue types must match
bool Nullable; // True if values can be null bool Nullable; // True if values can be null
bool Unsigned; // True if values are unsigned
int Type; // Type of individual values int Type; // Type of individual values
int Nval; // Max number of values in block int Nval; // Max number of values in block
int Prec; // Precision of float values int Prec; // Precision of float values
@@ -106,18 +116,22 @@ template <class TYPE>
class TYPBLK : public VALBLK { class TYPBLK : public VALBLK {
public: public:
// Constructors // Constructors
TYPBLK(void *mp, int size, int type); TYPBLK(void *mp, int size, int type, int prec = 0, bool un = false);
TYPBLK(void *mp, int size, int prec, int type); //TYPBLK(void *mp, int size, int prec, int type);
// Implementation // Implementation
virtual void Init(PGLOBAL g, bool check); virtual void Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return sizeof(TYPE);} virtual int GetVlen(void) {return sizeof(TYPE);}
//virtual PSZ GetCharValue(int n); //virtual PSZ GetCharValue(int n);
virtual short GetShortValue(int n) {return (short)Typp[n];} virtual short GetShortValue(int n) {return (short)Typp[n];}
virtual ushort GetUShortValue(int n) {return (ushort)Typp[n];}
virtual int GetIntValue(int n) {return (int)Typp[n];} virtual int GetIntValue(int n) {return (int)Typp[n];}
virtual uint GetUIntValue(int n) {return (uint)Typp[n];}
virtual longlong GetBigintValue(int n) {return (longlong)Typp[n];} virtual longlong GetBigintValue(int n) {return (longlong)Typp[n];}
virtual ulonglong GetUBigintValue(int n) {return (ulonglong)Typp[n];}
virtual double GetFloatValue(int n) {return (double)Typp[n];} virtual double GetFloatValue(int n) {return (double)Typp[n];}
virtual char GetTinyValue(int n) {return (char)Typp[n];} virtual char GetTinyValue(int n) {return (char)Typp[n];}
virtual uchar GetUTinyValue(int n) {return (uchar)Typp[n];}
virtual void Reset(int n) {Typp[n] = 0;} virtual void Reset(int n) {Typp[n] = 0;}
// Methods // Methods
@@ -125,14 +139,22 @@ class TYPBLK : public VALBLK {
virtual void SetValue(char *sp, uint len, int n); virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(short sval, int n) virtual void SetValue(short sval, int n)
{Typp[n] = (TYPE)sval; SetNull(n, false);} {Typp[n] = (TYPE)sval; SetNull(n, false);}
virtual void SetValue(ushort sval, int n)
{Typp[n] = (TYPE)sval; SetNull(n, false);}
virtual void SetValue(int lval, int n) virtual void SetValue(int lval, int n)
{Typp[n] = (TYPE)lval; SetNull(n, false);} {Typp[n] = (TYPE)lval; SetNull(n, false);}
virtual void SetValue(uint lval, int n)
{Typp[n] = (TYPE)lval; SetNull(n, false);}
virtual void SetValue(longlong lval, int n) virtual void SetValue(longlong lval, int n)
{Typp[n] = (TYPE)lval; SetNull(n, false);} {Typp[n] = (TYPE)lval; SetNull(n, false);}
virtual void SetValue(ulonglong lval, int n)
{Typp[n] = (TYPE)lval; SetNull(n, false);}
virtual void SetValue(double fval, int n) virtual void SetValue(double fval, int n)
{Typp[n] = (TYPE)fval; SetNull(n, false);} {Typp[n] = (TYPE)fval; SetNull(n, false);}
virtual void SetValue(char cval, int n) virtual void SetValue(char cval, int n)
{Typp[n] = (TYPE)cval; SetNull(n, false);} {Typp[n] = (TYPE)cval; SetNull(n, false);}
virtual void SetValue(uchar cval, int n)
{Typp[n] = (TYPE)cval; SetNull(n, false);}
virtual void SetValue(PVAL valp, int n); virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2); virtual void SetValue(PVBLK pv, int n1, int n2);
//virtual void SetValues(PVBLK pv, int k, int n); //virtual void SetValues(PVBLK pv, int k, int n);
@@ -168,10 +190,14 @@ class CHRBLK : public VALBLK {
virtual int GetVlen(void) {return Long;} virtual int GetVlen(void) {return Long;}
virtual PSZ GetCharValue(int n); virtual PSZ GetCharValue(int n);
virtual short GetShortValue(int n); virtual short GetShortValue(int n);
virtual ushort GetUShortValue(int n);
virtual int GetIntValue(int n); virtual int GetIntValue(int n);
virtual uint GetUIntValue(int n);
virtual longlong GetBigintValue(int n); virtual longlong GetBigintValue(int n);
virtual ulonglong GetUBigintValue(int n);
virtual double GetFloatValue(int n); virtual double GetFloatValue(int n);
virtual char GetTinyValue(int n); virtual char GetTinyValue(int n);
virtual uchar GetUTinyValue(int n);
virtual void Reset(int n); virtual void Reset(int n);
virtual void SetPrec(int p) {Ci = (p != 0);} virtual void SetPrec(int p) {Ci = (p != 0);}
virtual bool IsCi(void) {return Ci;} virtual bool IsCi(void) {return Ci;}
@@ -217,10 +243,14 @@ class STRBLK : public VALBLK {
virtual int GetVlen(void) {return sizeof(PSZ);} virtual int GetVlen(void) {return sizeof(PSZ);}
virtual PSZ GetCharValue(int n) {return Strp[n];} virtual PSZ GetCharValue(int n) {return Strp[n];}
virtual short GetShortValue(int n) {return (short)atoi(Strp[n]);} virtual short GetShortValue(int n) {return (short)atoi(Strp[n]);}
virtual ushort GetUShortValue(int n) {return (ushort)atoi(Strp[n]);}
virtual int GetIntValue(int n) {return atol(Strp[n]);} virtual int GetIntValue(int n) {return atol(Strp[n]);}
virtual uint GetUIntValue(int n) {return (unsigned)atol(Strp[n]);}
virtual longlong GetBigintValue(int n) {return atoll(Strp[n]);} virtual longlong GetBigintValue(int n) {return atoll(Strp[n]);}
virtual ulonglong GetUBigintValue(int n) {return (unsigned)atoll(Strp[n]);}
virtual double GetFloatValue(int n) {return atof(Strp[n]);} virtual double GetFloatValue(int n) {return atof(Strp[n]);}
virtual char GetTinyValue(int n) {return (char)atoi(Strp[n]);} virtual char GetTinyValue(int n) {return (char)atoi(Strp[n]);}
virtual uchar GetUTinyValue(int n) {return (uchar)atoi(Strp[n]);}
virtual void Reset(int n) {Strp[n] = NULL;} virtual void Reset(int n) {Strp[n] = NULL;}
// Methods // Methods

View File

@@ -1,5 +1,5 @@
/************* Value C++ Functions Source Code File (.CPP) *************/ /************* Value C++ Functions Source Code File (.CPP) *************/
/* Name: VALUE.CPP Version 2.2 */ /* Name: VALUE.CPP Version 2.3 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2001-2013 */ /* (C) Copyright to the author Olivier BERTRAND 2001-2013 */
/* */ /* */
@@ -20,7 +20,7 @@
/* functions used on one family only. The drawback is that for new */ /* functions used on one family only. The drawback is that for new */
/* types of objects, we shall have more classes to update. */ /* types of objects, we shall have more classes to update. */
/* Currently the only implemented types are STRING, INT, SHORT, TINY, */ /* Currently the only implemented types are STRING, INT, SHORT, TINY, */
/* DATE and LONGLONG. Shortly we should add at least UNSIGNED types. */ /* DATE and LONGLONG. Recently we added some UNSIGNED types. */
/***********************************************************************/ /***********************************************************************/
/***********************************************************************/ /***********************************************************************/
@@ -92,40 +92,12 @@ PSZ strlwr(PSZ s);
} }
#endif // !WIN32 #endif // !WIN32
#ifdef NOT_USED
/***********************************************************************/
/* Returns the bitmap representing the conditions that must not be */
/* met when returning from TestValue for a given operator. */
/* Bit one is EQ, bit 2 is LT, and bit 3 is GT. */
/***********************************************************************/
static BYTE OpBmp(PGLOBAL g, OPVAL opc)
{
BYTE bt;
switch (opc) {
case OP_IN:
case OP_EQ: bt = 0x06; break;
case OP_NE: bt = 0x01; break;
case OP_GT: bt = 0x03; break;
case OP_GE: bt = 0x02; break;
case OP_LT: bt = 0x05; break;
case OP_LE: bt = 0x04; break;
case OP_EXIST: bt = 0x00; break;
default:
sprintf(g->Message, MSG(BAD_FILTER_OP), opc);
longjmp(g->jumper[g->jump_level], 777);
} // endswitch opc
return bt;
} // end of OpBmp
#endif
/***********************************************************************/ /***********************************************************************/
/* GetTypeName: returns the PlugDB internal type name. */ /* GetTypeName: returns the PlugDB internal type name. */
/***********************************************************************/ /***********************************************************************/
PSZ GetTypeName(int type) PSZ GetTypeName(int type)
{ {
PSZ name = "UNKNOWN"; PSZ name;
switch (type) { switch (type) {
case TYPE_STRING: name = "CHAR"; break; case TYPE_STRING: name = "CHAR"; break;
@@ -135,6 +107,7 @@ PSZ GetTypeName(int type)
case TYPE_DATE: name = "DATE"; break; case TYPE_DATE: name = "DATE"; break;
case TYPE_FLOAT: name = "FLOAT"; break; case TYPE_FLOAT: name = "FLOAT"; break;
case TYPE_TINY: name = "TINY"; break; case TYPE_TINY: name = "TINY"; break;
default: name = "UNKNOWN"; break;
} // endswitch type } // endswitch type
return name; return name;
@@ -153,7 +126,6 @@ int GetTypeSize(int type, int len)
case TYPE_DATE: len = sizeof(int); break; case TYPE_DATE: len = sizeof(int); break;
case TYPE_FLOAT: len = sizeof(double); break; case TYPE_FLOAT: len = sizeof(double); break;
case TYPE_TINY: len = sizeof(char); break; case TYPE_TINY: len = sizeof(char); break;
break;
default: len = 0; default: len = 0;
} // endswitch type } // endswitch type
@@ -236,21 +208,22 @@ bool IsTypeNum(int type)
/***********************************************************************/ /***********************************************************************/
/* GetFmt: returns the format to use with a typed value. */ /* GetFmt: returns the format to use with a typed value. */
/***********************************************************************/ /***********************************************************************/
const char *GetFmt(int type) const char *GetFmt(int type, bool un)
{ {
const char *fmt; const char *fmt;
switch (type) { switch (type) {
case TYPE_STRING: fmt = "%s"; break; case TYPE_STRING: fmt = "%s"; break;
case TYPE_SHORT: fmt = "%hd"; break; case TYPE_SHORT: fmt = (un) ? "%hu" : "%hd"; break;
case TYPE_BIGINT: fmt = "%lld"; break; case TYPE_BIGINT: fmt = (un) ? "%llu" : "%lld"; break;
case TYPE_FLOAT: fmt = "%.*lf"; break; case TYPE_FLOAT: fmt = "%.*lf"; break;
default: fmt = "%d"; break; default: fmt = (un) ? "%u" : "%d"; break;
} // endswitch Type } // endswitch Type
return fmt; return fmt;
} // end of GetFmt } // end of GetFmt
#if 0
/***********************************************************************/ /***********************************************************************/
/* ConvertType: what this function does is to determine the type to */ /* ConvertType: what this function does is to determine the type to */
/* which should be converted a value so no precision would be lost. */ /* which should be converted a value so no precision would be lost. */
@@ -297,6 +270,7 @@ int ConvertType(int target, int type, CONV kind, bool match)
} // endswitch kind } // endswitch kind
} // end of ConvertType } // end of ConvertType
#endif // 0
/***********************************************************************/ /***********************************************************************/
/* AllocateConstant: allocates a constant Value. */ /* AllocateConstant: allocates a constant Value. */
@@ -322,7 +296,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type)
valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT); valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT);
break; break;
case TYPE_FLOAT: case TYPE_FLOAT:
valp = new(g) TYPVAL<double>(*(double *)value, TYPE_FLOAT); valp = new(g) TYPVAL<double>(*(double *)value, TYPE_FLOAT, 2);
break; break;
case TYPE_TINY: case TYPE_TINY:
valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY); valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY);
@@ -339,8 +313,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type)
/***********************************************************************/ /***********************************************************************/
/* Allocate a variable Value according to type, length and precision. */ /* Allocate a variable Value according to type, length and precision. */
/***********************************************************************/ /***********************************************************************/
PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, PSZ fmt)
PSZ dom, PCATLG cat)
{ {
PVAL valp; PVAL valp;
@@ -349,22 +322,38 @@ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec,
valp = new(g) TYPVAL<PSZ>(g, (PSZ)NULL, len, prec); valp = new(g) TYPVAL<PSZ>(g, (PSZ)NULL, len, prec);
break; break;
case TYPE_DATE: case TYPE_DATE:
valp = new(g) DTVAL(g, len, prec, dom); valp = new(g) DTVAL(g, len, prec, fmt);
break; break;
case TYPE_INT: case TYPE_INT:
valp = new(g) TYPVAL<int>((int)0, TYPE_INT); if (prec)
valp = new(g) TYPVAL<uint>((uint)0, TYPE_INT, 0, true);
else
valp = new(g) TYPVAL<int>((int)0, TYPE_INT);
break; break;
case TYPE_BIGINT: case TYPE_BIGINT:
valp = new(g) TYPVAL<longlong>((longlong)0, TYPE_BIGINT); if (prec)
valp = new(g) TYPVAL<ulonglong>((ulonglong)0, TYPE_BIGINT, 0, true);
else
valp = new(g) TYPVAL<longlong>((longlong)0, TYPE_BIGINT);
break; break;
case TYPE_SHORT: case TYPE_SHORT:
valp = new(g) TYPVAL<short>((short)0, TYPE_SHORT); if (prec)
valp = new(g) TYPVAL<ushort>((ushort)0, TYPE_SHORT, 0, true);
else
valp = new(g) TYPVAL<short>((short)0, TYPE_SHORT);
break; break;
case TYPE_FLOAT: case TYPE_FLOAT:
valp = new(g) TYPVAL<double>(0.0, prec, TYPE_FLOAT); valp = new(g) TYPVAL<double>(0.0, TYPE_FLOAT, prec);
break; break;
case TYPE_TINY: case TYPE_TINY:
valp = new(g) TYPVAL<char>((char)0, TYPE_TINY); if (prec)
valp = new(g) TYPVAL<uchar>((uchar)0, TYPE_TINY, 0, true);
else
valp = new(g) TYPVAL<char>((char)0, TYPE_TINY);
break; break;
default: default:
sprintf(g->Message, MSG(BAD_VALUE_TYPE), type); sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
@@ -379,9 +368,10 @@ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec,
/* Allocate a constant Value converted to newtype. */ /* Allocate a constant Value converted to newtype. */
/* Can also be used to copy a Value eventually converted. */ /* Can also be used to copy a Value eventually converted. */
/***********************************************************************/ /***********************************************************************/
PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype) PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
{ {
PSZ p, sp; PSZ p, sp;
bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned();
if (newtype == TYPE_VOID) // Means allocate a value of the same type if (newtype == TYPE_VOID) // Means allocate a value of the same type
newtype = valp->GetType(); newtype = valp->GetType();
@@ -396,22 +386,42 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype)
valp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec()); valp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec());
break; break;
case TYPE_SHORT: case TYPE_SHORT:
valp = new(g) TYPVAL<short>(valp->GetShortValue(), TYPE_SHORT); if (un)
valp = new(g) TYPVAL<ushort>(valp->GetUShortValue(),
TYPE_SHORT, 0, true);
else
valp = new(g) TYPVAL<short>(valp->GetShortValue(), TYPE_SHORT);
break; break;
case TYPE_INT: case TYPE_INT:
valp = new(g) TYPVAL<int>(valp->GetIntValue(), TYPE_INT); if (un)
valp = new(g) TYPVAL<uint>(valp->GetUIntValue(), TYPE_INT, 0, true);
else
valp = new(g) TYPVAL<int>(valp->GetIntValue(), TYPE_INT);
break; break;
case TYPE_BIGINT: case TYPE_BIGINT:
valp = new(g) TYPVAL<longlong>(valp->GetBigintValue(), TYPE_BIGINT); if (un)
valp = new(g) TYPVAL<ulonglong>(valp->GetUBigintValue(),
TYPE_BIGINT, 0, true);
else
valp = new(g) TYPVAL<longlong>(valp->GetBigintValue(), TYPE_BIGINT);
break; break;
case TYPE_DATE: case TYPE_DATE:
valp = new(g) DTVAL(g, valp->GetIntValue()); valp = new(g) DTVAL(g, valp->GetIntValue());
break; break;
case TYPE_FLOAT: case TYPE_FLOAT:
valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_FLOAT); valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_FLOAT,
valp->GetValPrec());
break; break;
case TYPE_TINY: case TYPE_TINY:
valp = new(g) TYPVAL<char>(valp->GetTinyValue(), TYPE_TINY); if (un)
valp = new(g) TYPVAL<uchar>(valp->GetUTinyValue(),
TYPE_TINY, 0, true);
else
valp = new(g) TYPVAL<char>(valp->GetTinyValue(), TYPE_TINY);
break; break;
default: default:
sprintf(g->Message, MSG(BAD_VALUE_TYPE), newtype); sprintf(g->Message, MSG(BAD_VALUE_TYPE), newtype);
@@ -428,14 +438,15 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype)
/***********************************************************************/ /***********************************************************************/
/* Class VALUE protected constructor. */ /* Class VALUE protected constructor. */
/***********************************************************************/ /***********************************************************************/
VALUE::VALUE(int type) : Type(type) VALUE::VALUE(int type, bool un) : Type(type)
{ {
Fmt = GetFmt(Type);
Xfmt = GetXfmt();
Null = false; Null = false;
Nullable = false; Nullable = false;
Unsigned = un;
Clen = 0; Clen = 0;
Prec = 0; Prec = 0;
Fmt = GetFmt(Type, Unsigned);
Xfmt = GetXfmt();
} // end of VALUE constructor } // end of VALUE constructor
/***********************************************************************/ /***********************************************************************/
@@ -446,11 +457,11 @@ const char *VALUE::GetXfmt(void)
const char *fmt; const char *fmt;
switch (Type) { switch (Type) {
case TYPE_STRING: fmt = "%*s"; break; case TYPE_STRING: fmt = "%*s"; break;
case TYPE_SHORT: fmt = "%*hd"; break; case TYPE_SHORT: fmt = (Unsigned) ? "%*hu" : "%*hd"; break;
case TYPE_BIGINT: fmt = "%*lld"; break; case TYPE_BIGINT: fmt = (Unsigned) ? "%*llu" : "%*lld"; break;
case TYPE_FLOAT: fmt = "%*.*lf"; break; case TYPE_FLOAT: fmt = "%*.*lf"; break;
default: fmt = "%*d"; break; default: fmt = (Unsigned) ? "%*u" : "%*d"; break;
} // endswitch Type } // endswitch Type
return fmt; return fmt;
@@ -462,22 +473,11 @@ const char *VALUE::GetXfmt(void)
/* TYPVAL public constructor from a constant typed value. */ /* TYPVAL public constructor from a constant typed value. */
/***********************************************************************/ /***********************************************************************/
template <class TYPE> template <class TYPE>
TYPVAL<TYPE>::TYPVAL(TYPE n, int type) : VALUE(type) TYPVAL<TYPE>::TYPVAL(TYPE n, int type, int prec, bool un)
: VALUE(type, un)
{ {
Tval = n; Tval = n;
Clen = sizeof(TYPE); Clen = sizeof(TYPE);
Prec = (Type == TYPE_FLOAT) ? 2 : 0;
} // end of TYPVAL constructor
/***********************************************************************/
/* TYPVAL public constructor from typed value. */
/***********************************************************************/
template <class TYPE>
TYPVAL<TYPE>::TYPVAL(TYPE n, int prec, int type) : VALUE(type)
{
assert(Type == TYPE_FLOAT);
Tval = n;
Clen = sizeof(TYPE);
Prec = prec; Prec = prec;
} // end of TYPVAL constructor } // end of TYPVAL constructor
@@ -522,14 +522,26 @@ template <>
short TYPVAL<short>::GetTypedValue(PVAL valp) short TYPVAL<short>::GetTypedValue(PVAL valp)
{return valp->GetShortValue();} {return valp->GetShortValue();}
template <>
ushort TYPVAL<ushort>::GetTypedValue(PVAL valp)
{return valp->GetUShortValue();}
template <> template <>
int TYPVAL<int>::GetTypedValue(PVAL valp) int TYPVAL<int>::GetTypedValue(PVAL valp)
{return valp->GetIntValue();} {return valp->GetIntValue();}
template <>
uint TYPVAL<uint>::GetTypedValue(PVAL valp)
{return valp->GetUIntValue();}
template <> template <>
longlong TYPVAL<longlong>::GetTypedValue(PVAL valp) longlong TYPVAL<longlong>::GetTypedValue(PVAL valp)
{return valp->GetBigintValue();} {return valp->GetBigintValue();}
template <>
ulonglong TYPVAL<ulonglong>::GetTypedValue(PVAL valp)
{return valp->GetUBigintValue();}
template <> template <>
double TYPVAL<double>::GetTypedValue(PVAL valp) double TYPVAL<double>::GetTypedValue(PVAL valp)
{return valp->GetFloatValue();} {return valp->GetFloatValue();}
@@ -538,6 +550,10 @@ template <>
char TYPVAL<char>::GetTypedValue(PVAL valp) char TYPVAL<char>::GetTypedValue(PVAL valp)
{return valp->GetTinyValue();} {return valp->GetTinyValue();}
template <>
uchar TYPVAL<uchar>::GetTypedValue(PVAL valp)
{return valp->GetUTinyValue();}
/***********************************************************************/ /***********************************************************************/
/* TYPVAL SetValue: convert chars extracted from a line to TYPE value.*/ /* TYPVAL SetValue: convert chars extracted from a line to TYPE value.*/
/***********************************************************************/ /***********************************************************************/
@@ -545,7 +561,7 @@ template <class TYPE>
void TYPVAL<TYPE>::SetValue_char(char *p, int n) void TYPVAL<TYPE>::SetValue_char(char *p, int n)
{ {
char *p2, buf[32]; char *p2, buf[32];
bool minus; bool minus = false;
for (p2 = p + n; p < p2 && *p == ' '; p++) ; for (p2 = p + n; p < p2 && *p == ' '; p++) ;
@@ -570,7 +586,7 @@ void TYPVAL<TYPE>::SetValue_char(char *p, int n)
} // endswitch *p } // endswitch *p
if (minus && Tval) if (minus && Tval)
Tval = - Tval; Tval = (-(signed)Tval) ? -(signed)Tval : Tval;
if (trace > 1) if (trace > 1)
htrc(strcat(strcat(strcpy(buf, " setting %s to: "), Fmt), "\n"), htrc(strcat(strcat(strcpy(buf, " setting %s to: "), Fmt), "\n"),
@@ -622,13 +638,21 @@ void TYPVAL<TYPE>::SetValue_psz(PSZ s)
template <> template <>
int TYPVAL<int>::GetTypedValue(PSZ s) {return atol(s);} int TYPVAL<int>::GetTypedValue(PSZ s) {return atol(s);}
template <> template <>
uint TYPVAL<uint>::GetTypedValue(PSZ s) {return (unsigned)atol(s);}
template <>
short TYPVAL<short>::GetTypedValue(PSZ s) {return (short)atoi(s);} short TYPVAL<short>::GetTypedValue(PSZ s) {return (short)atoi(s);}
template <> template <>
ushort TYPVAL<ushort>::GetTypedValue(PSZ s) {return (ushort)atoi(s);}
template <>
longlong TYPVAL<longlong>::GetTypedValue(PSZ s) {return atoll(s);} longlong TYPVAL<longlong>::GetTypedValue(PSZ s) {return atoll(s);}
template <> template <>
ulonglong TYPVAL<ulonglong>::GetTypedValue(PSZ s) {return (unsigned)atoll(s);}
template <>
double TYPVAL<double>::GetTypedValue(PSZ s) {return atof(s);} double TYPVAL<double>::GetTypedValue(PSZ s) {return atof(s);}
template <> template <>
char TYPVAL<char>::GetTypedValue(PSZ s) {return (char)atoi(s);} char TYPVAL<char>::GetTypedValue(PSZ s) {return (char)atoi(s);}
template <>
uchar TYPVAL<uchar>::GetTypedValue(PSZ s) {return (uchar)atoi(s);}
/***********************************************************************/ /***********************************************************************/
/* TYPVAL SetValue: set value with a TYPE extracted from a block. */ /* TYPVAL SetValue: set value with a TYPE extracted from a block. */
@@ -644,14 +668,26 @@ template <>
int TYPVAL<int>::GetTypedValue(PVBLK blk, int n) int TYPVAL<int>::GetTypedValue(PVBLK blk, int n)
{return blk->GetIntValue(n);} {return blk->GetIntValue(n);}
template <>
uint TYPVAL<uint>::GetTypedValue(PVBLK blk, int n)
{return (unsigned)blk->GetIntValue(n);}
template <> template <>
short TYPVAL<short>::GetTypedValue(PVBLK blk, int n) short TYPVAL<short>::GetTypedValue(PVBLK blk, int n)
{return blk->GetShortValue(n);} {return blk->GetShortValue(n);}
template <>
ushort TYPVAL<ushort>::GetTypedValue(PVBLK blk, int n)
{return (unsigned)blk->GetShortValue(n);}
template <> template <>
longlong TYPVAL<longlong>::GetTypedValue(PVBLK blk, int n) longlong TYPVAL<longlong>::GetTypedValue(PVBLK blk, int n)
{return blk->GetBigintValue(n);} {return blk->GetBigintValue(n);}
template <>
ulonglong TYPVAL<ulonglong>::GetTypedValue(PVBLK blk, int n)
{return (unsigned)blk->GetBigintValue(n);}
template <> template <>
double TYPVAL<double>::GetTypedValue(PVBLK blk, int n) double TYPVAL<double>::GetTypedValue(PVBLK blk, int n)
{return blk->GetFloatValue(n);} {return blk->GetFloatValue(n);}
@@ -660,6 +696,10 @@ template <>
char TYPVAL<char>::GetTypedValue(PVBLK blk, int n) char TYPVAL<char>::GetTypedValue(PVBLK blk, int n)
{return blk->GetTinyValue(n);} {return blk->GetTinyValue(n);}
template <>
uchar TYPVAL<uchar>::GetTypedValue(PVBLK blk, int n)
{return (unsigned)blk->GetTinyValue(n);}
/***********************************************************************/ /***********************************************************************/
/* TYPVAL SetBinValue: with bytes extracted from a line. */ /* TYPVAL SetBinValue: with bytes extracted from a line. */
/***********************************************************************/ /***********************************************************************/
@@ -684,7 +724,7 @@ bool TYPVAL<TYPE>::GetBinValue(void *buf, int buflen, bool go)
// be different from the variable length because no conversion is done. // be different from the variable length because no conversion is done.
// Therefore this test is useless anyway. // Therefore this test is useless anyway.
//#if defined(_DEBUG) //#if defined(_DEBUG)
// if (sizeof(int) > buflen) // if (sizeof(TYPE) > buflen)
// return true; // return true;
//#endif //#endif
@@ -730,6 +770,7 @@ char *TYPVAL<double>::GetCharString(char *p)
return p; return p;
} // end of GetCharString } // end of GetCharString
#if 0
/***********************************************************************/ /***********************************************************************/
/* TYPVAL GetShortString: get short representation of a typed value. */ /* TYPVAL GetShortString: get short representation of a typed value. */
/***********************************************************************/ /***********************************************************************/
@@ -779,6 +820,7 @@ char *TYPVAL<TYPE>::GetTinyString(char *p, int n)
sprintf(p, "%*d", n, (int)(char)Tval); sprintf(p, "%*d", n, (int)(char)Tval);
return p; return p;
} // end of GetIntString } // end of GetIntString
#endif // 0
/***********************************************************************/ /***********************************************************************/
/* TYPVAL compare value with another Value. */ /* TYPVAL compare value with another Value. */
@@ -875,7 +917,6 @@ TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING)
TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c) TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
: VALUE(TYPE_STRING) : VALUE(TYPE_STRING)
{ {
assert(Type == TYPE_STRING);
Len = (g) ? n : strlen(s); Len = (g) ? n : strlen(s);
if (!s) { if (!s) {
@@ -981,6 +1022,24 @@ void TYPVAL<PSZ>::SetValue(int n)
Null = false; Null = false;
} // end of SetValue } // end of SetValue
/***********************************************************************/
/* STRING SetValue: get the character representation of an uint. */
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(uint n)
{
char buf[16];
PGLOBAL& g = Global;
int k = sprintf(buf, "%u", n);
if (k > Len) {
sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
longjmp(g->jumper[g->jump_level], 138);
} else
SetValue_psz(buf);
Null = false;
} // end of SetValue
/***********************************************************************/ /***********************************************************************/
/* STRING SetValue: get the character representation of a short int. */ /* STRING SetValue: get the character representation of a short int. */
/***********************************************************************/ /***********************************************************************/
@@ -990,6 +1049,15 @@ void TYPVAL<PSZ>::SetValue(short i)
Null = false; Null = false;
} // end of SetValue } // end of SetValue
/***********************************************************************/
/* STRING SetValue: get the character representation of a ushort int. */
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(ushort i)
{
SetValue((uint)i);
Null = false;
} // end of SetValue
/***********************************************************************/ /***********************************************************************/
/* STRING SetValue: get the character representation of a big integer.*/ /* STRING SetValue: get the character representation of a big integer.*/
/***********************************************************************/ /***********************************************************************/
@@ -1008,6 +1076,24 @@ void TYPVAL<PSZ>::SetValue(longlong n)
Null = false; Null = false;
} // end of SetValue } // end of SetValue
/***********************************************************************/
/* STRING SetValue: get the character representation of a big integer.*/
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(ulonglong n)
{
char buf[24];
PGLOBAL& g = Global;
int k = sprintf(buf, "%llu", n);
if (k > Len) {
sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
longjmp(g->jumper[g->jump_level], 138);
} else
SetValue_psz(buf);
Null = false;
} // end of SetValue
/***********************************************************************/ /***********************************************************************/
/* STRING SetValue: get the character representation of a double. */ /* STRING SetValue: get the character representation of a double. */
/***********************************************************************/ /***********************************************************************/
@@ -1042,6 +1128,15 @@ void TYPVAL<PSZ>::SetValue(char c)
Null = false; Null = false;
} // end of SetValue } // end of SetValue
/***********************************************************************/
/* STRING SetValue: get the character representation of a tiny int. */
/***********************************************************************/
void TYPVAL<PSZ>::SetValue(uchar c)
{
SetValue((uint)c);
Null = false;
} // end of SetValue
/***********************************************************************/ /***********************************************************************/
/* STRING SetBinValue: fill string with chars extracted from a line. */ /* STRING SetBinValue: fill string with chars extracted from a line. */
/***********************************************************************/ /***********************************************************************/
@@ -1086,6 +1181,7 @@ char *TYPVAL<PSZ>::GetCharString(char *p)
return Strp; return Strp;
} // end of GetCharString } // end of GetCharString
#if 0
/***********************************************************************/ /***********************************************************************/
/* STRING GetShortString: get short representation of a char value. */ /* STRING GetShortString: get short representation of a char value. */
/***********************************************************************/ /***********************************************************************/
@@ -1130,6 +1226,7 @@ char *TYPVAL<PSZ>::GetTinyString(char *p, int n)
sprintf(p, "%*d", n, (Null) ? 0 : (char)atoi(Strp)); sprintf(p, "%*d", n, (Null) ? 0 : (char)atoi(Strp));
return p; return p;
} // end of GetIntString } // end of GetIntString
#endif // 0
/***********************************************************************/ /***********************************************************************/
/* STRING compare value with another Value. */ /* STRING compare value with another Value. */

View File

@@ -1,5 +1,5 @@
/**************** Value H Declares Source Code File (.H) ***************/ /**************** Value H Declares Source Code File (.H) ***************/
/* Name: VALUE.H Version 1.9 */ /* Name: VALUE.H Version 2.0 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2001-2013 */ /* (C) Copyright to the author Olivier BERTRAND 2001-2013 */
/* */ /* */
@@ -45,16 +45,16 @@ DllExport PSZ GetTypeName(int);
DllExport int GetTypeSize(int, int); DllExport int GetTypeSize(int, int);
#ifdef ODBC_SUPPORT #ifdef ODBC_SUPPORT
/* This function is exported for use in EOM table type DLLs */ /* 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 #endif
DllExport char *GetFormatType(int); DllExport char *GetFormatType(int);
DllExport int GetFormatType(char); DllExport int GetFormatType(char);
DllExport bool IsTypeChar(int type); DllExport bool IsTypeChar(int type);
DllExport bool IsTypeNum(int type); DllExport bool IsTypeNum(int type);
DllExport int ConvertType(int, int, CONV, bool match = false); //lExport int ConvertType(int, int, CONV, bool match = false);
DllExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID); DllExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID, int = 0);
DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 2, DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 0,
PSZ dom = NULL, PCATLG cat = NULL); PSZ fmt = NULL);
/***********************************************************************/ /***********************************************************************/
/* Class VALUE represents a constant or variable of any valid type. */ /* Class VALUE represents a constant or variable of any valid type. */
@@ -68,6 +68,7 @@ class DllExport VALUE : public BLOCK {
virtual bool IsTypeNum(void) = 0; virtual bool IsTypeNum(void) = 0;
virtual bool IsZero(void) = 0; virtual bool IsZero(void) = 0;
virtual bool IsCi(void) {return false;} virtual bool IsCi(void) {return false;}
virtual bool IsUnsigned(void) {return Unsigned;}
virtual void Reset(void) = 0; virtual void Reset(void) = 0;
virtual int GetSize(void) = 0; virtual int GetSize(void) = 0;
virtual int GetValLen(void) = 0; virtual int GetValLen(void) = 0;
@@ -75,9 +76,13 @@ class DllExport VALUE : public BLOCK {
virtual int GetLength(void) {return 1;} virtual int GetLength(void) {return 1;}
virtual PSZ GetCharValue(void) {assert(false); return NULL;} virtual PSZ GetCharValue(void) {assert(false); return NULL;}
virtual char GetTinyValue(void) {assert(false); return 0;} virtual char GetTinyValue(void) {assert(false); return 0;}
virtual uchar GetUTinyValue(void) {assert(false); return 0;}
virtual short GetShortValue(void) {assert(false); return 0;} virtual short GetShortValue(void) {assert(false); return 0;}
virtual ushort GetUShortValue(void) {assert(false); return 0;}
virtual int GetIntValue(void) = 0; virtual int GetIntValue(void) = 0;
virtual uint GetUIntValue(void) = 0;
virtual longlong GetBigintValue(void) = 0; virtual longlong GetBigintValue(void) = 0;
virtual ulonglong GetUBigintValue(void) = 0;
virtual double GetFloatValue(void) = 0; virtual double GetFloatValue(void) = 0;
virtual void *GetTo_Val(void) = 0; virtual void *GetTo_Val(void) = 0;
virtual void SetPrec(int prec) {Prec = prec;} virtual void SetPrec(int prec) {Prec = prec;}
@@ -94,20 +99,24 @@ class DllExport VALUE : public BLOCK {
virtual void SetValue_char(char *p, int n) = 0; virtual void SetValue_char(char *p, int n) = 0;
virtual void SetValue_psz(PSZ s) = 0; virtual void SetValue_psz(PSZ s) = 0;
virtual void SetValue(char c) {assert(false);} virtual void SetValue(char c) {assert(false);}
virtual void SetValue(uchar c) {assert(false);}
virtual void SetValue(short i) {assert(false);} virtual void SetValue(short i) {assert(false);}
virtual void SetValue(ushort i) {assert(false);}
virtual void SetValue(int n) {assert(false);} virtual void SetValue(int n) {assert(false);}
virtual void SetValue(uint n) {assert(false);}
virtual void SetValue(longlong n) {assert(false);} virtual void SetValue(longlong n) {assert(false);}
virtual void SetValue(ulonglong n) {assert(false);}
virtual void SetValue(double f) {assert(false);} virtual void SetValue(double f) {assert(false);}
virtual void SetValue_pvblk(PVBLK blk, int n) = 0; virtual void SetValue_pvblk(PVBLK blk, int n) = 0;
virtual void SetBinValue(void *p) = 0; virtual void SetBinValue(void *p) = 0;
virtual bool GetBinValue(void *buf, int buflen, bool go) = 0; virtual bool GetBinValue(void *buf, int buflen, bool go) = 0;
virtual char *ShowValue(char *buf, int len = 0) = 0; virtual char *ShowValue(char *buf, int len = 0) = 0;
virtual char *GetCharString(char *p) = 0; virtual char *GetCharString(char *p) = 0;
virtual char *GetShortString(char *p, int n) {return "#####";} //virtual char *GetShortString(char *p, int n) {return "#####";}
virtual char *GetIntString(char *p, int n) = 0; //virtual char *GetIntString(char *p, int n) = 0;
virtual char *GetBigintString(char *p, int n) = 0; //virtual char *GetBigintString(char *p, int n) = 0;
virtual char *GetFloatString(char *p, int n, int prec) = 0; //virtual char *GetFloatString(char *p, int n, int prec) = 0;
virtual char *GetTinyString(char *p, int n) {return "?";} //virtual char *GetTinyString(char *p, int n) {return "?";}
virtual bool IsEqual(PVAL vp, bool chktype) = 0; virtual bool IsEqual(PVAL vp, bool chktype) = 0;
virtual bool FormatValue(PVAL vp, char *fmt) = 0; virtual bool FormatValue(PVAL vp, char *fmt) = 0;
@@ -116,7 +125,7 @@ class DllExport VALUE : public BLOCK {
const char *GetXfmt(void); const char *GetXfmt(void);
// Constructor used by derived classes // Constructor used by derived classes
VALUE(int type); VALUE(int type, bool un = false);
// Members // Members
PGLOBAL Global; // To reduce arglist PGLOBAL Global; // To reduce arglist
@@ -124,6 +133,7 @@ class DllExport VALUE : public BLOCK {
const char *Xfmt; const char *Xfmt;
bool Nullable; // True if value can be null bool Nullable; // True if value can be null
bool Null; // True if value is null bool Null; // True if value is null
bool Unsigned; // True if unsigned
int Type; // The value type int Type; // The value type
int Clen; // Internal value length int Clen; // Internal value length
int Prec; int Prec;
@@ -135,9 +145,8 @@ class DllExport VALUE : public BLOCK {
template <class TYPE> template <class TYPE>
class DllExport TYPVAL : public VALUE { class DllExport TYPVAL : public VALUE {
public: public:
// Constructors // Constructor
TYPVAL(TYPE n, int type); TYPVAL(TYPE n, int type, int prec = 0, bool un = false);
TYPVAL(TYPE n, int prec, int type);
// Implementation // Implementation
virtual bool IsTypeNum(void) {return true;} virtual bool IsTypeNum(void) {return true;}
@@ -148,9 +157,13 @@ class DllExport TYPVAL : public VALUE {
virtual int GetSize(void) {return sizeof(TYPE);} virtual int GetSize(void) {return sizeof(TYPE);}
virtual PSZ GetCharValue(void) {return VALUE::GetCharValue();} virtual PSZ GetCharValue(void) {return VALUE::GetCharValue();}
virtual char GetTinyValue(void) {return (char)Tval;} virtual char GetTinyValue(void) {return (char)Tval;}
virtual uchar GetUTinyValue(void) {return (uchar)Tval;}
virtual short GetShortValue(void) {return (short)Tval;} virtual short GetShortValue(void) {return (short)Tval;}
virtual ushort GetUShortValue(void) {return (ushort)Tval;}
virtual int GetIntValue(void) {return (int)Tval;} virtual int GetIntValue(void) {return (int)Tval;}
virtual uint GetUIntValue(void) {return (uint)Tval;}
virtual longlong GetBigintValue(void) {return (longlong)Tval;} virtual longlong GetBigintValue(void) {return (longlong)Tval;}
virtual ulonglong GetUBigintValue(void) {return (ulonglong)Tval;}
virtual double GetFloatValue(void) {return (double)Tval;} virtual double GetFloatValue(void) {return (double)Tval;}
virtual void *GetTo_Val(void) {return &Tval;} virtual void *GetTo_Val(void) {return &Tval;}
@@ -159,20 +172,24 @@ class DllExport TYPVAL : public VALUE {
virtual void SetValue_char(char *p, int n); virtual void SetValue_char(char *p, int n);
virtual void SetValue_psz(PSZ s); virtual void SetValue_psz(PSZ s);
virtual void SetValue(char c) {Tval = (TYPE)c; Null = false;} virtual void SetValue(char c) {Tval = (TYPE)c; Null = false;}
virtual void SetValue(uchar c) {Tval = (TYPE)c; Null = false;}
virtual void SetValue(short i) {Tval = (TYPE)i; Null = false;} virtual void SetValue(short i) {Tval = (TYPE)i; Null = false;}
virtual void SetValue(ushort i) {Tval = (TYPE)i; Null = false;}
virtual void SetValue(int n) {Tval = (TYPE)n; Null = false;} virtual void SetValue(int n) {Tval = (TYPE)n; Null = false;}
virtual void SetValue(uint n) {Tval = (TYPE)n; Null = false;}
virtual void SetValue(longlong n) {Tval = (TYPE)n; Null = false;} virtual void SetValue(longlong n) {Tval = (TYPE)n; Null = false;}
virtual void SetValue(ulonglong n) {Tval = (TYPE)n; Null = false;}
virtual void SetValue(double f) {Tval = (TYPE)f; Null = false;} virtual void SetValue(double f) {Tval = (TYPE)f; Null = false;}
virtual void SetValue_pvblk(PVBLK blk, int n); virtual void SetValue_pvblk(PVBLK blk, int n);
virtual void SetBinValue(void *p); virtual void SetBinValue(void *p);
virtual bool GetBinValue(void *buf, int buflen, bool go); virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual char *ShowValue(char *buf, int); virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p); virtual char *GetCharString(char *p);
virtual char *GetShortString(char *p, int n); //virtual char *GetShortString(char *p, int n);
virtual char *GetIntString(char *p, int n); //virtual char *GetIntString(char *p, int n);
virtual char *GetBigintString(char *p, int n); //virtual char *GetBigintString(char *p, int n);
virtual char *GetFloatString(char *p, int n, int prec = -1); //virtual char *GetFloatString(char *p, int n, int prec = -1);
virtual char *GetTinyString(char *p, int n); //virtual char *GetTinyString(char *p, int n);
virtual bool IsEqual(PVAL vp, bool chktype); virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool SetConstFormat(PGLOBAL, FORMAT&); virtual bool SetConstFormat(PGLOBAL, FORMAT&);
virtual bool FormatValue(PVAL vp, char *fmt); virtual bool FormatValue(PVAL vp, char *fmt);
@@ -211,9 +228,13 @@ class DllExport TYPVAL<PSZ>: public VALUE {
virtual int GetSize(void) {return (Strp) ? strlen(Strp) : 0;} virtual int GetSize(void) {return (Strp) ? strlen(Strp) : 0;}
virtual PSZ GetCharValue(void) {return Strp;} virtual PSZ GetCharValue(void) {return Strp;}
virtual char GetTinyValue(void) {return (char)atoi(Strp);} virtual char GetTinyValue(void) {return (char)atoi(Strp);}
virtual uchar GetUTinyValue(void) {return (uchar)atoi(Strp);}
virtual short GetShortValue(void) {return (short)atoi(Strp);} virtual short GetShortValue(void) {return (short)atoi(Strp);}
virtual ushort GetUShortValue(void) {return (ushort)atoi(Strp);}
virtual int GetIntValue(void) {return atol(Strp);} virtual int GetIntValue(void) {return atol(Strp);}
virtual uint GetUIntValue(void) {return (uint)atol(Strp);}
virtual longlong GetBigintValue(void) {return atoll(Strp);} virtual longlong GetBigintValue(void) {return atoll(Strp);}
virtual ulonglong GetUBigintValue(void) {return (ulonglong)atoll(Strp);}
virtual double GetFloatValue(void) {return atof(Strp);} virtual double GetFloatValue(void) {return atof(Strp);}
virtual void *GetTo_Val(void) {return Strp;} virtual void *GetTo_Val(void) {return Strp;}
virtual void SetPrec(int prec) {Ci = prec != 0;} virtual void SetPrec(int prec) {Ci = prec != 0;}
@@ -224,30 +245,34 @@ class DllExport TYPVAL<PSZ>: public VALUE {
virtual void SetValue_psz(PSZ s); virtual void SetValue_psz(PSZ s);
virtual void SetValue_pvblk(PVBLK blk, int n); virtual void SetValue_pvblk(PVBLK blk, int n);
virtual void SetValue(char c); virtual void SetValue(char c);
virtual void SetValue(uchar c);
virtual void SetValue(short i); virtual void SetValue(short i);
virtual void SetValue(ushort i);
virtual void SetValue(int n); virtual void SetValue(int n);
virtual void SetValue(uint n);
virtual void SetValue(longlong n); virtual void SetValue(longlong n);
virtual void SetValue(ulonglong n);
virtual void SetValue(double f); virtual void SetValue(double f);
virtual void SetBinValue(void *p); virtual void SetBinValue(void *p);
virtual bool GetBinValue(void *buf, int buflen, bool go); virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual char *ShowValue(char *buf, int); virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p); virtual char *GetCharString(char *p);
virtual char *GetShortString(char *p, int n); //virtual char *GetShortString(char *p, int n);
virtual char *GetIntString(char *p, int n); //virtual char *GetIntString(char *p, int n);
virtual char *GetBigintString(char *p, int n); //virtual char *GetBigintString(char *p, int n);
virtual char *GetFloatString(char *p, int n, int prec = -1); //virtual char *GetFloatString(char *p, int n, int prec = -1);
virtual char *GetTinyString(char *p, int n); //virtual char *GetTinyString(char *p, int n);
virtual bool IsEqual(PVAL vp, bool chktype); virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool FormatValue(PVAL vp, char *fmt); virtual bool FormatValue(PVAL vp, char *fmt);
virtual bool SetConstFormat(PGLOBAL, FORMAT&); virtual bool SetConstFormat(PGLOBAL, FORMAT&);
// Specialized functions // Specialized functions
template <class T> //template <class T>
T GetValue_as(T type) {return Strp;} //T GetValue_as(T type) {return Strp;}
int GetValue_as(int type) {return atol(Strp);} //int GetValue_as(int type) {return atol(Strp);}
short GetValue_as(short type) {return (short)atoi(Strp);} //short GetValue_as(short type) {return (short)atoi(Strp);}
longlong GetValue_as(longlong type) {return atoll(Strp);} //longlong GetValue_as(longlong type) {return atoll(Strp);}
double GetValue_as(double type) {return atof(Strp);} //double GetValue_as(double type) {return atof(Strp);}
// Members // Members
PSZ Strp; PSZ Strp;

View File

@@ -66,7 +66,7 @@ extern MBLOCK Nmblk; /* Used to initialize MBLOCK's */
/* to have rows filled by blanks to be compatible with QRY blocks. */ /* to have rows filled by blanks to be compatible with QRY blocks. */
/***********************************************************************/ /***********************************************************************/
PVBLK AllocValBlock(PGLOBAL, void *, int, int, int, int, PVBLK AllocValBlock(PGLOBAL, void *, int, int, int, int,
bool check = true, bool blank = true); bool check = true, bool blank = true, bool un = false);
/***********************************************************************/ /***********************************************************************/
/* Check whether we have to create/update permanent indexes. */ /* Check whether we have to create/update permanent indexes. */
@@ -2919,7 +2919,7 @@ void KXYCOL::SetValue(PCOL colp, int i)
assert (Kblp != NULL); assert (Kblp != NULL);
#endif #endif
Kblp->SetValue(colp->GetValue(), (int)i); Kblp->SetValue(colp->GetValue(), i);
} // end of SetValue } // end of SetValue
/***********************************************************************/ /***********************************************************************/
@@ -2970,7 +2970,7 @@ void KXYCOL::FillValue(PVAL valp)
int KXYCOL::Compare(int i1, int i2) int KXYCOL::Compare(int i1, int i2)
{ {
// Do the actual comparison between values. // Do the actual comparison between values.
register int k = (int)Kblp->CompVal((int)i1, (int)i2); register int k = Kblp->CompVal(i1, i2);
#ifdef DEBUG2 #ifdef DEBUG2
htrc("Compare done result=%d\n", k); htrc("Compare done result=%d\n", k);
@@ -2991,7 +2991,7 @@ int KXYCOL::CompVal(int i)
htrc("Compare done result=%d\n", k); htrc("Compare done result=%d\n", k);
return k; return k;
#endif #endif
return (int)Kblp->CompVal(Valp, (int)i); return Kblp->CompVal(Valp, i);
} // end of CompVal } // end of CompVal
/***********************************************************************/ /***********************************************************************/
@@ -3000,7 +3000,7 @@ int KXYCOL::CompVal(int i)
int KXYCOL::CompBval(int i) int KXYCOL::CompBval(int i)
{ {
// Do the actual comparison between key values. // Do the actual comparison between key values.
return (int)Blkp->CompVal(Valp, (int)i); return Blkp->CompVal(Valp, i);
} // end of CompBval } // end of CompBval
/***********************************************************************/ /***********************************************************************/

View File

@@ -18,8 +18,28 @@
#include "colblk.h" #include "colblk.h"
#include "m_ctype.h" #include "m_ctype.h"
//pedef class INDEXDEF *PIXDEF; typedef class CMD *PCMD;
typedef char *PFIL; // Specific to CONNECT
// 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 TDBCAT *PTDBCAT;
typedef class CATCOL *PCATCOL; 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 PFIL GetFilter(void) {return To_Filter;}
inline void SetOrig(PTBX txp) {To_Orig = txp;} inline void SetOrig(PTBX txp) {To_Orig = txp;}
inline void SetFilter(PFIL fp) {To_Filter = fp;} 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 // Methods
virtual bool IsSame(PTBX tp) {return tp == this;} 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 int GetTdb_No(void) = 0; // Convenience during conversion
virtual PTDB GetNext(void) = 0; virtual PTDB GetNext(void) = 0;
//virtual int GetMaxSame(PGLOBAL) = 0;
virtual int Cardinality(PGLOBAL) = 0; virtual int Cardinality(PGLOBAL) = 0;
virtual int GetMaxSize(PGLOBAL) = 0; virtual int GetMaxSize(PGLOBAL) = 0;
virtual int GetProgMax(PGLOBAL) = 0; virtual int GetProgMax(PGLOBAL) = 0;
virtual int GetProgCur(void) = 0; virtual int GetProgCur(void) = 0;
virtual int GetBadLines(void) {return 0;} virtual int GetBadLines(void) {return 0;}
//virtual bool IsJoin(void) = 0;
virtual PTBX Copy(PTABS t) = 0; virtual PTBX Copy(PTABS t) = 0;
protected: protected:
@@ -66,8 +78,6 @@ class DllExport TBX: public BLOCK { // Base class for OPJOIN and TDB classes.
// Members // Members
PTBX To_Orig; // Pointer to original if it is a copy PTBX To_Orig; // Pointer to original if it is a copy
PFIL To_Filter; PFIL To_Filter;
//PFIL To_Noleft; // To filter not involved in LEFT JOIN
//JTYPE Jtype;
TUSE Use; TUSE Use;
}; // end of class TBX }; // end of class TBX