Commit a392c795 authored by Olivier Bertrand's avatar Olivier Bertrand

Fix and Enhance remote indexing:

- Apply to ODBC tables as well as MYSQL tables
- Fix and enhance the CheckCond routine
  Make ReadKey and MakeKeyWhere handle all conditions
  modified:   storage/connect/.gitattributes
  modified:   storage/connect/.gitignore
  modified:   storage/connect/connect.cc
  modified:   storage/connect/connect.h
  modified:   storage/connect/ha_connect.cc
  modified:   storage/connect/ha_connect.h
  modified:   storage/connect/mycat.cc
  modified:   storage/connect/tabmysql.cpp
  modified:   storage/connect/tabmysql.h
  modified:   storage/connect/tabodbc.cpp
  modified:   storage/connect/tabodbc.h
  modified:   storage/connect/xobject.cpp
  modified:   storage/connect/xobject.h
  modified:   storage/connect/xtable.h

Add some new tests:
  storage/connect/mysql-test/connect/r/endian.result
  storage/connect/mysql-test/connect/r/mysql_index.result
  storage/connect/mysql-test/connect/t/endian.test
  storage/connect/mysql-test/connect/t/mysql_index.test
parent 3a9a3b98
......@@ -11,8 +11,10 @@
# Declare files that will always have LF line endings on checkout.
*.result text eol=lf
mysql-test/connect/std_data/*.txt text eol=lf
mysql-test/connect/std_data/*.dat text eol=lf
# Denote files that should not be modified.
mysql-test/connect/std_data/*.txt binary
mysql-test/connect/std_data/*.dat binary
# Denote all files that are truly binary and should not be modified.
*.png binary
......
......@@ -82,6 +82,10 @@ RelWithDebInfo/
*.vcproj.*
*.vcproj.*.*
*.vcproj.*.*.*
*.vcxproj
*.vcxproj.*
*.vcxproj.*.*
*.vcxproj.*.*.*
# Build results
[Dd]ebug/
......
......@@ -735,17 +735,12 @@ static void SetSwapValue(PVAL valp, char *kp)
/* IndexRead: fetch a record having the index value. */
/***********************************************************************/
RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
const void *key, int len, bool mrr)
const key_range *kr, bool mrr)
{
char *kp= (char*)key;
int n, x;
short lg;
bool rcb;
RCODE rc;
PVAL valp;
PCOL colp;
XXBASE *xbp;
PTDBDOX tdbp;
PTDBDOX tdbp;
if (!ptdb)
return RC_FX;
......@@ -757,13 +752,13 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
return RC_FX;
} else if (x == 2) {
// Remote index
if (ptdb->ReadKey(g, op, key, len))
if (ptdb->ReadKey(g, op, kr))
return RC_FX;
goto rnd;
} else if (x == 3) {
if (key)
((PTDBASE)ptdb)->SetRecpos(g, *(int*)key);
if (kr)
((PTDBASE)ptdb)->SetRecpos(g, *(int*)kr->key);
if (op == OP_SAME)
return RC_NF;
......@@ -790,7 +785,14 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
xbp= (XXBASE*)tdbp->To_Kindex;
if (key) {
if (kr) {
char *kp= (char*)kr->key;
int len= kr->length;
short lg;
bool rcb;
PVAL valp;
PCOL colp;
for (n= 0; n < tdbp->Knum; n++) {
colp= (PCOL)tdbp->To_Key_Col[n];
......@@ -832,10 +834,10 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
kp+= valp->GetClen();
if (len == kp - (char*)key) {
if (len == kp - (char*)kr->key) {
n++;
break;
} else if (len < kp - (char*)key) {
} else if (len < kp - (char*)kr->key) {
strcpy(g->Message, "Key buffer is too small");
return RC_FX;
} // endif len
......
......@@ -36,7 +36,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp);
int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort);
int CntIndexInit(PGLOBAL g, PTDB tdbp, int id, bool sorted);
RCODE CntReadNext(PGLOBAL g, PTDB tdbp);
RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n, bool mrr);
RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const key_range *kr, bool mrr);
RCODE CntWriteRow(PGLOBAL g, PTDB tdbp);
RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp);
RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all);
......@@ -60,7 +60,7 @@ class TDBDOX: public TDBDOS {
friend int MakeIndex(PGLOBAL, PTDB, PIXDEF);
friend int CntCloseTable(PGLOBAL, PTDB, bool, bool);
friend int CntIndexInit(PGLOBAL, PTDB, int, bool);
friend RCODE CntIndexRead(PGLOBAL, PTDB, OPVAL, const void*, int, bool);
friend RCODE CntIndexRead(PGLOBAL, PTDB, OPVAL, const key_range*, bool);
friend RCODE CntDeleteRow(PGLOBAL, PTDB, bool);
friend int CntIndexRange(PGLOBAL, PTDB, const uchar**, uint*,
bool*, key_part_map*);
......
This diff is collapsed.
......@@ -241,11 +241,12 @@ public:
int MakeRecord(char *buf);
int ScanRecord(PGLOBAL g, uchar *buf);
int CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf);
int ReadIndexed(uchar *buf, OPVAL op, const uchar* key= NULL,
uint key_len= 0);
int ReadIndexed(uchar *buf, OPVAL op, const key_range *kr= NULL);
bool IsIndexed(Field *fp);
bool MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
const void *key, int klen);
inline char *Strz(LEX_STRING &ls);
const key_range *kr);
inline char *Strz(LEX_STRING &ls);
key_range start_key;
/** @brief
......@@ -374,7 +375,7 @@ public:
condition stack.
*/
virtual const COND *cond_push(const COND *cond);
PCFIL CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond);
PCFIL CheckCond(PGLOBAL g, PCFIL filp, const Item *cond);
const char *GetValStr(OPVAL vop, bool neg);
PFIL CondFilter(PGLOBAL g, Item *cond);
//PFIL CheckFilter(PGLOBAL g);
......
......@@ -299,13 +299,13 @@ int GetIndexType(TABTYPE type)
xtyp= 1;
break;
case TAB_MYSQL:
// case TAB_ODBC:
case TAB_ODBC:
xtyp= 2;
break;
case TAB_VIR:
xtyp= 3;
break;
case TAB_ODBC:
// case TAB_ODBC:
default:
xtyp= 0;
break;
......
SET time_zone='+00:00';
#
# Testing little endian table
#
CREATE TABLE t1
(
fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) NOT NULL,
birth DATE NOT NULL FIELD_FORMAT='L',
id CHAR(5) NOT NULL FIELD_FORMAT='L2',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='LF',
dept INT(4) NOT NULL FIELD_FORMAT='L2'
) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat';
SELECT * FROM t1;
fig name birth id salary dept
5500 ARCHIBALD 1980-01-25 3789 4380.50 318
123 OLIVER 1953-08-10 23456 3400.68 2158
3123 FOO 2002-07-23 888 0.00 318
INSERT INTO t1 VALUES (5555,'RONALD','1980-02-26','3333',4444.44,555);
SELECT * FROM t1;
fig name birth id salary dept
5500 ARCHIBALD 1980-01-25 3789 4380.50 318
123 OLIVER 1953-08-10 23456 3400.68 2158
3123 FOO 2002-07-23 888 0.00 318
5555 RONALD 1980-02-26 3333 4444.44 555
DROP TABLE t1;
CREATE TABLE t1
(
fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) NOT NULL,
birth DATE NOT NULL,
id CHAR(5) NOT NULL FIELD_FORMAT='S',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
dept INT(4) NOT NULL FIELD_FORMAT='S'
) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat' OPTION_LIST='Endian=Little';
SELECT * FROM t1;
fig name birth id salary dept
5500 ARCHIBALD 1980-01-25 3789 4380.50 318
123 OLIVER 1953-08-10 23456 3400.68 2158
3123 FOO 2002-07-23 888 0.00 318
5555 RONALD 1980-02-26 3333 4444.44 555
#
# Testing big endian table
#
CREATE TABLE t2 (
fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) NOT NULL,
birth DATE NOT NULL FIELD_FORMAT='B',
id CHAR(5) NOT NULL FIELD_FORMAT='BS',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='BF',
dept INT(4) NOT NULL FIELD_FORMAT='B2'
) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.bin';
INSERT INTO t2 SELECT * FROM t1;
SELECT * FROM t2;
fig name birth id salary dept
5500 ARCHIBALD 1980-01-25 3789 4380.50 318
123 OLIVER 1953-08-10 23456 3400.68 2158
3123 FOO 2002-07-23 888 0.00 318
5555 RONALD 1980-02-26 3333 4444.44 555
DROP TABLE t2;
CREATE TABLE t2 (
fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) NOT NULL,
birth DATE NOT NULL,
id CHAR(5) NOT NULL FIELD_FORMAT='S',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
dept INT(4) NOT NULL FIELD_FORMAT='2'
) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.bin' OPTION_LIST='Endian=Big';
SELECT * FROM t2;
fig name birth id salary dept
5500 ARCHIBALD 1980-01-25 3789 4380.50 318
123 OLIVER 1953-08-10 23456 3400.68 2158
3123 FOO 2002-07-23 888 0.00 318
5555 RONALD 1980-02-26 3333 4444.44 555
DROP TABLE t2;
CREATE TABLE t2 (
fig CHAR(4) NOT NULL,
name CHAR(10) NOT NULL,
birth DATE NOT NULL,
id SMALLINT(5) NOT NULL,
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
dept SMALLINT(4) NOT NULL
) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.bin' OPTION_LIST='Endian=Big';
SELECT * FROM t2;
fig name birth id salary dept
5500 ARCHIBALD 1980-01-25 3789 4380.50 318
123 OLIVER 1953-08-10 23456 3400.68 2158
3123 FOO 2002-07-23 888 0.00 318
5555 RONALD 1980-02-26 3333 4444.44 555
DROP TABLE t2;
CREATE TABLE t2 (
fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) NOT NULL,
birth DATE NOT NULL FIELD_FORMAT='B',
id CHAR(5) NOT NULL FIELD_FORMAT='BS',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='BF',
dept SMALLINT(4) NOT NULL FIELD_FORMAT='B'
) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.bin';
SELECT * FROM t2;
fig name birth id salary dept
5500 ARCHIBALD 1980-01-25 3789 4380.50 318
123 OLIVER 1953-08-10 23456 3400.68 2158
3123 FOO 2002-07-23 888 0.00 318
5555 RONALD 1980-02-26 3333 4444.44 555
DROP TABLE t1, t2;
#
# Make remote table
#
CREATE TABLE t1 (
id int(11) NOT NULL,
msg char(100) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO t1 VALUES(1,'Un'),(3,'Trois'),(5,'Cinq');
INSERT INTO t1 VALUES(2,'Two'),(4,'Four'),(6,'Six');
SELECT * FROM t1;
id msg
1 Un
3 Trois
5 Cinq
2 Two
4 Four
6 Six
#
# Make local MYSQL table with indexed id column
#
CREATE TABLE t2 (
id int(11) NOT NULL,
msg char(100) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=CONNECT DEFAULT CHARSET=latin1 TABLE_TYPE=MYSQL TABNAME=t1;
#
# Testing SELECT, etc.
#
SELECT * FROM t2;
id msg
1 Un
3 Trois
5 Cinq
2 Two
4 Four
6 Six
SELECT * FROM t2 WHERE id = 3;
id msg
3 Trois
SELECT * FROM t2 WHERE id IN (2,4);
id msg
2 Two
4 Four
SELECT * FROM t2 WHERE id IN (2,4) AND msg = 'Two';
id msg
2 Two
SELECT * FROM t2 WHERE id > 3;
id msg
5 Cinq
4 Four
6 Six
SELECT * FROM t2 WHERE id >= 3;
id msg
3 Trois
5 Cinq
4 Four
6 Six
SELECT * FROM t2 WHERE id < 3;
id msg
1 Un
2 Two
SELECT * FROM t2 WHERE id < 3 OR id > 4;
id msg
1 Un
2 Two
5 Cinq
6 Six
SELECT * FROM t2 WHERE id <= 3;
id msg
1 Un
2 Two
3 Trois
SELECT * FROM t2 WHERE id BETWEEN 3 AND 5;
id msg
3 Trois
4 Four
5 Cinq
SELECT * FROM t2 WHERE id > 2 AND id < 6;
id msg
3 Trois
4 Four
5 Cinq
SELECT * FROM t2 ORDER BY id;
id msg
1 Un
2 Two
3 Trois
4 Four
5 Cinq
6 Six
UPDATE t2 SET msg = 'Five' WHERE id = 5;
Warnings:
Note 1105 t1: 1 affected rows
SELECT * FROM t2;
id msg
1 Un
3 Trois
5 Five
2 Two
4 Four
6 Six
DELETE FROM t2 WHERE id = 4;
Warnings:
Note 1105 t1: 1 affected rows
SELECT * FROM t2;
id msg
1 Un
3 Trois
5 Five
2 Two
6 Six
DROP TABLE t2;
DROP TABLE t1;
let $MYSQLD_DATADIR= `select @@datadir`;
--copy_file $MTR_SUITE_DIR/std_data/Testbal.dat $MYSQLD_DATADIR/test/Testbal.dat
SET time_zone='+00:00';
--echo #
--echo # Testing little endian table
--echo #
CREATE TABLE t1
(
fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) NOT NULL,
birth DATE NOT NULL FIELD_FORMAT='L',
id CHAR(5) NOT NULL FIELD_FORMAT='L2',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='LF',
dept INT(4) NOT NULL FIELD_FORMAT='L2'
) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat';
SELECT * FROM t1;
INSERT INTO t1 VALUES (5555,'RONALD','1980-02-26','3333',4444.44,555);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1
(
fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) NOT NULL,
birth DATE NOT NULL,
id CHAR(5) NOT NULL FIELD_FORMAT='S',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
dept INT(4) NOT NULL FIELD_FORMAT='S'
) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.dat' OPTION_LIST='Endian=Little';
SELECT * FROM t1;
--echo #
--echo # Testing big endian table
--echo #
CREATE TABLE t2 (
fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) NOT NULL,
birth DATE NOT NULL FIELD_FORMAT='B',
id CHAR(5) NOT NULL FIELD_FORMAT='BS',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='BF',
dept INT(4) NOT NULL FIELD_FORMAT='B2'
) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.bin';
INSERT INTO t2 SELECT * FROM t1;
SELECT * FROM t2;
DROP TABLE t2;
CREATE TABLE t2 (
fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) NOT NULL,
birth DATE NOT NULL,
id CHAR(5) NOT NULL FIELD_FORMAT='S',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
dept INT(4) NOT NULL FIELD_FORMAT='2'
) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.bin' OPTION_LIST='Endian=Big';
SELECT * FROM t2;
DROP TABLE t2;
CREATE TABLE t2 (
fig CHAR(4) NOT NULL,
name CHAR(10) NOT NULL,
birth DATE NOT NULL,
id SMALLINT(5) NOT NULL,
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='F',
dept SMALLINT(4) NOT NULL
) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.bin' OPTION_LIST='Endian=Big';
SELECT * FROM t2;
DROP TABLE t2;
CREATE TABLE t2 (
fig INT(4) NOT NULL FIELD_FORMAT='C',
name CHAR(10) NOT NULL,
birth DATE NOT NULL FIELD_FORMAT='B',
id CHAR(5) NOT NULL FIELD_FORMAT='BS',
salary DOUBLE(9,2) NOT NULL DEFAULT 0.00 FIELD_FORMAT='BF',
dept SMALLINT(4) NOT NULL FIELD_FORMAT='B'
) ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=5 FILE_NAME='Testbal.bin';
SELECT * FROM t2;
DROP TABLE t1, t2;
#
# Clean up
#
--remove_file $MYSQLD_DATADIR/test/Testbal.dat
--remove_file $MYSQLD_DATADIR/test/Testbal.bin
-- source include/not_embedded.inc
#
# TODO: consider a possibility to run this test
# against some remote MySQL server
#
let $PORT= `select @@port`;
--disable_query_log
--replace_result $PORT PORT
--error 0,ER_UNKNOWN_ERROR
--eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='tx1' OPTION_LIST='host=localhost,user=root,port=$PORT'
if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
AND ENGINE='CONNECT'
AND CREATE_OPTIONS LIKE '%`table_type`=MySQL%'`)
{
Skip Need MySQL support;
}
DROP TABLE t1;
--enable_query_log
--echo #
--echo # Make remote table
--echo #
CREATE TABLE t1 (
id int(11) NOT NULL,
msg char(100) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO t1 VALUES(1,'Un'),(3,'Trois'),(5,'Cinq');
INSERT INTO t1 VALUES(2,'Two'),(4,'Four'),(6,'Six');
SELECT * FROM t1;
--echo #
--echo # Make local MYSQL table with indexed id column
--echo #
CREATE TABLE t2 (
id int(11) NOT NULL,
msg char(100) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=CONNECT DEFAULT CHARSET=latin1 TABLE_TYPE=MYSQL TABNAME=t1;
--echo #
--echo # Testing SELECT, etc.
--echo #
SELECT * FROM t2;
SELECT * FROM t2 WHERE id = 3;
SELECT * FROM t2 WHERE id IN (2,4);
SELECT * FROM t2 WHERE id IN (2,4) AND msg = 'Two';
SELECT * FROM t2 WHERE id > 3;
SELECT * FROM t2 WHERE id >= 3;
SELECT * FROM t2 WHERE id < 3;
SELECT * FROM t2 WHERE id < 3 OR id > 4;
SELECT * FROM t2 WHERE id <= 3;
SELECT * FROM t2 WHERE id BETWEEN 3 AND 5;
SELECT * FROM t2 WHERE id > 2 AND id < 6;
SELECT * FROM t2 ORDER BY id;
UPDATE t2 SET msg = 'Five' WHERE id = 5;
SELECT * FROM t2;
DELETE FROM t2 WHERE id = 4;
SELECT * FROM t2;
DROP TABLE t2;
DROP TABLE t1;
......@@ -1054,14 +1054,14 @@ int TDBMYSQL::SendCommand(PGLOBAL g)
/***********************************************************************/
/* Data Base indexed read routine for MYSQL access method. */
/***********************************************************************/
bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr)
{
bool oom;
int oldlen = Query->GetLength();
PHC hc = To_Def->GetHandler();
if (!key || op == OP_NEXT ||
Mode == MODE_UPDATE || Mode == MODE_DELETE) {
if (!key && Mode == MODE_READX) {
if (!(kr || hc->end_range) || op == OP_NEXT ||
Mode == MODE_UPDATE || Mode == MODE_DELETE) {
if (!kr && Mode == MODE_READX) {
// This is a false indexed read
m_Rc = Myc.ExecSQL(g, Query->GetStr());
Mode = MODE_READ;
......@@ -1069,37 +1069,39 @@ bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
} // endif key
return false;
} else if (op == OP_FIRST) {
if (To_CondFil) {
oom = Query->Append(" WHERE ");
if ((oom |= Query->Append(To_CondFil->Body))) {
strcpy(g->Message, "Readkey: Out of memory");
return true;
} // endif oom
} // endif To_Condfil
} else {
if (Myc.m_Res)
Myc.FreeResult();
To_Def->GetHandler()->MakeKeyWhere(g, Query, op, '`', key, len);
if (hc->MakeKeyWhere(g, Query, op, '`', kr))
return true;
if (To_CondFil) {
oom = Query->Append(" AND (");
oom |= Query->Append(To_CondFil->Body);
if (To_CondFil->Idx != hc->active_index) {
To_CondFil->Idx = hc->active_index;
To_CondFil->Body= (char*)PlugSubAlloc(g, NULL, 0);
*To_CondFil->Body= 0;
if ((oom |= Query->Append(')'))) {
strcpy(g->Message, "Readkey: Out of memory");
return true;
} // endif oom
if ((To_CondFil = hc->CheckCond(g, To_CondFil, To_CondFil->Cond)))
PlugSubAlloc(g, NULL, strlen(To_CondFil->Body) + 1);
} // endif active_index
if (To_CondFil)
if (Query->Append(" AND ") || Query->Append(To_CondFil->Body)) {
strcpy(g->Message, "Readkey: Out of memory");
return true;
} // endif Append
} // endif To_Condfil
} // endif To_Condfil
Mode = MODE_READ;
} // endif's op
} // endif's op
if (trace)
htrc("MYSQL ReadKey: Query=%s\n", Query->GetStr());
m_Rc = Myc.ExecSQL(g, Query->GetStr());
m_Rc = Myc.ExecSQL(g, Query->GetStr());
Query->Truncate(oldlen);
return (m_Rc == RC_FX) ? true : false;
} // end of ReadKey
......
......@@ -99,7 +99,7 @@ class TDBMYSQL : public TDBASE {
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
virtual bool ReadKey(PGLOBAL g, OPVAL op, const void *key, int len);
virtual bool ReadKey(PGLOBAL g, OPVAL op, const key_range *kr);
// Specific routines
bool SetColumnRanks(PGLOBAL g);
......
This diff is collapsed.
......@@ -42,7 +42,8 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
int GetOptions(void) {return Options;}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual int Indexable(void) {return 2;}
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
protected:
......@@ -111,15 +112,14 @@ class TDBODBC : public TDBASE {
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
virtual bool ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
{return true;}
virtual bool ReadKey(PGLOBAL g, OPVAL op, const key_range *kr);
protected:
// Internal functions
int Decode(char *utf, char *buf, size_t n);
char *MakeSQL(PGLOBAL g, bool cnt);
char *MakeInsert(PGLOBAL g);
char *MakeCommand(PGLOBAL g);
bool MakeSQL(PGLOBAL g, bool cnt);
bool MakeInsert(PGLOBAL g);
bool MakeCommand(PGLOBAL g);
//bool MakeFilter(PGLOBAL g, bool c);
bool BindParameters(PGLOBAL g);
//char *MakeUpdate(PGLOBAL g);
......@@ -129,14 +129,14 @@ class TDBODBC : public TDBASE {
ODBConn *Ocp; // Points to an ODBC connection class
ODBCCOL *Cnp; // Points to count(*) column
ODBCPARM Ops; // Additional parameters
char *Connect; // Points to connection string
PSTRG Query; // Constructed SQL query
char *Connect; // Points to connection string
char *TableName; // Points to ODBC table name
char *Schema; // Points to ODBC table Schema
char *User; // User connect info
char *Pwd; // Password connect info
char *Catalog; // Points to ODBC table Catalog
char *Srcdef; // The source table SQL definition
char *Query; // Points to SQL statement
char *Count; // Points to count(*) SQL statement
//char *Where; // Points to local where clause
char *Quote; // The identifier quoting character
......
......@@ -290,14 +290,14 @@ bool STRING::Set(char *s, uint n)
} // end of Set
/***********************************************************************/
/* Append a char* to a STRING. */
/* Append a char* to a STRING. */
/***********************************************************************/
bool STRING::Append(const char *s, uint ln)
bool STRING::Append(const char *s, uint ln, bool nq)
{
if (!s)
return false;
uint len = Length + ln + 1;
uint i, len = Length + ln + 1;
if (len > Size) {
char *p = Realloc(len);
......@@ -311,8 +311,22 @@ bool STRING::Append(const char *s, uint ln)
} // endif n
strncpy(Strp + Length, s, ln);
Length = len - 1;
if (nq) {
for (i = 0; i < ln; i++)
switch (s[i]) {
case '\\': Strp[Length++] = '\\'; Strp[Length++] = '\\'; break;
case '\0': Strp[Length++] = '\\'; Strp[Length++] = '0'; break;
case '\'': Strp[Length++] = '\\'; Strp[Length++] = '\''; break;
case '\n': Strp[Length++] = '\\'; Strp[Length++] = 'n'; break;
case '\r': Strp[Length++] = '\\'; Strp[Length++] = 'r'; break;
case '\032': Strp[Length++] = '\\'; Strp[Length++] = 'Z'; break;
default: Strp[Length++] = s[i];
} // endswitch s[i]
} else
for (i = 0; i < ln && s[i]; i++)
Strp[Length++] = s[i];
Strp[Length] = 0;
return false;
} // end of Append
......
......@@ -134,7 +134,7 @@ class DllExport STRING : public BLOCK {
inline void Reset(void) {*Strp = 0;}
bool Set(PSZ s);
bool Set(char *s, uint n);
bool Append(const char *s, uint ln);
bool Append(const char *s, uint ln, bool nq = false);
bool Append(PSZ s);
bool Append(STRING &str);
bool Append(char c);
......
......@@ -19,6 +19,7 @@
#include "m_ctype.h"
typedef class CMD *PCMD;
typedef struct st_key_range key_range;
// Commands executed by XDBC and MYX tables
class CMD : public BLOCK {
......@@ -32,12 +33,24 @@ class CMD : public BLOCK {
}; // end of class CMD
// Condition filter structure
typedef struct _cond_filter {
char *Body;
OPVAL Op;
PCMD Cmds;
} CONDFIL, *PCFIL;
class CONDFIL : public BLOCK {
public:
// Constructor
CONDFIL(const Item *cond, uint idx, AMT type)
{
Cond = cond; Idx = idx; Type = type; Body = NULL; Op = OP_XX; Cmds = NULL;
}
// Members
const Item *Cond;
AMT Type;
uint Idx;
char *Body;
OPVAL Op;
PCMD Cmds;
}; // end of class CONDFIL
typedef class CONDFIL *PCFIL;
typedef class TDBCAT *PTDBCAT;
typedef class CATCOL *PCATCOL;
......@@ -109,7 +122,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
virtual int DeleteDB(PGLOBAL, int) = 0;
virtual void CloseDB(PGLOBAL) = 0;
virtual int CheckWrite(PGLOBAL) {return 0;}
virtual bool ReadKey(PGLOBAL, OPVAL, const void *, int) = 0;
virtual bool ReadKey(PGLOBAL, OPVAL, const key_range *) = 0;
protected:
// Members
......@@ -188,7 +201,7 @@ class DllExport TDBASE : public TDB {
virtual void MarkDB(PGLOBAL g, PTDB tdb2);
virtual int MakeIndex(PGLOBAL g, PIXDEF, bool)
{strcpy(g->Message, "Remote index"); return RC_INFO;}
virtual bool ReadKey(PGLOBAL, OPVAL, const void *, int)
virtual bool ReadKey(PGLOBAL, OPVAL, const key_range *)
{assert(false); return true;}
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