diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 955489a35a..3d6616bd91 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -2878,7 +2878,8 @@ static void fts5MultiIterNext2( ){ assert( pIter->bSkipEmpty ); if( p->rc==SQLITE_OK ){ - do { + *pbNewTerm = 0; + do{ int iFirst = pIter->aFirst[1].iFirst; Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; int bNewTerm = 0; @@ -2891,8 +2892,6 @@ static void fts5MultiIterNext2( fts5MultiIterAdvanced(p, pIter, iFirst, 1); fts5MultiIterSetEof(pIter); *pbNewTerm = 1; - }else{ - *pbNewTerm = 0; } fts5AssertMultiIterSetup(p, pIter); @@ -3845,9 +3844,6 @@ static void fts5WriteFlushLeaf(Fts5Index *p, Fts5SegWriter *pWriter){ Fts5PageWriter *pPage = &pWriter->writer; i64 iRowid; -static int nCall = 0; -nCall++; - assert( (pPage->pgidx.n==0)==(pWriter->bFirstTermInPage) ); /* Set the szLeaf header field. */ diff --git a/ext/fts5/fts5_test_tok.c b/ext/fts5/fts5_test_tok.c index 10af126c10..cfc7a8b904 100644 --- a/ext/fts5/fts5_test_tok.c +++ b/ext/fts5/fts5_test_tok.c @@ -40,7 +40,7 @@ */ #if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_FTS5) -#include +#include "fts5.h" #include #include diff --git a/ext/fts5/test/fts5aa.test b/ext/fts5/test/fts5aa.test index 9a95d81cfb..64c5331c64 100644 --- a/ext/fts5/test/fts5aa.test +++ b/ext/fts5/test/fts5aa.test @@ -577,6 +577,20 @@ do_execsql_test 21.1 { COMMIT; } +do_execsql_test 22.0 { + CREATE VIRTUAL TABLE t9 USING fts5(x, detail=%DETAIL%); + INSERT INTO t9(rowid, x) VALUES(2, 'bbb'); + BEGIN; + INSERT INTO t9(rowid, x) VALUES(1, 'aaa'); + DELETE FROM t9 WHERE rowid = 2; + INSERT INTO t9(rowid, x) VALUES(3, 'bbb'); + COMMIT; +} + +do_execsql_test 22.1 { + SELECT rowid FROM t9('a*') +} {1} + } diff --git a/manifest b/manifest index 02667e9490..d5f08dc338 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Another\sminor\sformatting\sfix. -D 2017-04-21T19:58:35.957 +C Update\sthis\sbranch\swith\slatest\strunk\schanges. +D 2017-05-01T14:25:34.571 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -111,12 +111,12 @@ F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 F ext/fts5/fts5_expr.c f2825f714d91bbe62ab5820aee9ad12e0c94205b2a01725eaa9072415ae9ff1c F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2 -F ext/fts5/fts5_index.c 551add2b7762a2857336747def3b9d4fa304df476e188fb323492e2fd851772b +F ext/fts5/fts5_index.c dc25123df20c60492857de491a194dab4b46ace217b8483bda305d357bf6431d F ext/fts5/fts5_main.c 1ba0e7806886c1bc16e20d0dde1c2b535d1aeb98cbbb937c4c3e064af5ac6f03 F ext/fts5/fts5_storage.c 7750986004f3f0c94619a85ecb5dd6cbef53e5e3853488e8a906c269d4d11db6 F ext/fts5/fts5_tcl.c 4a901f00c8553740dba63511603f5527d741c26a F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc -F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be +F ext/fts5/fts5_test_tok.c f4c27f2e3200653a458f5316f6aaa863f7532d98fff7534ece3670fb7f2c196b F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 @@ -124,7 +124,7 @@ F ext/fts5/fts5_vocab.c e44fefa7f0c1db252998af071daf06a7147e17e7 F ext/fts5/fts5parse.y a070b538e08ae9e2177d15c337ed2a3464408f0f886e746307098f746efd94ca F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841 -F ext/fts5/test/fts5aa.test b3cb080db4851580705c5e261c9d4308edf030d5cbbc24b5d6668403b73f023b +F ext/fts5/test/fts5aa.test 6dd1bfa4426a8d77e8c8d447aad02515c85118b082f24053ac89802300077ff1 F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b F ext/fts5/test/fts5ac.test 55cad4275a1f5acabfe14d8442a8046b47e49e5f F ext/fts5/test/fts5ad.test 36995f0586f30f5602074e012b9224c71ec5171c @@ -351,14 +351,14 @@ F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca -F src/btree.c 24ae5472bd0b53b4130ecdda389deb621af721d1fcb50890b878102b00bd10fa +F src/btree.c a0d9a1c782ff3d22df5d217a4fa7125dd69ad5849caa51c4442c10246ca8ae27 F src/btree.h 80f518c0788be6cec8d9f8e13bd8e380df299d2b5e4ac340dc887b0642647cfc F src/btreeInt.h a392d353104b4add58b4a59cb185f5d5693dde832c565b77d8d4c343ed98f610 F src/build.c 3fd46781483b527ee18508e7854e87e60a259211bb9bbf16b6fafaf08a043a64 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 47d91a25ad8f199a71a5b1b7b169d6dd0d6e98c5719eca801568798743d1161c -F src/date.c ee676e7694dfadbdd2fde1a258a71be8360ba5ae +F src/date.c cc42a41c7422389860d40419a5e3bce5eaf6e7835c3ba2677751dc653550a5c7 F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d F src/delete.c 0d9d5549d42e79ce4d82ff1db1e6c81e36d2f67c F src/expr.c f10e35dc50be4c8f82eb99bf5d8530229d1d60957cc3c9473ffe584d0444087c @@ -408,7 +408,7 @@ F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 3e518b962d932a997fae373366880fc028c75706 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c bf8ab605e49717c222136380453cfb7eda564f8e500d5ff6a01341ea59fefe80 +F src/select.c 478e95d424bb86d34c7c95d20872cbd78df97af5f83c3fd7de55d5b2413f927d F src/shell.c 21b79c0e1b93f8e35fd7b4087d6ba438326c3d7e285d0dd51dfd741475f858a1 F src/sqlite.h.in 900a07463a87be50b9954817f4c24a0660b4c4ddc1bfe83dedea484c6ac98425 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -475,7 +475,7 @@ F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6 F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569 -F src/vdbe.c 857fd5fe839b2ce4b999f4c0e17106963f0cb96f5e8ba20ebb22701267c09af2 +F src/vdbe.c a4e1810c3b2a8119d08746d20ac9bab5d15c0ebed319ea1f57910948414ed114 F src/vdbe.h f7d1456e28875c2dcb964056589b5b7149ab7edf39edeca801596a39bb3d3848 F src/vdbeInt.h c070bc5c8b913bda0ceaa995cd4d939ded5e4fc96cf7c3c1c602d41b871f8ade F src/vdbeapi.c 5b08d82592bcff4470601fe78aaabebd50837860 @@ -484,14 +484,14 @@ F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9 F src/vdbemem.c 2c70f8f5de6c71fb99a22c5b83be9fab5c47cdd8e279fa44a8c00cfed06d7e89 F src/vdbesort.c e72fe02a2121386ba767ede8942e9450878b8fc873abf3d1b6824485f092570c F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834 -F src/vtab.c 007513c2ef52472fcdea6a741683d50662e82790 +F src/vtab.c 35b9bdc2b41de32a417141d12097bcc4e29a77ed7cdb8f836d1d2305d946b61b F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344 F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71 F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791 F src/where.c a12df4e97aec78ec37e3aa92eea6d889ef3cd9ce5cfe6b682bf1243c743d897c F src/whereInt.h 2a4b634d63ce488b46d4b0da8f2eaa8f9aeab202bc25ef76f007de5e3fba1f20 -F src/wherecode.c 943e32e9dccd0af802e0683ae11071c8bd808364e5908a5fb66758bd404c8681 +F src/wherecode.c 8ad48867660519e262a401720845dc76934f86f558ec9606335fafcd7a2554f8 F src/whereexpr.c e913aaa7b73ffcce66abcea5f197e2c538d48b5df78d0b7bba8ff4d73cc2e745 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -582,6 +582,7 @@ F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3 F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0 F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61 +F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9 F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738 F test/capi3.test f0c66919e43d42e1572a69be039e4527a931b00f F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 @@ -866,7 +867,7 @@ F test/in.test 20c5529986998949908f889c8208b2cd894b2cc9 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068 -F test/in5.test 6c006e0bcd7351b69350ef566e65f244023489e9 +F test/in5.test 7ae37fcd4a5e198291c6ab5f31a5bb3d15397efe8b75a6736d7a95a7b8dd9e08 F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822 F test/incrblob2.test a5ce5ed1d0b01e2ed347245a21170372528af0a5 F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4 @@ -888,7 +889,7 @@ F test/index7.test 7feababe16f2091b229c22aff2bcc1d4d6b9d2bb F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7 F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985 F test/indexexpr1.test 038b3befa74e5a75126b6e9dd2ae5df61c1c7cf7 -F test/indexexpr2.test bcf694ae72efaaeb97691b990b61e39bf233884e27b9cc6b845a1f0c6bc9f0bb +F test/indexexpr2.test 68ee9dbe83fcf85e50f4d0bd1f742a082496f2ee5153f4be2a1861db84462bf7 F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371 @@ -1048,6 +1049,7 @@ F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc F test/printf2.test 9e6db85f81c63f2367c34a9d7db384088bd374ad F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc +F test/pushdown.test a5d2e5e66cc94cfb0989a5dd23e77427dd6c4313019155ba9051f52dfc5326aa F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26 @@ -1507,7 +1509,7 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f -F tool/lemon.c 6b0cdffb377e79c6295c40300677688f3d35c21c0154da635642ef82dc3a5836 +F tool/lemon.c f4f1045743e12f86b132253a3192ef92c94bfceb7f41ac41b8e3b373aa78474e F tool/lempar.c db1bdb4821f2d8fbd76e577cf3ab18642c8d08d1 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 @@ -1582,7 +1584,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P da9a2e5aa977f7e8e9e4365f7b34bb4f482029a3d44646100773cedc8ea9b959 -R 5d55911452a98d7b9a566802f4defda8 +P 9fa2ce3c2b75408594d387684984cd946765776d30bc622a1f4e64d6fe1856d5 4e1df76e3d85922648e0e1cce73a266c3b1ed4511ace259ec0a01d7693af9e6f +R c99d2e434f8eea958d565fc3fbededc3 U dan -Z bc8b305bc880d9cdf8a4b644dabd4fac +Z e2770623607bd1150c892792253a1e62 diff --git a/manifest.uuid b/manifest.uuid index d9908b5ae2..f027c61c4c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9fa2ce3c2b75408594d387684984cd946765776d30bc622a1f4e64d6fe1856d5 \ No newline at end of file +11f4761c3a84e2cc9df62f117a003af8c57f3d226eec5a40d6241b121e78d002 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 48cfae5c72..35e47173fa 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8124,9 +8124,6 @@ int sqlite3BtreeInsert( ** btreeMoveto() call */ if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ loc = 0; - }else if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey>0 - && pCur->info.nKey==pX->nKey-1 ){ - loc = -1; }else if( loc==0 ){ rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc); if( rc ) return rc; diff --git a/src/date.c b/src/date.c index b49d506bc4..f668ad0a84 100644 --- a/src/date.c +++ b/src/date.c @@ -423,8 +423,10 @@ static void computeYMD(DateTime *p){ p->Y = 2000; p->M = 1; p->D = 1; + }else if( !validJulianDay(p->iJD) ){ + datetimeError(p); + return; }else{ - assert( validJulianDay(p->iJD) ); Z = (int)((p->iJD + 43200000)/86400000); A = (int)((Z - 1867216.25)/36524.25); A = Z + 1 + A - (A/4); diff --git a/src/select.c b/src/select.c index 3def13618e..77824c4aaa 100644 --- a/src/select.c +++ b/src/select.c @@ -5035,6 +5035,10 @@ int sqlite3Select( ** to be invoked again. */ if( pItem->addrFillSub ){ if( pItem->fg.viaCoroutine==0 ){ + /* The subroutine that manifests the view might be a one-time routine, + ** or it might need to be rerun on each iteration because it + ** encodes a correlated subquery. */ + testcase( sqlite3VdbeGetOp(v, pItem->addrFillSub)->opcode==OP_Once ); sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub); } continue; diff --git a/src/vdbe.c b/src/vdbe.c index 6f9d3e18b9..126c2d5657 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -764,7 +764,7 @@ jump_to_p2_and_check_for_interrupt: pOp = &aOp[pOp->p2 - 1]; /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, - ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon + ** OP_VNext, or OP_SorterNext) all jump here upon ** completion. Check to see if sqlite3_interrupt() has been called ** or if the progress callback needs to be invoked. ** @@ -1567,7 +1567,7 @@ arithmetic_result_is_null: /* Opcode: CollSeq P1 * * P4 ** -** P4 is a pointer to a CollSeq struct. If the next call to a user function +** P4 is a pointer to a CollSeq object. If the next call to a user function ** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will ** be returned. This is used by the built-in min(), max() and nullif() ** functions. @@ -1848,11 +1848,11 @@ case OP_RealAffinity: { /* in1 */ ** Force the value in register P1 to be the type defined by P2. ** **
    -**
  • TEXT -**
  • BLOB -**
  • NUMERIC -**
  • INTEGER -**
  • REAL +**
  • P2=='A' → BLOB +**
  • P2=='B' → TEXT +**
  • P2=='C' → NUMERIC +**
  • P2=='D' → INTEGER +**
  • P2=='E' → REAL **
** ** A NULL value is not changed by this routine. It remains NULL. @@ -2723,8 +2723,8 @@ op_column_out: ** ** Apply affinities to a range of P2 registers starting with P1. ** -** P4 is a string that is P2 characters long. The nth character of the -** string indicates the column affinity that should be used for the nth +** P4 is a string that is P2 characters long. The N-th character of the +** string indicates the column affinity that should be used for the N-th ** memory cell in the range. */ case OP_Affinity: { @@ -2751,8 +2751,8 @@ case OP_Affinity: { ** use as a data record in a database table or as a key ** in an index. The OP_Column opcode can decode the record later. ** -** P4 may be a string that is P2 characters long. The nth character of the -** string indicates the column affinity that should be used for the nth +** P4 may be a string that is P2 characters long. The N-th character of the +** string indicates the column affinity that should be used for the N-th ** field of the index key. ** ** The mapping from character to affinity is given by the SQLITE_AFF_ @@ -5748,7 +5748,7 @@ case OP_IntegrityCk: { /* Opcode: RowSetAdd P1 P2 * * * ** Synopsis: rowset(P1)=r[P2] ** -** Insert the integer value held by register P2 into a boolean index +** Insert the integer value held by register P2 into a RowSet object ** held in register P1. ** ** An assertion fails if P2 is not an integer. @@ -5768,8 +5768,9 @@ case OP_RowSetAdd: { /* in1, in2 */ /* Opcode: RowSetRead P1 P2 P3 * * ** Synopsis: r[P3]=rowset(P1) ** -** Extract the smallest value from boolean index P1 and put that value into -** register P3. Or, if boolean index P1 is initially empty, leave P3 +** Extract the smallest value from the RowSet object in P1 +** and put that value into register P3. +** Or, if RowSet object P1 is initially empty, leave P3 ** unchanged and jump to instruction P2. */ case OP_RowSetRead: { /* jump, in1, out3 */ @@ -5800,15 +5801,14 @@ case OP_RowSetRead: { /* jump, in1, out3 */ ** integer in P3 into the RowSet and continue on to the ** next opcode. ** -** The RowSet object is optimized for the case where successive sets -** of integers, where each set contains no duplicates. Each set -** of values is identified by a unique P4 value. The first set -** must have P4==0, the final set P4=-1. P4 must be either -1 or -** non-negative. For non-negative values of P4 only the lower 4 -** bits are significant. +** The RowSet object is optimized for the case where sets of integers +** are inserted in distinct phases, which each set contains no duplicates. +** Each set is identified by a unique P4 value. The first set +** must have P4==0, the final set must have P4==-1, and for all other sets +** must have P4>0. ** ** This allows optimizations: (a) when P4==0 there is no need to test -** the rowset object for P3, as it is guaranteed not to contain it, +** the RowSet object for P3, as it is guaranteed not to contain it, ** (b) when P4==-1 there is no need to insert the value, as it will ** never be tested for, and (c) when a value that is part of set X is ** inserted, there is no need to search to see if the same value was diff --git a/src/vtab.c b/src/vtab.c index 48891034d5..e603e921e6 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -1053,7 +1053,7 @@ FuncDef *sqlite3VtabOverloadFunction( if( NEVER(pExpr==0) ) return pDef; if( pExpr->op!=TK_COLUMN ) return pDef; pTab = pExpr->pTab; - if( NEVER(pTab==0) ) return pDef; + if( pTab==0 ) return pDef; if( !IsVirtual(pTab) ) return pDef; pVtab = sqlite3GetVTable(db, pTab)->pVtab; assert( pVtab!=0 ); diff --git a/src/wherecode.c b/src/wherecode.c index d429fbb523..feda45f911 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1129,6 +1129,8 @@ Bitmask sqlite3WhereCodeOneLoopStart( int addrCont; /* Jump here to continue with next cycle */ int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ int iReleaseReg = 0; /* Temp register to free before returning */ + Index *pIdx = 0; /* Index used by loop (if any) */ + int loopAgain; /* True if constraint generator loop should repeat */ pParse = pWInfo->pParse; v = pParse->pVdbe; @@ -1454,7 +1456,6 @@ Bitmask sqlite3WhereCodeOneLoopStart( int endEq; /* True if range end uses ==, >= or <= */ int start_constraints; /* Start of range is constrained */ int nConstraint; /* Number of constraint terms */ - Index *pIdx; /* The index we will be using */ int iIdxCur; /* The VDBE cursor for the index */ int nExtraReg = 0; /* Number of extra registers needed */ int op; /* Instruction opcode */ @@ -1705,6 +1706,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( }else{ assert( pLevel->p5==0 ); } + if( omitTable ) pIdx = 0; }else #ifndef SQLITE_OMIT_OR_OPTIMIZATION @@ -2022,43 +2024,56 @@ Bitmask sqlite3WhereCodeOneLoopStart( /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. + ** + ** This loop may run either once (pIdx==0) or twice (pIdx!=0). If + ** it is run twice, then the first iteration codes those sub-expressions + ** that can be computed using columns from pIdx only (without seeking + ** the main table cursor). */ - for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ - Expr *pE; - int skipLikeAddr = 0; - testcase( pTerm->wtFlags & TERM_VIRTUAL ); - testcase( pTerm->wtFlags & TERM_CODED ); - if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( (pTerm->prereqAll & pLevel->notReady)!=0 ){ - testcase( pWInfo->untestedTerms==0 - && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ); - pWInfo->untestedTerms = 1; - continue; - } - pE = pTerm->pExpr; - assert( pE!=0 ); - if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ - continue; - } - if( pTerm->wtFlags & TERM_LIKECOND ){ - /* If the TERM_LIKECOND flag is set, that means that the range search - ** is sufficient to guarantee that the LIKE operator is true, so we - ** can skip the call to the like(A,B) function. But this only works - ** for strings. So do not skip the call to the function on the pass - ** that compares BLOBs. */ + do{ + loopAgain = 0; + for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ + Expr *pE; + int skipLikeAddr = 0; + testcase( pTerm->wtFlags & TERM_VIRTUAL ); + testcase( pTerm->wtFlags & TERM_CODED ); + if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; + if( (pTerm->prereqAll & pLevel->notReady)!=0 ){ + testcase( pWInfo->untestedTerms==0 + && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ); + pWInfo->untestedTerms = 1; + continue; + } + pE = pTerm->pExpr; + assert( pE!=0 ); + if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ + continue; + } + if( pIdx && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){ + loopAgain = 1; + continue; + } + if( pTerm->wtFlags & TERM_LIKECOND ){ + /* If the TERM_LIKECOND flag is set, that means that the range search + ** is sufficient to guarantee that the LIKE operator is true, so we + ** can skip the call to the like(A,B) function. But this only works + ** for strings. So do not skip the call to the function on the pass + ** that compares BLOBs. */ #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS - continue; + continue; #else - u32 x = pLevel->iLikeRepCntr; - assert( x>0 ); - skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)? OP_IfNot : OP_If, (int)(x>>1)); - VdbeCoverage(v); + u32 x = pLevel->iLikeRepCntr; + assert( x>0 ); + skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If, (int)(x>>1)); + VdbeCoverage(v); #endif + } + sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); + if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr); + pTerm->wtFlags |= TERM_CODED; } - sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); - if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr); - pTerm->wtFlags |= TERM_CODED; - } + pIdx = 0; + }while( loopAgain ); /* Insert code to test for implied constraints based on transitivity ** of the "==" operator. diff --git a/test/cachespill.test b/test/cachespill.test new file mode 100644 index 0000000000..069251354f --- /dev/null +++ b/test/cachespill.test @@ -0,0 +1,77 @@ +# 2017 April 26 +# +# 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. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix cachespill + +ifcapable !pager_pragmas { + finish_test + return +} + +#------------------------------------------------------------------------- +# Test that "PRAGMA cache_spill = 0" completely disables cache spilling. +# +do_execsql_test 1.1 { + PRAGMA auto_vacuum = 0; + PRAGMA page_size = 1024; + PRAGMA cache_size = 100; + CREATE TABLE t1(a); +} + +do_test 1.2 { + file size test.db +} {2048} + +do_test 1.3 { + execsql { + BEGIN; + WITH s(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<200 + ) INSERT INTO t1 SELECT randomblob(900) FROM s; + } + expr {[file size test.db] > 50000} +} {1} + +do_test 1.4 { + execsql ROLLBACK + file size test.db +} {2048} + +do_test 1.5 { + execsql { + PRAGMA cache_spill = 0; + BEGIN; + WITH s(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<200 + ) INSERT INTO t1 SELECT randomblob(900) FROM s; + } + file size test.db +} {2048} + +do_test 1.5 { + execsql { + ROLLBACK; + PRAGMA cache_spill = 1; + BEGIN; + WITH s(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<200 + ) INSERT INTO t1 SELECT randomblob(900) FROM s; + } + expr {[file size test.db] > 50000} +} {1} + +do_execsql_test 1.6 { ROLLBACK } + + +finish_test diff --git a/test/in5.test b/test/in5.test index ac60cfe58e..a5ea7c1784 100644 --- a/test/in5.test +++ b/test/in5.test @@ -237,4 +237,16 @@ do_execsql_test 8.4 { SELECT count(*) FROM n1 WHERE a IN (SELECT +a FROM n1) } 3 +#------------------------------------------------------------------------- +# Test that ticket 61fe97454c is fixed. +# +do_execsql_test 9.0 { + CREATE TABLE t9(a INTEGER PRIMARY KEY); + INSERT INTO t9 VALUES (44), (45); +} +do_execsql_test 9.1 { + SELECT * FROM t9 WHERE a IN (44, 45, 44, 45) +} {44 45} + + finish_test diff --git a/test/indexexpr2.test b/test/indexexpr2.test index 140498b124..47d50de3ef 100644 --- a/test/indexexpr2.test +++ b/test/indexexpr2.test @@ -32,5 +32,13 @@ do_execsql_test 1.2 { SELECT 'TWOX' == (b || 'x') COLLATE nocase FROM t1 WHERE (b || 'x')>'onex' } {0 1} +do_execsql_test 2.0 { + CREATE INDEX i2 ON t1(a+1); +} + +do_execsql_test 2.1 { + SELECT a+1, quote(a+1) FROM t1 ORDER BY 1; +} {2 2 3 3 4 4} + finish_test diff --git a/test/pushdown.test b/test/pushdown.test new file mode 100644 index 0000000000..5be6054c08 --- /dev/null +++ b/test/pushdown.test @@ -0,0 +1,59 @@ +# 2017 April 29 +# +# 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. +# +#*********************************************************************** + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix pushdown + +do_execsql_test 1.0 { + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES(1, 'b1', 'c1'); + INSERT INTO t1 VALUES(2, 'b2', 'c2'); + INSERT INTO t1 VALUES(3, 'b3', 'c3'); + INSERT INTO t1 VALUES(4, 'b4', 'c4'); + CREATE INDEX i1 ON t1(a, c); +} + +proc f {val} { + lappend ::L $val + return 0 +} +db func f f + +do_test 1.1 { + set L [list] + execsql { SELECT * FROM t1 WHERE a=2 AND f(b) AND f(c) } + set L +} {c2} + +do_test 1.2 { + set L [list] + execsql { SELECT * FROM t1 WHERE a=3 AND f(c) AND f(b) } + set L +} {c3} + +do_execsql_test 1.3 { + DROP INDEX i1; + CREATE INDEX i1 ON t1(a, b); +} +do_test 1.4 { + set L [list] + execsql { SELECT * FROM t1 WHERE a=2 AND f(b) AND f(c) } + set L +} {b2} + +do_test 1.5 { + set L [list] + execsql { SELECT * FROM t1 WHERE a=3 AND f(c) AND f(b) } + set L +} {b3} + +finish_test diff --git a/tool/lemon.c b/tool/lemon.c index af8e4de12c..37d2c781d9 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -4161,7 +4161,7 @@ void ReportTable( for(i=0; inxstate; i++){ for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){ if( ap->type==REDUCE || ap->type==SHIFTREDUCE ){ - ap->x.rp->doesReduce = i; + ap->x.rp->doesReduce = 1; } } }