From 1eb6eeb829c126d0be49a3049be24a9b589b7d83 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 14 Aug 2015 20:08:13 +0000 Subject: [PATCH] Updated testing of cursor-hints. Remove the test_cursorhint.c file and associated logic in the core and do tests based purely on the newly enhanced EXPLAIN output. FossilOrigin-Name: bf383e665a191a4f33a540d1240960a922e22813 --- main.mk | 1 - manifest | 19 +++-- manifest.uuid | 2 +- src/tclsqlite.c | 3 - src/test_cursorhint.c | 162 ------------------------------------------ src/vdbe.c | 4 -- test/cursorhint.test | 133 +++++++++++++++++++++++----------- 7 files changed, 102 insertions(+), 222 deletions(-) delete mode 100644 src/test_cursorhint.c diff --git a/main.mk b/main.mk index 44f4bbf094..f3bdae6a83 100644 --- a/main.mk +++ b/main.mk @@ -262,7 +262,6 @@ TESTSRC = \ $(TOP)/src/test_blob.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ - $(TOP)/src/test_cursorhint.c \ $(TOP)/src/test_demovfs.c \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_fs.c \ diff --git a/manifest b/manifest index a0e60280dd..794278256f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\scursor\shint\smechanism\sso\sthat\sit\sdoes\sthe\sright\sthing\sfor\sindexed\nlookups. -D 2015-08-14T18:50:04.420 +C Updated\stesting\sof\scursor-hints.\s\sRemove\sthe\stest_cursorhint.c\sfile\sand\nassociated\slogic\sin\sthe\score\sand\sdo\stests\sbased\spurely\son\sthe\snewly\senhanced\nEXPLAIN\soutput. +D 2015-08-14T20:08:13.528 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2fc9ca6bf5949d415801c007ed3004a4bdb7c380 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -256,7 +256,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 389329247c56b23329a9285155106cd6b6ebad42 +F main.mk 73167b34b0e67c0be32c1da2d988a376851c9ab1 F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 @@ -344,7 +344,7 @@ F src/sqliteInt.h cbd6d166c5f8aa17e4be463ccefef41cd1d40286 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e -F src/tclsqlite.c 72f4dd747d5604a508bbb6935817d3afe5ffd6e2 +F src/tclsqlite.c d9439b6a910985b7fff43ba6756bcef00de22649 F src/test1.c d339ae9b9baf9221c657c9628c9061d88bd831f6 F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622 @@ -360,7 +360,6 @@ F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_config.c fb2e5d354d9a077f5fbb261652eff4787deb104f -F src/test_cursorhint.c bba837177d1693037f5c83dcb443cf453ee656ed F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f @@ -399,7 +398,7 @@ F src/update.c 487747b328b7216bb7f6af0695d6937d5c9e605f F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c bc9dd64b5db544218b871b66243871c202b2781f F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 74561c2d15895f930f08e4216d454efaaaf530c4 +F src/vdbe.c 882cac44eb4f53d18e31c79fc1741d400016f867 F src/vdbe.h 529bb4a7bedcd28dccba5abb3927e3c5cb70a832 F src/vdbeInt.h 7258d75fc2dad0bccdef14d7d8d2fd50fd1bf2d2 F src/vdbeapi.c adabbd66eb2e3a10f3998485ee0be7e326d06ee4 @@ -561,7 +560,7 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2 F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8 F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47 -F test/cursorhint.test e55ad8c466327ffb3511b60007102bca22314d0a +F test/cursorhint.test c3844bed3eec3506b38b98ab5f0ca22a4ab9ecb4 F test/date.test 42973251b9429f2c41b77eb98a7b0b0ba2d3b2c0 F test/dbstatus.test 8de104bb5606f19537d23cd553b41349b5ab1204 F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2 @@ -1375,7 +1374,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P fc3fb5cd0d2c123a069e5b18b62bb1f708c8698a -R 020be40332ddb39fbaad6fc302316e47 +P 581e3d4988e98975fea5daaeb9f854c54a4976b7 +R 32fb6312a84d28df618932a2d55ba493 U drh -Z 56068f8a083e66d3150e6ce38cb011fe +Z 247ce995f99250cbca60587acaa0c7c9 diff --git a/manifest.uuid b/manifest.uuid index 3a1ba3442d..00b59df147 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -581e3d4988e98975fea5daaeb9f854c54a4976b7 \ No newline at end of file +bf383e665a191a4f33a540d1240960a922e22813 \ No newline at end of file diff --git a/src/tclsqlite.c b/src/tclsqlite.c index f8073fe3ef..f024317e90 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -3739,7 +3739,6 @@ static void init_all(Tcl_Interp *interp){ extern int Sqlitetestasync_Init(Tcl_Interp*); extern int Sqlitetest_autoext_Init(Tcl_Interp*); extern int Sqlitetest_blob_Init(Tcl_Interp*); - extern int Sqlitetest_cursorhint_Init(Tcl_Interp*); extern int Sqlitetest_demovfs_Init(Tcl_Interp *); extern int Sqlitetest_func_Init(Tcl_Interp*); extern int Sqlitetest_hexio_Init(Tcl_Interp*); @@ -3785,8 +3784,6 @@ static void init_all(Tcl_Interp *interp){ Sqlitetestasync_Init(interp); Sqlitetest_autoext_Init(interp); Sqlitetest_blob_Init(interp); - Sqlitetest_cursorhint_Init(interp); - Sqlitetest_demovfs_Init(interp); Sqlitetest_demovfs_Init(interp); Sqlitetest_func_Init(interp); Sqlitetest_hexio_Init(interp); diff --git a/src/test_cursorhint.c b/src/test_cursorhint.c deleted file mode 100644 index 0f94232696..0000000000 --- a/src/test_cursorhint.c +++ /dev/null @@ -1,162 +0,0 @@ -/* -** 2008 March 19 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing all sorts of SQLite interfaces. This code -** implements new SQL functions used by the test scripts. -*/ -#include "sqlite3.h" -#include "tcl.h" -#include -#include -#include - -#include "sqliteInt.h" -#include "vdbeInt.h" - -struct CursorHintGlobal { - Tcl_Interp *interp; - Tcl_Obj *pScript; -} cursorhintglobal; - -static char *exprToString(Mem *aMem, Expr *pExpr){ - char *zRet = 0; - char *zBinOp = 0; - - switch( pExpr->op ){ - case TK_STRING: - zRet = sqlite3_mprintf("%Q", pExpr->u.zToken); - break; - - case TK_INTEGER: - zRet = sqlite3_mprintf("%d", pExpr->u.iValue); - break; - - case TK_NULL: - zRet = sqlite3_mprintf("%s", "NULL"); - break; - - case TK_REGISTER: { - Mem *pMem = &aMem[pExpr->iTable]; - if( pMem->flags & MEM_Int ){ - zRet = sqlite3_mprintf("%lld", pMem->u.i); - } - else if( pMem->flags & MEM_Real ){ - zRet = sqlite3_mprintf("%f", pMem->u.r); - } - else if( pMem->flags & MEM_Str ){ - zRet = sqlite3_mprintf("%.*Q", pMem->n, pMem->z); - } - else if( pMem->flags & MEM_Blob ){ - } - else{ - zRet = sqlite3_mprintf("%s", "NULL"); - } - break; - } - - case TK_COLUMN: { - zRet = sqlite3_mprintf("col(%d)", (int)pExpr->iColumn); - break; - } - - case TK_LT: zBinOp = "<"; break; - case TK_LE: zBinOp = "<="; break; - case TK_GT: zBinOp = ">"; break; - case TK_GE: zBinOp = ">="; break; - case TK_NE: zBinOp = "!="; break; - case TK_EQ: zBinOp = "=="; break; - case TK_IS: zBinOp = "IS"; break; - case TK_ISNOT: zBinOp = "IS NOT"; break; - case TK_AND: zBinOp = "AND"; break; - case TK_OR: zBinOp = "OR"; break; - case TK_PLUS: zBinOp = "+"; break; - case TK_STAR: zBinOp = "*"; break; - case TK_MINUS: zBinOp = "-"; break; - case TK_REM: zBinOp = "%"; break; - case TK_BITAND: zBinOp = "&"; break; - case TK_BITOR: zBinOp = "|"; break; - case TK_SLASH: zBinOp = "/"; break; - case TK_LSHIFT: zBinOp = "<<"; break; - case TK_RSHIFT: zBinOp = ">>"; break; - case TK_CONCAT: zBinOp = "||"; break; - - default: - zRet = sqlite3_mprintf("%s", "expr"); - break; - } - - if( zBinOp ){ - zRet = sqlite3_mprintf("(%z %s %z)", - exprToString(aMem, pExpr->pLeft), - zBinOp, - exprToString(aMem, pExpr->pRight) - ); - } - - return zRet; -} - -void sqlite3BtreeCursorHintTest(Mem *aMem, Expr *pExpr){ - if( cursorhintglobal.pScript ){ - Tcl_Obj *pEval = Tcl_DuplicateObj(cursorhintglobal.pScript); - char *zExpr; - Tcl_Obj *pObj; - Tcl_IncrRefCount(pEval); - zExpr = exprToString(aMem, pExpr); - pObj = Tcl_NewStringObj(zExpr, -1); - sqlite3_free(zExpr); - Tcl_ListObjAppendElement(cursorhintglobal.interp, pEval, pObj); - Tcl_EvalObjEx(cursorhintglobal.interp, pEval, TCL_GLOBAL_ONLY); - Tcl_DecrRefCount(pEval); - } -} - -/* -** Usage: cursorhint_hook SCRIPT -*/ -static int install_cursorhint_hook( - ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int objc, /* Number of arguments */ - Tcl_Obj *CONST objv[] /* Command arguments */ -){ - if( objc!=1 && objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "?SCRIPT?"); - return TCL_ERROR; - } - if( cursorhintglobal.pScript ){ - Tcl_DecrRefCount(cursorhintglobal.pScript); - memset(&cursorhintglobal, 0, sizeof(cursorhintglobal)); - } - if( objc==2 ){ - cursorhintglobal.interp = interp; - cursorhintglobal.pScript = Tcl_DuplicateObj(objv[1]); - } - return TCL_OK; -} - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest_cursorhint_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - } aObjCmd[] = { - { "cursorhint_hook", install_cursorhint_hook }, - }; - int i; - for(i=0; iapCsr[pOp->p1]; if( pC ){ sqlite3BtreeCursorHint(pC->pCursor, BTREE_HINT_RANGE, pOp->p4.pExpr, aMem); -#ifdef SQLITE_TEST - void sqlite3BtreeCursorHintTest(Mem*, Expr*); - sqlite3BtreeCursorHintTest(p->aMem, pOp->p4.pExpr); -#endif } break; } diff --git a/test/cursorhint.test b/test/cursorhint.test index b4bd7dc14a..b9677b640d 100644 --- a/test/cursorhint.test +++ b/test/cursorhint.test @@ -16,57 +16,108 @@ source $testdir/tester.tcl set testprefix cursorhint do_execsql_test 1.0 { - CREATE TABLE t1(a,b); - CREATE TABLE t2(x,y); - INSERT INTO t1 VALUES(10, 15); - INSERT INTO t1 VALUES(20, 25); - INSERT INTO t2 VALUES('ten', 'fifteen'); - INSERT INTO t2 VALUES('twenty', 'twentyfive'); + CREATE TABLE t1(a,b,c,d); + CREATE TABLE t2(x,y,z); + INSERT INTO t1(a,b) VALUES(10, 15); + INSERT INTO t1(a,b) VALUES(20, 25); + INSERT INTO t2(x,y) VALUES('ten', 'fifteen'); + INSERT INTO t2(x,y) VALUES('twenty', 'twentyfive'); + CREATE TABLE t3(id TEXT PRIMARY KEY, a, b, c, d) WITHOUT ROWID; + INSERT INTO t3(id,a,b,c,d) SELECT rowid, a, b, c, d FROM t1; PRAGMA automatic_index = 0; } -proc H {expr} { - lappend ::cursorhint $expr +# Run EXPLAIN on $sql. Return a list of P4 values for all $opcode +# opcodes. +# +proc p4_of_opcode {db opcode sql} { + set res {} + $db eval "EXPLAIN $sql" x { + if {$x(opcode)==$opcode} {lappend res $x(p4)} + } + return $res } -proc do_cursorhint_test {tn sql hints} { - cursorhint_hook H - set ::cursorhint [list] - set testbody [subst { - execsql {$sql} - set ::cursorhint - }] - uplevel [list do_test $tn $testbody [list {*}$hints]] - cursorhint_hook +# Run EXPLAIN on $sql. Return a list of P5 values for all $opcode +# opcodes that contain regexp $comment in their comment +# +proc p5_of_opcode {db opcode comment sql} { + set res {} + $db eval "EXPLAIN $sql" x { + if {$x(opcode)==$opcode && [regexp $comment $x(comment)]} { + lappend res $x(p5) + } + } + return $res } +# Verify that when t1 is in the outer loop and t2 is in the inner loop, +# no cursor hints occur for t1 (since it is a full table scan) but that +# each t2 access has a cursor hint based on the current t1.a value. +# +do_test 1.1 { + p4_of_opcode db CursorHint { + SELECT * FROM t1 CROSS JOIN t2 WHERE a=x + } +} {/(r*==c0)/} +do_test 1.2 { + p5_of_opcode db OpenRead . { + SELECT * FROM t1 CROSS JOIN t2 WHERE a=x + } +} {00 00} -do_cursorhint_test 1.1 { - SELECT * FROM t1 CROSS JOIN t2 WHERE a=x; -} { - {(10 == col(0))} - {(20 == col(0))} -} +# Do the same test the other way around. +# +do_test 2.1 { + p4_of_opcode db CursorHint { + SELECT * FROM t2 CROSS JOIN t1 WHERE a=x + } +} {/(c0==r*)/} +do_test 2.2 { + p5_of_opcode db OpenRead . { + SELECT * FROM t2 CROSS JOIN t1 WHERE a=x + } +} {00 00} -do_cursorhint_test 1.2 { - SELECT * FROM t2 CROSS JOIN t1 WHERE a=x; -} { - {(col(0) == 'ten')} - {(col(0) == 'twenty')} -} +# Various expressions captured by CursorHint +# +do_test 3.1 { + p4_of_opcode db CursorHint { + SELECT * FROM t1 WHERE a=15 AND c=22 AND rowid!=98 + } +} {/(c0==15).*(c2==22).*(rowid!=98)/} +do_test 3.2 { + p4_of_opcode db CursorHint { + SELECT * FROM t3 WHERE a<15 AND b>22 AND id!=98 + } +} {/(c1<15).*(c2>22).*(c0!=98)/} -do_cursorhint_test 1.3 { - SELECT * FROM t1 CROSS JOIN t2 WHERE b=15; -} { - {(col(1) == 15)} -} - -do_cursorhint_test 1.3 { - SELECT * FROM t1 CROSS JOIN t2 WHERE y=b+1; -} { - {(col(1) == (15 + 1))} - {(col(1) == (25 + 1))} -} +# Indexed queries +# +do_test 4.1 { + db eval { + CREATE INDEX t1bc ON t1(b,c); + CREATE INDEX t2yz ON t2(y,z); + } + p4_of_opcode db CursorHint { + SELECT * FROM t1 WHERE b>11; + } +} {/(c0>11)/} +do_test 4.2 { + p5_of_opcode db OpenRead . { + SELECT * FROM t1 WHERE b>11; + } +} {02 00} +do_test 4.3 { + p4_of_opcode db CursorHint { + SELECT c FROM t1 WHERE b>11; + } +} {/(c0>11)/} +do_test 4.4 { + p5_of_opcode db OpenRead . { + SELECT c FROM t1 WHERE b>11; + } +} {00} finish_test