From: drh Date: Thu, 3 Mar 2016 17:54:30 +0000 (+0000) Subject: Merge 3.11.1 changes into trunk. X-Git-Tag: version-3.12.0~115 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b382017084a910f3d4436b8110d73764caf01b0;p=thirdparty%2Fsqlite.git Merge 3.11.1 changes into trunk. FossilOrigin-Name: 7abc2dd953477797fa05421b061d73596aa025fb --- 5b382017084a910f3d4436b8110d73764caf01b0 diff --cc ext/fts5/test/fts5simple.test index 01111d78c8,d1b5647604..464b601548 --- a/ext/fts5/test/fts5simple.test +++ b/ext/fts5/test/fts5simple.test @@@ -409,25 -409,23 +409,43 @@@ do_catchsql_test 19.2 SELECT * FROM x1 WHERE x1 MATCH 'c0 AND (c1 AND (c2 AND (c3 AND (c4 AND (c5 AND (c6 AND (c7 AND (c8 AND (c9 AND (c10 AND (c11 AND (c12 AND (c13 AND (c14 AND (c15 AND (c16 AND (c17 AND (c18 AND (c19 AND (c20 AND (c21 AND (c22 AND (c23 AND (c24 AND (c25 AND (c26 AND (c27 AND (c28 AND (c29 AND (c30 AND (c31 AND (c32 AND (c33 AND (c34 AND (c35 AND (c36 AND (c37 AND (c38 AND (c39 AND (c40 AND (c41 AND (c42 AND (c43 AND (c44 AND (c45 AND (c46 AND (c47 AND (c48 AND (c49 AND (c50 AND (c51 AND (c52 AND (c53 AND (c54 AND (c55 AND (c56 AND (c57 AND (c58 AND (c59 AND (c60 AND (c61 AND (c62 AND (c63 AND (c64 AND (c65 AND (c66 AND (c67 AND (c68 AND (c69 AND (c70 AND (c71 AND (c72 AND (c73 AND (c74 AND (c75 AND (c76 AND (c77 AND (c78 AND (c79 AND (c80 AND (c81 AND (c82 AND (c83 AND (c84 AND (c85 AND (c86 AND (c87 AND (c88 AND (c89 AND (c90 AND (c91 AND (c92 AND (c93 AND (c94 AND (c95 AND (c96 AND (c97 AND (c98 AND (c99 AND (c100 AND (c101 AND (c102 AND (c103 AND (c104 AND (c105 AND (c106 AND (c107 AND (c108 AND (c109 AND (c110 AND (c111 AND (c112 AND (c113 AND (c114 AND (c115 AND (c116 AND (c117 AND (c118 AND (c119 AND (c120 AND (c121 AND (c122 AND (c123 AND (c124 AND (c125 AND (c126 AND (c127 AND (c128 AND (c129 AND (c130 AND (c131 AND (c132 AND (c133 AND (c134 AND (c135 AND (c136 AND (c137 AND (c138 AND (c139 AND (c140 AND (c141 AND (c142 AND (c143 AND (c144 AND (c145 AND (c146 AND (c147 AND (c148 AND (c149 AND (c150 AND (c151 AND (c152 AND (c153 AND (c154 AND (c155 AND (c156 AND (c157 AND (c158 AND (c159 AND (c160 AND (c161 AND (c162 AND (c163 AND (c164 AND (c165 AND (c166 AND (c167 AND (c168 AND (c169 AND (c170 AND (c171 AND (c172 AND (c173 AND (c174 AND (c175 AND (c176 AND (c177 AND (c178 AND (c179 AND (c180 AND (c181 AND (c182 AND (c183 AND (c184 AND (c185 AND (c186 AND (c187 AND (c188 AND (c189 AND (c190 AND (c191 AND (c192 AND (c193 AND (c194 AND (c195 AND (c196 AND (c197 AND (c198 AND (c199 AND c200)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))'; } {1 {fts5: parser stack overflow}} +#------------------------------------------------------------------------- +reset_db +breakpoint +do_execsql_test 20.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(x1, rank) VALUES('pgsz', 32); + INSERT INTO x1(rowid, x) VALUES(11111, 'onetwothree'); +} +do_test 20.1 { + for {set i 1} {$i <= 200} {incr i} { + execsql { INSERT INTO x1(rowid, x) VALUES($i, 'one two three'); } + } + execsql { INSERT INTO x1(x1) VALUES('optimize'); } + execsql { DELETE FROM x1 WHERE rowid = 4; } +} {} +do_execsql_test 20.2 { + INSERT INTO x1(x1) VALUES('optimize'); + INSERT INTO x1(x1) VALUES('integrity-check'); +} {} + - finish_test + #------------------------------------------------------------------------- + reset_db + do_execsql_test 20.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(x1, rank) VALUES('pgsz', 32); + INSERT INTO x1(rowid, x) VALUES(11111, 'onetwothree'); + } + do_test 20.1 { + for {set i 1} {$i <= 200} {incr i} { + execsql { INSERT INTO x1(rowid, x) VALUES($i, 'one two three'); } + } + execsql { INSERT INTO x1(x1) VALUES('optimize'); } + execsql { DELETE FROM x1 WHERE rowid = 4; } + } {} + do_execsql_test 20.2 { + INSERT INTO x1(x1) VALUES('optimize'); + INSERT INTO x1(x1) VALUES('integrity-check'); + } {} + finish_test diff --cc manifest index 18c08f648b,907e6740e1..293b1945bd --- a/manifest +++ b/manifest @@@ -1,10 -1,10 +1,10 @@@ - C Enhance\stest_bestindex.c\sso\sthat\sit\scan\sbe\sused\sto\stest\splans\sgenerated\sby\sxBestIndex. - D 2016-03-02T16:01:41.146 -C Version\s3.11.1 -D 2016-03-03T16:17:53.102 ++C Merge\s3.11.1\schanges\sinto\strunk. ++D 2016-03-03T17:54:30.421 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 56ea123a975690bf9ed38b31bb89ff87b02a7c2b +F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 -F VERSION 1a9f17ac8a5066544976a390298fe62228c58a9e +F VERSION c6b1f51809551d60ad001e6d87cf3ab2c7f54b6f F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 @@@ -114,9 -114,9 +114,9 @@@ F ext/fts5/fts5_tokenize.c 2ce7b4418353 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8 -F ext/fts5/fts5parse.y 59432ea369f1aa65511bad465f55d31a22f9f223 +F ext/fts5/fts5parse.y 86fe6ba094a47e02fe8be2571539e6833d197764 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba - F ext/fts5/test/fts5_common.tcl 61ff0d1a29d98a91c4553b20b3f410d858834ee9 + F ext/fts5/test/fts5_common.tcl b9b1fed811c0390511cef8b254826ea15d380f4d F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b F ext/fts5/test/fts5ac.test 55cad4275a1f5acabfe14d8442a8046b47e49e5f @@@ -161,9 -160,9 +161,9 @@@ F ext/fts5/test/fts5faultB.test 92ae906 F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741 F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d -F ext/fts5/test/fts5matchinfo.test 86569026d20f1ed748236587ce798de8a96615f1 +F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b F ext/fts5/test/fts5merge.test 8f3cdba2ec9c5e7e568246e81b700ad37f764367 - F ext/fts5/test/fts5merge2.test c0cb66eb38a41c26cc5848fb9e50093e0f59ac93 + F ext/fts5/test/fts5merge2.test a6da3c16d694235938d1939f503cfa53f0943d75 F ext/fts5/test/fts5near.test b214cddb1c1f1bddf45c75af768f20145f7e71cc F ext/fts5/test/fts5onepass.test 7ed9608e258132cb8d55e7c479b08676ad68810c F ext/fts5/test/fts5optimize.test 42741e7c085ee0a1276140a752d4407d97c2c9f5 @@@ -177,7 -176,7 +177,7 @@@ F ext/fts5/test/fts5rank.test 7e9e64eac F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17 F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6 - F ext/fts5/test/fts5simple.test 92e06be1c119f88a73ea11a05599a276ec3ff7fd -F ext/fts5/test/fts5simple.test 09420cb1137f3a19d02dacb5b4b6831d2e683773 ++F ext/fts5/test/fts5simple.test ac5006cc3d0d08b3538e1e76c7300de9f24fbed1 F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46 F ext/fts5/test/fts5simple3.test 8e71733b3d1b0e695011d02c68ebc5ca40b6124e F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48 @@@ -212,9 -211,9 +212,9 @@@ F ext/misc/nextchar.c 35c8b8baacb96d92a F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a -F ext/misc/series.c b8fb7befd85b3a9b4a10e701b30b2b79ca92b6d4 +F ext/misc/series.c e1ef8bc23328d4e2196835737f62b324bdcd1c0d F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 - F ext/misc/spellfix.c 525190484b7a9dbc6be646c4842274fff4f27d53 + F ext/misc/spellfix.c 194b5fc3a9a63cb6c5680d8f713800012bddca7c F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e @@@ -371,13 -370,12 +371,13 @@@ F src/test9.c bea1e8cf52aa93695487baded F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8 F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 - F src/test_bestindex.c a711473c79e812e4082fbf045ed6c18c99c16058 -F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07 ++F src/test_bestindex.c cd36324f05404df5f1a82608a321b91932a549ea +F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f -F src/test_config.c 7985332c806d1cece793475c75a6abcccde9d331 +F src/test_config.c 0dee90328e3dedf8ba002ee94b6a7e7ea7726fe4 F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc -F src/test_fs.c a61f54247fdb843761d709879c3bcd1989b2050c +F src/test_fs.c f10f840ca4f8c72e4837908bd8347ac4bcab074b F src/test_func.c 37453d346cfcf118774efd5bf6187f7e6a7e3254 F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32 @@@ -966,9 -963,8 +966,9 @@@ F test/randexpr1.test eda062a97e60f9c38 F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736 F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 +F test/regexp2.test aa7ffcc21350007a78361b82bcf3b74d12227144 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 - F test/releasetest.tcl 975449bf742b8bb9025208292208af816a1fcb58 + F test/releasetest.tcl a246ecb14ed594bf44bf77bd21df873971d779bf F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5 @@@ -1430,30 -1425,12 +1430,30 @@@ F tool/varint.c 5d94cb5003db9dbbcbcc5df F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 -F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f +F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b1258814f6100f594210775e9e3007b5b0c65025 -R da5680e10572eb2ee67e7f4f853b931e -T +bgcolor * #d0c0ff -T +sym-release * -T +sym-version-3.11.1 * +F vsixtest/App.xaml b76d3b48860e7454775c47ea38ffea9c4abe3e85 +F vsixtest/App.xaml.cpp c465147f50871165c60ca16955219f6c5812d6d8 +F vsixtest/App.xaml.h 4a9768e2983d05600ad1e1c2f1b00a132967da9f +F vsixtest/Assets/LockScreenLogo.scale-200.png e820c9a3deb909197081b0bf3216c06e13905f0a +F vsixtest/Assets/SplashScreen.scale-200.png cab70988ca71bebec7bfeb3b6dbafe17b9ab0b4a +F vsixtest/Assets/Square150x150Logo.scale-200.png e17b40817db7a239fc239d83efcc951fb824e3ff +F vsixtest/Assets/Square44x44Logo.scale-200.png 2f166237094dea94d952d10b9eeae81806844f1c +F vsixtest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png 5f6a6d391b95a3061ccca6e6fdd6955ede63b4ed +F vsixtest/Assets/StoreLogo.png 0828b7257db74a4ecd5eeb6b7b4971f0fdc4d9d1 +F vsixtest/Assets/Wide310x150Logo.scale-200.png 04ddefe5bc5f43ae12a7433f6f236ddab101ac42 +F vsixtest/MainPage.xaml 34f49897e3ca533a7e74506ba0759b66eebce151 +F vsixtest/MainPage.xaml.cpp 7f31fc6de751b64676c0924c97a5485d950a91d7 +F vsixtest/MainPage.xaml.h cc05cca10d50a003f6c6e4448b701cdd07f52f29 +F vsixtest/Package.appxmanifest 6b6db1eb7df3a315c5d681059754d5f0e0c47a93 +F vsixtest/pch.cpp cb823cfac36f1a39a7eb0acbd7e9a0b0de8f23af +F vsixtest/pch.h 9cab7980f2ac4baa40807d8b5e52af32a21cf78c +F vsixtest/vsixtest.sln 77cadbe4e96c1fe1bf51cd77de9e9b0a12ada547 +F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 +F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc +F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e +F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 - P 3d9daa929c0abe6dc01e800ef343b0eef2f0c76a - R 10e42f20a022f81e947260641e83d066 - U dan - Z 32cbbe1a7e810bc34e8a7796bb6fedf4 ++P 3c15a9bf45cd7dae2fbd99123b8dd75ce278d6e4 f047920ce16971e573bc6ec9a48b118c9de2b3a7 ++R 7bed5868510318c8bb3057f2d53886a9 + U drh -Z ad71638129773a9e26cf148e72895b35 ++Z 5d4c029f83980452f09894533c95c4c4 diff --cc manifest.uuid index a4b1d5378e,6b480a26b8..57eca760b2 --- a/manifest.uuid +++ b/manifest.uuid @@@ -1,1 -1,1 +1,1 @@@ - 3c15a9bf45cd7dae2fbd99123b8dd75ce278d6e4 -f047920ce16971e573bc6ec9a48b118c9de2b3a7 ++7abc2dd953477797fa05421b061d73596aa025fb diff --cc src/test_bestindex.c index 6982ce3ca9,0000000000..ab10463fd9 mode 100644,000000..100644 --- a/src/test_bestindex.c +++ b/src/test_bestindex.c @@@ -1,566 -1,0 +1,564 @@@ +/* +** 2016-03-01 +** +** 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 the virtual table xBestIndex method and the query +** planner. +*/ + + +/* +** INSTRUCTIONS +** +** This module exports a single tcl command - [register_tcl_module]. When +** invoked, it registers a special virtual table module with a database +** connection. +** +** The virtual table is currently read-only. And always returns zero rows. +** It is created with a single argument - the name of a Tcl command - as +** follows: +** +** CREATE VIRTUAL TABLE x1 USING tcl(tcl_command); +** +** The command [tcl_command] is invoked when the table is first created (or +** connected), when the xBestIndex() method is invoked and when the xFilter() +** method is called. When it is created (or connected), it is invoked as +** follows: +** +** tcl_command xConnect +** +** In this case the return value of the script is passed to the +** sqlite3_declare_vtab() function to create the virtual table schema. +** +** When the xBestIndex() method is called by SQLite, the Tcl command is +** invoked as: +** +** tcl_command xBestIndex CONSTRAINTS ORDERBY MASK +** +** where CONSTRAINTS is a tcl representation of the aConstraints[] array, +** ORDERBY is a representation of the contents of the aOrderBy[] array and +** MASK is a copy of sqlite3_index_info.colUsed. For example if the virtual +** table is declared as: +** +** CREATE TABLE x1(a, b, c) +** +** and the query is: +** +** SELECT * FROM x1 WHERE a=? AND c module name ("fs") +** argv[1] -> database name +** argv[2] -> table name +** argv[...] -> other module argument fields. +*/ +static int tclConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + Tcl_Interp *interp = (Tcl_Interp*)pAux; + tcl_vtab *pTab; + const char *zCmd; + Tcl_Obj *pScript = 0; + int rc; + + if( argc!=4 ){ + *pzErr = sqlite3_mprintf("wrong number of arguments"); + return SQLITE_ERROR; + } + zCmd = argv[3]; + + pTab = (tcl_vtab*)sqlite3_malloc(sizeof(tcl_vtab)); + if( pTab==0 ) return SQLITE_NOMEM; + memset(pTab, 0, sizeof(tcl_vtab)); + + pTab->pCmd = Tcl_NewStringObj(zCmd, -1); + pTab->interp = interp; + pTab->db = db; + Tcl_IncrRefCount(pTab->pCmd); + + pScript = Tcl_DuplicateObj(pTab->pCmd); + Tcl_IncrRefCount(pScript); + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xConnect", -1)); + + rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL); + if( rc!=TCL_OK ){ + *pzErr = sqlite3_mprintf("%s", Tcl_GetStringResult(interp)); + rc = SQLITE_ERROR; + }else{ + rc = sqlite3_declare_vtab(db, Tcl_GetStringResult(interp)); + } + + if( rc!=SQLITE_OK ){ + sqlite3_free(pTab); + pTab = 0; + } + + *ppVtab = &pTab->base; + return rc; +} + +/* The xDisconnect and xDestroy methods are also the same */ +static int tclDisconnect(sqlite3_vtab *pVtab){ + tcl_vtab *pTab = (tcl_vtab*)pVtab; + Tcl_DecrRefCount(pTab->pCmd); + sqlite3_free(pTab); + return SQLITE_OK; +} + +/* +** Open a new tcl cursor. +*/ +static int tclOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + tcl_cursor *pCur; + pCur = sqlite3_malloc(sizeof(tcl_cursor)); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(tcl_cursor)); + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* +** Close a tcl cursor. +*/ +static int tclClose(sqlite3_vtab_cursor *cur){ + tcl_cursor *pCur = (tcl_cursor *)cur; + if( pCur ){ + sqlite3_finalize(pCur->pStmt); + sqlite3_free(pCur); + } + return SQLITE_OK; +} + +static int tclNext(sqlite3_vtab_cursor *pVtabCursor){ + tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; - tcl_vtab *pTab = (tcl_vtab*)(pVtabCursor->pVtab); + if( pCsr->pStmt ){ + tcl_vtab *pTab = (tcl_vtab*)(pVtabCursor->pVtab); + int rc = sqlite3_step(pCsr->pStmt); + if( rc!=SQLITE_ROW ){ + const char *zErr; + rc = sqlite3_finalize(pCsr->pStmt); + pCsr->pStmt = 0; + if( rc!=SQLITE_OK ){ + zErr = sqlite3_errmsg(pTab->db); + pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); + } + } + } + return SQLITE_OK; +} + +static int tclFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; + tcl_vtab *pTab = (tcl_vtab*)(pVtabCursor->pVtab); + Tcl_Interp *interp = pTab->interp; + Tcl_Obj *pScript; + Tcl_Obj *pArg; + int ii; + int rc; + + pScript = Tcl_DuplicateObj(pTab->pCmd); + Tcl_IncrRefCount(pScript); + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xFilter", -1)); + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewIntObj(idxNum)); + if( idxStr ){ + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(idxStr, -1)); + }else{ + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("", -1)); + } + + pArg = Tcl_NewObj(); + Tcl_IncrRefCount(pArg); + for(ii=0; iibase.zErrMsg = sqlite3_mprintf("%s", zErr); + }else{ + /* Analyze the scripts return value. The return value should be a tcl + ** list object with an even number of elements. The first element of each + ** pair must be one of: + ** + ** "sql" (SQL statement to return data) + */ + Tcl_Obj *pRes = Tcl_GetObjResult(interp); + Tcl_Obj **apElem = 0; + int nElem; + rc = Tcl_ListObjGetElements(interp, pRes, &nElem, &apElem); + if( rc!=TCL_OK ){ + const char *zErr = Tcl_GetStringResult(interp); + rc = SQLITE_ERROR; + pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); + }else{ - int iArgv = 1; + for(ii=0; rc==SQLITE_OK && iidb, zSql, -1, &pCsr->pStmt, 0); + if( rc!=SQLITE_OK ){ + const char *zErr = sqlite3_errmsg(pTab->db); + pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zErr); + } + }else{ + rc = SQLITE_ERROR; + pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zCmd); + } + } + } + } + + if( rc==SQLITE_OK ){ + rc = tclNext(pVtabCursor); + } + return rc; +} + +static int tclColumn( + sqlite3_vtab_cursor *pVtabCursor, + sqlite3_context *ctx, + int i +){ + tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; + sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, i+1)); + return SQLITE_OK; +} + +static int tclRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){ + tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; + *pRowid = sqlite3_column_int64(pCsr->pStmt, 0); + return SQLITE_OK; +} + +static int tclEof(sqlite3_vtab_cursor *pVtabCursor){ + tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; + return (pCsr->pStmt==0); +} + +static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ + tcl_vtab *pTab = (tcl_vtab*)tab; + Tcl_Interp *interp = pTab->interp; + Tcl_Obj *pArg; + Tcl_Obj *pScript; + int ii; + int rc = SQLITE_OK; + + pScript = Tcl_DuplicateObj(pTab->pCmd); + Tcl_IncrRefCount(pScript); + Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xBestIndex", -1)); + + pArg = Tcl_NewObj(); + Tcl_IncrRefCount(pArg); + for(ii=0; iinConstraint; ii++){ + struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii]; + Tcl_Obj *pElem = Tcl_NewObj(); + const char *zOp = "?"; + + Tcl_IncrRefCount(pElem); + + switch( pCons->op ){ + case SQLITE_INDEX_CONSTRAINT_EQ: + zOp = "eq"; break; + case SQLITE_INDEX_CONSTRAINT_GT: + zOp = "gt"; break; + case SQLITE_INDEX_CONSTRAINT_LE: + zOp = "le"; break; + case SQLITE_INDEX_CONSTRAINT_LT: + zOp = "lt"; break; + case SQLITE_INDEX_CONSTRAINT_GE: + zOp = "ge"; break; + case SQLITE_INDEX_CONSTRAINT_MATCH: + zOp = "match"; break; + case SQLITE_INDEX_CONSTRAINT_LIKE: + zOp = "like"; break; + case SQLITE_INDEX_CONSTRAINT_GLOB: + zOp = "glob"; break; + case SQLITE_INDEX_CONSTRAINT_REGEXP: + zOp = "regexp"; break; + } + + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("op", -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zOp, -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("column", -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->iColumn)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("usable", -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->usable)); + + Tcl_ListObjAppendElement(0, pArg, pElem); + Tcl_DecrRefCount(pElem); + } + + Tcl_ListObjAppendElement(0, pScript, pArg); + Tcl_DecrRefCount(pArg); + + pArg = Tcl_NewObj(); + Tcl_IncrRefCount(pArg); + for(ii=0; iinOrderBy; ii++){ + struct sqlite3_index_orderby const *pOrder = &pIdxInfo->aOrderBy[ii]; + Tcl_Obj *pElem = Tcl_NewObj(); + Tcl_IncrRefCount(pElem); + + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("column", -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pOrder->iColumn)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("desc", -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pOrder->desc)); + + Tcl_ListObjAppendElement(0, pArg, pElem); + Tcl_DecrRefCount(pElem); + } + + Tcl_ListObjAppendElement(0, pScript, pArg); + Tcl_DecrRefCount(pArg); + + Tcl_ListObjAppendElement(0, pScript, Tcl_NewWideIntObj(pIdxInfo->colUsed)); + + rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL); + Tcl_DecrRefCount(pScript); + if( rc!=TCL_OK ){ + const char *zErr = Tcl_GetStringResult(interp); + rc = SQLITE_ERROR; + pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); + }else{ + /* Analyze the scripts return value. The return value should be a tcl + ** list object with an even number of elements. The first element of each + ** pair must be one of: + ** + ** "orderby" (value of orderByConsumed flag) + ** "cost" (value of estimatedCost field) + ** "rows" (value of estimatedRows field) + ** "use" (index of used constraint in aConstraint[]) + ** "idxnum" (value of idxNum field) + ** "idxstr" (value of idxStr field) + ** "omit" (index of omitted constraint in aConstraint[]) + */ + Tcl_Obj *pRes = Tcl_GetObjResult(interp); + Tcl_Obj **apElem = 0; + int nElem; + rc = Tcl_ListObjGetElements(interp, pRes, &nElem, &apElem); + if( rc!=TCL_OK ){ + const char *zErr = Tcl_GetStringResult(interp); + rc = SQLITE_ERROR; + pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); + }else{ + int iArgv = 1; + for(ii=0; rc==SQLITE_OK && iiestimatedCost); + }else + if( sqlite3_stricmp("orderby", zCmd)==0 ){ + rc = Tcl_GetIntFromObj(interp, p, &pIdxInfo->orderByConsumed); + }else + if( sqlite3_stricmp("idxnum", zCmd)==0 ){ + rc = Tcl_GetIntFromObj(interp, p, &pIdxInfo->idxNum); + }else + if( sqlite3_stricmp("idxstr", zCmd)==0 ){ + sqlite3_free(pIdxInfo->idxStr); + pIdxInfo->idxStr = sqlite3_mprintf("%s", Tcl_GetString(p)); + pIdxInfo->needToFreeIdxStr = 1; + }else + if( sqlite3_stricmp("rows", zCmd)==0 ){ + rc = Tcl_GetWideIntFromObj(interp, p, &pIdxInfo->estimatedRows); + }else + if( sqlite3_stricmp("use", zCmd)==0 + || sqlite3_stricmp("omit", zCmd)==0 + ){ + int iCons; + rc = Tcl_GetIntFromObj(interp, p, &iCons); + if( rc==SQLITE_OK ){ + if( iCons<0 || iCons>=pIdxInfo->nConstraint ){ + rc = SQLITE_ERROR; + pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %d", iCons); + }else{ + int bOmit = (zCmd[0]=='o' || zCmd[0]=='O'); + pIdxInfo->aConstraintUsage[iCons].argvIndex = iArgv++; + pIdxInfo->aConstraintUsage[iCons].omit = bOmit; + } + } + }else{ + rc = SQLITE_ERROR; + pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zCmd); + } + if( rc!=SQLITE_OK && pTab->base.zErrMsg==0 ){ + const char *zErr = Tcl_GetStringResult(interp); + pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); + } + } + } + } + + return rc; +} + +/* +** A virtual table module that provides read-only access to a +** Tcl global variable namespace. +*/ +static sqlite3_module tclModule = { + 0, /* iVersion */ + tclConnect, + tclConnect, + tclBestIndex, + tclDisconnect, + tclDisconnect, + tclOpen, /* xOpen - open a cursor */ + tclClose, /* xClose - close a cursor */ + tclFilter, /* xFilter - configure scan constraints */ + tclNext, /* xNext - advance a cursor */ + tclEof, /* xEof - check for end of scan */ + tclColumn, /* xColumn - read data */ + tclRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ +}; + +/* +** Decode a pointer to an sqlite3 object. +*/ +extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); + +/* +** Register the echo virtual table module. +*/ +static int register_tcl_module( + 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 */ +){ + sqlite3 *db; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3_create_module(db, "tcl", &tclModule, (void *)interp); +#endif + return TCL_OK; +} + +#endif + + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetesttcl_Init(Tcl_Interp *interp){ +#ifndef SQLITE_OMIT_VIRTUALTABLE + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + void *clientData; + } aObjCmd[] = { + { "register_tcl_module", register_tcl_module, 0 }, + }; + int i; + for(i=0; i