Fix a bug in the LIKE query optimization. (Found by coverage testing.) (CVS 6137)
FossilOrigin-Name: fe90e9116b6e1e25cf3119d2777a8e9c135153ce
This commit is contained in:
parent
f70c1fee96
commit
5bd98aef66
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
||||
C Make\sthe\ssame\schange\sas\s(6121)\s(accidentally\sreverted).\sAlso\senhance\stest_journal.c\sto\scatch\sthis\skind\sof\sbug.\s(CVS\s6136)
|
||||
D 2009-01-07T18:08:49
|
||||
C Fix\sa\sbug\sin\sthe\sLIKE\squery\soptimization.\s\s(Found\sby\scoverage\stesting.)\s(CVS\s6137)
|
||||
D 2009-01-07T18:24:03
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in 05461a9b5803d5ad10c79f989801e9fd2cc3e592
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -163,7 +163,7 @@ F src/sqliteLimit.h 651a2757ba55aeba1da167786b6a8c3404433940
|
||||
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
||||
F src/table.c 23db1e5f27c03160987c122a078b4bb51ef0b2f8
|
||||
F src/tclsqlite.c 4415e1033bd3e92b05a6a9cde911ee4de3b82df9
|
||||
F src/test1.c b193b8b80617bdb8297b25a87d00ee8d5a125d0d
|
||||
F src/test1.c 058a52226e6c47e92b9df14654c5a1b41009e0fe
|
||||
F src/test2.c 724095fc69cb54b018aaa4463a56836c0b53a17a
|
||||
F src/test3.c 88a246b56b824275300e6c899634fbac1dc94b14
|
||||
F src/test4.c f79ab52d27ff49b784b631a42e2ccd52cfd5c84c
|
||||
@ -207,7 +207,7 @@ F src/vdbeblob.c b0dcebfafedcf9c0addc7901ad98f6f986c08935
|
||||
F src/vdbemem.c 19f94b504d3da44b31aef200fa6c8e07862de2e8
|
||||
F src/vtab.c e39e011d7443a8d574b1b9cde207a35522e6df43
|
||||
F src/walker.c 488c2660e13224ff70c0c82761118efb547f8f0d
|
||||
F src/where.c ad9d49f77b9c70adc38cf1b829c870f30a9afe04
|
||||
F src/where.c 9852acecfeee1f8650fdec46f20e2368e6c159a0
|
||||
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/alias.test 597662c5d777a122f9a3df0047ea5c5bd383a911
|
||||
@ -415,7 +415,7 @@ F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19
|
||||
F test/jrnlmode.test 513b495624bfe54da24ae1208125421d8167953d
|
||||
F test/lastinsert.test 474d519c68cb79d07ecae56a763aa7f322c72f51
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/like.test fef924922828d5a2a5bff80b9bdd9ff57a1ca500
|
||||
F test/like.test e55cbbc21729f577b74ec333c753a2d6eda03f9f
|
||||
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
|
||||
F test/limit.test 2db7b3b34fb925b8e847d583d2eb67531d0ce67e
|
||||
F test/loadext.test 18db29c081380fdedcfbd8c633847712059ae104
|
||||
@ -693,7 +693,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
P 0f57011e3b21fa5f6a819ce5a7fd8d44ea70679f
|
||||
R cebd5b9f713ddcff8e7a2c71139b4a4c
|
||||
U danielk1977
|
||||
Z 62d24e33d87117ee5ab38c9511e98dd8
|
||||
P ccc9c211a285fd4da68b69e15594f080371be522
|
||||
R 3780da89c170554b5cb3d38edab02288
|
||||
U drh
|
||||
Z 9ba15e241fcdcbb40439174ae087420f
|
||||
|
@ -1 +1 @@
|
||||
ccc9c211a285fd4da68b69e15594f080371be522
|
||||
fe90e9116b6e1e25cf3119d2777a8e9c135153ce
|
50
src/test1.c
50
src/test1.c
@ -13,7 +13,7 @@
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test1.c,v 1.338 2008/12/17 15:18:18 danielk1977 Exp $
|
||||
** $Id: test1.c,v 1.339 2009/01/07 18:24:03 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
@ -333,6 +333,53 @@ static int test_exec_printf(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_exec_hex DB HEX
|
||||
**
|
||||
** Invoke the sqlite3_exec() on a string that is obtained by translating
|
||||
** HEX into ASCII. Most characters are translated as is. %HH becomes
|
||||
** a hex character.
|
||||
*/
|
||||
static int test_exec_hex(
|
||||
void *NotUsed,
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int argc, /* Number of arguments */
|
||||
char **argv /* Text of each argument */
|
||||
){
|
||||
sqlite3 *db;
|
||||
Tcl_DString str;
|
||||
int rc, i, j;
|
||||
char *zErr = 0;
|
||||
char *zHex;
|
||||
char zSql[500];
|
||||
char zBuf[30];
|
||||
if( argc!=3 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||||
" DB HEX", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
||||
zHex = argv[2];
|
||||
for(i=j=0; i<sizeof(zSql) && zHex[j]; i++, j++){
|
||||
if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){
|
||||
zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]);
|
||||
j += 2;
|
||||
}else{
|
||||
zSql[i] = zHex[j];
|
||||
}
|
||||
}
|
||||
zSql[i] = 0;
|
||||
Tcl_DStringInit(&str);
|
||||
rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
|
||||
sprintf(zBuf, "%d", rc);
|
||||
Tcl_AppendElement(interp, zBuf);
|
||||
Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
|
||||
Tcl_DStringFree(&str);
|
||||
if( zErr ) sqlite3_free(zErr);
|
||||
if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: db_enter DB
|
||||
** db_leave DB
|
||||
@ -4758,6 +4805,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_snprintf_int", (Tcl_CmdProc*)test_snprintf_int },
|
||||
{ "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
|
||||
{ "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
|
||||
{ "sqlite3_exec_hex", (Tcl_CmdProc*)test_exec_hex },
|
||||
{ "sqlite3_exec", (Tcl_CmdProc*)test_exec },
|
||||
{ "sqlite3_exec_nr", (Tcl_CmdProc*)test_exec_nr },
|
||||
#ifndef SQLITE_OMIT_GET_TABLE
|
||||
|
34
src/where.c
34
src/where.c
@ -16,7 +16,7 @@
|
||||
** so is applicable. Because this module is responsible for selecting
|
||||
** indices, you might also think of this module as the "query optimizer".
|
||||
**
|
||||
** $Id: where.c,v 1.357 2009/01/06 14:19:37 drh Exp $
|
||||
** $Id: where.c,v 1.358 2009/01/07 18:24:03 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -264,20 +264,16 @@ static void whereClauseClear(WhereClause*);
|
||||
** Deallocate all memory associated with a WhereOrInfo object.
|
||||
*/
|
||||
static void whereOrInfoDelete(sqlite3 *db, WhereOrInfo *p){
|
||||
if( p ){
|
||||
whereClauseClear(&p->wc);
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
whereClauseClear(&p->wc);
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
|
||||
/*
|
||||
** Deallocate all memory associated with a WhereAndInfo object.
|
||||
*/
|
||||
static void whereAndInfoDelete(sqlite3 *db, WhereAndInfo *p){
|
||||
if( p ){
|
||||
whereClauseClear(&p->wc);
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
whereClauseClear(&p->wc);
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -623,13 +619,14 @@ static int isLikeOrGlob(
|
||||
int *pisComplete, /* True if the only wildcard is % in the last character */
|
||||
int *pnoCase /* True if uppercase is equivalent to lowercase */
|
||||
){
|
||||
const char *z;
|
||||
Expr *pRight, *pLeft;
|
||||
ExprList *pList;
|
||||
int c, cnt;
|
||||
char wc[3];
|
||||
CollSeq *pColl;
|
||||
sqlite3 *db = pParse->db;
|
||||
const char *z; /* String on RHS of LIKE operator */
|
||||
Expr *pRight, *pLeft; /* Right and left size of LIKE operator */
|
||||
ExprList *pList; /* List of operands to the LIKE operator */
|
||||
int c; /* One character in z[] */
|
||||
int cnt; /* Number of non-wildcard prefix characters */
|
||||
char wc[3]; /* Wildcard characters */
|
||||
CollSeq *pColl; /* Collating sequence for LHS */
|
||||
sqlite3 *db = pParse->db; /* Database connection */
|
||||
|
||||
if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){
|
||||
return 0;
|
||||
@ -639,8 +636,7 @@ static int isLikeOrGlob(
|
||||
#endif
|
||||
pList = pExpr->pList;
|
||||
pRight = pList->a[0].pExpr;
|
||||
if( pRight->op!=TK_STRING
|
||||
&& (pRight->op!=TK_REGISTER || pRight->iColumn!=TK_STRING) ){
|
||||
if( pRight->op!=TK_STRING ){
|
||||
return 0;
|
||||
}
|
||||
pLeft = pList->a[1].pExpr;
|
||||
@ -663,7 +659,7 @@ static int isLikeOrGlob(
|
||||
if( z ){
|
||||
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ cnt++; }
|
||||
}
|
||||
if( cnt==0 || 255==(u8)z[cnt] ){
|
||||
if( cnt==0 || 255==(u8)z[cnt-1] ){
|
||||
return 0;
|
||||
}
|
||||
*pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;
|
||||
|
@ -13,7 +13,7 @@
|
||||
# in particular the optimizations that occur to help those operators
|
||||
# run faster.
|
||||
#
|
||||
# $Id: like.test,v 1.10 2008/09/09 12:31:34 drh Exp $
|
||||
# $Id: like.test,v 1.11 2009/01/07 18:24:03 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -551,4 +551,72 @@ do_test like-8.4 {
|
||||
} {1 abcdef 1 ghijkl 1 mnopqr 2 abcdef 2 ghijkl 2 mnopqr}
|
||||
|
||||
|
||||
ifcapable like_opt {
|
||||
# Evaluate SQL. Return the result set followed by the
|
||||
# and the number of full-scan steps.
|
||||
#
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
proc count_steps {sql} {
|
||||
set r [db eval $sql]
|
||||
lappend r scan [db status step] sort [db status sort]
|
||||
}
|
||||
do_test like-9.1 {
|
||||
count_steps {
|
||||
SELECT x FROM t2 WHERE x LIKE 'x%'
|
||||
}
|
||||
} {xyz scan 0 sort 0}
|
||||
do_test like-9.2 {
|
||||
count_steps {
|
||||
SELECT x FROM t2 WHERE x LIKE '_y%'
|
||||
}
|
||||
} {xyz scan 19 sort 0}
|
||||
do_test like-9.3.1 {
|
||||
set res [sqlite3_exec_hex db {
|
||||
SELECT x FROM t2 WHERE x LIKE '%78%25'
|
||||
}]
|
||||
} {0 {x xyz}}
|
||||
ifcapable explain {
|
||||
do_test like-9.3.2 {
|
||||
set res [sqlite3_exec_hex db {
|
||||
EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%78%25'
|
||||
}]
|
||||
regexp {INDEX i2} $res
|
||||
} {1}
|
||||
}
|
||||
do_test like-9.4.1 {
|
||||
sqlite3_exec_hex db {INSERT INTO t2 VALUES('%ffhello')}
|
||||
set res [sqlite3_exec_hex db {
|
||||
SELECT substr(x,2) AS x FROM t2 WHERE +x LIKE '%ff%25'
|
||||
}]
|
||||
} {0 {x hello}}
|
||||
do_test like-9.4.2 {
|
||||
set res [sqlite3_exec_hex db {
|
||||
SELECT substr(x,2) AS x FROM t2 WHERE x LIKE '%ff%25'
|
||||
}]
|
||||
} {0 {x hello}}
|
||||
ifcapable explain {
|
||||
do_test like-9.4.3 {
|
||||
set res [sqlite3_exec_hex db {
|
||||
EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%ff%25'
|
||||
}]
|
||||
regexp {INDEX i2} $res
|
||||
} {0}
|
||||
}
|
||||
do_test like-9.5.1 {
|
||||
set res [sqlite3_exec_hex db {
|
||||
SELECT x FROM t2 WHERE x LIKE '%fe%25'
|
||||
}]
|
||||
} {0 {}}
|
||||
ifcapable explain {
|
||||
do_test like-9.5.2 {
|
||||
set res [sqlite3_exec_hex db {
|
||||
EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%fe%25'
|
||||
}]
|
||||
regexp {INDEX i2} $res
|
||||
} {1}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
Loading…
Reference in New Issue
Block a user