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 @@ ...@@ -11,8 +11,10 @@
# Declare files that will always have LF line endings on checkout. # Declare files that will always have LF line endings on checkout.
*.result text eol=lf *.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. # Denote all files that are truly binary and should not be modified.
*.png binary *.png binary
......
...@@ -82,6 +82,10 @@ RelWithDebInfo/ ...@@ -82,6 +82,10 @@ RelWithDebInfo/
*.vcproj.* *.vcproj.*
*.vcproj.*.* *.vcproj.*.*
*.vcproj.*.*.* *.vcproj.*.*.*
*.vcxproj
*.vcxproj.*
*.vcxproj.*.*
*.vcxproj.*.*.*
# Build results # Build results
[Dd]ebug/ [Dd]ebug/
......
...@@ -735,15 +735,10 @@ static void SetSwapValue(PVAL valp, char *kp) ...@@ -735,15 +735,10 @@ static void SetSwapValue(PVAL valp, char *kp)
/* IndexRead: fetch a record having the index value. */ /* IndexRead: fetch a record having the index value. */
/***********************************************************************/ /***********************************************************************/
RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, 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; int n, x;
short lg;
bool rcb;
RCODE rc; RCODE rc;
PVAL valp;
PCOL colp;
XXBASE *xbp; XXBASE *xbp;
PTDBDOX tdbp; PTDBDOX tdbp;
...@@ -757,13 +752,13 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, ...@@ -757,13 +752,13 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
return RC_FX; return RC_FX;
} else if (x == 2) { } else if (x == 2) {
// Remote index // Remote index
if (ptdb->ReadKey(g, op, key, len)) if (ptdb->ReadKey(g, op, kr))
return RC_FX; return RC_FX;
goto rnd; goto rnd;
} else if (x == 3) { } else if (x == 3) {
if (key) if (kr)
((PTDBASE)ptdb)->SetRecpos(g, *(int*)key); ((PTDBASE)ptdb)->SetRecpos(g, *(int*)kr->key);
if (op == OP_SAME) if (op == OP_SAME)
return RC_NF; return RC_NF;
...@@ -790,7 +785,14 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, ...@@ -790,7 +785,14 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
xbp= (XXBASE*)tdbp->To_Kindex; 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++) { for (n= 0; n < tdbp->Knum; n++) {
colp= (PCOL)tdbp->To_Key_Col[n]; colp= (PCOL)tdbp->To_Key_Col[n];
...@@ -832,10 +834,10 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, ...@@ -832,10 +834,10 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
kp+= valp->GetClen(); kp+= valp->GetClen();
if (len == kp - (char*)key) { if (len == kp - (char*)kr->key) {
n++; n++;
break; break;
} else if (len < kp - (char*)key) { } else if (len < kp - (char*)kr->key) {
strcpy(g->Message, "Key buffer is too small"); strcpy(g->Message, "Key buffer is too small");
return RC_FX; return RC_FX;
} // endif len } // endif len
......
...@@ -36,7 +36,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp); ...@@ -36,7 +36,7 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp);
int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort); int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort);
int CntIndexInit(PGLOBAL g, PTDB tdbp, int id, bool sorted); int CntIndexInit(PGLOBAL g, PTDB tdbp, int id, bool sorted);
RCODE CntReadNext(PGLOBAL g, PTDB tdbp); 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 CntWriteRow(PGLOBAL g, PTDB tdbp);
RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp); RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp);
RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all); RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all);
...@@ -60,7 +60,7 @@ class TDBDOX: public TDBDOS { ...@@ -60,7 +60,7 @@ class TDBDOX: public TDBDOS {
friend int MakeIndex(PGLOBAL, PTDB, PIXDEF); friend int MakeIndex(PGLOBAL, PTDB, PIXDEF);
friend int CntCloseTable(PGLOBAL, PTDB, bool, bool); friend int CntCloseTable(PGLOBAL, PTDB, bool, bool);
friend int CntIndexInit(PGLOBAL, PTDB, int, 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 RCODE CntDeleteRow(PGLOBAL, PTDB, bool);
friend int CntIndexRange(PGLOBAL, PTDB, const uchar**, uint*, friend int CntIndexRange(PGLOBAL, PTDB, const uchar**, uint*,
bool*, key_part_map*); bool*, key_part_map*);
......
This diff is collapsed.
...@@ -241,11 +241,12 @@ public: ...@@ -241,11 +241,12 @@ public:
int MakeRecord(char *buf); int MakeRecord(char *buf);
int ScanRecord(PGLOBAL g, uchar *buf); int ScanRecord(PGLOBAL g, uchar *buf);
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 key_range *kr= NULL);
uint key_len= 0); bool IsIndexed(Field *fp);
bool MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q, bool MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
const void *key, int klen); const key_range *kr);
inline char *Strz(LEX_STRING &ls); inline char *Strz(LEX_STRING &ls);
key_range start_key;
/** @brief /** @brief
...@@ -374,7 +375,7 @@ public: ...@@ -374,7 +375,7 @@ public:
condition stack. condition stack.
*/ */
virtual const COND *cond_push(const COND *cond); 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); const char *GetValStr(OPVAL vop, bool neg);
PFIL CondFilter(PGLOBAL g, Item *cond); PFIL CondFilter(PGLOBAL g, Item *cond);
//PFIL CheckFilter(PGLOBAL g); //PFIL CheckFilter(PGLOBAL g);
......
...@@ -299,13 +299,13 @@ int GetIndexType(TABTYPE type) ...@@ -299,13 +299,13 @@ int GetIndexType(TABTYPE type)
xtyp= 1; xtyp= 1;
break; break;
case TAB_MYSQL: case TAB_MYSQL:
// case TAB_ODBC: case TAB_ODBC:
xtyp= 2; xtyp= 2;
break; break;
case TAB_VIR: case TAB_VIR:
xtyp= 3; xtyp= 3;
break; break;
case TAB_ODBC: // case TAB_ODBC:
default: default:
xtyp= 0; xtyp= 0;
break; 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) ...@@ -1054,14 +1054,14 @@ int TDBMYSQL::SendCommand(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
/* Data Base indexed read routine for MYSQL access method. */ /* 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(); int oldlen = Query->GetLength();
PHC hc = To_Def->GetHandler();
if (!key || op == OP_NEXT || if (!(kr || hc->end_range) || op == OP_NEXT ||
Mode == MODE_UPDATE || Mode == MODE_DELETE) { Mode == MODE_UPDATE || Mode == MODE_DELETE) {
if (!key && Mode == MODE_READX) { if (!kr && Mode == MODE_READX) {
// This is a false indexed read // This is a false indexed read
m_Rc = Myc.ExecSQL(g, Query->GetStr()); m_Rc = Myc.ExecSQL(g, Query->GetStr());
Mode = MODE_READ; Mode = MODE_READ;
...@@ -1069,36 +1069,38 @@ bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len) ...@@ -1069,36 +1069,38 @@ bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
} // endif key } // endif key
return false; 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 { } else {
if (Myc.m_Res) if (Myc.m_Res)
Myc.FreeResult(); Myc.FreeResult();
To_Def->GetHandler()->MakeKeyWhere(g, Query, op, '`', key, len); if (hc->MakeKeyWhere(g, Query, op, '`', kr))
return true;
if (To_CondFil) { if (To_CondFil) {
oom = Query->Append(" AND ("); if (To_CondFil->Idx != hc->active_index) {
oom |= Query->Append(To_CondFil->Body); To_CondFil->Idx = hc->active_index;
To_CondFil->Body= (char*)PlugSubAlloc(g, NULL, 0);
*To_CondFil->Body= 0;
if ((To_CondFil = hc->CheckCond(g, To_CondFil, To_CondFil->Cond)))
PlugSubAlloc(g, NULL, strlen(To_CondFil->Body) + 1);
} // endif active_index
if ((oom |= Query->Append(')'))) { if (To_CondFil)
if (Query->Append(" AND ") || Query->Append(To_CondFil->Body)) {
strcpy(g->Message, "Readkey: Out of memory"); strcpy(g->Message, "Readkey: Out of memory");
return true; return true;
} // endif oom } // 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); Query->Truncate(oldlen);
return (m_Rc == RC_FX) ? true : false; return (m_Rc == RC_FX) ? true : false;
......
...@@ -99,7 +99,7 @@ class TDBMYSQL : public TDBASE { ...@@ -99,7 +99,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); virtual bool ReadKey(PGLOBAL g, OPVAL op, const key_range *kr);
// Specific routines // Specific routines
bool SetColumnRanks(PGLOBAL g); bool SetColumnRanks(PGLOBAL g);
......
This diff is collapsed.
...@@ -42,6 +42,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */ ...@@ -42,6 +42,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
int GetOptions(void) {return Options;} int GetOptions(void) {return Options;}
// 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);
...@@ -111,15 +112,14 @@ class TDBODBC : public TDBASE { ...@@ -111,15 +112,14 @@ 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) virtual bool ReadKey(PGLOBAL g, OPVAL op, const key_range *kr);
{return true;}
protected: protected:
// Internal functions // Internal functions
int Decode(char *utf, char *buf, size_t n); int Decode(char *utf, char *buf, size_t n);
char *MakeSQL(PGLOBAL g, bool cnt); bool MakeSQL(PGLOBAL g, bool cnt);
char *MakeInsert(PGLOBAL g); bool MakeInsert(PGLOBAL g);
char *MakeCommand(PGLOBAL g); bool MakeCommand(PGLOBAL g);
//bool MakeFilter(PGLOBAL g, bool c); //bool MakeFilter(PGLOBAL g, bool c);
bool BindParameters(PGLOBAL g); bool BindParameters(PGLOBAL g);
//char *MakeUpdate(PGLOBAL g); //char *MakeUpdate(PGLOBAL g);
...@@ -129,6 +129,7 @@ class TDBODBC : public TDBASE { ...@@ -129,6 +129,7 @@ class TDBODBC : public TDBASE {
ODBConn *Ocp; // Points to an ODBC connection class ODBConn *Ocp; // Points to an ODBC connection class
ODBCCOL *Cnp; // Points to count(*) column ODBCCOL *Cnp; // Points to count(*) column
ODBCPARM Ops; // Additional parameters ODBCPARM Ops; // Additional parameters
PSTRG Query; // Constructed SQL query
char *Connect; // Points to connection string char *Connect; // Points to connection string
char *TableName; // Points to ODBC table name char *TableName; // Points to ODBC table name
char *Schema; // Points to ODBC table Schema char *Schema; // Points to ODBC table Schema
...@@ -136,7 +137,6 @@ class TDBODBC : public TDBASE { ...@@ -136,7 +137,6 @@ class TDBODBC : public TDBASE {
char *Pwd; // Password connect info char *Pwd; // Password connect info
char *Catalog; // Points to ODBC table Catalog char *Catalog; // Points to ODBC table Catalog
char *Srcdef; // The source table SQL definition char *Srcdef; // The source table SQL definition
char *Query; // Points to SQL statement
char *Count; // Points to count(*) SQL statement char *Count; // Points to count(*) SQL statement
//char *Where; // Points to local where clause //char *Where; // Points to local where clause
char *Quote; // The identifier quoting character char *Quote; // The identifier quoting character
......
...@@ -292,12 +292,12 @@ bool STRING::Set(char *s, uint n) ...@@ -292,12 +292,12 @@ bool STRING::Set(char *s, uint n)
/***********************************************************************/ /***********************************************************************/
/* 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) if (!s)
return false; return false;
uint len = Length + ln + 1; uint i, len = Length + ln + 1;
if (len > Size) { if (len > Size) {
char *p = Realloc(len); char *p = Realloc(len);
...@@ -311,8 +311,22 @@ bool STRING::Append(const char *s, uint ln) ...@@ -311,8 +311,22 @@ bool STRING::Append(const char *s, uint ln)
} // endif n } // endif n
strncpy(Strp + Length, s, ln); if (nq) {
Length = len - 1; 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; Strp[Length] = 0;
return false; return false;
} // end of Append } // end of Append
......
...@@ -134,7 +134,7 @@ class DllExport STRING : public BLOCK { ...@@ -134,7 +134,7 @@ class DllExport STRING : public BLOCK {
inline void Reset(void) {*Strp = 0;} inline void Reset(void) {*Strp = 0;}
bool Set(PSZ s); bool Set(PSZ s);
bool Set(char *s, uint n); 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(PSZ s);
bool Append(STRING &str); bool Append(STRING &str);
bool Append(char c); bool Append(char c);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "m_ctype.h" #include "m_ctype.h"
typedef class CMD *PCMD; typedef class CMD *PCMD;
typedef struct st_key_range key_range;
// Commands executed by XDBC and MYX tables // Commands executed by XDBC and MYX tables
class CMD : public BLOCK { class CMD : public BLOCK {
...@@ -32,12 +33,24 @@ class CMD : public BLOCK { ...@@ -32,12 +33,24 @@ class CMD : public BLOCK {
}; // end of class CMD }; // end of class CMD
// Condition filter structure // Condition filter structure
typedef struct _cond_filter { 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; char *Body;
OPVAL Op; OPVAL Op;
PCMD Cmds; PCMD Cmds;
} CONDFIL, *PCFIL; }; // end of class CONDFIL
typedef class CONDFIL *PCFIL;
typedef class TDBCAT *PTDBCAT; typedef class TDBCAT *PTDBCAT;
typedef class CATCOL *PCATCOL; typedef class CATCOL *PCATCOL;
...@@ -109,7 +122,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block. ...@@ -109,7 +122,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) {return 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: protected:
// Members // Members
...@@ -188,7 +201,7 @@ class DllExport TDBASE : public TDB { ...@@ -188,7 +201,7 @@ class DllExport TDBASE : public TDB {
virtual void MarkDB(PGLOBAL g, PTDB tdb2); virtual void MarkDB(PGLOBAL g, PTDB tdb2);
virtual int MakeIndex(PGLOBAL g, PIXDEF, bool) virtual int MakeIndex(PGLOBAL g, PIXDEF, bool)
{strcpy(g->Message, "Remote index"); return RC_INFO;} {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;} {assert(false); return true;}
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