Merge the latest trunk enhancements into the begin-concurrent branch.

FossilOrigin-Name: eedf6bed2abdaa8a245a4871f9455e3660a7dfeb3bd5f2631d3305cb41591aeb
This commit is contained in:
drh
2024-04-15 14:36:02 +00:00
24 changed files with 427 additions and 107 deletions
+1 -1
View File
@@ -446,7 +446,7 @@ static void fts3SnippetDetails(
}
mCover |= mPhrase;
for(j=0; j<pPhrase->nToken; j++){
for(j=0; j<pPhrase->nToken && j<pIter->nSnippet; j++){
mHighlight |= (mPos>>j);
}
+1 -1
View File
@@ -499,7 +499,7 @@ static void icuLoadCollation(
{ "QUARTERNARY", UCOL_QUATERNARY },
{ "IDENTICAL", UCOL_IDENTICAL },
};
int i;
unsigned int i;
for(i=0; i<sizeof(aStrength)/sizeof(aStrength[0]); i++){
if( sqlite3_stricmp(zOption,aStrength[i].zName)==0 ){
ucol_setStrength(pUCollator, aStrength[i].val);
+19 -5
View File
@@ -494,6 +494,15 @@ static void dbdataValue(
}
}
/* This macro is a copy of the MX_CELL() macro in the SQLite core. Given
** a page-size, it returns the maximum number of cells that may be present
** on the page. */
#define DBDATA_MX_CELL(pgsz) ((pgsz-8)/6)
/* Maximum number of fields that may appear in a single record. This is
** the "hard-limit", according to comments in sqliteLimit.h. */
#define DBDATA_MX_FIELD 32676
/*
** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
*/
@@ -522,6 +531,9 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
assert( iOff+3+2<=pCsr->nPage );
pCsr->iCell = pTab->bPtr ? -2 : 0;
pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
if( pCsr->nCell>DBDATA_MX_CELL(pCsr->nPage) ){
pCsr->nCell = DBDATA_MX_CELL(pCsr->nPage);
}
}
if( pTab->bPtr ){
@@ -566,19 +578,19 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
if( pCsr->iCell>=pCsr->nCell ){
bNextPage = 1;
}else{
int iCellPtr = iOff + 8 + nPointer + pCsr->iCell*2;
iOff += 8 + nPointer + pCsr->iCell*2;
if( iOff>pCsr->nPage ){
if( iCellPtr>pCsr->nPage ){
bNextPage = 1;
}else{
iOff = get_uint16(&pCsr->aPage[iOff]);
iOff = get_uint16(&pCsr->aPage[iCellPtr]);
}
/* For an interior node cell, skip past the child-page number */
iOff += nPointer;
/* Load the "byte of payload including overflow" field */
if( bNextPage || iOff>pCsr->nPage ){
if( bNextPage || iOff>pCsr->nPage || iOff<=iCellPtr ){
bNextPage = 1;
}else{
iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
@@ -661,7 +673,9 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
pCsr->iField++;
if( pCsr->iField>0 ){
sqlite3_int64 iType;
if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
if( pCsr->pHdrPtr>=&pCsr->pRec[pCsr->nRec]
|| pCsr->iField>=DBDATA_MX_FIELD
){
bNextPage = 1;
}else{
int szField = 0;
+28
View File
@@ -524,5 +524,33 @@ do_test 7.1 {
list [catch { $R finish } msg] $msg
} {1 {file is not a database}}
reset_db
breakpoint
do_test 8.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
| size 8192 pagesize 4096 filename db.sqlite
| page 1 offset 0
| 0: ac ae b3 76 74 65 20 66 6f 72 6d 61 74 20 33 00 ...vte format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 01 00 00 00 02 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
| 96: 00 2e 76 8a 0d ff ff ff 1e 0f cb 00 0f cb 00 00 ..v.............
| 4032: 00 00 00 00 00 00 00 00 00 00 00 33 01 06 17 19 ...........3....
| 4048: 19 01 43 74 61 62 6c 65 54 61 62 6c 65 30 54 61 ..CtableTable0Ta
| 4064: 62 6c 65 30 02 43 52 45 41 54 45 20 54 41 42 4c ble0.CREATE TABL
| 4080: 45 20 54 61 62 6c 65 30 20 28 43 6f 6c 30 20 29 E Table0 (Col0 )
| page 2 offset 4096
| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
| end db.sqlite
}]} {}
do_test 8.1 {
set R [sqlite3_recover_init db main test.db2]
catch { $R run }
list [catch { $R finish } msg] $msg
} {0 {}}
finish_test
+1 -1
View File
@@ -1189,7 +1189,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
if( bTable && !bVirtual ){
if( SQLITE_ROW==sqlite3_step(pTblname) ){
const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0);
recoverAddTable(p, zTbl, iRoot);
if( zTbl ) recoverAddTable(p, zTbl, iRoot);
}
recoverReset(p, pTblname);
}
+26 -26
View File
@@ -1,5 +1,5 @@
C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\sbegin-concurrent\sbranch.
D 2024-04-05T14:46:00.940
D 2024-04-15T14:36:02.295
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -75,7 +75,7 @@ F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
F ext/fts3/fts3_porter.c e19807ce0ae31c1c6e9898e89ecc93183d7ec224ea101af039722a4f49e5f2b8
F ext/fts3/fts3_snippet.c 4d6523e3eddeb7b46e7a82b3476a0a86a0c04821e0e2b8dd40f45ee28057cb13
F ext/fts3/fts3_snippet.c 610328fe128c047c6b0eba77768982ccf3933daae095d497949a75c9dfd47409
F ext/fts3/fts3_term.c 845f0e2456b1be42f7f1bec1da1dfc05bc347531eff90775ffc6698902c281de
F ext/fts3/fts3_test.c d8d7b2734f894e8a489987447658e374cdd3a3bc8575c401decf1911cb7c6454
F ext/fts3/fts3_tokenize_vtab.c 7fd9ef364f257b97218b9c331f2378e307375c592f70fd541f714e747d944962
@@ -249,7 +249,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl 3eba8e9bee4221ed165f3304b51b2a74a705f4ec5df3d044573a2be539534af8
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
F ext/icu/icu.c 5c858611fd11d65caf8a04acd836af9193880a724ba75cee63f9da75ce4a469d
F ext/icu/icu.c 3add8197e0a86c1761771a39500ebae749438bcf1836160b407a56b4eaa8721c
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
F ext/intck/intck1.test f3a3cba14b6aeff145ffa5515546dd22f7510dad91512e519f43b92b56514012
F ext/intck/intck2.test d2457c7e5e5b688046d15ebe08a1e1427cc5e7a6dc8d6af215f42e8bcaf67304
@@ -479,13 +479,13 @@ F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69
F ext/rbu/sqlite3rbu.c 4a3376c0fb9a844a799ac529fb81260523f6b13c9f629bc270c632dbae5fc1f8
F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304
F ext/rbu/test_rbu.c ee6ede75147bc081fe9bc3931e6b206277418d14d3fbceea6fdc6216d9b47055
F ext/recover/dbdata.c b7746c2ec801b453840831311be4b31f8c8f9dd97791060a69bbf12392c78949
F ext/recover/dbdata.c d2e00d3cac74319c9c6def2e56ab2146b4f4ba5d820ab275e8da24e9766c247e
F ext/recover/recover1.test c484d01502239f11b61f23c1cee9f5dd19fa17617f8974e42e74d64639c524cf
F ext/recover/recover_common.tcl a61306c1eb45c0c3fc45652c35b2d4ec19729e340bdf65a272ce4c229cefd85a
F ext/recover/recoverbuild.test c74170e0f7b02456af41838afeb5353fdb985a48cc2331d661bbabbca7c6b8e3
F ext/recover/recoverclobber.test 3ba6c0c373c5c63d17e82eced64c05c57ccaf26c1abe1ca7141334022a79f32e
F ext/recover/recovercorrupt.test 64c081ad1200ae77b447da99eb724785d6bf71715f394543dc7689642e92bf49
F ext/recover/recovercorrupt2.test b9b974f006340a1300b5a7e687bd6097c5238498181c6f92d87406a77ece430b
F ext/recover/recovercorrupt2.test 1418f1710debc24ff38276cedfcea234beb37a34205708e7e3e6d76cc4a979db
F ext/recover/recoverfault.test 9d9f88eeb222615a25e7514f234c950d46bee20d24cd8db49d8fff8d650dcfe1
F ext/recover/recoverfault2.test 730e7371bcda769554d15460cb23126abba1be8eca9539ccabf63623e7bb7e09
F ext/recover/recoverold.test 68db3d6f85dd2b98e785b6c4da4f5eea4bbe52ccf6674d9a94c7506dc92596aa
@@ -493,7 +493,7 @@ F ext/recover/recoverpgsz.test 3658ab8e68475b1bb87d6af88baa04551c84b73280a566a1b
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
F ext/recover/recoverslowidx.test 5205a9742dd9490ee99950dabb622307355ef1662dea6a3a21030057bfd81411
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
F ext/recover/sqlite3recover.c e6eb20c469bcdb96f297f2241860bccabf9f036bfa7f3d47bcc6ca1191b108dc
F ext/recover/sqlite3recover.c 65ef0f56301a16c0536c9839fb7e23540c9c4f75da0afe3b7b4d163c8f624404
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
F ext/recover/test_recover.c fd871a40f2238022bedcbdf3cb493b91225edaa94d6ae8892af97a10e7ccc4ba
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -694,7 +694,7 @@ F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c 501daeef838fa82a9fb53540d72f29e3d9172c8867f1e19f94f681e2e20b966e
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
F src/btree.c ea6f38398e28cc4ae70a0d55e94d14e61ddaa05705e40796c542aaf6e8ae0b6f
F src/btree.c e841f070323b6c5fbc480b02cc3f5f2e9e27d3bf84bdf9bd16cf9550673ec683
F src/btree.h bdeeb35614caa33526b603138f04c8d07a3f90a1300b5ade76848b755edf2027
F src/btreeInt.h 8efd30e75e35a3c6a1c4dad7410d4ddfcd560f5f46401b208fa79eceef34525a
F src/build.c c02fca1b600267120d1492f15a8301d48c59d37094c363eb5c12cca08d9133b8
@@ -705,7 +705,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
F src/expr.c cd46ce2ebe46a30e63087dbe8aff7d6e34ba8acc8c658e8e18fcaa35f2711391
F src/expr.c 36071487e377356f1dd62e1e35870ed36a7212cb34ab1578b75d4a27ecdbfcb8
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
F src/func.c a37134215de0da2744d99df69f4742c1e858a5734161b22d5a309b77cced3c6e
@@ -714,7 +714,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c bc4d172b52a6167cd28797397a464c2cca9607dc047dfa0b5cf61687962e6964
F src/insert.c 4bd7c7e54a1062dcd0214b7a6296f7194eb10fb14d3ddca1ed20b01c2a86a18c
F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
@@ -742,7 +742,7 @@ F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d87210
F src/os_unix.c a31c14ba25e87757809853f58d1573ff8cb422e3543093582e523809d96738e0
F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c f7db1a855ce8fea25365fa47f0917cee693259d8c8eb2c8b06cf9bae15d7a1b5
F src/pager.c f620722c6f5fbd0c36c9a5cec9a2a3463fb1841490bb2fd50ef756c09dd4d89e
F src/pager.h e2df6b92e0402bc8d516016f361da82758b7d7769ef1a18e2abeadece18103e0
F src/parse.y 08247e876d6508e7bcf624d48f4993f4051899e1e73400fe7da9de34af755a90
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
@@ -753,14 +753,14 @@ F src/pragma.h 6ebbdee90ed56a892d2c728e27fd9c1ce48c8a28841888d0c6c147946b38cb25
F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c
F src/printf.c 87b67bba3662a0523f39ae6b084a3907109702f717c654d6cecb838af5cd57f1
F src/random.c a3e70f8515721ff24d2c0e6afd83923e8faab5ab79ececea4c1bf9fe4049fbb2
F src/resolve.c eb1860b134fb044fd819c4347105c148d5aac7c6498032be2829e5cc95619b28
F src/resolve.c 6310bdfed32184cd3a5d6ba203dfee1ea323051cb38a6c2e80a5b79c069f4e87
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 41e2d88aa372dd0dae4f8044cf128c2845b130d224da671e8fc6e33d94aaf161
F src/select.c c7d2945000205580e6da1128b16fbd72af4aebd8f1c75f6d860b6a31eee66011
F src/shell.c.in 0354ca51eee5fbf6af394a7ef9f5ef6823ef45b743db65431f6777e4d5be2199
F src/sqlite.h.in 8fa422820b1226e7c67ff5ba1f81868c0a66e463b48a49933b8d069c2b82f103
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
F src/sqliteInt.h 9198f2dcd1c145e657a8c01691942f20542a0b85cd4f0386b86ce28d37a83d84
F src/sqliteInt.h 6a40d25c01675425584f8c3982b3312daa187c93a6224f9a86006bdc06ed1908
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -840,9 +840,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 7a63ccb09c364d941bee07c9e6f0d7f081679d6d21331e0b7fef2e7493a3e16e
F src/wal.h e9aeb67102d9b9a0b089b80bd6136a16dd6360ac3daa731f2b71c6d4f8341717
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
F src/where.c 9982128f010a699560fb5be37633801c7641ac3540f49db43cec878025929a0e
F src/where.c 09253e913dc1a93aa6e0e1a5d25a392b8fa39096cc30d230dd302264b3be0661
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
F src/wherecode.c e033875570f5d65b99fdb5189e597d91c8bc34f4196089fd50e6086d174035e7
F src/whereexpr.c 7b64295f1d82ad0928df435925dd7bbd5997b44a026153113eace0d9e71ff435
F src/window.c 5d95122dd330bfaebd732358c8ef067c5a9394a53ac249470d611d0ce2c52be2
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -1216,7 +1216,7 @@ F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
F test/fts3snippet.test 0887196d67cffbe365edde535b95ecc642a532ce8551ccd9a73aab5999c3ffae
F test/fts3snippet2.test e79afeb1f673713f96d7fc5655726081975399d11e659d15553207be43301dc4
F test/fts3snippet2.test 03f6738ab3897bea2ba6be424a0613872e167acbf37a66200d655d737b470f65
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
@@ -1262,7 +1262,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
F test/fuzzcheck.c e6a40f53ac5624aa5b7c4f31c385f09ba088d524cecc4512fd3057caeed8f530
F test/fuzzcheck.c dc159967609d00b0cfe619e735cbbf8482570aca85711397034b0662b6c18fc7
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1274,7 +1274,7 @@ F test/fuzzdata8.db 4a53b6d077c6a5c23b609d8d3ac66996fa55ba3f8d02f9b6efdd0214a767
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
F test/fuzzinvariants.c 4355043e98cd8555c62462fcbba91c17c6492b0b017bbbe68656d5f2208f6444
F test/fuzzinvariants.c 0729b9d8ed77ad0f8c5c7601168a707d5803087d2da030ede9057c51c809cc6c
F test/gcfault.test 4ea410ac161e685f17b19e1f606f58514a2850e806c65b846d05f60d436c5b0d
F test/gencol1.test e169bdfa11c7ed5e9f322a98a7db3afe9e66235750b68c923efee8e1876b46ec
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
@@ -1526,7 +1526,7 @@ F test/printf.test 685fec5a0c5af2490ab0632775a301554361d674211d690f5bee0a97b0533
F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/pushdown.test 1495a09837a1cedfc0adf07ba42dc6b83be05a2c15de331b67c39a0e22078238
F test/pushdown.test 3330746a897ea271b1021bc1e7e57c6f8d49bcb8ca7d58a823d01aa64a303cc7
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
F test/quickcheck.test a4b7e878cd97e46108291c409b0bf8214f29e18fddd68a42bc5c1375ad1fb80a
@@ -1545,7 +1545,7 @@ F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed13
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/returning1.test 3ead782eddf51f573cdd43bcbb10d1b485ac095a19a76d16c43fd159ea9b7466
F test/returning1.test b27646c5e25431dd47cf72f525d1b2d5ad4ae14e21d9cf3d65769f05e48f64f3
F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
@@ -1706,7 +1706,7 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl fe617b88c7eb08bdf983d2aaa31c20fbf439eee7b8e0d61ca636fcd0c305bbbf
F test/testrunner.tcl b48a8fc17e3b200244f53d60348afa7fe9482400d164e95709890743af9536d0
F test/testrunner.tcl 1386667c04207d0a540ce1a9bc5ee0b734f7a3ba856c14a03943fb4f32de55bb
F test/testrunner_data.tcl 3d36660cfd55ea5e20e661e8f94c0520feebcb437848f9b98b33c483cc479c0c
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
@@ -1923,7 +1923,7 @@ F test/upfrom2.test 66f3ebf721b3cebd922faee5c386bf244f816d416b57c000753ff51af623
F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0
F test/upfrom4.test 78f742a6577c91a7a55c64edb8811004e7c6aa99b8d57b2320f70a918c357807
F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6
F test/upsert1.test a512e2f884d3a36159fce2e45108c236f78ae38e35bda55f4050db580ceb25d3
F test/upsert1.test beba4316fbd4b7b9d76784313f6129a548cfe7abea04d46db33e2efce1ab0ac2
F test/upsert2.test 720e94d09f7362a282bc69b3c6b83d51daeaaf0440eb4920a08b86518b8c7496
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
@@ -1933,7 +1933,7 @@ F test/uri.test c1abaaaa28e9422d61e5f3f9cbc8ef993ec49fe802f581520731708561d49384
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
F test/utf16align.test 9fde0bb5d3a821594aa68c6829ab9c5453a084384137ebb9f6153e2d678039da
F test/vacuum-into.test 35dc6f79b563f91c61822f61797363e97fed1bf28f1f722688b98d43f1980d76
F test/vacuum-into.test 77845cee98770c416dae9b0da6bb3229753861f2da65c11b4f9715d081712d8a
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520
F test/vacuum3.test d9d9a04ee58c485b94694fd4f68cffaba49c32234fdefe1ac1a622c5e17d4ce3
@@ -2201,8 +2201,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 9e6b64decb42dfebd3b882fd93f3bbfec11eca83b754514cc72c90616ca6f9dd 4484ec6d26b31305e31de89bdbae26344d8083a7e7de20861430d31737d9979c
R 15624cf878e0a524616232dc95af170f
P 4ff83342415db6c1a55f877481df77dbc671673ff46bd0afa1826481bb67380d b40580be719a129ecd1aa3c69d1086c967d063920fdd48617c864e73c059abc1
R 30f8f8d6f74fe58524a5cb4796e1b64c
U drh
Z 0e6901fbd5cc5b4092f74129cd600369
Z 7549b0a77b031bb2c3549bb86ed115b2
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
4ff83342415db6c1a55f877481df77dbc671673ff46bd0afa1826481bb67380d
eedf6bed2abdaa8a245a4871f9455e3660a7dfeb3bd5f2631d3305cb41591aeb
+25 -14
View File
@@ -5603,6 +5603,10 @@ static int accessPayload(
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
pCur->curFlags |= BTCF_ValidOvfl;
}else{
/* Sanity check the validity of the overflow page cache */
assert( pCur->aOverflow[0]==nextPage || pCur->aOverflow[0]==0 );
assert( pCur->aOverflow[0]!=0 || pCur->aOverflow[offset/ovflSize]==0 );
/* If the overflow page-list cache has been allocated and the
** entry for the first required overflow page is valid, skip
** directly to it.
@@ -6092,6 +6096,23 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
return rc;
}
#ifdef SQLITE_DEBUG
/* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that
** this flags are true for a consistent database.
**
** This routine is is called from within assert() statements only.
** It is an internal verification routine and does not appear in production
** builds.
*/
static int cursorIsAtLastEntry(BtCursor *pCur){
int ii;
for(ii=0; ii<pCur->iPage; ii++){
if( pCur->aiIdx[ii]!=pCur->apPage[ii]->nCell ) return 0;
}
return pCur->ix==pCur->pPage->nCell-1 && pCur->pPage->leaf!=0;
}
#endif
/* Move the cursor to the last entry in the table. Return SQLITE_OK
** on success. Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.
@@ -6120,18 +6141,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
/* If the cursor already points to the last entry, this is a no-op. */
if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
#ifdef SQLITE_DEBUG
/* This block serves to assert() that the cursor really does point
** to the last entry in the b-tree. */
int ii;
for(ii=0; ii<pCur->iPage; ii++){
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
}
assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
testcase( pCur->ix!=pCur->pPage->nCell-1 );
/* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
assert( pCur->pPage->leaf );
#endif
assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
*pRes = 0;
return SQLITE_OK;
}
@@ -6184,6 +6194,7 @@ int sqlite3BtreeTableMoveto(
}
if( pCur->info.nKey<intKey ){
if( (pCur->curFlags & BTCF_AtLast)!=0 ){
assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
*pRes = -1;
return SQLITE_OK;
}
@@ -10001,7 +10012,7 @@ int sqlite3BtreeInsert(
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
idx = ++pCur->ix;
pCur->curFlags &= ~BTCF_ValidNKey;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
}else{
assert( pPage->leaf );
}
@@ -10031,7 +10042,7 @@ int sqlite3BtreeInsert(
*/
if( pPage->nOverflow ){
assert( rc==SQLITE_OK );
pCur->curFlags &= ~(BTCF_ValidNKey);
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
rc = balance(pCur);
/* Must make sure nOverflow is reset to zero even if the balance()
+50 -12
View File
@@ -2500,7 +2500,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
return WRC_Continue;
}
}
static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){
static int exprIsConst(Parse *pParse, Expr *p, int initFlag){
Walker w;
w.eCode = initFlag;
w.pParse = pParse;
@@ -2509,7 +2509,6 @@ static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){
#ifdef SQLITE_DEBUG
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
#endif
w.u.iCur = iCur;
sqlite3WalkExpr(&w, p);
return w.eCode;
}
@@ -2529,7 +2528,7 @@ static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){
** function and on its parameters.
*/
int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
return exprIsConst(pParse, p, 1, 0);
return exprIsConst(pParse, p, 1);
}
/*
@@ -2546,7 +2545,23 @@ int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
*/
static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
return exprIsConst(pParse, p, 2, 0);
return exprIsConst(pParse, p, 2);
}
/*
** This routine examines sub-SELECT statements as an expression is being
** walked as part of sqlite3ExprIsTableConstant(). Sub-SELECTs are considered
** constant as long as they are uncorrelated - meaning that they do not
** contain any terms from outer contexts.
*/
static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){
assert( pSelect!=0 );
assert( pWalker->eCode==3 || pWalker->eCode==0 );
if( (pSelect->selFlags & SF_Correlated)!=0 ){
pWalker->eCode = 0;
return WRC_Abort;
}
return WRC_Prune;
}
/*
@@ -2554,9 +2569,26 @@ static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
** for any single row of the table with cursor iCur. In other words, the
** expression must not refer to any non-deterministic function nor any
** table other than iCur.
**
** Consider uncorrelated subqueries to be constants if the bAllowSubq
** parameter is true.
*/
int sqlite3ExprIsTableConstant(Expr *p, int iCur){
return exprIsConst(0, p, 3, iCur);
static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){
Walker w;
w.eCode = 3;
w.pParse = 0;
w.xExprCallback = exprNodeIsConstant;
if( bAllowSubq ){
w.xSelectCallback = exprSelectWalkTableConstant;
}else{
w.xSelectCallback = sqlite3SelectWalkFail;
#ifdef SQLITE_DEBUG
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
#endif
}
w.u.iCur = iCur;
sqlite3WalkExpr(&w, p);
return w.eCode;
}
/*
@@ -2574,7 +2606,10 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
**
** (1) pExpr cannot refer to any table other than pSrc->iCursor.
**
** (2) pExpr cannot use subqueries or non-deterministic functions.
** (2a) pExpr cannot use subqueries unless the bAllowSubq parameter is
** true and the subquery is non-correlated
**
** (2b) pExpr cannot use non-deterministic functions.
**
** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
** (Is there some way to relax this constraint?)
@@ -2603,7 +2638,8 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
int sqlite3ExprIsSingleTableConstraint(
Expr *pExpr, /* The constraint */
const SrcList *pSrcList, /* Complete FROM clause */
int iSrc /* Which element of pSrcList to use */
int iSrc, /* Which element of pSrcList to use */
int bAllowSubq /* Allow non-correlated subqueries */
){
const SrcItem *pSrc = &pSrcList->a[iSrc];
if( pSrc->fg.jointype & JT_LTORJ ){
@@ -2628,7 +2664,8 @@ int sqlite3ExprIsSingleTableConstraint(
}
}
}
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
/* Rules (1), (2a), and (2b) handled by the following: */
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor, bAllowSubq);
}
@@ -2713,7 +2750,7 @@ int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
*/
int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
assert( isInit==0 || isInit==1 );
return exprIsConst(0, p, 4+isInit, 0);
return exprIsConst(0, p, 4+isInit);
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
@@ -5031,8 +5068,9 @@ expr_code_doover:
if( !ExprHasProperty(pExpr, EP_Collate) ){
/* A TK_COLLATE Expr node without the EP_Collate tag is a so-called
** "SOFT-COLLATE" that is added to constraints that are pushed down
** from outer queries into sub-queries by the push-down optimization.
** Clear subtypes as subtypes may not cross a subquery boundary.
** from outer queries into sub-queries by the WHERE-clause push-down
** optimization. Clear subtypes as subtypes may not cross a subquery
** boundary.
*/
assert( pExpr->pLeft );
sqlite3ExprCode(pParse, pExpr->pLeft, target);
+4 -1
View File
@@ -3182,7 +3182,10 @@ static int xferOptimization(
}
}
#ifndef SQLITE_OMIT_CHECK
if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
if( pDest->pCheck
&& (db->mDbFlags & DBFLAG_Vacuum)==0
&& sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1)
){
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
}
#endif
+1 -1
View File
@@ -7261,7 +7261,7 @@ sqlite3_file *sqlite3PagerFile(Pager *pPager){
** This will be either the rollback journal or the WAL file.
*/
sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
#if SQLITE_OMIT_WAL
#ifdef SQLITE_OMIT_WAL
return pPager->jfd;
#else
return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
+7
View File
@@ -632,6 +632,11 @@ static int lookupName(
&& ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
){
cnt = cntTab;
#if SQLITE_ALLOW_ROWID_IN_VIEW+0==2
if( pMatch->pTab!=0 && IsView(pMatch->pTab) ){
eNewExprOp = TK_NULL;
}
#endif
if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1;
pExpr->affExpr = SQLITE_AFF_INTEGER;
}
@@ -1349,6 +1354,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
testcase( pNC->ncFlags & NC_PartIdx );
testcase( pNC->ncFlags & NC_IdxExpr );
testcase( pNC->ncFlags & NC_GenCol );
assert( pExpr->x.pSelect );
if( pNC->ncFlags & NC_SelfRef ){
notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
}else{
@@ -1357,6 +1363,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( pNC->nRef>=nRef );
if( nRef!=pNC->nRef ){
ExprSetProperty(pExpr, EP_VarSelect);
pExpr->x.pSelect->selFlags |= SF_Correlated;
}
pNC->ncFlags |= NC_Subquery;
}
+18 -6
View File
@@ -5060,6 +5060,18 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
** The hope is that the terms added to the inner query will make it more
** efficient.
**
** NAME AMBIGUITY
**
** This optimization is called the "WHERE-clause push-down optimization".
**
** Do not confuse this optimization with another unrelated optimization
** with a similar name: The "MySQL push-down optimization" causes WHERE
** clause terms that can be evaluated using only the index and without
** reference to the table are run first, so that if they are false,
** unnecessary table seeks are avoided.
**
** RULES
**
** Do not attempt this optimization if:
**
** (1) (** This restriction was removed on 2017-09-29. We used to
@@ -5125,10 +5137,10 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING
** clause and the subquery.
**
** Without this restriction, the push-down optimization might move
** the ON/USING filter expression from the left side of a RIGHT JOIN
** over to the right side, which leads to incorrect answers. See
** also restriction (6) in sqlite3ExprIsSingleTableConstraint().
** Without this restriction, the WHERE-clause push-down optimization
** might move the ON/USING filter expression from the left side of a
** RIGHT JOIN over to the right side, which leads to incorrect answers.
** See also restriction (6) in sqlite3ExprIsSingleTableConstraint().
**
** (10) The inner query is not the right-hand table of a RIGHT JOIN.
**
@@ -5260,7 +5272,7 @@ static int pushDownWhereTerms(
}
#endif
if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){
if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc, 1) ){
nChng++;
pSubq->selFlags |= SF_PushDown;
while( pSubq ){
@@ -7689,7 +7701,7 @@ int sqlite3Select(
#endif
assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
}else{
TREETRACE(0x4000,pParse,p,("Push-down not possible\n"));
TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n"));
}
/* Convert unused result columns of the subquery into simple NULL
+4 -4
View File
@@ -1927,7 +1927,7 @@ struct sqlite3 {
#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
/* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
#define SQLITE_PushDown 0x00001000 /* The push-down optimization */
#define SQLITE_PushDown 0x00001000 /* WHERE-clause push-down opt */
#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
@@ -3601,11 +3601,12 @@ struct Select {
#define SF_View 0x0200000 /* SELECT statement is a view */
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
#define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
#define SF_Correlated 0x20000000 /* True if references the outer context */
/* True if S exists and has SF_NestedFrom */
#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
@@ -5104,8 +5105,7 @@ int sqlite3ExprTruthValue(const Expr*);
int sqlite3ExprIsConstant(Parse*,Expr*);
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
int sqlite3ExprIsTableConstant(Expr*,int);
int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int);
int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
int sqlite3ExprContainsSubquery(Expr*);
#endif
+2 -2
View File
@@ -942,7 +942,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
** WHERE clause (or the ON clause of a LEFT join) that constrain which
** rows of the target table (pSrc) that can be used. */
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom)
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom, 0)
){
pPartial = sqlite3ExprAnd(pParse, pPartial,
sqlite3ExprDup(pParse->db, pExpr, 0));
@@ -1211,7 +1211,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr;
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc)
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc, 0)
){
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
}
+6
View File
@@ -2474,6 +2474,12 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** iLoop==3: Code all remaining expressions.
**
** An effort is made to skip unnecessary iterations of the loop.
**
** This optimization of causing simple query restrictions to occur before
** more complex one is call the "push-down" optimization in MySQL. Here
** in SQLite, the name is "MySQL push-down", since there is also another
** totally unrelated optimization called "WHERE-clause push-down".
** Sometimes the qualifier is omitted, resulting in an ambiguity, so beware.
*/
iLoop = (pIdx ? 1 : 2);
do{
+11
View File
@@ -55,5 +55,16 @@ do_execsql_test 2.2 {
'(def AND (one NEAR abc)) OR one'
} {<b>one</b>}
#-------------------------------------------------------------------------
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE f USING fts3(a,b);
INSERT INTO f VALUES (101,x'056522650565056505650d051e056505650565286505650565056505056505650565056505650565056505650565056505650565056505656505650565056505650d05650505656505650565ef65056505844c746e65650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056f05650565056505650565056505650565050565056505640565056505650565056505651e05650565056505650565056505650505656565056505650565056505651e0565056505650565056505650565052265056505650569056505650565056505650565056505650565056505650500406505650565056505650565056505000101e5c501014b010101c501c5c501010101f5010201010101014101017373737373737373737373737373737373737373737373737373737330737373737373737373737373737365056505650d051e05650565056528056505650d05650505656505650565650565056505650565056505e505650565056505656505650565056505650d05650505656505650565ef65056505844c746e65650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565286505c705650565050565059494949494949494949494949494949494949494949494949494949494949494949494650565056505650565056505650565056505650565056505656505650565056505650d05650505656505650565ef650565058405056505650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056505650565056505650505650565056505650565056505650565056500000000000000000000000000000000000000000000000000000000000000000565056505656505650565056505650d056500000000000000000000000000000000000000000000000000000000000000000100000000000000ed0000000000ffffffffffffffffffffff0007ffffff0001c5c50001c5c50001c5c50001c5c50001c5c50001c5c50001e5c50001c5c50001c5c50001c5c50001c5c50001c5c5000100000014720000000000000016dac5c50001c5c50001c5c50001c5c50001c5c50001c5c50d0505656505650565ef650565058405056505650565056505650565056505650565056505650565058405800465056505650565056505651e650565056505650565056505650d05650505656505650565050565650584058005650565056505650565056505650565056522650565056505650d051e056505650561286505c70565056505056505650565056505650565056505650565056505650565056505656505650565056505650d05650505656505650565ef650565058405056505650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056505650565056505650565226505737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373733a73737373737373737373737373737373737373737373737373737373737373737373737373737373737c7373737365056505650d051e05650565056528650565056505650505650565056505650565056505650565056505e505650565056505656505650565056505650d05650505656505650565ef65056505');
}
do_execsql_test 3.1 {
SELECT length(snippet(f)) FROM f WHERE b MATCH x'0565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056505650565056505650565056505650565050565056505640565056505650565056505651e05650565056522650565056505650d051e056505650565286505650565056505056505650565056505650565056505650565056505650565056505656505650565056505650d05650505656505650565ef65056505844c746e65650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056f05650565056505650565056505650565050565056505640565056505650565056505651e05650565056505650565056505650505656565056505650565056505651e0565056505650565056505650565052265056505650569056505650565056505650565056505650565056505650500406505650565056505650565056505000101e5c501014b010101c501c5c501010101f50102010101010141010141010001017bf15905000000000017';
} {192}
set sqlite_fts3_enable_parentheses 0
finish_test
+11 -5
View File
@@ -979,7 +979,8 @@ extern int fuzz_invariant(
int iRow, /* The row number for pStmt */
int nRow, /* Total number of output rows */
int *pbCorrupt, /* IN/OUT: Flag indicating a corrupt database file */
int eVerbosity /* How much debugging output */
int eVerbosity, /* How much debugging output */
unsigned int dbOpt /* Default optimization flags */
);
/* Implementation of sqlite_dbdata and sqlite_dbptr */
@@ -1031,7 +1032,12 @@ static int recoverDatabase(sqlite3 *db){
/*
** Run the SQL text
*/
static int runDbSql(sqlite3 *db, const char *zSql, unsigned int *pBtsFlags){
static int runDbSql(
sqlite3 *db, /* Run SQL on this database connection */
const char *zSql, /* The SQL to be run */
unsigned int *pBtsFlags,
unsigned int dbOpt /* Default optimization flags */
){
int rc;
sqlite3_stmt *pStmt;
int bCorrupt = 0;
@@ -1107,7 +1113,7 @@ static int runDbSql(sqlite3 *db, const char *zSql, unsigned int *pBtsFlags){
iRow++;
for(iCnt=0; iCnt<99999; iCnt++){
rc = fuzz_invariant(db, pStmt, iCnt, iRow, nRow,
&bCorrupt, eVerbosity);
&bCorrupt, eVerbosity, dbOpt);
if( rc==SQLITE_DONE ) break;
if( rc!=SQLITE_ERROR ) g.nInvariant++;
if( eVerbosity>0 ){
@@ -1330,7 +1336,7 @@ int runCombinedDbSqlInput(
char cSaved = zSql[i+1];
zSql[i+1] = 0;
if( sqlite3_complete(zSql+j) ){
rc = runDbSql(cx.db, zSql+j, &btsFlags);
rc = runDbSql(cx.db, zSql+j, &btsFlags, dbOpt);
j = i+1;
}
zSql[i+1] = cSaved;
@@ -1340,7 +1346,7 @@ int runCombinedDbSqlInput(
}
}
if( j<i ){
runDbSql(cx.db, zSql+j, &btsFlags);
runDbSql(cx.db, zSql+j, &btsFlags, dbOpt);
}
}
testrun_finished:
+24 -15
View File
@@ -30,7 +30,13 @@
/* Forward references */
static char *fuzz_invariant_sql(sqlite3_stmt*, int);
static int sameValue(sqlite3_stmt*,int,sqlite3_stmt*,int,sqlite3_stmt*);
static void reportInvariantFailed(sqlite3_stmt*,sqlite3_stmt*,int);
static void reportInvariantFailed(
sqlite3_stmt *pOrig, /* The original query */
sqlite3_stmt *pTest, /* The alternative test query with a missing row */
int iRow, /* Row number in pOrig */
unsigned int dbOpt, /* Optimization flags on pOrig */
int noOpt /* True if opt flags inverted for pTest */
);
/*
** Do an invariant check on pStmt. iCnt determines which invariant check to
@@ -68,7 +74,8 @@ int fuzz_invariant(
int iRow, /* Current row number */
int nRow, /* Number of output rows from pStmt */
int *pbCorrupt, /* IN/OUT: Flag indicating a corrupt database file */
int eVerbosity /* How much debugging output */
int eVerbosity, /* How much debugging output */
unsigned int dbOpt /* Default optimization flags */
){
char *zTest;
sqlite3_stmt *pTestStmt = 0;
@@ -76,13 +83,20 @@ int fuzz_invariant(
int i;
int nCol;
int nParam;
int noOpt = (iCnt%3)==0;
if( *pbCorrupt ) return SQLITE_DONE;
nParam = sqlite3_bind_parameter_count(pStmt);
if( nParam>100 ) return SQLITE_DONE;
zTest = fuzz_invariant_sql(pStmt, iCnt);
if( zTest==0 ) return SQLITE_DONE;
if( noOpt ){
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, ~dbOpt);
}
rc = sqlite3_prepare_v2(db, zTest, -1, &pTestStmt, 0);
if( noOpt ){
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, dbOpt);
}
if( rc ){
if( eVerbosity ){
printf("invariant compile failed: %s\n%s\n",
@@ -212,7 +226,7 @@ int fuzz_invariant(
}
sqlite3_finalize(pCk);
if( rc==SQLITE_DONE ){
reportInvariantFailed(pStmt, pTestStmt, iRow);
reportInvariantFailed(pStmt, pTestStmt, iRow, dbOpt, noOpt);
return SQLITE_INTERNAL;
}else if( eVerbosity>0 ){
printf("invariant-error ignored due to the use of virtual tables\n");
@@ -223,7 +237,6 @@ not_a_fault:
return SQLITE_OK;
}
/*
** Generate SQL used to test a statement invariant.
**
@@ -296,14 +309,6 @@ static char *fuzz_invariant_sql(sqlite3_stmt *pStmt, int iCnt){
** WHERE clause. */
continue;
}
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( sqlite3_strlike("%rowid%",zColName,0)==0
|| sqlite3_strlike("%oid%",zColName,0)==0
){
/* ROWID values are unreliable if SQLITE_ALLOW_ROWID_IN_VIEW is used */
continue;
}
#endif
for(j=0; j<i; j++){
const char *zPrior = sqlite3_column_name(pBase, j);
if( sqlite3_stricmp(zPrior, zColName)==0 ) break;
@@ -497,13 +502,17 @@ static void printRow(sqlite3_stmt *pStmt, int iRow){
static void reportInvariantFailed(
sqlite3_stmt *pOrig, /* The original query */
sqlite3_stmt *pTest, /* The alternative test query with a missing row */
int iRow /* Row number in pOrig */
int iRow, /* Row number in pOrig */
unsigned int dbOpt, /* Optimization flags on pOrig */
int noOpt /* True if opt flags inverted for pTest */
){
int iTestRow = 0;
printf("Invariant check failed on row %d.\n", iRow);
printf("Original query --------------------------------------------------\n");
printf("Original query (opt-flags: 0x%08x) --------------------------\n",
dbOpt);
printf("%s\n", sqlite3_expanded_sql(pOrig));
printf("Alternative query -----------------------------------------------\n");
printf("Alternative query (opt-flags: 0x%08x) -----------------------\n",
noOpt ? ~dbOpt : dbOpt);
printf("%s\n", sqlite3_expanded_sql(pTest));
printf("Result row that is missing from the alternative -----------------\n");
printRow(pOrig, iRow);
+109 -4
View File
@@ -1,4 +1,4 @@
# 2017 April 29
# 2017-04-29
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
@@ -8,6 +8,26 @@
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Test cases for the push-down optimizations.
#
#
# There are two different meanings for "push-down optimization".
#
# (1) "MySQL push-down" means that WHERE clause terms that can be
# evaluated using only the index and without reference to the
# table are run first, so that if they are false, unnecessary table
# seeks are avoided. See https://sqlite.org/src/info/d7bb79ed3a40419d
# from 2017-04-29.
#
# (2) "WHERE-clause pushdown" means to push WHERE clause terms in
# outer queries down into subqueries. See
# https://sqlite.org/src/info/6df18e949d367629 from 2015-06-02.
#
# This module started out as tests for MySQL push-down only. But because
# of naming ambiguity, it has picked up test cases for WHERE-clause push-down
# over the years.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -87,8 +107,8 @@ do_test 2.2 {
} {three}
# 2022-11-25 dbsqlfuzz crash-3a548de406a50e896c1bf7142692d35d339d697f
# Disable the push-down optimization for compound subqueries if any
# arm of the compound has an incompatible affinity.
# Disable the WHERE-clause push-down optimization for compound subqueries
# if any arm of the compound has an incompatible affinity.
#
reset_db
do_execsql_test 3.1 {
@@ -185,7 +205,7 @@ do_eqp_test 3.8 {
# SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2)
# 2023-05-09 https://sqlite.org/forum/forumpost/a7d4be7fb6
# Restriction (9) on the push-down optimization.
# Restriction (9) on the WHERE-clause push-down optimization.
#
reset_db
db null -
@@ -227,4 +247,89 @@ do_execsql_test 5.0 {
WHERE e>0;
} {- - 3 4 5}
# 2024-04-05
# Allow push-down of operators of the form "expr IN table".
#
reset_db
do_execsql_test 6.0 {
CREATE TABLE t01(w,x,y,z);
CREATE TABLE t02(w,x,y,z);
CREATE VIEW t0(w,x,y,z) AS
SELECT w,x,y,z FROM t01 UNION ALL SELECT w,x,y,z FROM t02;
CREATE INDEX t01x ON t01(w,x,y);
CREATE INDEX t02x ON t02(w,x,y);
CREATE VIEW v1(k) AS VALUES(77),(88),(99);
CREATE TABLE k1(k);
INSERT INTO k1 SELECT * FROM v1;
}
do_eqp_test 6.1 {
WITH k(n) AS (VALUES(77),(88),(99))
SELECT max(z) FROM t0 WHERE w=123 AND x IN k AND y BETWEEN 44 AND 55;
} {
QUERY PLAN
|--CO-ROUTINE t0
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | |--SEARCH t01 USING INDEX t01x (w=? AND x=? AND y>? AND y<?)
| | `--LIST SUBQUERY xxxxxx
| | |--MATERIALIZE k
| | | `--SCAN 3 CONSTANT ROWS
| | `--SCAN k
| `--UNION ALL
| |--SEARCH t02 USING INDEX t02x (w=? AND x=? AND y>? AND y<?)
| `--LIST SUBQUERY xxxxxx
| `--SCAN k
|--SEARCH t0
`--LIST SUBQUERY xxxxxx
`--SCAN k
}
# ^^^^--- The key feature above is that the SEARCH for each subquery
# uses all three fields of the index w, x, and y. Prior to the push-down
# of "expr IN table", only the w term of the index would be used. Similar
# for the following tests:
#
do_eqp_test 6.2 {
SELECT max(z) FROM t0 WHERE w=123 AND x IN v1 AND y BETWEEN 44 AND 55;
} {
QUERY PLAN
|--CO-ROUTINE t0
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | |--SEARCH t01 USING INDEX t01x (w=? AND x=? AND y>? AND y<?)
| | `--LIST SUBQUERY xxxxxx
| | |--CO-ROUTINE v1
| | | `--SCAN 3 CONSTANT ROWS
| | `--SCAN v1
| `--UNION ALL
| |--SEARCH t02 USING INDEX t02x (w=? AND x=? AND y>? AND y<?)
| `--LIST SUBQUERY xxxxxx
| |--CO-ROUTINE v1
| | `--SCAN 3 CONSTANT ROWS
| `--SCAN v1
|--SEARCH t0
`--LIST SUBQUERY xxxxxx
|--CO-ROUTINE v1
| `--SCAN 3 CONSTANT ROWS
`--SCAN v1
}
do_eqp_test 6.3 {
SELECT max(z) FROM t0 WHERE w=123 AND x IN k1 AND y BETWEEN 44 AND 55;
} {
QUERY PLAN
|--CO-ROUTINE t0
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | |--SEARCH t01 USING INDEX t01x (w=? AND x=? AND y>? AND y<?)
| | `--LIST SUBQUERY xxxxxx
| | `--SCAN k1
| `--UNION ALL
| |--SEARCH t02 USING INDEX t02x (w=? AND x=? AND y>? AND y<?)
| `--LIST SUBQUERY xxxxxx
| `--SCAN k1
|--SEARCH t0
`--LIST SUBQUERY xxxxxx
`--SCAN k1
}
finish_test
+5 -5
View File
@@ -227,21 +227,21 @@ ifcapable !allow_rowid_in_view {
} else {
# Note: The values returned by the RETURNING clauses of the following
# two statements are the rowid columns of views. These values are not
# well defined, so the INSERT returns -1, and the UPDATE returns 1, 2
# and 3. These match the values used for new.rowid expressions, but
# not much else.
# well defined, so the INSERT returns -1, and the UPDATE returns NULL.
# These match the values used for new.rowid expressions, but not much
# else.
do_catchsql_test 10.3a {
INSERT INTO t1(a, b) VALUES(1234, 5678) RETURNING rowid;
} {0 -1}
do_catchsql_test 10.3b {
UPDATE t1 SET a='z' WHERE b='y' RETURNING rowid;
} {0 {1 2 3}}
} {0 {{} {} {}}}
do_execsql_test 10.4 {
SELECT * FROM log;
} {
insert -1 1234 5678 update 1 z y update 2 z y update 3 z y
insert -1 1234 5678 update {} z y update {} z y update {} z y
}
}
+15 -2
View File
@@ -270,7 +270,7 @@ set TRG(schema) {
/* Fields updated as jobs run */
starttime INTEGER,
endtime INTEGER,
state TEXT CHECK( state IN ('', 'ready', 'running', 'done', 'failed') ),
state TEXT CHECK( state IN ('','ready','running','done','failed','omit') ),
output TEXT
);
@@ -447,6 +447,10 @@ if {[llength $argv]==1
} job {
display_job [array get job]
}
set nOmit [db one {SELECT count(*) FROM jobs WHERE state='omit'}]
if {$nOmit} {
puts "$nOmit jobs omitted due to failures"
}
}
mydb close
@@ -975,11 +979,16 @@ proc make_new_testset {} {
proc mark_job_as_finished {jobid output state endtm} {
r_write_db {
if {$state=="failed"} {
set childstate omit
} else {
set childstate ready
}
trdb eval {
UPDATE jobs
SET output=$output, state=$state, endtime=$endtm
WHERE jobid=$jobid;
UPDATE jobs SET state='ready' WHERE depid=$jobid;
UPDATE jobs SET state=$childstate WHERE depid=$jobid;
}
}
}
@@ -1202,6 +1211,10 @@ proc run_testset {} {
puts "FAILED: $displayname"
}
}
set nOmit [trdb one {SELECT count(*) FROM jobs WHERE state='omit'}]
if {$nOmit>0} {
puts "$nOmit jobs skipped due to prior failures"
}
}
puts "\nTest database is $TRG(dbname)"
+24
View File
@@ -268,4 +268,28 @@ do_catchsql_test upsert1-1210 {
INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT(b+?1) DO NOTHING;
} {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}}
# 2024-04-11 https://sqlite.org/forum/forumpost/284955a3cd454a15
# Incorrect value passed into a trigger that fires as the result of
# an upsert.
#
reset_db
do_execsql_test upsert1-1300 {
CREATE TABLE t1(x INT, y TEXT);
INSERT INTO t1 VALUES
(11, printf('%.9000c','a')),
(11, printf('%.9000c','a')),
(33, printf('%.9000c','b')),
(33, printf('%.9000c','b'));
CREATE TABLE t2(x INT UNIQUE, y TEXT);
CREATE TRIGGER r1 BEFORE UPDATE ON t2 BEGIN
SELECT raise(ABORT,'Incorrect old.y value passed to trigger!')
WHERE old.y != new.y;
/* ^^^ This trigger will fire and cause the ABORT if the problem has
** not been fixed, or if there is a regression. */
END;
INSERT INTO t2(x, y) SELECT x, y FROM t1
WHERE true
ON CONFLICT (x) DO UPDATE SET y = excluded.y;
} {}
finish_test
+34 -1
View File
@@ -26,13 +26,36 @@ ifcapable {!vacuum} {
forcedelete out.db
do_execsql_test vacuum-into-100 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE t1(
a INTEGER PRIMARY KEY,
b ANY,
c INT AS (b+1), --- See "2024-04-09" block
CHECK( typeof(b)!='integer' OR b>a-5 ) --- comment below
);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a,b) SELECT x, randomblob(600) FROM c;
CREATE INDEX t1b ON t1(b);
DELETE FROM t1 WHERE a%2;
SELECT count(*), sum(a), sum(length(b)) FROM t1;
} {50 2550 30000}
# Update 2024-04-09 for forum post eec177d68fe7fa2c.
#
# VACUUM INTO is sensitive to tables holding both generated columns
# and CHECK constraints.
#
# CHECK constraints are ignored for read-only databases in order to save
# memory (see check-in 34ddf02d3d21151b on 2014-05-21). But the xfer
# optimization normally only works if CHECK constraints match between the
# source and destination tables. So the xfer optimization was not
# working for VACUUM INTO when the source was a read-only database and the
# table held CHECK constraints. But if the table has generated columns,
# then the xfer optimization is required or else VACUUM will raise an
# error.
#
# Fix this by ignoring CHECK constraints when determining whether or not
# the xfer optimization can run while doing VACUUM.
do_execsql_test vacuum-into-110 {
VACUUM main INTO 'out.db';
} {}
@@ -88,11 +111,21 @@ do_catchsql_test vacuum-into-420 {
# The ability to VACUUM INTO a read-only database
db close
if {$tcl_platform(platform)=="windows"} {
file attributes test.db -readonly 1
} else {
file attributes test.db -permissions 292 ;# 292 == 0444
}
sqlite3 db test.db -readonly 1
forcedelete test.db2
do_execsql_test vacuum-into-500 {
VACUUM INTO 'test.db2';
}
if {$tcl_platform(platform)=="windows"} {
file attributes test.db -readonly 0
} else {
file attributes test.db -permissions 420 ;# 420 = 0644
}
sqlite3 db2 test.db2
do_test vacuum-into-510 {
db2 eval {SELECT name FROM sqlite_master ORDER BY 1}