$(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 \
-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
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
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
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
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
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
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
-581e3d4988e98975fea5daaeb9f854c54a4976b7
\ No newline at end of file
+bf383e665a191a4f33a540d1240960a922e22813
\ No newline at end of file
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*);
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);
+++ /dev/null
-/*
-** 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 <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#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; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
- Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
- }
- sqlite3_initialize();
- return TCL_OK;
-}
pC = p->apCsr[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;
}
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_cursorhint_test 1.2 {
- SELECT * FROM t2 CROSS JOIN t1 WHERE a=x;
-} {
- {(col(0) == 'ten')}
- {(col(0) == 'twenty')}
-}
+# 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.3 {
- SELECT * FROM t1 CROSS JOIN t2 WHERE b=15;
-} {
- {(col(1) == 15)}
-}
+# 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 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