Merge trunk changes into this branch.

FossilOrigin-Name: d5b7c5a88dd58de85b3060a1f28b6d96e6e21207
This commit is contained in:
dan 2014-10-13 18:09:13 +00:00
commit d0b8f93b5f
47 changed files with 1256 additions and 690 deletions

View File

@ -3116,6 +3116,7 @@ static int fts3FilterMethod(
/* In case the cursor has been used before, clear it now. */
sqlite3_finalize(pCsr->pStmt);
sqlite3_free(pCsr->aDoclist);
sqlite3_free(pCsr->aMatchinfo);
sqlite3Fts3ExprFree(pCsr->pExpr);
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
@ -4426,7 +4427,7 @@ static int fts3EvalIncrPhraseNext(
bMaxSet = 1;
}
}
assert( rc!=SQLITE_OK || a[p->nToken-1].bIgnore==0 );
assert( rc!=SQLITE_OK || (p->nToken>=1 && a[p->nToken-1].bIgnore==0) );
assert( rc!=SQLITE_OK || bMaxSet );
/* Keep advancing iterators until they all point to the same document */

View File

@ -190,7 +190,7 @@ static int getNextToken(
/* Set variable i to the maximum number of bytes of input to tokenize. */
for(i=0; i<n; i++){
if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
if( z[i]=='*' || z[i]=='"' ) break;
if( z[i]=='"' ) break;
}
*pnConsumed = i;

View File

@ -1,5 +1,5 @@
C Further\swork\son\sbalance_nonroot().
D 2014-10-13T18:03:27.743
C Merge\strunk\schanges\sinto\sthis\sbranch.
D 2014-10-13T18:09:13.737
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -78,11 +78,11 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 2f5e925bdb9d6d3e488c5a981af60cad4f9cdfe7
F ext/fts3/fts3.c 8b6cceb3e0be22da26d83a3cec0e0e337e6b8ec6
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 53d4eca1fb23eab00681fb028fb82eb5705c1e21
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
F ext/fts3/fts3_expr.c 351395fad6fcb16ecfc61db0861008a70101330c
F ext/fts3/fts3_expr.c 40123785eaa3ebd4c45c9b23407cc44ac0c49905
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
@ -166,26 +166,26 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c ba266a779bc7ce10e52e59e7d3dc79fa342e8fdb
F src/analyze.c 6290a109be876daaa242cd7216f97240f5401776
F src/analyze.c 8c322e1ecc08909526dbd5ab4421889d05f2263d
F src/attach.c f4e94df2d1826feda65eb0939f7f6f5f923a0ad9
F src/auth.c d8abcde53426275dab6243b441256fcd8ccbebb2
F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
F src/btree.c 63211ca1d4ae867eede39a37901aec4746d904a7
F src/btree.c 3d9d1db1d05724346876cf456a850628a9e75331
F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8
F src/btreeInt.h 1bd7957161a1346a914f1f09231610e777a8e58d
F src/build.c bde83dd5cf812e310a7e5ad2846790a14745bef4
F src/build.c 9dc2bd94347b878c89627000c92b0c8d97ec2919
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c 535183afb3c75628b78ce82612931ac7cdf26f14
F src/ctime.c bb434068b5308a857b181c2d204a320ff0d6c638
F src/date.c 57a7f9ba9f6b4d5268f5e411739066a611f99036
F src/delete.c fae81cc2eb14b75267d4f47d3cfc9ae02aae726f
F src/expr.c f32119248996680aa73c5c37bfdd42820804dc17
F src/expr.c fc204d08af06437ddaffe5a1b1f1f6f9e1a55d6d
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c da985ae673efef2c712caef825a5d2edb087ead7
F src/func.c ba47c1671ab3cfdafa6e9d6ee490939ea578adee
F src/global.c 5110fa12e09729b84eee0191c984ec4008e21937
F src/global.c 01c1f36ecfcf10770db648422a8852c222308bb9
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
@ -194,11 +194,11 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
F src/loadext.c de741e66e5ddc1598d904d7289239696e40ed994
F src/main.c d15621461fb0c52675eba2b650492ed1beef69ab
F src/malloc.c 5bb99ee1e08ad58e457063cf79ce521db0e24195
F src/main.c bbe872b0ac0007bed0ebe1936fc493b039ad4f51
F src/malloc.c 3c3ac67969612493d435e14b6832793209afd2ec
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c faf615aafd8be74a71494dfa027c113ea5c6615f
F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
F src/mem5.c 61eeb90134f9a5be6c2e68d8daae7628b25953fb
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
@ -215,29 +215,29 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c fb587121840f690101336879adfa6d0b2cd0e8c7
F src/os_win.c 0a4042ef35f322e86fa01f6c8884c5e645b911e7
F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21
F src/pager.c 0abcb0904a78d68b96357f360c6b160bcfc2a3e0
F src/pager.c 492aab0f963ddd7b6795de6376a38b139c767919
F src/pager.h 8b6707cb32c788cf36bfc3d63f6d4b4fa689e7c2
F src/parse.y b98772da2bb5415970085b707203f92569400aa8
F src/parse.y 5dfead8aed90cb0c7c1115898ee2266804daff45
F src/pcache.c 4121a0571c18581ee9f82f086d5e2030051ebd6a
F src/pcache.h 9b559127b83f84ff76d735c8262f04853be0c59a
F src/pcache1.c dab8ab930d4a73b99768d881185994f34b80ecaa
F src/pcache1.c e412cb585f777c840ddce0500eddc5c6043c2bb5
F src/pragma.c 3f3e959390a10c0131676f0e307acce372777e0f
F src/prepare.c 6ef0cf2f9274982988ed6b7cab1be23147e94196
F src/printf.c 3a47f526b173813d9a7f4e7044007771ba68cde1
F src/printf.c 6b79bbd063dcbadca4cf617a4cde255bcc13ea64
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c a3466128b52a86c466e47ac1a19e2174f7b5cf89
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c a83ed8bc2a31c131e3addb6f0488b68334085e7b
F src/shell.c dad23987c34faddb061a339da3e92e05ccc6935e
F src/sqlite.h.in 8b018219ce988913e5977d5de9ab4beb33be23b6
F src/select.c 428165951748151e87a15295b7357221433e311b
F src/shell.c 18ee8bbe9502d8848072dc2eddd1ea09254ba494
F src/sqlite.h.in 4a5e5158c189d2bcd45c7c4607c2c0eb6d25c153
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
F src/sqliteInt.h 5e09fe04f999223680801ddf8fbae6b60751d613
F src/sqliteInt.h f7812f74f2d0c6041ef6b91a99c5a45f775dd408
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/status.c 961d5926e5a8fda611d385ec22c226b8635cd1cb
F src/table.c 2e99ef7ef16187e17033d9398dc962ce22dab5cb
F src/tclsqlite.c c67d310c833046cccc192125d64ad422ab882684
F src/test1.c 523cd70ded28db71af9a30ec184cbe0957de9575
F src/test1.c 518db4305d76b29dd9da3f022ca899c8fcdf9fc7
F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
@ -250,7 +250,7 @@ F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
F src/test_config.c 6f721f0337b96d58e81ff69bba101113c8168c2b
F src/test_config.c a4cdebe093474c02eecc5e4008b1a22198edf975
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
@ -282,27 +282,27 @@ F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 22dded4283dc4b25422f6444cdcb8d6b1ea0b5ff
F src/threads.c 60c9d400abf17ccdc8767cdc6af90b9c5acf58bd
F src/tokenize.c cc9016e5007fc5e76789079616d2f26741bcc689
F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f
F src/update.c 729f6f18fc27740591d085e1172cebe311144bf0
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c 4006c01772bd8d8ac4306d523bbcee41d3e392d8
F src/vacuum.c 59f03f92bcff57faa6a8ca256eb29ccddfb0614a
F src/vdbe.c 91b7e12bca7b6056574ce28935e3e3f4769ce3c4
F src/vdbe.c cf7c24e531aad047689e4235a66b22526e765e46
F src/vdbe.h 09f5b4e3719fa454f252322b1cdab5cf1f361327
F src/vdbeInt.h bb7f7ecfdead1a2ae0251b59f86f5724838d975c
F src/vdbeapi.c e9e33b59834e3edc8790209765e069874c269d9d
F src/vdbeaux.c a05adc3c96abdaf3db14768ddd63132fc9678060
F src/vdbeInt.h 90c0ae53382d16a4f77ad5a9c4b3e35278e9e061
F src/vdbeapi.c 37a6c6ae284a97bcace365f2f0a225680c0499d9
F src/vdbeaux.c edbb7a9c8b2a8f7a68ac75c2475edd4040266b76
F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4
F src/vdbemem.c 1e105dacf5190fc85a8ec2107c0dcc1884e75099
F src/vdbemem.c 481327f50d9da330053aa7456702ce46d0a4e70f
F src/vdbesort.c 5c1bacf90578d22b630fbf6ed98ccf60d83435ef
F src/vdbetrace.c 4f29b04edb0cec3d5fcd9b566d9f0e75c8984362
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f
F src/wal.c 10e7de7ce90865a68153f001a61f1d985cd17983
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c a14d3d8042adeb51f81731c1b47b3e481d1cc23a
F src/where.c 2947912f1f3d6a7766fe087fd532a5d688d745b1
F src/whereInt.h 124d970450955a6982e174b07c320ae6d62a595c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@ -326,6 +326,8 @@ F test/analyze9.test 72795c8113604b5dcd47a1498a61d6d7fb5d041a
F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
@ -419,7 +421,7 @@ F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
F test/corruptH.test 88ed71a086e13591c917aac6de32750e7c7281cb
F test/corruptI.test 0afbba50bfae006094cc548b4605f521c1179502
F test/corruptI.test 221ad8b7f0a9ac6b80fc577e73b5ad8cdea31243
F test/cost.test 19d314526616ce4473eb4e4e450fcb94499ce318
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62
@ -448,7 +450,7 @@ F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
F test/distinct.test 086e70c765f172e8974e9f83b9ac5ca03c154e77
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_createtable.test 181653f6f45e3adde73f8686600ce5ad7515466b
F test/e_createtable.test c7e67b49e6cf92473c8fb30ab26143e9e2128cf7
F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
@ -461,7 +463,7 @@ F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52
F test/e_uri.test a2c92d80093a7efdcfbb11093651cbea87097b6b
F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
@ -469,12 +471,12 @@ F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d
F test/expr.test c4b9bf0cc60b26862475e19999fbd2609ca8259c
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a
@ -560,13 +562,13 @@ F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
F test/fts3expr.test 3401d47b229c4504424caf362cc4ff704cad4162
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
F test/fts3expr3.test 9e91b8edbcb197bf2e92161aa7696446d96dce5f
F test/fts3expr4.test 0713d94ab951ed88a8c3629a4889a48c55c4067c
F test/fts3expr4.test e1be1248566f43c252d4404d52914f1fc4bfa065
F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
F test/fts3fault2.test 3198eef2804deea7cac8403e771d9cbcb752d887
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
F test/fts3join.test 53e66a0c21eb568580674a43b21c059acb26f499
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test ff423e73faab8fc6d7adeefedf74dd8e2b0b14e0
F test/fts3matchinfo.test 58544fa4d254000fa4e7f494b0a832f7ba61d45e
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
F test/fts3prefix.test b36d4f00b128a51e7b386cc013a874246d9d7dc1
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
@ -629,7 +631,7 @@ F test/index.test 4d990005a67a36984e4f1a5f1bdccea8d08da4ee
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
F test/index3.test 55a90cff99834305e8141df7afaef39674b57062
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test fc07c14193c0430814e7a08b5da46888ee795c33
F test/index5.test 25b0b451aceed4ac5f7d49f856f6de7257470b3e
F test/index6.test fb370966ac3cd0989053dd5385757b5c3e24ab6a
F test/index7.test 917cf1e1c7439bb155abbeabec511b28945e157b
F test/indexedby.test b2f22f3e693a53813aa3f50b812eb609ba6df1ec
@ -690,7 +692,7 @@ F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
F test/malloc9.test 2307c6ee3703b0a21391f3ea92388b4b73f9105e
F test/mallocA.test c049224adeb0244b8f6eb770c1fa6ac40f9b3518
F test/mallocA.test 672cd7dedb63771bade3a6f557f851a4ad161d4a
F test/mallocAll.test 98f1be74bc9f49a858bc4f361fc58e26486798be
F test/mallocB.test bc475ab850cda896142ab935bbfbc74c24e51ed6
F test/mallocC.test 3dffe16532f109293ce1ccecd0c31dca55ef08c4
@ -749,6 +751,7 @@ F test/orderby5.test 8f08a54836d21fb7c70245360751aedd1c2286fb
F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
@ -780,7 +783,7 @@ F test/rdonly.test dd30a4858d8e0fbad2304c2bd74a33d4df36412a
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
F test/releasetest.tcl a0df0dfc5e3ee83ade87b9cc96db41b52d590b9e
F test/releasetest.tcl 4296b9adbc5992bcd0b0b2876b7651f57c1494f2
F test/resolver01.test 33abf37ff8335e6bf98f2b45a0af3e06996ccd9a
F test/rollback.test e9504a009a202c3ed711da2e6879ff60c5a4669c
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
@ -857,9 +860,9 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 83f6b3318f7ee60e52b978b5a5e5dd7e83dfb7ee
F test/speedtest1.c e4e2aa37ff66bad9f414a50a8cb9edfaac65c9e5
F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
F test/sqllimits1.test 9014524e7ab16e2a4976b13397db4c29cc29c6d9
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
F test/subquery.test 666fdecceac258f5fd84bed09a64e49d9f37edd9
@ -930,6 +933,7 @@ F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
F test/tkt-b75a9ca6b0.test 97cc2d5eeaf82799eb42138c0a1ff64370238ce4
F test/tkt-ba7cbfaedc.test e76d88e572e489ee0d64fe4caf4af18b3d1dc688
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447
@ -1200,7 +1204,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P fec849dcca3aead2bc2d4ecffeda750684d32fb0
R 79e5b5564c934fc68257d82dc897cefd
P 6594f9b420e2fa642737722ff8521f756ecef227 04892f8ba6c55cec4fe37bfe59b6349fd2a40698
R 76183a9b7ddeb938a48604dbc4dd8cd6
U dan
Z ae5b74eee28666050af6baaa639de56c
Z 504cabb1e1fb0c47450f76fec3d8495b

View File

@ -1 +1 @@
6594f9b420e2fa642737722ff8521f756ecef227
d5b7c5a88dd58de85b3060a1f28b6d96e6e21207

View File

@ -1437,7 +1437,7 @@ static void decodeIntArray(
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( z==0 ) z = "";
#else
if( NEVER(z==0) ) z = "";
assert( z!=0 );
#endif
for(i=0; *z && i<nOut; i++){
v = 0;
@ -1446,16 +1446,14 @@ static void decodeIntArray(
z++;
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( aOut ){
aOut[i] = v;
}else
if( aOut ) aOut[i] = v;
if( aLog ) aLog[i] = sqlite3LogEst(v);
#else
assert( aOut==0 );
UNUSED_PARAMETER(aOut);
assert( aLog!=0 );
aLog[i] = sqlite3LogEst(v);
#endif
{
aLog[i] = sqlite3LogEst(v);
}
if( *z==' ' ) z++;
}
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
@ -1516,8 +1514,17 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
z = argv[2];
if( pIndex ){
int nCol = pIndex->nKeyCol+1;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
tRowcnt * const aiRowEst = pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(
sizeof(tRowcnt) * nCol
);
if( aiRowEst==0 ) pInfo->db->mallocFailed = 1;
#else
tRowcnt * const aiRowEst = 0;
#endif
pIndex->bUnordered = 0;
decodeIntArray((char*)z, pIndex->nKeyCol+1, 0, pIndex->aiRowLogEst, pIndex);
decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex);
if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
}else{
Index fakeIdx;
@ -1576,25 +1583,38 @@ static void initAvgEq(Index *pIdx){
pIdx->aAvgEq[nCol] = 1;
}
for(iCol=0; iCol<nCol; iCol++){
int nSample = pIdx->nSample;
int i; /* Used to iterate through samples */
tRowcnt sumEq = 0; /* Sum of the nEq values */
tRowcnt nSum = 0; /* Number of terms contributing to sumEq */
tRowcnt avgEq = 0;
tRowcnt nDLt = pFinal->anDLt[iCol];
tRowcnt nRow; /* Number of rows in index */
i64 nSum100 = 0; /* Number of terms contributing to sumEq */
i64 nDist100; /* Number of distinct values in index */
if( pIdx->aiRowEst==0 || pIdx->aiRowEst[iCol+1]==0 ){
nRow = pFinal->anLt[iCol];
nDist100 = (i64)100 * pFinal->anDLt[iCol];
nSample--;
}else{
nRow = pIdx->aiRowEst[0];
nDist100 = ((i64)100 * pIdx->aiRowEst[0]) / pIdx->aiRowEst[iCol+1];
}
/* Set nSum to the number of distinct (iCol+1) field prefixes that
** occur in the stat4 table for this index before pFinal. Set
** sumEq to the sum of the nEq values for column iCol for the same
** set (adding the value only once where there exist duplicate
** prefixes). */
for(i=0; i<(pIdx->nSample-1); i++){
if( aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){
** occur in the stat4 table for this index. Set sumEq to the sum of
** the nEq values for column iCol for the same set (adding the value
** only once where there exist duplicate prefixes). */
for(i=0; i<nSample; i++){
if( i==(pIdx->nSample-1)
|| aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol]
){
sumEq += aSample[i].anEq[iCol];
nSum++;
nSum100 += 100;
}
}
if( nDLt>nSum ){
avgEq = (pFinal->anLt[iCol] - sumEq)/(nDLt - nSum);
if( nDist100>nSum100 ){
avgEq = ((i64)100 * (nRow - sumEq))/(nDist100 - nSum100);
}
if( avgEq==0 ) avgEq = 1;
pIdx->aAvgEq[iCol] = avgEq;
@ -1846,6 +1866,11 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
rc = loadStat4(db, sInfo.zDatabase);
db->lookaside.bEnabled = lookasideEnabled;
}
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3_free(pIdx->aiRowEst);
pIdx->aiRowEst = 0;
}
#endif
if( rc==SQLITE_NOMEM ){

View File

@ -776,7 +776,7 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){
** back to where it ought to be if this routine returns true.
*/
int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
return pCur && pCur->eState!=CURSOR_VALID;
return pCur->eState!=CURSOR_VALID;
}
/*
@ -4029,6 +4029,7 @@ static int accessPayload(
MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
unsigned char * const pBufStart = pBuf;
int bEnd; /* True if reading to end of data */
#endif
@ -4156,6 +4157,7 @@ static int accessPayload(
** 4) there is no open write-transaction, and
** 5) the database is not a WAL database,
** 6) all data from the page is being read.
** 7) at least 4 bytes have already been read into the output buffer
**
** then data can be read directly from the database file into the
** output buffer, bypassing the page-cache altogether. This speeds
@ -4167,9 +4169,11 @@ static int accessPayload(
&& pBt->inTransaction==TRANS_READ /* (4) */
&& (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
&& pBt->pPage1->aData[19]==0x01 /* (5) */
&& &pBuf[-4]>=pBufStart /* (7) */
){
u8 aSave[4];
u8 *aWrite = &pBuf[-4];
assert( aWrite>=pBufStart ); /* hence (7) */
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
nextPage = get4byte(aWrite);
@ -4992,8 +4996,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
assert( pCur->info.nSize==0 );
if( pCur->eState!=CURSOR_VALID ){
assert( pCur->eState>=CURSOR_REQUIRESEEK );
rc = btreeRestoreCursorPosition(pCur);
rc = restoreCursorPosition(pCur);
if( rc!=SQLITE_OK ){
return rc;
}
@ -5849,11 +5852,6 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
** in pTemp or the original pCell) and also record its index.
** Allocating a new entry in pPage->aCell[] implies that
** pPage->nOverflow is incremented.
**
** If nSkip is non-zero, then do not copy the first nSkip bytes of the
** cell. The caller will overwrite them after this function returns. If
** nSkip is non-zero, then pCell may not point to an invalid memory location
** (but pCell+nSkip is always valid).
*/
static void insertCell(
MemPage *pPage, /* Page into which we are copying */
@ -5870,7 +5868,6 @@ static void insertCell(
int ins; /* Index in data[] where new cell pointer is inserted */
int cellOffset; /* Address of first cell pointer in data[] */
u8 *data; /* The content of the whole page */
int nSkip = (iChild ? 4 : 0);
if( *pRC ) return;
@ -5888,7 +5885,7 @@ static void insertCell(
assert( sz==cellSizePtr(pPage, pCell) || (sz==8 && iChild>0) );
if( pPage->nOverflow || sz+2>pPage->nFree ){
if( pTemp ){
memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip);
memcpy(pTemp, pCell, sz);
pCell = pTemp;
}
if( iChild ){
@ -5917,7 +5914,7 @@ static void insertCell(
assert( idx+sz <= (int)pPage->pBt->usableSize );
pPage->nCell++;
pPage->nFree -= (u16)(2 + sz);
memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip);
memcpy(&data[idx], pCell, sz);
if( iChild ){
put4byte(&data[idx], iChild);
}

View File

@ -435,6 +435,9 @@ static void freeIndex(sqlite3 *db, Index *p){
sqlite3ExprDelete(db, p->pPartIdxWhere);
sqlite3DbFree(db, p->zColAff);
if( p->isResized ) sqlite3DbFree(db, p->azColl);
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
sqlite3_free(p->aiRowEst);
#endif
sqlite3DbFree(db, p);
}
@ -2744,7 +2747,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
}else{
addr2 = sqlite3VdbeCurrentAddr(v);
}
sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, regRecord);

View File

@ -3236,90 +3236,86 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
exprToRegister(pExpr, iMem);
}
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
#ifdef SQLITE_DEBUG
/*
** Generate a human-readable explanation of an expression tree.
*/
void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
int op; /* The opcode being coded */
void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
const char *zBinOp = 0; /* Binary operator */
const char *zUniOp = 0; /* Unary operator */
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( pExpr==0 ){
op = TK_NULL;
}else{
op = pExpr->op;
sqlite3TreeViewLine(pView, "nil");
sqlite3TreeViewPop(pView);
return;
}
switch( op ){
switch( pExpr->op ){
case TK_AGG_COLUMN: {
sqlite3ExplainPrintf(pOut, "AGG{%d:%d}",
sqlite3TreeViewLine(pView, "AGG{%d:%d}",
pExpr->iTable, pExpr->iColumn);
break;
}
case TK_COLUMN: {
if( pExpr->iTable<0 ){
/* This only happens when coding check constraints */
sqlite3ExplainPrintf(pOut, "COLUMN(%d)", pExpr->iColumn);
sqlite3TreeViewLine(pView, "COLUMN(%d)", pExpr->iColumn);
}else{
sqlite3ExplainPrintf(pOut, "{%d:%d}",
sqlite3TreeViewLine(pView, "{%d:%d}",
pExpr->iTable, pExpr->iColumn);
}
break;
}
case TK_INTEGER: {
if( pExpr->flags & EP_IntValue ){
sqlite3ExplainPrintf(pOut, "%d", pExpr->u.iValue);
sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
}else{
sqlite3ExplainPrintf(pOut, "%s", pExpr->u.zToken);
sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
}
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
sqlite3ExplainPrintf(pOut,"%s", pExpr->u.zToken);
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_STRING: {
sqlite3ExplainPrintf(pOut,"%Q", pExpr->u.zToken);
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
break;
}
case TK_NULL: {
sqlite3ExplainPrintf(pOut,"NULL");
sqlite3TreeViewLine(pView,"NULL");
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
sqlite3ExplainPrintf(pOut,"%s", pExpr->u.zToken);
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_VARIABLE: {
sqlite3ExplainPrintf(pOut,"VARIABLE(%s,%d)",
pExpr->u.zToken, pExpr->iColumn);
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
pExpr->u.zToken, pExpr->iColumn);
break;
}
case TK_REGISTER: {
sqlite3ExplainPrintf(pOut,"REGISTER(%d)", pExpr->iTable);
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
break;
}
case TK_AS: {
sqlite3ExplainExpr(pOut, pExpr->pLeft);
sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_ID: {
sqlite3TreeViewLine(pView,"ID %Q", pExpr->u.zToken);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
const char *zAff = "unk";
switch( sqlite3AffinityType(pExpr->u.zToken, 0) ){
case SQLITE_AFF_TEXT: zAff = "TEXT"; break;
case SQLITE_AFF_NONE: zAff = "NONE"; break;
case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break;
case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break;
case SQLITE_AFF_REAL: zAff = "REAL"; break;
}
sqlite3ExplainPrintf(pOut, "CAST-%s(", zAff);
sqlite3ExplainExpr(pOut, pExpr->pLeft);
sqlite3ExplainPrintf(pOut, ")");
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
#endif /* SQLITE_OMIT_CAST */
@ -3343,6 +3339,7 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
case TK_LSHIFT: zBinOp = "LSHIFT"; break;
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
case TK_CONCAT: zBinOp = "CONCAT"; break;
case TK_DOT: zBinOp = "DOT"; break;
case TK_UMINUS: zUniOp = "UMINUS"; break;
case TK_UPLUS: zUniOp = "UPLUS"; break;
@ -3352,8 +3349,8 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
case TK_COLLATE: {
sqlite3ExplainExpr(pOut, pExpr->pLeft);
sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken);
sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
@ -3365,41 +3362,36 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
}else{
pFarg = pExpr->x.pList;
}
if( op==TK_AGG_FUNCTION ){
sqlite3ExplainPrintf(pOut, "AGG_FUNCTION%d:%s(",
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
pExpr->op2, pExpr->u.zToken);
}else{
sqlite3ExplainPrintf(pOut, "FUNCTION:%s(", pExpr->u.zToken);
sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
}
if( pFarg ){
sqlite3ExplainExprList(pOut, pFarg);
sqlite3TreeViewExprList(pView, pFarg, 0, 0);
}
sqlite3ExplainPrintf(pOut, ")");
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS: {
sqlite3ExplainPrintf(pOut, "EXISTS(");
sqlite3ExplainSelect(pOut, pExpr->x.pSelect);
sqlite3ExplainPrintf(pOut,")");
sqlite3TreeViewLine(pView, "EXISTS-expr");
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_SELECT: {
sqlite3ExplainPrintf(pOut, "(");
sqlite3ExplainSelect(pOut, pExpr->x.pSelect);
sqlite3ExplainPrintf(pOut, ")");
sqlite3TreeViewLine(pView, "SELECT-expr");
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
sqlite3ExplainPrintf(pOut, "IN(");
sqlite3ExplainExpr(pOut, pExpr->pLeft);
sqlite3ExplainPrintf(pOut, ",");
sqlite3TreeViewLine(pView, "IN");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
sqlite3ExplainSelect(pOut, pExpr->x.pSelect);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
}else{
sqlite3ExplainExprList(pOut, pExpr->x.pList);
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
}
sqlite3ExplainPrintf(pOut, ")");
break;
}
#endif /* SQLITE_OMIT_SUBQUERY */
@ -3419,13 +3411,10 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
Expr *pX = pExpr->pLeft;
Expr *pY = pExpr->x.pList->a[0].pExpr;
Expr *pZ = pExpr->x.pList->a[1].pExpr;
sqlite3ExplainPrintf(pOut, "BETWEEN(");
sqlite3ExplainExpr(pOut, pX);
sqlite3ExplainPrintf(pOut, ",");
sqlite3ExplainExpr(pOut, pY);
sqlite3ExplainPrintf(pOut, ",");
sqlite3ExplainExpr(pOut, pZ);
sqlite3ExplainPrintf(pOut, ")");
sqlite3TreeViewLine(pView, "BETWEEN");
sqlite3TreeViewExpr(pView, pX, 1);
sqlite3TreeViewExpr(pView, pY, 1);
sqlite3TreeViewExpr(pView, pZ, 0);
break;
}
case TK_TRIGGER: {
@ -3436,15 +3425,14 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
** is set to the column of the pseudo-table to read, or to -1 to
** read the rowid field.
*/
sqlite3ExplainPrintf(pOut, "%s(%d)",
sqlite3TreeViewLine(pView, "%s(%d)",
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
break;
}
case TK_CASE: {
sqlite3ExplainPrintf(pOut, "CASE(");
sqlite3ExplainExpr(pOut, pExpr->pLeft);
sqlite3ExplainPrintf(pOut, ",");
sqlite3ExplainExprList(pOut, pExpr->x.pList);
sqlite3TreeViewLine(pView, "CASE");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
break;
}
#ifndef SQLITE_OMIT_TRIGGER
@ -3456,55 +3444,57 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
case OE_Fail: zType = "fail"; break;
case OE_Ignore: zType = "ignore"; break;
}
sqlite3ExplainPrintf(pOut, "RAISE-%s(%s)", zType, pExpr->u.zToken);
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
break;
}
#endif
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
}
}
if( zBinOp ){
sqlite3ExplainPrintf(pOut,"%s(", zBinOp);
sqlite3ExplainExpr(pOut, pExpr->pLeft);
sqlite3ExplainPrintf(pOut,",");
sqlite3ExplainExpr(pOut, pExpr->pRight);
sqlite3ExplainPrintf(pOut,")");
sqlite3TreeViewLine(pView, "%s", zBinOp);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
}else if( zUniOp ){
sqlite3ExplainPrintf(pOut,"%s(", zUniOp);
sqlite3ExplainExpr(pOut, pExpr->pLeft);
sqlite3ExplainPrintf(pOut,")");
sqlite3TreeViewLine(pView, "%s", zUniOp);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
sqlite3TreeViewPop(pView);
}
#endif /* defined(SQLITE_ENABLE_TREE_EXPLAIN) */
#endif /* SQLITE_DEBUG */
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
#ifdef SQLITE_DEBUG
/*
** Generate a human-readable explanation of an expression list.
*/
void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){
void sqlite3TreeViewExprList(
TreeView *pView,
const ExprList *pList,
u8 moreToFollow,
const char *zLabel
){
int i;
if( pList==0 || pList->nExpr==0 ){
sqlite3ExplainPrintf(pOut, "(empty-list)");
return;
}else if( pList->nExpr==1 ){
sqlite3ExplainExpr(pOut, pList->a[0].pExpr);
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
if( pList==0 ){
sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
}else{
sqlite3ExplainPush(pOut);
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nExpr; i++){
sqlite3ExplainPrintf(pOut, "item[%d] = ", i);
sqlite3ExplainPush(pOut);
sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
sqlite3ExplainPop(pOut);
if( pList->a[i].zName ){
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1);
#if 0
if( pList->a[i].zName ){
sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
}
if( pList->a[i].bSpanIsTab ){
sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
}
if( i<pList->nExpr-1 ){
sqlite3ExplainNL(pOut);
}
#endif
}
sqlite3ExplainPop(pOut);
}
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_DEBUG */

View File

@ -129,6 +129,13 @@ const unsigned char sqlite3CtypeMap[256] = {
};
#endif
/* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards
** compatibility for legacy applications, the URI filename capability is
** disabled by default.
**
** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled
** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options.
*/
#ifndef SQLITE_USE_URI
# define SQLITE_USE_URI 0
#endif

View File

@ -476,6 +476,11 @@ int sqlite3_config(int op, ...){
break;
}
/* EVIDENCE-OF: R-55548-33817 The compile-time setting for URI filenames
** can be changed at start-time using the
** sqlite3_config(SQLITE_CONFIG_URI,1) or
** sqlite3_config(SQLITE_CONFIG_URI,0) configuration calls.
*/
case SQLITE_CONFIG_URI: {
sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
break;
@ -2213,7 +2218,7 @@ int sqlite3ParseUri(
assert( *pzErrMsg==0 );
if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri)
&& nUri>=5 && memcmp(zUri, "file:", 5)==0
&& nUri>=5 && memcmp(zUri, "file:", 5)==0 /* IMP: R-57884-37496 */
){
char *zOpt;
int eState; /* Parser state when parsing URI */
@ -2443,7 +2448,9 @@ static int openDatabase(
testcase( (1<<(flags&7))==0x02 ); /* READONLY */
testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE_BKPT;
if( ((1<<(flags&7)) & 0x46)==0 ){
return SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */
}
if( sqlite3GlobalConfig.bCoreMutex==0 ){
isThreadsafe = 0;
@ -3327,22 +3334,6 @@ int sqlite3_test_control(int op, ...){
break;
}
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
/* sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT,
** sqlite3_stmt*,const char**);
**
** If compiled with SQLITE_ENABLE_TREE_EXPLAIN, each sqlite3_stmt holds
** a string that describes the optimized parse tree. This test-control
** returns a pointer to that string.
*/
case SQLITE_TESTCTRL_EXPLAIN_STMT: {
sqlite3_stmt *pStmt = va_arg(ap, sqlite3_stmt*);
const char **pzRet = va_arg(ap, const char**);
*pzRet = sqlite3VdbeExplanation((Vdbe*)pStmt);
break;
}
#endif
/* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int);
**
** Set or clear a flag that indicates that the database file is always well-

View File

@ -310,7 +310,7 @@ void *sqlite3Malloc(u64 n){
}else{
p = sqlite3GlobalConfig.m.xMalloc((int)n);
}
assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-04675-44850 */
assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-11148-40995 */
return p;
}
@ -447,25 +447,27 @@ static int isLookaside(sqlite3 *db, void *p){
*/
int sqlite3MallocSize(void *p){
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
return sqlite3GlobalConfig.m.xSize(p);
}
int sqlite3DbMallocSize(sqlite3 *db, void *p){
if( db==0 ){
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
return sqlite3MallocSize(p);
}else{
assert( sqlite3_mutex_held(db->mutex) );
if( isLookaside(db, p) ){
return db->lookaside.sz;
}else{
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
return sqlite3GlobalConfig.m.xSize(p);
}
}
}
sqlite3_uint64 sqlite3_msize(void *p){
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
return (sqlite3_uint64)sqlite3GlobalConfig.m.xSize(p);
}
@ -474,8 +476,8 @@ sqlite3_uint64 sqlite3_msize(void *p){
*/
void sqlite3_free(void *p){
if( p==0 ) return; /* IMP: R-49053-54554 */
assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
@ -519,8 +521,8 @@ void sqlite3DbFree(sqlite3 *db, void *p){
return;
}
}
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
sqlite3_free(p);
@ -532,11 +534,13 @@ void sqlite3DbFree(sqlite3 *db, void *p){
void *sqlite3Realloc(void *pOld, u64 nBytes){
int nOld, nNew, nDiff;
void *pNew;
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
if( pOld==0 ){
return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */
return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */
}
if( nBytes==0 ){
sqlite3_free(pOld); /* IMP: R-31593-10574 */
sqlite3_free(pOld); /* IMP: R-26507-47431 */
return 0;
}
if( nBytes>=0x7fffff00 ){
@ -558,8 +562,6 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nDiff);
}
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
if( pNew==0 && mem0.alarmCallback ){
sqlite3MallocAlarm((int)nBytes);
@ -573,7 +575,7 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
}else{
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
}
assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-04675-44850 */
assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-11148-40995 */
return pNew;
}
@ -585,7 +587,7 @@ void *sqlite3_realloc(void *pOld, int n){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
if( n<0 ) n = 0;
if( n<0 ) n = 0; /* IMP: R-26507-47431 */
return sqlite3Realloc(pOld, n);
}
void *sqlite3_realloc64(void *pOld, sqlite3_uint64 n){
@ -672,8 +674,8 @@ void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){
if( !p && db ){
db->mallocFailed = 1;
}
sqlite3MemdebugSetType(p, MEMTYPE_DB |
((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
sqlite3MemdebugSetType(p,
(db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP);
return p;
}
@ -699,15 +701,14 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
sqlite3DbFree(db, p);
}
}else{
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
pNew = sqlite3_realloc64(p, n);
if( !pNew ){
sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
db->mallocFailed = 1;
}
sqlite3MemdebugSetType(pNew, MEMTYPE_DB |
sqlite3MemdebugSetType(pNew,
(db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
}
}

View File

@ -394,7 +394,7 @@ void sqlite3MemdebugSetType(void *p, u8 eType){
** This routine is designed for use within an assert() statement, to
** verify the type of an allocation. For example:
**
** assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
*/
int sqlite3MemdebugHasType(void *p, u8 eType){
int rc = 1;
@ -416,7 +416,7 @@ int sqlite3MemdebugHasType(void *p, u8 eType){
** This routine is designed for use within an assert() statement, to
** verify the type of an allocation. For example:
**
** assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
*/
int sqlite3MemdebugNoType(void *p, u8 eType){
int rc = 1;

View File

@ -3618,13 +3618,15 @@ int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
if( rc==SQLITE_OK ){
pager_reset(pPager);
sqlite3PageFree(pPager->pTmpSpace);
pPager->pTmpSpace = pNew;
rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
}
if( rc==SQLITE_OK ){
sqlite3PageFree(pPager->pTmpSpace);
pPager->pTmpSpace = pNew;
pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
pPager->pageSize = pageSize;
}else{
sqlite3PageFree(pNew);
}
}

View File

@ -399,9 +399,6 @@ cmd ::= DROP VIEW ifexists(E) fullname(X). {
cmd ::= select(X). {
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
sqlite3Select(pParse, X, &dest);
sqlite3ExplainBegin(pParse->pVdbe);
sqlite3ExplainSelect(pParse->pVdbe, X);
sqlite3ExplainFinish(pParse->pVdbe);
sqlite3SelectDelete(pParse->db, X);
}
@ -964,7 +961,7 @@ expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}
** unary TK_ISNULL or TK_NOTNULL expression. */
static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
sqlite3 *db = pParse->db;
if( db->mallocFailed==0 && pY->op==TK_NULL ){
if( pY && pA && pY->op==TK_NULL ){
pA->op = (u8)op;
sqlite3ExprDelete(db, pA->pRight);
pA->pRight = 0;

View File

@ -688,7 +688,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
if( createFlag==1 && (
nPinned>=pGroup->mxPinned
|| nPinned>=pCache->n90pct
|| pcache1UnderMemoryPressure(pCache)
|| (pcache1UnderMemoryPressure(pCache) && pCache->nRecyclable<nPinned)
)){
return 0;
}

View File

@ -1056,6 +1056,69 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
}
#endif
#ifdef SQLITE_DEBUG
/*************************************************************************
** Routines for implementing the "TreeView" display of hierarchical
** data structures for debugging.
**
** The main entry points (coded elsewhere) are:
** sqlite3TreeViewExpr(0, pExpr, 0);
** sqlite3TreeViewExprList(0, pList, 0, 0);
** sqlite3TreeViewSelect(0, pSelect, 0);
** Insert calls to those routines while debugging in order to display
** a diagram of Expr, ExprList, and Select objects.
**
*/
/* Add a new subitem to the tree. The moreToFollow flag indicates that this
** is not the last item in the tree. */
TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
if( p==0 ){
p = sqlite3_malloc( sizeof(*p) );
if( p==0 ) return 0;
memset(p, 0, sizeof(*p));
}else{
p->iLevel++;
}
assert( moreToFollow==0 || moreToFollow==1 );
if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
return p;
}
/* Finished with one layer of the tree */
void sqlite3TreeViewPop(TreeView *p){
if( p==0 ) return;
p->iLevel--;
if( p->iLevel<0 ) sqlite3_free(p);
}
/* Generate a single line of output for the tree, with a prefix that contains
** all the appropriate tree lines */
void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_list ap;
int i;
StrAccum acc;
char zBuf[500];
sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
acc.useMalloc = 0;
if( p ){
for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4);
}
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
}
va_start(ap, zFormat);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
va_end(ap);
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
sqlite3StrAccumFinish(&acc);
fprintf(stdout,"%s", zBuf);
fflush(stdout);
}
/* Shorthand for starting a new tree item that consists of a single label */
void sqlite3TreeViewItem(TreeView *p, const char *zLabel, u8 moreToFollow){
p = sqlite3TreeViewPush(p, moreToFollow);
sqlite3TreeViewLine(p, "%s", zLabel);
}
#endif /* SQLITE_DEBUG */
/*
** variable-argument wrapper around sqlite3VXPrintf().
*/

View File

@ -1181,7 +1181,6 @@ static void generateSortTail(
int nKey;
int iSortTab; /* Sorter cursor to read from */
int nSortData; /* Trailing values to read from sorter */
u8 p5; /* p5 parameter for 1st OP_Column */
int i;
int bSeq; /* True if sorter record includes seq. no. */
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
@ -1215,19 +1214,16 @@ static void generateSortTail(
addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
p5 = OPFLAG_CLEARCACHE;
sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab);
bSeq = 0;
}else{
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
iSortTab = iTab;
p5 = 0;
bSeq = 1;
}
for(i=0; i<nSortData; i++){
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i);
if( i==0 ) sqlite3VdbeChangeP5(v, p5);
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
}
switch( eDest ){
@ -3642,6 +3638,13 @@ static int flattenSubquery(
*/
sqlite3SelectDelete(db, pSub1);
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
sqlite3DebugPrintf("After flattening:\n");
sqlite3TreeViewSelect(0, p, 0);
}
#endif
return 1;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
@ -4649,7 +4652,10 @@ int sqlite3Select(
memset(&sAggInfo, 0, sizeof(sAggInfo));
#if SELECTTRACE_ENABLED
pParse->nSelectIndent++;
SELECTTRACE(1,pParse,p, ("begin processing\n"));
SELECTTRACE(1,pParse,p, ("begin processing:\n"));
if( sqlite3SelectTrace & 0x100 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
@ -5146,12 +5152,11 @@ int sqlite3Select(
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
sqlite3ExprCacheClear(pParse);
if( groupBySort ){
sqlite3VdbeAddOp2(v, OP_SorterData, sAggInfo.sortingIdx, sortOut);
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, sortOut,sortPTab);
}
for(j=0; j<pGroupBy->nExpr; j++){
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
if( j==0 ) sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
}else{
sAggInfo.directMode = 1;
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
@ -5417,97 +5422,96 @@ select_end:
return rc;
}
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
#ifdef SQLITE_DEBUG
/*
** Generate a human-readable description of a the Select object.
*/
static void explainOneSelect(Vdbe *pVdbe, Select *p){
sqlite3ExplainPrintf(pVdbe, "SELECT ");
if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
if( p->selFlags & SF_Distinct ){
sqlite3ExplainPrintf(pVdbe, "DISTINCT ");
}
if( p->selFlags & SF_Aggregate ){
sqlite3ExplainPrintf(pVdbe, "agg_flag ");
}
sqlite3ExplainNL(pVdbe);
sqlite3ExplainPrintf(pVdbe, " ");
}
sqlite3ExplainExprList(pVdbe, p->pEList);
sqlite3ExplainNL(pVdbe);
void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
pView = sqlite3TreeViewPush(pView, moreToFollow);
sqlite3TreeViewLine(pView, "SELECT%s%s",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
((p->selFlags & SF_Aggregate) ? " agg_flag" : "")
);
if( p->pSrc && p->pSrc->nSrc ) n++;
if( p->pWhere ) n++;
if( p->pGroupBy ) n++;
if( p->pHaving ) n++;
if( p->pOrderBy ) n++;
if( p->pLimit ) n++;
if( p->pOffset ) n++;
if( p->pPrior ) n++;
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
if( p->pSrc && p->pSrc->nSrc ){
int i;
sqlite3ExplainPrintf(pVdbe, "FROM ");
sqlite3ExplainPush(pVdbe);
pView = sqlite3TreeViewPush(pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
for(i=0; i<p->pSrc->nSrc; i++){
struct SrcList_item *pItem = &p->pSrc->a[i];
sqlite3ExplainPrintf(pVdbe, "{%d,*} = ", pItem->iCursor);
if( pItem->pSelect ){
sqlite3ExplainSelect(pVdbe, pItem->pSelect);
if( pItem->pTab ){
sqlite3ExplainPrintf(pVdbe, " (tabname=%s)", pItem->pTab->zName);
}
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, zLine, sizeof(zLine), 0);
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
if( pItem->zDatabase ){
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);
}else if( pItem->zName ){
sqlite3ExplainPrintf(pVdbe, "%s", pItem->zName);
sqlite3XPrintf(&x, 0, " %s", pItem->zName);
}
if( pItem->pTab ){
sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName);
}
if( pItem->zAlias ){
sqlite3ExplainPrintf(pVdbe, " (AS %s)", pItem->zAlias);
sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias);
}
if( pItem->jointype & JT_LEFT ){
sqlite3ExplainPrintf(pVdbe, " LEFT-JOIN");
sqlite3XPrintf(&x, 0, " LEFT-JOIN");
}
sqlite3ExplainNL(pVdbe);
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
if( pItem->pSelect ){
sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
}
sqlite3TreeViewPop(pView);
}
sqlite3ExplainPop(pVdbe);
sqlite3TreeViewPop(pView);
}
if( p->pWhere ){
sqlite3ExplainPrintf(pVdbe, "WHERE ");
sqlite3ExplainExpr(pVdbe, p->pWhere);
sqlite3ExplainNL(pVdbe);
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
sqlite3TreeViewExpr(pView, p->pWhere, 0);
sqlite3TreeViewPop(pView);
}
if( p->pGroupBy ){
sqlite3ExplainPrintf(pVdbe, "GROUPBY ");
sqlite3ExplainExprList(pVdbe, p->pGroupBy);
sqlite3ExplainNL(pVdbe);
sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
}
if( p->pHaving ){
sqlite3ExplainPrintf(pVdbe, "HAVING ");
sqlite3ExplainExpr(pVdbe, p->pHaving);
sqlite3ExplainNL(pVdbe);
sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
sqlite3TreeViewExpr(pView, p->pHaving, 0);
sqlite3TreeViewPop(pView);
}
if( p->pOrderBy ){
sqlite3ExplainPrintf(pVdbe, "ORDERBY ");
sqlite3ExplainExprList(pVdbe, p->pOrderBy);
sqlite3ExplainNL(pVdbe);
sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
}
if( p->pLimit ){
sqlite3ExplainPrintf(pVdbe, "LIMIT ");
sqlite3ExplainExpr(pVdbe, p->pLimit);
sqlite3ExplainNL(pVdbe);
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit, 0);
sqlite3TreeViewPop(pView);
}
if( p->pOffset ){
sqlite3ExplainPrintf(pVdbe, "OFFSET ");
sqlite3ExplainExpr(pVdbe, p->pOffset);
sqlite3ExplainNL(pVdbe);
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
sqlite3TreeViewExpr(pView, p->pOffset, 0);
sqlite3TreeViewPop(pView);
}
if( p->pPrior ){
const char *zOp = "UNION";
switch( p->op ){
case TK_ALL: zOp = "UNION ALL"; break;
case TK_INTERSECT: zOp = "INTERSECT"; break;
case TK_EXCEPT: zOp = "EXCEPT"; break;
}
sqlite3TreeViewItem(pView, zOp, (n--)>0);
sqlite3TreeViewSelect(pView, p->pPrior, 0);
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
}
void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
if( p==0 ){
sqlite3ExplainPrintf(pVdbe, "(null-select)");
return;
}
sqlite3ExplainPush(pVdbe);
while( p ){
explainOneSelect(pVdbe, p);
p = p->pNext;
if( p==0 ) break;
sqlite3ExplainNL(pVdbe);
sqlite3ExplainPrintf(pVdbe, "%s\n", selectOpName(p->op));
}
sqlite3ExplainPrintf(pVdbe, "END");
sqlite3ExplainPop(pVdbe);
}
/* End of the structure debug printing code
*****************************************************************************/
#endif /* defined(SQLITE_ENABLE_TREE_EXPLAIN) */
#endif /* SQLITE_DEBUG */

View File

@ -1353,15 +1353,6 @@ static int shell_exec(
sqlite3_free(zEQP);
}
/* Output TESTCTRL_EXPLAIN text of requested */
if( pArg && pArg->mode==MODE_Explain ){
const char *zExplain = 0;
sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain);
if( zExplain && zExplain[0] ){
fprintf(pArg->out, "%s", zExplain);
}
}
/* If the shell is currently in ".explain" mode, gather the extra
** data required to add indents to the output.*/
if( pArg && pArg->mode==MODE_Explain ){
@ -3734,6 +3725,7 @@ static int process_input(ShellState *p, FILE *in){
if( nSql ){
if( !_all_whitespace(zSql) ){
fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
errCnt++;
}
free(zSql);
}

View File

@ -2664,9 +2664,9 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** an English language description of the error following a failure of any
** of the sqlite3_open() routines.
**
** ^The default encoding for the database will be UTF-8 if
** sqlite3_open() or sqlite3_open_v2() is called and
** UTF-16 in the native byte order if sqlite3_open16() is used.
** ^The default encoding will be UTF-8 for databases created using
** sqlite3_open() or sqlite3_open_v2(). ^The default encoding for databases
** created using sqlite3_open16() will be UTF-16 in the native byte order.
**
** Whether or not an error occurs when it is opened, resources
** associated with the [database connection] handle should be released by
@ -2754,13 +2754,14 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** then it is interpreted as an absolute path. ^If the path does not begin
** with a '/' (meaning that the authority section is omitted from the URI)
** then the path is interpreted as a relative path.
** ^On windows, the first component of an absolute path
** is a drive specification (e.g. "C:").
** ^(On windows, the first component of an absolute path
** is a drive specification (e.g. "C:").)^
**
** [[core URI query parameters]]
** The query component of a URI may contain parameters that are interpreted
** either by SQLite itself, or by a [VFS | custom VFS implementation].
** SQLite interprets the following three query parameters:
** SQLite and its built-in [VFSes] interpret the
** following query parameters:
**
** <ul>
** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
@ -2795,11 +2796,9 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** a URI filename, its value overrides any behavior requested by setting
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
**
** <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
** "1") or "false" (or "off" or "no" or "0") to indicate that the
** <li> <b>psow</b>: ^The psow parameter indicates whether or not the
** [powersafe overwrite] property does or does not apply to the
** storage media on which the database file resides. ^The psow query
** parameter only works for the built-in unix and Windows VFSes.
** storage media on which the database file resides.
**
** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
** which if set disables file locking in rollback journal modes. This
@ -3394,11 +3393,10 @@ typedef struct sqlite3_context sqlite3_context;
** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined.
**
** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
** ^The fifth argument to the BLOB and string binding interfaces
** is a destructor used to dispose of the BLOB or
** string after SQLite has finished with it. ^The destructor is called
** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(),
** sqlite3_bind_text(), or sqlite3_bind_text16() fails.
** to dispose of the BLOB or string even if the call to bind API fails.
** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.
@ -3409,7 +3407,7 @@ typedef struct sqlite3_context sqlite3_context;
** ^The sixth argument to sqlite3_bind_text64() must be one of
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
** to specify the encoding of the text in the third parameter. If
** the sixth argument to sqlite3_bind_text64() is not how of the
** the sixth argument to sqlite3_bind_text64() is not one of the
** allowed values shown above, or if the text encoding is different
** from the encoding specified by the sixth parameter, then the behavior
** is undefined.
@ -4445,7 +4443,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** of the application-defined function to be NULL.
**
** ^The sqlite3_result_text(), sqlite3_result_text16(),
** sqlite3_result_text16le(), and sqlite3_result_text16be()
** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
** set the return value of the application-defined function to be
** a text string which is represented as UTF-8, UTF-16 native byte order,
** UTF-16 little endian, or UTF-16 big endian, respectively.
@ -6205,7 +6203,7 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_ISKEYWORD 16
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
#define SQLITE_TESTCTRL_BYTEORDER 22

View File

@ -159,7 +159,7 @@
*/
#if defined(__GNUC__)
# define SQLITE_NOINLINE __attribute__((noinline))
#elif defined(_MSC_VER)
#elif defined(_MSC_VER) && _MSC_VER>=1310
# define SQLITE_NOINLINE __declspec(noinline)
#else
# define SQLITE_NOINLINE
@ -469,6 +469,11 @@
#define MIN(A,B) ((A)<(B)?(A):(B))
#define MAX(A,B) ((A)>(B)?(A):(B))
/*
** Swap two objects of type TYPE.
*/
#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
/*
** Check to see if this machine uses EBCDIC. (Yes, believe it or
** not, there are still machines out there that use EBCDIC.)
@ -855,6 +860,7 @@ typedef struct StrAccum StrAccum;
typedef struct Table Table;
typedef struct TableLock TableLock;
typedef struct Token Token;
typedef struct TreeView TreeView;
typedef struct Trigger Trigger;
typedef struct TriggerPrg TriggerPrg;
typedef struct TriggerStep TriggerStep;
@ -1795,6 +1801,7 @@ struct Index {
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */
IndexSample *aSample; /* Samples of the left-most key */
tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this table */
#endif
};
@ -2225,7 +2232,7 @@ struct SrcList {
#define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */
#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */
#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */
#define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */
/* 0x0080 // not currently used */
#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
@ -2659,7 +2666,6 @@ struct AuthContext {
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
#define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
@ -2923,6 +2929,17 @@ struct With {
} a[1];
};
#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
** data structures on sqlite3DebugPrintf() using a tree-like view.
*/
struct TreeView {
int iLevel; /* Which level of the tree we are on */
u8 bLine[100]; /* Draw vertical in column i if bLine[i] is true */
};
#endif /* SQLITE_DEBUG */
/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
@ -3087,25 +3104,14 @@ char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
void *sqlite3TestTextToPtr(const char*);
#endif
/* Output formatting for SQLITE_TESTCTRL_EXPLAIN */
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
void sqlite3ExplainBegin(Vdbe*);
void sqlite3ExplainPrintf(Vdbe*, const char*, ...);
void sqlite3ExplainNL(Vdbe*);
void sqlite3ExplainPush(Vdbe*);
void sqlite3ExplainPop(Vdbe*);
void sqlite3ExplainFinish(Vdbe*);
void sqlite3ExplainSelect(Vdbe*, Select*);
void sqlite3ExplainExpr(Vdbe*, Expr*);
void sqlite3ExplainExprList(Vdbe*, ExprList*);
const char *sqlite3VdbeExplanation(Vdbe*);
#else
# define sqlite3ExplainBegin(X)
# define sqlite3ExplainSelect(A,B)
# define sqlite3ExplainExpr(A,B)
# define sqlite3ExplainExprList(A,B)
# define sqlite3ExplainFinish(X)
# define sqlite3VdbeExplanation(X) 0
#if defined(SQLITE_DEBUG)
TreeView *sqlite3TreeViewPush(TreeView*,u8);
void sqlite3TreeViewPop(TreeView*);
void sqlite3TreeViewLine(TreeView*, const char*, ...);
void sqlite3TreeViewItem(TreeView*, const char*, u8);
void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
#endif
@ -3793,10 +3799,9 @@ SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...);
# define sqlite3MemdebugNoType(X,Y) 1
#endif
#define MEMTYPE_HEAP 0x01 /* General heap allocations */
#define MEMTYPE_LOOKASIDE 0x02 /* Might have been lookaside memory */
#define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */
#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */
#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */
#define MEMTYPE_DB 0x10 /* Uses sqlite3DbMalloc, not sqlite_malloc */
/*
** Threading interface

View File

@ -213,7 +213,7 @@ int sqlite3_db_status(
}
db->pnBytesFreed = 0;
*pHighwater = 0;
*pHighwater = 0; /* IMP: R-64479-57858 */
*pCurrent = nByte;
break;
@ -238,7 +238,9 @@ int sqlite3_db_status(
sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
}
}
*pHighwater = 0;
*pHighwater = 0; /* IMP: R-42420-56072 */
/* IMP: R-54100-20147 */
/* IMP: R-29431-39229 */
*pCurrent = nRet;
break;
}
@ -248,7 +250,7 @@ int sqlite3_db_status(
** have been satisfied. The *pHighwater is always set to zero.
*/
case SQLITE_DBSTATUS_DEFERRED_FKS: {
*pHighwater = 0;
*pHighwater = 0; /* IMP: R-11967-56545 */
*pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0;
break;
}

View File

@ -5513,10 +5513,11 @@ static int test_limit(
{ "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
{ "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER },
{ "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
{ "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS },
/* Out of range test cases */
{ "SQLITE_LIMIT_TOOSMALL", -1, },
{ "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_TRIGGER_DEPTH+1 },
{ "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS+1 },
};
int i, id;
int val;

View File

@ -644,6 +644,7 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
LINKVAR( DEFAULT_FILE_FORMAT );
LINKVAR( MAX_ATTACHED );
LINKVAR( MAX_DEFAULT_PAGE_SIZE );
LINKVAR( MAX_WORKER_THREADS );
{
static const int cv_TEMP_STORE = SQLITE_TEMP_STORE;

View File

@ -105,7 +105,7 @@ int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
/* A running thread */
struct SQLiteThread {
uintptr_t tid; /* The thread handle */
void *tid; /* The thread handle */
unsigned id; /* The thread identifier */
void *(*xTask)(void*); /* The routine to run as a thread */
void *pIn; /* Argument to xTask */
@ -153,7 +153,7 @@ int sqlite3ThreadCreate(
}else{
p->xTask = xTask;
p->pIn = pIn;
p->tid = _beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id);
p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id);
if( p->tid==0 ){
memset(p, 0, sizeof(*p));
}

View File

@ -214,6 +214,7 @@ static VdbeCursor *allocateCursor(
memset(pCx, 0, sizeof(VdbeCursor));
pCx->iDb = iDb;
pCx->nField = nField;
pCx->aOffset = &pCx->aType[nField];
if( isBtreeCursor ){
pCx->pCursor = (BtCursor*)
&pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
@ -1558,6 +1559,7 @@ case OP_Function: {
ctx.pVdbe = p;
MemSetTypeFlag(ctx.pOut, MEM_Null);
ctx.fErrorOrAux = 0;
db->lastRowid = lastRowid;
(*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
lastRowid = db->lastRowid; /* Remember rowid changes made by xFunc */
@ -2275,7 +2277,7 @@ case OP_Column: {
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( p2<pC->nField );
aOffset = pC->aType + pC->nField;
aOffset = pC->aOffset;
#ifndef SQLITE_OMIT_VIRTUALTABLE
assert( pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */
#endif
@ -2286,7 +2288,7 @@ case OP_Column: {
/* If the cursor cache is stale, bring it up-to-date */
rc = sqlite3VdbeCursorMoveto(pC);
if( rc ) goto abort_due_to_error;
if( pC->cacheStatus!=p->cacheCtr || (pOp->p5&OPFLAG_CLEARCACHE)!=0 ){
if( pC->cacheStatus!=p->cacheCtr ){
if( pC->nullRow ){
if( pCrsr==0 ){
assert( pC->pseudoTableReg>0 );
@ -2331,14 +2333,6 @@ case OP_Column: {
pC->iHdrOffset = getVarint32(pC->aRow, offset);
pC->nHdrParsed = 0;
aOffset[0] = offset;
if( avail<offset ){
/* pC->aRow does not have to hold the entire row, but it does at least
** need to cover the header of the record. If pC->aRow does not contain
** the complete header, then set it to zero, forcing the header to be
** dynamically allocated. */
pC->aRow = 0;
pC->szRow = 0;
}
/* Make sure a corrupt database has not given us an oversize header.
** Do this now to avoid an oversize memory allocation.
@ -2353,6 +2347,22 @@ case OP_Column: {
rc = SQLITE_CORRUPT_BKPT;
goto op_column_error;
}
if( avail<offset ){
/* pC->aRow does not have to hold the entire row, but it does at least
** need to cover the header of the record. If pC->aRow does not contain
** the complete header, then set it to zero, forcing the header to be
** dynamically allocated. */
pC->aRow = 0;
pC->szRow = 0;
}
/* The following goto is an optimization. It can be omitted and
** everything will still work. But OP_Column is measurably faster
** by skipping the subsequent conditional, which is always true.
*/
assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */
goto op_column_read_header;
}
/* Make sure at least the first p2+1 entries of the header have been
@ -2362,6 +2372,7 @@ case OP_Column: {
/* If there is more header available for parsing in the record, try
** to extract additional fields up through the p2+1-th field
*/
op_column_read_header:
if( pC->iHdrOffset<aOffset[0] ){
/* Make sure zData points to enough of the record to cover the header. */
if( pC->aRow==0 ){
@ -3553,7 +3564,6 @@ case OP_SeekGT: { /* jump, in3 */
applyNumericAffinity(pIn3, 0);
}
iKey = sqlite3VdbeIntValue(pIn3);
pC->rowidIsValid = 0;
/* If the P3 value could not be converted into an integer without
** loss of information, then special processing is required... */
@ -3589,13 +3599,10 @@ case OP_SeekGT: { /* jump, in3 */
}
}
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
pC->movetoTarget = iKey; /* Used by OP_Delete */
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
if( res==0 ){
pC->rowidIsValid = 1;
pC->lastRowid = iKey;
}
}else{
nField = pOp->p4.i;
assert( pOp->p4type==P4_INT32 );
@ -3625,7 +3632,6 @@ case OP_SeekGT: { /* jump, in3 */
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
pC->rowidIsValid = 0;
}
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
@ -3637,7 +3643,6 @@ case OP_SeekGT: { /* jump, in3 */
res = 0;
rc = sqlite3BtreeNext(pC->pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
pC->rowidIsValid = 0;
}else{
res = 0;
}
@ -3647,7 +3652,6 @@ case OP_SeekGT: { /* jump, in3 */
res = 0;
rc = sqlite3BtreePrevious(pC->pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
pC->rowidIsValid = 0;
}else{
/* res might be negative because the table is empty. Check to
** see if this is the case.
@ -3684,7 +3688,6 @@ case OP_Seek: { /* in2 */
pC->nullRow = 0;
pIn2 = &aMem[pOp->p2];
pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
pC->rowidIsValid = 0;
pC->deferredMoveto = 1;
break;
}
@ -3870,15 +3873,13 @@ case OP_NotExists: { /* jump, in3 */
res = 0;
iKey = pIn3->u.i;
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
pC->lastRowid = pIn3->u.i;
pC->rowidIsValid = res==0 ?1:0;
pC->movetoTarget = iKey; /* Used by OP_Delete */
pC->nullRow = 0;
pC->cacheStatus = CACHE_STALE;
pC->deferredMoveto = 0;
VdbeBranchTaken(res!=0,2);
if( res!=0 ){
pc = pOp->p2 - 1;
assert( pC->rowidIsValid==0 );
}
pC->seekResult = res;
break;
@ -4026,7 +4027,6 @@ case OP_NewRowid: { /* out2-prerelease */
}
assert( v>0 ); /* EV: R-40812-03570 */
}
pC->rowidIsValid = 0;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
}
@ -4131,7 +4131,6 @@ case OP_InsertInt: {
pData->z, pData->n, nZero,
(pOp->p5 & OPFLAG_APPEND)!=0, seekResult
);
pC->rowidIsValid = 0;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
@ -4168,33 +4167,32 @@ case OP_InsertInt: {
** using OP_NotFound prior to invoking this opcode.
*/
case OP_Delete: {
i64 iKey;
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
iKey = pC->lastRowid; /* Only used for the update hook */
/* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
** OP_Column on the same table without any intervening operations that
** might move or invalidate the cursor. Hence cursor pC is always pointing
** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
** below is always a no-op and cannot fail. We will run it anyhow, though,
** to guard against future changes to the code generator.
**/
assert( pC->deferredMoveto==0 );
rc = sqlite3VdbeCursorMoveto(pC);
if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
#ifdef SQLITE_DEBUG
/* The seek operation that positioned the cursor prior to OP_Delete will
** have also set the pC->movetoTarget field to the rowid of the row that
** is being deleted */
if( pOp->p4.z && pC->isTable ){
i64 iKey = 0;
sqlite3BtreeKeySize(pC->pCursor, &iKey);
assert( pC->movetoTarget==iKey );
}
#endif
rc = sqlite3BtreeDelete(pC->pCursor);
pC->cacheStatus = CACHE_STALE;
/* Invoke the update-hook if required. */
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && pC->isTable ){
db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE,
db->aDb[pC->iDb].zName, pOp->p4.z, iKey);
db->aDb[pC->iDb].zName, pOp->p4.z, pC->movetoTarget);
assert( pC->iDb>=0 );
}
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
@ -4247,10 +4245,17 @@ case OP_SorterCompare: {
break;
};
/* Opcode: SorterData P1 P2 * * *
/* Opcode: SorterData P1 P2 P3 * *
** Synopsis: r[P2]=data
**
** Write into register P2 the current sorter data for sorter cursor P1.
** Then clear the column header cache on cursor P3.
**
** This opcode is normally use to move a record out of the sorter and into
** a register that is the source for a pseudo-table cursor created using
** OpenPseudo. That pseudo-table cursor is the one that is identified by
** parameter P3. Clearing the P3 column cache as part of this opcode saves
** us from having to issue a separate NullRow instruction to clear that cache.
*/
case OP_SorterData: {
VdbeCursor *pC;
@ -4260,6 +4265,8 @@ case OP_SorterData: {
assert( isSorter(pC) );
rc = sqlite3VdbeSorterRowkey(pC, pOut);
assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE;
break;
}
@ -4306,16 +4313,20 @@ case OP_RowData: {
assert( pC->pseudoTableReg==0 );
assert( pC->pCursor!=0 );
pCrsr = pC->pCursor;
assert( sqlite3BtreeCursorIsValid(pCrsr) );
/* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
** OP_Rewind/Op_Next with no intervening instructions that might invalidate
** the cursor. Hence the following sqlite3VdbeCursorMoveto() call is always
** a no-op and can never fail. But we leave it in place as a safety.
** the cursor. If this where not the case, on of the following assert()s
** would fail. Should this ever change (because of changes in the code
** generator) then the fix would be to insert a call to
** sqlite3VdbeCursorMoveto().
*/
assert( pC->deferredMoveto==0 );
assert( sqlite3BtreeCursorIsValid(pCrsr) );
#if 0 /* Not required due to the previous to assert() statements */
rc = sqlite3VdbeCursorMoveto(pC);
if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
if( rc!=SQLITE_OK ) goto abort_due_to_error;
#endif
if( pC->isTable==0 ){
assert( !pC->isTable );
@ -4332,7 +4343,8 @@ case OP_RowData: {
goto too_big;
}
}
if( sqlite3VdbeMemClearAndResize(pOut, n) ){
testcase( n==0 );
if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){
goto no_mem;
}
pOut->n = n;
@ -4383,14 +4395,10 @@ case OP_Rowid: { /* out2-prerelease */
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
assert( pC->pCursor!=0 );
rc = sqlite3VdbeCursorMoveto(pC);
rc = sqlite3VdbeCursorRestore(pC);
if( rc ) goto abort_due_to_error;
if( pC->rowidIsValid ){
v = pC->lastRowid;
}else{
rc = sqlite3BtreeKeySize(pC->pCursor, &v);
assert( rc==SQLITE_OK ); /* Always so because of CursorMoveto() above */
}
rc = sqlite3BtreeKeySize(pC->pCursor, &v);
assert( rc==SQLITE_OK ); /* Always so because of CursorRestore() above */
}
pOut->u.i = v;
break;
@ -4409,7 +4417,6 @@ case OP_NullRow: {
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
pC->nullRow = 1;
pC->rowidIsValid = 0;
pC->cacheStatus = CACHE_STALE;
if( pC->pCursor ){
sqlite3BtreeClearCursor(pC->pCursor);
@ -4443,7 +4450,6 @@ case OP_Last: { /* jump */
rc = sqlite3BtreeLast(pCrsr, &res);
pC->nullRow = (u8)res;
pC->deferredMoveto = 0;
pC->rowidIsValid = 0;
pC->cacheStatus = CACHE_STALE;
#ifdef SQLITE_DEBUG
pC->seekOp = OP_Last;
@ -4510,7 +4516,6 @@ case OP_Rewind: { /* jump */
rc = sqlite3BtreeFirst(pCrsr, &res);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
pC->rowidIsValid = 0;
}
pC->nullRow = (u8)res;
assert( pOp->p2>0 && pOp->p2<p->nOp );
@ -4636,7 +4641,6 @@ next_tail:
}else{
pC->nullRow = 1;
}
pC->rowidIsValid = 0;
goto check_for_interrupt;
}
@ -4752,10 +4756,16 @@ case OP_IdxRowid: { /* out2-prerelease */
pCrsr = pC->pCursor;
assert( pCrsr!=0 );
pOut->flags = MEM_Null;
rc = sqlite3VdbeCursorMoveto(pC);
if( NEVER(rc) ) goto abort_due_to_error;
assert( pC->deferredMoveto==0 );
assert( pC->isTable==0 );
assert( pC->deferredMoveto==0 );
/* sqlite3VbeCursorRestore() can only fail if the record has been deleted
** out from under the cursor. That will never happend for an IdxRowid
** opcode, hence the NEVER() arround the check of the return value.
*/
rc = sqlite3VdbeCursorRestore(pC);
if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
if( !pC->nullRow ){
rowid = 0; /* Not needed. Only used to silence a warning. */
rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid);

View File

@ -73,7 +73,6 @@ struct VdbeCursor {
#endif
i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
u8 nullRow; /* True if pointing to a row with no data */
u8 rowidIsValid; /* True if lastRowid is valid */
u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
@ -83,7 +82,6 @@ struct VdbeCursor {
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
i64 seqCount; /* Sequence counter */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
i64 lastRowid; /* Rowid being deleted by OP_Delete */
VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
/* Cached information about the header for the data record that the
@ -100,6 +98,7 @@ struct VdbeCursor {
u32 szRow; /* Byte available in aRow */
u32 iHdrOffset; /* Offset to next unparsed byte of the header */
const u8 *aRow; /* Data for the current row, if all on one page */
u32 *aOffset; /* Pointer to aType[nField] */
u32 aType[1]; /* Type values for all entries in the record */
/* 2*nField extra array elements allocated for aType[], beyond the one
** static element declared in the structure. nField total array slots for
@ -360,10 +359,6 @@ struct Vdbe {
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
char *zSql; /* Text of the SQL statement that generated this */
void *pFree; /* Free this when deleting the vdbe */
#ifdef SQLITE_ENABLE_TREE_EXPLAIN
Explain *pExplain; /* The explainer */
char *zExplain; /* Explanation of data structures */
#endif
VdbeFrame *pFrame; /* Parent frame */
VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
int nFrame; /* Number of frames in pFrame list */
@ -388,6 +383,7 @@ struct Vdbe {
void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
int sqlite3VdbeCursorMoveto(VdbeCursor*);
int sqlite3VdbeCursorRestore(VdbeCursor*);
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
void sqlite3VdbePrintOp(FILE*, int, Op*);
#endif

View File

@ -318,6 +318,7 @@ void sqlite3_result_text64(
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
assert( xDel!=SQLITE_DYNAMIC );
if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
if( n>0x7fffffff ){
(void)invokeValueDestructor(z, xDel, pCtx);
}else{

View File

@ -752,7 +752,8 @@ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
}
/*
** Remove the last opcode inserted
** If the last opcode is "op" and it is not a jump destination,
** then remove it. Return true if and only if an opcode was removed.
*/
int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){
@ -1744,7 +1745,7 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
sqlite3BtreeCloseCursor(pCx->pCursor);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pCx->pVtabCursor ){
else if( pCx->pVtabCursor ){
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
const sqlite3_module *pModule = pVtabCursor->pVtab->pModule;
p->inVtabMethod = 1;
@ -1787,9 +1788,10 @@ static void closeAllCursors(Vdbe *p){
VdbeFrame *pFrame;
for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
sqlite3VdbeFrameRestore(pFrame);
p->pFrame = 0;
p->nFrame = 0;
}
p->pFrame = 0;
p->nFrame = 0;
assert( p->nFrame==0 );
if( p->apCsr ){
int i;
@ -1811,7 +1813,7 @@ static void closeAllCursors(Vdbe *p){
}
/* Delete any auxdata allocations made by the VM */
sqlite3VdbeDeleteAuxData(p, -1, 0);
if( p->pAuxData ) sqlite3VdbeDeleteAuxData(p, -1, 0);
assert( p->pAuxData==0 );
}
@ -2677,10 +2679,6 @@ void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
sqlite3DbFree(db, p->aColName);
sqlite3DbFree(db, p->zSql);
sqlite3DbFree(db, p->pFree);
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
sqlite3DbFree(db, p->zExplain);
sqlite3DbFree(db, p->pExplain);
#endif
}
/*
@ -2721,9 +2719,7 @@ static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
assert( p->isTable );
rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
if( rc ) return rc;
p->lastRowid = p->movetoTarget;
if( res!=0 ) return SQLITE_CORRUPT_BKPT;
p->rowidIsValid = 1;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
@ -2749,6 +2745,17 @@ static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){
return rc;
}
/*
** Check to ensure that the cursor is valid. Restore the cursor
** if need be. Return any I/O error from the restore operation.
*/
int sqlite3VdbeCursorRestore(VdbeCursor *p){
if( sqlite3BtreeCursorHasMoved(p->pCursor) ){
return handleMovedCursor(p);
}
return SQLITE_OK;
}
/*
** Make sure the cursor p is ready to read or write the row to which it
** was last positioned. Return an error code if an OOM fault or I/O error
@ -2766,7 +2773,7 @@ int sqlite3VdbeCursorMoveto(VdbeCursor *p){
if( p->deferredMoveto ){
return handleDeferredMoveto(p);
}
if( sqlite3BtreeCursorHasMoved(p->pCursor) ){
if( p->pCursor && sqlite3BtreeCursorHasMoved(p->pCursor) ){
return handleMovedCursor(p);
}
return SQLITE_OK;

View File

@ -31,7 +31,10 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){
*/
assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
/* MEM_Dyn may only be set if Mem.szMalloc==0 */
/* MEM_Dyn may only be set if Mem.szMalloc==0. In this way we
** ensure that if Mem.szMalloc>0 then it is safe to do
** Mem.z = Mem.zMalloc without having to check Mem.flags&MEM_Dyn.
** That saves a few cycles in inner loops. */
assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 );
/* Cannot be both MEM_Int and MEM_Real at the same time */
@ -167,7 +170,8 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
** if unable to complete the resizing.
*/
int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
assert( szNew>=0 );
assert( szNew>0 );
assert( (pMem->flags & MEM_Dyn)==0 || pMem->szMalloc==0 );
if( pMem->szMalloc<szNew ){
return sqlite3VdbeMemGrow(pMem, szNew, 0);
}
@ -891,7 +895,10 @@ int sqlite3VdbeMemSetStr(
if( nByte>iLimit ){
return SQLITE_TOOBIG;
}
if( sqlite3VdbeMemClearAndResize(pMem, nAlloc) ){
testcase( nAlloc==0 );
testcase( nAlloc==31 );
testcase( nAlloc==32 );
if( sqlite3VdbeMemClearAndResize(pMem, MAX(nAlloc,32)) ){
return SQLITE_NOMEM;
}
memcpy(pMem->z, z, nAlloc);
@ -994,7 +1001,7 @@ int sqlite3VdbeMemFromBtree(
** Convert it into a string with encoding enc and return a pointer
** to a zero-terminated version of that string.
*/
SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
assert( pVal!=0 );
assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );

View File

@ -183,118 +183,3 @@ char *sqlite3VdbeExpandSql(
}
#endif /* #ifndef SQLITE_OMIT_TRACE */
/*****************************************************************************
** The following code implements the data-structure explaining logic
** for the Vdbe.
*/
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
/*
** Allocate a new Explain object
*/
void sqlite3ExplainBegin(Vdbe *pVdbe){
if( pVdbe ){
Explain *p;
sqlite3BeginBenignMalloc();
p = (Explain *)sqlite3MallocZero( sizeof(Explain) );
if( p ){
p->pVdbe = pVdbe;
sqlite3_free(pVdbe->pExplain);
pVdbe->pExplain = p;
sqlite3StrAccumInit(&p->str, p->zBase, sizeof(p->zBase),
SQLITE_MAX_LENGTH);
p->str.useMalloc = 2;
}else{
sqlite3EndBenignMalloc();
}
}
}
/*
** Return true if the Explain ends with a new-line.
*/
static int endsWithNL(Explain *p){
return p && p->str.zText && p->str.nChar
&& p->str.zText[p->str.nChar-1]=='\n';
}
/*
** Append text to the indentation
*/
void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){
Explain *p;
if( pVdbe && (p = pVdbe->pExplain)!=0 ){
va_list ap;
if( p->nIndent && endsWithNL(p) ){
int n = p->nIndent;
if( n>ArraySize(p->aIndent) ) n = ArraySize(p->aIndent);
sqlite3AppendSpace(&p->str, p->aIndent[n-1]);
}
va_start(ap, zFormat);
sqlite3VXPrintf(&p->str, SQLITE_PRINTF_INTERNAL, zFormat, ap);
va_end(ap);
}
}
/*
** Append a '\n' if there is not already one.
*/
void sqlite3ExplainNL(Vdbe *pVdbe){
Explain *p;
if( pVdbe && (p = pVdbe->pExplain)!=0 && !endsWithNL(p) ){
sqlite3StrAccumAppend(&p->str, "\n", 1);
}
}
/*
** Push a new indentation level. Subsequent lines will be indented
** so that they begin at the current cursor position.
*/
void sqlite3ExplainPush(Vdbe *pVdbe){
Explain *p;
if( pVdbe && (p = pVdbe->pExplain)!=0 ){
if( p->str.zText && p->nIndent<ArraySize(p->aIndent) ){
const char *z = p->str.zText;
int i = p->str.nChar-1;
int x;
while( i>=0 && z[i]!='\n' ){ i--; }
x = (p->str.nChar - 1) - i;
if( p->nIndent && x<p->aIndent[p->nIndent-1] ){
x = p->aIndent[p->nIndent-1];
}
p->aIndent[p->nIndent] = x;
}
p->nIndent++;
}
}
/*
** Pop the indentation stack by one level.
*/
void sqlite3ExplainPop(Vdbe *p){
if( p && p->pExplain ) p->pExplain->nIndent--;
}
/*
** Free the indentation structure
*/
void sqlite3ExplainFinish(Vdbe *pVdbe){
if( pVdbe && pVdbe->pExplain ){
sqlite3_free(pVdbe->zExplain);
sqlite3ExplainNL(pVdbe);
pVdbe->zExplain = sqlite3StrAccumFinish(&pVdbe->pExplain->str);
sqlite3_free(pVdbe->pExplain);
pVdbe->pExplain = 0;
sqlite3EndBenignMalloc();
}
}
/*
** Return the explanation of a virtual machine.
*/
const char *sqlite3VdbeExplanation(Vdbe *pVdbe){
return (pVdbe && pVdbe->zExplain) ? pVdbe->zExplain : 0;
}
#endif /* defined(SQLITE_DEBUG) */

View File

@ -364,11 +364,6 @@ static int allowedOp(int op){
return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL;
}
/*
** Swap two objects of type TYPE.
*/
#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
/*
** Commute a comparison operator. Expressions of the form "X op Y"
** are converted into "Y op X".
@ -2212,16 +2207,23 @@ static int whereRangeScanEst(
iUpper = a[0] + a[1];
}
assert( pLower==0 || (pLower->eOperator & (WO_GT|WO_GE))!=0 );
assert( pUpper==0 || (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
assert( p->aSortOrder!=0 );
if( p->aSortOrder[nEq] ){
/* The roles of pLower and pUpper are swapped for a DESC index */
SWAP(WhereTerm*, pLower, pUpper);
}
/* If possible, improve on the iLower estimate using ($P:$L). */
if( pLower ){
int bOk; /* True if value is extracted from pExpr */
Expr *pExpr = pLower->pExpr->pRight;
assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
if( rc==SQLITE_OK && bOk ){
tRowcnt iNew;
whereKeyStats(pParse, p, pRec, 0, a);
iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0);
iNew = a[0] + ((pLower->eOperator & (WO_GT|WO_LE)) ? a[1] : 0);
if( iNew>iLower ) iLower = iNew;
nOut--;
pLower = 0;
@ -2232,12 +2234,11 @@ static int whereRangeScanEst(
if( pUpper ){
int bOk; /* True if value is extracted from pExpr */
Expr *pExpr = pUpper->pExpr->pRight;
assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
if( rc==SQLITE_OK && bOk ){
tRowcnt iNew;
whereKeyStats(pParse, p, pRec, 1, a);
iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0);
iNew = a[0] + ((pUpper->eOperator & (WO_GT|WO_LE)) ? a[1] : 0);
if( iNew<iUpper ) iUpper = iNew;
nOut--;
pUpper = 0;
@ -2736,9 +2737,8 @@ static void explainAppendTerm(
/*
** Argument pLevel describes a strategy for scanning table pTab. This
** function returns a pointer to a string buffer containing a description
** of the subset of table rows scanned by the strategy in the form of an
** SQL expression. Or, if all rows are scanned, NULL is returned.
** function appends text to pStr that describes the subset of table
** rows scanned by the strategy in the form of an SQL expression.
**
** For example, if the query:
**
@ -2748,49 +2748,37 @@ static void explainAppendTerm(
** string similar to:
**
** "a=? AND b>?"
**
** The returned pointer points to memory obtained from sqlite3DbMalloc().
** It is the responsibility of the caller to free the buffer when it is
** no longer required.
*/
static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){
static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop, Table *pTab){
Index *pIndex = pLoop->u.btree.pIndex;
u16 nEq = pLoop->u.btree.nEq;
u16 nSkip = pLoop->u.btree.nSkip;
int i, j;
Column *aCol = pTab->aCol;
i16 *aiColumn = pIndex->aiColumn;
StrAccum txt;
if( nEq==0 && (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
return 0;
}
sqlite3StrAccumInit(&txt, 0, 0, SQLITE_MAX_LENGTH);
txt.db = db;
sqlite3StrAccumAppend(&txt, " (", 2);
if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return;
sqlite3StrAccumAppend(pStr, " (", 2);
for(i=0; i<nEq; i++){
char *z = aiColumn[i] < 0 ? "rowid" : aCol[aiColumn[i]].zName;
if( i>=nSkip ){
explainAppendTerm(&txt, i, z, "=");
explainAppendTerm(pStr, i, z, "=");
}else{
if( i ) sqlite3StrAccumAppend(&txt, " AND ", 5);
sqlite3StrAccumAppend(&txt, "ANY(", 4);
sqlite3StrAccumAppendAll(&txt, z);
sqlite3StrAccumAppend(&txt, ")", 1);
if( i ) sqlite3StrAccumAppend(pStr, " AND ", 5);
sqlite3XPrintf(pStr, 0, "ANY(%s)", z);
}
}
j = i;
if( pLoop->wsFlags&WHERE_BTM_LIMIT ){
char *z = aiColumn[j] < 0 ? "rowid" : aCol[aiColumn[j]].zName;
explainAppendTerm(&txt, i++, z, ">");
explainAppendTerm(pStr, i++, z, ">");
}
if( pLoop->wsFlags&WHERE_TOP_LIMIT ){
char *z = aiColumn[j] < 0 ? "rowid" : aCol[aiColumn[j]].zName;
explainAppendTerm(&txt, i, z, "<");
explainAppendTerm(pStr, i, z, "<");
}
sqlite3StrAccumAppend(&txt, ")", 1);
return sqlite3StrAccumFinish(&txt);
sqlite3StrAccumAppend(pStr, ")", 1);
}
/*
@ -2814,11 +2802,13 @@ static void explainOneScan(
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
char *zMsg; /* Text to add to EQP output */
int iId = pParse->iSelectId; /* Select id (left-most output column) */
int isSearch; /* True for a SEARCH. False for SCAN. */
WhereLoop *pLoop; /* The controlling WhereLoop object */
u32 flags; /* Flags that describe this loop */
char *zMsg; /* Text to add to EQP output */
StrAccum str; /* EQP output string */
char zBuf[100]; /* Initial space for EQP output string */
pLoop = pLevel->pWLoop;
flags = pLoop->wsFlags;
@ -2828,54 +2818,70 @@ static void explainOneScan(
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
zMsg = sqlite3MPrintf(db, "%s", isSearch?"SEARCH":"SCAN");
sqlite3StrAccumInit(&str, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
str.db = db;
sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN");
if( pItem->pSelect ){
zMsg = sqlite3MAppendf(db, zMsg, "%s SUBQUERY %d", zMsg,pItem->iSelectId);
sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId);
}else{
zMsg = sqlite3MAppendf(db, zMsg, "%s TABLE %s", zMsg, pItem->zName);
sqlite3XPrintf(&str, 0, " TABLE %s", pItem->zName);
}
if( pItem->zAlias ){
zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
sqlite3XPrintf(&str, 0, " AS %s", pItem->zAlias);
}
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0
&& ALWAYS(pLoop->u.btree.pIndex!=0)
){
const char *zFmt;
Index *pIdx = pLoop->u.btree.pIndex;
char *zWhere = explainIndexRange(db, pLoop, pItem->pTab);
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
const char *zFmt = 0;
Index *pIdx;
assert( pLoop->u.btree.pIndex!=0 );
pIdx = pLoop->u.btree.pIndex;
assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){
zFmt = zWhere ? "%s USING PRIMARY KEY%.0s%s" : "%s%.0s%s";
if( isSearch ){
zFmt = "PRIMARY KEY";
}
}else if( flags & WHERE_AUTO_INDEX ){
zFmt = "%s USING AUTOMATIC COVERING INDEX%.0s%s";
zFmt = "AUTOMATIC COVERING INDEX";
}else if( flags & WHERE_IDX_ONLY ){
zFmt = "%s USING COVERING INDEX %s%s";
zFmt = "COVERING INDEX %s";
}else{
zFmt = "%s USING INDEX %s%s";
zFmt = "INDEX %s";
}
if( zFmt ){
sqlite3StrAccumAppend(&str, " USING ", 7);
sqlite3XPrintf(&str, 0, zFmt, pIdx->zName);
explainIndexRange(&str, pLoop, pItem->pTab);
}
zMsg = sqlite3MAppendf(db, zMsg, zFmt, zMsg, pIdx->zName, zWhere);
sqlite3DbFree(db, zWhere);
}else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg);
const char *zRange;
if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid=?)", zMsg);
zRange = "(rowid=?)";
}else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>? AND rowid<?)", zMsg);
zRange = "(rowid>? AND rowid<?)";
}else if( flags&WHERE_BTM_LIMIT ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>?)", zMsg);
}else if( ALWAYS(flags&WHERE_TOP_LIMIT) ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid<?)", zMsg);
zRange = "(rowid>?)";
}else{
assert( flags&WHERE_TOP_LIMIT);
zRange = "(rowid<?)";
}
sqlite3StrAccumAppendAll(&str, " USING INTEGER PRIMARY KEY ");
sqlite3StrAccumAppendAll(&str, zRange);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
sqlite3XPrintf(&str, 0, " VIRTUAL TABLE INDEX %d:%s",
pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
}
#endif
zMsg = sqlite3MAppendf(db, zMsg, "%s", zMsg);
#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
if( pLoop->nOut>=10 ){
sqlite3XPrintf(&str, 0, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut));
}else{
sqlite3StrAccumAppend(&str, " (~1 row)", 9);
}
#endif
zMsg = sqlite3StrAccumFinish(&str);
sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
}
}
@ -3529,8 +3535,9 @@ static Bitmask codeOneLoopStart(
** eliminating duplicates from other WHERE clauses, the action for each
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
*/
wctrlFlags = WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY;
wctrlFlags = WHERE_OMIT_OPEN_CLOSE
| WHERE_FORCE_TABLE
| WHERE_ONETABLE_ONLY;
for(ii=0; ii<pOrWc->nTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
@ -3542,6 +3549,7 @@ static Bitmask codeOneLoopStart(
pOrExpr = pAndExpr;
}
/* Loop through table entries that match term pOrTerm. */
WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
wctrlFlags, iCovCur);
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
@ -3761,21 +3769,26 @@ static Bitmask codeOneLoopStart(
return pLevel->notReady;
}
#if defined(WHERETRACE_ENABLED) && defined(SQLITE_ENABLE_TREE_EXPLAIN)
#ifdef WHERETRACE_ENABLED
/*
** Generate "Explanation" text for a WhereTerm.
** Print the content of a WhereTerm object
*/
static void whereExplainTerm(Vdbe *v, WhereTerm *pTerm){
char zType[4];
memcpy(zType, "...", 4);
if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
sqlite3ExplainPrintf(v, "%s ", zType);
sqlite3ExplainExpr(v, pTerm->pExpr);
static void whereTermPrint(WhereTerm *pTerm, int iTerm){
if( pTerm==0 ){
sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm);
}else{
char zType[4];
memcpy(zType, "...", 4);
if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
sqlite3DebugPrintf("TERM-%-3d %p %s cursor=%-3d prob=%-3d op=0x%03x\n",
iTerm, pTerm, zType, pTerm->leftCursor, pTerm->truthProb,
pTerm->eOperator);
sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
}
}
#endif /* WHERETRACE_ENABLED && SQLITE_ENABLE_TREE_EXPLAIN */
#endif
#ifdef WHERETRACE_ENABLED
/*
@ -3819,27 +3832,12 @@ static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm);
}
sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
#ifdef SQLITE_ENABLE_TREE_EXPLAIN
/* If the 0x100 bit of wheretracing is set, then show all of the constraint
** expressions in the WhereLoop.aLTerm[] array.
*/
if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){ /* WHERETRACE 0x100 */
if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){
int i;
Vdbe *v = pWInfo->pParse->pVdbe;
sqlite3ExplainBegin(v);
for(i=0; i<p->nLTerm; i++){
WhereTerm *pTerm = p->aLTerm[i];
if( pTerm==0 ) continue;
sqlite3ExplainPrintf(v, " (%d) #%-2d ", i+1, (int)(pTerm-pWC->a));
sqlite3ExplainPush(v);
whereExplainTerm(v, pTerm);
sqlite3ExplainPop(v);
sqlite3ExplainNL(v);
whereTermPrint(p->aLTerm[i], i);
}
sqlite3ExplainFinish(v);
sqlite3DebugPrintf("%s", sqlite3VdbeExplanation(v));
}
#endif
}
#endif
@ -4152,7 +4150,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
** than pTemplate, so just ignore pTemplate */
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf("ins-noop: ");
sqlite3DebugPrintf(" skip: ");
whereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
@ -4168,10 +4166,10 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
if( p!=0 ){
sqlite3DebugPrintf("ins-del: ");
sqlite3DebugPrintf("replace: ");
whereLoopPrint(p, pBuilder->pWC);
}
sqlite3DebugPrintf("ins-new: ");
sqlite3DebugPrintf(" add: ");
whereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
@ -4195,7 +4193,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
*ppTail = pToDel->pNextLoop;
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf("ins-del: ");
sqlite3DebugPrintf(" delete: ");
whereLoopPrint(pToDel, pBuilder->pWC);
}
#endif
@ -5019,7 +5017,6 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
struct SrcList_item *pItem;
pWC = pBuilder->pWC;
if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
pWCEnd = pWC->a + pWC->nTerm;
pNew = pBuilder->pNew;
memset(&sSum, 0, sizeof(sSum));
@ -5040,6 +5037,7 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
sSubBuild.pOrderBy = 0;
sSubBuild.pOrSet = &sCur;
WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm));
for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
if( (pOrTerm->eOperator & WO_AND)!=0 ){
sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
@ -5054,6 +5052,15 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
continue;
}
sCur.n = 0;
#ifdef WHERETRACE_ENABLED
WHERETRACE(0x200, ("OR-term %d of %p has %d subterms:\n",
(int)(pOrTerm-pOrWC->a), pTerm, sSubBuild.pWC->nTerm));
if( sqlite3WhereTrace & 0x400 ){
for(i=0; i<sSubBuild.pWC->nTerm; i++){
whereTermPrint(&sSubBuild.pWC->a[i], i);
}
}
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pItem->pTab) ){
rc = whereLoopAddVirtual(&sSubBuild, mExtra);
@ -5062,6 +5069,9 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
{
rc = whereLoopAddBtree(&sSubBuild, mExtra);
}
if( rc==SQLITE_OK ){
rc = whereLoopAddOr(&sSubBuild, mExtra);
}
assert( rc==SQLITE_OK || sCur.n==0 );
if( sCur.n==0 ){
sSum.n = 0;
@ -5106,6 +5116,7 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
pNew->prereq = sSum.a[i].prereq;
rc = whereLoopInsert(pBuilder, pNew);
}
WHERETRACE(0x200, ("End processing OR-clause %p\n", pTerm));
}
}
return rc;
@ -5349,7 +5360,7 @@ static i8 wherePathSatisfiesOrderBy(
isMatch = 1;
break;
}
if( isMatch && (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){
if( isMatch && (wctrlFlags & WHERE_GROUPBY)==0 ){
/* Make sure the sort order is compatible in an ORDER BY clause.
** Sort order is irrelevant for a GROUP BY clause. */
if( revSet ){
@ -5814,12 +5825,15 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
&& pWInfo->nOBSat==pWInfo->pOrderBy->nExpr
){
Bitmask notUsed = 0;
Bitmask revMask = 0;
int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy,
pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], &notUsed
pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], &revMask
);
assert( pWInfo->sorted==0 );
pWInfo->sorted = (nOrder==pWInfo->pOrderBy->nExpr);
if( nOrder==pWInfo->pOrderBy->nExpr ){
pWInfo->sorted = 1;
pWInfo->revMask = revMask;
}
}
}
@ -6172,23 +6186,16 @@ WhereInfo *sqlite3WhereBegin(
/* Construct the WhereLoop objects */
WHERETRACE(0xffff,("*** Optimizer Start ***\n"));
#if defined(WHERETRACE_ENABLED)
/* Display all terms of the WHERE clause */
#if defined(WHERETRACE_ENABLED) && defined(SQLITE_ENABLE_TREE_EXPLAIN)
if( sqlite3WhereTrace & 0x100 ){
int i;
Vdbe *v = pParse->pVdbe;
sqlite3ExplainBegin(v);
for(i=0; i<sWLB.pWC->nTerm; i++){
sqlite3ExplainPrintf(v, "#%-2d ", i);
sqlite3ExplainPush(v);
whereExplainTerm(v, &sWLB.pWC->a[i]);
sqlite3ExplainPop(v);
sqlite3ExplainNL(v);
whereTermPrint(&sWLB.pWC->a[i], i);
}
sqlite3ExplainFinish(v);
sqlite3DebugPrintf("%s", sqlite3VdbeExplanation(v));
}
#endif
if( nTabList!=1 || whereShortCut(&sWLB)==0 ){
rc = whereLoopAddAll(&sWLB);
if( rc ) goto whereBeginError;

117
test/analyzeD.test Normal file
View File

@ -0,0 +1,117 @@
# 2005 July 22
#
# 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
# This file implements tests for the ANALYZE command.
#
# $Id: analyze.test,v 1.9 2008/08/11 18:44:58 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix analyzeD
ifcapable {!stat4} {
finish_test
return
}
# Set up a table with the following properties:
#
# * Contains 1000 rows.
# * Column a contains even integers between 0 and 18, inclusive (so that
# a=? for any such integer matches 100 rows).
# * Column b contains integers between 0 and 9, inclusive.
# * Column c contains integers between 0 and 199, inclusive (so that
# for any such integer, c=? matches 5 rows).
# * Then add 7 rows with a new value for "a" - 3001. The stat4 table will
# not contain any samples with a=3001.
#
do_execsql_test 1.0 {
CREATE TABLE t1(a, b, c);
}
do_test 1.1 {
for {set i 1} {$i < 1000} {incr i} {
set c [expr $i % 200]
execsql { INSERT INTO t1(a, b, c) VALUES( 2*($i/100), $i%10, $c ) }
}
execsql {
INSERT INTO t1 VALUES(3001, 3001, 3001);
INSERT INTO t1 VALUES(3001, 3001, 3002);
INSERT INTO t1 VALUES(3001, 3001, 3003);
INSERT INTO t1 VALUES(3001, 3001, 3004);
INSERT INTO t1 VALUES(3001, 3001, 3005);
INSERT INTO t1 VALUES(3001, 3001, 3006);
INSERT INTO t1 VALUES(3001, 3001, 3007);
CREATE INDEX t1_ab ON t1(a, b);
CREATE INDEX t1_c ON t1(c);
ANALYZE;
}
} {}
# With full ANALYZE data, SQLite sees that c=150 (5 rows) is better than
# a=3001 (7 rows).
#
do_eqp_test 1.2 {
SELECT * FROM t1 WHERE a=3001 AND c=150;
} {
0 0 0 {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
}
do_test 1.3 {
execsql { DELETE FROM sqlite_stat1 }
db close
sqlite3 db test.db
} {}
# Without stat1, because 3001 is larger than all samples in the stat4
# table, SQLite things that a=3001 matches just 1 row. So it (incorrectly)
# chooses it over the c=150 index (5 rows). Even with stat1 data, things
# worked this way before commit [e6f7f97dbc].
#
do_eqp_test 1.4 {
SELECT * FROM t1 WHERE a=3001 AND c=150;
} {
0 0 0 {SEARCH TABLE t1 USING INDEX t1_ab (a=?)}
}
do_test 1.5 {
execsql {
UPDATE t1 SET a=13 WHERE a = 3001;
ANALYZE;
}
} {}
do_eqp_test 1.6 {
SELECT * FROM t1 WHERE a=13 AND c=150;
} {
0 0 0 {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
}
do_test 1.7 {
execsql { DELETE FROM sqlite_stat1 }
db close
sqlite3 db test.db
} {}
# Same test as 1.4, except this time the 7 rows that match the a=? condition
# do not feature larger values than all rows in the stat4 table. So SQLite
# gets this right, even without stat1 data.
do_eqp_test 1.8 {
SELECT * FROM t1 WHERE a=13 AND c=150;
} {
0 0 0 {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
}
finish_test

242
test/analyzeE.test Normal file
View File

@ -0,0 +1,242 @@
# 2014-10-08
#
# 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.
#
#***********************************************************************
# This file implements tests for using STAT4 information
# on a descending index in a range query.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix analyzeE
ifcapable {!stat4} {
finish_test
return
}
# Verify that range queries on an ASCENDING index will use the
# index only if the range covers only a small fraction of the
# entries.
#
do_execsql_test analyzeE-1.0 {
CREATE TABLE t1(a,b);
WITH RECURSIVE
cnt(x) AS (VALUES(1000) UNION ALL SELECT x+1 FROM cnt WHERE x<2000)
INSERT INTO t1(a,b) SELECT x, x FROM cnt;
CREATE INDEX t1a ON t1(a);
ANALYZE;
} {}
do_execsql_test analyzeE-1.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500;
} {/SCAN TABLE t1/}
do_execsql_test analyzeE-1.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750;
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.4 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1 AND 500
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.5 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.6 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<500
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.7 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>2500
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.8 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1900
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.9 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1100
} {/SCAN TABLE t1/}
do_execsql_test analyzeE-1.10 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1100
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.11 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1900
} {/SCAN TABLE t1/}
# Verify that everything works the same on a DESCENDING index.
#
do_execsql_test analyzeE-2.0 {
DROP INDEX t1a;
CREATE INDEX t1a ON t1(a DESC);
ANALYZE;
} {}
do_execsql_test analyzeE-2.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500;
} {/SCAN TABLE t1/}
do_execsql_test analyzeE-2.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750;
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.4 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1 AND 500
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.5 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.6 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<500
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.7 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>2500
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.8 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1900
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.9 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1100
} {/SCAN TABLE t1/}
do_execsql_test analyzeE-2.10 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1100
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.11 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1900
} {/SCAN TABLE t1/}
# Now do a range query on the second term of an ASCENDING index
# where the first term is constrained by equality.
#
do_execsql_test analyzeE-3.0 {
DROP TABLE t1;
CREATE TABLE t1(a,b,c);
WITH RECURSIVE
cnt(x) AS (VALUES(1000) UNION ALL SELECT x+1 FROM cnt WHERE x<2000)
INSERT INTO t1(a,b,c) SELECT x, x, 123 FROM cnt;
CREATE INDEX t1ca ON t1(c,a);
ANALYZE;
} {}
do_execsql_test analyzeE-3.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500 AND c=123;
} {/SCAN TABLE t1/}
do_execsql_test analyzeE-3.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000 AND c=123;
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750 AND c=123;
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.4 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1 AND 500 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.5 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.6 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<500 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.7 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>2500 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.8 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1900 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.9 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1100 AND c=123
} {/SCAN TABLE t1/}
do_execsql_test analyzeE-3.10 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1100 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.11 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1900 AND c=123
} {/SCAN TABLE t1/}
# Repeat the 3.x tests using a DESCENDING index
#
do_execsql_test analyzeE-4.0 {
DROP INDEX t1ca;
CREATE INDEX t1ca ON t1(c ASC,a DESC);
ANALYZE;
} {}
do_execsql_test analyzeE-4.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500 AND c=123;
} {/SCAN TABLE t1/}
do_execsql_test analyzeE-4.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000 AND c=123;
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750 AND c=123;
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.4 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1 AND 500 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.5 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.6 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<500 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.7 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>2500 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.8 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1900 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.9 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1100 AND c=123
} {/SCAN TABLE t1/}
do_execsql_test analyzeE-4.10 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1100 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.11 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1900 AND c=123
} {/SCAN TABLE t1/}
finish_test

View File

@ -75,31 +75,34 @@ do_test 2.2 {
catchsql { SELECT * FROM r WHERE x >= 10 }
} {1 {database disk image is malformed}}
reset_db
do_execsql_test 3.1 {
PRAGMA page_size = 512;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
WITH s(a, b) AS (
SELECT 2, 'abcdefghij'
UNION ALL
SELECT a+2, b FROM s WHERe a < 40
)
INSERT INTO t1 SELECT * FROM s;
} {}
do_test 3.2 {
hexio_write test.db [expr 512+3] 0054
db close
sqlite3 db test.db
execsql { INSERT INTO t1 VALUES(5, 'klmnopqrst') }
execsql { INSERT INTO t1 VALUES(7, 'klmnopqrst') }
} {}
db close
sqlite3 db test.db
do_catchsql_test 3.2 {
INSERT INTO t1 VALUES(9, 'klmnopqrst');
} {1 {database disk image is malformed}}
if {[db one {SELECT sqlite_compileoption_used('ENABLE_OVERSIZE_CELL_CHECK')}]} {
# The following tests only work if OVERSIZE_CELL_CHECK is disabled
} else {
reset_db
do_execsql_test 3.1 {
PRAGMA auto_vacuum=0;
PRAGMA page_size = 512;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
WITH s(a, b) AS (
SELECT 2, 'abcdefghij'
UNION ALL
SELECT a+2, b FROM s WHERe a < 40
)
INSERT INTO t1 SELECT * FROM s;
} {}
do_test 3.2 {
hexio_write test.db [expr 512+3] 0054
db close
sqlite3 db test.db
execsql { INSERT INTO t1 VALUES(5, 'klmnopqrst') }
execsql { INSERT INTO t1 VALUES(7, 'klmnopqrst') }
} {}
db close
sqlite3 db test.db
do_catchsql_test 3.3 {
INSERT INTO t1 VALUES(9, 'klmnopqrst');
} {1 {database disk image is malformed}}
} ;# end-if !defined(ENABLE_OVERSIZE_CELL_CHECK)
finish_test

View File

@ -862,11 +862,11 @@ do_createtable_tests 3.2.3 -query {
3 "INSERT INTO t1 DEFAULT VALUES" {NULL NULL NULL}
}
# EVIDENCE-OF: R-62940-43005 An explicit DEFAULT clause may specify that
# EVIDENCE-OF: R-07343-35026 An explicit DEFAULT clause may specify that
# the default value is NULL, a string constant, a blob constant, a
# signed-number, or any constant expression enclosed in parentheses. An
# explicit default value may also be one of the special case-independent
# keywords CURRENT_TIME, CURRENT_DATE or CURRENT_TIMESTAMP.
# signed-number, or any constant expression enclosed in parentheses. A
# default value may also be one of the special case-independent keywords
# CURRENT_TIME, CURRENT_DATE or CURRENT_TIMESTAMP.
#
do_execsql_test e_createtable-3.3.1 {
CREATE TABLE t4(
@ -884,9 +884,9 @@ do_execsql_test e_createtable-3.3.1 {
);
} {}
# EVIDENCE-OF: R-36381-62919 For the purposes of the DEFAULT clause, an
# expression is considered constant provided that it does not contain
# any sub-queries, column or table references, or string literals
# EVIDENCE-OF: R-18415-27776 For the purposes of the DEFAULT clause, an
# expression is considered constant if it does contains no sub-queries,
# column or table references, bound parameters, or string literals
# enclosed in double-quotes instead of single-quotes.
#
do_createtable_tests 3.4.1 -error {
@ -896,6 +896,7 @@ do_createtable_tests 3.4.1 -error {
2 {CREATE TABLE t5(x DEFAULT ( "abc" ))} {}
3 {CREATE TABLE t5(x DEFAULT ( 1 IN (SELECT 1) ))} {}
4 {CREATE TABLE t5(x DEFAULT ( EXISTS (SELECT 1) ))} {}
5 {CREATE TABLE t5(x DEFAULT ( x!=?1 ))} {}
}
do_createtable_tests 3.4.2 -repair {
catchsql { DROP TABLE t5 }

View File

@ -125,6 +125,9 @@ if {$tcl_platform(platform) == "unix"} {
sqlite3_shutdown
sqlite3_config_uri 1
# EVIDENCE-OF: R-06842-00595 If the URI contains an authority, then it
# must be either an empty string or the string "localhost".
#
# EVIDENCE-OF: R-17482-00398 If the authority is not an empty string or
# "localhost", an error is returned to the caller.
#

View File

@ -58,6 +58,18 @@ do_test eval-2.2 {
SELECT * FROM t2
}
} {}
do_test eval-2.3 {
execsql {
INSERT INTO t2 SELECT x, x+1 FROM t1 WHERE x<5;
SELECT x, test_eval('DELETE FROM t2 WHERE x='||x), y FROM t2
ORDER BY rowid DESC;
}
} {4 {} {} 3 {} {} 2 {} {} 1 {} {}}
do_test eval-2.4 {
execsql {
SELECT * FROM t2
}
} {}
# Modify a row while it is being read.
#

View File

@ -205,6 +205,10 @@ test_expr expr-1.125 {i1=6, i2=NULL} \
test_expr expr-1.126 {i1=8, i2=8} \
{CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} no
do_catchsql_test expr-1.127 {
SELECT 1 IS #1;
} {1 {near "#1": syntax error}}
ifcapable floatingpoint {if {[working_64bit_int]} {
test_expr expr-1.200\
{i1=9223372036854775806, i2=1} {i1+i2} 9223372036854775807

View File

@ -24,12 +24,16 @@ ifcapable !fts3||!icu {
set sqlite_fts3_enable_parentheses 1
proc test_icu_fts3expr {expr} {
db one {SELECT fts3_exprtest('icu', $expr, 'a', 'b', 'c')}
proc test_fts3expr {tokenizer expr} {
db one {SELECT fts3_exprtest($tokenizer, $expr, 'a', 'b', 'c')}
}
proc do_icu_expr_test {tn expr res} {
uplevel [list do_test $tn [list test_icu_fts3expr $expr] $res]
uplevel [list do_test $tn [list test_fts3expr icu $expr] [list {*}$res]]
}
proc do_simple_expr_test {tn expr res} {
uplevel [list do_test $tn [list test_fts3expr simple $expr] [list {*}$res]]
}
#-------------------------------------------------------------------------
@ -53,5 +57,26 @@ do_icu_expr_test 2.1 {
f (e NEAR/2 a)
} {AND {AND {AND {PHRASE 3 0 f} {PHRASE 3 0 (}} {NEAR/2 {PHRASE 3 0 e} {PHRASE 3 0 a}}} {PHRASE 3 0 )}}
#-------------------------------------------------------------------------
#
do_simple_expr_test 3.1 {*lOl* *h4h*} {
AND {PHRASE 3 0 lol+} {PHRASE 3 0 h4h+}
}
do_icu_expr_test 3.2 {*lOl* *h4h*} {
AND {AND {AND {PHRASE 3 0 *} {PHRASE 3 0 lol+}} {PHRASE 3 0 *}} {PHRASE 3 0 h4h+}
}
do_simple_expr_test 3.3 { * } { }
do_simple_expr_test 3.4 { *a } { PHRASE 3 0 a }
do_simple_expr_test 3.5 { a*b } { AND {PHRASE 3 0 a+} {PHRASE 3 0 b} }
do_simple_expr_test 3.6 { *a*b } { AND {PHRASE 3 0 a+} {PHRASE 3 0 b} }
do_simple_expr_test 3.7 { *"abc" } { PHRASE 3 0 abc }
do_simple_expr_test 3.8 { "abc"* } { PHRASE 3 0 abc }
do_simple_expr_test 3.8 { "ab*c" } { PHRASE 3 0 ab+ c }
do_icu_expr_test 3.9 { "ab*c" } { PHRASE 3 0 ab+ * c }
do_icu_expr_test 3.10 { ab*c } { AND {PHRASE 3 0 ab+} {PHRASE 3 0 c}}
finish_test

View File

@ -433,4 +433,21 @@ do_execsql_test 9.1 {
SELECT snippet(ft2, '[', ']', '', -1, 1) FROM ft2 WHERE ft2 MATCH 'c';
} {{[c]} {[c]}}
#---------------------------------------------------------------------------
# Test for a memory leak
#
do_execsql_test 10.1 {
DROP TABLE t10;
CREATE VIRTUAL TABLE t10 USING fts4(idx, value);
INSERT INTO t10 values (1, 'one'),(2, 'two'),(3, 'three');
SELECT docId, t10.*
FROM t10
JOIN (SELECT 1 AS idx UNION SELECT 2 UNION SELECT 3) AS x
WHERE t10 MATCH x.idx
AND matchinfo(t10) not null
GROUP BY docId
ORDER BY 1;
} {1 1 one 2 2 two 3 3 three}
finish_test

View File

@ -16,6 +16,9 @@ source $testdir/tester.tcl
set ::testprefix index5
do_test 1.1 {
if {[permutation]=="memsubsys1"} {
execsql { PRAGMA auto_vacuum = 0; }
}
execsql {
PRAGMA page_size = 1024;
CREATE TABLE t1(x);
@ -38,7 +41,7 @@ tvfs filter xWrite
tvfs script write_cb
proc write_cb {xCall file handle iOfst args} {
if {[file tail $file]=="test.db"} {
lappend ::write_list [expr $iOfst/1024]
lappend ::write_list [expr $iOfst/1024 + 1]
}
}

View File

@ -119,8 +119,6 @@ do_execsql_test 7.0 {
PRAGMA cache_size = 5;
}
do_faultsim_test 7 -faults oom-trans* -prep {
if {$iFail < 500} { set iFail 2000 }
if {$iFail > 1215} { set iFail 2000 }
} -body {
execsql {
WITH r(x,y) AS (

49
test/ovfl.test Normal file
View File

@ -0,0 +1,49 @@
# 2014 October 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the SQLITE_DIRECT_OVERFLOW_READ logic.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix ovfl
# Populate table t2:
#
# CREATE TABLE t1(c1 TEXT, c2 TEXT);
#
# with 2000 rows. In each row, c2 spans multiple overflow pages. The text
# value of c1 ranges in size from 1 to 2000 bytes. The idea is to create
# at least one row where the first byte of c2 is also the first byte of
# an overflow page. This was at one point exposing an obscure bug in the
# SQLITE_DIRECT_OVERFLOW_READ logic.
#
do_test 1.1 {
set c2 [string repeat abcdefghij 200]
execsql {
PRAGMA cache_size = 10;
CREATE TABLE t1(c1 TEXT, c2 TEXT);
BEGIN;
}
for {set i 1} {$i <= 2000} {incr i} {
set c1 [string repeat . $i]
execsql { INSERT INTO t1 VALUES($c1, $c2) }
}
execsql COMMIT
} {}
do_execsql_test 1.2 {
SELECT sum(length(c2)) FROM t1;
} [expr 2000 * 2000]
finish_test

View File

@ -13,6 +13,7 @@ optional) are:
-makefile PATH-TO-MAKEFILE (default "releasetest.mk")
-platform PLATFORM (see below)
-quick BOOLEAN (default "0")
-config CONFIGNAME (Run only CONFIGNAME)
The default value for -makefile is "./releasetest.mk".
@ -292,6 +293,7 @@ proc run_test_suite {name testtarget config} {
proc process_options {argv} {
set ::MAKEFILE releasetest.mk ;# Default value
set ::QUICK 0 ;# Default value
set config {}
set platform $::tcl_platform(os)-$::tcl_platform(machine)
for {set i 0} {$i < [llength $argv]} {incr i} {
@ -310,6 +312,11 @@ proc process_options {argv} {
incr i
set ::QUICK [lindex $argv $i]
}
-config {
incr i
set config [lindex $argv $i]
}
default {
puts stderr ""
@ -333,7 +340,12 @@ proc process_options {argv} {
exit
}
set ::CONFIGLIST $::Platforms($platform)
if {$config!=""} {
if {[llength $config]==1} {lappend config fulltest}
set ::CONFIGLIST $config
} else {
set ::CONFIGLIST $::Platforms($platform)
}
puts "Running the following configurations for $platform:"
puts " [string trim $::CONFIGLIST]"
}

View File

@ -934,6 +934,7 @@ void testset_cte(void){
}
#ifdef SQLITE_ENABLE_RTREE
/* Generate two numbers between 1 and mx. The first number is less than
** the second. Usually the numbers are near each other but can sometimes
** be far apart.
@ -954,7 +955,9 @@ static void twoCoords(
*pX0 = x0;
*pX1 = x1;
}
#endif
#ifdef SQLITE_ENABLE_RTREE
/* The following routine is an R-Tree geometry callback. It returns
** true if the object overlaps a slice on the Y coordinate between the
** two values given as arguments. In other words
@ -974,7 +977,9 @@ static int xsliceGeometryCallback(
*pRes = aCoord[3]>=p->aParam[0] && aCoord[2]<=p->aParam[1];
return SQLITE_OK;
}
#endif /* SQLITE_ENABLE_RTREE */
#ifdef SQLITE_ENABLE_RTREE
/*
** A testset for the R-Tree virtual table
*/
@ -1110,6 +1115,7 @@ void testset_rtree(int p1, int p2){
}
speedtest1_end_test();
}
#endif /* SQLITE_ENABLE_RTREE */
/*
** A testset used for debugging speedtest1 itself.
@ -1329,7 +1335,12 @@ int main(int argc, char **argv){
}else if( strcmp(zTSet,"cte")==0 ){
testset_cte();
}else if( strcmp(zTSet,"rtree")==0 ){
#ifdef SQLITE_ENABLE_RTREE
testset_rtree(6, 147);
#else
fatal_error("compile with -DSQLITE_ENABLE_RTREE to enable "
"the R-Tree tests\n");
#endif
}else{
fatal_error("unknown testset: \"%s\"\nChoices: main debug1 cte rtree\n",
zTSet);

View File

@ -51,6 +51,13 @@ do_test sqllimits1-1.9 {
do_test sqllimits1-1.10 {
sqlite3_limit db SQLITE_LIMIT_VARIABLE_NUMBER -1
} $SQLITE_MAX_VARIABLE_NUMBER
do_test sqllimits1-1.11 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH -1
} $SQLITE_MAX_TRIGGER_DEPTH
do_test sqllimits1-1.12 {
sqlite3_limit db SQLITE_LIMIT_WORKER_THREADS 99999
sqlite3_limit db SQLITE_LIMIT_WORKER_THREADS -1
} $SQLITE_MAX_WORKER_THREADS
# Limit parameters out of range.
#

65
test/tkt-ba7cbfaedc.test Normal file
View File

@ -0,0 +1,65 @@
# 2014-10-11
#
# 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.
#
#*************************************************************************
#
# Test that ticket [ba7cbfaedc] has been fixed.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix tkt-ba7cbfaedc
do_execsql_test 1 {
CREATE TABLE t1 (x, y);
INSERT INTO t1 VALUES (3, 'a');
INSERT INTO t1 VALUES (1, 'a');
INSERT INTO t1 VALUES (2, 'b');
INSERT INTO t1 VALUES (2, 'a');
INSERT INTO t1 VALUES (3, 'b');
INSERT INTO t1 VALUES (1, 'b');
}
do_execsql_test 1.1 {
CREATE INDEX i1 ON t1(x, y);
}
foreach {n idx} {
1 { CREATE INDEX i1 ON t1(x, y) }
2 { CREATE INDEX i1 ON t1(x DESC, y) }
3 { CREATE INDEX i1 ON t1(x, y DESC) }
4 { CREATE INDEX i1 ON t1(x DESC, y DESC) }
} {
catchsql { DROP INDEX i1 }
execsql $idx
foreach {tn q res} {
1 "GROUP BY x, y ORDER BY x, y" {1 a 1 b 2 a 2 b 3 a 3 b}
2 "GROUP BY x, y ORDER BY x DESC, y" {3 a 3 b 2 a 2 b 1 a 1 b}
3 "GROUP BY x, y ORDER BY x, y DESC" {1 b 1 a 2 b 2 a 3 b 3 a}
4 "GROUP BY x, y ORDER BY x DESC, y DESC" {3 b 3 a 2 b 2 a 1 b 1 a}
} {
do_execsql_test 1.$n.$tn "SELECT * FROM t1 $q" $res
}
}
do_execsql_test 2.0 {
drop table if exists t1;
create table t1(id int);
insert into t1(id) values(1),(2),(3),(4),(5);
create index t1_idx_id on t1(id asc);
select * from t1 group by id order by id;
select * from t1 group by id order by id asc;
select * from t1 group by id order by id desc;
} {
1 2 3 4 5 1 2 3 4 5 5 4 3 2 1
}
finish_test