Commit 18fc51f5 authored by Alexander Barkov's avatar Alexander Barkov

Merge with 10.0-connect

parents 51e28066 0993d4b4
...@@ -350,8 +350,7 @@ TIDBLK::TIDBLK(PCOLUMN cp) : SPCBLK(cp) ...@@ -350,8 +350,7 @@ TIDBLK::TIDBLK(PCOLUMN cp) : SPCBLK(cp)
*Format.Type = 'C'; *Format.Type = 'C';
Format.Length = Long; Format.Length = Long;
Format.Prec = 1; // Case insensitive Format.Prec = 1; // Case insensitive
Constant = (To_Tdb->GetAmType() != TYPE_AM_PLG && Constant = (To_Tdb->GetAmType() != TYPE_AM_TBL);
To_Tdb->GetAmType() != TYPE_AM_PLM);
Tname = NULL; Tname = NULL;
} // end of TIDBLK constructor } // end of TIDBLK constructor
...@@ -367,3 +366,30 @@ void TIDBLK::ReadColumn(PGLOBAL g) ...@@ -367,3 +366,30 @@ void TIDBLK::ReadColumn(PGLOBAL g)
} // end of ReadColumn } // end of ReadColumn
/***********************************************************************/
/* SIDBLK constructor for the SERVID special column. */
/***********************************************************************/
SIDBLK::SIDBLK(PCOLUMN cp) : SPCBLK(cp)
{
//Is_Key = 2; for when the MUL table indexed reading will be implemented.
Long = 64;
Buf_Type = TYPE_STRING;
*Format.Type = 'C';
Format.Length = Long;
Format.Prec = 1; // Case insensitive
Constant = (To_Tdb->GetAmType() != TYPE_AM_TBL);
Sname = NULL;
} // end of TIDBLK constructor
/***********************************************************************/
/* ReadColumn: what this routine does is to return the server ID. */
/***********************************************************************/
void SIDBLK::ReadColumn(PGLOBAL g)
{
//if (Sname == NULL) {
Sname = (char*)To_Tdb->GetServer();
Value->SetValue_psz(Sname);
// } // endif Sname
} // end of ReadColumn
...@@ -179,4 +179,29 @@ class TIDBLK : public SPCBLK { ...@@ -179,4 +179,29 @@ class TIDBLK : public SPCBLK {
PSZ Tname; // The current table name PSZ Tname; // The current table name
}; // end of class TIDBLK }; // end of class TIDBLK
/***********************************************************************/
/* Class SIDBLK: SERVID special column descriptor. */
/***********************************************************************/
class SIDBLK : public SPCBLK {
public:
// Constructor
SIDBLK(PCOLUMN cp);
// Implementation
virtual int GetAmType(void) {return TYPE_AM_SRVID;}
// Methods
virtual void Reset(void) {} // This is a pseudo constant column
virtual int CheckSpcCol(PTDB tdbp, int n)
{return (n == 3 && tdbp == To_Tdb) ? 1 : 2;}
virtual void ReadColumn(PGLOBAL g);
protected:
// Default constructor not to be used
SIDBLK(void) {}
// Members
PSZ Sname; // The current server name
}; // end of class SIDBLK
#endif // __COLBLK__H #endif // __COLBLK__H
...@@ -239,7 +239,7 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, ...@@ -239,7 +239,7 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
char *p; char *p;
int i, n; int i, n;
PCOL colp; PCOL colp;
PCOLUMN cp; //PCOLUMN cp;
PDBUSER dup= PlgGetUser(g); PDBUSER dup= PlgGetUser(g);
if (xtrace) if (xtrace)
...@@ -251,6 +251,8 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, ...@@ -251,6 +251,8 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
return true; return true;
} // endif tdbp } // endif tdbp
tdbp->SetMode(mode);
if (!c1) { if (!c1) {
if (mode == MODE_INSERT) if (mode == MODE_INSERT)
// Allocate all column blocks for that table // Allocate all column blocks for that table
...@@ -261,12 +263,12 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, ...@@ -261,12 +263,12 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
if (xtrace) if (xtrace)
printf("Allocating column %s\n", p); printf("Allocating column %s\n", p);
if (*p == '*') { // if (*p == '*') {
// This is a special column // // This is a special column
cp= new(g) COLUMN(p + 1); // cp= new(g) COLUMN(p + 1);
cp->SetTo_Table(tdbp->GetTable()); // cp->SetTo_Table(tdbp->GetTable());
colp= ((PTDBASE)tdbp)->InsertSpcBlk(g, cp); // colp= ((PTDBASE)tdbp)->InsertSpcBlk(g, cp);
} else // } else
colp= tdbp->ColDB(g, p, 0); colp= tdbp->ColDB(g, p, 0);
if (!colp) { if (!colp) {
...@@ -330,7 +332,7 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, ...@@ -330,7 +332,7 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
printf("Opening table %s in mode %d tdbp=%p\n", printf("Opening table %s in mode %d tdbp=%p\n",
tdbp->GetName(), mode, tdbp); tdbp->GetName(), mode, tdbp);
tdbp->SetMode(mode); //tdbp->SetMode(mode);
if (del && ((PTDBASE)tdbp)->GetFtype() != RECFM_NAF) { if (del && ((PTDBASE)tdbp)->GetFtype() != RECFM_NAF) {
// To avoid erasing the table when doing a partial delete // To avoid erasing the table when doing a partial delete
......
...@@ -47,20 +47,9 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len, ...@@ -47,20 +47,9 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
PGLOBAL CntExit(PGLOBAL g); PGLOBAL CntExit(PGLOBAL g);
/***********************************************************************/ /***********************************************************************/
/* Definition of classes XCOLCRT, XIXDEF, XKPDEF, DOXDEF, TDBDOX */ /* Definition of classes XKPDEF, DOXDEF, TDBDOX */
/* These classes purpose is chiefly to access protected items! */ /* These classes purpose is chiefly to access protected items! */
/***********************************************************************/ /***********************************************************************/
class XCOLCRT: public COLCRT {
friend class ha_connect;
friend bool CntCreateTable(PGLOBAL, char *, PCXF);
public:
XCOLCRT(PSZ name) : COLCRT(name) {Nulls= -1;} // Constructor
bool HasNulls(void) {return (Nulls != 0);}
private:
int Nulls;
}; // end of class XCOLCRT
class DOXDEF: public DOSDEF { class DOXDEF: public DOSDEF {
//friend class TDBDOX; //friend class TDBDOX;
//friend int MakeIndex(PGLOBAL, PTDB, PIXDEF); //friend int MakeIndex(PGLOBAL, PTDB, PIXDEF);
...@@ -87,11 +76,7 @@ class XKPDEF: public KPARTDEF { ...@@ -87,11 +76,7 @@ class XKPDEF: public KPARTDEF {
//friend int CntMakeIndex(PGLOBAL, const char *, PIXDEF); //friend int CntMakeIndex(PGLOBAL, const char *, PIXDEF);
friend int CntIndexInit(PGLOBAL, PTDB, int); friend int CntIndexInit(PGLOBAL, PTDB, int);
public: public:
XKPDEF(const char *name, int n) : KPARTDEF((PSZ)name, n) {HasNulls= false;} XKPDEF(const char *name, int n) : KPARTDEF((PSZ)name, n) {}
void SetNulls(bool b) {HasNulls= b;}
protected:
bool HasNulls; /* Can have null values */
}; // end of class XKPDEF }; // end of class XKPDEF
//RCODE CheckRecord(PGLOBAL g, PTDB tdbp, char *oldbuf, char *newbuf); //RCODE CheckRecord(PGLOBAL g, PTDB tdbp, char *oldbuf, char *newbuf);
...@@ -107,6 +107,9 @@ ...@@ -107,6 +107,9 @@
#include "field.h" #include "field.h"
#include "sql_parse.h" #include "sql_parse.h"
#include "sql_base.h" #include "sql_base.h"
#if defined(NEW_WAY)
#include "sql_table.h"
#endif // NEW_WAY
#undef OFFSET #undef OFFSET
#define NOPARSE #define NOPARSE
...@@ -162,7 +165,7 @@ extern "C" char nmfile[]; ...@@ -162,7 +165,7 @@ extern "C" char nmfile[];
extern "C" char pdebug[]; extern "C" char pdebug[];
extern "C" { extern "C" {
char version[]= "Version 1.01.0006 Mai 21, 2013"; char version[]= "Version 1.01.0007 July 26, 2013";
#if defined(XMSG) #if defined(XMSG)
char msglang[]; // Default message language char msglang[]; // Default message language
...@@ -468,6 +471,7 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg) ...@@ -468,6 +471,7 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
creat_query_id= (table && table->in_use) ? table->in_use->query_id : 0; creat_query_id= (table && table->in_use) ? table->in_use->query_id : 0;
stop= false; stop= false;
indexing= -1; indexing= -1;
locked= 0;
data_file_name= NULL; data_file_name= NULL;
index_file_name= NULL; index_file_name= NULL;
enable_activate_all_index= 0; enable_activate_all_index= 0;
...@@ -844,11 +848,13 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) ...@@ -844,11 +848,13 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
pcf->Flags= 0; pcf->Flags= 0;
// Now get column information // Now get column information
pcf->Name= (char*)fp->field_name;
if (fop && fop->special) { if (fop && fop->special) {
pcf->Name= "*"; pcf->Fieldfmt= (char*)fop->special;
pcf->Flags= U_SPECIAL;
return fldp; return fldp;
} else } // endif special
pcf->Name= (char*)fp->field_name;
pcf->Prec= 0; pcf->Prec= 0;
pcf->Opt= (fop) ? (int)fop->opt : 0; pcf->Opt= (fop) ? (int)fop->opt : 0;
...@@ -874,9 +880,13 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) ...@@ -874,9 +880,13 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_VAR_STRING:
pcf->Flags |= U_VAR; pcf->Flags |= U_VAR;
/* no break */ /* no break */
case MYSQL_TYPE_STRING: default:
pcf->Type= TYPE_STRING; pcf->Type= MYSQLtoPLG(fp->type());
break;
} // endswitch SQL type
switch (pcf->Type) {
case TYPE_STRING:
// Do something for case // Do something for case
cp= fp->charset()->name; cp= fp->charset()->name;
...@@ -887,26 +897,10 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) ...@@ -887,26 +897,10 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
} // endif ci } // endif ci
break; break;
case MYSQL_TYPE_LONG: case TYPE_FLOAT:
pcf->Type= TYPE_INT;
break;
case MYSQL_TYPE_SHORT:
pcf->Type= TYPE_SHORT;
break;
case MYSQL_TYPE_TINY:
pcf->Type= TYPE_TINY;
break;
case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_FLOAT:
pcf->Type= TYPE_FLOAT;
pcf->Prec= max(min(fp->decimals(), ((unsigned)pcf->Length - 2)), 0); pcf->Prec= max(min(fp->decimals(), ((unsigned)pcf->Length - 2)), 0);
break; break;
case MYSQL_TYPE_DATE: case TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
pcf->Type= TYPE_DATE;
// Field_length is only used for DATE columns // Field_length is only used for DATE columns
if (fop->fldlen) if (fop->fldlen)
pcf->Length= (int)fop->fldlen; pcf->Length= (int)fop->fldlen;
...@@ -931,12 +925,8 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) ...@@ -931,12 +925,8 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
pcf->Length= (len) ? len : 11; pcf->Length= (len) ? len : 11;
} // endelse } // endelse
break;
case MYSQL_TYPE_LONGLONG:
pcf->Type= TYPE_BIGINT;
break; break;
default: default:
pcf->Type=TYPE_ERROR;
break; break;
} // endswitch type } // endswitch type
...@@ -954,7 +944,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) ...@@ -954,7 +944,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
if (fp->comment.str && fp->comment.length) { if (fp->comment.str && fp->comment.length) {
pcf->Remark= (char*)PlugSubAlloc(g, NULL, fp->comment.length + 1); pcf->Remark= (char*)PlugSubAlloc(g, NULL, fp->comment.length + 1);
memcpy(pcf->Remark, fp->comment.str, fp->comment.length); memcpy(pcf->Remark, fp->comment.str, fp->comment.length);
pcf->Remark[fp->comment.length] = 0; pcf->Remark[fp->comment.length]= 0;
} else } else
pcf->Remark= NULL; pcf->Remark= NULL;
...@@ -1042,6 +1032,7 @@ const char *ha_connect::GetTableName(void) ...@@ -1042,6 +1032,7 @@ const char *ha_connect::GetTableName(void)
return (tshp) ? tshp->table_name.str : table->s->table_name.str; return (tshp) ? tshp->table_name.str : table->s->table_name.str;
} // end of GetTableName } // end of GetTableName
#if 0
/****************************************************************************/ /****************************************************************************/
/* Returns the column real or special name length of a field. */ /* Returns the column real or special name length of a field. */
/****************************************************************************/ /****************************************************************************/
...@@ -1054,7 +1045,7 @@ int ha_connect::GetColNameLen(Field *fp) ...@@ -1054,7 +1045,7 @@ int ha_connect::GetColNameLen(Field *fp)
if (fop && fop->special) if (fop && fop->special)
n= strlen(fop->special) + 1; n= strlen(fop->special) + 1;
else else
n= strlen(fp->field_name) + 1; n= strlen(fp->field_name);
return n; return n;
} // end of GetColNameLen } // end of GetColNameLen
...@@ -1084,6 +1075,7 @@ void ha_connect::AddColName(char *cp, Field *fp) ...@@ -1084,6 +1075,7 @@ void ha_connect::AddColName(char *cp, Field *fp)
strcpy(cp, (char*)fp->field_name); strcpy(cp, (char*)fp->field_name);
} // end of AddColName } // end of AddColName
#endif // 0
/****************************************************************************/ /****************************************************************************/
/* Get the table description block of a CONNECT table. */ /* Get the table description block of a CONNECT table. */
...@@ -1145,20 +1137,21 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del) ...@@ -1145,20 +1137,21 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del)
char *p; char *p;
unsigned int k1, k2, n1, n2; unsigned int k1, k2, n1, n2;
Field* *field; Field* *field;
Field* fp;
MY_BITMAP *map= table->read_set; MY_BITMAP *map= table->read_set;
MY_BITMAP *ump= (xmod == MODE_UPDATE) ? table->write_set : NULL; MY_BITMAP *ump= (xmod == MODE_UPDATE) ? table->write_set : NULL;
k1= k2= 0; k1= k2= 0;
n1= n2= 1; // 1 is space for final null character n1= n2= 1; // 1 is space for final null character
for (field= table->field; *field; field++) { for (field= table->field; fp= *field; field++) {
if (bitmap_is_set(map, (*field)->field_index)) { if (bitmap_is_set(map, fp->field_index)) {
n1+= (GetColNameLen(*field) + 1); n1+= (strlen(fp->field_name) + 1);
k1++; k1++;
} // endif } // endif
if (ump && bitmap_is_set(ump, (*field)->field_index)) { if (ump && bitmap_is_set(ump, fp->field_index)) {
n2+= GetColNameLen(*field); n2+= (strlen(fp->field_name) + 1);
k2++; k2++;
} // endif } // endif
...@@ -1167,9 +1160,9 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del) ...@@ -1167,9 +1160,9 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del)
if (k1) { if (k1) {
p= c1= (char*)PlugSubAlloc(g, NULL, n1); p= c1= (char*)PlugSubAlloc(g, NULL, n1);
for (field= table->field; *field; field++) for (field= table->field; fp= *field; field++)
if (bitmap_is_set(map, (*field)->field_index)) { if (bitmap_is_set(map, fp->field_index)) {
AddColName(p, *field); strcpy(p, (char*)fp->field_name);
p+= (strlen(p) + 1); p+= (strlen(p) + 1);
} // endif used field } // endif used field
...@@ -1179,9 +1172,9 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del) ...@@ -1179,9 +1172,9 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del)
if (k2) { if (k2) {
p= c2= (char*)PlugSubAlloc(g, NULL, n2); p= c2= (char*)PlugSubAlloc(g, NULL, n2);
for (field= table->field; *field; field++) for (field= table->field; fp= *field; field++)
if (bitmap_is_set(ump, (*field)->field_index)) { if (bitmap_is_set(ump, fp->field_index)) {
AddColName(p, *field); strcpy(p, (char*)fp->field_name);
p+= (strlen(p) + 1); p+= (strlen(p) + 1);
} // endif used field } // endif used field
...@@ -1280,7 +1273,7 @@ int ha_connect::MakeRecord(char *buf) ...@@ -1280,7 +1273,7 @@ int ha_connect::MakeRecord(char *buf)
if (bitmap_is_set(map, fp->field_index)) { if (bitmap_is_set(map, fp->field_index)) {
// This is a used field, fill the buffer with value // This is a used field, fill the buffer with value
for (colp= tdbp->GetColumns(); colp; colp= colp->GetNext()) for (colp= tdbp->GetColumns(); colp; colp= colp->GetNext())
if (!stricmp(colp->GetName(), GetColName(fp))) if (!stricmp(colp->GetName(), (char*)fp->field_name))
break; break;
if (!colp) { if (!colp) {
...@@ -1847,7 +1840,7 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked) ...@@ -1847,7 +1840,7 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked)
DBUG_ENTER("ha_connect::open"); DBUG_ENTER("ha_connect::open");
if (xtrace) if (xtrace)
printf("open: name=%s mode=%d test=%ud\n", name, mode, test_if_locked); printf("open: name=%s mode=%d test=%u\n", name, mode, test_if_locked);
if (!(share= get_share())) if (!(share= get_share()))
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -1891,7 +1884,7 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -1891,7 +1884,7 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT* check_opt)
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
rc= 0; rc= 0;
} else } else
rc = HA_ERR_INTERNAL_ERROR; rc= HA_ERR_INTERNAL_ERROR;
} // endif's } // endif's
...@@ -1964,8 +1957,11 @@ int ha_connect::write_row(uchar *buf) ...@@ -1964,8 +1957,11 @@ int ha_connect::write_row(uchar *buf)
PGLOBAL& g= xp->g; PGLOBAL& g= xp->g;
DBUG_ENTER("ha_connect::write_row"); DBUG_ENTER("ha_connect::write_row");
// Open the table if it was not opened yet (possible ???) // Open the table if it was not opened yet (locked)
if (!IsOpened()) if (!IsOpened() || xmod != tdbp->GetMode()) {
if (IsOpened())
CloseTable(g);
if (OpenTable(g)) { if (OpenTable(g)) {
if (strstr(g->Message, "read only")) if (strstr(g->Message, "read only"))
rc= HA_ERR_TABLE_READONLY; rc= HA_ERR_TABLE_READONLY;
...@@ -1975,6 +1971,8 @@ int ha_connect::write_row(uchar *buf) ...@@ -1975,6 +1971,8 @@ int ha_connect::write_row(uchar *buf)
DBUG_RETURN(rc); DBUG_RETURN(rc);
} // endif tdbp } // endif tdbp
} // endif isopened
if (tdbp->GetMode() == MODE_ANY) if (tdbp->GetMode() == MODE_ANY)
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -2093,6 +2091,13 @@ int ha_connect::index_init(uint idx, bool sorted) ...@@ -2093,6 +2091,13 @@ int ha_connect::index_init(uint idx, bool sorted)
if ((rc= rnd_init(0))) if ((rc= rnd_init(0)))
return rc; return rc;
if (locked == 2) {
// Indexes are not updated in lock write mode
active_index= MAX_KEY;
indexing= 0;
DBUG_RETURN(0);
} // endif locked
indexing= CntIndexInit(g, tdbp, (signed)idx); indexing= CntIndexInit(g, tdbp, (signed)idx);
if (indexing <= 0) { if (indexing <= 0) {
...@@ -2337,17 +2342,16 @@ int ha_connect::rnd_init(bool scan) ...@@ -2337,17 +2342,16 @@ int ha_connect::rnd_init(bool scan)
printf("%p in rnd_init: scan=%d\n", this, scan); printf("%p in rnd_init: scan=%d\n", this, scan);
if (g) { if (g) {
// Open the table if it was not opened yet (possible ???)
if (!IsOpened()) {
if (!table || xmod == MODE_INSERT) if (!table || xmod == MODE_INSERT)
DBUG_RETURN(HA_ERR_INITIALIZATION); DBUG_RETURN(HA_ERR_INITIALIZATION);
// Close the table if it was opened yet (locked?)
if (IsOpened())
CloseTable(g);
if (OpenTable(g, xmod == MODE_DELETE)) if (OpenTable(g, xmod == MODE_DELETE))
DBUG_RETURN(HA_ERR_INITIALIZATION); DBUG_RETURN(HA_ERR_INITIALIZATION);
} else
void(CntRewindTable(g, tdbp)); // Read from beginning
} // endif g } // endif g
xp->nrd= xp->fnd= xp->nfd= 0; xp->nrd= xp->fnd= xp->nfd= 0;
...@@ -2761,6 +2765,153 @@ bool ha_connect::IsSameIndex(PIXDEF xp1, PIXDEF xp2) ...@@ -2761,6 +2765,153 @@ bool ha_connect::IsSameIndex(PIXDEF xp1, PIXDEF xp2)
return b; return b;
} // end of IsSameIndex } // end of IsSameIndex
MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
MODE newmode, bool *chk, bool *cras)
{
if (xtrace) {
LEX_STRING *query_string= thd_query_string(thd);
printf("%p check_mode: cmdtype=%d\n", this, thd_sql_command(thd));
printf("Cmd=%.*s\n", (int) query_string->length, query_string->str);
} // endif xtrace
// Next code is temporarily replaced until sql_command is set
stop= false;
if (newmode == MODE_WRITE) {
switch (thd_sql_command(thd)) {
case SQLCOM_LOCK_TABLES:
locked= 2;
case SQLCOM_CREATE_TABLE:
case SQLCOM_INSERT:
case SQLCOM_LOAD:
case SQLCOM_INSERT_SELECT:
newmode= MODE_INSERT;
break;
// case SQLCOM_REPLACE:
// case SQLCOM_REPLACE_SELECT:
// newmode= MODE_UPDATE; // To be checked
// break;
case SQLCOM_DELETE:
case SQLCOM_DELETE_MULTI:
case SQLCOM_TRUNCATE:
newmode= MODE_DELETE;
break;
case SQLCOM_UPDATE:
case SQLCOM_UPDATE_MULTI:
newmode= MODE_UPDATE;
break;
case SQLCOM_SELECT:
case SQLCOM_OPTIMIZE:
newmode= MODE_READ;
break;
case SQLCOM_DROP_TABLE:
case SQLCOM_RENAME_TABLE:
case SQLCOM_ALTER_TABLE:
newmode= MODE_ANY;
break;
case SQLCOM_DROP_INDEX:
case SQLCOM_CREATE_INDEX:
newmode= MODE_ANY;
// stop= true;
break;
case SQLCOM_CREATE_VIEW:
case SQLCOM_DROP_VIEW:
newmode= MODE_ANY;
break;
default:
printf("Unsupported sql_command=%d", thd_sql_command(thd));
strcpy(g->Message, "CONNECT Unsupported command");
my_message(ER_NOT_ALLOWED_COMMAND, g->Message, MYF(0));
newmode= MODE_ERROR;
break;
} // endswitch newmode
} else if (newmode == MODE_READ) {
switch (thd_sql_command(thd)) {
case SQLCOM_CREATE_TABLE:
*chk= true;
*cras= true;
case SQLCOM_INSERT:
case SQLCOM_LOAD:
case SQLCOM_INSERT_SELECT:
// case SQLCOM_REPLACE:
// case SQLCOM_REPLACE_SELECT:
case SQLCOM_DELETE:
case SQLCOM_DELETE_MULTI:
case SQLCOM_TRUNCATE:
case SQLCOM_UPDATE:
case SQLCOM_UPDATE_MULTI:
case SQLCOM_SELECT:
case SQLCOM_OPTIMIZE:
break;
case SQLCOM_LOCK_TABLES:
locked= 1;
break;
case SQLCOM_DROP_INDEX:
case SQLCOM_CREATE_INDEX:
case SQLCOM_ALTER_TABLE:
*chk= true;
// stop= true;
case SQLCOM_DROP_TABLE:
case SQLCOM_RENAME_TABLE:
newmode= MODE_ANY;
break;
case SQLCOM_CREATE_VIEW:
case SQLCOM_DROP_VIEW:
newmode= MODE_ANY;
break;
default:
printf("Unsupported sql_command=%d", thd_sql_command(thd));
strcpy(g->Message, "CONNECT Unsupported command");
my_message(ER_NOT_ALLOWED_COMMAND, g->Message, MYF(0));
newmode= MODE_ERROR;
break;
} // endswitch newmode
} // endif's newmode
if (xtrace)
printf("New mode=%d\n", newmode);
return newmode;
} // end of check_mode
int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type)
{
int rc= 0;
bool chk=false, cras= false;
MODE newmode;
PGLOBAL g= GetPlug(thd, xp);
DBUG_ENTER("ha_connect::start_stmt");
// Action will depend on lock_type
switch (lock_type) {
case TL_WRITE_ALLOW_WRITE:
case TL_WRITE_CONCURRENT_INSERT:
case TL_WRITE_DELAYED:
case TL_WRITE_DEFAULT:
case TL_WRITE_LOW_PRIORITY:
case TL_WRITE:
case TL_WRITE_ONLY:
newmode= MODE_WRITE;
break;
case TL_READ:
case TL_READ_WITH_SHARED_LOCKS:
case TL_READ_HIGH_PRIORITY:
case TL_READ_NO_INSERT:
case TL_READ_DEFAULT:
newmode= MODE_READ;
break;
case TL_UNLOCK:
default:
newmode= MODE_ANY;
break;
} // endswitch mode
xmod= CheckMode(g, thd, newmode, &chk, &cras);
DBUG_RETURN((xmod == MODE_ERROR) ? HA_ERR_INTERNAL_ERROR : 0);
} // end of start_stmt
/** /**
@brief @brief
This create a lock on the table. If you are implementing a storage engine This create a lock on the table. If you are implementing a storage engine
...@@ -2822,7 +2973,8 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -2822,7 +2973,8 @@ int ha_connect::external_lock(THD *thd, int lock_type)
if (newmode == MODE_ANY) { if (newmode == MODE_ANY) {
// This is unlocking, do it by closing the table // This is unlocking, do it by closing the table
if (xp->CheckQueryID()) if (xp->CheckQueryID() && thd_sql_command(thd) != SQLCOM_UNLOCK_TABLES
&& thd_sql_command(thd) != SQLCOM_LOCK_TABLES)
rc= 2; // Logical error ??? rc= 2; // Logical error ???
else if (g->Xchk) { else if (g->Xchk) {
if (!tdbp || *tdbp->GetName() == '#') { if (!tdbp || *tdbp->GetName() == '#') {
...@@ -2910,117 +3062,25 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -2910,117 +3062,25 @@ int ha_connect::external_lock(THD *thd, int lock_type)
if (CloseTable(g)) { if (CloseTable(g)) {
// This is an error while builing index // This is an error while builing index
#if defined(_DEBUG) //#if defined(_DEBUG)
// Make it a warning to avoid crash // Make it a warning to avoid crash on debug
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
rc= 0; rc= 0;
#else // !_DEBUG //#else // !_DEBUG
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); // my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
rc= HA_ERR_INTERNAL_ERROR; // rc= HA_ERR_INTERNAL_ERROR;
#endif // !DEBUG //#endif // !DEBUG
} // endif Close } // endif Close
locked= 0;
DBUG_RETURN(rc); DBUG_RETURN(rc);
} // endif MODE_ANY } // endif MODE_ANY
if (xtrace) { // Table mode depends on the query type
LEX_STRING *query_string= thd_query_string(thd); newmode= CheckMode(g, thd, newmode, &xcheck, &cras);
printf("%p external_lock: cmdtype=%d\n", this, thd_sql_command(thd));
printf("Cmd=%.*s\n", (int) query_string->length, query_string->str);
} // endif xtrace
// Next code is temporarily replaced until sql_command is set
stop= false;
if (newmode == MODE_WRITE) { if (newmode == MODE_ERROR)
switch (thd_sql_command(thd)) {
case SQLCOM_CREATE_TABLE:
case SQLCOM_INSERT:
case SQLCOM_LOAD:
case SQLCOM_INSERT_SELECT:
newmode= MODE_INSERT;
break;
// case SQLCOM_REPLACE:
// case SQLCOM_REPLACE_SELECT:
// newmode= MODE_UPDATE; // To be checked
// break;
case SQLCOM_DELETE:
case SQLCOM_DELETE_MULTI:
case SQLCOM_TRUNCATE:
newmode= MODE_DELETE;
break;
case SQLCOM_UPDATE:
case SQLCOM_UPDATE_MULTI:
newmode= MODE_UPDATE;
break;
case SQLCOM_SELECT:
case SQLCOM_OPTIMIZE:
newmode= MODE_READ;
break;
case SQLCOM_DROP_TABLE:
case SQLCOM_RENAME_TABLE:
case SQLCOM_ALTER_TABLE:
newmode= MODE_ANY;
break;
case SQLCOM_DROP_INDEX:
case SQLCOM_CREATE_INDEX:
newmode= MODE_ANY;
// stop= true;
break;
case SQLCOM_CREATE_VIEW:
case SQLCOM_DROP_VIEW:
newmode= MODE_ANY;
break;
default:
printf("Unsupported sql_command=%d", thd_sql_command(thd));
sprintf(g->Message, "Unsupported sql_command=%d", thd_sql_command(thd));
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
break;
} // endswitch newmode
} else if (newmode == MODE_READ) {
switch (thd_sql_command(thd)) {
case SQLCOM_CREATE_TABLE:
xcheck= true;
cras= true;
case SQLCOM_INSERT:
case SQLCOM_LOAD:
case SQLCOM_INSERT_SELECT:
// case SQLCOM_REPLACE:
// case SQLCOM_REPLACE_SELECT:
case SQLCOM_DELETE:
case SQLCOM_DELETE_MULTI:
case SQLCOM_TRUNCATE:
case SQLCOM_UPDATE:
case SQLCOM_UPDATE_MULTI:
case SQLCOM_SELECT:
case SQLCOM_OPTIMIZE:
break;
case SQLCOM_DROP_INDEX:
case SQLCOM_CREATE_INDEX:
case SQLCOM_ALTER_TABLE:
xcheck= true;
// stop= true;
case SQLCOM_DROP_TABLE:
case SQLCOM_RENAME_TABLE:
newmode= MODE_ANY;
break;
case SQLCOM_CREATE_VIEW:
case SQLCOM_DROP_VIEW:
newmode= MODE_ANY;
break;
default:
printf("Unsupported sql_command=%d", thd_sql_command(thd));
sprintf(g->Message, "Unsupported sql_command=%d", thd_sql_command(thd));
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
break;
} // endswitch newmode
} // endif's newmode
if (xtrace)
printf("New mode=%d\n", newmode);
// If this is the start of a new query, cleanup the previous one // If this is the start of a new query, cleanup the previous one
if (xp->CheckCleanup()) { if (xp->CheckCleanup()) {
...@@ -3205,7 +3265,7 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to) ...@@ -3205,7 +3265,7 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to)
/* We have to retrieve the information about this table options. */ /* We have to retrieve the information about this table options. */
ha_table_option_struct *pos; ha_table_option_struct *pos;
char key[MAX_DBKEY_LENGTH], db[128], tabname[128]; char key[MAX_DBKEY_LENGTH], db[128], tabname[128];
int rc = 0; int rc= 0;
uint key_length; uint key_length;
TABLE_SHARE *share; TABLE_SHARE *share;
THD *thd= current_thd; THD *thd= current_thd;
...@@ -3340,11 +3400,69 @@ static char *encode(PGLOBAL g, char *cnm) ...@@ -3340,11 +3400,69 @@ static char *encode(PGLOBAL g, char *cnm)
@return @return
Return 0 if ok Return 0 if ok
*/ */
#if defined(NEW_WAY)
static bool add_fields(PGLOBAL g,
THD *thd,
Alter_info *alter_info,
char *name,
int typ, int len, int dec,
uint type_modifier,
char *rem,
// CHARSET_INFO *cs,
// void *vcolinfo,
// engine_option_value *create_options,
int flg,
bool dbf)
{
register Create_field *new_field;
char *length, *decimals;
enum_field_types type= PLGtoMYSQL(typ, dbf);
//Virtual_column_info *vcol_info= (Virtual_column_info *)vcolinfo;
engine_option_value *crop;
LEX_STRING *comment= thd->make_lex_string(rem, strlen(rem));
LEX_STRING *field_name= thd->make_lex_string(name, strlen(name));
DBUG_ENTER("ha_connect::add_fields");
length= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(length, "%d", len);
if (dec) {
decimals= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(decimals, "%d", dec);
} else
decimals= NULL;
if (flg) {
engine_option_value *start= NULL, *end= NULL;
LEX_STRING *flag= thd->make_lex_string("flag", 4);
crop= new(thd->mem_root) engine_option_value(*flag, (ulonglong)flg,
&start, &end, thd->mem_root);
} else
crop= NULL;
if (check_string_char_length(field_name, "", NAME_CHAR_LEN,
system_charset_info, 1)) {
my_error(ER_TOO_LONG_IDENT, MYF(0), field_name->str); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
} // endif field_name
if (!(new_field= new Create_field()) ||
new_field->init(thd, field_name->str, type, length, decimals,
type_modifier, NULL, NULL, comment, NULL,
NULL, NULL, 0, NULL, crop, true))
DBUG_RETURN(1);
static bool add_field(String *sql, const char *field_name, const char *type, alter_info->create_list.push_back(new_field);
int len, int dec, uint tm, const char *rem, int flag) 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)
{ {
bool error= false; bool error= false;
const char *type= PLGtoMYSQLtype(typ, dbf);
type= PLGtoMYSQLtype(typ, true);
error|= sql->append('`'); error|= sql->append('`');
error|= sql->append(field_name); error|= sql->append(field_name);
...@@ -3355,7 +3473,7 @@ static bool add_field(String *sql, const char *field_name, const char *type, ...@@ -3355,7 +3473,7 @@ static bool add_field(String *sql, const char *field_name, const char *type,
error|= sql->append('('); error|= sql->append('(');
error|= sql->append_ulonglong(len); error|= sql->append_ulonglong(len);
if (dec || !strcmp(type, "DOUBLE")) { if (!strcmp(type, "DOUBLE")) {
error|= sql->append(','); error|= sql->append(',');
error|= sql->append_ulonglong(dec); error|= sql->append_ulonglong(dec);
} // endif dec } // endif dec
...@@ -3377,9 +3495,225 @@ static bool add_field(String *sql, const char *field_name, const char *type, ...@@ -3377,9 +3495,225 @@ static bool add_field(String *sql, const char *field_name, const char *type,
error|= sql->append_ulonglong(flag); error|= sql->append_ulonglong(flag);
} // endif flag } // endif flag
sql->append(','); error|= sql->append(',');
return error; return error;
} // end of add_field } // end of add_field
#endif // !NEW_WAY
/**
Initialise the table share with the new columns.
@return
Return 0 if ok
*/
#if defined(NEW_WAY)
//static bool sql_unusable_for_discovery(THD *thd, const char *sql);
static int init_table_share(THD *thd,
TABLE_SHARE *table_s,
HA_CREATE_INFO *create_info,
Alter_info *alter_info)
{
int rc= 0;
handler *file;
LEX_CUSTRING frm= {0,0};
DBUG_ENTER("init_table_share");
#if 0
ulonglong saved_mode= thd->variables.sql_mode;
CHARSET_INFO *old_cs= thd->variables.character_set_client;
Parser_state parser_state;
char *sql_copy;
LEX *old_lex;
Query_arena *arena, backup;
LEX tmp_lex;
/*
Ouch. Parser may *change* the string it's working on.
Currently (2013-02-26) it is used to permanently disable
conditional comments.
Anyway, let's copy the caller's string...
*/
if (!(sql_copy= thd->strmake(sql, sql_length)))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
if (parser_state.init(thd, sql_copy, sql_length))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
thd->variables.sql_mode= MODE_NO_ENGINE_SUBSTITUTION | MODE_NO_DIR_IN_CREATE;
thd->variables.character_set_client= system_charset_info;
old_lex= thd->lex;
thd->lex= &tmp_lex;
arena= thd->stmt_arena;
if (arena->is_conventional())
arena= 0;
else
thd->set_n_backup_active_arena(arena, &backup);
lex_start(thd);
if ((error= parse_sql(thd, & parser_state, NULL)))
goto ret;
if (table_s->sql_unusable_for_discovery(thd, NULL)) {
my_error(ER_SQL_DISCOVER_ERROR, MYF(0), plugin_name(db_plugin)->str,
db.str, table_name.str, sql_copy);
goto ret;
} // endif unusable
thd->lex->create_info.db_type= plugin_data(db_plugin, handlerton *);
if (tabledef_version.str)
thd->lex->create_info.tabledef_version= tabledef_version;
#endif // 0
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);
if (file)
delete file;
else
rc= OPEN_FRM_CORRUPTED;
if (!rc && frm.str) {
table_s->option_list= 0; // cleanup existing options ...
table_s->option_struct= 0; // ... if it's an assisted discovery
rc= table_s->init_from_binary_frm_image(thd, true, frm.str, frm.length);
} // endif frm
//ret:
my_free(const_cast<uchar*>(frm.str));
reenable_binlog(thd);
#if 0
lex_end(thd->lex);
thd->lex= old_lex;
if (arena)
thd->restore_active_arena(arena, &backup);
thd->variables.sql_mode= saved_mode;
thd->variables.character_set_client= old_cs;
#endif // 0
if (thd->is_error() || rc) {
thd->clear_error();
my_error(ER_NO_SUCH_TABLE, MYF(0), table_s->db.str,
table_s->table_name.str);
DBUG_RETURN(HA_ERR_NOT_A_TABLE);
} else
DBUG_RETURN(0);
} // end of init_table_share
#else // !NEW_WAY
static int init_table_share(THD* thd,
TABLE_SHARE *table_s,
HA_CREATE_INFO *create_info,
String *sql)
{
bool oom= false;
PTOS topt= table_s->option_struct;
sql->length(sql->length()-1); // remove the trailing comma
sql->append(')');
for (ha_create_table_option *opt= connect_table_option_list;
opt->name; opt++) {
ulonglong vull;
const char *vstr;
switch (opt->type) {
case HA_OPTION_TYPE_ULL:
vull= *(ulonglong*)(((char*)topt) + opt->offset);
if (vull != opt->def_value) {
oom|= sql->append(' ');
oom|= sql->append(opt->name);
oom|= sql->append('=');
oom|= sql->append_ulonglong(vull);
} // endif vull
break;
case HA_OPTION_TYPE_STRING:
vstr= *(char**)(((char*)topt) + opt->offset);
if (vstr) {
oom|= sql->append(' ');
oom|= sql->append(opt->name);
oom|= sql->append("='");
oom|= sql->append_for_single_quote(vstr, strlen(vstr));
oom|= sql->append('\'');
} // endif vstr
break;
case HA_OPTION_TYPE_BOOL:
vull= *(bool*)(((char*)topt) + opt->offset);
if (vull != opt->def_value) {
oom|= sql->append(' ');
oom|= sql->append(opt->name);
oom|= sql->append('=');
oom|= sql->append(vull ? "ON" : "OFF");
} // endif vull
break;
default: // no enums here, good :)
break;
} // endswitch type
if (oom)
return HA_ERR_OUT_OF_MEM;
} // endfor opt
if (create_info->connect_string.length) {
oom|= sql->append(' ');
oom|= sql->append("CONNECTION='");
oom|= sql->append_for_single_quote(create_info->connect_string.str,
create_info->connect_string.length);
oom|= sql->append('\'');
if (oom)
return HA_ERR_OUT_OF_MEM;
} // endif string
if (create_info->default_table_charset) {
oom|= sql->append(' ');
oom|= sql->append("CHARSET=");
oom|= sql->append(create_info->default_table_charset->csname);
if (oom)
return HA_ERR_OUT_OF_MEM;
} // endif charset
if (xtrace)
htrc("s_init: %.*s\n", sql->length(), sql->ptr());
return table_s->init_from_sql_statement_string(thd, true,
sql->ptr(), sql->length());
} // end of init_table_share
#endif // !NEW_WAY
// Add an option to the create_info option list
static void add_option(THD* thd, HA_CREATE_INFO *create_info,
const char *opname, const char *opval)
{
#if defined(NEW_WAY)
LEX_STRING *opn= thd->make_lex_string(opname, strlen(opname));
LEX_STRING *val= thd->make_lex_string(opval, strlen(opval));
engine_option_value *pov, **start= &create_info->option_list, *end= NULL;
for (pov= *start; pov; pov= pov->next)
end= pov;
pov= new(thd->mem_root) engine_option_value(*opn, *val, false, start, &end);
#endif // NEW_WAY
} // end of add_option
/** /**
@brief @brief
...@@ -3389,6 +3723,9 @@ static bool add_field(String *sql, const char *field_name, const char *type, ...@@ -3389,6 +3723,9 @@ static bool add_field(String *sql, const char *field_name, const char *type,
When assisted discovery is used the .frm file have not already been When assisted discovery is used the .frm file have not already been
created. You can overwrite some definitions at this point but the created. You can overwrite some definitions at this point but the
main purpose of it is to define the columns for some table types. main purpose of it is to define the columns for some table types.
@note
this function is no more called in case of CREATE .. SELECT
*/ */
static int connect_assisted_discovery(handlerton *hton, THD* thd, static int connect_assisted_discovery(handlerton *hton, THD* thd,
TABLE_SHARE *table_s, TABLE_SHARE *table_s,
...@@ -3402,7 +3739,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3402,7 +3739,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
#if defined(WIN32) #if defined(WIN32)
char *nsp= NULL, *cls= NULL; char *nsp= NULL, *cls= NULL;
#endif // WIN32 #endif // WIN32
int port= 0, hdr= 0, mxr= 0, b= 0; int port= 0, hdr= 0, mxr= 0, rc= 0;
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL); uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
bool bif, ok= false, dbf= false; bool bif, ok= false, dbf= false;
TABTYPE ttp= TAB_UNDEF; TABTYPE ttp= TAB_UNDEF;
...@@ -3410,15 +3747,19 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3410,15 +3747,19 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
PCOLRES crp; PCOLRES crp;
PGLOBAL g= GetPlug(thd, NULL); PGLOBAL g= GetPlug(thd, NULL);
PTOS topt= table_s->option_struct; PTOS topt= table_s->option_struct;
#if defined(NEW_WAY)
//CHARSET_INFO *cs;
Alter_info alter_info;
#else // !NEW_WAY
char buf[1024]; char buf[1024];
String sql(buf, sizeof(buf), system_charset_info); String sql(buf, sizeof(buf), system_charset_info);
sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info);
#endif // !NEW_WAY
if (!g) if (!g)
return HA_ERR_INTERNAL_ERROR; return HA_ERR_INTERNAL_ERROR;
sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info);
user= host= pwd= prt= tbl= src= col= ocl= pic= fcl= rnk= dsn= NULL; user= host= pwd= prt= tbl= src= col= ocl= pic= fcl= rnk= dsn= NULL;
// Get the useful create options // Get the useful create options
...@@ -3468,6 +3809,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3468,6 +3809,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ttp= GetTypeID(topt->type); ttp= GetTypeID(topt->type);
sprintf(g->Message, "No table_type. Was set to %s", topt->type); sprintf(g->Message, "No table_type. Was set to %s", topt->type);
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
add_option(thd, create_info, "table_type", topt->type);
} else if (ttp == TAB_NIY) { } else if (ttp == TAB_NIY) {
sprintf(g->Message, "Unsupported table type %s", topt->type); sprintf(g->Message, "Unsupported table type %s", topt->type);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
...@@ -3500,6 +3842,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3500,6 +3842,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL))) } else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL)))
tab= (char*)create_info->alias; tab= (char*)create_info->alias;
#if defined(NEW_WAY)
add_option(thd, create_info, "tabname", tab);
#endif // NEW_WAY
} // endif tab } // endif tab
switch (ttp) { switch (ttp) {
...@@ -3536,7 +3881,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3536,7 +3881,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
dsn= (char*)PlugSubAlloc(g, NULL, strlen(dsn) + 1); dsn= (char*)PlugSubAlloc(g, NULL, strlen(dsn) + 1);
strncpy(dsn, create_info->connect_string.str, strncpy(dsn, create_info->connect_string.str,
create_info->connect_string.length); create_info->connect_string.length);
dsn[create_info->connect_string.length] = 0; dsn[create_info->connect_string.length]= 0;
mydef->SetName(create_info->alias); mydef->SetName(create_info->alias);
mydef->SetCat(cat); mydef->SetCat(cat);
...@@ -3561,12 +3906,17 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3561,12 +3906,17 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
break; break;
#endif // WIN32 #endif // WIN32
case TAB_PIVOT: case TAB_PIVOT:
supfnc = FNC_NO; supfnc= FNC_NO;
case TAB_PRX: case TAB_PRX:
case TAB_TBL: case TAB_TBL:
case TAB_XCL: case TAB_XCL:
case TAB_OCCUR: case TAB_OCCUR:
if (!stricmp(tab, create_info->alias) &&
(!db || !stricmp(db, table_s->db.str)))
sprintf(g->Message, "A %s table cannot refer to itself", topt->type);
else
ok= true; ok= true;
break; break;
default: default:
sprintf(g->Message, "Cannot get column info for table type %s", topt->type); sprintf(g->Message, "Cannot get column info for table type %s", topt->type);
...@@ -3585,13 +3935,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3585,13 +3935,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ok= false; ok= false;
} // endif src } // endif src
// Here we should test the flag column options when
// this function is called in case of CREATE .. SELECT
if (ok) { if (ok) {
char *cnm, *rem; char *cnm, *rem;
int i, len, dec, typ, flg; int i, len, dec, typ, flg;
const char *type;
PDBUSER dup= PlgGetUser(g); PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL; PCATLG cat= (dup) ? dup->Catalog : NULL;
...@@ -3682,24 +4028,35 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3682,24 +4028,35 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if (fnc != FNC_NO || src || ttp == TAB_PIVOT) { if (fnc != FNC_NO || src || ttp == TAB_PIVOT) {
// Catalog like table // Catalog like table
for (crp= qrp->Colresp; !b && crp; crp= crp->Next) { for (crp= qrp->Colresp; !rc && crp; crp= crp->Next) {
cnm= encode(g, crp->Name); cnm= encode(g, crp->Name);
type= PLGtoMYSQLtype(crp->Type, dbf); typ= crp->Type;
len= crp->Length; len= crp->Length;
dec= crp->Prec; dec= crp->Prec;
flg= crp->Flag; flg= crp->Flag;
#if defined(NEW_WAY)
// Now add the field // Now add the field
if (add_field(&sql, cnm, type, len, dec, NOT_NULL_FLAG, 0, flg)) rc= add_fields(g, thd, &alter_info, cnm, typ, len, dec,
b= HA_ERR_OUT_OF_MEM; 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))
rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY
} // endfor crp } // endfor crp
} else // Not a catalog table } else // Not a catalog table
for (i= 0; !b && i < qrp->Nblin; i++) { for (i= 0; !rc && i < qrp->Nblin; i++) {
rem= NULL;
typ= len= dec= 0; typ= len= dec= 0;
tm= NOT_NULL_FLAG; tm= NOT_NULL_FLAG;
cnm= (char*)"noname"; cnm= (char*)"noname";
#if defined(NEW_WAY)
rem= "";
// cs= NULL;
#else // !NEW_WAY
rem= NULL;
#endif // !NEW_WAY
for (crp= qrp->Colresp; crp; crp= crp->Next) for (crp= qrp->Colresp; crp; crp= crp->Next)
switch (crp->Fld) { switch (crp->Fld) {
...@@ -3755,103 +4112,27 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3755,103 +4112,27 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
#endif // ODBC_SUPPORT #endif // ODBC_SUPPORT
// Make the arguments as required by add_fields // Make the arguments as required by add_fields
type= PLGtoMYSQLtype(typ, true);
if (typ == TYPE_DATE) if (typ == TYPE_DATE)
len= 0; len= 0;
// Now add the field // Now add the field
if (add_field(&sql, cnm, type, len, dec, tm, rem, 0)) #if defined(NEW_WAY)
b= HA_ERR_OUT_OF_MEM; 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))
rc= HA_ERR_OUT_OF_MEM;
#endif // !NEW_WAY
} // endfor i } // endfor i
sql.length(sql.length()-1); // remove the trailing comma #if defined(NEW_WAY)
sql.append(')'); rc= init_table_share(thd, table_s, create_info, &alter_info);
#else // !NEW_WAY
for (ha_create_table_option *opt= connect_table_option_list; if (!rc)
opt->name; opt++) { rc= init_table_share(thd, table_s, create_info, &sql);
ulonglong vull; #endif // !NEW_WAY
const char *vstr;
bool oom= false;
switch (opt->type) {
case HA_OPTION_TYPE_ULL:
vull= *(ulonglong*)(((char*)topt) + opt->offset);
if (vull != opt->def_value) {
oom|= sql.append(' ');
oom|= sql.append(opt->name);
oom|= sql.append('=');
oom|= sql.append_ulonglong(vull);
} // endif vull
break;
case HA_OPTION_TYPE_STRING:
vstr= *(char**)(((char*)topt) + opt->offset);
if (vstr) {
oom|= sql.append(' ');
oom|= sql.append(opt->name);
oom|= sql.append("='");
oom|= sql.append_for_single_quote(vstr, strlen(vstr));
oom|= sql.append('\'');
} // endif vstr
break;
case HA_OPTION_TYPE_BOOL:
vull= *(bool*)(((char*)topt) + opt->offset);
if (vull != opt->def_value) {
oom|= sql.append(' ');
oom|= sql.append(opt->name);
oom|= sql.append('=');
oom|= sql.append(vull ? "ON" : "OFF");
} // endif vull
break;
default: // no enums here, good :)
break;
} // endswitch type
if (oom) return rc;
b= HA_ERR_OUT_OF_MEM;
} // endfor opt
if (create_info->connect_string.length) {
bool oom= false;
oom|= sql.append(' ');
oom|= sql.append("CONNECTION='");
oom|= sql.append_for_single_quote(create_info->connect_string.str,
create_info->connect_string.length);
oom|= sql.append('\'');
if (oom)
b= HA_ERR_OUT_OF_MEM;
} // endif string
if (create_info->default_table_charset) {
bool oom= false;
oom|= sql.append(' ');
oom|= sql.append("CHARSET=");
oom|= sql.append(create_info->default_table_charset->csname);
if (oom)
b= HA_ERR_OUT_OF_MEM;
} // endif charset
if (xtrace)
printf("s_init: %.*s\n", sql.length(), sql.ptr());
if (!b)
b= table_s->init_from_sql_statement_string(thd, true,
sql.ptr(), sql.length());
return b;
} // endif ok } // endif ok
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
...@@ -3949,6 +4230,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -3949,6 +4230,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
switch (type) { switch (type) {
case TAB_PRX: case TAB_PRX:
case TAB_XCL: case TAB_XCL:
case TAB_PIVOT:
case TAB_OCCUR: case TAB_OCCUR:
if (options->srcdef) { if (options->srcdef) {
strcpy(g->Message, "Cannot check looping reference"); strcpy(g->Message, "Cannot check looping reference");
......
...@@ -167,9 +167,9 @@ class ha_connect: public handler ...@@ -167,9 +167,9 @@ class ha_connect: public handler
PIXDEF GetIndexInfo(void); PIXDEF GetIndexInfo(void);
const char *GetDBName(const char *name); const char *GetDBName(const char *name);
const char *GetTableName(void); const char *GetTableName(void);
int GetColNameLen(Field *fp); //int GetColNameLen(Field *fp);
char *GetColName(Field *fp); //char *GetColName(Field *fp);
void AddColName(char *cp, Field *fp); //void AddColName(char *cp, Field *fp);
TABLE *GetTable(void) {return table;} TABLE *GetTable(void) {return table;}
bool IsSameIndex(PIXDEF xp1, PIXDEF xp2); bool IsSameIndex(PIXDEF xp1, PIXDEF xp2);
...@@ -208,7 +208,7 @@ class ha_connect: public handler ...@@ -208,7 +208,7 @@ class ha_connect: public handler
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_HAS_RECORDS | return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_HAS_RECORDS |
HA_NO_AUTO_INCREMENT | HA_NO_PREFIX_CHAR_KEYS | HA_NO_AUTO_INCREMENT | HA_NO_PREFIX_CHAR_KEYS |
HA_NO_COPY_ON_ALTER | HA_CAN_VIRTUAL_COLUMNS | HA_NO_COPY_ON_ALTER | HA_CAN_VIRTUAL_COLUMNS |
HA_NULL_IN_KEY | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE); /*HA_NULL_IN_KEY |*/ HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE);
} }
/** @brief /** @brief
...@@ -319,6 +319,21 @@ const char *GetValStr(OPVAL vop, bool neg); ...@@ -319,6 +319,21 @@ const char *GetValStr(OPVAL vop, bool neg);
*/ */
virtual ha_rows records(); virtual ha_rows records();
/**
Type of table for caching query
CONNECT should not use caching because its tables are external
data prone to me modified out of MariaDB
*/
virtual uint8 table_cache_type(void)
{
#if defined(MEMORY_TRACE)
// Temporary until bug MDEV-4771 is fixed
return HA_CACHE_TBL_NONTRANSACT;
#else
return HA_CACHE_TBL_NOCACHE;
#endif
}
/** @brief /** @brief
We implement this in ha_connect.cc; it's a required method. We implement this in ha_connect.cc; it's a required method.
*/ */
...@@ -400,6 +415,7 @@ const char *GetValStr(OPVAL vop, bool neg); ...@@ -400,6 +415,7 @@ const char *GetValStr(OPVAL vop, bool neg);
void position(const uchar *record); ///< required void position(const uchar *record); ///< required
int info(uint); ///< required int info(uint); ///< required
int extra(enum ha_extra_function operation); int extra(enum ha_extra_function operation);
int start_stmt(THD *thd, thr_lock_type lock_type);
int external_lock(THD *thd, int lock_type); ///< required int external_lock(THD *thd, int lock_type); ///< required
int delete_all_rows(void); int delete_all_rows(void);
ha_rows records_in_range(uint inx, key_range *min_key, ha_rows records_in_range(uint inx, key_range *min_key,
...@@ -429,6 +445,7 @@ const char *GetValStr(OPVAL vop, bool neg); ...@@ -429,6 +445,7 @@ const char *GetValStr(OPVAL vop, bool neg);
protected: protected:
bool check_privileges(THD *thd, PTOS options); bool check_privileges(THD *thd, PTOS options);
MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras);
// Members // Members
static ulong num; // Tracable handler number static ulong num; // Tracable handler number
...@@ -446,6 +463,7 @@ const char *GetValStr(OPVAL vop, bool neg); ...@@ -446,6 +463,7 @@ const char *GetValStr(OPVAL vop, bool neg);
bool valid_info; // True if xinfo is valid bool valid_info; // True if xinfo is valid
bool stop; // Used when creating index bool stop; // Used when creating index
int indexing; // Type of indexing for CONNECT int indexing; // Type of indexing for CONNECT
int locked; // Table lock
THR_LOCK_DATA lock_data; THR_LOCK_DATA lock_data;
public: public:
......
...@@ -315,4 +315,4 @@ bool MACINFO::GetOneInfo(PGLOBAL g, int flag, void *v, int lv) ...@@ -315,4 +315,4 @@ bool MACINFO::GetOneInfo(PGLOBAL g, int flag, void *v, int lv)
*((int*)v) = n; *((int*)v) = n;
return false; return false;
} // end of ReadColumn } // end of GetOneInfo
...@@ -468,9 +468,9 @@ int MYCAT::GetColCatInfo(PGLOBAL g, PTABDEF defp) ...@@ -468,9 +468,9 @@ int MYCAT::GetColCatInfo(PGLOBAL g, PTABDEF defp)
break; break;
} // endswitch tc } // endswitch tc
do { // do {
field= Hc->GetColumnOption(g, field, pcf); field= Hc->GetColumnOption(g, field, pcf);
} while (field && (*pcf->Name =='*' /*|| pcf->Flags & U_VIRTUAL*/)); // } while (field && (*pcf->Name =='*' /*|| pcf->Flags & U_VIRTUAL*/));
if (tc == TAB_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) { if (tc == TAB_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) {
// DBF date format defaults to 'YYYMMDD' // DBF date format defaults to 'YYYMMDD'
......
...@@ -134,7 +134,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, ...@@ -134,7 +134,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/**********************************************************************/ /**********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
buftyp, fldtyp, length, true, true); buftyp, fldtyp, length, false, true);
// Some columns must be renamed // Some columns must be renamed
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
......
...@@ -30,10 +30,12 @@ t2 CREATE TABLE `t2` ( ...@@ -30,10 +30,12 @@ t2 CREATE TABLE `t2` (
SELECT * FROM t2; SELECT * FROM t2;
ERROR HY000: Got error 174 '(1054) Unknown column 'x' in 'field list' [SELECT `x`, `y` FROM `t1`]' from CONNECT ERROR HY000: Got error 174 '(1054) Unknown column 'x' in 'field list' [SELECT `x`, `y` FROM `t1`]' from CONNECT
DROP TABLE t2; DROP TABLE t2;
CREATE TABLE t2 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=PORT';
ALTER TABLE t1 RENAME t1backup; ALTER TABLE t1 RENAME t1backup;
SELECT * FROM t2; SELECT * FROM t2;
ERROR 42S02: Table 'test.t2' doesn't exist ERROR HY000: Got error 174 '(1146) Table 'test.t1' doesn't exist [SELECT `a`, `b` FROM `t1`]' from CONNECT
ALTER TABLE t1backup RENAME t1; ALTER TABLE t1backup RENAME t1;
DROP TABLE t2;
# #
# Testing SELECT, etc. # Testing SELECT, etc.
# #
......
...@@ -78,6 +78,8 @@ Car DOUBLE(8,2) FLAG=1, ...@@ -78,6 +78,8 @@ Car DOUBLE(8,2) FLAG=1,
Food DOUBLE(8,2) FLAG=1) Food DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT ENGINE=CONNECT TABLE_TYPE=PIVOT
SRCDEF='select who, week, what, sum(amount) as amount from expenses where week in (4,5) group by who, week, what'; SRCDEF='select who, week, what, sum(amount) as amount from expenses where week in (4,5) group by who, week, what';
Warnings:
Warning 1105 Cannot check looping reference
ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=PORT'; ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=PORT';
Warnings: Warnings:
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
...@@ -125,6 +127,8 @@ Middle DOUBLE(8,2) FLAG=1, ...@@ -125,6 +127,8 @@ Middle DOUBLE(8,2) FLAG=1,
Last DOUBLE(8,2) FLAG=1) Last DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT ENGINE=CONNECT TABLE_TYPE=PIVOT
SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk'; SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk';
Warnings:
Warning 1105 Cannot check looping reference
ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=PORT'; ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=PORT';
Warnings: Warnings:
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
......
...@@ -413,7 +413,7 @@ DROP TABLE t1; ...@@ -413,7 +413,7 @@ DROP TABLE t1;
SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml'); SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml');
SELECT CAST(@a AS CHAR CHARACTER SET latin1); SELECT CAST(@a AS CHAR CHARACTER SET latin1);
CAST(@a AS CHAR CHARACTER SET latin1) <?xml version="1.0" encoding="iso-8859-1"?> CAST(@a AS CHAR CHARACTER SET latin1) <?xml version="1.0" encoding="iso-8859-1"?>
<!-- Created by CONNECT Version 1.01.0006 Mai 21, 2013 --> <!-- Created by CONNECT Version 1.01.0007 July 26, 2013 -->
<t1> <t1>
<line> <line>
<node>ÀÁÂÃ</node> <node>ÀÁÂÃ</node>
......
...@@ -64,11 +64,13 @@ SELECT * FROM t2; ...@@ -64,11 +64,13 @@ SELECT * FROM t2;
DROP TABLE t2; DROP TABLE t2;
# The remote table disappeared # The remote table disappeared
--replace_result $PORT PORT
--eval CREATE TABLE t2 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
ALTER TABLE t1 RENAME t1backup; ALTER TABLE t1 RENAME t1backup;
--error ER_NO_SUCH_TABLE --error ER_GET_ERRMSG
SELECT * FROM t2; SELECT * FROM t2;
ALTER TABLE t1backup RENAME t1; ALTER TABLE t1backup RENAME t1;
DROP TABLE t2;
--echo # --echo #
......
...@@ -281,7 +281,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, ...@@ -281,7 +281,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_COLUMNS, qrp = PlgAllocResult(g, ncol, maxres, IDS_COLUMNS,
buftyp, fldtyp, length, true, true); buftyp, fldtyp, length, false, true);
if (info) // Info table if (info) // Info table
return qrp; return qrp;
...@@ -423,7 +423,7 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info) ...@@ -423,7 +423,7 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info)
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC, qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC,
buftyp, fldtyp, length, true, true); buftyp, fldtyp, length, false, true);
/************************************************************************/ /************************************************************************/
/* Now get the results into blocks. */ /* Now get the results into blocks. */
...@@ -468,7 +468,7 @@ PQRYRES ODBCDrivers(PGLOBAL g, bool info) ...@@ -468,7 +468,7 @@ PQRYRES ODBCDrivers(PGLOBAL g, bool info)
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_DRIVER, qrp = PlgAllocResult(g, ncol, maxres, IDS_DRIVER,
buftyp, fldtyp, length, true, true); buftyp, fldtyp, length, false, true);
/************************************************************************/ /************************************************************************/
/* Now get the results into blocks. */ /* Now get the results into blocks. */
...@@ -533,7 +533,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) ...@@ -533,7 +533,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info)
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES, buftyp, qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES, buftyp,
fldtyp, length, true, true); fldtyp, length, false, true);
if (info) if (info)
return qrp; return qrp;
...@@ -617,7 +617,7 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table) ...@@ -617,7 +617,7 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table)
/* Allocate the structure used to refer to the result set. */ /* Allocate the structure used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_PKEY, qrp = PlgAllocResult(g, ncol, maxres, IDS_PKEY,
buftyp, NULL, length, true, true); buftyp, NULL, length, false, true);
if (trace) if (trace)
htrc("Getting pkey results ncol=%d\n", qrp->Nbcol); htrc("Getting pkey results ncol=%d\n", qrp->Nbcol);
...@@ -699,7 +699,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat, ...@@ -699,7 +699,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat,
/* Allocate the structure used to refer to the result set. */ /* Allocate the structure used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_STAT, qrp = PlgAllocResult(g, ncol, maxres, IDS_STAT,
buftyp, NULL, length, true, true); buftyp, NULL, length, false, true);
if (trace) if (trace)
htrc("Getting stat results ncol=%d\n", qrp->Nbcol); htrc("Getting stat results ncol=%d\n", qrp->Nbcol);
...@@ -1210,20 +1210,19 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols) ...@@ -1210,20 +1210,19 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
RETCODE rc; RETCODE rc;
HSTMT hstmt; HSTMT hstmt;
//m_Recset = new(m_G) RECSET(this);
//ASSERT(m_Recset);
try { try {
b = false; b = false;
if (m_hstmt) { if (m_hstmt) {
/*RETCODE rc;*/
// All this did not seems to make sense and was been commented out // All this did not seems to make sense and was been commented out
// if (IsOpen()) // if (IsOpen())
// Close(SQL_CLOSE); // Close(SQL_CLOSE);
/*rc =*/ SQLFreeStmt(m_hstmt, SQL_CLOSE); rc = SQLFreeStmt(m_hstmt, SQL_CLOSE);
if (trace && !Check(rc))
htrc("Error: SQLFreeStmt rc=%d\n", rc);
hstmt = m_hstmt; hstmt = m_hstmt;
m_hstmt = NULL; m_hstmt = NULL;
ThrowDBX(MSG(SEQUENCE_ERROR)); ThrowDBX(MSG(SEQUENCE_ERROR));
...@@ -1340,7 +1339,6 @@ int ODBConn::GetResultSize(char *sql, ODBCCOL *colp) ...@@ -1340,7 +1339,6 @@ int ODBConn::GetResultSize(char *sql, ODBCCOL *colp)
} // endfor n } // endfor n
} catch(DBX *x) { } catch(DBX *x) {
// strcpy(m_G->Message, x->m_ErrMsg[0]);
strcpy(m_G->Message, x->GetErrorMessage(0)); strcpy(m_G->Message, x->GetErrorMessage(0));
if (trace) if (trace)
...@@ -1516,7 +1514,6 @@ bool ODBConn::BindParam(ODBCCOL *colp) ...@@ -1516,7 +1514,6 @@ bool ODBConn::BindParam(ODBCCOL *colp)
#endif // 0 #endif // 0
buf = colp->GetBuffer(0); buf = colp->GetBuffer(0);
// len = colp->GetBuflen();
len = IsTypeNum(colp->GetResultType()) ? 0 : colp->GetBuflen(); len = IsTypeNum(colp->GetResultType()) ? 0 : colp->GetBuflen();
ct = GetSQLCType(colp->GetResultType()); ct = GetSQLCType(colp->GetResultType());
sqlt = GetSQLType(colp->GetResultType()); sqlt = GetSQLType(colp->GetResultType());
...@@ -1580,7 +1577,6 @@ bool ODBConn::GetDataSources(PQRYRES qrp) ...@@ -1580,7 +1577,6 @@ bool ODBConn::GetDataSources(PQRYRES qrp)
rv = true; rv = true;
} // end try/catch } // end try/catch
//SQLFreeEnv(m_henv);
Close(); Close();
return rv; return rv;
} // end of GetDataSources } // end of GetDataSources
...@@ -1632,7 +1628,6 @@ bool ODBConn::GetDrivers(PQRYRES qrp) ...@@ -1632,7 +1628,6 @@ bool ODBConn::GetDrivers(PQRYRES qrp)
rv = true; rv = true;
} // end try/catch } // end try/catch
//SQLFreeEnv(m_henv);
Close(); Close();
return rv; return rv;
} // end of GetDrivers } // end of GetDrivers
...@@ -1801,7 +1796,6 @@ int ODBConn::GetCatInfo(CATPARM *cap) ...@@ -1801,7 +1796,6 @@ int ODBConn::GetCatInfo(CATPARM *cap)
} else // ODBC Ver 3 } else // ODBC Ver 3
rc = SQLFetch(hstmt); rc = SQLFetch(hstmt);
// if (!Check(rc))
if (rc == SQL_NO_DATA_FOUND) { if (rc == SQL_NO_DATA_FOUND) {
if (cap->Pat) if (cap->Pat)
sprintf(m_G->Message, MSG(NO_TABCOL_DATA), cap->Tab, cap->Pat); sprintf(m_G->Message, MSG(NO_TABCOL_DATA), cap->Tab, cap->Pat);
...@@ -1837,270 +1831,35 @@ int ODBConn::GetCatInfo(CATPARM *cap) ...@@ -1837,270 +1831,35 @@ int ODBConn::GetCatInfo(CATPARM *cap)
/***********************************************************************/ /***********************************************************************/
void ODBConn::Close() void ODBConn::Close()
{ {
/*RETCODE rc;*/ RETCODE rc;
#if 0
// Close any open recordsets
AfxLockGlobals(CRIT_ODBC);
TRY
{
while (!m_listRecordsets.IsEmpty())
{
CRecordset* pSet = (CRecordset*)m_listRecordsets.GetHead();
pSet->Close(); // will implicitly remove from list
pSet->m_pDatabase = NULL;
}
}
CATCH_ALL(e)
{
AfxUnlockGlobals(CRIT_ODBC);
THROW_LAST();
}
END_CATCH_ALL
AfxUnlockGlobals(CRIT_ODBC);
#endif // 0
if (m_hstmt) { if (m_hstmt) {
// Is required for multiple tables // Is required for multiple tables
/*rc =*/ SQLFreeStmt(m_hstmt, SQL_DROP); rc = SQLFreeStmt(m_hstmt, SQL_DROP);
m_hstmt = NULL; m_hstmt = NULL;
} // endif m_hstmt } // endif m_hstmt
if (m_hdbc != SQL_NULL_HDBC) { if (m_hdbc != SQL_NULL_HDBC) {
/*rc =*/ SQLDisconnect(m_hdbc); rc = SQLDisconnect(m_hdbc);
/*rc =*/ SQLFreeConnect(m_hdbc);
m_hdbc = SQL_NULL_HDBC;
// AfxLockGlobals(CRIT_ODBC); if (trace && rc != SQL_SUCCESS)
// ASSERT(m_nAlloc != 0); htrc("Error: SQLDisconnect rc=%d\n", rc);
// m_nAlloc--;
// AfxUnlockGlobals(CRIT_ODBC);
} // endif m_hdbc
if (m_henv != SQL_NULL_HENV) { rc = SQLFreeConnect(m_hdbc);
if (trace) {
RETCODE rc = SQLFreeEnv(m_henv);
if (rc != SQL_SUCCESS) // Nothing we can do if (trace && rc != SQL_SUCCESS)
htrc("Error: SQLFreeEnv failure ignored in Close\n"); htrc("Error: SQLFreeConnect rc=%d\n", rc);
} else m_hdbc = SQL_NULL_HDBC;
SQLFreeEnv(m_henv); } // endif m_hdbc
m_henv = SQL_NULL_HENV;
} // endif m_henv
} // end of Close
#if 0
// Silently disconnect and free all ODBC resources.
// Don't throw any exceptions
void ODBConn::Free()
{
// Trap failures upon close
try {
Close();
} catch(DBX*) {
// Nothing we can do
if (trace)
htrc("Error: exception by Close ignored in Free\n");
// DELETE_EXCEPTION(x);
} // endcatch
// free henv if refcount goes to 0
//AfxLockGlobals(CRIT_ODBC);
if (m_henv != SQL_NULL_HENV) { if (m_henv != SQL_NULL_HENV) {
ASSERT(m_nAlloc >= 0); rc = SQLFreeEnv(m_henv);
if (m_nAlloc == 0) { if (trace && rc != SQL_SUCCESS) // Nothing we can do
// free last connection - release HENV htrc("Error: SQLFreeEnv failure ignored in Close\n");
if (trace) {
RETCODE rc = SQLFreeEnv(m_henv);
if (rc != SQL_SUCCESS) // Nothing we can do
htrc("Error: SQLFreeEnv failure ignored in Free\n");
} else
SQLFreeEnv(m_henv);
m_henv = SQL_NULL_HENV; m_henv = SQL_NULL_HENV;
} // endif m_nAlloc
} // endif m_henv } // endif m_henv
//AfxUnlockGlobals(CRIT_ODBC);
} // end of Free
//////////////////////////////////////////////////////////////////////////////
// CRecordset helpers
//id AFXAPI AfxSetCurrentRecord(int* plCurrentRecord, int nRows, RETCODE nRetCode);
//id AFXAPI AfxSetRecordCount(int* plRecordCount, int lCurrentRecord,
//bool bEOFSeen, RETCODE nRetCode);
/***********************************************************************/
/* RECSET class implementation */
/***********************************************************************/
RECSET::RECSET(ODBConn *dbcp)
{
m_pDB = dbcp;
m_hstmt = SQL_NULL_HSTMT;
m_OpenType = snapshot;
m_Options = none;
#if 0
m_lOpen = AFX_RECORDSET_STATUS_UNKNOWN;
m_nEditMode = noMode;
m_nDefaultType = snapshot;
m_bAppendable = false;
m_bUpdatable = false;
m_bScrollable = false;
m_bRecordsetDb = false;
m_bRebindParams = false;
m_bLongBinaryColumns = false;
m_nLockMode = optimistic;
m_dwInitialGetDataLen = 0;
m_rgODBCFieldInfos = NULL;
m_rgFieldInfos = NULL;
m_rgRowStatus = NULL;
m_dwRowsetSize = 25;
m_dwAllocatedRowsetSize = 0;
m_nFields = 0;
m_nParams = 0;
m_nFieldsBound = 0;
m_lCurrentRecord = AFX_CURRENT_RECORD_UNDEFINED;
m_lRecordCount = 0;
m_bUseUpdateSQL = false;
m_bUseODBCCursorLib = false;
m_nResultCols = -1;
m_bCheckCacheForDirtyFields = true;
m_pbFieldFlags = NULL;
m_pbParamFlags = NULL;
m_plParamLength = NULL;
m_pvFieldProxy = NULL;
m_pvParamProxy = NULL;
m_nProxyFields = 0;
m_nProxyParams = 0;
m_hstmtUpdate = SQL_NULL_HSTMT;
#endif // 0
} // end of RECSET constructor
RECSET::~RECSET()
{
try {
if (m_hstmt) {
if (trace && (m_dwOptions & useMultiRowFetch)) {
htrc("WARNING: Close called implicitly from destructor\n");
htrc("Use of multi row fetch requires explicit call\n");
htrc("to Close or memory leaks will result\n");
} // endif trace
Close();
} // endif m_hstmt
// if (m_bRecordsetDb)
// delete m_pDB; ??????
m_pDB = NULL;
} catch(DBX*) {
// Nothing we can do
if (trace)
htrc("Error: Exception ignored in ~RECSET\n");
} // endtry/catch
} // end of ~RECSET
/***********************************************************************/
/* Open: this function does the following: */
/* Allocates the hstmt, */
/* Bind columns, */
/* Execute the SQL statement */
/***********************************************************************/
bool RECSET::Open(PSZ sql, uint Type, DWORD options)
{
ASSERT(m_pDB && m_pDB->IsOpen());
ASSERT(Type == DB_USE_DEFAULT_TYPE || Type == dynaset ||
Type == snapshot || Type == forwardOnly || Type == dynamic);
//ASSERT(!(options & readOnly && options & appendOnly));
// Cache state info and allocate hstmt
SetState(Type, sql, options);
try {
if (m_hstmt) {
if (IsOpen())
Close(SQL_CLOSE);
} else {
RETCODE rc = SQLAllocStmt(m_pDB->m_hdbc, &m_hstmt);
if (!Check(rc))
ThrowDBException(SQL_INVALID_HANDLE);
} // endif m_hstmt
m_pDB->OnSetOptions(m_hstmt);
// Allocate the field/param status arrays, if necessary
// bool bUnbound = false;
// if (m_nFields > 0 || m_nParams > 0)
// AllocStatusArrays();
// else
// bUnbound = true;
// Build SQL and prep/execute or just execute direct
// BuildSQL(sql);
PrepareAndExecute(sql);
// Cache some field info and prepare the rowset
AllocAndCacheFieldInfo();
AllocRowset();
// If late binding, still need to allocate status arrays
// if (bUnbound && (m_nFields > 0 || m_nParams > 0))
// AllocStatusArrays();
} catch(DBX *x) {
Close(SQL_DROP);
// strcpy(m_pDB->m_G->Message, x->GetErrorMessage[0]);
strcpy(m_pDB->m_G->Message, x->GetErrorMessage(0));
return true;
} // endtry/catch
return false;
} // end of Open
/***********************************************************************/
/* Close a hstmt. */
/***********************************************************************/
void RECSET::Close(SWORD option)
{
if (m_hstmt != SQL_NULL_HSTMT) {
RETCODE rc = SQLFreeStmt(m_hstmt, option);
if (option == SQL_DROP)
m_hstmt = SQL_NULL_HSTMT;
} // endif m_hstmt
#if 0
m_lOpen = RECORDSET_STATUS_CLOSED;
m_bBOF = true;
m_bEOF = true;
m_bDeleted = false;
m_bAppendable = false;
m_bUpdatable = false;
m_bScrollable = false;
m_bRebindParams = false;
m_bLongBinaryColumns = false;
m_nLockMode = optimistic;
m_nFieldsBound = 0;
m_nResultCols = -1;
#endif // 0
} // end of Close } // end of Close
#endif // 0
...@@ -151,7 +151,8 @@ enum ALGMOD {AMOD_AUTO = 0, /* PLG chooses best algorithm */ ...@@ -151,7 +151,8 @@ enum ALGMOD {AMOD_AUTO = 0, /* PLG chooses best algorithm */
#define NAM_LEN 128 #define NAM_LEN 128
#endif // !0 #endif // !0
enum MODE {MODE_ANY = 0, /* Unspecified mode */ enum MODE {MODE_ERROR = -1, /* Invalid mode */
MODE_ANY = 0, /* Unspecified mode */
MODE_READ = 10, /* Input/Output mode */ MODE_READ = 10, /* Input/Output mode */
MODE_WRITE = 20, /* Input/Output mode */ MODE_WRITE = 20, /* Input/Output mode */
MODE_UPDATE = 30, /* Input/Output mode */ MODE_UPDATE = 30, /* Input/Output mode */
...@@ -319,7 +320,8 @@ enum COLUSE {U_P = 0x01, /* the projection list. */ ...@@ -319,7 +320,8 @@ enum COLUSE {U_P = 0x01, /* the projection list. */
U_VAR = 0x10, /* a VARCHAR column */ U_VAR = 0x10, /* a VARCHAR column */
U_VIRTUAL = 0x20, /* a VIRTUAL column */ U_VIRTUAL = 0x20, /* a VIRTUAL column */
U_NULLS = 0x40, /* The column may have nulls */ U_NULLS = 0x40, /* The column may have nulls */
U_IS_NULL = 0x80}; /* The column has a null value */ U_IS_NULL = 0x80, /* The column has a null value */
U_SPECIAL = 0x100}; /* The column is special */
/***********************************************************************/ /***********************************************************************/
/* DB description class and block pointer definitions. */ /* DB description class and block pointer definitions. */
......
...@@ -383,6 +383,7 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff) ...@@ -383,6 +383,7 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
Name = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Name) + 1); Name = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Name) + 1);
strcpy(Name, cfp->Name); strcpy(Name, cfp->Name);
if (!(cfp->Flags & U_SPECIAL)) {
Poff = poff; Poff = poff;
Buf_Type = cfp->Type; Buf_Type = cfp->Type;
...@@ -398,7 +399,7 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff) ...@@ -398,7 +399,7 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
Long = cfp->Length; Long = cfp->Length;
Opt = cfp->Opt; Opt = cfp->Opt;
Key = cfp->Key; Key = cfp->Key;
//Freq = cfp->Freq; // Freq = cfp->Freq;
if (cfp->Remark && *cfp->Remark) { if (cfp->Remark && *cfp->Remark) {
Desc = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Remark) + 1); Desc = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Remark) + 1);
...@@ -410,13 +411,15 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff) ...@@ -410,13 +411,15 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
strcpy(Decode, cfp->Datefmt); strcpy(Decode, cfp->Datefmt);
} // endif Datefmt } // endif Datefmt
} // endif special
if (cfp->Fieldfmt) { if (cfp->Fieldfmt) {
Fmt = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Fieldfmt) + 1); Fmt = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Fieldfmt) + 1);
strcpy(Fmt, cfp->Fieldfmt); strcpy(Fmt, cfp->Fieldfmt);
} // endif Fieldfmt } // endif Fieldfmt
Flags = cfp->Flags; Flags = cfp->Flags;
return (Flags & U_VIRTUAL) ? 0 : Long; return (Flags & (U_VIRTUAL|U_SPECIAL)) ? 0 : Long;
} // end of Define } // end of Define
/* ------------------------- End of RelDef --------------------------- */ /* ------------------------- End of RelDef --------------------------- */
...@@ -175,6 +175,7 @@ class DllExport COLDEF : public COLCRT { /* Column description block ...@@ -175,6 +175,7 @@ class DllExport COLDEF : public COLCRT { /* Column description block
friend class MYCAT; friend class MYCAT;
friend class COLBLK; friend class COLBLK;
friend class DBFFAM; friend class DBFFAM;
friend class TDBASE;
public: public:
COLDEF(void); // Constructor COLDEF(void); // Constructor
......
...@@ -339,7 +339,7 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q, ...@@ -339,7 +339,7 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/*********************************************************************/ /*********************************************************************/
qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3, qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3,
buftyp, fldtyp, length, true, false); buftyp, fldtyp, length, false, false);
qrp->Nblin = imax; qrp->Nblin = imax;
if (info) if (info)
......
...@@ -307,15 +307,17 @@ PCOL TDBASE::ColDB(PGLOBAL g, PSZ name, int num) ...@@ -307,15 +307,17 @@ PCOL TDBASE::ColDB(PGLOBAL g, PSZ name, int num)
/*****************************************************************/ /*****************************************************************/
if (cp) if (cp)
colp = cp; colp = cp;
else else if (!(cdp->Flags & U_SPECIAL))
colp = MakeCol(g, cdp, cprec, i); colp = MakeCol(g, cdp, cprec, i);
else if (Mode == MODE_READ)
colp = InsertSpcBlk(g, cdp);
if (trace) if (trace)
htrc("colp=%p\n", colp); htrc("colp=%p\n", colp);
if (name || num) if (name || num)
break; break;
else if (colp) else if (colp && !colp->IsSpecial())
cprec = colp; cprec = colp;
} // endif Name } // endif Name
...@@ -339,30 +341,35 @@ PCOL TDBASE::InsertSpecialColumn(PGLOBAL g, PCOL colp) ...@@ -339,30 +341,35 @@ PCOL TDBASE::InsertSpecialColumn(PGLOBAL g, PCOL colp)
/***********************************************************************/ /***********************************************************************/
/* Make a special COLBLK to insert in a table. */ /* Make a special COLBLK to insert in a table. */
/***********************************************************************/ /***********************************************************************/
PCOL TDBASE::InsertSpcBlk(PGLOBAL g, PCOLUMN cp) PCOL TDBASE::InsertSpcBlk(PGLOBAL g, PCOLDEF cdp)
{ {
char *name = (char*)cp->GetName(); //char *name = cdp->GetName();
char *name = cdp->GetFmt();
PCOLUMN cp;
PCOL colp; PCOL colp;
if (!strcmp(name, "FILEID")) { cp= new(g) COLUMN(cdp->GetName());
// !strcmp(name, "SERVID")) { cp->SetTo_Table(To_Table);
if (!stricmp(name, "FILEID") ||
!stricmp(name, "SERVID")) {
if (!To_Def || !(To_Def->GetPseudo() & 2)) { if (!To_Def || !(To_Def->GetPseudo() & 2)) {
sprintf(g->Message, MSG(BAD_SPEC_COLUMN)); sprintf(g->Message, MSG(BAD_SPEC_COLUMN));
return NULL; return NULL;
} // endif Pseudo } // endif Pseudo
// if (!strcmp(name, "FILEID")) if (!stricmp(name, "FILEID"))
colp = new(g) FIDBLK(cp); colp = new(g) FIDBLK(cp);
// else else
// colp = new(g) SIDBLK(cp); colp = new(g) SIDBLK(cp);
} else if (!strcmp(name, "TABID")) { } else if (!stricmp(name, "TABID")) {
colp = new(g) TIDBLK(cp); colp = new(g) TIDBLK(cp);
//} else if (!strcmp(name, "CONID")) { //} else if (!stricmp(name, "CONID")) {
// colp = new(g) CIDBLK(cp); // colp = new(g) CIDBLK(cp);
} else if (!strcmp(name, "ROWID")) { } else if (!stricmp(name, "ROWID")) {
colp = new(g) RIDBLK(cp, false); colp = new(g) RIDBLK(cp, false);
} else if (!strcmp(name, "ROWNUM")) { } else if (!stricmp(name, "ROWNUM")) {
colp = new(g) RIDBLK(cp, true); colp = new(g) RIDBLK(cp, true);
} else { } else {
sprintf(g->Message, MSG(BAD_SPECIAL_COL), name); sprintf(g->Message, MSG(BAD_SPECIAL_COL), name);
......
...@@ -194,6 +194,7 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url) ...@@ -194,6 +194,7 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url)
if (trace) if (trace)
htrc("server: %s Tabname: %s", url, Tabname); htrc("server: %s Tabname: %s", url, Tabname);
Server = url;
return GetServerInfo(g, url); return GetServerInfo(g, url);
} else { } else {
// URL, parse it // URL, parse it
...@@ -216,8 +217,10 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url) ...@@ -216,8 +217,10 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url)
if (!(Hostname = strchr(Username, '@'))) { if (!(Hostname = strchr(Username, '@'))) {
strcpy(g->Message, "No host specified in URL"); strcpy(g->Message, "No host specified in URL");
return true; return true;
} else } else {
*Hostname++ = 0; // End Username *Hostname++ = 0; // End Username
Server = Hostname;
} // endif Hostname
if ((Password = strchr(Username, ':'))) { if ((Password = strchr(Username, ':'))) {
*Password++ = 0; // End username *Password++ = 0; // End username
...@@ -308,6 +311,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -308,6 +311,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Username = Cat->GetStringCatInfo(g, "User", "*"); Username = Cat->GetStringCatInfo(g, "User", "*");
Password = Cat->GetStringCatInfo(g, "Password", NULL); Password = Cat->GetStringCatInfo(g, "Password", NULL);
Portnumber = Cat->GetIntCatInfo("Port", GetDefaultPort()); Portnumber = Cat->GetIntCatInfo("Port", GetDefaultPort());
Server = Hostname;
} else if (ParseURL(g, url)) } else if (ParseURL(g, url))
return TRUE; return TRUE;
...@@ -327,6 +331,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -327,6 +331,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Username = Cat->GetStringCatInfo(g, "User", "*"); Username = Cat->GetStringCatInfo(g, "User", "*");
Password = Cat->GetStringCatInfo(g, "Password", NULL); Password = Cat->GetStringCatInfo(g, "Password", NULL);
Portnumber = Cat->GetIntCatInfo("Port", GetDefaultPort()); Portnumber = Cat->GetIntCatInfo("Port", GetDefaultPort());
Server = Hostname;
} else { } else {
char *locdb = Database; char *locdb = Database;
...@@ -365,13 +370,14 @@ PTDB MYSQLDEF::GetTable(PGLOBAL g, MODE m) ...@@ -365,13 +370,14 @@ PTDB MYSQLDEF::GetTable(PGLOBAL g, MODE m)
TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp) TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
{ {
if (tdp) { if (tdp) {
Host = tdp->GetHostname(); Host = tdp->Hostname;
Database = tdp->GetDatabase(); Database = tdp->Database;
Tabname = tdp->GetTabname(); Tabname = tdp->Tabname;
Srcdef = tdp->GetSrcdef(); Srcdef = tdp->Srcdef;
User = tdp->GetUsername(); User = tdp->Username;
Pwd = tdp->GetPassword(); Pwd = tdp->Password;
Port = tdp->GetPortnumber(); Server = tdp->Server;
Port = tdp->Portnumber;
Isview = tdp->Isview; Isview = tdp->Isview;
Prep = tdp->Bind; Prep = tdp->Bind;
Delayed = tdp->Delayed; Delayed = tdp->Delayed;
...@@ -382,6 +388,7 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp) ...@@ -382,6 +388,7 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
Srcdef = NULL; Srcdef = NULL;
User = NULL; User = NULL;
Pwd = NULL; Pwd = NULL;
Server = NULL;
Port = 0; Port = 0;
Isview = FALSE; Isview = FALSE;
Prep = FALSE; Prep = FALSE;
...@@ -473,10 +480,11 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g) ...@@ -473,10 +480,11 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g)
if (Columns) { if (Columns) {
for (colp = Columns; colp; colp = colp->GetNext()) for (colp = Columns; colp; colp = colp->GetNext())
if (colp->IsSpecial()) { if (!colp->IsSpecial()) {
strcpy(g->Message, MSG(NO_SPEC_COL)); // if (colp->IsSpecial()) {
return TRUE; // strcpy(g->Message, MSG(NO_SPEC_COL));
} else { // return TRUE;
// } else {
if (b) if (b)
strcat(Query, ", "); strcat(Query, ", ");
else else
...@@ -519,10 +527,11 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g) ...@@ -519,10 +527,11 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
return FALSE; // already done return FALSE; // already done
for (colp = Columns; colp; colp = colp->GetNext()) for (colp = Columns; colp; colp = colp->GetNext())
if (colp->IsSpecial()) { if (!colp->IsSpecial()) {
strcpy(g->Message, MSG(NO_SPEC_COL)); // if (colp->IsSpecial()) {
return TRUE; // strcpy(g->Message, MSG(NO_SPEC_COL));
} else { // return TRUE;
// } else {
len += (strlen(colp->GetName()) + 4); len += (strlen(colp->GetName()) + 4);
((PMYCOL)colp)->Rank = Nparm++; ((PMYCOL)colp)->Rank = Nparm++;
} // endif colp } // endif colp
...@@ -1232,7 +1241,7 @@ void MYSQLCOL::ReadColumn(PGLOBAL g) ...@@ -1232,7 +1241,7 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
if (trace) if (trace)
htrc("MySQL ReadColumn: name=%s buf=%s\n", Name, buf); htrc("MySQL ReadColumn: name=%s buf=%s\n", Name, buf);
Value->SetValue_char(buf, Long); Value->SetValue_char(buf, min((unsigned)Long, strlen(buf)));
} else { } else {
if (Nullable) if (Nullable)
Value->SetNull(true); Value->SetNull(true);
......
...@@ -49,6 +49,7 @@ class MYSQLDEF : public TABDEF {/* Logical table description */ ...@@ -49,6 +49,7 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
PSZ Srcdef; /* The source table SQL definition */ PSZ Srcdef; /* The source table SQL definition */
PSZ Username; /* User logon name */ PSZ Username; /* User logon name */
PSZ Password; /* Password logon info */ PSZ Password; /* Password logon info */
PSZ Server; /* PServerID */
int Portnumber; /* MySQL port number (0 = default) */ int Portnumber; /* MySQL port number (0 = default) */
bool Isview; /* TRUE if this table is a MySQL view */ bool Isview; /* TRUE if this table is a MySQL view */
bool Bind; /* Use prepared statement on insert */ bool Bind; /* Use prepared statement on insert */
...@@ -77,6 +78,7 @@ class TDBMYSQL : public TDBASE { ...@@ -77,6 +78,7 @@ class TDBMYSQL : public TDBASE {
virtual void ResetDB(void) {N = 0;} virtual void ResetDB(void) {N = 0;}
virtual int RowNumber(PGLOBAL g, bool b = FALSE); virtual int RowNumber(PGLOBAL g, bool b = FALSE);
virtual bool IsView(void) {return Isview;} virtual bool IsView(void) {return Isview;}
virtual PSZ GetServer(void) {return Server;}
void SetDatabase(LPCSTR db) {Database = (char*)db;} void SetDatabase(LPCSTR db) {Database = (char*)db;}
// Database routines // Database routines
...@@ -110,6 +112,7 @@ class TDBMYSQL : public TDBASE { ...@@ -110,6 +112,7 @@ class TDBMYSQL : public TDBASE {
char *Database; // Database to be used by server char *Database; // Database to be used by server
char *Tabname; // External table name char *Tabname; // External table name
char *Srcdef; // The source table SQL definition char *Srcdef; // The source table SQL definition
char *Server; // The server ID
char *Query; // Points to SQL query char *Query; // Points to SQL query
char *Qbuf; // Used for not prepared insert char *Qbuf; // Used for not prepared insert
bool Fetched; // True when fetch was done bool Fetched; // True when fetch was done
......
...@@ -75,6 +75,7 @@ class TDBODBC : public TDBASE { ...@@ -75,6 +75,7 @@ class TDBODBC : public TDBASE {
virtual void SetFile(PGLOBAL g, PSZ fn); virtual void SetFile(PGLOBAL g, PSZ fn);
virtual void ResetSize(void); virtual void ResetSize(void);
virtual int GetAffectedRows(void) {return AftRows;} virtual int GetAffectedRows(void) {return AftRows;}
virtual PSZ GetServer(void) {return "ODBC";}
// Database routines // Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n); virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
......
...@@ -36,7 +36,9 @@ ...@@ -36,7 +36,9 @@
#include "global.h" #include "global.h"
#include "plgdbsem.h" #include "plgdbsem.h"
#include "reldef.h" #include "reldef.h"
//#include "xobject.h" #if !defined(WIN32)
#include "osutil.h"
#endif // !WIN32
#include "filamtxt.h" #include "filamtxt.h"
#include "tabdos.h" #include "tabdos.h"
#include "tabsys.h" #include "tabsys.h"
...@@ -320,7 +322,11 @@ int TDBINI::DeleteDB(PGLOBAL g, int irc) ...@@ -320,7 +322,11 @@ int TDBINI::DeleteDB(PGLOBAL g, int irc)
break; break;
case RC_FX: case RC_FX:
while (ReadDB(g) == RC_OK) while (ReadDB(g) == RC_OK)
WritePrivateProfileString(Section, NULL, NULL, Ifile); if (!WritePrivateProfileString(Section, NULL, NULL, Ifile)) {
sprintf(g->Message, "Error %d accessing %s",
GetLastError(), Ifile);
return RC_FX;
} // endif
break; break;
default: default:
...@@ -328,7 +334,11 @@ int TDBINI::DeleteDB(PGLOBAL g, int irc) ...@@ -328,7 +334,11 @@ int TDBINI::DeleteDB(PGLOBAL g, int irc)
strcpy(g->Message, MSG(NO_SECTION_NAME)); strcpy(g->Message, MSG(NO_SECTION_NAME));
return RC_FX; return RC_FX;
} else } else
WritePrivateProfileString(Section, NULL, NULL, Ifile); if (!WritePrivateProfileString(Section, NULL, NULL, Ifile)) {
sprintf(g->Message, "Error %d accessing %s",
GetLastError(), Ifile);
return RC_FX;
} // endif rc
} // endswitch irc } // endswitch irc
...@@ -461,13 +471,13 @@ void INICOL::ReadColumn(PGLOBAL g) ...@@ -461,13 +471,13 @@ void INICOL::ReadColumn(PGLOBAL g)
Valbuf[Long] = '\0'; Valbuf[Long] = '\0';
break; break;
default: default:
GetPrivateProfileString(tdbp->Section, Name, "", GetPrivateProfileString(tdbp->Section, Name, "\b",
Valbuf, Long + 1, tdbp->Ifile); Valbuf, Long + 1, tdbp->Ifile);
break; break;
} // endswitch Flag } // endswitch Flag
// Missing keys are interpreted as null values // Missing keys are interpreted as null values
if (!strcmp(Valbuf, "")) { if (!strcmp(Valbuf, "\b")) {
if (Nullable) if (Nullable)
Value->SetNull(true); Value->SetNull(true);
...@@ -485,6 +495,7 @@ void INICOL::ReadColumn(PGLOBAL g) ...@@ -485,6 +495,7 @@ void INICOL::ReadColumn(PGLOBAL g)
void INICOL::WriteColumn(PGLOBAL g) void INICOL::WriteColumn(PGLOBAL g)
{ {
char *p; char *p;
bool rc;
PTDBINI tdbp = (PTDBINI)To_Tdb; PTDBINI tdbp = (PTDBINI)To_Tdb;
if (trace > 1) if (trace > 1)
...@@ -510,11 +521,12 @@ void INICOL::WriteColumn(PGLOBAL g) ...@@ -510,11 +521,12 @@ void INICOL::WriteColumn(PGLOBAL g)
if (tdbp->Mode == MODE_UPDATE) { if (tdbp->Mode == MODE_UPDATE) {
strcpy(g->Message, MSG(NO_SEC_UPDATE)); strcpy(g->Message, MSG(NO_SEC_UPDATE));
longjmp(g->jumper[g->jump_level], 31); longjmp(g->jumper[g->jump_level], 31);
} else { } else if (*p) {
tdbp->Section = p; tdbp->Section = p;
return; } else
} // endif Mode tdbp->Section = NULL;
return;
} else if (!tdbp->Section) { } else if (!tdbp->Section) {
strcpy(g->Message, MSG(SEC_NAME_FIRST)); strcpy(g->Message, MSG(SEC_NAME_FIRST));
longjmp(g->jumper[g->jump_level], 31); longjmp(g->jumper[g->jump_level], 31);
...@@ -523,8 +535,16 @@ void INICOL::WriteColumn(PGLOBAL g) ...@@ -523,8 +535,16 @@ void INICOL::WriteColumn(PGLOBAL g)
/*********************************************************************/ /*********************************************************************/
/* Updating must be done only when not in checking pass. */ /* Updating must be done only when not in checking pass. */
/*********************************************************************/ /*********************************************************************/
if (Status) if (Status) {
WritePrivateProfileString(tdbp->Section, Name, p, tdbp->Ifile); rc = WritePrivateProfileString(tdbp->Section, Name, p, tdbp->Ifile);
if (!rc) {
sprintf(g->Message, "Error %d writing to %s",
GetLastError(), tdbp->Ifile);
longjmp(g->jumper[g->jump_level], 31);
} // endif rc
} // endif Status
} // end of WriteColumn } // end of WriteColumn
...@@ -724,14 +744,21 @@ int TDBXIN::DeleteDB(PGLOBAL g, int irc) ...@@ -724,14 +744,21 @@ int TDBXIN::DeleteDB(PGLOBAL g, int irc)
if (irc == RC_EF) { if (irc == RC_EF) {
} else if (irc == RC_FX) { } else if (irc == RC_FX) {
for (Section = Seclist; *Section; Section += (strlen(Section) + 1)) for (Section = Seclist; *Section; Section += (strlen(Section) + 1))
WritePrivateProfileString(Section, NULL, NULL, Ifile); if (!WritePrivateProfileString(Section, NULL, NULL, Ifile)) {
sprintf(g->Message, "Error %d accessing %s",
GetLastError(), Ifile);
return RC_FX;
} // endif
} else if (Section) { } else if (!Section) {
WritePrivateProfileString(Section, Keycur, NULL, Ifile);
} else {
strcpy(g->Message, MSG(NO_SECTION_NAME)); strcpy(g->Message, MSG(NO_SECTION_NAME));
return RC_FX; return RC_FX;
} // endif's } else
if (!WritePrivateProfileString(Section, Keycur, NULL, Ifile)) {
sprintf(g->Message, "Error %d accessing %s",
GetLastError(), Ifile);
return RC_FX;
} // endif
return RC_OK; return RC_OK;
} // end of DeleteDB } // end of DeleteDB
...@@ -792,6 +819,7 @@ void XINCOL::ReadColumn(PGLOBAL g) ...@@ -792,6 +819,7 @@ void XINCOL::ReadColumn(PGLOBAL g)
void XINCOL::WriteColumn(PGLOBAL g) void XINCOL::WriteColumn(PGLOBAL g)
{ {
char *p; char *p;
bool rc;
PTDBXIN tdbp = (PTDBXIN)To_Tdb; PTDBXIN tdbp = (PTDBXIN)To_Tdb;
if (trace > 1) if (trace > 1)
...@@ -813,20 +841,22 @@ void XINCOL::WriteColumn(PGLOBAL g) ...@@ -813,20 +841,22 @@ void XINCOL::WriteColumn(PGLOBAL g)
if (tdbp->Mode == MODE_UPDATE) { if (tdbp->Mode == MODE_UPDATE) {
strcpy(g->Message, MSG(NO_SEC_UPDATE)); strcpy(g->Message, MSG(NO_SEC_UPDATE));
longjmp(g->jumper[g->jump_level], 31); longjmp(g->jumper[g->jump_level], 31);
} else { } else if (*p) {
tdbp->Section = p; tdbp->Section = p;
return; } else
} // endif Mode tdbp->Section = NULL;
return;
} else if (Flag == 2) { } else if (Flag == 2) {
if (tdbp->Mode == MODE_UPDATE) { if (tdbp->Mode == MODE_UPDATE) {
strcpy(g->Message, MSG(NO_KEY_UPDATE)); strcpy(g->Message, MSG(NO_KEY_UPDATE));
longjmp(g->jumper[g->jump_level], 31); longjmp(g->jumper[g->jump_level], 31);
} else { } else if (*p) {
tdbp->Keycur = p; tdbp->Keycur = p;
return; } else
} // endif Mode tdbp->Keycur = NULL;
return;
} else if (!tdbp->Section || !tdbp->Keycur) { } else if (!tdbp->Section || !tdbp->Keycur) {
strcpy(g->Message, MSG(SEC_KEY_FIRST)); strcpy(g->Message, MSG(SEC_KEY_FIRST));
longjmp(g->jumper[g->jump_level], 31); longjmp(g->jumper[g->jump_level], 31);
...@@ -835,8 +865,16 @@ void XINCOL::WriteColumn(PGLOBAL g) ...@@ -835,8 +865,16 @@ void XINCOL::WriteColumn(PGLOBAL g)
/*********************************************************************/ /*********************************************************************/
/* Updating must be done only when not in checking pass. */ /* Updating must be done only when not in checking pass. */
/*********************************************************************/ /*********************************************************************/
if (Status) if (Status) {
WritePrivateProfileString(tdbp->Section, tdbp->Keycur, p, tdbp->Ifile); rc = WritePrivateProfileString(tdbp->Section, tdbp->Keycur, p, tdbp->Ifile);
if (!rc) {
sprintf(g->Message, "Error %d writing to %s",
GetLastError(), tdbp->Ifile);
longjmp(g->jumper[g->jump_level], 31);
} // endif rc
} // endif Status
} // end of WriteColumn } // end of WriteColumn
......
...@@ -380,7 +380,8 @@ int TDBTBL::GetMaxSize(PGLOBAL g) ...@@ -380,7 +380,8 @@ int TDBTBL::GetMaxSize(PGLOBAL g)
void TDBTBL::ResetDB(void) void TDBTBL::ResetDB(void)
{ {
for (PCOL colp = Columns; colp; colp = colp->GetNext()) for (PCOL colp = Columns; colp; colp = colp->GetNext())
if (colp->GetAmType() == TYPE_AM_TABID) if (colp->GetAmType() == TYPE_AM_TABID ||
colp->GetAmType() == TYPE_AM_SRVID)
colp->COLBLK::Reset(); colp->COLBLK::Reset();
for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext()) for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext())
...@@ -492,7 +493,8 @@ int TDBTBL::ReadDB(PGLOBAL g) ...@@ -492,7 +493,8 @@ int TDBTBL::ReadDB(PGLOBAL g)
// Check and initialize the subtable columns // Check and initialize the subtable columns
for (PCOL cp = Columns; cp; cp = cp->GetNext()) for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID) if (cp->GetAmType() == TYPE_AM_TABID ||
cp->GetAmType() == TYPE_AM_SRVID)
cp->COLBLK::Reset(); cp->COLBLK::Reset();
else if (((PPRXCOL)cp)->Init(g) && !Accept) else if (((PPRXCOL)cp)->Init(g) && !Accept)
return RC_FX; return RC_FX;
......
...@@ -159,7 +159,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, ...@@ -159,7 +159,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/**********************************************************************/ /**********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
buftyp, fldtyp, length, true, true); buftyp, fldtyp, length, false, true);
// Some columns must be renamed // Some columns must be renamed
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
...@@ -226,8 +226,12 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, ...@@ -226,8 +226,12 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
crp->Kdata->SetValue((fp->null_ptr != 0) ? 1 : 0, i); crp->Kdata->SetValue((fp->null_ptr != 0) ? 1 : 0, i);
crp = crp->Next; // Remark crp = crp->Next; // Remark
fld = fp->comment.str;
// For Valgrind
if (fp->comment.length > 0 && (fld = fp->comment.str))
crp->Kdata->SetValue(fld, fp->comment.length, i); crp->Kdata->SetValue(fld, fp->comment.length, i);
else
crp->Kdata->Reset(i);
crp = crp->Next; // New crp = crp->Next; // New
crp->Kdata->SetValue((fmt) ? fmt : (char*) "", i); crp->Kdata->SetValue((fmt) ? fmt : (char*) "", i);
...@@ -364,7 +368,11 @@ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b) ...@@ -364,7 +368,11 @@ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b)
#if defined(MYSQL_SUPPORT) #if defined(MYSQL_SUPPORT)
// Access sub-table via MySQL API // Access sub-table via MySQL API
if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYPRX"))) { if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYPRX"))) {
sprintf(g->Message, "Cannot access %s.%s", db, name); char buf[MAX_STR];
strcpy(buf, g->Message);
sprintf(g->Message, "Error accessing %s.%s: %s", db, name, buf);
hc->tshp = NULL;
goto err; goto err;
} // endif Define } // endif Define
......
...@@ -70,6 +70,7 @@ class DllExport TDBPRX : public TDBASE { ...@@ -70,6 +70,7 @@ class DllExport TDBPRX : public TDBASE {
virtual int GetRecpos(void) {return Tdbp->GetRecpos();} virtual int GetRecpos(void) {return Tdbp->GetRecpos();}
virtual void ResetDB(void) {Tdbp->ResetDB();} virtual void ResetDB(void) {Tdbp->ResetDB();}
virtual int RowNumber(PGLOBAL g, bool b = FALSE); virtual int RowNumber(PGLOBAL g, bool b = FALSE);
virtual PSZ GetServer(void) {return (Tdbp) ? Tdbp->GetServer() : "?";}
// Database routines // Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n); virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
......
...@@ -211,7 +211,7 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info) ...@@ -211,7 +211,7 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info)
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/*********************************************************************/ /*********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
buftyp, fldtyp, length, true, true); buftyp, fldtyp, length, false, true);
if (info) if (info)
return qrp; return qrp;
......
...@@ -592,7 +592,7 @@ void CHRBLK::SetValue(char *sp, uint len, int n) ...@@ -592,7 +592,7 @@ void CHRBLK::SetValue(char *sp, uint len, int n)
#endif #endif
if (sp) if (sp)
memcpy(p, sp, Long); memcpy(p, sp, min((unsigned)Long, len));
if (Blanks) { if (Blanks) {
// Suppress eventual ending zero and right fill with blanks // Suppress eventual ending zero and right fill with blanks
...@@ -712,7 +712,7 @@ void *CHRBLK::GetValPtrEx(int n) ...@@ -712,7 +712,7 @@ void *CHRBLK::GetValPtrEx(int n)
// For VCT blocks we must remove rightmost blanks. // For VCT blocks we must remove rightmost blanks.
char *p = Valp + Long; char *p = Valp + Long;
for (p--; *p == ' ' && p >= Valp; p--) ; for (p--; p >= Valp && *p == ' '; p--) ;
*(++p) = '\0'; *(++p) = '\0';
} // endif Blanks } // endif Blanks
......
...@@ -583,12 +583,12 @@ template <> ...@@ -583,12 +583,12 @@ template <>
void TYPVAL<double>::SetValue_char(char *p, int n) void TYPVAL<double>::SetValue_char(char *p, int n)
{ {
if (p) { if (p) {
char *p2, buf[32]; char buf[32];
for (p2 = p + n; p < p2 && *p == ' '; p++) ; for (; n > 0 && *p == ' '; p++)
n--;
n = min(p2 - p, 31); memcpy(buf, p, min(n, 31));
memcpy(buf, p, n);
buf[n] = '\0'; buf[n] = '\0';
Tval = atof(buf); Tval = atof(buf);
...@@ -875,12 +875,16 @@ TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING) ...@@ -875,12 +875,16 @@ TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING)
TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c) TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
: VALUE(TYPE_STRING) : VALUE(TYPE_STRING)
{ {
assert(Type == TYPE_STRING && (g || s)); assert(Type == TYPE_STRING);
Len = (g) ? n : strlen(s); Len = (g) ? n : strlen(s);
if (g && !s) { if (!s) {
if (g) {
Strp = (char *)PlugSubAlloc(g, NULL, Len + 1); Strp = (char *)PlugSubAlloc(g, NULL, Len + 1);
Strp[Len] = '\0'; Strp[Len] = '\0';
} else
assert(false);
} else } else
Strp = s; Strp = s;
...@@ -912,16 +916,22 @@ bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype) ...@@ -912,16 +916,22 @@ bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype)
void TYPVAL<PSZ>::SetValue_char(char *p, int n) void TYPVAL<PSZ>::SetValue_char(char *p, int n)
{ {
if (p) { if (p) {
n = min(n, Len); if ((n = min(n, Len))) {
strncpy(Strp, p, n); strncpy(Strp, p, n);
for (p = Strp + n - 1; (*p == ' ' || *p == '\0') && p >= Strp; p--) ; // for (p = Strp + n - 1; p >= Strp && (*p == ' ' || *p == '\0'); p--) ;
for (p = Strp + n - 1; p >= Strp; p--)
if (*p && *p != ' ')
break;
*(++p) = '\0'; *(++p) = '\0';
if (trace > 1) if (trace > 1)
htrc(" Setting string to: '%s'\n", Strp); htrc(" Setting string to: '%s'\n", Strp);
} else
Reset();
Null = false; Null = false;
} else { } else {
Reset(); Reset();
......
...@@ -83,6 +83,7 @@ class DllExport VALUE : public BLOCK { ...@@ -83,6 +83,7 @@ class DllExport VALUE : public BLOCK {
virtual void SetPrec(int prec) {Prec = prec;} virtual void SetPrec(int prec) {Prec = prec;}
bool IsNull(void) {return Null;} bool IsNull(void) {return Null;}
void SetNull(bool b) {Null = b;} void SetNull(bool b) {Null = b;}
bool GetNullable(void) {return Nullable;}
void SetNullable(bool b) {Nullable = b;} void SetNullable(bool b) {Nullable = b;}
int GetType(void) {return Type;} int GetType(void) {return Type;}
int GetClen(void) {return Clen;} int GetClen(void) {return Clen;}
......
...@@ -1832,8 +1832,9 @@ int XINDXS::Range(PGLOBAL g, int limit, bool incl) ...@@ -1832,8 +1832,9 @@ int XINDXS::Range(PGLOBAL g, int limit, bool incl)
/*********************************************************************/ /*********************************************************************/
if (xp->GetType() == TYPE_CONST) { if (xp->GetType() == TYPE_CONST) {
kp->Valp->SetValue_pval(xp->GetValue(), !kp->Prefix); kp->Valp->SetValue_pval(xp->GetValue(), !kp->Prefix);
k = FastFind(Nval);
if ((k = FastFind(Nval)) < Num_K) if (k < Num_K || Op != OP_EQ)
if (limit) if (limit)
n = (Mul) ? k : kp->Val_K; n = (Mul) ? k : kp->Val_K;
else else
...@@ -2797,7 +2798,7 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln) ...@@ -2797,7 +2798,7 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
if (Asc) if (Asc)
IsSorted = colp->GetOpt() < 0; IsSorted = colp->GetOpt() < 0;
//MayHaveNulls = colp->HasNulls(); //SetNulls(colp->IsNullable()); for when null columns will be indexable
return false; return false;
} // end of Init } // end of Init
...@@ -2956,6 +2957,11 @@ void KXYCOL::InitBinFind(void *vp) ...@@ -2956,6 +2957,11 @@ void KXYCOL::InitBinFind(void *vp)
void KXYCOL::FillValue(PVAL valp) void KXYCOL::FillValue(PVAL valp)
{ {
valp->SetValue_pvblk(Kblp, Val_K); valp->SetValue_pvblk(Kblp, Val_K);
// Set null when applicable (NIY)
//if (valp->GetNullable())
// valp->SetNull(valp->IsZero());
} // end of FillValue } // end of FillValue
/***********************************************************************/ /***********************************************************************/
......
...@@ -113,6 +113,7 @@ class DllExport TDB: public TBX { // Table Descriptor Block. ...@@ -113,6 +113,7 @@ class DllExport TDB: public TBX { // Table Descriptor Block.
{fprintf(f, "%s AM(%d)\n", m, GetAmType());} {fprintf(f, "%s AM(%d)\n", m, GetAmType());}
virtual void Print(PGLOBAL g, FILE *f, uint n); virtual void Print(PGLOBAL g, FILE *f, uint n);
virtual void Print(PGLOBAL g, char *ps, uint z); virtual void Print(PGLOBAL g, char *ps, uint z);
virtual PSZ GetServer(void) = 0;
// Database pure virtual routines // Database pure virtual routines
virtual PCOL ColDB(PGLOBAL g, PSZ name, int num) = 0; virtual PCOL ColDB(PGLOBAL g, PSZ name, int num) = 0;
...@@ -192,13 +193,14 @@ class DllExport TDBASE : public TDB { ...@@ -192,13 +193,14 @@ class DllExport TDBASE : public TDB {
virtual void ResetSize(void) {MaxSize = -1;} virtual void ResetSize(void) {MaxSize = -1;}
virtual void RestoreNrec(void) {} virtual void RestoreNrec(void) {}
virtual int ResetTableOpt(PGLOBAL g, bool dox); virtual int ResetTableOpt(PGLOBAL g, bool dox);
virtual PSZ GetServer(void) {return "Current";}
// Database routines // Database routines
virtual PCOL ColDB(PGLOBAL g, PSZ name, int num); virtual PCOL ColDB(PGLOBAL g, PSZ name, int num);
virtual PCOL MakeCol(PGLOBAL, PCOLDEF, PCOL, int) virtual PCOL MakeCol(PGLOBAL, PCOLDEF, PCOL, int)
{assert(false); return NULL;} {assert(false); return NULL;}
virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp); virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
virtual PCOL InsertSpcBlk(PGLOBAL g, PCOLUMN cp); virtual PCOL InsertSpcBlk(PGLOBAL g, PCOLDEF cdp);
virtual void MarkDB(PGLOBAL g, PTDB tdb2); virtual void MarkDB(PGLOBAL g, PTDB tdb2);
protected: protected:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment