From dbbda39453fbc2e0b1cf5dfb7c03e7e2be116ee1 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 6 Nov 2015 12:50:57 +0000 Subject: [PATCH] Have fts5 load its configuration from the xConnect() method is invoked. This ensures that the very first query run uses the correct value of the 'rank' option. FossilOrigin-Name: 33e6606f5e497e81119ec491cf2370f60bddafc0 --- ext/fts5/fts5_config.c | 54 ++++++++++++++++++---------------- ext/fts5/fts5_index.c | 3 -- ext/fts5/fts5_main.c | 45 ++++++++++++++++++++++++---- ext/fts5/test/fts5fault1.test | 6 ++-- ext/fts5/test/fts5fault4.test | 2 +- ext/fts5/test/fts5rank.test | 55 +++++++++++++++++++++++++++++++++++ ext/fts5/test/fts5simple.test | 15 ++++++++++ manifest | 26 ++++++++--------- manifest.uuid | 2 +- 9 files changed, 157 insertions(+), 51 deletions(-) diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c index b566526e0e..4f6272dbe2 100644 --- a/ext/fts5/fts5_config.c +++ b/ext/fts5/fts5_config.c @@ -707,33 +707,37 @@ int sqlite3Fts5ConfigParseRank( *pzRank = 0; *pzRankArgs = 0; - p = fts5ConfigSkipWhitespace(p); - pRank = p; - p = fts5ConfigSkipBareword(p); - - if( p ){ - zRank = sqlite3Fts5MallocZero(&rc, 1 + p - pRank); - if( zRank ) memcpy(zRank, pRank, p-pRank); - }else{ + if( p==0 ){ rc = SQLITE_ERROR; - } - - if( rc==SQLITE_OK ){ - p = fts5ConfigSkipWhitespace(p); - if( *p!='(' ) rc = SQLITE_ERROR; - p++; - } - if( rc==SQLITE_OK ){ - const char *pArgs; + }else{ p = fts5ConfigSkipWhitespace(p); - pArgs = p; - if( *p!=')' ){ - p = fts5ConfigSkipArgs(p); - if( p==0 ){ - rc = SQLITE_ERROR; - }else{ - zRankArgs = sqlite3Fts5MallocZero(&rc, 1 + p - pArgs); - if( zRankArgs ) memcpy(zRankArgs, pArgs, p-pArgs); + pRank = p; + p = fts5ConfigSkipBareword(p); + + if( p ){ + zRank = sqlite3Fts5MallocZero(&rc, 1 + p - pRank); + if( zRank ) memcpy(zRank, pRank, p-pRank); + }else{ + rc = SQLITE_ERROR; + } + + if( rc==SQLITE_OK ){ + p = fts5ConfigSkipWhitespace(p); + if( *p!='(' ) rc = SQLITE_ERROR; + p++; + } + if( rc==SQLITE_OK ){ + const char *pArgs; + p = fts5ConfigSkipWhitespace(p); + pArgs = p; + if( *p!=')' ){ + p = fts5ConfigSkipArgs(p); + if( p==0 ){ + rc = SQLITE_ERROR; + }else{ + zRankArgs = sqlite3Fts5MallocZero(&rc, 1 + p - pArgs); + if( zRankArgs ) memcpy(zRankArgs, pArgs, p-pArgs); + } } } } diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index a91af1304a..b7374f9805 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -4447,9 +4447,6 @@ int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){ /* Allocate the hash table if it has not already been allocated */ if( p->pHash==0 ){ p->rc = sqlite3Fts5HashNew(&p->pHash, &p->nPendingData); - - /* Force the configuration to be loaded */ - fts5StructureRelease(fts5StructureRead(p)); } /* Flush the hash table to disk if required */ diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index bd004cf824..ee5adc4b98 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -395,6 +395,15 @@ static int fts5InitVtab( rc = sqlite3Fts5ConfigDeclareVtab(pConfig); } + /* Load the initial configuration */ + if( rc==SQLITE_OK ){ + assert( pConfig->pzErrmsg==0 ); + pConfig->pzErrmsg = pzErr; + rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex); + sqlite3Fts5IndexRollback(pTab->pIndex); + pConfig->pzErrmsg = 0; + } + if( rc!=SQLITE_OK ){ fts5FreeVtab(pTab); pTab = 0; @@ -829,6 +838,36 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ return rc; } + +static sqlite3_stmt *fts5PrepareStatement( + int *pRc, + Fts5Config *pConfig, + const char *zFmt, + ... +){ + sqlite3_stmt *pRet = 0; + va_list ap; + va_start(ap, zFmt); + + if( *pRc==SQLITE_OK ){ + int rc; + char *zSql = sqlite3_vmprintf(zFmt, ap); + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0); + if( rc!=SQLITE_OK ){ + *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db)); + } + sqlite3_free(zSql); + } + *pRc = rc; + } + + va_end(ap); + return pRet; +} + static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){ Fts5Config *pConfig = pTab->pConfig; Fts5Sorter *pSorter; @@ -853,17 +892,13 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){ ** table, saving it creates a circular reference. ** ** If SQLite a built-in statement cache, this wouldn't be a problem. */ - zSql = sqlite3Fts5Mprintf(&rc, + pSorter->pStmt = fts5PrepareStatement(&rc, pConfig, "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s", pConfig->zDb, pConfig->zName, zRank, pConfig->zName, (zRankArgs ? ", " : ""), (zRankArgs ? zRankArgs : ""), bDesc ? "DESC" : "ASC" ); - if( zSql ){ - rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pSorter->pStmt, 0); - sqlite3_free(zSql); - } pCsr->pSorter = pSorter; if( rc==SQLITE_OK ){ diff --git a/ext/fts5/test/fts5fault1.test b/ext/fts5/test/fts5fault1.test index 13f36803e1..429ea39af0 100644 --- a/ext/fts5/test/fts5fault1.test +++ b/ext/fts5/test/fts5fault1.test @@ -52,7 +52,7 @@ do_faultsim_test 2 -prep { INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno'); } } -test { - faultsim_test_result {0 {}} + faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}} } reset_db @@ -66,7 +66,7 @@ do_faultsim_test 3 -prep { } -body { execsql { DELETE FROM t1 } } -test { - faultsim_test_result {0 {}} + faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}} } reset_db @@ -101,7 +101,7 @@ foreach {tn expr res} { } -body " execsql { SELECT rowid FROM t2 WHERE t2 MATCH '$expr' } " -test " - faultsim_test_result {[list 0 $res]} + faultsim_test_result {[list 0 $res]} {1 {vtable constructor failed: t2}} " } diff --git a/ext/fts5/test/fts5fault4.test b/ext/fts5/test/fts5fault4.test index a392b238ee..989a372d49 100644 --- a/ext/fts5/test/fts5fault4.test +++ b/ext/fts5/test/fts5fault4.test @@ -107,7 +107,7 @@ set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}] do_faultsim_test 4 -faults oom-* -body { db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'} } -test { - faultsim_test_result {0 {0 {} 3}} + faultsim_test_result {0 {0 {} 4}} } #------------------------------------------------------------------------- diff --git a/ext/fts5/test/fts5rank.test b/ext/fts5/test/fts5rank.test index 2182ab3097..4961b42605 100644 --- a/ext/fts5/test/fts5rank.test +++ b/ext/fts5/test/fts5rank.test @@ -41,5 +41,60 @@ do_execsql_test 1.3 { WHERE xyz MATCH 'x AND y' ORDER BY rank } [list [string map {x [x] y [y]} $doc]] +#------------------------------------------------------------------------- +# Check that the 'rank' option really is persistent. +# +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE tt USING fts5(a); + INSERT INTO tt VALUES('a x x x x'); + INSERT INTO tt VALUES('x x a a a'); + INSERT INTO tt VALUES('x a a x x'); +} + +proc firstinst {cmd} { + foreach {p c o} [$cmd xInst 0] {} + return $o +} +sqlite3_fts5_create_function db firstinst firstinst + +do_execsql_test 2.1 { + SELECT rowid FROM tt('a') ORDER BY rank; +} {2 3 1} + +do_execsql_test 2.2 { + SELECT rowid FROM tt('a', 'firstinst()') ORDER BY rank; +} {1 3 2} + +do_execsql_test 2.3 { + INSERT INTO tt(tt, rank) VALUES('rank', 'firstinst()'); + SELECT rowid FROM tt('a') ORDER BY rank; +} {1 3 2} + +do_test 2.4 { + sqlite3 db2 test.db + catchsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2 +} {1 {no such function: firstinst}} + +do_test 2.5 { + db2 close + sqlite3 db2 test.db + sqlite3_fts5_create_function db2 firstinst firstinst + execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2 +} {1 3 2} + +do_test 2.6 { + execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2 +} {1 3 2} + +do_test 2.7 { + execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db +} {1 3 2} + + + + + + + finish_test diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test index 458d018c34..27a1aee08b 100644 --- a/ext/fts5/test/fts5simple.test +++ b/ext/fts5/test/fts5simple.test @@ -336,5 +336,20 @@ do_test 14.2 { fts5_level_segs ttt } {1} +#------------------------------------------------------------------------- +db func rnddoc fts5_rnddoc +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(x1, rank) VALUES('pgsz', 32); + + WITH ii(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<10 ) + INSERT INTO x1 SELECT rnddoc(5) FROM ii; +} + +do_execsql_test 4.1 { + SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads' +} {0 {} 4} + + finish_test diff --git a/manifest b/manifest index daf44cfd73..4163d9d511 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stypo\sin\shelp\sinformation\sfor\san\sFTS5\sscript. -D 2015-11-05T21:49:19.879 +C Have\sfts5\sload\sits\sconfiguration\sfrom\sthe\sxConnect()\smethod\sis\sinvoked.\sThis\sensures\sthat\sthe\svery\sfirst\squery\srun\suses\sthe\scorrect\svalue\sof\sthe\s'rank'\soption. +D 2015-11-06T12:50:57.166 F Makefile.in 3a705bb4bd12e194212ddbdbf068310d17153cdb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4 @@ -106,11 +106,11 @@ F ext/fts5/fts5.h 8b9a13b309b180e9fb88ea5666c0d8d73c6102d9 F ext/fts5/fts5Int.h acf968e43d57b6b1caf7554d34ec35d6ed3b4fe8 F ext/fts5/fts5_aux.c 1f384972d606375b8fa078319f25ab4b5feb1b35 F ext/fts5/fts5_buffer.c 1e49512a535045e621246dc7f4f65f3593fa0fc2 -F ext/fts5/fts5_config.c 81ec07cb644e33df4cd58d46990016b2ce7c175c +F ext/fts5/fts5_config.c 6fc92c0b1bda5244c28a54c9ba740736bd5513d9 F ext/fts5/fts5_expr.c 28b15c9ae296204bc0a2e5cf7a667d840a9d2900 F ext/fts5/fts5_hash.c a9d4c1efebc2a91d26ad7ebdfcbf2678ceac405f -F ext/fts5/fts5_index.c 967d797282e4595f8671d152ed8ecf6cc7e640b5 -F ext/fts5/fts5_main.c 39358d3d8f0d6ea3757c40e0ddcbb6bc435604c3 +F ext/fts5/fts5_index.c b622a0a70f57a96469e6828da2dd70e0872aeb37 +F ext/fts5/fts5_main.c 0569cd9fc18f3b56f6eeac601836df8ed5fb54cb F ext/fts5/fts5_storage.c 9ea3d92178743758b6c54d9fe8836bbbdcc92e3b F ext/fts5/fts5_tcl.c 3bf445e66de32137d4693694ff7b1fd6074e32bd F ext/fts5/fts5_test_mi.c e96be827aa8f571031e65e481251dc1981d608bf @@ -149,10 +149,10 @@ F ext/fts5/test/fts5dlidx.test ecba5e62ea8b26c33829961602069c546228046d F ext/fts5/test/fts5doclist.test 8edb5b57e5f144030ed74ec00ef6fa4294fed79b F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0 F ext/fts5/test/fts5eb.test 3e5869af2008cbc4ad03a175a0b6f6e58134cd43 -F ext/fts5/test/fts5fault1.test 7a562367cb4a735b57b410dbdb62dcc8d971faec +F ext/fts5/test/fts5fault1.test 4b39c47ca3544615daa8a2f733b911fa08022c77 F ext/fts5/test/fts5fault2.test 28c36c843bb39ae855ba79827417ecc37f114341 F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3 -F ext/fts5/test/fts5fault4.test 762991d526ee67c2b374351a17248097ea38bee7 +F ext/fts5/test/fts5fault4.test 4864f2b5c2c083440dbe85aff60897bc1aa04603 F ext/fts5/test/fts5fault5.test f2b8645053d48982e8979749e93994c43011c118 F ext/fts5/test/fts5fault6.test 9682664d679643ac6736e90c225526cc84073cda F ext/fts5/test/fts5fault7.test 01be274bfc8d9bf22451a3bf5892e9399d044f1b @@ -170,11 +170,11 @@ F ext/fts5/test/fts5porter.test 7cdc07bef301d70eebbfa75dcaf45c3680e1d0e1 F ext/fts5/test/fts5porter2.test 2e65633d58a1c525d5af0f6c01e5a59155bb3487 F ext/fts5/test/fts5prefix.test 7ccbdf180ed561a912acef520519e85af8642239 F ext/fts5/test/fts5query.test f5ec25f5f2fbb70033424113cdffc101b1985a40 -F ext/fts5/test/fts5rank.test 11dcebba31d822f7e99685b4ea2c2ae3ec0b16f1 +F ext/fts5/test/fts5rank.test 7e9e64eac7245637f6f2033aec4b292aaf611aab F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17 F ext/fts5/test/fts5rowid.test 400384798349d658eaf06aefa1e364957d5d4821 -F ext/fts5/test/fts5simple.test ec1c6a6f51890ba864f866387794878ff2994de9 +F ext/fts5/test/fts5simple.test 9bded45827b4ab8933c87b7b3bcc3cd47f7378a4 F ext/fts5/test/fts5synonym.test cf88c0a56d5ea9591e3939ef1f6e294f7f2d0671 F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89 F ext/fts5/test/fts5unicode.test fbef8d8a3b4b88470536cc57604a82ca52e51841 @@ -1398,7 +1398,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 445480095e6877cce8220b1c095f334bbb04c1c3 -R 68d01af6e20ce1ec369a81a5012243d6 -U mistachkin -Z 34f3b0f0379f36a413653d60c651c6ba +P 777ae8007f6ff303b120b25f2dc37d7ef6b6a4f8 +R 4ec8b8e5e66f6ab44c58d4f991232b45 +U dan +Z f9c34cc6cfcf4374f3d76c696dbe3249 diff --git a/manifest.uuid b/manifest.uuid index 1f1b6d3fb2..146948eca4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -777ae8007f6ff303b120b25f2dc37d7ef6b6a4f8 \ No newline at end of file +33e6606f5e497e81119ec491cf2370f60bddafc0 \ No newline at end of file -- 2.47.2