diff --git a/ext/misc/spellfix.c b/ext/misc/spellfix.c index 768ea5753c..4be73bb39e 100644 --- a/ext/misc/spellfix.c +++ b/ext/misc/spellfix.c @@ -2051,6 +2051,7 @@ static int spellfix1Close(sqlite3_vtab_cursor *cur){ ** (D) scope = $scope ** (E) distance < $distance ** (F) distance <= $distance +** (G) rowid = $rowid ** ** The plan number is a bit mask formed with these bits: ** @@ -2060,8 +2061,9 @@ static int spellfix1Close(sqlite3_vtab_cursor *cur){ ** 0x08 (D) is found ** 0x10 (E) is found ** 0x20 (F) is found +** 0x40 (G) is found ** -** filter.argv[*] values contains $str, $langid, $top, and $scope, +** filter.argv[*] values contains $str, $langid, $top, $scope and $rowid ** if specified and in that order. */ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ @@ -2070,6 +2072,7 @@ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ int iTopTerm = -1; int iScopeTerm = -1; int iDistTerm = -1; + int iRowidTerm = -1; int i; const struct sqlite3_index_constraint *pConstraint; pConstraint = pIdxInfo->aConstraint; @@ -2122,6 +2125,15 @@ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ iPlan |= pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ? 16 : 32; iDistTerm = i; } + + /* Terms of the form: distance < $dist or distance <= $dist */ + if( (iPlan & 64)==0 + && pConstraint->iColumn<0 + && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ + ){ + iPlan |= 64; + iRowidTerm = i; + } } if( iPlan&1 ){ int idx = 2; @@ -2149,6 +2161,11 @@ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ pIdxInfo->aConstraintUsage[iDistTerm].omit = 1; } pIdxInfo->estimatedCost = 1e5; + }else if( (iPlan & 64) ){ + pIdxInfo->idxNum = 64; + pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1; + pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1; + pIdxInfo->estimatedCost = 5; }else{ pIdxInfo->idxNum = 0; pIdxInfo->estimatedCost = 1e50; @@ -2465,16 +2482,23 @@ static int spellfix1FilterForFullScan( int argc, sqlite3_value **argv ){ - int rc; + int rc = SQLITE_OK; char *zSql; spellfix1_vtab *pVTab = pCur->pVTab; spellfix1ResetCursor(pCur); + assert( idxNum==0 || idxNum==64 ); zSql = sqlite3_mprintf( - "SELECT word, rank, NULL, langid, id FROM \"%w\".\"%w_vocab\"", - pVTab->zDbName, pVTab->zTableName); + "SELECT word, rank, NULL, langid, id FROM \"%w\".\"%w_vocab\"%s", + pVTab->zDbName, pVTab->zTableName, + ((idxNum & 64) ? " WHERE rowid=?" : "") + ); if( zSql==0 ) return SQLITE_NOMEM; rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pFullScan, 0); sqlite3_free(zSql); + if( rc==SQLITE_OK && (idxNum & 64) ){ + assert( argc==1 ); + rc = sqlite3_bind_value(pCur->pFullScan, 1, argv[0]); + } pCur->nRow = pCur->iRow = 0; if( rc==SQLITE_OK ){ rc = sqlite3_step(pCur->pFullScan); diff --git a/manifest b/manifest index 9793a62dd6..336d04f480 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\sundocumented\srequirement\sfor\sapplications\sthat\suse\san\sSQLITE_ENABLE_SQLLOG\sbuild\sto\sdefine\sa\ssqlite3_init_sqllog()\sfunction. -D 2014-01-21T15:04:47.807 +C Update\sthe\sspellfix\svirtual\stable\sto\soptimize\squeries\sof\sthe\sform\s"SELECT\s...\sFROM\stbl\sWHERE\srowid=?". +D 2014-01-22T17:43:16.604 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -114,7 +114,7 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a -F ext/misc/spellfix.c 76578f2c56ceaa23d22032338d90db79c68490fb +F ext/misc/spellfix.c adfc569fafef7a1eb8f21528e5277686b358c3ce F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e @@ -825,7 +825,7 @@ F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b F test/speedtest1.c 7130d2cb6db45baa553a4ab2f715116c71c2d9f4 -F test/spellfix.test 8c40b169b104086d8795781f670ba3c786d6d8be +F test/spellfix.test 674db5da8b16d2b54939b68ccc0ac31ca53d9977 F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298 F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9 @@ -1152,7 +1152,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 7d9e22187daaa3160b875a1df17b924969bf718e -R 72db5d0300da6235ddfc19ebd0af857f +P 5e43bf013253921e4dfbe71de11ee7ed4b3e7eae +R d2ae80bd066cad79603d23bc83a10a19 U dan -Z 21763f37f81635b2fe9a520f9fd3a652 +Z 90dc7fd11fe48035054a3857f5aa405e diff --git a/manifest.uuid b/manifest.uuid index 89ddacefff..3b856a138c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5e43bf013253921e4dfbe71de11ee7ed4b3e7eae \ No newline at end of file +a0ba55ff0596c5f15e9cdb254c68ef50df2dfaad \ No newline at end of file diff --git a/test/spellfix.test b/test/spellfix.test index 9eb7a45f5d..3e6fdf7eec 100644 --- a/test/spellfix.test +++ b/test/spellfix.test @@ -221,6 +221,51 @@ foreach {tn word res} { } $res } +#------------------------------------------------------------------------- +# Try some queries by rowid. +# +do_execsql_test 6.1.1 { + SELECT word FROM t3 WHERE rowid = 10; +} {keener} +do_execsql_test 6.1.2 { + SELECT word, distance FROM t3 WHERE rowid = 10; +} {keener {}} +do_execsql_test 6.1.3 { + SELECT word, distance FROM t3 WHERE rowid = 10 AND word MATCH 'kiiner'; +} {keener 300} + +proc trace_callback {sql} { + if {[string range $sql 0 2] == "-- "} { + lappend ::trace [string range $sql 3 end] + } +} + +proc do_tracesql_test {tn sql {res {}}} { + set ::trace [list] + uplevel [list do_test $tn [subst -nocommands { + set vals [execsql {$sql}] + concat [set vals] [set ::trace] + }] [list {*}$res]] +} + +db trace trace_callback +do_tracesql_test 6.2.1 { + SELECT word FROM t3 WHERE rowid = 10; +} {keener + {SELECT word, rank, NULL, langid, id FROM "main"."t3_vocab" WHERE rowid=?} +} +do_tracesql_test 6.2.2 { + SELECT word, distance FROM t3 WHERE rowid = 10; +} {keener {} + {SELECT word, rank, NULL, langid, id FROM "main"."t3_vocab" WHERE rowid=?} +} +do_tracesql_test 6.2.3 { + SELECT word, distance FROM t3 WHERE rowid = 10 AND word MATCH 'kiiner'; +} {keener 300 + {SELECT id, word, rank, k1 FROM "main"."t3_vocab" WHERE langid=0 AND k2>=?1 AND k2