Commit 187e4169 authored by Olivier Bertrand's avatar Olivier Bertrand

- Implement "remote" index (similar to FEDERATED ones) for MYSQL tables.

  Not yet done for ODBC tables.
modified:
  storage/connect/connect.cc
  storage/connect/ha_connect.cc
  storage/connect/ha_connect.h
  storage/connect/mycat.cc
  storage/connect/plgdbsem.h
  storage/connect/reldef.h
  storage/connect/tabdos.h
  storage/connect/tabmysql.cpp
  storage/connect/tabmysql.h
  storage/connect/tabodbc.cpp
  storage/connect/tabodbc.h
  storage/connect/xindex.cpp
  storage/connect/xtable.h

- Return error in "info" on Cardinality error.
modified:
  storage/connect/ha_connect.cc
parent 213ecbbb
...@@ -587,7 +587,7 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp) ...@@ -587,7 +587,7 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp)
tbxp= (TDBDOX*)tdbp; tbxp= (TDBDOX*)tdbp;
tbxp->SetKindex(NULL); tbxp->SetKindex(NULL);
tbxp->To_Key_Col= NULL; tbxp->To_Key_Col= NULL;
rc= tbxp->ResetTableOpt(g, ((PTDBASE)tdbp)->GetDef()->Indexable()); rc= tbxp->ResetTableOpt(g, ((PTDBASE)tdbp)->GetDef()->Indexable() == 1);
err: err:
if (trace > 1) if (trace > 1)
...@@ -709,7 +709,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, ...@@ -709,7 +709,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
const void *key, int len) const void *key, int len)
{ {
char *kp= (char*)key; char *kp= (char*)key;
int n; int n, x;
short lg; short lg;
bool rcb; bool rcb;
RCODE rc; RCODE rc;
...@@ -720,9 +720,18 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, ...@@ -720,9 +720,18 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
if (!ptdb) if (!ptdb)
return RC_FX; return RC_FX;
if (!((PTDBASE)ptdb)->GetDef()->Indexable()) { else
x= ((PTDBASE)ptdb)->GetDef()->Indexable();
if (!x) {
sprintf(g->Message, "CntIndexRead: Table %s is not indexable", ptdb->GetName()); sprintf(g->Message, "CntIndexRead: Table %s is not indexable", ptdb->GetName());
return RC_FX; return RC_FX;
} else if (x == 2) {
// Remote index
if (ptdb->ReadKey(g, op, key, len))
return RC_FX;
goto rnd;
} else } else
tdbp= (PTDBDOX)ptdb; tdbp= (PTDBDOX)ptdb;
...@@ -782,8 +791,9 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, ...@@ -782,8 +791,9 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
xbp->SetOp(op); xbp->SetOp(op);
xbp->SetNth(0); xbp->SetNth(0);
if ((rc= (RCODE)tdbp->ReadDB(g)) == RC_OK) rnd:
rc= EvalColumns(g, tdbp); if ((rc= (RCODE)ptdb->ReadDB(g)) == RC_OK)
rc= EvalColumns(g, ptdb);
return rc; return rc;
} // end of CntIndexRead } // end of CntIndexRead
...@@ -795,7 +805,7 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len, ...@@ -795,7 +805,7 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
bool *incl, key_part_map *kmap) bool *incl, key_part_map *kmap)
{ {
const uchar *p, *kp; const uchar *p, *kp;
int i, n, k[2]; int i, n, x, k[2];
short lg; short lg;
bool b, rcb; bool b, rcb;
PVAL valp; PVAL valp;
...@@ -805,10 +815,16 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len, ...@@ -805,10 +815,16 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
if (!ptdb) if (!ptdb)
return -1; return -1;
else if (!((PTDBASE)ptdb)->GetDef()->Indexable()) {
x= ((PTDBASE)ptdb)->GetDef()->Indexable();
if (!x) {
sprintf(g->Message, "CntIndexRange: Table %s is not indexable", ptdb->GetName()); sprintf(g->Message, "CntIndexRange: Table %s is not indexable", ptdb->GetName());
DBUG_PRINT("Range", ("%s", g->Message)); DBUG_PRINT("Range", ("%s", g->Message));
return -1; return -1;
} else if (x == 2) {
// Remote index
return 2;
} else } else
tdbp= (PTDBDOX)ptdb; tdbp= (PTDBDOX)ptdb;
......
...@@ -1218,9 +1218,10 @@ PTDB ha_connect::GetTDB(PGLOBAL g) ...@@ -1218,9 +1218,10 @@ PTDB ha_connect::GetTDB(PGLOBAL g)
if (!xp->CheckQuery(valid_query_id) && tdbp if (!xp->CheckQuery(valid_query_id) && tdbp
&& !stricmp(tdbp->GetName(), table_name) && !stricmp(tdbp->GetName(), table_name)
&& (tdbp->GetMode() == xmod && (tdbp->GetMode() == xmod
|| (tdbp->GetMode() == MODE_READ && xmod == MODE_READX)
|| tdbp->GetAmType() == TYPE_AM_XML)) { || tdbp->GetAmType() == TYPE_AM_XML)) {
tp= tdbp; tp= tdbp;
// tp->SetMode(xmod); tp->SetMode(xmod);
} else if ((tp= CntGetTDB(g, table_name, xmod, this))) { } else if ((tp= CntGetTDB(g, table_name, xmod, this))) {
valid_query_id= xp->last_query_id; valid_query_id= xp->last_query_id;
tp->SetMode(xmod); tp->SetMode(xmod);
...@@ -1613,6 +1614,88 @@ int ha_connect::CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf) ...@@ -1613,6 +1614,88 @@ int ha_connect::CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf)
} // end of dummy CheckRecord } // end of dummy CheckRecord
/***********************************************************************/
/* Return the where clause for remote indexed read. */
/***********************************************************************/
bool ha_connect::MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
const void *key, int klen)
{
const uchar *ptr;
uint rem, len, stlen; //, prtlen;
bool nq, b= false;
Field *fp;
KEY *kfp;
KEY_PART_INFO *kpart;
if (active_index == MAX_KEY)
return 0;
strcat(qry, " WHERE (");
kfp= &table->key_info[active_index];
rem= kfp->user_defined_key_parts,
len= klen,
ptr= (const uchar *)key;
for (kpart= kfp->key_part; rem; rem--, kpart++) {
fp= kpart->field;
stlen= kpart->store_length;
// prtlen= min(stlen, len);
nq= fp->str_needs_quotes();
if (b)
strcat(qry, " AND ");
else
b= true;
strcat(strncat(strcat(qry, q), fp->field_name, strlen(fp->field_name)), q);
switch (op) {
case OP_EQ:
case OP_GT:
case OP_GE:
strcat(qry, GetValStr(op, false));
break;
default:
strcat(qry, " ??? ");
} // endwitch op
if (nq)
strcat(qry, "'");
if (kpart->key_part_flag & HA_VAR_LENGTH_PART) {
String varchar;
uint var_length= uint2korr(ptr);
varchar.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH,
var_length, &my_charset_bin);
strncat(qry, varchar.ptr(), varchar.length());
} else {
char strbuff[MAX_FIELD_WIDTH];
String str(strbuff, sizeof(strbuff), kpart->field->charset()), *res;
res= fp->val_str(&str, ptr);
strncat(qry, res->ptr(), res->length());
} // endif flag
if (nq)
strcat(qry, "'");
if (stlen >= len)
break;
len-= stlen;
/* For nullable columns, null-byte is already skipped before, that is
ptr was incremented by 1. Since store_length still counts null-byte,
we need to subtract 1 from store_length. */
ptr+= stlen - test(kpart->null_bit);
} // endfor kpart
strcat(qry, ")");
return false;
} // end of MakeKeyWhere
/***********************************************************************/ /***********************************************************************/
/* Return the string representing an operator. */ /* Return the string representing an operator. */
/***********************************************************************/ /***********************************************************************/
...@@ -1738,7 +1821,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond) ...@@ -1738,7 +1821,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
} else { } else {
p1= p2 + strlen(p2); p1= p2 + strlen(p2);
strcpy(p1, GetValStr(vop, FALSE)); strcpy(p1, GetValStr(vop, false));
p2= p1 + strlen(p1); p2= p1 + strlen(p1);
} // endif CheckCond } // endif CheckCond
...@@ -2092,7 +2175,9 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -2092,7 +2175,9 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT* check_opt)
dup->Check |= CHK_OPT; dup->Check |= CHK_OPT;
if (tdbp) { if (tdbp) {
if (!((PTDBASE)tdbp)->GetDef()->Indexable()) { if (((PTDBASE)tdbp)->GetDef()->Indexable() == 2) {
// Nothing to do for remote index
} else if (!((PTDBASE)tdbp)->GetDef()->Indexable()) {
sprintf(g->Message, "optimize: Table %s is not indexable", tdbp->GetName()); sprintf(g->Message, "optimize: Table %s is not indexable", tdbp->GetName());
my_message(ER_INDEX_REBUILD, g->Message, MYF(0)); my_message(ER_INDEX_REBUILD, g->Message, MYF(0));
rc= HA_ERR_UNSUPPORTED; rc= HA_ERR_UNSUPPORTED;
...@@ -2306,6 +2391,18 @@ int ha_connect::index_init(uint idx, bool sorted) ...@@ -2306,6 +2391,18 @@ int ha_connect::index_init(uint idx, bool sorted)
if (xtrace) if (xtrace)
htrc("index_init: this=%p idx=%u sorted=%d\n", this, idx, sorted); htrc("index_init: this=%p idx=%u sorted=%d\n", this, idx, sorted);
if (GetIndexType(GetRealType()) == 2) {
// This is a remote index
xmod= MODE_READX;
if (!(rc= rnd_init(0))) {
active_index= idx;
indexing= 2; // TO DO: mul?
} //endif rc
DBUG_RETURN(rc);
} // endif index type
if ((rc= rnd_init(0))) if ((rc= rnd_init(0)))
return rc; return rc;
...@@ -2821,12 +2918,16 @@ int ha_connect::info(uint flag) ...@@ -2821,12 +2918,16 @@ int ha_connect::info(uint flag)
if (cat && table) if (cat && table)
cat->SetDataPath(g, table->s->db.str); cat->SetDataPath(g, table->s->db.str);
else else
return HA_ERR_INTERNAL_ERROR; // Should never happen DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen
tdbp= GetTDB(g); tdbp= GetTDB(g);
} // endif tdbp } // endif tdbp
valid_info= CntInfo(g, tdbp, &xinfo); valid_info= CntInfo(g, tdbp, &xinfo);
if (((signed)xinfo.records) < 0)
DBUG_RETURN(HA_ERR_INITIALIZATION); // Error in Cardinality
} // endif valid_info } // endif valid_info
if (flag & HA_STATUS_VARIABLE) { if (flag & HA_STATUS_VARIABLE) {
...@@ -3086,7 +3187,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd, ...@@ -3086,7 +3187,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
newmode= MODE_ALTER; newmode= MODE_ALTER;
break; break;
default: default:
htrc("Unsupported sql_command=%d", thd_sql_command(thd)); htrc("Unsupported sql_command=%d\n", thd_sql_command(thd));
strcpy(g->Message, "CONNECT Unsupported command"); strcpy(g->Message, "CONNECT Unsupported command");
my_message(ER_NOT_ALLOWED_COMMAND, g->Message, MYF(0)); my_message(ER_NOT_ALLOWED_COMMAND, g->Message, MYF(0));
newmode= MODE_ERROR; newmode= MODE_ERROR;
...@@ -3131,7 +3232,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd, ...@@ -3131,7 +3232,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
newmode= MODE_ALTER; newmode= MODE_ALTER;
break; break;
default: default:
htrc("Unsupported sql_command=%d", thd_sql_command(thd)); htrc("Unsupported sql_command=%d\n", thd_sql_command(thd));
strcpy(g->Message, "CONNECT Unsupported command"); strcpy(g->Message, "CONNECT Unsupported command");
my_message(ER_NOT_ALLOWED_COMMAND, g->Message, MYF(0)); my_message(ER_NOT_ALLOWED_COMMAND, g->Message, MYF(0));
newmode= MODE_ERROR; newmode= MODE_ERROR;
...@@ -3255,8 +3356,7 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -3255,8 +3356,7 @@ int ha_connect::external_lock(THD *thd, int lock_type)
// DBUG_RETURN(HA_ERR_INTERNAL_ERROR); causes assert error // DBUG_RETURN(HA_ERR_INTERNAL_ERROR); causes assert error
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
DBUG_RETURN(0); DBUG_RETURN(0);
} // endif Indexable } else if (((PTDBASE)tdbp)->GetDef()->Indexable() == 1) {
bool oldsep= ((PCHK)g->Xchk)->oldsep; bool oldsep= ((PCHK)g->Xchk)->oldsep;
bool newsep= ((PCHK)g->Xchk)->newsep; bool newsep= ((PCHK)g->Xchk)->newsep;
PTDBDOS tdp= (PTDBDOS)tdbp; PTDBDOS tdp= (PTDBDOS)tdbp;
...@@ -3337,6 +3437,8 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -3337,6 +3437,8 @@ int ha_connect::external_lock(THD *thd, int lock_type)
rc= 0; rc= 0;
} // endif MakeIndex } // endif MakeIndex
} // endif indexable
} // endif Tdbp } // endif Tdbp
} // endelse Xchk } // endelse Xchk
...@@ -4831,7 +4933,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -4831,7 +4933,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
sprintf(g->Message, "Table type %s is not indexable", options->type); sprintf(g->Message, "Table type %s is not indexable", options->type);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
rc= HA_ERR_UNSUPPORTED; rc= HA_ERR_UNSUPPORTED;
} // endif Indexable } // endif index type
} // endif xdp } // endif xdp
...@@ -4840,62 +4942,6 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -4840,62 +4942,6 @@ int ha_connect::create(const char *name, TABLE *table_arg,
my_message(ER_UNKNOWN_ERROR, my_message(ER_UNKNOWN_ERROR,
"CONNECT index modification should be in-place", MYF(0)); "CONNECT index modification should be in-place", MYF(0));
DBUG_RETURN(HA_ERR_UNSUPPORTED); DBUG_RETURN(HA_ERR_UNSUPPORTED);
#if 0
PIXDEF xdp= GetIndexInfo();
PCHK xcp= (PCHK)g->Xchk;
if (xdp) {
if (!IsTypeIndexable(type)) {
g->Xchk= NULL;
sprintf(g->Message, "Table type %s is not indexable", options->type);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
rc= HA_ERR_INTERNAL_ERROR;
} else {
xcp->newpix= xdp;
xcp->newsep= GetBooleanOption("Sepindex", false);
} // endif Indexable
} else if (!xcp->oldpix)
g->Xchk= NULL;
if (xtrace && g->Xchk)
htrc("oldsep=%d newsep=%d oldpix=%p newpix=%p\n",
xcp->oldsep, xcp->newsep, xcp->oldpix, xcp->newpix);
// if (g->Xchk &&
// (sqlcom != SQLCOM_CREATE_INDEX && sqlcom != SQLCOM_DROP_INDEX)) {
if (g->Xchk) {
PIXDEF xp1, xp2;
bool b= false; // true if index changes
if (xcp->oldsep == xcp->newsep) {
for (xp1= xcp->newpix, xp2= xcp->oldpix;
xp1 || xp2;
xp1= xp1->Next, xp2= xp2->Next)
if (!xp1 || !xp2 || !IsSameIndex(xp1, xp2)) {
b= true;
break;
} // endif xp1
} else
b= true;
if (!b)
g->Xchk= NULL;
#if 0
if (b) {
// CONNECT does not support indexing via ALTER TABLE
my_message(ER_UNKNOWN_ERROR,
"CONNECT does not support index modification via ALTER TABLE",
MYF(0));
DBUG_RETURN(HA_ERR_UNSUPPORTED);
} // endif b
#endif // 0
} // endif Xchk
#endif // 0
} // endif Xchk } // endif Xchk
table= st; table= st;
......
...@@ -198,6 +198,8 @@ public: ...@@ -198,6 +198,8 @@ public:
int CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf); int CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf);
int ReadIndexed(uchar *buf, OPVAL op, const uchar* key= NULL, int ReadIndexed(uchar *buf, OPVAL op, const uchar* key= NULL,
uint key_len= 0); uint key_len= 0);
bool MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
const void *key, int klen);
/** @brief /** @brief
The name that will be used for display purposes. The name that will be used for display purposes.
......
...@@ -275,9 +275,10 @@ int GetIndexType(TABTYPE type) ...@@ -275,9 +275,10 @@ int GetIndexType(TABTYPE type)
xtyp= 1; xtyp= 1;
break; break;
case TAB_MYSQL: case TAB_MYSQL:
// case TAB_ODBC:
xtyp= 2;
break;
case TAB_ODBC: case TAB_ODBC:
// xtyp= 2; Remote indexes not implemented yet
// break;
default: default:
xtyp= 0; xtyp= 0;
break; break;
......
...@@ -158,6 +158,7 @@ enum ALGMOD {AMOD_AUTO = 0, /* PLG chooses best algorithm */ ...@@ -158,6 +158,7 @@ enum ALGMOD {AMOD_AUTO = 0, /* PLG chooses best algorithm */
enum MODE {MODE_ERROR = -1, /* Invalid mode */ enum MODE {MODE_ERROR = -1, /* Invalid mode */
MODE_ANY = 0, /* Unspecified mode */ MODE_ANY = 0, /* Unspecified mode */
MODE_READ = 10, /* Input/Output mode */ MODE_READ = 10, /* Input/Output mode */
MODE_READX = 11, /* Read indexed 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 */
MODE_INSERT = 40, /* Input/Output mode */ MODE_INSERT = 40, /* Input/Output mode */
......
...@@ -31,6 +31,7 @@ class DllExport RELDEF : public BLOCK { // Relation definition block ...@@ -31,6 +31,7 @@ class DllExport RELDEF : public BLOCK { // Relation definition block
PSZ GetName(void) {return Name;} PSZ GetName(void) {return Name;}
PSZ GetDB(void) {return (PSZ)Database;} PSZ GetDB(void) {return (PSZ)Database;}
PCOLDEF GetCols(void) {return To_Cols;} PCOLDEF GetCols(void) {return To_Cols;}
PHC GetHandler(void) {return Hc;}
void SetCols(PCOLDEF pcd) {To_Cols = pcd;} void SetCols(PCOLDEF pcd) {To_Cols = pcd;}
PCATLG GetCat(void) {return Cat;} PCATLG GetCat(void) {return Cat;}
virtual const char *GetType(void) = 0; virtual const char *GetType(void) = 0;
...@@ -45,7 +46,7 @@ class DllExport RELDEF : public BLOCK { // Relation definition block ...@@ -45,7 +46,7 @@ class DllExport RELDEF : public BLOCK { // Relation definition block
int GetSizeCatInfo(PSZ what, PSZ sdef); int GetSizeCatInfo(PSZ what, PSZ sdef);
int GetCharCatInfo(PSZ what, PSZ sdef, char *buf, int size); int GetCharCatInfo(PSZ what, PSZ sdef, char *buf, int size);
char *GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef); char *GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef);
virtual bool Indexable(void) {return false;} virtual int Indexable(void) {return 0;}
virtual bool Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am) = 0; virtual bool Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am) = 0;
virtual PTDB GetTable(PGLOBAL g, MODE mode) = 0; virtual PTDB GetTable(PGLOBAL g, MODE mode) = 0;
......
...@@ -49,7 +49,7 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */ ...@@ -49,7 +49,7 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
int GetEnding(void) {return Ending;} int GetEnding(void) {return Ending;}
// Methods // Methods
virtual bool Indexable(void) {return Compressed != 1;} virtual int Indexable(void) {return (Compressed != 1) ? 1 : 0;}
virtual bool DeleteIndexFile(PGLOBAL g, PIXDEF pxdf); virtual bool DeleteIndexFile(PGLOBAL g, PIXDEF pxdf);
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff); virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode); virtual PTDB GetTable(PGLOBAL g, MODE mode);
...@@ -149,7 +149,7 @@ class DllExport TDBDOS : public TDBASE { ...@@ -149,7 +149,7 @@ class DllExport TDBDOS : public TDBASE {
virtual int EstimatedLength(PGLOBAL g); virtual int EstimatedLength(PGLOBAL g);
// Optimization routines // Optimization routines
int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add); virtual int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add);
protected: protected:
// Members // Members
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#include "tabmysql.h" #include "tabmysql.h"
#include "valblk.h" #include "valblk.h"
#include "tabutil.h" #include "tabutil.h"
#include "ha_connect.h"
#if defined(_CONSOLE) #if defined(_CONSOLE)
void PrintResult(PGLOBAL, PSEM, PQRYRES); void PrintResult(PGLOBAL, PSEM, PQRYRES);
...@@ -481,16 +482,16 @@ PCOL TDBMYSQL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) ...@@ -481,16 +482,16 @@ PCOL TDBMYSQL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/* Note: when implementing EOM filtering, column only used in local */ /* Note: when implementing EOM filtering, column only used in local */
/* filter should be removed from column list. */ /* filter should be removed from column list. */
/***********************************************************************/ /***********************************************************************/
bool TDBMYSQL::MakeSelect(PGLOBAL g) bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx)
{ {
char *tk = "`"; char *tk = "`";
int rank = 0; int len = 0, rank = 0;
bool b = FALSE; bool b = false;
PCOL colp; PCOL colp;
//PDBUSER dup = PlgGetUser(g); //PDBUSER dup = PlgGetUser(g);
if (Query) if (Query)
return FALSE; // already done return false; // already done
if (Srcdef) { if (Srcdef) {
Query = Srcdef; Query = Srcdef;
...@@ -506,12 +507,12 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g) ...@@ -506,12 +507,12 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g)
if (!colp->IsSpecial()) { if (!colp->IsSpecial()) {
// if (colp->IsSpecial()) { // if (colp->IsSpecial()) {
// strcpy(g->Message, MSG(NO_SPEC_COL)); // strcpy(g->Message, MSG(NO_SPEC_COL));
// return TRUE; // return true;
// } else { // } else {
if (b) if (b)
strcat(Query, ", "); strcat(Query, ", ");
else else
b = TRUE; b = true;
strcat(strcat(strcat(Query, tk), colp->GetName()), tk); strcat(strcat(strcat(Query, tk), colp->GetName()), tk);
((PMYCOL)colp)->Rank = rank++; ((PMYCOL)colp)->Rank = rank++;
...@@ -526,16 +527,24 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g) ...@@ -526,16 +527,24 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g)
} // endif ncol } // endif ncol
strcat(strcat(strcat(strcat(Query, " FROM "), tk), Tabname), tk); strcat(strcat(strcat(strcat(Query, " FROM "), tk), Tabname), tk);
len = strlen(Query);
if (To_CondFil) if (To_CondFil) {
if (!mx) {
strcat(strcat(Query, " WHERE "), To_CondFil->Body); strcat(strcat(Query, " WHERE "), To_CondFil->Body);
len = strlen(Query) + 1;
} else
len += (strlen(To_CondFil->Body) + 256);
} else
len += (mx ? 256 : 1);
if (trace) if (trace)
htrc("Query=%s\n", Query); htrc("Query=%s\n", Query);
// Now we know how much to suballocate // Now we know how much to suballocate
PlugSubAlloc(g, NULL, strlen(Query) + 1); PlugSubAlloc(g, NULL, len);
return FALSE; return false;
} // end of MakeSelect } // end of MakeSelect
/***********************************************************************/ /***********************************************************************/
...@@ -833,9 +842,9 @@ bool TDBMYSQL::OpenDB(PGLOBAL g) ...@@ -833,9 +842,9 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
/*********************************************************************/ /*********************************************************************/
/* Allocate whatever is used for getting results. */ /* Allocate whatever is used for getting results. */
/*********************************************************************/ /*********************************************************************/
if (Mode == MODE_READ) { if (Mode == MODE_READ || Mode == MODE_READX) {
if (!MakeSelect(g)) MakeSelect(g, Mode == MODE_READX);
m_Rc = Myc.ExecSQL(g, Query); m_Rc = (Mode == MODE_READ) ? Myc.ExecSQL(g, Query) : RC_OK;
#if 0 #if 0
if (!Myc.m_Res || !Myc.m_Fields) { if (!Myc.m_Res || !Myc.m_Fields) {
...@@ -994,6 +1003,36 @@ int TDBMYSQL::SendCommand(PGLOBAL g) ...@@ -994,6 +1003,36 @@ int TDBMYSQL::SendCommand(PGLOBAL g)
} // end of SendCommand } // end of SendCommand
/***********************************************************************/
/* Data Base indexed read routine for MYSQL access method. */
/***********************************************************************/
bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
{
int oldlen = strlen(Query);
bool rc;
if (op == OP_NEXT)
return false;
else if (op == OP_FIRST) {
if (To_CondFil)
strcat(strcat(Query, " WHERE "), To_CondFil->Body);
} else {
if (Myc.m_Res)
Myc.FreeResult();
rc = To_Def->GetHandler()->MakeKeyWhere(g, Query, op, "`", key, len);
if (To_CondFil)
strcat(strcat(strcat(Query, " AND ("), To_CondFil->Body), ")");
} // endif's op
m_Rc = Myc.ExecSQL(g, Query);
Query[oldlen] = 0;
return false;
} // end of ReadKey
/***********************************************************************/ /***********************************************************************/
/* Data Base read routine for MYSQL access method. */ /* Data Base read routine for MYSQL access method. */
/***********************************************************************/ /***********************************************************************/
...@@ -1451,7 +1490,7 @@ bool TDBMYEXC::OpenDB(PGLOBAL g) ...@@ -1451,7 +1490,7 @@ bool TDBMYEXC::OpenDB(PGLOBAL g)
Use = USE_OPEN; // Do it now in case we are recursively called Use = USE_OPEN; // Do it now in case we are recursively called
if (Mode != MODE_READ) { if (Mode != MODE_READ && Mode != MODE_READX) {
strcpy(g->Message, "No INSERT/DELETE/UPDATE of MYSQL EXEC tables"); strcpy(g->Message, "No INSERT/DELETE/UPDATE of MYSQL EXEC tables");
return true; return true;
} // endif Mode } // endif Mode
......
...@@ -39,6 +39,7 @@ class MYSQLDEF : public TABDEF {/* Logical table description */ ...@@ -39,6 +39,7 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
inline int GetPortnumber(void) {return Portnumber;} inline int GetPortnumber(void) {return Portnumber;}
// Methods // Methods
virtual int Indexable(void) {return 2;}
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff); virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m); virtual PTDB GetTable(PGLOBAL g, MODE m);
bool ParseURL(PGLOBAL g, char *url, bool b = true); bool ParseURL(PGLOBAL g, char *url, bool b = true);
...@@ -96,6 +97,7 @@ class TDBMYSQL : public TDBASE { ...@@ -96,6 +97,7 @@ class TDBMYSQL : public TDBASE {
virtual int WriteDB(PGLOBAL g); virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc); virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g); virtual void CloseDB(PGLOBAL g);
virtual bool ReadKey(PGLOBAL g, OPVAL op, const void *key, int len);
// Specific routines // Specific routines
bool SetColumnRanks(PGLOBAL g); bool SetColumnRanks(PGLOBAL g);
...@@ -104,7 +106,7 @@ class TDBMYSQL : public TDBASE { ...@@ -104,7 +106,7 @@ class TDBMYSQL : public TDBASE {
protected: protected:
// Internal functions // Internal functions
bool MakeSelect(PGLOBAL g); bool MakeSelect(PGLOBAL g, bool mx);
bool MakeInsert(PGLOBAL g); bool MakeInsert(PGLOBAL g);
int BindColumns(PGLOBAL g); int BindColumns(PGLOBAL g);
int MakeCommand(PGLOBAL g); int MakeCommand(PGLOBAL g);
......
...@@ -752,7 +752,7 @@ bool TDBODBC::OpenDB(PGLOBAL g) ...@@ -752,7 +752,7 @@ bool TDBODBC::OpenDB(PGLOBAL g)
/*********************************************************************/ /*********************************************************************/
/* Make the command and allocate whatever is used for getting results. */ /* Make the command and allocate whatever is used for getting results. */
/*********************************************************************/ /*********************************************************************/
if (Mode == MODE_READ) { if (Mode == MODE_READ || Mode == MODE_READX) {
if ((Query = MakeSQL(g, false))) { if ((Query = MakeSQL(g, false))) {
for (PODBCCOL colp = (PODBCCOL)Columns; colp; for (PODBCCOL colp = (PODBCCOL)Columns; colp;
colp = (PODBCCOL)colp->GetNext()) colp = (PODBCCOL)colp->GetNext())
...@@ -1315,7 +1315,7 @@ bool TDBXDBC::OpenDB(PGLOBAL g) ...@@ -1315,7 +1315,7 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
Use = USE_OPEN; // Do it now in case we are recursively called Use = USE_OPEN; // Do it now in case we are recursively called
if (Mode != MODE_READ) { if (Mode != MODE_READ && Mode != MODE_READX) {
strcpy(g->Message, "No INSERT/DELETE/UPDATE of XDBC tables"); strcpy(g->Message, "No INSERT/DELETE/UPDATE of XDBC tables");
return true; return true;
} // endif Mode } // endif Mode
......
...@@ -90,6 +90,7 @@ class TDBODBC : public TDBASE { ...@@ -90,6 +90,7 @@ class TDBODBC : public TDBASE {
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";} virtual PSZ GetServer(void) {return "ODBC";}
virtual int Indexable(void) {return 2;}
// 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);
...@@ -100,6 +101,8 @@ class TDBODBC : public TDBASE { ...@@ -100,6 +101,8 @@ class TDBODBC : public TDBASE {
virtual int WriteDB(PGLOBAL g); virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc); virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g); virtual void CloseDB(PGLOBAL g);
virtual bool ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
{return true;}
protected: protected:
// Internal functions // Internal functions
......
...@@ -79,7 +79,7 @@ int PlgMakeIndex(PGLOBAL g, PSZ name, PIXDEF pxdf, bool add) ...@@ -79,7 +79,7 @@ int PlgMakeIndex(PGLOBAL g, PSZ name, PIXDEF pxdf, bool add)
{ {
int rc; int rc;
PTABLE tablep; PTABLE tablep;
PTDBDOS tdbp; PTDBASE tdbp;
PCATLG cat = PlgGetCatalog(g, true); PCATLG cat = PlgGetCatalog(g, true);
/*********************************************************************/ /*********************************************************************/
...@@ -87,13 +87,13 @@ int PlgMakeIndex(PGLOBAL g, PSZ name, PIXDEF pxdf, bool add) ...@@ -87,13 +87,13 @@ int PlgMakeIndex(PGLOBAL g, PSZ name, PIXDEF pxdf, bool add)
/*********************************************************************/ /*********************************************************************/
tablep = new(g) XTAB(name); tablep = new(g) XTAB(name);
if (!(tdbp = (PTDBDOS)cat->GetTable(g, tablep))) if (!(tdbp = (PTDBASE)cat->GetTable(g, tablep)))
rc = RC_NF; rc = RC_NF;
else if (!tdbp->GetDef()->Indexable()) { else if (!tdbp->GetDef()->Indexable()) {
sprintf(g->Message, MSG(TABLE_NO_INDEX), name); sprintf(g->Message, MSG(TABLE_NO_INDEX), name);
rc = RC_NF; rc = RC_NF;
} else if ((rc = tdbp->MakeIndex(g, pxdf, add)) == RC_INFO) } else if ((rc = tdbp->MakeIndex(g, pxdf, add)) == RC_INFO)
rc = RC_OK; // No index rc = RC_OK; // No or remote index
return rc; return rc;
} // end of PlgMakeIndex } // end of PlgMakeIndex
......
...@@ -107,6 +107,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block. ...@@ -107,6 +107,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
virtual int DeleteDB(PGLOBAL, int) = 0; virtual int DeleteDB(PGLOBAL, int) = 0;
virtual void CloseDB(PGLOBAL) = 0; virtual void CloseDB(PGLOBAL) = 0;
virtual int CheckWrite(PGLOBAL g) {return 0;} virtual int CheckWrite(PGLOBAL g) {return 0;}
virtual bool ReadKey(PGLOBAL, OPVAL, const void *, int) = 0;
protected: protected:
// Members // Members
...@@ -176,6 +177,11 @@ class DllExport TDBASE : public TDB { ...@@ -176,6 +177,11 @@ class DllExport TDBASE : public TDB {
virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp); virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
virtual PCOL InsertSpcBlk(PGLOBAL g, PCOLDEF cdp); virtual PCOL InsertSpcBlk(PGLOBAL g, PCOLDEF cdp);
virtual void MarkDB(PGLOBAL g, PTDB tdb2); virtual void MarkDB(PGLOBAL g, PTDB tdb2);
virtual int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add)
{strcpy(g->Message, "Remote index"); return RC_INFO;}
virtual bool ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
{assert(false); return true;}
protected: protected:
// Members // Members
......
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