mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge 10.0-connect -> 10.0
This commit is contained in:
@ -166,6 +166,7 @@ my $DEFAULT_SUITES= join(',', map { "$_-" } qw(
|
||||
main
|
||||
archive
|
||||
binlog
|
||||
connect
|
||||
csv
|
||||
federated
|
||||
funcs_1
|
||||
@ -380,7 +381,6 @@ sub main {
|
||||
mtr_report("Logging: $0 ", join(" ", @ARGV));
|
||||
|
||||
$DEFAULT_SUITES.= ',' . join(',', qw(
|
||||
connect
|
||||
query_response_time
|
||||
sequence
|
||||
spider
|
||||
|
@ -264,6 +264,19 @@ int main() {
|
||||
ENDIF(UNIX)
|
||||
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
|
||||
|
@ -164,8 +164,7 @@ bool COLBLK::CheckSort(PTDB tdbp)
|
||||
/* Now we use Format.Length for the len parameter to avoid strings */
|
||||
/* to be truncated when converting from string to coded string. */
|
||||
/* Added in version 1.5 is the arguments GetPrecision() and Domain */
|
||||
/* in calling AllocateValue. Domain is used for TYPE_TOKEN only, */
|
||||
/* but why was GetPrecision() not specified ? To be checked. */
|
||||
/* in calling AllocateValue. Domain is used for TYPE_DATE only. */
|
||||
/***********************************************************************/
|
||||
bool COLBLK::InitValue(PGLOBAL g)
|
||||
{
|
||||
@ -174,8 +173,7 @@ bool COLBLK::InitValue(PGLOBAL g)
|
||||
|
||||
// Allocate a Value object
|
||||
if (!(Value = AllocateValue(g, Buf_Type, Format.Length,
|
||||
GetPrecision(), GetDomain(),
|
||||
(To_Tdb) ? To_Tdb->GetCat() : NULL)))
|
||||
GetPrecision(), GetDomain())))
|
||||
return true;
|
||||
|
||||
AddStatus(BUF_READY);
|
||||
|
@ -251,7 +251,7 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
|
||||
return true;
|
||||
} // endif tdbp
|
||||
|
||||
tdbp->SetMode(mode);
|
||||
//tdbp->SetMode(mode); done in ha_connect::GetTDB
|
||||
|
||||
if (!c1) {
|
||||
if (mode == MODE_INSERT)
|
||||
@ -498,8 +498,8 @@ RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all)
|
||||
|
||||
if (!tdbp || tdbp->GetMode() != MODE_DELETE)
|
||||
return RC_FX;
|
||||
// else
|
||||
// ((PTDBDOX)tdbp)->SetModified(true);
|
||||
else if (tdbp->IsReadOnly())
|
||||
return RC_NF;
|
||||
|
||||
if (((PTDBASE)tdbp)->GetDef()->Indexable() && all)
|
||||
((PTDBDOS)tdbp)->Cardinal= 0;
|
||||
@ -518,17 +518,13 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp)
|
||||
int rc= RC_OK;
|
||||
TDBDOX *tbxp= NULL;
|
||||
|
||||
if (!tdbp)
|
||||
return rc; // Already done
|
||||
if (!tdbp || tdbp->GetUse() != USE_OPEN)
|
||||
return rc; // Nothing to do
|
||||
|
||||
if (xtrace)
|
||||
printf("CntCloseTable: tdbp=%p mode=%d\n", tdbp, tdbp->GetMode());
|
||||
|
||||
/*********************************************************************/
|
||||
/* This will close the table file(s) and also finalize write */
|
||||
/* operations such as Insert, Update, or Delete. */
|
||||
/*********************************************************************/
|
||||
if (tdbp->GetMode() == MODE_DELETE)
|
||||
if (tdbp->GetMode() == MODE_DELETE && tdbp->GetUse() == USE_OPEN)
|
||||
rc= tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine
|
||||
|
||||
// Prepare error return
|
||||
@ -543,6 +539,8 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp)
|
||||
goto err;
|
||||
} // endif
|
||||
|
||||
// This will close the table file(s) and also finalize write
|
||||
// operations such as Insert, Update, or Delete.
|
||||
tdbp->CloseDB(g);
|
||||
|
||||
g->jump_level--;
|
||||
|
@ -17,8 +17,6 @@ typedef class BLKFAM *PBLKFAM;
|
||||
typedef class DOSDEF *PDOSDEF;
|
||||
typedef class TDBDOS *PTDBDOS;
|
||||
|
||||
#define TYPE_AM_BLK (AMT)160
|
||||
|
||||
/***********************************************************************/
|
||||
/* This is the base class for all file access method classes. */
|
||||
/***********************************************************************/
|
||||
|
@ -91,7 +91,7 @@ typedef struct _vecheader {
|
||||
/* Conversion of block values allowed conditionally for insert only. */
|
||||
/***********************************************************************/
|
||||
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 --------------------------- */
|
||||
|
||||
|
@ -10,9 +10,6 @@
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
#define TYPE_AM_ZIP (AMT)150
|
||||
#define TYPE_AM_ZLIB (AMT)155
|
||||
|
||||
typedef class ZIPFAM *PZIPFAM;
|
||||
typedef class ZBKFAM *PZBKFAM;
|
||||
typedef class ZIXFAM *PZIXFAM;
|
||||
|
@ -165,7 +165,7 @@ extern "C" char nmfile[];
|
||||
extern "C" char pdebug[];
|
||||
|
||||
extern "C" {
|
||||
char version[]= "Version 1.01.0008 August 18, 2013";
|
||||
char version[]= "Version 1.01.0009 October 29, 2013";
|
||||
|
||||
#if defined(XMSG)
|
||||
char msglang[]; // Default message language
|
||||
@ -183,7 +183,7 @@ ulong ha_connect::num= 0;
|
||||
//int DTVAL::Shift= 0;
|
||||
|
||||
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,
|
||||
TABLE_SHARE *table,
|
||||
@ -258,17 +258,21 @@ ha_create_table_option connect_field_option_list[]=
|
||||
/***********************************************************************/
|
||||
/* Push G->Message as a MySQL warning. */
|
||||
/***********************************************************************/
|
||||
bool PushWarning(PGLOBAL g, PTDBASE tdbp)
|
||||
bool PushWarning(PGLOBAL g, PTDBASE tdbp, int level)
|
||||
{
|
||||
PHC phc;
|
||||
THD *thd;
|
||||
MYCAT *cat= (MYCAT*)tdbp->GetDef()->GetCat();
|
||||
Sql_condition::enum_warning_level wlvl;
|
||||
|
||||
|
||||
if (!cat || !(phc= cat->GetHandler()) || !phc->GetTable() ||
|
||||
!(thd= (phc->GetTable())->in_use))
|
||||
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;
|
||||
} // end of PushWarning
|
||||
|
||||
@ -552,7 +556,7 @@ static PCONNECT GetUser(THD *thd, PCONNECT xp)
|
||||
/****************************************************************************/
|
||||
/* 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);
|
||||
return (lxp) ? lxp->g : NULL;
|
||||
@ -659,6 +663,8 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
|
||||
opval= (char*)options->colist;
|
||||
else if (!stricmp(opname, "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)
|
||||
opval= GetListOption(xp->g, opname, options->oplist);
|
||||
@ -1096,19 +1102,20 @@ PTDB ha_connect::GetTDB(PGLOBAL g)
|
||||
&& (tdbp->GetMode() == xmod
|
||||
|| tdbp->GetAmType() == TYPE_AM_XML)) {
|
||||
tp= tdbp;
|
||||
tp->SetMode(xmod);
|
||||
// tp->SetMode(xmod);
|
||||
} else if ((tp= CntGetTDB(g, table_name, xmod, this)))
|
||||
valid_query_id= xp->last_query_id;
|
||||
else
|
||||
printf("GetTDB: %s\n", g->Message);
|
||||
|
||||
tp->SetMode(xmod);
|
||||
return tp;
|
||||
} // end of GetTDB
|
||||
|
||||
/****************************************************************************/
|
||||
/* 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;
|
||||
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
|
||||
if (!g || !table) {
|
||||
printf("OpenTable logical error; g=%p table=%p\n", g, table);
|
||||
return true;
|
||||
return HA_ERR_INITIALIZATION;
|
||||
} // endif g
|
||||
|
||||
if (!(tdbp= GetTDB(g)))
|
||||
return true;
|
||||
return RC_FX;
|
||||
else if (tdbp->IsReadOnly())
|
||||
switch (xmod) {
|
||||
case MODE_WRITE:
|
||||
@ -1128,7 +1135,7 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del)
|
||||
case MODE_UPDATE:
|
||||
case MODE_DELETE:
|
||||
strcpy(g->Message, MSG(READ_ONLY));
|
||||
return true;
|
||||
return HA_ERR_TABLE_READONLY;
|
||||
default:
|
||||
break;
|
||||
} // endswitch xmode
|
||||
@ -1205,7 +1212,7 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del)
|
||||
valid_info= false;
|
||||
} // endif rc
|
||||
|
||||
return rc;
|
||||
return (rc) ? HA_ERR_INITIALIZATION : 0;
|
||||
} // end of OpenTable
|
||||
|
||||
|
||||
@ -1239,15 +1246,16 @@ int ha_connect::CloseTable(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
int ha_connect::MakeRecord(char *buf)
|
||||
{
|
||||
char *p, *fmt, val[32];
|
||||
int rc= 0;
|
||||
Field* *field;
|
||||
Field *fp;
|
||||
my_bitmap_map *org_bitmap;
|
||||
CHARSET_INFO *charset= tdbp->data_charset();
|
||||
const MY_BITMAP *map;
|
||||
PVAL value;
|
||||
PCOL colp= NULL;
|
||||
char *p, *fmt, val[32];
|
||||
int rc= 0;
|
||||
Field* *field;
|
||||
Field *fp;
|
||||
my_bitmap_map *org_bitmap;
|
||||
CHARSET_INFO *charset= tdbp->data_charset();
|
||||
//MY_BITMAP readmap;
|
||||
MY_BITMAP *map;
|
||||
PVAL value;
|
||||
PCOL colp= NULL;
|
||||
DBUG_ENTER("ha_connect::MakeRecord");
|
||||
|
||||
if (xtrace > 1)
|
||||
@ -1263,7 +1271,7 @@ int ha_connect::MakeRecord(char *buf)
|
||||
memset(buf, 0, table->s->null_bytes);
|
||||
|
||||
// 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
|
||||
for (field= table->field; *field && !rc; field++) {
|
||||
@ -1300,6 +1308,9 @@ int ha_connect::MakeRecord(char *buf)
|
||||
case MYSQL_TYPE_TIME:
|
||||
fmt= "%H:%M:%S";
|
||||
break;
|
||||
case MYSQL_TYPE_YEAR:
|
||||
fmt= "%Y";
|
||||
break;
|
||||
default:
|
||||
fmt= "%Y-%m-%d %H:%M:%S";
|
||||
break;
|
||||
@ -1401,24 +1412,25 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *buf)
|
||||
value->SetValue(fp->val_real());
|
||||
break;
|
||||
case TYPE_DATE:
|
||||
if (!sdvalin) {
|
||||
if (!sdvalin)
|
||||
sdvalin= (DTVAL*)AllocateValue(xp->g, TYPE_DATE, 19);
|
||||
|
||||
// Get date in the format produced by MySQL fields
|
||||
switch (fp->type()) {
|
||||
case MYSQL_TYPE_DATE:
|
||||
fmt= "YYYY-MM-DD";
|
||||
break;
|
||||
case MYSQL_TYPE_TIME:
|
||||
fmt= "hh:mm:ss";
|
||||
break;
|
||||
default:
|
||||
fmt= "YYYY-MM-DD hh:mm:ss";
|
||||
} // endswitch type
|
||||
|
||||
((DTVAL*)sdvalin)->SetFormat(g, fmt, strlen(fmt));
|
||||
} // endif sdvalin
|
||||
// Get date in the format produced by MySQL fields
|
||||
switch (fp->type()) {
|
||||
case MYSQL_TYPE_DATE:
|
||||
fmt= "YYYY-MM-DD";
|
||||
break;
|
||||
case MYSQL_TYPE_TIME:
|
||||
fmt= "hh:mm:ss";
|
||||
break;
|
||||
case MYSQL_TYPE_YEAR:
|
||||
fmt= "YYYY";
|
||||
break;
|
||||
default:
|
||||
fmt= "YYYY-MM-DD hh:mm:ss";
|
||||
} // endswitch type
|
||||
|
||||
((DTVAL*)sdvalin)->SetFormat(g, fmt, strlen(fmt));
|
||||
fp->val_str(&attribute);
|
||||
sdvalin->SetValue_psz(attribute.c_ptr_safe());
|
||||
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)
|
||||
{
|
||||
char *body= filp->Body;
|
||||
unsigned int i;
|
||||
bool ismul= false;
|
||||
bool ismul= false, x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
|
||||
PPARM pfirst= NULL, pprec= NULL, pp[2]= {NULL, NULL};
|
||||
OPVAL vop= OP_XX;
|
||||
|
||||
@ -1572,6 +1585,9 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
|
||||
char *p1, *p2;
|
||||
Item_cond *cond_item= (Item_cond *)cond;
|
||||
|
||||
if (x)
|
||||
return NULL;
|
||||
|
||||
if (xtrace > 1)
|
||||
printf("Cond: Ftype=%d name=%s\n", cond_item->functype(),
|
||||
cond_item->func_name());
|
||||
@ -1586,7 +1602,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
|
||||
List_iterator<Item> li(*arglist);
|
||||
Item *subitem;
|
||||
|
||||
p1= filp + strlen(filp);
|
||||
p1= body + strlen(body);
|
||||
strcpy(p1, "(");
|
||||
p2= p1 + 1;
|
||||
|
||||
@ -1615,7 +1631,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
|
||||
} else if (cond->type() == COND::FUNC_ITEM) {
|
||||
unsigned int i;
|
||||
// int n;
|
||||
bool iscol, neg= FALSE;
|
||||
bool iscol, neg= FALSE;
|
||||
Item_func *condf= (Item_func *)cond;
|
||||
Item* *args= condf->arguments();
|
||||
|
||||
@ -1644,6 +1660,9 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
|
||||
else if (ismul && tty == TYPE_AM_WMI)
|
||||
return NULL; // Not supported by WQL
|
||||
|
||||
if (x && (neg || !(vop == OP_EQ || vop == OP_IN)))
|
||||
return NULL;
|
||||
|
||||
for (i= 0; i < condf->argument_count(); i++) {
|
||||
if (xtrace > 1)
|
||||
printf("Argtype(%d)=%d\n", i, args[i]->type());
|
||||
@ -1660,6 +1679,9 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
|
||||
ha_field_option_struct *fop;
|
||||
Item_field *pField= (Item_field *)args[i];
|
||||
|
||||
if (x && i)
|
||||
return NULL;
|
||||
|
||||
if (pField->field->table != table)
|
||||
return NULL; // Field does not belong to this table
|
||||
else
|
||||
@ -1685,10 +1707,10 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
|
||||
if (i && ismul)
|
||||
return NULL;
|
||||
|
||||
strcat(filp, fnm);
|
||||
strcat(body, fnm);
|
||||
} else {
|
||||
char buff[256];
|
||||
String *res, tmp(buff,sizeof(buff), &my_charset_bin);
|
||||
char buff[256];
|
||||
String *res, tmp(buff, sizeof(buff), &my_charset_bin);
|
||||
Item_basic_constant *pval= (Item_basic_constant *)args[i];
|
||||
|
||||
if ((res= pval->val_str(&tmp)) == NULL)
|
||||
@ -1698,26 +1720,46 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
|
||||
printf("Value=%.*s\n", res->length(), res->ptr());
|
||||
|
||||
// IN and BETWEEN clauses should be col VOP list
|
||||
if (!i && ismul)
|
||||
if (!i && (x || ismul))
|
||||
return NULL;
|
||||
|
||||
// Append the value to the filter
|
||||
if (args[i]->type() == COND::STRING_ITEM)
|
||||
strcat(strcat(strcat(filp, "'"), res->ptr()), "'");
|
||||
else
|
||||
strncat(filp, res->ptr(), res->length());
|
||||
if (!x) {
|
||||
// Append the value to the filter
|
||||
if (args[i]->field_type() == MYSQL_TYPE_VARCHAR)
|
||||
strcat(strcat(strcat(body, "'"), res->ptr()), "'");
|
||||
else
|
||||
strncat(body, res->ptr(), res->length());
|
||||
|
||||
} else {
|
||||
if (args[i]->field_type() == MYSQL_TYPE_VARCHAR) {
|
||||
// Add the command to the list
|
||||
PCMD *ncp, cmdp= new(g) CMD(g, (char*)res->ptr());
|
||||
|
||||
for (ncp= &filp->Cmds; *ncp; ncp= &(*ncp)->Next) ;
|
||||
|
||||
*ncp= cmdp;
|
||||
} else
|
||||
return NULL;
|
||||
|
||||
} // endif x
|
||||
|
||||
} // endif
|
||||
|
||||
if (!i)
|
||||
strcat(filp, GetValStr(vop, neg));
|
||||
else if (vop == OP_XX && i == 1)
|
||||
strcat(filp, " AND ");
|
||||
else if (vop == OP_IN)
|
||||
strcat(filp, (i == condf->argument_count() - 1) ? ")" : ",");
|
||||
if (!x) {
|
||||
if (!i)
|
||||
strcat(body, GetValStr(vop, neg));
|
||||
else if (vop == OP_XX && i == 1)
|
||||
strcat(body, " AND ");
|
||||
else if (vop == OP_IN)
|
||||
strcat(body, (i == condf->argument_count() - 1) ? ")" : ",");
|
||||
|
||||
} // endif x
|
||||
|
||||
} // endfor i
|
||||
|
||||
if (x)
|
||||
filp->Op= vop;
|
||||
|
||||
} else {
|
||||
if (xtrace > 1)
|
||||
printf("Unsupported condition\n");
|
||||
@ -1753,23 +1795,31 @@ const COND *ha_connect::cond_push(const COND *cond)
|
||||
DBUG_ENTER("ha_connect::cond_push");
|
||||
|
||||
if (tdbp) {
|
||||
AMT tty= tdbp->GetAmType();
|
||||
AMT tty= tdbp->GetAmType();
|
||||
bool x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
|
||||
|
||||
if (tty == TYPE_AM_WMI || tty == TYPE_AM_ODBC ||
|
||||
tty == TYPE_AM_TBL || tty == TYPE_AM_MYSQL) {
|
||||
tty == TYPE_AM_TBL || tty == TYPE_AM_MYSQL || x) {
|
||||
PGLOBAL& g= xp->g;
|
||||
PFIL filp= (PFIL)PlugSubAlloc(g, NULL, 0);
|
||||
PFIL filp= (PFIL)PlugSubAlloc(g, NULL, sizeof(FILTER));
|
||||
|
||||
*filp= 0;
|
||||
filp->Body= (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0);
|
||||
*filp->Body= 0;
|
||||
filp->Op= OP_XX;
|
||||
filp->Cmds= NULL;
|
||||
|
||||
if (CheckCond(g, filp, tty, (Item *)cond)) {
|
||||
if (xtrace)
|
||||
puts(filp);
|
||||
puts(filp->Body);
|
||||
|
||||
if (!x)
|
||||
PlugSubAlloc(g, NULL, strlen(filp->Body) + 1);
|
||||
else
|
||||
cond= NULL; // Does this work?
|
||||
|
||||
tdbp->SetFilter(filp);
|
||||
// cond= NULL; // This does not work anyway
|
||||
PlugSubAlloc(g, NULL, strlen(filp) + 1);
|
||||
} // endif filp
|
||||
} else if (x && cond)
|
||||
tdbp->SetFilter(filp); // Wrong filter
|
||||
|
||||
} // endif tty
|
||||
|
||||
@ -1965,14 +2015,8 @@ int ha_connect::write_row(uchar *buf)
|
||||
if (IsOpened())
|
||||
CloseTable(g);
|
||||
|
||||
if (OpenTable(g)) {
|
||||
if (strstr(g->Message, "read only"))
|
||||
rc= HA_ERR_TABLE_READONLY;
|
||||
else
|
||||
rc= HA_ERR_INITIALIZATION;
|
||||
|
||||
if ((rc= OpenTable(g)))
|
||||
DBUG_RETURN(rc);
|
||||
} // endif tdbp
|
||||
|
||||
} // 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 rc;
|
||||
PGLOBAL g= ((table && table->in_use) ? GetPlug(table->in_use, xp) :
|
||||
(xp) ? xp->g : NULL);
|
||||
DBUG_ENTER("ha_connect::rnd_init");
|
||||
@ -2344,18 +2389,21 @@ int ha_connect::rnd_init(bool scan)
|
||||
if (xtrace)
|
||||
printf("%p in rnd_init: scan=%d\n", this, scan);
|
||||
|
||||
if (g) {
|
||||
if (!table || xmod == MODE_INSERT)
|
||||
DBUG_RETURN(HA_ERR_INITIALIZATION);
|
||||
if (!g || !table || xmod == MODE_INSERT)
|
||||
DBUG_RETURN(HA_ERR_INITIALIZATION);
|
||||
|
||||
// Close the table if it was opened yet (locked?)
|
||||
if (IsOpened())
|
||||
CloseTable(g);
|
||||
// Close the table if it was opened yet (locked?)
|
||||
if (IsOpened())
|
||||
CloseTable(g);
|
||||
|
||||
if (OpenTable(g, xmod == MODE_DELETE))
|
||||
DBUG_RETURN(HA_ERR_INITIALIZATION);
|
||||
// When updating, to avoid skipped update, force the table
|
||||
// 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->tb1= my_interval_timer();
|
||||
@ -2566,7 +2614,6 @@ int ha_connect::info(uint flag)
|
||||
xp->CheckCleanup();
|
||||
} // endif xmod
|
||||
|
||||
// tdbp= OpenTable(g, xmod == MODE_DELETE);
|
||||
tdbp= GetTDB(g);
|
||||
} // endif tdbp
|
||||
|
||||
@ -2661,18 +2708,19 @@ int ha_connect::delete_all_rows()
|
||||
PGLOBAL g= xp->g;
|
||||
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
|
||||
rc= CloseTable(g);
|
||||
|
||||
if (!(OpenTable(g))) {
|
||||
if (!(rc= OpenTable(g))) {
|
||||
if (CntDeleteRow(g, tdbp, true)) {
|
||||
printf("%s\n", g->Message);
|
||||
rc= HA_ERR_INTERNAL_ERROR;
|
||||
} // endif
|
||||
|
||||
} else
|
||||
rc= HA_ERR_INITIALIZATION;
|
||||
} // endif rc
|
||||
|
||||
DBUG_RETURN(rc);
|
||||
} // end of delete_all_rows
|
||||
@ -3461,12 +3509,13 @@ static bool add_fields(PGLOBAL g,
|
||||
DBUG_RETURN(0);
|
||||
} // end of add_fields
|
||||
#else // !NEW_WAY
|
||||
static bool add_field(String *sql, const char *field_name, int typ, int len,
|
||||
int dec, uint tm, const char *rem, int flag, bool dbf)
|
||||
static bool add_field(String *sql, const char *field_name, int typ,
|
||||
int len, int dec, uint tm, const char *rem,
|
||||
int flag, bool dbf, char v)
|
||||
{
|
||||
char var = (len > 255) ? 'V' : v;
|
||||
bool error= false;
|
||||
const char *type= PLGtoMYSQLtype(typ, dbf);
|
||||
// type= PLGtoMYSQLtype(typ, true); ?????
|
||||
const char *type= PLGtoMYSQLtype(typ, dbf, var);
|
||||
|
||||
error|= sql->append('`');
|
||||
error|= sql->append(field_name);
|
||||
@ -3479,7 +3528,8 @@ static bool add_field(String *sql, const char *field_name, int typ, int len,
|
||||
|
||||
if (!strcmp(type, "DOUBLE")) {
|
||||
error|= sql->append(',');
|
||||
error|= sql->append_ulonglong(dec);
|
||||
// dec must be <= len and <= 31
|
||||
error|= sql->append_ulonglong(min(dec, (len - 1)));
|
||||
} // endif dec
|
||||
|
||||
error|= sql->append(')');
|
||||
@ -3518,6 +3568,8 @@ static int init_table_share(THD *thd,
|
||||
HA_CREATE_INFO *create_info,
|
||||
Alter_info *alter_info)
|
||||
{
|
||||
KEY *not_used_1;
|
||||
uint not_used_2;
|
||||
int rc= 0;
|
||||
handler *file;
|
||||
LEX_CUSTRING frm= {0,0};
|
||||
@ -3577,9 +3629,8 @@ static int init_table_share(THD *thd,
|
||||
tmp_disable_binlog(thd);
|
||||
|
||||
file= mysql_create_frm_image(thd, table_s->db.str, table_s->table_name.str,
|
||||
create_info, alter_info,
|
||||
// &thd->lex->create_info, &thd->lex->alter_info,
|
||||
C_ORDINARY_CREATE, &frm);
|
||||
create_info, alter_info, C_ORDINARY_CREATE,
|
||||
¬_used_1, ¬_used_2, &frm);
|
||||
if (file)
|
||||
delete file;
|
||||
else
|
||||
@ -3772,13 +3823,14 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
TABTYPE ttp= TAB_UNDEF;
|
||||
PQRYRES qrp= NULL;
|
||||
PCOLRES crp;
|
||||
PGLOBAL g= GetPlug(thd, NULL);
|
||||
PCONNECT xp= NULL;
|
||||
PGLOBAL g= GetPlug(thd, xp);
|
||||
PTOS topt= table_s->option_struct;
|
||||
#if defined(NEW_WAY)
|
||||
//CHARSET_INFO *cs;
|
||||
Alter_info alter_info;
|
||||
#else // !NEW_WAY
|
||||
char buf[1024];
|
||||
char v, buf[1024];
|
||||
String sql(buf, sizeof(buf), system_charset_info);
|
||||
|
||||
sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info);
|
||||
@ -3821,7 +3873,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
#endif // WIN32
|
||||
port= atoi(GetListOption(g, "port", topt->oplist, "0"));
|
||||
mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
|
||||
#if defined(PROMPT_OK)
|
||||
cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0"));
|
||||
#endif // PROMPT_OK
|
||||
} else {
|
||||
host= "localhost";
|
||||
user= "root";
|
||||
@ -3879,14 +3933,16 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
case TAB_ODBC:
|
||||
dsn= create_info->connect_string.str;
|
||||
|
||||
if (fnc & (FNC_DSN | FNC_DRIVER))
|
||||
if (fnc & (FNC_DSN | FNC_DRIVER)) {
|
||||
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) {
|
||||
if ((dsn = ODBCCheckConnection(g, dsn, cop)) != NULL) {
|
||||
thd->make_lex_string(&create_info->connect_string, dsn, strlen(dsn));
|
||||
ok= true;
|
||||
} // endif dsn
|
||||
#endif // PROMPT_OK
|
||||
|
||||
} else if (!dsn)
|
||||
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);
|
||||
#else // !NEW_WAY
|
||||
// Now add the field
|
||||
if (add_field(&sql, cnm, typ, len, dec, NOT_NULL_FLAG, 0, flg, dbf))
|
||||
if (add_field(&sql, cnm, typ, len, dec, NOT_NULL_FLAG, 0, flg, dbf, 0))
|
||||
rc= HA_ERR_OUT_OF_MEM;
|
||||
#endif // !NEW_WAY
|
||||
} // endfor crp
|
||||
@ -4122,6 +4178,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
break;
|
||||
case FLD_TYPE:
|
||||
typ= crp->Kdata->GetIntValue(i);
|
||||
v = (crp->Nulls) ? crp->Nulls[i] : 0;
|
||||
break;
|
||||
case FLD_PREC:
|
||||
len= crp->Kdata->GetIntValue(i);
|
||||
@ -4152,7 +4209,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
int plgtyp;
|
||||
|
||||
// typ must be PLG type, not SQL type
|
||||
if (!(plgtyp= TranslateSQLType(typ, dec, len))) {
|
||||
if (!(plgtyp= TranslateSQLType(typ, dec, len, v))) {
|
||||
sprintf(g->Message, "Unsupported SQL type %d", typ);
|
||||
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
|
||||
return HA_ERR_INTERNAL_ERROR;
|
||||
@ -4177,7 +4234,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
rc= add_fields(g, thd, &alter_info, cnm, typ, len, dec,
|
||||
tm, rem, 0, true);
|
||||
#else // !NEW_WAY
|
||||
if (add_field(&sql, cnm, typ, len, dec, tm, rem, 0, true))
|
||||
if (add_field(&sql, cnm, typ, len, dec, tm, rem, 0, dbf, v))
|
||||
rc= HA_ERR_OUT_OF_MEM;
|
||||
#endif // !NEW_WAY
|
||||
} // endfor i
|
||||
@ -4671,6 +4728,6 @@ maria_declare_plugin(connect)
|
||||
NULL, /* status variables */
|
||||
NULL, /* system variables */
|
||||
"0.1", /* string version */
|
||||
MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
|
||||
MariaDB_PLUGIN_MATURITY_ALPHA /* maturity */
|
||||
}
|
||||
maria_declare_plugin_end;
|
||||
|
@ -174,7 +174,7 @@ public:
|
||||
bool IsSameIndex(PIXDEF xp1, PIXDEF xp2);
|
||||
|
||||
PTDB GetTDB(PGLOBAL g);
|
||||
bool OpenTable(PGLOBAL g, bool del= false);
|
||||
int OpenTable(PGLOBAL g, bool del= false);
|
||||
bool IsOpened(void);
|
||||
int CloseTable(PGLOBAL g);
|
||||
int MakeRecord(char *buf);
|
||||
|
@ -8,6 +8,9 @@
|
||||
#include <libxml/tree.h>
|
||||
#include <libxml/xpath.h>
|
||||
#include <libxml/xpathInternals.h>
|
||||
#include <libxml/catalog.h>
|
||||
#include <libxml/xmlschemastypes.h>
|
||||
#include <libxml/relaxng.h>
|
||||
//#if defined(WIN32)
|
||||
//#include <windows.h>
|
||||
//#else // !WIN32
|
||||
@ -290,10 +293,46 @@ if (!rc)
|
||||
/******************************************************************/
|
||||
/* 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)
|
||||
{
|
||||
xmlCleanupParser();
|
||||
xmlMemoryDump();
|
||||
xmlCleanupParser_replacement();
|
||||
} // end of XmlCleanupParserLib
|
||||
|
||||
/******************************************************************/
|
||||
|
@ -87,7 +87,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
|
||||
FLD_KEY, FLD_SCALE, FLD_RADIX, FLD_NULL,
|
||||
FLD_REM, FLD_NO, FLD_CHARSET};
|
||||
static unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 256, 32, 32};
|
||||
char *fld, *fmt, cmd[128];
|
||||
char *fld, *fmt, v, cmd[128];
|
||||
int i, n, nf, ncol = sizeof(buftyp) / sizeof(int);
|
||||
int len, type, prec, rc, k = 0;
|
||||
PQRYRES qrp;
|
||||
@ -139,6 +139,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
|
||||
// Some columns must be renamed
|
||||
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
|
||||
switch (++i) {
|
||||
case 2: crp->Nulls = (char*)PlugSubAlloc(g, NULL, n); break;
|
||||
case 4: crp->Name = "Length"; break;
|
||||
case 5: crp->Name = "Key"; break;
|
||||
case 10: crp->Name = "Date_fmt"; break;
|
||||
@ -166,7 +167,8 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
|
||||
// Get type, type name, and precision
|
||||
fld = myc.GetCharField(1);
|
||||
prec = 0;
|
||||
len = 255; // Default for text or blob
|
||||
len = 0;
|
||||
v = 0;
|
||||
|
||||
if ((nf = sscanf(fld, "%[^(](%d,%d", cmd, &len, &prec)) < 1) {
|
||||
sprintf(g->Message, MSG(BAD_FIELD_TYPE), fld);
|
||||
@ -175,14 +177,16 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
|
||||
} else
|
||||
qrp->Nblin++;
|
||||
|
||||
if ((type = MYSQLtoPLG(cmd)) == TYPE_ERROR) {
|
||||
if ((type = MYSQLtoPLG(cmd, &v)) == TYPE_ERROR) {
|
||||
sprintf(g->Message, "Unsupported column type %s", cmd);
|
||||
myc.Close();
|
||||
return NULL;
|
||||
} // endif type
|
||||
} else if (type == TYPE_STRING)
|
||||
len = min(len, 4096);
|
||||
|
||||
crp = crp->Next; // Data_Type
|
||||
crp->Kdata->SetValue(type, i);
|
||||
crp->Nulls[i] = v;
|
||||
crp = crp->Next; // Type_Name
|
||||
crp->Kdata->SetValue(cmd, i);
|
||||
|
||||
@ -253,6 +257,7 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
|
||||
const char *user, const char *pwd,
|
||||
const char *srcdef, int port)
|
||||
{
|
||||
char *query;
|
||||
int w;
|
||||
MYSQLC myc;
|
||||
PQRYRES qrp = NULL;
|
||||
@ -260,12 +265,15 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
|
||||
if (!port)
|
||||
port = mysqld_port;
|
||||
|
||||
query = (char *)PlugSubAlloc(g, NULL, strlen(srcdef) + 9);
|
||||
strcat(strcpy(query, srcdef), " LIMIT 0");
|
||||
|
||||
// Open a MySQL connection for this table
|
||||
if (myc.Open(g, host, db, user, pwd, port))
|
||||
return NULL;
|
||||
|
||||
// Send the source command to MySQL
|
||||
if (myc.ExecSQL(g, srcdef, &w) == RC_OK)
|
||||
if (myc.ExecSQL(g, query, &w) == RC_OK)
|
||||
qrp = myc.GetResult(g);
|
||||
|
||||
myc.Close();
|
||||
@ -701,7 +709,7 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
|
||||
crp->Clen = GetTypeSize(crp->Type, crp->Length);
|
||||
|
||||
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),
|
||||
GetFormatType(crp->Type));
|
||||
return NULL;
|
||||
@ -778,6 +786,42 @@ void MYSQLC::Rewind(void)
|
||||
|
||||
} // end of Rewind
|
||||
|
||||
/***********************************************************************/
|
||||
/* Exec the Select SQL command and return ncol or afrws (TDBMYEXC). */
|
||||
/***********************************************************************/
|
||||
int MYSQLC::ExecSQLcmd(PGLOBAL g, const char *query, int *w)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
|
||||
if (!m_DB) {
|
||||
strcpy(g->Message, "MySQL not connected");
|
||||
return RC_FX;
|
||||
} else
|
||||
*w = 0;
|
||||
|
||||
if (!stricmp(query, "Warning") || !stricmp(query, "Note")
|
||||
|| !stricmp(query, "Error"))
|
||||
return RC_INFO;
|
||||
else
|
||||
m_Afrw = 0;
|
||||
|
||||
//if (mysql_query(m_DB, query) != 0) {
|
||||
if (mysql_real_query(m_DB, query, strlen(query))) {
|
||||
m_Afrw = (int)mysql_errno(m_DB);
|
||||
sprintf(g->Message, "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. */
|
||||
/***********************************************************************/
|
||||
|
@ -26,7 +26,6 @@
|
||||
#define DllItem
|
||||
#endif // !WIN32
|
||||
|
||||
//#define TYPE_AM_MYSQL (AMT)192
|
||||
#define MYSQL_ENABLED 0x00000001
|
||||
#define MYSQL_LOGON 0x00000002
|
||||
|
||||
@ -75,9 +74,12 @@ class DllItem MYSQLC {
|
||||
//const char *ServerInfo(void);
|
||||
int KillQuery(ulong id);
|
||||
int ExecSQL(PGLOBAL g, const char *query, int *w = NULL);
|
||||
int ExecSQLcmd(PGLOBAL g, const char *query, int *w);
|
||||
#if defined(MYSQL_PREPARED_STATEMENTS)
|
||||
int PrepareSQL(PGLOBAL g, const char *query);
|
||||
int ExecStmt(PGLOBAL g);
|
||||
int BindParams(PGLOBAL g, MYSQL_BIND *bind);
|
||||
#endif // MYSQL_PREPARED_STATEMENTS
|
||||
PQRYRES GetResult(PGLOBAL g, bool pdb = FALSE);
|
||||
int Fetch(PGLOBAL g, int pos);
|
||||
char *GetCharField(int i);
|
||||
@ -99,5 +101,6 @@ class DllItem MYSQLC {
|
||||
int m_Rows; // The number of rows of the result
|
||||
int N;
|
||||
int m_Fields; // The number of result fields
|
||||
int m_Afrw; // The number of affected rows
|
||||
}; // end of class MYSQLC
|
||||
|
||||
|
15
storage/connect/mysql-test/connect/my.cnf
Normal file
15
storage/connect/mysql-test/connect/my.cnf
Normal 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
|
@ -48,7 +48,7 @@ salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
|
||||
dept INT(4) NOT NULL FIELD_FORMAT='S'
|
||||
) ENGINE=CONNECT TABLE_TYPE=BIN READONLY=Yes FILE_NAME='Testbal.dat';
|
||||
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;
|
||||
Warnings:
|
||||
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'
|
||||
) 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);
|
||||
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
|
||||
ERROR HY000: Table 't1' is read only
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Testing that the underlying file is created
|
||||
|
@ -50,13 +50,13 @@ children SMALLINT(2) NOT NULL
|
||||
) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='people.csv'
|
||||
HEADER=1 SEP_CHAR=';' QUOTED=1 READONLY=yes;
|
||||
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';
|
||||
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';
|
||||
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
|
||||
ERROR HY000: Table 't1' is read only
|
||||
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;
|
||||
name birth children
|
||||
Archibald 2001-05-17 3
|
||||
@ -90,7 +90,7 @@ t1 CREATE TABLE `t1` (
|
||||
`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
|
||||
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;
|
||||
name birth children
|
||||
Archibald 2001-05-17 3
|
||||
|
@ -77,13 +77,13 @@ t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL
|
||||
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=DBF `FILE_NAME`='t1.dbf' `READONLY`=Yes
|
||||
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;
|
||||
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;
|
||||
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
|
||||
ERROR HY000: Table 't1' is read only
|
||||
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;
|
||||
Warnings:
|
||||
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
|
||||
|
@ -30,13 +30,13 @@ t1 CREATE TABLE `t1` (
|
||||
`id` int(11) NOT NULL
|
||||
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=FIX `FILE_NAME`='t1.txt' `READONLY`=1
|
||||
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;
|
||||
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;
|
||||
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
|
||||
ERROR HY000: Table 't1' is read only
|
||||
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;
|
||||
Warnings:
|
||||
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
|
||||
|
@ -194,13 +194,13 @@ t1 CREATE TABLE `t1` (
|
||||
`c2` char(60) DEFAULT NULL
|
||||
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=INI `FILE_NAME`='t1.ini' `READONLY`=1
|
||||
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;
|
||||
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;
|
||||
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
|
||||
ERROR HY000: Table 't1' is read only
|
||||
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;
|
||||
Warnings:
|
||||
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
|
||||
|
@ -44,7 +44,7 @@ SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`b` varchar(10) DEFAULT NULL
|
||||
`b` char(10) DEFAULT NULL
|
||||
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
|
||||
SELECT * FROM t2;
|
||||
a b
|
||||
@ -176,7 +176,7 @@ t1 CREATE TABLE `t1` (
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`a` varchar(10) DEFAULT NULL
|
||||
`a` char(10) DEFAULT NULL
|
||||
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
|
||||
SELECT * FROM t2;
|
||||
a
|
||||
|
42
storage/connect/mysql-test/connect/r/mysql_discovery.result
Normal file
42
storage/connect/mysql-test/connect/r/mysql_discovery.result
Normal 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;
|
62
storage/connect/mysql-test/connect/r/mysql_exec.result
Normal file
62
storage/connect/mysql-test/connect/r/mysql_exec.result
Normal 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;
|
218
storage/connect/mysql-test/connect/r/mysql_new.result
Normal file
218
storage/connect/mysql-test/connect/r/mysql_new.result
Normal 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;
|
@ -1,6 +1,6 @@
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`Description` varchar(128) NOT NULL,
|
||||
`Description` char(128) NOT NULL,
|
||||
`Attributes` varchar(256) NOT NULL
|
||||
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers'
|
||||
SET NAMES utf8;
|
||||
@ -41,3 +41,13 @@ test2
|
||||
ÆÇÈÉË
|
||||
DROP VIEW v1;
|
||||
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;
|
||||
|
@ -1,6 +1,6 @@
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`Description` varchar(128) NOT NULL,
|
||||
`Description` char(128) NOT NULL,
|
||||
`Attributes` varchar(256) NOT NULL
|
||||
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers'
|
||||
SET NAMES utf8;
|
||||
|
@ -13,3 +13,14 @@ Thomas Dominique NULL
|
||||
Lemonnier Nathalie Directeur Marketing Client
|
||||
Menseau Eric NULL
|
||||
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;
|
||||
|
@ -103,13 +103,13 @@ t1 CREATE TABLE `t1` (
|
||||
`b` char(10) NOT NULL
|
||||
) ENGINE=CONNECT DEFAULT CHARSET=latin1 MAX_ROWS=10 `TABLE_TYPE`=VEC `FILE_NAME`='t1vec' `READONLY`=yes
|
||||
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;
|
||||
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;
|
||||
ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
|
||||
ERROR HY000: Table 't1' is read only
|
||||
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;
|
||||
Warnings:
|
||||
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
|
||||
|
@ -413,7 +413,7 @@ DROP TABLE t1;
|
||||
SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml');
|
||||
SELECT CAST(@a AS CHAR CHARACTER SET latin1);
|
||||
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>
|
||||
<line>
|
||||
<node>ÀÁÂÃ</node>
|
||||
|
@ -46,7 +46,7 @@ CREATE TABLE t1
|
||||
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
|
||||
dept INT(4) NOT NULL FIELD_FORMAT='S'
|
||||
) 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);
|
||||
ALTER TABLE t1 READONLY=NO;
|
||||
SHOW CREATE TABLE t1;
|
||||
@ -54,7 +54,7 @@ INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
|
||||
SELECT * FROM t1;
|
||||
ALTER TABLE t1 READONLY=YES;
|
||||
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);
|
||||
DROP TABLE t1;
|
||||
|
||||
|
@ -45,13 +45,13 @@ CREATE TABLE t1
|
||||
children SMALLINT(2) NOT NULL
|
||||
) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='people.csv'
|
||||
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);
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
UPDATE t1 SET children=6 WHERE name='BILL';
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
DELETE FROM t1 WHERE name='BILL';
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
TRUNCATE TABLE t1;
|
||||
SELECT * FROM t1;
|
||||
ALTER TABLE t1 READONLY=no;
|
||||
@ -60,7 +60,7 @@ INSERT INTO t1 VALUES ('BILL','1973-06-30',5);
|
||||
SELECT * FROM t1;
|
||||
ALTER TABLE t1 READONLY=1;
|
||||
SHOW CREATE TABLE t1;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
INSERT INTO t1 VALUES ('BILL','1973-06-30',5);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
@ -66,13 +66,13 @@ INSERT INTO t1 VALUES (10),(20);
|
||||
SELECT * FROM t1;
|
||||
ALTER TABLE t1 READONLY=Yes;
|
||||
SHOW CREATE TABLE t1;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
INSERT INTO t1 VALUES (30);
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
UPDATE t1 SET a=30 WHERE a=10;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
DELETE FROM t1 WHERE a=10;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
TRUNCATE TABLE t1;
|
||||
ALTER TABLE t1 READONLY=NO;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
@ -28,13 +28,13 @@ INSERT INTO t1 VALUES (10);
|
||||
SELECT * FROM t1;
|
||||
ALTER TABLE t1 READONLY=1;
|
||||
SHOW CREATE TABLE t1;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
INSERT INTO t1 VALUES (20);
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
UPDATE t1 SET id=20 WHERE id=10;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
DELETE FROM t1 WHERE id=10;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
TRUNCATE TABLE t1;
|
||||
ALTER TABLE t1 READONLY=0;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
@ -99,13 +99,13 @@ INSERT INTO t1 VALUES ('UK',10),('FR',20),('RU',30);
|
||||
SELECT * FROM t1;
|
||||
ALTER TABLE t1 READONLY=1;
|
||||
SHOW CREATE TABLE t1;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
INSERT INTO t1 VALUES ('US',40);
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
UPDATE t1 SET c2=20 WHERE c2=10;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
DELETE FROM t1 WHERE c2=10;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
TRUNCATE TABLE t1;
|
||||
ALTER TABLE t1 READONLY=0;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
27
storage/connect/mysql-test/connect/t/myconn.inc
Normal file
27
storage/connect/mysql-test/connect/t/myconn.inc
Normal 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;
|
9
storage/connect/mysql-test/connect/t/myconn_cleanup.inc
Normal file
9
storage/connect/mysql-test/connect/t/myconn_cleanup.inc
Normal 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
|
33
storage/connect/mysql-test/connect/t/mysql_discovery.test
Normal file
33
storage/connect/mysql-test/connect/t/mysql_discovery.test
Normal 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
|
||||
|
45
storage/connect/mysql-test/connect/t/mysql_exec.test
Normal file
45
storage/connect/mysql-test/connect/t/mysql_exec.test
Normal 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
|
||||
|
325
storage/connect/mysql-test/connect/t/mysql_new.test
Normal file
325
storage/connect/mysql-test/connect/t/mysql_new.test
Normal 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
|
||||
|
@ -67,3 +67,13 @@ SELECT * FROM v1;
|
||||
|
||||
DROP VIEW v1;
|
||||
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;
|
||||
|
@ -23,4 +23,17 @@ let $MYSQLD_DATADIR= `select @@datadir`;
|
||||
SELECT Nom, Fonction FROM contact WHERE Repertoire='ascii';
|
||||
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
|
||||
|
@ -52,13 +52,13 @@ SELECT fname, ftype, size FROM dir1 ORDER BY fname, ftype;
|
||||
--echo #
|
||||
ALTER TABLE t1 READONLY=yes;
|
||||
SHOW CREATE TABLE t1;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
INSERT INTO t1 VALUES (4,'test04');
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
UPDATE t1 SET b='test04' WHERE a=3;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
DELETE FROM t1 WHERE a=3;
|
||||
--error ER_GET_ERRMSG
|
||||
--error ER_OPEN_AS_READONLY
|
||||
TRUNCATE TABLE t1;
|
||||
ALTER TABLE t1 READONLY=no;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
@ -29,7 +29,7 @@
|
||||
/************************************************************************/
|
||||
/* Convert from MySQL type name to PlugDB type number */
|
||||
/************************************************************************/
|
||||
int MYSQLtoPLG(char *typname)
|
||||
int MYSQLtoPLG(char *typname, char *var)
|
||||
{
|
||||
int type;
|
||||
|
||||
@ -56,6 +56,28 @@ int MYSQLtoPLG(char *typname)
|
||||
else
|
||||
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;
|
||||
} // end of MYSQLtoPLG
|
||||
|
||||
@ -98,14 +120,18 @@ enum enum_field_types PLGtoMYSQL(int type, bool dbf)
|
||||
/************************************************************************/
|
||||
/* Convert from PlugDB type to MySQL type name */
|
||||
/************************************************************************/
|
||||
const char *PLGtoMYSQLtype(int type, bool dbf)
|
||||
const char *PLGtoMYSQLtype(int type, bool dbf, char v)
|
||||
{
|
||||
switch (type) {
|
||||
case TYPE_INT: return "INT";
|
||||
case TYPE_SHORT: return "SMALLINT";
|
||||
case TYPE_FLOAT: return "DOUBLE";
|
||||
case TYPE_DATE: return dbf ? "DATE" : "DATETIME";
|
||||
case TYPE_STRING: return "VARCHAR";
|
||||
case TYPE_DATE: return dbf ? "DATE" :
|
||||
(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_TINY: return "TINYINT";
|
||||
default: return "CHAR(0)";
|
||||
|
@ -1,9 +1,14 @@
|
||||
/***********************************************************************/
|
||||
/* Prototypes of Functions used externally. */
|
||||
/***********************************************************************/
|
||||
#ifndef __MYUTIL__H
|
||||
#define __MYUTIL__H
|
||||
|
||||
enum enum_field_types PLGtoMYSQL(int type, bool dbf);
|
||||
const char *PLGtoMYSQLtype(int type, bool dbf);
|
||||
int MYSQLtoPLG(char *typname);
|
||||
const char *PLGtoMYSQLtype(int type, bool dbf, char var = NULL);
|
||||
int MYSQLtoPLG(char *typname, char *var = NULL);
|
||||
int MYSQLtoPLG(int mytype);
|
||||
char *MyDateFmt(int mytype);
|
||||
char *MyDateFmt(char *typname);
|
||||
|
||||
#endif // __MYUTIL__H
|
||||
|
@ -1,7 +1,9 @@
|
||||
/***********************************************************************/
|
||||
/* ODBC catalog function prototypes. */
|
||||
/***********************************************************************/
|
||||
#if defined(PROMPT_OK)
|
||||
char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop);
|
||||
#endif // PROMPT_OK
|
||||
PQRYRES ODBCDataSources(PGLOBAL g, bool info);
|
||||
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
|
||||
char *colpat, bool info);
|
||||
|
@ -108,16 +108,18 @@ static int GetSQLCType(int type)
|
||||
/***********************************************************************/
|
||||
/* TranslateSQLType: translate a SQL Type to a PLG type. */
|
||||
/***********************************************************************/
|
||||
int TranslateSQLType(int stp, int prec, int& len)
|
||||
int TranslateSQLType(int stp, int prec, int& len, char& v)
|
||||
{
|
||||
int type;
|
||||
|
||||
switch (stp) {
|
||||
case SQL_CHAR: // 1
|
||||
case SQL_VARCHAR: // 12
|
||||
v = 'V';
|
||||
case SQL_CHAR: // 1
|
||||
type = TYPE_STRING;
|
||||
break;
|
||||
case SQL_LONGVARCHAR: // (-1)
|
||||
v = 'V';
|
||||
type = TYPE_STRING;
|
||||
len = min(abs(len), 255);
|
||||
break;
|
||||
@ -172,6 +174,7 @@ int TranslateSQLType(int stp, int prec, int& len)
|
||||
return type;
|
||||
} // end of TranslateSQLType
|
||||
|
||||
#if defined(PROMPT_OK)
|
||||
/***********************************************************************/
|
||||
/* ODBCCheckConnection: Check completeness of connection string. */
|
||||
/***********************************************************************/
|
||||
@ -203,6 +206,7 @@ char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop)
|
||||
ocp->Close();
|
||||
return newdsn; // Return complete connection string
|
||||
} // end of ODBCCheckConnection
|
||||
#endif // PROMPT_OK
|
||||
|
||||
/***********************************************************************/
|
||||
/* Allocate the structure used to refer to the result set. */
|
||||
@ -871,7 +875,8 @@ ODBConn::ODBConn(PGLOBAL g, TDBODBC *tdbp)
|
||||
m_Connect = NULL;
|
||||
m_Updatable = true;
|
||||
m_Transact = false;
|
||||
m_IDQuoteChar = '\'';
|
||||
m_IDQuoteChar[0] = '"';
|
||||
m_IDQuoteChar[1] = 0;
|
||||
//*m_ErrMsg = '\0';
|
||||
} // end of ODBConn
|
||||
|
||||
@ -889,7 +894,7 @@ bool ODBConn::Check(RETCODE rc)
|
||||
{
|
||||
switch (rc) {
|
||||
case SQL_SUCCESS_WITH_INFO:
|
||||
if (trace > 1) {
|
||||
if (trace) {
|
||||
DBX x(rc);
|
||||
|
||||
x.BuildErrorMessage(this, m_hstmt);
|
||||
@ -1113,7 +1118,7 @@ bool ODBConn::Connect(DWORD Options)
|
||||
if (hWnd == NULL)
|
||||
hWnd = GetDesktopWindow();
|
||||
#else // !WIN32
|
||||
HWND hWnd = 1;
|
||||
HWND hWnd = (HWND)1;
|
||||
#endif // !WIN32
|
||||
PGLOBAL& g = m_G;
|
||||
PDBUSER dup = PlgGetUser(g);
|
||||
@ -1230,20 +1235,13 @@ void ODBConn::GetConnectInfo()
|
||||
SQL_MODE_READ_ONLY);
|
||||
#endif // 0
|
||||
|
||||
// Cache the quote char to use when constructing SQL
|
||||
char QuoteChar[2];
|
||||
|
||||
// Get the quote char to use when constructing SQL
|
||||
rc = SQLGetInfo(m_hdbc, SQL_IDENTIFIER_QUOTE_CHAR,
|
||||
QuoteChar, sizeof(QuoteChar), &nResult);
|
||||
|
||||
if (Check(rc) && nResult == 1)
|
||||
m_IDQuoteChar = QuoteChar[0];
|
||||
else
|
||||
m_IDQuoteChar = ' ';
|
||||
m_IDQuoteChar, sizeof(m_IDQuoteChar), &nResult);
|
||||
|
||||
if (trace)
|
||||
htrc("DBMS: %s, Version: %s",
|
||||
GetStringInfo(SQL_DBMS_NAME), GetStringInfo(SQL_DBMS_VER));
|
||||
htrc("DBMS: %s, Version: %s, rc=%d\n",
|
||||
GetStringInfo(SQL_DBMS_NAME), GetStringInfo(SQL_DBMS_VER), rc);
|
||||
|
||||
} // end of GetConnectInfo
|
||||
|
||||
@ -1511,14 +1509,16 @@ int ODBConn::PrepareSQL(char *sql)
|
||||
|
||||
hstmt = m_hstmt;
|
||||
m_hstmt = NULL;
|
||||
ThrowDBX(MSG(SEQUENCE_ERROR));
|
||||
} else {
|
||||
rc = SQLAllocStmt(m_hdbc, &hstmt);
|
||||
|
||||
if (!Check(rc))
|
||||
ThrowDBX(SQL_INVALID_HANDLE, "SQLAllocStmt");
|
||||
if (m_Tdb->GetAmType() != TYPE_AM_XDBC)
|
||||
ThrowDBX(MSG(SEQUENCE_ERROR));
|
||||
|
||||
} // endif hstmt
|
||||
} // endif m_hstmt
|
||||
|
||||
rc = SQLAllocStmt(m_hdbc, &hstmt);
|
||||
|
||||
if (!Check(rc))
|
||||
ThrowDBX(SQL_INVALID_HANDLE, "SQLAllocStmt");
|
||||
|
||||
OnSetOptions(hstmt);
|
||||
b = true;
|
||||
@ -1565,7 +1565,7 @@ int ODBConn::PrepareSQL(char *sql)
|
||||
/***********************************************************************/
|
||||
/* Execute a prepared statement. */
|
||||
/***********************************************************************/
|
||||
int ODBConn::ExecuteSQL(bool x)
|
||||
int ODBConn::ExecuteSQL(void)
|
||||
{
|
||||
PGLOBAL& g = m_G;
|
||||
SWORD ncol = 0;
|
||||
@ -1580,26 +1580,17 @@ int ODBConn::ExecuteSQL(bool x)
|
||||
if (!Check(rc))
|
||||
ThrowDBX(rc, "SQLExecute", m_hstmt);
|
||||
|
||||
if (!Check(SQLNumResultCols(m_hstmt, &ncol)))
|
||||
if (!Check(rc = SQLNumResultCols(m_hstmt, &ncol)))
|
||||
ThrowDBX(rc, "SQLNumResultCols", m_hstmt);
|
||||
|
||||
if (ncol) {
|
||||
if (x) {
|
||||
afrw = ncol;
|
||||
strcpy(g->Message, "Result set column number");
|
||||
} else {
|
||||
// This should never happen while inserting
|
||||
strcpy(g->Message, "Logical error while inserting");
|
||||
} // endif ncol
|
||||
|
||||
// This should never happen while inserting
|
||||
strcpy(g->Message, "Logical error while inserting");
|
||||
} else {
|
||||
// Insert, Update or Delete statement
|
||||
if (!Check(SQLRowCount(m_hstmt, &afrw)))
|
||||
if (!Check(rc = SQLRowCount(m_hstmt, &afrw)))
|
||||
ThrowDBX(rc, "SQLRowCount", m_hstmt);
|
||||
|
||||
if (x)
|
||||
strcpy(g->Message, "Affected rows");
|
||||
|
||||
} // endif ncol
|
||||
|
||||
} catch(DBX *x) {
|
||||
@ -1613,6 +1604,7 @@ int ODBConn::ExecuteSQL(bool x)
|
||||
m_Transact = false;
|
||||
} // endif m_Transact
|
||||
|
||||
afrw = -1;
|
||||
} // end try/catch
|
||||
|
||||
return (int)afrw;
|
||||
@ -1667,6 +1659,112 @@ bool ODBConn::BindParam(ODBCCOL *colp)
|
||||
return false;
|
||||
} // end of BindParam
|
||||
|
||||
/***********************************************************************/
|
||||
/* Execute an SQL command. */
|
||||
/***********************************************************************/
|
||||
bool ODBConn::ExecSQLcommand(char *sql)
|
||||
{
|
||||
char cmd[16];
|
||||
bool b, rcd = false;
|
||||
UINT txn = 0;
|
||||
PGLOBAL& g = m_G;
|
||||
SWORD ncol = 0;
|
||||
SQLLEN afrw;
|
||||
RETCODE rc;
|
||||
HSTMT hstmt;
|
||||
|
||||
try {
|
||||
b = FALSE;
|
||||
|
||||
// Check whether we should use transaction
|
||||
if (sscanf(sql, " %15s ", cmd) == 1) {
|
||||
if (!stricmp(cmd, "INSERT") || !stricmp(cmd, "UPDATE") ||
|
||||
!stricmp(cmd, "DELETE") || !stricmp(cmd, "REPLACE")) {
|
||||
// Does the data source support transactions
|
||||
rc = SQLGetInfo(m_hdbc, SQL_TXN_CAPABLE, &txn, 0, NULL);
|
||||
|
||||
if (Check(rc) && txn != SQL_TC_NONE) {
|
||||
rc = SQLSetConnectAttr(m_hdbc, SQL_ATTR_AUTOCOMMIT,
|
||||
SQL_AUTOCOMMIT_OFF, SQL_IS_UINTEGER);
|
||||
|
||||
if (!Check(rc))
|
||||
ThrowDBX(SQL_INVALID_HANDLE, "SQLSetConnectAttr");
|
||||
|
||||
m_Transact = TRUE;
|
||||
} // endif txn
|
||||
|
||||
} // endif cmd
|
||||
|
||||
} // endif sql
|
||||
|
||||
// Allocate the statement handle
|
||||
rc = SQLAllocStmt(m_hdbc, &hstmt);
|
||||
|
||||
if (!Check(rc))
|
||||
ThrowDBX(SQL_INVALID_HANDLE, "SQLAllocStmt");
|
||||
|
||||
OnSetOptions(hstmt);
|
||||
b = true;
|
||||
|
||||
if (trace)
|
||||
htrc("ExecSQLcommand hstmt=%p %.64s\n", hstmt, sql);
|
||||
|
||||
// Proceed with command execution
|
||||
do {
|
||||
rc = SQLExecDirect(hstmt, (PUCHAR)sql, SQL_NTS);
|
||||
} while (rc == SQL_STILL_EXECUTING);
|
||||
|
||||
if (!Check(rc))
|
||||
ThrowDBX(rc, "SQLExecDirect", hstmt);
|
||||
|
||||
// Check whether this is a query returning a result set
|
||||
if (!Check(rc = SQLNumResultCols(hstmt, &ncol)))
|
||||
ThrowDBX(rc, "SQLNumResultCols", hstmt);
|
||||
|
||||
if (!ncol) {
|
||||
if (!Check(SQLRowCount(hstmt, &afrw)))
|
||||
ThrowDBX(rc, "SQLRowCount", hstmt);
|
||||
|
||||
m_Tdb->AftRows = (int)afrw;
|
||||
strcpy(g->Message, "Affected rows");
|
||||
} else {
|
||||
m_Tdb->AftRows = (int)ncol;
|
||||
strcpy(g->Message, "Result set column number");
|
||||
} // endif ncol
|
||||
|
||||
} catch(DBX *x) {
|
||||
if (trace)
|
||||
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
|
||||
htrc(x->m_ErrMsg[i]);
|
||||
|
||||
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 */
|
||||
/* description of all the columns of an SQL command. */
|
||||
|
@ -127,7 +127,7 @@ class ODBConn : public BLOCK {
|
||||
|
||||
// Attributes
|
||||
public:
|
||||
char GetQuoteChar(void) {return m_IDQuoteChar;}
|
||||
char *GetQuoteChar(void) {return m_IDQuoteChar;}
|
||||
// Database successfully opened?
|
||||
bool IsOpen(void) {return m_hdbc != SQL_NULL_HDBC;}
|
||||
PSZ GetStringInfo(ushort infotype);
|
||||
@ -142,8 +142,9 @@ class ODBConn : public BLOCK {
|
||||
int ExecDirectSQL(char *sql, ODBCCOL *tocols);
|
||||
int Fetch(void);
|
||||
int PrepareSQL(char *sql);
|
||||
int ExecuteSQL(bool x);
|
||||
int ExecuteSQL(void);
|
||||
bool BindParam(ODBCCOL *colp);
|
||||
bool ExecSQLcommand(char *sql);
|
||||
int GetCatInfo(CATPARM *cap);
|
||||
bool GetDataSources(PQRYRES qrp);
|
||||
bool GetDrivers(PQRYRES qrp);
|
||||
@ -183,9 +184,9 @@ class ODBConn : public BLOCK {
|
||||
DWORD m_QueryTimeout;
|
||||
DWORD m_UpdateOptions;
|
||||
DWORD m_RowsetSize;
|
||||
char m_IDQuoteChar[2];
|
||||
int m_Catver;
|
||||
PSZ m_Connect;
|
||||
bool m_Updatable;
|
||||
bool m_Transact;
|
||||
char m_IDQuoteChar;
|
||||
}; // end of ODBConn class definition
|
||||
|
@ -106,13 +106,20 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
|
||||
TYPE_AM_DOM = 80, /* DOM access method type no */
|
||||
TYPE_AM_DIR = 90, /* DIR access method type no */
|
||||
TYPE_AM_ODBC = 100, /* ODBC access method type no */
|
||||
TYPE_AM_XDBC = 101, /* XDBC access method type no */
|
||||
TYPE_AM_OEM = 110, /* OEM access method type no */
|
||||
TYPE_AM_TBL = 115, /* TBL access method type no */
|
||||
TYPE_AM_PIVOT = 120, /* PIVOT access method type no */
|
||||
TYPE_AM_SRC = 121, /* PIVOT multiple column type no */
|
||||
TYPE_AM_FNC = 122, /* PIVOT source column type no */
|
||||
TYPE_AM_XCOL = 124, /* XCOL access method type no */
|
||||
TYPE_AM_XML = 127, /* XML access method type no */
|
||||
TYPE_AM_OCCUR = 128, /* OCCUR access method type no */
|
||||
TYPE_AM_PRX = 129, /* PROXY access method type no */
|
||||
TYPE_AM_XTB = 130, /* SYS table access method type */
|
||||
TYPE_AM_BLK = 131, /* BLK access method type no */
|
||||
TYPE_AM_ZIP = 132, /* ZIP access method type no */
|
||||
TYPE_AM_ZLIB = 133, /* ZLIB access method type no */
|
||||
TYPE_AM_MAC = 137, /* MAC table access method type */
|
||||
TYPE_AM_WMI = 139, /* WMI table access method type */
|
||||
TYPE_AM_XCL = 140, /* SYS column access method type */
|
||||
@ -123,7 +130,8 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
|
||||
TYPE_AM_DMY = 172, /* DMY Dummy tables am type no */
|
||||
TYPE_AM_SET = 180, /* SET Set tables am type no */
|
||||
TYPE_AM_MYSQL = 192, /* MYSQL access method type no */
|
||||
TYPE_AM_CAT = 193, /* Catalog access method type no */
|
||||
TYPE_AM_MYX = 193, /* MYSQL EXEC access method type */
|
||||
TYPE_AM_CAT = 195, /* Catalog access method type no */
|
||||
TYPE_AM_OUT = 200}; /* Output relations (storage) */
|
||||
|
||||
enum RECFM {RECFM_NAF = -2, /* Not a file */
|
||||
@ -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);
|
||||
char *MakeEscape(PGLOBAL g, char* str, char q);
|
||||
|
||||
bool PushWarning(PGLOBAL, PTDBASE);
|
||||
bool PushWarning(PGLOBAL, PTDBASE, int level = 1);
|
||||
|
@ -330,7 +330,7 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
|
||||
// Allocate the Value Block that will contain data
|
||||
if (crp->Length || nonull)
|
||||
crp->Kdata = AllocValBlock(g, NULL, crp->Type, maxres,
|
||||
crp->Length, 0, true, blank);
|
||||
crp->Length, 0, true, blank, false);
|
||||
else
|
||||
crp->Kdata = NULL;
|
||||
|
||||
|
@ -77,7 +77,7 @@ extern "C" int trace;
|
||||
/* No conversion of block values (check = true). */
|
||||
/***********************************************************************/
|
||||
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 -------------------------- */
|
||||
|
||||
|
@ -524,6 +524,7 @@ bool TDBCAT::OpenDB(PGLOBAL g)
|
||||
if (Initialize(g))
|
||||
return true;
|
||||
|
||||
Use = USE_OPEN;
|
||||
return InitCol(g);
|
||||
} // end of OpenDB
|
||||
|
||||
|
@ -321,7 +321,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
Portnumber = Cat->GetIntCatInfo("Port", GetDefaultPort());
|
||||
Server = Hostname;
|
||||
} else if (ParseURL(g, url))
|
||||
return TRUE;
|
||||
return true;
|
||||
|
||||
Bind = !!Cat->GetIntCatInfo("Bind", 0);
|
||||
Delayed = !!Cat->GetIntCatInfo("Delayed", 0);
|
||||
@ -344,7 +344,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
char *locdb = Database;
|
||||
|
||||
if (ParseURL(g, url))
|
||||
return TRUE;
|
||||
return true;
|
||||
|
||||
Database = locdb;
|
||||
} // endif url
|
||||
@ -353,9 +353,15 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
} // endif am
|
||||
|
||||
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;
|
||||
} // end of DefineAM
|
||||
|
||||
@ -388,6 +394,8 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
|
||||
User = tdp->Username;
|
||||
Pwd = tdp->Password;
|
||||
Server = tdp->Server;
|
||||
Qrystr = tdp->Qrystr;
|
||||
Quoted = max(0, tdp->Quoted);
|
||||
Port = tdp->Portnumber;
|
||||
Isview = tdp->Isview;
|
||||
Prep = tdp->Bind;
|
||||
@ -400,6 +408,8 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
|
||||
User = NULL;
|
||||
Pwd = NULL;
|
||||
Server = NULL;
|
||||
Qrystr = NULL;
|
||||
Quoted = 0;
|
||||
Port = 0;
|
||||
Isview = FALSE;
|
||||
Prep = FALSE;
|
||||
@ -424,6 +434,8 @@ TDBMYSQL::TDBMYSQL(PGLOBAL g, PTDBMY tdbp) : TDBASE(tdbp)
|
||||
Srcdef = tdbp->Srcdef;
|
||||
User = tdbp->User;
|
||||
Pwd = tdbp->Pwd;
|
||||
Qrystr = tdbp->Qrystr;
|
||||
Quoted = tdbp->Quoted;
|
||||
Port = tdbp->Port;
|
||||
Isview = tdbp->Isview;
|
||||
Prep = tdbp->Prep;
|
||||
@ -516,7 +528,7 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g)
|
||||
strcat(strcat(strcat(strcat(Query, " FROM "), tk), Tabname), tk);
|
||||
|
||||
if (To_Filter)
|
||||
strcat(strcat(Query, " WHERE "), To_Filter);
|
||||
strcat(strcat(Query, " WHERE "), To_Filter->Body);
|
||||
|
||||
if (trace)
|
||||
htrc("Query=%s\n", Query);
|
||||
@ -610,118 +622,109 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
|
||||
return FALSE;
|
||||
} // 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
|
||||
/***********************************************************************/
|
||||
/* 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 = "`";
|
||||
int len = 0, nset = 0;
|
||||
bool b = FALSE;
|
||||
PXOB xp;
|
||||
PSELECT selp;
|
||||
char *qc, cmd[8], tab[96], end[1024];
|
||||
|
||||
if (Query)
|
||||
return FALSE; // already done
|
||||
Query = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
|
||||
memset(end, 0, sizeof(end));
|
||||
|
||||
if (To_Filter)
|
||||
if (To_Filter->CheckLocal(this)) {
|
||||
where = (char*)PlugSubAlloc(g, NULL, 512); // Should be enough
|
||||
*where = '\0';
|
||||
if (sscanf(Qrystr, "%s `%[^`]`%1023c", cmd, tab, end) > 2 ||
|
||||
sscanf(Qrystr, "%s \"%[^\"]\"%1023c", cmd, tab, end) > 2)
|
||||
qc = "`";
|
||||
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))
|
||||
return TRUE;
|
||||
|
||||
To_Filter = NULL;
|
||||
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;
|
||||
assert(!stricmp(cmd, "update"));
|
||||
strcat(strcat(strcat(strcpy(Query, "UPDATE "), qc), Tabname), qc);
|
||||
strcat(Query, end);
|
||||
return RC_OK;
|
||||
} // end of MakeUpdate
|
||||
|
||||
/***********************************************************************/
|
||||
/* MakeDelete: make the Delete statement use with MySQL connection. */
|
||||
/* If no filtering Truncate is used because it is faster than Delete. */
|
||||
/* However, the number of deleted lines is not returned by MySQL. */
|
||||
/* Note: currently limited to local filtering. */
|
||||
/* MakeDelete: make the Delete statement used with MySQL connection. */
|
||||
/* Limited to remote filtering. */
|
||||
/***********************************************************************/
|
||||
bool TDBMYSQL::MakeDelete(PGLOBAL g)
|
||||
int TDBMYSQL::MakeDelete(PGLOBAL g)
|
||||
{
|
||||
char *tk = "`";
|
||||
int len = 0;
|
||||
char *qc, cmd[8], from[8], tab[96], end[512];
|
||||
|
||||
if (Query)
|
||||
return FALSE; // already done
|
||||
Query = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
|
||||
memset(end, 0, sizeof(end));
|
||||
|
||||
if (!To_Filter)
|
||||
AftRows = -1; // Means "all lines deleted"
|
||||
if (sscanf(Qrystr, "%s %s `%[^`]`%511c", cmd, from, tab, end) > 2 ||
|
||||
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
|
||||
len += (strlen(Tabname) + 16);
|
||||
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);
|
||||
assert(!stricmp(cmd, "delete") && !stricmp(from, "from"));
|
||||
strcat(strcat(strcat(strcpy(Query, "DELETE FROM "), qc), Tabname), qc);
|
||||
|
||||
if (To_Filter)
|
||||
strcat(strcat(Query, " WHERE "), To_Filter);
|
||||
if (*end)
|
||||
strcat(Query, end);
|
||||
|
||||
return FALSE;
|
||||
return RC_OK;
|
||||
} // end of MakeDelete
|
||||
#endif // 0
|
||||
|
||||
@ -751,7 +754,8 @@ int TDBMYSQL::GetMaxSize(PGLOBAL g)
|
||||
Query = NULL; // Must be remade when columns are known
|
||||
#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
|
||||
|
||||
return MaxSize;
|
||||
@ -766,12 +770,11 @@ int TDBMYSQL::RowNumber(PGLOBAL g, bool b)
|
||||
} // 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)
|
||||
{
|
||||
return (Mode == MODE_DELETE || Mode == MODE_UPDATE) ? 0
|
||||
: GetMaxSize(g);
|
||||
return (Mode == MODE_UPDATE) ? 0 : GetMaxSize(g);
|
||||
} // end of GetProgMax
|
||||
|
||||
/***********************************************************************/
|
||||
@ -874,33 +877,17 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
|
||||
m_Rc = Myc.ExecSQL(g, cmd, &w);
|
||||
} // endif m_Rc
|
||||
|
||||
#if 0
|
||||
} else if (Next) {
|
||||
strcpy(g->Message, MSG(NO_JOIN_UPDEL));
|
||||
} 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
|
||||
} else
|
||||
// m_Rc = (Mode == MODE_DELETE) ? MakeDelete(g) : MakeUpdate(g);
|
||||
m_Rc = MakeCommand(g);
|
||||
|
||||
if (m_Rc == RC_FX) {
|
||||
Myc.Close();
|
||||
return TRUE;
|
||||
return true;
|
||||
} // endif rc
|
||||
|
||||
Use = USE_OPEN; // Do it now in case we are recursively called
|
||||
return FALSE;
|
||||
Use = USE_OPEN;
|
||||
return false;
|
||||
} // end of OpenDB
|
||||
|
||||
/***********************************************************************/
|
||||
@ -975,6 +962,38 @@ char *TDBMYSQL::FindFieldColumn(char *name)
|
||||
return cp;
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
@ -986,6 +1005,9 @@ int TDBMYSQL::ReadDB(PGLOBAL g)
|
||||
htrc("MySQL ReadDB: R%d Mode=%d key=%p link=%p Kindex=%p\n",
|
||||
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. */
|
||||
/* Here is the place to fetch the line. */
|
||||
@ -1041,12 +1063,16 @@ int TDBMYSQL::WriteDB(PGLOBAL g)
|
||||
} // 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)
|
||||
{
|
||||
strcpy(g->Message, MSG(NO_MYSQL_DELETE));
|
||||
return RC_FX;
|
||||
if (irc == 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
|
||||
|
||||
/***********************************************************************/
|
||||
@ -1237,7 +1263,7 @@ void MYSQLCOL::InitBind(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
void MYSQLCOL::ReadColumn(PGLOBAL g)
|
||||
{
|
||||
char *buf;
|
||||
char *p, *buf, tim[20];
|
||||
int rc;
|
||||
PTDBMY tdbp = (PTDBMY)To_Tdb;
|
||||
|
||||
@ -1257,7 +1283,14 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
|
||||
if (trace)
|
||||
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 {
|
||||
if (Nullable)
|
||||
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 ???
|
||||
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. */
|
||||
/***********************************************************************/
|
||||
char *TDBMYEXC::MakeCMD(PGLOBAL g)
|
||||
PCMD TDBMYEXC::MakeCMD(PGLOBAL g)
|
||||
{
|
||||
char *xcmd = NULL;
|
||||
PCMD xcmd = NULL;
|
||||
|
||||
if (To_Filter) {
|
||||
if (Cmdcol) {
|
||||
char col[128], cmd[1024];
|
||||
int n;
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
n = sscanf(To_Filter, "%s = '%1023c", col, cmd);
|
||||
|
||||
if (n == 2 && !stricmp(col, Cmdcol)) {
|
||||
xcmd = (char*)PlugSubAlloc(g, NULL, strlen(cmd) + 1);
|
||||
|
||||
strcpy(xcmd, cmd);
|
||||
xcmd[strlen(xcmd) - 1] = 0;
|
||||
if (!stricmp(Cmdcol, To_Filter->Body) &&
|
||||
(To_Filter->Op == OP_EQ || To_Filter->Op == OP_IN)) {
|
||||
xcmd = To_Filter->Cmds;
|
||||
} else
|
||||
strcpy(g->Message, "Invalid command specification filter");
|
||||
|
||||
@ -1357,7 +1404,7 @@ char *TDBMYEXC::MakeCMD(PGLOBAL g)
|
||||
} else if (!Srcdef)
|
||||
strcpy(g->Message, "No Srcdef default command");
|
||||
else
|
||||
xcmd = Srcdef;
|
||||
xcmd = new(g) CMD(g, Srcdef);
|
||||
|
||||
return xcmd;
|
||||
} // end of MakeCMD
|
||||
@ -1368,7 +1415,7 @@ char *TDBMYEXC::MakeCMD(PGLOBAL g)
|
||||
int TDBMYEXC::GetMaxSize(PGLOBAL g)
|
||||
{
|
||||
if (MaxSize < 0) {
|
||||
MaxSize = 1;
|
||||
MaxSize = 10; // a guess
|
||||
} // endif MaxSize
|
||||
|
||||
return MaxSize;
|
||||
@ -1379,8 +1426,6 @@ int TDBMYEXC::GetMaxSize(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
bool TDBMYEXC::OpenDB(PGLOBAL g)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (Use == USE_OPEN) {
|
||||
strcpy(g->Message, "Multiple execution is not allowed");
|
||||
return true;
|
||||
@ -1407,20 +1452,11 @@ bool TDBMYEXC::OpenDB(PGLOBAL g)
|
||||
/*********************************************************************/
|
||||
/* Get the command to execute. */
|
||||
/*********************************************************************/
|
||||
if (!(Query = MakeCMD(g))) {
|
||||
if (!(Cmdlist = MakeCMD(g))) {
|
||||
Myc.Close();
|
||||
return true;
|
||||
} // endif Query
|
||||
|
||||
if ((rc = Myc.ExecSQL(g, Query)) == RC_NF) {
|
||||
strcpy(g->Message, "Affected rows");
|
||||
AftRows = Myc.m_Rows;
|
||||
} else if (rc == RC_OK) {
|
||||
sprintf(g->Message, "Columns and %d rows", Myc.m_Rows);
|
||||
AftRows = Myc.m_Fields;
|
||||
} else
|
||||
return true;
|
||||
|
||||
return false;
|
||||
} // end of OpenDB
|
||||
|
||||
@ -1429,7 +1465,54 @@ bool TDBMYEXC::OpenDB(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
int TDBMYEXC::ReadDB(PGLOBAL g)
|
||||
{
|
||||
return (++N) ? RC_EF : RC_OK;
|
||||
if (Havew) {
|
||||
// Process result set from SHOW WARNINGS
|
||||
if (Myc.Fetch(g, -1) != RC_OK) {
|
||||
Myc.FreeResult();
|
||||
Havew = Isw = false;
|
||||
} else {
|
||||
N++;
|
||||
Isw = true;
|
||||
return RC_OK;
|
||||
} // endif Fetch
|
||||
|
||||
} // endif m_Res
|
||||
|
||||
if (Cmdlist) {
|
||||
// Process query to send
|
||||
int rc;
|
||||
|
||||
do {
|
||||
Query = Cmdlist->Cmd;
|
||||
|
||||
switch (rc = Myc.ExecSQLcmd(g, Query, &Warnings)) {
|
||||
case RC_NF:
|
||||
AftRows = Myc.m_Afrw;
|
||||
strcpy(g->Message, "Affected rows");
|
||||
break;
|
||||
case RC_OK:
|
||||
AftRows = Myc.m_Fields;
|
||||
strcpy(g->Message, "Result set columns");
|
||||
break;
|
||||
case RC_FX:
|
||||
AftRows = Myc.m_Afrw;
|
||||
Nerr++;
|
||||
break;
|
||||
case RC_INFO:
|
||||
Shw = true;
|
||||
} // endswitch rc
|
||||
|
||||
Cmdlist = (Nerr > Mxr) ? NULL : Cmdlist->Next;
|
||||
} while (rc == RC_INFO);
|
||||
|
||||
if (Shw && Warnings)
|
||||
Havew = (Myc.ExecSQL(g, "SHOW WARNINGS") == RC_OK);
|
||||
|
||||
++N;
|
||||
return RC_OK;
|
||||
} else
|
||||
return RC_EF;
|
||||
|
||||
} // end of ReadDB
|
||||
|
||||
/***********************************************************************/
|
||||
@ -1480,12 +1563,23 @@ void MYXCOL::ReadColumn(PGLOBAL g)
|
||||
{
|
||||
PTDBMYX tdbp = (PTDBMYX)To_Tdb;
|
||||
|
||||
switch (Flag) {
|
||||
case 0: Value->SetValue_psz(tdbp->Query); break;
|
||||
case 1: Value->SetValue(tdbp->AftRows); break;
|
||||
case 2: Value->SetValue_psz(g->Message); break;
|
||||
default: Value->SetValue_psz("Invalid Flag"); break;
|
||||
} // endswitch Flag
|
||||
if (tdbp->Isw) {
|
||||
char *buf = NULL;
|
||||
|
||||
if (Flag < 3) {
|
||||
buf = tdbp->Myc.GetCharField(Flag);
|
||||
Value->SetValue_psz(buf);
|
||||
} else
|
||||
Value->Reset();
|
||||
|
||||
} else
|
||||
switch (Flag) {
|
||||
case 0: Value->SetValue_psz(tdbp->Query); break;
|
||||
case 1: Value->SetValue(tdbp->AftRows); break;
|
||||
case 2: Value->SetValue_psz(g->Message); break;
|
||||
case 3: Value->SetValue(tdbp->Warnings); break;
|
||||
default: Value->SetValue_psz("Invalid Flag"); break;
|
||||
} // endswitch Flag
|
||||
|
||||
} // end of ReadColumn
|
||||
|
||||
|
@ -20,6 +20,7 @@ typedef class MYSQLC *PMYC;
|
||||
/***********************************************************************/
|
||||
class MYSQLDEF : public TABDEF {/* Logical table description */
|
||||
friend class TDBMYSQL;
|
||||
friend class TDBMYEXC;
|
||||
friend class TDBMCL;
|
||||
friend class ha_connect;
|
||||
public:
|
||||
@ -52,7 +53,10 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
|
||||
PSZ Username; /* User logon name */
|
||||
PSZ Password; /* Password logon info */
|
||||
PSZ Server; /* PServerID */
|
||||
PSZ Qrystr; /* The original query */
|
||||
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 Bind; /* Use prepared statement on insert */
|
||||
bool Delayed; /* Delayed insert */
|
||||
@ -102,9 +106,11 @@ class TDBMYSQL : public TDBASE {
|
||||
// Internal functions
|
||||
bool MakeSelect(PGLOBAL g);
|
||||
bool MakeInsert(PGLOBAL g);
|
||||
//bool MakeUpdate(PGLOBAL g);
|
||||
//bool MakeDelete(PGLOBAL g);
|
||||
int BindColumns(PGLOBAL g);
|
||||
int MakeCommand(PGLOBAL g);
|
||||
//int MakeUpdate(PGLOBAL g);
|
||||
//int MakeDelete(PGLOBAL g);
|
||||
int SendCommand(PGLOBAL g);
|
||||
|
||||
// Members
|
||||
MYSQLC Myc; // MySQL connection class
|
||||
@ -118,6 +124,7 @@ class TDBMYSQL : public TDBASE {
|
||||
char *Server; // The server ID
|
||||
char *Query; // Points to SQL query
|
||||
char *Qbuf; // Used for not prepared insert
|
||||
char *Qrystr; // The original query
|
||||
bool Fetched; // True when fetch was done
|
||||
bool Isview; // True if this table is a MySQL view
|
||||
bool Prep; // Use prepared statement on insert
|
||||
@ -127,6 +134,7 @@ class TDBMYSQL : public TDBASE {
|
||||
int N; // The current table index
|
||||
int Port; // MySQL port number (0 = default)
|
||||
int Nparm; // The number of statement parameters
|
||||
int Quoted; // The identifier quoting level
|
||||
}; // end of class TDBMYSQL
|
||||
|
||||
/***********************************************************************/
|
||||
@ -167,13 +175,12 @@ class MYSQLCOL : public COLBLK {
|
||||
class TDBMYEXC : public TDBMYSQL {
|
||||
friend class MYXCOL;
|
||||
public:
|
||||
// Constructor
|
||||
TDBMYEXC(PMYDEF tdp) : TDBMYSQL(tdp) {Cmdcol = NULL;}
|
||||
TDBMYEXC(PGLOBAL g, PTDBMYX tdbp) : TDBMYSQL(g, tdbp)
|
||||
{Cmdcol = tdbp->Cmdcol;}
|
||||
// Constructors
|
||||
TDBMYEXC(PMYDEF tdp);
|
||||
TDBMYEXC(PGLOBAL g, PTDBMYX tdbp);
|
||||
|
||||
// Implementation
|
||||
//virtual AMT GetAmType(void) {return TYPE_AM_MYSQL;}
|
||||
virtual AMT GetAmType(void) {return TYPE_AM_MYX;}
|
||||
virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBMYEXC(g, this);}
|
||||
|
||||
// Methods
|
||||
@ -203,13 +210,20 @@ class TDBMYEXC : public TDBMYSQL {
|
||||
|
||||
protected:
|
||||
// Internal functions
|
||||
char *MakeCMD(PGLOBAL g);
|
||||
PCMD MakeCMD(PGLOBAL g);
|
||||
//bool MakeSelect(PGLOBAL g);
|
||||
//bool MakeInsert(PGLOBAL g);
|
||||
//int BindColumns(PGLOBAL g);
|
||||
|
||||
// Members
|
||||
PCMD Cmdlist; // The commands to execute
|
||||
char *Cmdcol; // The name of the Xsrc command column
|
||||
bool Shw; // Show warnings
|
||||
bool Havew; // True when processing warnings
|
||||
bool Isw; // True for warning lines
|
||||
int Warnings; // Warnings number
|
||||
int Mxr; // Maximum errors before closing
|
||||
int Nerr; // Number of errors so far
|
||||
}; // end of class TDBMYEXC
|
||||
|
||||
/***********************************************************************/
|
||||
|
@ -495,6 +495,7 @@ bool TDBOCCUR::OpenDB(PGLOBAL g)
|
||||
if (Tdbp->OpenDB(g))
|
||||
return TRUE;
|
||||
|
||||
Use = USE_OPEN;
|
||||
return ViewColumnList(g);
|
||||
} // end of OpenDB
|
||||
|
||||
|
@ -3,8 +3,6 @@
|
||||
|
||||
#include "tabutil.h"
|
||||
|
||||
#define TYPE_AM_OCCUR (AMT)128
|
||||
|
||||
typedef class OCCURDEF *POCCURDEF;
|
||||
typedef class TDBOCCUR *PTDBOCCUR;
|
||||
typedef class OCCURCOL *POCCURCOL;
|
||||
|
@ -90,8 +90,8 @@ extern int num_read, num_there, num_eq[2]; // Statistics
|
||||
/***********************************************************************/
|
||||
ODBCDEF::ODBCDEF(void)
|
||||
{
|
||||
Connect = Tabname = Tabowner = Tabqual = Srcdef = Qchar = NULL;
|
||||
Catver = Options = 0;
|
||||
Connect = Tabname = Tabowner = Tabqual = Srcdef = Qrystr = NULL;
|
||||
Catver = Options = Quoted = 0;
|
||||
Xsrc = false;
|
||||
} // end of ODBCDEF constructor
|
||||
|
||||
@ -107,9 +107,11 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
Tabowner = Cat->GetStringCatInfo(g, "Owner", "");
|
||||
Tabqual = Cat->GetStringCatInfo(g, "Qualifier", "");
|
||||
Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL);
|
||||
Qchar = Cat->GetStringCatInfo(g, "Qchar", "");
|
||||
Qrystr = Cat->GetStringCatInfo(g, "Query_String", "?");
|
||||
Catver = Cat->GetIntCatInfo("Catver", 2);
|
||||
Xsrc = Cat->GetBoolCatInfo("Execsrc", FALSE);
|
||||
Mxr = Cat->GetIntCatInfo("Maxerr", 0);
|
||||
Quoted = Cat->GetIntCatInfo("Quoted", 0);
|
||||
Options = ODBConn::noOdbcDialog;
|
||||
Pseudo = 2; // FILID is Ok but not ROWID
|
||||
return false;
|
||||
@ -169,8 +171,9 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
|
||||
Owner = tdp->Tabowner;
|
||||
Qualifier = tdp->Tabqual;
|
||||
Srcdef = tdp->Srcdef;
|
||||
Quote = tdp->GetQchar();
|
||||
Qrystr = tdp->Qrystr;
|
||||
Options = tdp->Options;
|
||||
Quoted = max(0, tdp->GetQuoted());
|
||||
Rows = tdp->GetElemt();
|
||||
Catver = tdp->Catver;
|
||||
} else {
|
||||
@ -179,12 +182,14 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
|
||||
Owner = NULL;
|
||||
Qualifier = NULL;
|
||||
Srcdef = NULL;
|
||||
Quote = NULL;
|
||||
Qrystr = NULL;
|
||||
Options = 0;
|
||||
Quoted = 0;
|
||||
Rows = 0;
|
||||
Catver = 0;
|
||||
} // endif tdp
|
||||
|
||||
Quote = NULL;
|
||||
Query = NULL;
|
||||
Count = NULL;
|
||||
//Where = NULL;
|
||||
@ -207,6 +212,7 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
|
||||
Owner = tdbp->Owner;
|
||||
Qualifier = tdbp->Qualifier;
|
||||
Srcdef = tdbp->Srcdef;
|
||||
Qrystr = tdbp->Qrystr;
|
||||
Quote = tdbp->Quote;
|
||||
Query = tdbp->Query;
|
||||
Count = tdbp->Count;
|
||||
@ -214,6 +220,7 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
|
||||
MulConn = tdbp->MulConn;
|
||||
DBQ = tdbp->DBQ;
|
||||
Options = tdbp->Options;
|
||||
Quoted = tdbp->Quoted;
|
||||
Rows = tdbp->Rows;
|
||||
Fpos = tdbp->Fpos;
|
||||
AftRows = tdbp->AftRows;
|
||||
@ -395,7 +402,7 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
|
||||
|
||||
// Below 14 is length of 'select ' + length of ' from ' + 1
|
||||
len = (strlen(colist) + strlen(buf) + 14);
|
||||
len += (To_Filter ? strlen(To_Filter) + 7 : 0);
|
||||
len += (To_Filter ? strlen(To_Filter->Body) + 7 : 0);
|
||||
|
||||
// if (tablep->GetQualifier()) This is used when using a table
|
||||
// qualp = tablep->GetQualifier(); from anotherPlugDB database but
|
||||
@ -432,7 +439,7 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
|
||||
strcat(sql, tabname);
|
||||
|
||||
if (To_Filter)
|
||||
strcat(strcat(sql, " WHERE "), To_Filter);
|
||||
strcat(strcat(sql, " WHERE "), To_Filter->Body);
|
||||
|
||||
return sql;
|
||||
} // end of MakeSQL
|
||||
@ -440,21 +447,18 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
|
||||
/***********************************************************************/
|
||||
/* 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 = "`";
|
||||
int len = 0;
|
||||
bool b = FALSE;
|
||||
PCOL colp;
|
||||
|
||||
if (Query)
|
||||
return false; // already done
|
||||
|
||||
for (colp = Columns; colp; colp = colp->GetNext())
|
||||
if (colp->IsSpecial()) {
|
||||
strcpy(g->Message, MSG(NO_ODBC_SPECOL));
|
||||
return true;
|
||||
return NULL;
|
||||
} else {
|
||||
len += (strlen(colp->GetName()) + 4);
|
||||
((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
|
||||
len = (strlen(TableName) + strlen(colist) + strlen(valist) + 32);
|
||||
Query = (char*)PlugSubAlloc(g, NULL, len);
|
||||
strcpy(Query, "INSERT INTO ");
|
||||
stmt = (char*)PlugSubAlloc(g, NULL, len);
|
||||
strcpy(stmt, "INSERT INTO ");
|
||||
|
||||
if (Quote)
|
||||
strcat(strcat(strcat(Query, Quote), TableName), Quote);
|
||||
strcat(strcat(strcat(stmt, Quote), TableName), Quote);
|
||||
else
|
||||
strcat(Query, TableName);
|
||||
strcat(stmt, TableName);
|
||||
|
||||
strcat(strcat(strcat(Query, " ("), colist), ") VALUES (");
|
||||
strcat(strcat(Query, valist), ")");
|
||||
strcat(strcat(strcat(stmt, " ("), colist), ") VALUES (");
|
||||
strcat(strcat(stmt, valist), ")");
|
||||
|
||||
return false;
|
||||
return stmt;
|
||||
} // end of MakeInsert
|
||||
|
||||
/***********************************************************************/
|
||||
@ -514,6 +518,127 @@ bool TDBODBC::BindParameters(PGLOBAL g)
|
||||
return false;
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
@ -533,7 +658,7 @@ int TDBODBC::GetMaxSize(PGLOBAL g)
|
||||
{
|
||||
if (MaxSize < 0) {
|
||||
// Make MariaDB happy
|
||||
MaxSize = 100;
|
||||
MaxSize = (Mode == MODE_DELETE) ? 0 : 10;
|
||||
#if 0
|
||||
// This is unuseful and takes time
|
||||
if (Srcdef) {
|
||||
@ -616,51 +741,40 @@ bool TDBODBC::OpenDB(PGLOBAL g)
|
||||
|
||||
if (Ocp->Open(Connect, Options) < 1)
|
||||
return true;
|
||||
else if (Quoted)
|
||||
Quote = Ocp->GetQuoteChar();
|
||||
|
||||
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) {
|
||||
/*******************************************************************/
|
||||
/* The issue here is that if max result size is needed, it must be */
|
||||
/* calculated before the result set for the final data retrieval is*/
|
||||
/* allocated and the final statement prepared so we call GetMaxSize*/
|
||||
/* here. It can be a waste of time if the max size is not needed */
|
||||
/* but currently we always are asking for it (for progress info). */
|
||||
/*******************************************************************/
|
||||
GetMaxSize(g); // Will be set for next call
|
||||
if ((Query = MakeSQL(g, false))) {
|
||||
for (PODBCCOL colp = (PODBCCOL)Columns; colp;
|
||||
colp = (PODBCCOL)colp->GetNext())
|
||||
if (!colp->IsSpecial())
|
||||
colp->AllocateBuffers(g, Rows);
|
||||
|
||||
if (!Query)
|
||||
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;
|
||||
rc = ((Rows = Ocp->ExecDirectSQL(Query, (PODBCCOL)Columns)) < 0);
|
||||
} // endif Query
|
||||
|
||||
if (!rc)
|
||||
rc = ((Rows = Ocp->ExecDirectSQL(Query, (PODBCCOL)Columns)) < 0);
|
||||
|
||||
} else if (Mode == MODE_INSERT) {
|
||||
if (!(rc = MakeInsert(g)))
|
||||
if ((Query = MakeInsert(g))) {
|
||||
if (Nparm != Ocp->PrepareSQL(Query)) {
|
||||
strcpy(g->Message, MSG(PARM_CNT_MISS));
|
||||
rc = true;
|
||||
} else
|
||||
rc = BindParameters(g);
|
||||
|
||||
} else {
|
||||
strcpy(g->Message, "No DELETE/UPDATE of ODBC tablesd");
|
||||
return true;
|
||||
} // endelse
|
||||
} // endif Query
|
||||
|
||||
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();
|
||||
return true;
|
||||
} // 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",
|
||||
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) {
|
||||
// Direct access of ODBC tables is not implemented yet
|
||||
strcpy(g->Message, MSG(NO_ODBC_DIRECT));
|
||||
@ -720,7 +849,7 @@ int TDBODBC::ReadDB(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
int TDBODBC::WriteDB(PGLOBAL g)
|
||||
{
|
||||
int n = Ocp->ExecuteSQL(false);
|
||||
int n = Ocp->ExecuteSQL();
|
||||
|
||||
if (n < 0) {
|
||||
AftRows = n;
|
||||
@ -736,8 +865,22 @@ int TDBODBC::WriteDB(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
int TDBODBC::DeleteDB(PGLOBAL g, int irc)
|
||||
{
|
||||
strcpy(g->Message, MSG(NO_ODBC_DELETE));
|
||||
return RC_FX;
|
||||
if (irc == 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
|
||||
|
||||
/***********************************************************************/
|
||||
@ -751,6 +894,7 @@ void TDBODBC::CloseDB(PGLOBAL g)
|
||||
// } // endif
|
||||
|
||||
if (Ocp)
|
||||
|
||||
Ocp->Close();
|
||||
|
||||
if (trace)
|
||||
@ -934,7 +1078,7 @@ void ODBCCOL::AllocateBuffers(PGLOBAL g, int rows)
|
||||
if (Buf_Type == TYPE_DATE)
|
||||
Bufp = PlugSubAlloc(g, NULL, rows * sizeof(TIMESTAMP_STRUCT));
|
||||
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();
|
||||
} // endelse
|
||||
|
||||
@ -1004,6 +1148,22 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
/* Implementation of the TDBODBC class. */
|
||||
/***********************************************************************/
|
||||
TDBXDBC::TDBXDBC(PODEF tdp) : TDBODBC(tdp)
|
||||
{
|
||||
Cmdlist = NULL;
|
||||
Cmdcol = NULL;
|
||||
Mxr = tdp->Mxr;
|
||||
Nerr = 0;
|
||||
} // end of TDBXDBC constructor
|
||||
|
||||
TDBXDBC::TDBXDBC(PTDBXDBC tdbp) : TDBODBC(tdbp)
|
||||
{
|
||||
Cmdlist = tdbp->Cmdlist;
|
||||
Cmdcol = tdbp->Cmdcol;
|
||||
Mxr = tdbp->Mxr;
|
||||
Nerr = tdbp->Nerr;
|
||||
} // end of TDBXDBC copy constructor
|
||||
|
||||
PTDB TDBXDBC::CopyOne(PTABS t)
|
||||
{
|
||||
PTDB tp;
|
||||
@ -1036,23 +1196,15 @@ PCOL TDBXDBC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
|
||||
/***********************************************************************/
|
||||
/* MakeCMD: make the SQL statement to send to ODBC connection. */
|
||||
/***********************************************************************/
|
||||
char *TDBXDBC::MakeCMD(PGLOBAL g)
|
||||
PCMD TDBXDBC::MakeCMD(PGLOBAL g)
|
||||
{
|
||||
char *xcmd = NULL;
|
||||
PCMD xcmd = NULL;
|
||||
|
||||
if (To_Filter) {
|
||||
if (Cmdcol) {
|
||||
char col[128], cmd[1024];
|
||||
int n;
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
n = sscanf(To_Filter, "%s = '%1023c", col, cmd);
|
||||
|
||||
if (n == 2 && !stricmp(col, Cmdcol)) {
|
||||
xcmd = (char*)PlugSubAlloc(g, NULL, strlen(cmd) + 1);
|
||||
|
||||
strcpy(xcmd, cmd);
|
||||
xcmd[strlen(xcmd) - 1] = 0;
|
||||
if (!stricmp(Cmdcol, To_Filter->Body) &&
|
||||
(To_Filter->Op == OP_EQ || To_Filter->Op == OP_IN)) {
|
||||
xcmd = To_Filter->Cmds;
|
||||
} else
|
||||
strcpy(g->Message, "Invalid command specification filter");
|
||||
|
||||
@ -1062,7 +1214,7 @@ char *TDBXDBC::MakeCMD(PGLOBAL g)
|
||||
} else if (!Srcdef)
|
||||
strcpy(g->Message, "No Srcdef default command");
|
||||
else
|
||||
xcmd = Srcdef;
|
||||
xcmd = new(g) CMD(g, Srcdef);
|
||||
|
||||
return xcmd;
|
||||
} // end of MakeCMD
|
||||
@ -1088,12 +1240,12 @@ bool TDBXDBC::BindParameters(PGLOBAL g)
|
||||
#endif // 0
|
||||
|
||||
/***********************************************************************/
|
||||
/* XDBC GetMaxSize: returns table size (always one row). */
|
||||
/* XDBC GetMaxSize: returns table size (not always one row). */
|
||||
/***********************************************************************/
|
||||
int TDBXDBC::GetMaxSize(PGLOBAL g)
|
||||
{
|
||||
if (MaxSize < 0)
|
||||
MaxSize = 1;
|
||||
MaxSize = 10; // Just a guess
|
||||
|
||||
return MaxSize;
|
||||
} // end of GetMaxSize
|
||||
@ -1142,19 +1294,12 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
|
||||
/*********************************************************************/
|
||||
/* Get the command to execute. */
|
||||
/*********************************************************************/
|
||||
if (!(Query = MakeCMD(g))) {
|
||||
if (!(Cmdlist = MakeCMD(g))) {
|
||||
Ocp->Close();
|
||||
return true;
|
||||
} // endif Query
|
||||
|
||||
Rows = 1;
|
||||
|
||||
if (Ocp->PrepareSQL(Query)) {
|
||||
strcpy(g->Message, "Parameters not supported");
|
||||
AftRows = -1;
|
||||
} else
|
||||
AftRows = 0;
|
||||
|
||||
return false;
|
||||
} // end of OpenDB
|
||||
|
||||
@ -1163,18 +1308,18 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
int TDBXDBC::ReadDB(PGLOBAL g)
|
||||
{
|
||||
if (trace)
|
||||
htrc("XDBC ReadDB: query=%s\n", SVP(Query));
|
||||
if (Cmdlist) {
|
||||
Query = Cmdlist->Cmd;
|
||||
|
||||
if (Rows--) {
|
||||
if (!AftRows)
|
||||
AftRows = Ocp->ExecuteSQL(true);
|
||||
if (Ocp->ExecSQLcommand(Query))
|
||||
Nerr++;
|
||||
|
||||
Fpos++; // Used for progress info
|
||||
Cmdlist = (Nerr > Mxr) ? NULL : Cmdlist->Next;
|
||||
return RC_OK;
|
||||
} else
|
||||
return RC_EF;
|
||||
|
||||
Fpos++; // Used for progress info
|
||||
return RC_OK;
|
||||
} // end of ReadDB
|
||||
|
||||
/***********************************************************************/
|
||||
@ -1186,6 +1331,15 @@ int TDBXDBC::WriteDB(PGLOBAL g)
|
||||
return RC_FX;
|
||||
} // 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 ------------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
|
@ -34,7 +34,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
|
||||
PSZ GetTabowner(void) {return Tabowner;}
|
||||
PSZ GetTabqual(void) {return Tabqual;}
|
||||
PSZ GetSrcdef(void) {return Srcdef;}
|
||||
PSZ GetQchar(void) {return (Qchar && *Qchar) ? Qchar : NULL;}
|
||||
int GetQuoted(void) {return Quoted;}
|
||||
int GetCatver(void) {return Catver;}
|
||||
int GetOptions(void) {return Options;}
|
||||
|
||||
@ -50,8 +50,11 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
|
||||
PSZ Tabqual; /* External table qualifier */
|
||||
PSZ Srcdef; /* The source table SQL definition */
|
||||
PSZ Qchar; /* Identifier quoting character */
|
||||
PSZ Qrystr; /* The original query */
|
||||
int Catver; /* ODBC version for catalog functions */
|
||||
int Options; /* Open connection options */
|
||||
int Quoted; /* Identifier quoting level */
|
||||
int Mxr; /* Maxerr for an Exec table */
|
||||
bool Xsrc; /* Execution type */
|
||||
}; // end of ODBCDEF
|
||||
|
||||
@ -96,13 +99,14 @@ class TDBODBC : public TDBASE {
|
||||
|
||||
protected:
|
||||
// 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);
|
||||
//bool MakeUpdate(PGLOBAL g, PSELECT selist);
|
||||
bool MakeInsert(PGLOBAL g);
|
||||
//bool MakeDelete(PGLOBAL g);
|
||||
char *MakeInsert(PGLOBAL g);
|
||||
char *MakeCommand(PGLOBAL g);
|
||||
//bool MakeFilter(PGLOBAL g, bool c);
|
||||
bool BindParameters(PGLOBAL g);
|
||||
//char *MakeUpdate(PGLOBAL g);
|
||||
//char *MakeDelete(PGLOBAL g);
|
||||
|
||||
// Members
|
||||
ODBConn *Ocp; // Points to an ODBC connection class
|
||||
@ -118,7 +122,9 @@ class TDBODBC : public TDBASE {
|
||||
char *Quote; // The identifier quoting character
|
||||
char *MulConn; // Used for multiple ODBC tables
|
||||
char *DBQ; // The address part of Connect string
|
||||
char *Qrystr; // The original query
|
||||
int Options; // Connect options
|
||||
int Quoted; // The identifier quoting level
|
||||
int Fpos; // Position of last read record
|
||||
int AftRows; // The number of affected rows
|
||||
int Rows; // Rowset size
|
||||
@ -179,12 +185,12 @@ class TDBXDBC : public TDBODBC {
|
||||
friend class XSRCCOL;
|
||||
friend class ODBConn;
|
||||
public:
|
||||
// Constructor
|
||||
TDBXDBC(PODEF tdp = NULL) : TDBODBC(tdp) {Cmdcol = NULL;}
|
||||
TDBXDBC(PTDBXDBC tdbp) : TDBODBC(tdbp) {Cmdcol = tdbp->Cmdcol;}
|
||||
// Constructors
|
||||
TDBXDBC(PODEF tdp = NULL);
|
||||
TDBXDBC(PTDBXDBC tdbp);
|
||||
|
||||
// Implementation
|
||||
//virtual AMT GetAmType(void) {return TYPE_AM_ODBC;}
|
||||
virtual AMT GetAmType(void) {return TYPE_AM_XDBC;}
|
||||
virtual PTDB Duplicate(PGLOBAL g)
|
||||
{return (PTDB)new(g) TDBXDBC(this);}
|
||||
|
||||
@ -204,16 +210,19 @@ class TDBXDBC : public TDBODBC {
|
||||
virtual bool OpenDB(PGLOBAL g);
|
||||
virtual int ReadDB(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);
|
||||
|
||||
protected:
|
||||
// Internal functions
|
||||
char *MakeCMD(PGLOBAL g);
|
||||
PCMD MakeCMD(PGLOBAL g);
|
||||
//bool BindParameters(PGLOBAL g);
|
||||
|
||||
// Members
|
||||
PCMD Cmdlist; // The commands to execute
|
||||
char *Cmdcol; // The name of the Xsrc command column
|
||||
int Mxr; // Maximum errors before closing
|
||||
int Nerr; // Number of errors so far
|
||||
}; // end of class TDBXDBC
|
||||
|
||||
/***********************************************************************/
|
||||
|
@ -607,6 +607,8 @@ bool TDBPIVOT::OpenDB(PGLOBAL g)
|
||||
if (Tdbp->OpenDB(g))
|
||||
return TRUE;
|
||||
|
||||
Use = USE_OPEN; // Do it now in case we are recursively called
|
||||
|
||||
/*********************************************************************/
|
||||
/* Make all required pivot columns for object views. */
|
||||
/*********************************************************************/
|
||||
|
@ -295,15 +295,18 @@ bool TDBTBL::InitTableList(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTABLE tabp)
|
||||
{
|
||||
char *fil, op[8], tn[NAME_LEN];
|
||||
char *body, *fil, op[8], tn[NAME_LEN];
|
||||
bool neg;
|
||||
|
||||
if (!filp)
|
||||
return TRUE;
|
||||
else if (strstr(filp, " OR ") || strstr(filp, " AND "))
|
||||
else
|
||||
body = filp->Body;
|
||||
|
||||
if (strstr(body, " OR ") || strstr(body, " AND "))
|
||||
return TRUE; // Not handled yet
|
||||
else
|
||||
fil = filp + (*filp == '(' ? 1 : 0);
|
||||
fil = body + (*body == '(' ? 1 : 0);
|
||||
|
||||
if (sscanf(fil, "TABID %s", op) != 1)
|
||||
return TRUE; // ignore invalid filter
|
||||
|
@ -495,6 +495,7 @@ bool TDBPRX::OpenDB(PGLOBAL g)
|
||||
if (Tdbp->OpenDB(g))
|
||||
return TRUE;
|
||||
|
||||
Use = USE_OPEN;
|
||||
return FALSE;
|
||||
} // end of OpenDB
|
||||
|
||||
|
@ -6,8 +6,6 @@
|
||||
|
||||
//#include "tabtbl.h"
|
||||
|
||||
#define TYPE_AM_PRX (AMT)129
|
||||
|
||||
typedef class PRXDEF *PPRXDEF;
|
||||
typedef class TDBPRX *PTDBPRX;
|
||||
typedef class XXLCOL *PXXLCOL;
|
||||
|
@ -81,7 +81,7 @@ char *strerror(int num);
|
||||
/* Conversion of block values allowed conditionally for insert only. */
|
||||
/***********************************************************************/
|
||||
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 -------------------------- */
|
||||
|
@ -480,18 +480,19 @@ bool TDBWMI::Initialize(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
void TDBWMI::DoubleSlash(PGLOBAL g)
|
||||
{
|
||||
if (To_Filter && strchr(To_Filter, '\\')) {
|
||||
char *buf = (char*)PlugSubAlloc(g, NULL, strlen(To_Filter) * 2);
|
||||
if (To_Filter && strchr(To_Filter->Body, '\\')) {
|
||||
char *body = To_Filter->Body;
|
||||
char *buf = (char*)PlugSubAlloc(g, NULL, strlen(body) * 2);
|
||||
int i = 0, k = 0;
|
||||
|
||||
do {
|
||||
if (To_Filter[i] == '\\')
|
||||
if (body[i] == '\\')
|
||||
buf[k++] = '\\';
|
||||
|
||||
buf[k++] = To_Filter[i];
|
||||
} while (To_Filter[i++]);
|
||||
buf[k++] = body[i];
|
||||
} while (body[i++]);
|
||||
|
||||
To_Filter = buf;
|
||||
To_Filter->Body = buf;
|
||||
} // endif To_Filter
|
||||
|
||||
} // end of DoubleSlash
|
||||
@ -539,13 +540,13 @@ char *TDBWMI::MakeWQL(PGLOBAL g)
|
||||
|
||||
// Below 14 is length of 'select ' + length of ' from ' + 1
|
||||
len = (strlen(colist) + strlen(Wclass) + 14);
|
||||
len += (To_Filter ? strlen(To_Filter) + 7 : 0);
|
||||
len += (To_Filter ? strlen(To_Filter->Body) + 7 : 0);
|
||||
wql = (char*)PlugSubAlloc(g, NULL, len);
|
||||
strcat(strcat(strcpy(wql, "SELECT "), colist), " FROM ");
|
||||
strcat(wql, Wclass);
|
||||
|
||||
if (To_Filter)
|
||||
strcat(strcat(wql, " WHERE "), To_Filter);
|
||||
strcat(strcat(wql, " WHERE "), To_Filter->Body);
|
||||
|
||||
return wql;
|
||||
} // end of MakeWQL
|
||||
@ -666,6 +667,8 @@ bool TDBWMI::OpenDB(PGLOBAL g)
|
||||
} else
|
||||
DoubleSlash(g);
|
||||
|
||||
Use = USE_OPEN; // Do it now in case we are recursively called
|
||||
|
||||
/*********************************************************************/
|
||||
/* Initialize the WMI processing. */
|
||||
/*********************************************************************/
|
||||
|
@ -193,6 +193,7 @@ bool TDBXCL::OpenDB(PGLOBAL g)
|
||||
if (Tdbp->OpenDB(g))
|
||||
return TRUE;
|
||||
|
||||
Use = USE_OPEN;
|
||||
return FALSE;
|
||||
} // end of OpenDB
|
||||
|
||||
|
@ -3,8 +3,6 @@
|
||||
|
||||
#include "tabutil.h"
|
||||
|
||||
#define TYPE_AM_XCOL (AMT)124
|
||||
|
||||
typedef class XCLDEF *PXCLDEF;
|
||||
typedef class TDBXCL *PTDBXCL;
|
||||
typedef class XCLCOL *PXCLCOL;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/************ 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 */
|
||||
/* */
|
||||
@ -16,7 +16,7 @@
|
||||
/* types of objects, we shall have more classes to update. */
|
||||
/* This is why we are now using a template class for many types. */
|
||||
/* 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. */
|
||||
/***********************************************************************/
|
||||
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;
|
||||
|
||||
@ -64,22 +64,38 @@ PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len,
|
||||
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
case TYPE_DATE: // ?????
|
||||
blkp = new(g) DATBLK(mp, nval);
|
||||
break;
|
||||
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;
|
||||
case TYPE_FLOAT:
|
||||
blkp = new(g) TYPBLK<double>(mp, nval, prec, type);
|
||||
blkp = new(g) TYPBLK<double>(mp, nval, type, prec);
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
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. */
|
||||
/***********************************************************************/
|
||||
VALBLK::VALBLK(void *mp, int type, int nval)
|
||||
VALBLK::VALBLK(void *mp, int type, int nval, bool un)
|
||||
{
|
||||
Blkp = mp;
|
||||
To_Nulls = NULL;
|
||||
Check = true;
|
||||
Nullable = false;
|
||||
Unsigned = un;
|
||||
Type = type;
|
||||
Nval = nval;
|
||||
Prec = 0;
|
||||
@ -195,23 +212,15 @@ void VALBLK::ChkTyp(PVBLK vb)
|
||||
/* -------------------------- Class TYPBLK --------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Constructors. */
|
||||
/* Constructor. */
|
||||
/***********************************************************************/
|
||||
template <class TYPE>
|
||||
TYPBLK<TYPE>::TYPBLK(void *mp, int nval, int type)
|
||||
: VALBLK(mp, type, nval), Typp((TYPE*&)Blkp)
|
||||
TYPBLK<TYPE>::TYPBLK(void *mp, int nval, int type, int prec, bool un)
|
||||
: 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;
|
||||
Fmt = GetFmt(Type);
|
||||
} // end of DBLBLK constructor
|
||||
} // end of TYPBLK constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* Initialization routine. */
|
||||
@ -249,14 +258,26 @@ template <>
|
||||
int TYPBLK<int>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetIntValue();}
|
||||
|
||||
template <>
|
||||
uint TYPBLK<uint>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetUIntValue();}
|
||||
|
||||
template <>
|
||||
short TYPBLK<short>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetShortValue();}
|
||||
|
||||
template <>
|
||||
ushort TYPBLK<ushort>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetUShortValue();}
|
||||
|
||||
template <>
|
||||
longlong TYPBLK<longlong>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetBigintValue();}
|
||||
|
||||
template <>
|
||||
ulonglong TYPBLK<ulonglong>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetUBigintValue();}
|
||||
|
||||
template <>
|
||||
double TYPBLK<double>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetFloatValue();}
|
||||
@ -265,6 +286,10 @@ template <>
|
||||
char TYPBLK<char>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetTinyValue();}
|
||||
|
||||
template <>
|
||||
uchar TYPBLK<uchar>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetUTinyValue();}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Set one value in a block from a zero terminated string. */
|
||||
/***********************************************************************/
|
||||
@ -286,13 +311,21 @@ void TYPBLK<TYPE>::SetValue(PSZ p, int n)
|
||||
template <>
|
||||
int TYPBLK<int>::GetTypedValue(PSZ p) {return atol(p);}
|
||||
template <>
|
||||
uint TYPBLK<uint>::GetTypedValue(PSZ p) {return (unsigned)atol(p);}
|
||||
template <>
|
||||
short TYPBLK<short>::GetTypedValue(PSZ p) {return (short)atoi(p);}
|
||||
template <>
|
||||
ushort TYPBLK<ushort>::GetTypedValue(PSZ p) {return (ushort)atoi(p);}
|
||||
template <>
|
||||
longlong TYPBLK<longlong>::GetTypedValue(PSZ p) {return atoll(p);}
|
||||
template <>
|
||||
ulonglong TYPBLK<ulonglong>::GetTypedValue(PSZ p) {return (unsigned)atoll(p);}
|
||||
template <>
|
||||
double TYPBLK<double>::GetTypedValue(PSZ p) {return atof(p);}
|
||||
template <>
|
||||
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. */
|
||||
@ -333,14 +366,26 @@ template <>
|
||||
int TYPBLK<int>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetIntValue(n);}
|
||||
|
||||
template <>
|
||||
uint TYPBLK<uint>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetUIntValue(n);}
|
||||
|
||||
template <>
|
||||
short TYPBLK<short>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetShortValue(n);}
|
||||
|
||||
template <>
|
||||
ushort TYPBLK<ushort>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetUShortValue(n);}
|
||||
|
||||
template <>
|
||||
longlong TYPBLK<longlong>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetBigintValue(n);}
|
||||
|
||||
template <>
|
||||
ulonglong TYPBLK<ulonglong>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetUBigintValue(n);}
|
||||
|
||||
template <>
|
||||
double TYPBLK<double>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetFloatValue(n);}
|
||||
@ -349,6 +394,10 @@ template <>
|
||||
char TYPBLK<char>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetTinyValue(n);}
|
||||
|
||||
template <>
|
||||
uchar TYPBLK<uchar>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetUTinyValue(n);}
|
||||
|
||||
#if 0
|
||||
/***********************************************************************/
|
||||
/* 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));
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
@ -524,6 +581,14 @@ int CHRBLK::GetIntValue(int n)
|
||||
return atol((char *)GetValPtrEx(n));
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
@ -532,6 +597,14 @@ longlong CHRBLK::GetBigintValue(int n)
|
||||
return atoll((char *)GetValPtrEx(n));
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
@ -548,6 +621,14 @@ char CHRBLK::GetTinyValue(int n)
|
||||
return (char)atoi((char *)GetValPtrEx(n));
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*************** 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 */
|
||||
/* */
|
||||
@ -18,8 +18,9 @@
|
||||
/***********************************************************************/
|
||||
/* Utility used to allocate value blocks. */
|
||||
/***********************************************************************/
|
||||
DllExport PVBLK AllocValBlock(PGLOBAL, void*, int, int, int, int, bool, bool);
|
||||
const char *GetFmt(int type);
|
||||
DllExport PVBLK AllocValBlock(PGLOBAL, void*, int, int, int, int,
|
||||
bool, bool, bool);
|
||||
const char *GetFmt(int type, bool un = false);
|
||||
|
||||
/***********************************************************************/
|
||||
/* Class VALBLK represent a base class for variable blocks. */
|
||||
@ -28,7 +29,7 @@ class VALBLK : public BLOCK {
|
||||
//friend void SemColData(PGLOBAL g, PSEM semp);
|
||||
public:
|
||||
// Constructors
|
||||
VALBLK(void *mp, int type, int nval);
|
||||
VALBLK(void *mp, int type, int nval, bool un = false);
|
||||
|
||||
// Implementation
|
||||
int GetNval(void) {return Nval;}
|
||||
@ -48,10 +49,14 @@ class VALBLK : public BLOCK {
|
||||
virtual int GetVlen(void) = 0;
|
||||
virtual PSZ GetCharValue(int n);
|
||||
virtual short GetShortValue(int n) = 0;
|
||||
virtual ushort GetUShortValue(int n) = 0;
|
||||
virtual int GetIntValue(int n) = 0;
|
||||
virtual uint GetUIntValue(int n) = 0;
|
||||
virtual longlong GetBigintValue(int n) = 0;
|
||||
virtual ulonglong GetUBigintValue(int n) = 0;
|
||||
virtual double GetFloatValue(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 Reset(int n) = 0;
|
||||
virtual bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
|
||||
@ -60,10 +65,14 @@ class VALBLK : public BLOCK {
|
||||
|
||||
// Methods
|
||||
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(uint 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(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(char *sp, uint len, int n) {assert(false);}
|
||||
virtual void SetValue(PVAL valp, int n) = 0;
|
||||
@ -94,6 +103,7 @@ class VALBLK : public BLOCK {
|
||||
void *Blkp; // To value block
|
||||
bool Check; // If true SetValue types must match
|
||||
bool Nullable; // True if values can be null
|
||||
bool Unsigned; // True if values are unsigned
|
||||
int Type; // Type of individual values
|
||||
int Nval; // Max number of values in block
|
||||
int Prec; // Precision of float values
|
||||
@ -106,18 +116,22 @@ template <class TYPE>
|
||||
class TYPBLK : public VALBLK {
|
||||
public:
|
||||
// Constructors
|
||||
TYPBLK(void *mp, int size, int type);
|
||||
TYPBLK(void *mp, int size, int prec, int type);
|
||||
TYPBLK(void *mp, int size, int type, int prec = 0, bool un = false);
|
||||
//TYPBLK(void *mp, int size, int prec, int type);
|
||||
|
||||
// Implementation
|
||||
virtual void Init(PGLOBAL g, bool check);
|
||||
virtual int GetVlen(void) {return sizeof(TYPE);}
|
||||
//virtual PSZ GetCharValue(int 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 uint GetUIntValue(int n) {return (uint)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 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;}
|
||||
|
||||
// Methods
|
||||
@ -125,14 +139,22 @@ class TYPBLK : public VALBLK {
|
||||
virtual void SetValue(char *sp, uint len, int n);
|
||||
virtual void SetValue(short sval, int n)
|
||||
{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)
|
||||
{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)
|
||||
{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)
|
||||
{Typp[n] = (TYPE)fval; SetNull(n, false);}
|
||||
virtual void SetValue(char cval, int n)
|
||||
{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(PVBLK pv, int n1, int n2);
|
||||
//virtual void SetValues(PVBLK pv, int k, int n);
|
||||
@ -168,10 +190,14 @@ class CHRBLK : public VALBLK {
|
||||
virtual int GetVlen(void) {return Long;}
|
||||
virtual PSZ GetCharValue(int n);
|
||||
virtual short GetShortValue(int n);
|
||||
virtual ushort GetUShortValue(int n);
|
||||
virtual int GetIntValue(int n);
|
||||
virtual uint GetUIntValue(int n);
|
||||
virtual longlong GetBigintValue(int n);
|
||||
virtual ulonglong GetUBigintValue(int n);
|
||||
virtual double GetFloatValue(int n);
|
||||
virtual char GetTinyValue(int n);
|
||||
virtual uchar GetUTinyValue(int n);
|
||||
virtual void Reset(int n);
|
||||
virtual void SetPrec(int p) {Ci = (p != 0);}
|
||||
virtual bool IsCi(void) {return Ci;}
|
||||
@ -217,10 +243,14 @@ class STRBLK : public VALBLK {
|
||||
virtual int GetVlen(void) {return sizeof(PSZ);}
|
||||
virtual PSZ GetCharValue(int n) {return 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 uint GetUIntValue(int n) {return (unsigned)atol(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 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;}
|
||||
|
||||
// Methods
|
||||
|
@ -1,5 +1,5 @@
|
||||
/************* 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 */
|
||||
/* */
|
||||
@ -20,7 +20,7 @@
|
||||
/* functions used on one family only. The drawback is that for new */
|
||||
/* types of objects, we shall have more classes to update. */
|
||||
/* 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
|
||||
|
||||
#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. */
|
||||
/***********************************************************************/
|
||||
PSZ GetTypeName(int type)
|
||||
{
|
||||
PSZ name = "UNKNOWN";
|
||||
PSZ name;
|
||||
|
||||
switch (type) {
|
||||
case TYPE_STRING: name = "CHAR"; break;
|
||||
@ -135,6 +107,7 @@ PSZ GetTypeName(int type)
|
||||
case TYPE_DATE: name = "DATE"; break;
|
||||
case TYPE_FLOAT: name = "FLOAT"; break;
|
||||
case TYPE_TINY: name = "TINY"; break;
|
||||
default: name = "UNKNOWN"; break;
|
||||
} // endswitch type
|
||||
|
||||
return name;
|
||||
@ -153,7 +126,6 @@ int GetTypeSize(int type, int len)
|
||||
case TYPE_DATE: len = sizeof(int); break;
|
||||
case TYPE_FLOAT: len = sizeof(double); break;
|
||||
case TYPE_TINY: len = sizeof(char); break;
|
||||
break;
|
||||
default: len = 0;
|
||||
} // endswitch type
|
||||
|
||||
@ -236,21 +208,22 @@ bool IsTypeNum(int type)
|
||||
/***********************************************************************/
|
||||
/* 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;
|
||||
|
||||
switch (type) {
|
||||
case TYPE_STRING: fmt = "%s"; break;
|
||||
case TYPE_SHORT: fmt = "%hd"; break;
|
||||
case TYPE_BIGINT: fmt = "%lld"; break;
|
||||
case TYPE_FLOAT: fmt = "%.*lf"; break;
|
||||
default: fmt = "%d"; break;
|
||||
case TYPE_STRING: fmt = "%s"; break;
|
||||
case TYPE_SHORT: fmt = (un) ? "%hu" : "%hd"; break;
|
||||
case TYPE_BIGINT: fmt = (un) ? "%llu" : "%lld"; break;
|
||||
case TYPE_FLOAT: fmt = "%.*lf"; break;
|
||||
default: fmt = (un) ? "%u" : "%d"; break;
|
||||
} // endswitch Type
|
||||
|
||||
return fmt;
|
||||
} // end of GetFmt
|
||||
|
||||
#if 0
|
||||
/***********************************************************************/
|
||||
/* ConvertType: what this function does is to determine the type to */
|
||||
/* 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
|
||||
|
||||
} // end of ConvertType
|
||||
#endif // 0
|
||||
|
||||
/***********************************************************************/
|
||||
/* 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);
|
||||
break;
|
||||
case TYPE_FLOAT:
|
||||
valp = new(g) TYPVAL<double>(*(double *)value, TYPE_FLOAT);
|
||||
valp = new(g) TYPVAL<double>(*(double *)value, TYPE_FLOAT, 2);
|
||||
break;
|
||||
case 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. */
|
||||
/***********************************************************************/
|
||||
PVAL AllocateValue(PGLOBAL g, int type, int len, int prec,
|
||||
PSZ dom, PCATLG cat)
|
||||
PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, PSZ fmt)
|
||||
{
|
||||
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);
|
||||
break;
|
||||
case TYPE_DATE:
|
||||
valp = new(g) DTVAL(g, len, prec, dom);
|
||||
valp = new(g) DTVAL(g, len, prec, fmt);
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
case TYPE_FLOAT:
|
||||
valp = new(g) TYPVAL<double>(0.0, prec, TYPE_FLOAT);
|
||||
valp = new(g) TYPVAL<double>(0.0, TYPE_FLOAT, prec);
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
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. */
|
||||
/* 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
|
||||
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());
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
case TYPE_DATE:
|
||||
valp = new(g) DTVAL(g, valp->GetIntValue());
|
||||
break;
|
||||
case TYPE_FLOAT:
|
||||
valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_FLOAT);
|
||||
valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_FLOAT,
|
||||
valp->GetValPrec());
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
sprintf(g->Message, MSG(BAD_VALUE_TYPE), newtype);
|
||||
@ -428,14 +438,15 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype)
|
||||
/***********************************************************************/
|
||||
/* 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;
|
||||
Nullable = false;
|
||||
Unsigned = un;
|
||||
Clen = 0;
|
||||
Prec = 0;
|
||||
Fmt = GetFmt(Type, Unsigned);
|
||||
Xfmt = GetXfmt();
|
||||
} // end of VALUE constructor
|
||||
|
||||
/***********************************************************************/
|
||||
@ -446,11 +457,11 @@ const char *VALUE::GetXfmt(void)
|
||||
const char *fmt;
|
||||
|
||||
switch (Type) {
|
||||
case TYPE_STRING: fmt = "%*s"; break;
|
||||
case TYPE_SHORT: fmt = "%*hd"; break;
|
||||
case TYPE_BIGINT: fmt = "%*lld"; break;
|
||||
case TYPE_FLOAT: fmt = "%*.*lf"; break;
|
||||
default: fmt = "%*d"; break;
|
||||
case TYPE_STRING: fmt = "%*s"; break;
|
||||
case TYPE_SHORT: fmt = (Unsigned) ? "%*hu" : "%*hd"; break;
|
||||
case TYPE_BIGINT: fmt = (Unsigned) ? "%*llu" : "%*lld"; break;
|
||||
case TYPE_FLOAT: fmt = "%*.*lf"; break;
|
||||
default: fmt = (Unsigned) ? "%*u" : "%*d"; break;
|
||||
} // endswitch Type
|
||||
|
||||
return fmt;
|
||||
@ -462,22 +473,11 @@ const char *VALUE::GetXfmt(void)
|
||||
/* TYPVAL public constructor from a constant typed value. */
|
||||
/***********************************************************************/
|
||||
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;
|
||||
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;
|
||||
} // end of TYPVAL constructor
|
||||
|
||||
@ -522,14 +522,26 @@ template <>
|
||||
short TYPVAL<short>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetShortValue();}
|
||||
|
||||
template <>
|
||||
ushort TYPVAL<ushort>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetUShortValue();}
|
||||
|
||||
template <>
|
||||
int TYPVAL<int>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetIntValue();}
|
||||
|
||||
template <>
|
||||
uint TYPVAL<uint>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetUIntValue();}
|
||||
|
||||
template <>
|
||||
longlong TYPVAL<longlong>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetBigintValue();}
|
||||
|
||||
template <>
|
||||
ulonglong TYPVAL<ulonglong>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetUBigintValue();}
|
||||
|
||||
template <>
|
||||
double TYPVAL<double>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetFloatValue();}
|
||||
@ -538,6 +550,10 @@ template <>
|
||||
char TYPVAL<char>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetTinyValue();}
|
||||
|
||||
template <>
|
||||
uchar TYPVAL<uchar>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetUTinyValue();}
|
||||
|
||||
/***********************************************************************/
|
||||
/* 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)
|
||||
{
|
||||
char *p2, buf[32];
|
||||
bool minus;
|
||||
bool minus = false;
|
||||
|
||||
for (p2 = p + n; p < p2 && *p == ' '; p++) ;
|
||||
|
||||
@ -570,7 +586,7 @@ void TYPVAL<TYPE>::SetValue_char(char *p, int n)
|
||||
} // endswitch *p
|
||||
|
||||
if (minus && Tval)
|
||||
Tval = - Tval;
|
||||
Tval = (-(signed)Tval) ? -(signed)Tval : Tval;
|
||||
|
||||
if (trace > 1)
|
||||
htrc(strcat(strcat(strcpy(buf, " setting %s to: "), Fmt), "\n"),
|
||||
@ -622,13 +638,21 @@ void TYPVAL<TYPE>::SetValue_psz(PSZ s)
|
||||
template <>
|
||||
int TYPVAL<int>::GetTypedValue(PSZ s) {return atol(s);}
|
||||
template <>
|
||||
uint TYPVAL<uint>::GetTypedValue(PSZ s) {return (unsigned)atol(s);}
|
||||
template <>
|
||||
short TYPVAL<short>::GetTypedValue(PSZ s) {return (short)atoi(s);}
|
||||
template <>
|
||||
ushort TYPVAL<ushort>::GetTypedValue(PSZ s) {return (ushort)atoi(s);}
|
||||
template <>
|
||||
longlong TYPVAL<longlong>::GetTypedValue(PSZ s) {return atoll(s);}
|
||||
template <>
|
||||
ulonglong TYPVAL<ulonglong>::GetTypedValue(PSZ s) {return (unsigned)atoll(s);}
|
||||
template <>
|
||||
double TYPVAL<double>::GetTypedValue(PSZ s) {return atof(s);}
|
||||
template <>
|
||||
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. */
|
||||
@ -644,14 +668,26 @@ template <>
|
||||
int TYPVAL<int>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetIntValue(n);}
|
||||
|
||||
template <>
|
||||
uint TYPVAL<uint>::GetTypedValue(PVBLK blk, int n)
|
||||
{return (unsigned)blk->GetIntValue(n);}
|
||||
|
||||
template <>
|
||||
short TYPVAL<short>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetShortValue(n);}
|
||||
|
||||
template <>
|
||||
ushort TYPVAL<ushort>::GetTypedValue(PVBLK blk, int n)
|
||||
{return (unsigned)blk->GetShortValue(n);}
|
||||
|
||||
template <>
|
||||
longlong TYPVAL<longlong>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetBigintValue(n);}
|
||||
|
||||
template <>
|
||||
ulonglong TYPVAL<ulonglong>::GetTypedValue(PVBLK blk, int n)
|
||||
{return (unsigned)blk->GetBigintValue(n);}
|
||||
|
||||
template <>
|
||||
double TYPVAL<double>::GetTypedValue(PVBLK blk, int n)
|
||||
{return blk->GetFloatValue(n);}
|
||||
@ -660,6 +696,10 @@ template <>
|
||||
char TYPVAL<char>::GetTypedValue(PVBLK blk, int 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. */
|
||||
/***********************************************************************/
|
||||
@ -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.
|
||||
// Therefore this test is useless anyway.
|
||||
//#if defined(_DEBUG)
|
||||
// if (sizeof(int) > buflen)
|
||||
// if (sizeof(TYPE) > buflen)
|
||||
// return true;
|
||||
//#endif
|
||||
|
||||
@ -730,6 +770,7 @@ char *TYPVAL<double>::GetCharString(char *p)
|
||||
return p;
|
||||
} // end of GetCharString
|
||||
|
||||
#if 0
|
||||
/***********************************************************************/
|
||||
/* 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);
|
||||
return p;
|
||||
} // end of GetIntString
|
||||
#endif // 0
|
||||
|
||||
/***********************************************************************/
|
||||
/* 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)
|
||||
: VALUE(TYPE_STRING)
|
||||
{
|
||||
assert(Type == TYPE_STRING);
|
||||
Len = (g) ? n : strlen(s);
|
||||
|
||||
if (!s) {
|
||||
@ -981,6 +1022,24 @@ void TYPVAL<PSZ>::SetValue(int n)
|
||||
Null = false;
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
@ -990,6 +1049,15 @@ void TYPVAL<PSZ>::SetValue(short i)
|
||||
Null = false;
|
||||
} // 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.*/
|
||||
/***********************************************************************/
|
||||
@ -1008,6 +1076,24 @@ void TYPVAL<PSZ>::SetValue(longlong n)
|
||||
Null = false;
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
@ -1042,6 +1128,15 @@ void TYPVAL<PSZ>::SetValue(char c)
|
||||
Null = false;
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
@ -1086,6 +1181,7 @@ char *TYPVAL<PSZ>::GetCharString(char *p)
|
||||
return Strp;
|
||||
} // end of GetCharString
|
||||
|
||||
#if 0
|
||||
/***********************************************************************/
|
||||
/* 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));
|
||||
return p;
|
||||
} // end of GetIntString
|
||||
#endif // 0
|
||||
|
||||
/***********************************************************************/
|
||||
/* STRING compare value with another Value. */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**************** 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 */
|
||||
/* */
|
||||
@ -45,16 +45,16 @@ DllExport PSZ GetTypeName(int);
|
||||
DllExport int GetTypeSize(int, int);
|
||||
#ifdef ODBC_SUPPORT
|
||||
/* This function is exported for use in EOM table type DLLs */
|
||||
DllExport int TranslateSQLType(int stp, int prec, int& len);
|
||||
DllExport int TranslateSQLType(int stp, int prec, int& len, char& v);
|
||||
#endif
|
||||
DllExport char *GetFormatType(int);
|
||||
DllExport int GetFormatType(char);
|
||||
DllExport bool IsTypeChar(int type);
|
||||
DllExport bool IsTypeNum(int type);
|
||||
DllExport int ConvertType(int, int, CONV, bool match = false);
|
||||
DllExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID);
|
||||
DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 2,
|
||||
PSZ dom = NULL, PCATLG cat = NULL);
|
||||
//lExport int ConvertType(int, int, CONV, bool match = false);
|
||||
DllExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID, int = 0);
|
||||
DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 0,
|
||||
PSZ fmt = NULL);
|
||||
|
||||
/***********************************************************************/
|
||||
/* 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 IsZero(void) = 0;
|
||||
virtual bool IsCi(void) {return false;}
|
||||
virtual bool IsUnsigned(void) {return Unsigned;}
|
||||
virtual void Reset(void) = 0;
|
||||
virtual int GetSize(void) = 0;
|
||||
virtual int GetValLen(void) = 0;
|
||||
@ -75,9 +76,13 @@ class DllExport VALUE : public BLOCK {
|
||||
virtual int GetLength(void) {return 1;}
|
||||
virtual PSZ GetCharValue(void) {assert(false); return NULL;}
|
||||
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 ushort GetUShortValue(void) {assert(false); return 0;}
|
||||
virtual int GetIntValue(void) = 0;
|
||||
virtual uint GetUIntValue(void) = 0;
|
||||
virtual longlong GetBigintValue(void) = 0;
|
||||
virtual ulonglong GetUBigintValue(void) = 0;
|
||||
virtual double GetFloatValue(void) = 0;
|
||||
virtual void *GetTo_Val(void) = 0;
|
||||
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_psz(PSZ s) = 0;
|
||||
virtual void SetValue(char c) {assert(false);}
|
||||
virtual void SetValue(uchar c) {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(uint 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_pvblk(PVBLK blk, int n) = 0;
|
||||
virtual void SetBinValue(void *p) = 0;
|
||||
virtual bool GetBinValue(void *buf, int buflen, bool go) = 0;
|
||||
virtual char *ShowValue(char *buf, int len = 0) = 0;
|
||||
virtual char *GetCharString(char *p) = 0;
|
||||
virtual char *GetShortString(char *p, int n) {return "#####";}
|
||||
virtual char *GetIntString(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 *GetTinyString(char *p, int n) {return "?";}
|
||||
//virtual char *GetShortString(char *p, int n) {return "#####";}
|
||||
//virtual char *GetIntString(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 *GetTinyString(char *p, int n) {return "?";}
|
||||
virtual bool IsEqual(PVAL vp, bool chktype) = 0;
|
||||
virtual bool FormatValue(PVAL vp, char *fmt) = 0;
|
||||
|
||||
@ -116,7 +125,7 @@ class DllExport VALUE : public BLOCK {
|
||||
const char *GetXfmt(void);
|
||||
|
||||
// Constructor used by derived classes
|
||||
VALUE(int type);
|
||||
VALUE(int type, bool un = false);
|
||||
|
||||
// Members
|
||||
PGLOBAL Global; // To reduce arglist
|
||||
@ -124,6 +133,7 @@ class DllExport VALUE : public BLOCK {
|
||||
const char *Xfmt;
|
||||
bool Nullable; // True if value can be null
|
||||
bool Null; // True if value is null
|
||||
bool Unsigned; // True if unsigned
|
||||
int Type; // The value type
|
||||
int Clen; // Internal value length
|
||||
int Prec;
|
||||
@ -135,9 +145,8 @@ class DllExport VALUE : public BLOCK {
|
||||
template <class TYPE>
|
||||
class DllExport TYPVAL : public VALUE {
|
||||
public:
|
||||
// Constructors
|
||||
TYPVAL(TYPE n, int type);
|
||||
TYPVAL(TYPE n, int prec, int type);
|
||||
// Constructor
|
||||
TYPVAL(TYPE n, int type, int prec = 0, bool un = false);
|
||||
|
||||
// Implementation
|
||||
virtual bool IsTypeNum(void) {return true;}
|
||||
@ -148,9 +157,13 @@ class DllExport TYPVAL : public VALUE {
|
||||
virtual int GetSize(void) {return sizeof(TYPE);}
|
||||
virtual PSZ GetCharValue(void) {return VALUE::GetCharValue();}
|
||||
virtual char GetTinyValue(void) {return (char)Tval;}
|
||||
virtual uchar GetUTinyValue(void) {return (uchar)Tval;}
|
||||
virtual short GetShortValue(void) {return (short)Tval;}
|
||||
virtual ushort GetUShortValue(void) {return (ushort)Tval;}
|
||||
virtual int GetIntValue(void) {return (int)Tval;}
|
||||
virtual uint GetUIntValue(void) {return (uint)Tval;}
|
||||
virtual longlong GetBigintValue(void) {return (longlong)Tval;}
|
||||
virtual ulonglong GetUBigintValue(void) {return (ulonglong)Tval;}
|
||||
virtual double GetFloatValue(void) {return (double)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_psz(PSZ s);
|
||||
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(ushort i) {Tval = (TYPE)i; 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(ulonglong n) {Tval = (TYPE)n; Null = false;}
|
||||
virtual void SetValue(double f) {Tval = (TYPE)f; Null = false;}
|
||||
virtual void SetValue_pvblk(PVBLK blk, int n);
|
||||
virtual void SetBinValue(void *p);
|
||||
virtual bool GetBinValue(void *buf, int buflen, bool go);
|
||||
virtual char *ShowValue(char *buf, int);
|
||||
virtual char *GetCharString(char *p);
|
||||
virtual char *GetShortString(char *p, int n);
|
||||
virtual char *GetIntString(char *p, int n);
|
||||
virtual char *GetBigintString(char *p, int n);
|
||||
virtual char *GetFloatString(char *p, int n, int prec = -1);
|
||||
virtual char *GetTinyString(char *p, int n);
|
||||
//virtual char *GetShortString(char *p, int n);
|
||||
//virtual char *GetIntString(char *p, int n);
|
||||
//virtual char *GetBigintString(char *p, int n);
|
||||
//virtual char *GetFloatString(char *p, int n, int prec = -1);
|
||||
//virtual char *GetTinyString(char *p, int n);
|
||||
virtual bool IsEqual(PVAL vp, bool chktype);
|
||||
virtual bool SetConstFormat(PGLOBAL, FORMAT&);
|
||||
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 PSZ GetCharValue(void) {return 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 ushort GetUShortValue(void) {return (ushort)atoi(Strp);}
|
||||
virtual int GetIntValue(void) {return atol(Strp);}
|
||||
virtual uint GetUIntValue(void) {return (uint)atol(Strp);}
|
||||
virtual longlong GetBigintValue(void) {return atoll(Strp);}
|
||||
virtual ulonglong GetUBigintValue(void) {return (ulonglong)atoll(Strp);}
|
||||
virtual double GetFloatValue(void) {return atof(Strp);}
|
||||
virtual void *GetTo_Val(void) {return Strp;}
|
||||
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_pvblk(PVBLK blk, int n);
|
||||
virtual void SetValue(char c);
|
||||
virtual void SetValue(uchar c);
|
||||
virtual void SetValue(short i);
|
||||
virtual void SetValue(ushort i);
|
||||
virtual void SetValue(int n);
|
||||
virtual void SetValue(uint n);
|
||||
virtual void SetValue(longlong n);
|
||||
virtual void SetValue(ulonglong n);
|
||||
virtual void SetValue(double f);
|
||||
virtual void SetBinValue(void *p);
|
||||
virtual bool GetBinValue(void *buf, int buflen, bool go);
|
||||
virtual char *ShowValue(char *buf, int);
|
||||
virtual char *GetCharString(char *p);
|
||||
virtual char *GetShortString(char *p, int n);
|
||||
virtual char *GetIntString(char *p, int n);
|
||||
virtual char *GetBigintString(char *p, int n);
|
||||
virtual char *GetFloatString(char *p, int n, int prec = -1);
|
||||
virtual char *GetTinyString(char *p, int n);
|
||||
//virtual char *GetShortString(char *p, int n);
|
||||
//virtual char *GetIntString(char *p, int n);
|
||||
//virtual char *GetBigintString(char *p, int n);
|
||||
//virtual char *GetFloatString(char *p, int n, int prec = -1);
|
||||
//virtual char *GetTinyString(char *p, int n);
|
||||
virtual bool IsEqual(PVAL vp, bool chktype);
|
||||
virtual bool FormatValue(PVAL vp, char *fmt);
|
||||
virtual bool SetConstFormat(PGLOBAL, FORMAT&);
|
||||
|
||||
// Specialized functions
|
||||
template <class T>
|
||||
T GetValue_as(T type) {return Strp;}
|
||||
int GetValue_as(int type) {return atol(Strp);}
|
||||
short GetValue_as(short type) {return (short)atoi(Strp);}
|
||||
longlong GetValue_as(longlong type) {return atoll(Strp);}
|
||||
double GetValue_as(double type) {return atof(Strp);}
|
||||
//template <class T>
|
||||
//T GetValue_as(T type) {return Strp;}
|
||||
//int GetValue_as(int type) {return atol(Strp);}
|
||||
//short GetValue_as(short type) {return (short)atoi(Strp);}
|
||||
//longlong GetValue_as(longlong type) {return atoll(Strp);}
|
||||
//double GetValue_as(double type) {return atof(Strp);}
|
||||
|
||||
// Members
|
||||
PSZ Strp;
|
||||
|
@ -66,7 +66,7 @@ extern MBLOCK Nmblk; /* Used to initialize MBLOCK's */
|
||||
/* to have rows filled by blanks to be compatible with QRY blocks. */
|
||||
/***********************************************************************/
|
||||
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. */
|
||||
@ -2919,7 +2919,7 @@ void KXYCOL::SetValue(PCOL colp, int i)
|
||||
assert (Kblp != NULL);
|
||||
#endif
|
||||
|
||||
Kblp->SetValue(colp->GetValue(), (int)i);
|
||||
Kblp->SetValue(colp->GetValue(), i);
|
||||
} // end of SetValue
|
||||
|
||||
/***********************************************************************/
|
||||
@ -2970,7 +2970,7 @@ void KXYCOL::FillValue(PVAL valp)
|
||||
int KXYCOL::Compare(int i1, int i2)
|
||||
{
|
||||
// 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
|
||||
htrc("Compare done result=%d\n", k);
|
||||
@ -2991,7 +2991,7 @@ int KXYCOL::CompVal(int i)
|
||||
htrc("Compare done result=%d\n", k);
|
||||
return k;
|
||||
#endif
|
||||
return (int)Kblp->CompVal(Valp, (int)i);
|
||||
return Kblp->CompVal(Valp, i);
|
||||
} // end of CompVal
|
||||
|
||||
/***********************************************************************/
|
||||
@ -3000,7 +3000,7 @@ int KXYCOL::CompVal(int i)
|
||||
int KXYCOL::CompBval(int i)
|
||||
{
|
||||
// Do the actual comparison between key values.
|
||||
return (int)Blkp->CompVal(Valp, (int)i);
|
||||
return Blkp->CompVal(Valp, i);
|
||||
} // end of CompBval
|
||||
|
||||
/***********************************************************************/
|
||||
|
@ -18,8 +18,28 @@
|
||||
#include "colblk.h"
|
||||
#include "m_ctype.h"
|
||||
|
||||
//pedef class INDEXDEF *PIXDEF;
|
||||
typedef char *PFIL; // Specific to CONNECT
|
||||
typedef class CMD *PCMD;
|
||||
|
||||
// Commands executed by XDBC and MYX tables
|
||||
class CMD : public BLOCK {
|
||||
public:
|
||||
// Constructor
|
||||
CMD(PGLOBAL g, char *cmd) {
|
||||
Cmd = (char*)PlugSubAlloc(g, NULL, strlen(cmd) + 1);
|
||||
strcpy(Cmd, cmd); Next = NULL; }
|
||||
|
||||
// Members
|
||||
PCMD Next;
|
||||
char *Cmd;
|
||||
}; // end of class CMD
|
||||
|
||||
// Filter passed all tables
|
||||
typedef struct _filter {
|
||||
char *Body;
|
||||
OPVAL Op;
|
||||
PCMD Cmds;
|
||||
} FILTER, *PFIL;
|
||||
|
||||
typedef class TDBCAT *PTDBCAT;
|
||||
typedef class CATCOL *PCATCOL;
|
||||
|
||||
@ -39,24 +59,16 @@ class DllExport TBX: public BLOCK { // Base class for OPJOIN and TDB classes.
|
||||
inline PFIL GetFilter(void) {return To_Filter;}
|
||||
inline void SetOrig(PTBX txp) {To_Orig = txp;}
|
||||
inline void SetFilter(PFIL fp) {To_Filter = fp;}
|
||||
//inline JTYPE GetJtype(void) {return Jtype;}
|
||||
//inline void SetJtype(JTYPE jt) {Jtype = jt;}
|
||||
//inline PFIL GetNoleft(void) {return To_Noleft;}
|
||||
//inline void SetNoleft(PFIL fp) {To_Noleft = fp;}
|
||||
|
||||
// Methods
|
||||
virtual bool IsSame(PTBX tp) {return tp == this;}
|
||||
//virtual bool Include(PTBX tbxp) = 0;
|
||||
//virtual bool CheckFilter(void) = 0;
|
||||
virtual int GetTdb_No(void) = 0; // Convenience during conversion
|
||||
virtual PTDB GetNext(void) = 0;
|
||||
//virtual int GetMaxSame(PGLOBAL) = 0;
|
||||
virtual int Cardinality(PGLOBAL) = 0;
|
||||
virtual int GetMaxSize(PGLOBAL) = 0;
|
||||
virtual int GetProgMax(PGLOBAL) = 0;
|
||||
virtual int GetProgCur(void) = 0;
|
||||
virtual int GetBadLines(void) {return 0;}
|
||||
//virtual bool IsJoin(void) = 0;
|
||||
virtual PTBX Copy(PTABS t) = 0;
|
||||
|
||||
protected:
|
||||
@ -66,8 +78,6 @@ class DllExport TBX: public BLOCK { // Base class for OPJOIN and TDB classes.
|
||||
// Members
|
||||
PTBX To_Orig; // Pointer to original if it is a copy
|
||||
PFIL To_Filter;
|
||||
//PFIL To_Noleft; // To filter not involved in LEFT JOIN
|
||||
//JTYPE Jtype;
|
||||
TUSE Use;
|
||||
}; // end of class TBX
|
||||
|
||||
|
Reference in New Issue
Block a user