Fix a bug in the LIKE query optimization. (Found by coverage testing.) (CVS 6137)

FossilOrigin-Name: fe90e9116b6e1e25cf3119d2777a8e9c135153ce
This commit is contained in:
drh 2009-01-07 18:24:03 +00:00
parent f70c1fee96
commit 5bd98aef66
5 changed files with 143 additions and 31 deletions

View File

@ -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

View File

@ -1 +1 @@
ccc9c211a285fd4da68b69e15594f080371be522
fe90e9116b6e1e25cf3119d2777a8e9c135153ce

View File

@ -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

View File

@ -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;

View File

@ -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