From f26a1549ac363019e032f7d328d435e1c118b5fd Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 2 Dec 2014 19:04:54 +0000 Subject: [PATCH 01/13] Add the SQLITE_CHECKPOINT_TRUNCATE option. FossilOrigin-Name: 8e20a43419e46b6b9d1f60ec7ea420bbfb3ef358 --- manifest | 29 +++++++++++--------- manifest.uuid | 2 +- src/main.c | 9 ++++--- src/pragma.c | 4 ++- src/sqlite.h.in | 21 +++++++++------ src/test1.c | 3 ++- src/vdbe.c | 1 + src/wal.c | 70 +++++++++++++++++++++++++++++++++++-------------- test/wal5.test | 43 +++++++++++++++++++++++++++++- 9 files changed, 133 insertions(+), 49 deletions(-) diff --git a/manifest b/manifest index 7f9f9524d0..35fb1bb478 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Convert\stwo\sunreachable\sbranches\sinto\sassert()\sstatements. -D 2014-12-02T16:16:47.791 +C Add\sthe\sSQLITE_CHECKPOINT_TRUNCATE\soption. +D 2014-12-02T19:04:54.595 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -195,7 +195,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770 F src/loadext.c de741e66e5ddc1598d904d7289239696e40ed994 -F src/main.c 54d0f4896cebc61ae5f831937464953780fe5346 +F src/main.c 34b895b5ebfc73cd690dcd9ac6d0eecb28ce729f F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c faf615aafd8be74a71494dfa027c113ea5c6615f @@ -222,7 +222,7 @@ F src/parse.y 5dfead8aed90cb0c7c1115898ee2266804daff45 F src/pcache.c ace1b67632deeaa84859b4c16c27711dfb7db3d4 F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8 F src/pcache1.c facbdd3ecc09c8f750089d941305694301328e98 -F src/pragma.c 3f3e959390a10c0131676f0e307acce372777e0f +F src/pragma.c d54cdd40b63d608f2d95b7482c710690e3593a73 F src/prepare.c b7b7bf020bd4c962f7c8aed5a3c542c7dfe9f9c7 F src/printf.c 9e75a6a0b55bf61cfff7d7e19d89834a1b938236 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 @@ -230,7 +230,7 @@ F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 428165951748151e87a15295b7357221433e311b F src/shell.c 45d9c9bd7cde07845af957f2d849933b990773cf -F src/sqlite.h.in c63db0117aeb749ca02b6016dbbbccbbbd9a141d +F src/sqlite.h.in 400bac7dd1294cb902b5eb85feed1689a2623ced F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d F src/sqliteInt.h c9e95b8fa9aee30d46387735c5be73fa58886e38 @@ -238,7 +238,7 @@ F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 81712116e826b0089bb221b018929536b2b5406f F src/table.c f142bba7903e93ca8d113a5b8877a108ad1a27dc F src/tclsqlite.c 0a874655dd39a9875e39c5d3c464db662171d228 -F src/test1.c a0bce4f47da65b76c80e5f8bf9a5ef174603866a +F src/test1.c f5d7ecd3dd663b11f35269fd91f7090db0570903 F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712 F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df @@ -291,7 +291,7 @@ F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c 3b627daa45c7308c1e36e3dbaa3f9ce7e5c7fa73 F src/vacuum.c 9b30ec729337dd012ed88d4c292922c8ef9cf00c -F src/vdbe.c ec1f55acef4864520ca2017b9f0d60c2ac1b8b78 +F src/vdbe.c 60217f3b8ab984b2e2bb9e3965276dd29e5efe5d F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3 F src/vdbeInt.h 9bb69ff2447c34b6ccc58b34ec35b615f86ead78 F src/vdbeapi.c 07acb615d1e4170e71fc1b0d087f3c53a1ad8e83 @@ -301,7 +301,7 @@ F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f F src/vdbesort.c 42c166f7ca78cb643c7f4e4bdfa83c59d363d1a6 F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 F src/vtab.c c08ec66f45919eaa726bf88aa53eb08379d607f9 -F src/wal.c 486e644b3b8aa5ad066f625bc428aa8ff7001405 +F src/wal.c f09818db7ba6e31d7a681eb99f801a7722c731d9 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 F src/where.c a0b16f9d78321cb340a977287d19f826555c7d3b @@ -1113,7 +1113,7 @@ F test/wal.test 885f32b2b390b30b4aa3dbb0e568f8f78d40f5cc F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0 F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c -F test/wal5.test 8f888b50f66b78821e61ed0e233ded5de378224b +F test/wal5.test 174cc1512e304a7dfa28ac30527e28ea02fc37df F test/wal6.test 527581f5527bf9c24394991e2be83000aace5f9e F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8 F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd @@ -1223,7 +1223,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0d04f380e1bd17104b3cf76b64d0cfc79a726606 -R 22214da224af1bd07c2ba4ce527797c4 -U drh -Z 4469ca4ec037115204af98a9b9e41068 +P 61b31e771430f490fc2c4cef55046debc4a5f4f5 +R 837049ab8d5153c1422981d3f48166e4 +T *branch * checkpoint-truncate +T *sym-checkpoint-truncate * +T -sym-trunk * +U dan +Z ce82007701b4a39f21164e74e2380c4f diff --git a/manifest.uuid b/manifest.uuid index fe8f0fdad5..9aff9e9fbc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -61b31e771430f490fc2c4cef55046debc4a5f4f5 \ No newline at end of file +8e20a43419e46b6b9d1f60ec7ea420bbfb3ef358 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 1d34b13d6f..9ac3fde733 100644 --- a/src/main.c +++ b/src/main.c @@ -1936,10 +1936,11 @@ int sqlite3_wal_checkpoint_v2( if( pnLog ) *pnLog = -1; if( pnCkpt ) *pnCkpt = -1; - assert( SQLITE_CHECKPOINT_FULL>SQLITE_CHECKPOINT_PASSIVE ); - assert( SQLITE_CHECKPOINT_FULLSQLITE_CHECKPOINT_RESTART ){ + assert( SQLITE_CHECKPOINT_PASSIVE==0 ); + assert( SQLITE_CHECKPOINT_FULL==1 ); + assert( SQLITE_CHECKPOINT_RESTART==2 ); + assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); + if( eModeSQLITE_CHECKPOINT_TRUNCATE ){ return SQLITE_MISUSE; } diff --git a/src/pragma.c b/src/pragma.c index 543f265ba9..ab9a283629 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -2195,7 +2195,7 @@ void sqlite3Pragma( #ifndef SQLITE_OMIT_WAL /* - ** PRAGMA [database.]wal_checkpoint = passive|full|restart + ** PRAGMA [database.]wal_checkpoint = passive|full|restart|truncate ** ** Checkpoint the database. */ @@ -2207,6 +2207,8 @@ void sqlite3Pragma( eMode = SQLITE_CHECKPOINT_FULL; }else if( sqlite3StrICmp(zRight, "restart")==0 ){ eMode = SQLITE_CHECKPOINT_RESTART; + }else if( sqlite3StrICmp(zRight, "truncate")==0 ){ + eMode = SQLITE_CHECKPOINT_TRUNCATE; } } sqlite3VdbeSetNumCols(v, 3); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index f1b917c308..807c9ee62c 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7291,6 +7291,10 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); ** that the next client to write to the database file restarts the log file ** from the beginning. This call blocks database writers while it is running, ** but not database readers. +** +**
SQLITE_CHECKPOINT_TRUNCATE
+** This mode works the same way as SQLITE_CHECKPOINT_RESTART except that, +** if successful, it also truncates the log file to zero bytes in size. ** ** ** If pnLog is not NULL, then *pnLog is set to the total number of frames in @@ -7306,11 +7310,11 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); ** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a ** busy-handler configured, it will not be invoked in this case. ** -** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive -** "writer" lock on the database file. If the writer lock cannot be obtained -** immediately, and a busy-handler is configured, it is invoked and the writer -** lock retried until either the busy-handler returns 0 or the lock is -** successfully obtained. The busy-handler is also invoked while waiting for +** The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the +** exclusive "writer" lock on the database file. If the writer lock cannot be +** obtained immediately, and a busy-handler is configured, it is invoked and +** the writer lock retried until either the busy-handler returns 0 or the lock +** is successfully obtained. The busy-handler is also invoked while waiting for ** database readers as described above. If the busy-handler returns 0 before ** the writer lock is obtained or while waiting for database readers, the ** checkpoint operation proceeds from that point in the same way as @@ -7349,9 +7353,10 @@ int sqlite3_wal_checkpoint_v2( ** documentation for additional information about the meaning and use of ** each of these values. */ -#define SQLITE_CHECKPOINT_PASSIVE 0 -#define SQLITE_CHECKPOINT_FULL 1 -#define SQLITE_CHECKPOINT_RESTART 2 +#define SQLITE_CHECKPOINT_PASSIVE 0 +#define SQLITE_CHECKPOINT_FULL 1 +#define SQLITE_CHECKPOINT_RESTART 2 +#define SQLITE_CHECKPOINT_TRUNCATE 3 /* ** CAPI3REF: Virtual Table Interface Configuration diff --git a/src/test1.c b/src/test1.c index 1c43861547..be4ad92c11 100644 --- a/src/test1.c +++ b/src/test1.c @@ -5690,10 +5690,11 @@ static int test_wal_checkpoint_v2( int nCkpt = -555; Tcl_Obj *pRet; - const char * aMode[] = { "passive", "full", "restart", 0 }; + const char * aMode[] = { "passive", "full", "restart", "truncate", 0 }; assert( SQLITE_CHECKPOINT_PASSIVE==0 ); assert( SQLITE_CHECKPOINT_FULL==1 ); assert( SQLITE_CHECKPOINT_RESTART==2 ); + assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); if( objc!=3 && objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?"); diff --git a/src/vdbe.c b/src/vdbe.c index 822bf80bb8..7f661b42b1 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5724,6 +5724,7 @@ case OP_Checkpoint: { assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE || pOp->p2==SQLITE_CHECKPOINT_FULL || pOp->p2==SQLITE_CHECKPOINT_RESTART + || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE ); rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); if( rc==SQLITE_BUSY ){ diff --git a/src/wal.c b/src/wal.c index 3033444b41..849b776743 100644 --- a/src/wal.c +++ b/src/wal.c @@ -1623,6 +1623,34 @@ static int walPagesize(Wal *pWal){ return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); } +/* +** The following is guaranteed when this function is called: +** +** a) the WRITER lock is held, +** b) the entire log file has been checkpointed, and +** c) any existing readers are reading exclusively from the database +** file - there are no readers that may attempt to read a frame from +** the log file. +** +** This function updates the shared-memory structures so that the next +** client to write to the database (which may be this one) does so by +** writing frames into the start of the log file. +*/ +static void walRestartHdr(Wal *pWal){ + volatile WalCkptInfo *pInfo = walCkptInfo(pWal); + int i; /* Loop counter */ + u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ + pWal->nCkpt++; + pWal->hdr.mxFrame = 0; + sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); + sqlite3_randomness(4, &aSalt[1]); + walIndexWriteHdr(pWal); + pInfo->nBackfill = 0; + pInfo->aReadMark[1] = 0; + for(i=2; iaReadMark[i] = READMARK_NOT_USED; + assert( pInfo->aReadMark[0]==0 ); +} + /* ** Copy as much content as we can from the WAL back into the database file ** in response to an sqlite3_wal_checkpoint() request or the equivalent. @@ -1775,19 +1803,34 @@ static int walCheckpoint( rc = SQLITE_OK; } - /* If this is an SQLITE_CHECKPOINT_RESTART operation, and the entire wal - ** file has been copied into the database file, then block until all - ** readers have finished using the wal file. This ensures that the next - ** process to write to the database restarts the wal file. + /* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the + ** entire wal file has been copied into the database file, then block + ** until all readers have finished using the wal file. This ensures that + ** the next process to write to the database restarts the wal file. */ if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ assert( pWal->writeLock ); if( pInfo->nBackfillhdr.mxFrame ){ rc = SQLITE_BUSY; - }else if( eMode==SQLITE_CHECKPOINT_RESTART ){ + }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ assert( mxSafeFrame==pWal->hdr.mxFrame ); rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); if( rc==SQLITE_OK ){ + if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){ + /* If this is a TRUNCATE checkpoint, also truncate the wal file + ** to zero bytes in size on disk. + ** + ** In theory, it might be safe to do this without updating the + ** wal-index header in shared memory, as all subsequent reader or + ** writer clients should see that the entire log file has been + ** checkpointed and behave accordingly. This seems unsafe though, + ** as it would leave the system in a state where the contents of + ** the wal-index header do not match the contents of the + ** file-system. To avoid this, update the wal-index header to + ** indicate that the log file contains zero valid frames. */ + walRestartHdr(pWal); + rc = sqlite3OsTruncate(pWal->pWalFd, 0); + } walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); } } @@ -2573,7 +2616,6 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ return rc; } - /* ** This function is called just before writing a set of frames to the log ** file (see sqlite3WalFrames()). It checks to see if, instead of appending @@ -2606,20 +2648,8 @@ static int walRestartLog(Wal *pWal){ ** In theory it would be Ok to update the cache of the header only ** at this point. But updating the actual wal-index header is also ** safe and means there is no special case for sqlite3WalUndo() - ** to handle if this transaction is rolled back. - */ - int i; /* Loop counter */ - u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ - - pWal->nCkpt++; - pWal->hdr.mxFrame = 0; - sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); - aSalt[1] = salt1; - walIndexWriteHdr(pWal); - pInfo->nBackfill = 0; - pInfo->aReadMark[1] = 0; - for(i=2; iaReadMark[i] = READMARK_NOT_USED; - assert( pInfo->aReadMark[0]==0 ); + ** to handle if this transaction is rolled back. */ + walRestartHdr(pWal); walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); }else if( rc!=SQLITE_BUSY ){ return rc; diff --git a/test/wal5.test b/test/wal5.test index 68750f1479..09c7d76040 100644 --- a/test/wal5.test +++ b/test/wal5.test @@ -55,7 +55,8 @@ foreach {testprefix do_wal_checkpoint} { if {[lsearch {-mode -db} $key]<0} { error "unknown switch: $key" } } - if {$a(-mode)!="restart" && $a(-mode)!="full"} { set a(-mode) passive } + set vals {restart full truncate} + if {[lsearch -exact $vals $a(-mode)]<0} { set a(-mode) passive } set cmd [list sqlite3_wal_checkpoint_v2 $dbhandle $a(-mode)] if {[info exists a(-db)]} { lappend sql $a(-db) } @@ -278,6 +279,11 @@ foreach {testprefix do_wal_checkpoint} { 9 RESTART 2 {1 4 3} 2 10 RESTART 3 {1 4 4} 3 + 11 TRUNCATE - {0 0 0} 3 + 12 TRUNCATE 1 {1 3 3} 1 + 13 TRUNCATE 2 {1 4 3} 2 + 14 TRUNCATE 3 {1 4 4} 3 + } { do_multiclient_test tn { setup_and_attach_aux @@ -348,6 +354,41 @@ foreach {testprefix do_wal_checkpoint} { do_test 3.$tn.6 { code3 { do_wal_checkpoint db3 } } {0 0 0} } + + # Test SQLITE_CHECKPOINT_TRUNCATE. + # + do_multiclient_test tn { + + code1 $do_wal_checkpoint + code2 $do_wal_checkpoint + code3 $do_wal_checkpoint + + do_test 3.$tn.1 { + sql1 { + PRAGMA page_size = 1024; + PRAGMA journal_mode = WAL; + PRAGMA synchronous = normal; + CREATE TABLE t1(x, y); + CREATE INDEX i1 ON t1(x, y); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(3, 4); + } + file size test.db-wal + } [wal_file_size 8 1024] + + do_test 3.$tn.2 { do_wal_checkpoint db -mode truncate } {0 0 0} + do_test 3.$tn.3 { file size test.db-wal } 0 + + do_test 3.$tn.4 { + sql2 { SELECT * FROM t1 } + } {1 2 3 4} + + do_test 3.$tn.5 { + sql2 { INSERT INTO t1 VALUES('a', 'b') } + file size test.db-wal + } [wal_file_size 2 1024] + + } } From 0fe8c1b96724c954628594fcbd44b284f9636d13 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 2 Dec 2014 19:35:09 +0000 Subject: [PATCH 02/13] When attempting to restart a wal file, make any required calls to sqlite3_randomness() before waiting on or checking for wal file readers. This restores the behaviour exhibited by the trunk. FossilOrigin-Name: 6ee08769f0ffbb3d620c66b89180ece7782dc820 --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/wal.c | 14 ++++++++++---- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 35fb1bb478..0caddab954 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_CHECKPOINT_TRUNCATE\soption. -D 2014-12-02T19:04:54.595 +C When\sattempting\sto\srestart\sa\swal\sfile,\smake\sany\srequired\scalls\sto\ssqlite3_randomness()\sbefore\swaiting\son\sor\schecking\sfor\swal\sfile\sreaders.\sThis\srestores\sthe\sbehaviour\sexhibited\sby\sthe\strunk. +D 2014-12-02T19:35:09.278 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -301,7 +301,7 @@ F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f F src/vdbesort.c 42c166f7ca78cb643c7f4e4bdfa83c59d363d1a6 F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 F src/vtab.c c08ec66f45919eaa726bf88aa53eb08379d607f9 -F src/wal.c f09818db7ba6e31d7a681eb99f801a7722c731d9 +F src/wal.c e396f31038aa01b9de95584b703692716275aedc F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 F src/where.c a0b16f9d78321cb340a977287d19f826555c7d3b @@ -1223,10 +1223,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 61b31e771430f490fc2c4cef55046debc4a5f4f5 -R 837049ab8d5153c1422981d3f48166e4 -T *branch * checkpoint-truncate -T *sym-checkpoint-truncate * -T -sym-trunk * +P 8e20a43419e46b6b9d1f60ec7ea420bbfb3ef358 +R 54481572fc28e1041792401f62b71701 U dan -Z ce82007701b4a39f21164e74e2380c4f +Z a7c4df9879a4ca8a80f8224dd87c78e4 diff --git a/manifest.uuid b/manifest.uuid index 9aff9e9fbc..4930bb9b15 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8e20a43419e46b6b9d1f60ec7ea420bbfb3ef358 \ No newline at end of file +6ee08769f0ffbb3d620c66b89180ece7782dc820 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 849b776743..b88ece88b8 100644 --- a/src/wal.c +++ b/src/wal.c @@ -1635,15 +1635,19 @@ static int walPagesize(Wal *pWal){ ** This function updates the shared-memory structures so that the next ** client to write to the database (which may be this one) does so by ** writing frames into the start of the log file. +** +** The value of parameter salt1 is used as the aSalt[1] value in the +** new wal-index header. It should be passed a pseudo-random value (i.e. +** one obtained from sqlite3_randomness()). */ -static void walRestartHdr(Wal *pWal){ +static void walRestartHdr(Wal *pWal, u32 salt1){ volatile WalCkptInfo *pInfo = walCkptInfo(pWal); int i; /* Loop counter */ u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ pWal->nCkpt++; pWal->hdr.mxFrame = 0; sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); - sqlite3_randomness(4, &aSalt[1]); + memcpy(&pWal->hdr.aSalt[1], &salt1, 4); walIndexWriteHdr(pWal); pInfo->nBackfill = 0; pInfo->aReadMark[1] = 0; @@ -1813,6 +1817,8 @@ static int walCheckpoint( if( pInfo->nBackfillhdr.mxFrame ){ rc = SQLITE_BUSY; }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ + u32 salt1; + sqlite3_randomness(4, &salt1); assert( mxSafeFrame==pWal->hdr.mxFrame ); rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); if( rc==SQLITE_OK ){ @@ -1828,7 +1834,7 @@ static int walCheckpoint( ** the wal-index header do not match the contents of the ** file-system. To avoid this, update the wal-index header to ** indicate that the log file contains zero valid frames. */ - walRestartHdr(pWal); + walRestartHdr(pWal, salt1); rc = sqlite3OsTruncate(pWal->pWalFd, 0); } walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); @@ -2649,7 +2655,7 @@ static int walRestartLog(Wal *pWal){ ** at this point. But updating the actual wal-index header is also ** safe and means there is no special case for sqlite3WalUndo() ** to handle if this transaction is rolled back. */ - walRestartHdr(pWal); + walRestartHdr(pWal, salt1); walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); }else if( rc!=SQLITE_BUSY ){ return rc; From 2d2e7bfeff0dcac767d0bd69a7d11df303d261fa Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Dec 2014 15:50:09 +0000 Subject: [PATCH 03/13] Updates to the documentation for sqlite3_wal_checkpoint_v2() and related interfaces, including adding many requirements marks. FossilOrigin-Name: 1e212d9899387344fd62c7b6fbcc59ea885b6d7c --- manifest | 13 +++--- manifest.uuid | 2 +- src/sqlite.h.in | 111 ++++++++++++++++++++++++++---------------------- 3 files changed, 67 insertions(+), 59 deletions(-) diff --git a/manifest b/manifest index e04f96ce65..97c3ddfce2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssupport\sfor\sSQLITE_CHECKPOINT_TRUNCATE. -D 2014-12-02T20:51:52.630 +C Updates\sto\sthe\sdocumentation\sfor\ssqlite3_wal_checkpoint_v2()\sand\srelated\ninterfaces,\sincluding\sadding\smany\srequirements\smarks. +D 2014-12-03T15:50:09.223 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -230,7 +230,7 @@ F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 428165951748151e87a15295b7357221433e311b F src/shell.c 45d9c9bd7cde07845af957f2d849933b990773cf -F src/sqlite.h.in 400bac7dd1294cb902b5eb85feed1689a2623ced +F src/sqlite.h.in 7d33b94a32b013832b53ad86be543168f87f8eb7 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d F src/sqliteInt.h c9e95b8fa9aee30d46387735c5be73fa58886e38 @@ -1223,8 +1223,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 61b31e771430f490fc2c4cef55046debc4a5f4f5 6ee08769f0ffbb3d620c66b89180ece7782dc820 -R 54481572fc28e1041792401f62b71701 -T +closed 6ee08769f0ffbb3d620c66b89180ece7782dc820 +P edda2b9e7a15ed486de81b10dd9bacd39c571d3f +R d436425f6a4681c70264f79cf1bfa41d U drh -Z 2b54bfeee1d348300e5d5565430bbc39 +Z 881f6486595c3b0d62652277de190ac9 diff --git a/manifest.uuid b/manifest.uuid index e1c0f3e973..74bdbd7193 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -edda2b9e7a15ed486de81b10dd9bacd39c571d3f \ No newline at end of file +1e212d9899387344fd62c7b6fbcc59ea885b6d7c \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 807c9ee62c..74c59f9257 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7249,7 +7249,7 @@ int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); ** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a ** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint. ** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL -** or RESET checkpoint. +** or RESET or TRUNCATE checkpoint. ** ** ^The [wal_checkpoint pragma] can be used to invoke this interface ** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the @@ -7263,79 +7263,87 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Checkpoint a database ** -** Run a checkpoint operation on WAL database zDb attached to database -** handle db. The specific operation is determined by the value of the -** eMode parameter: +** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint operation +** on database X of [database connection] D in mode M. Status information is +** written back into integers pointed to by L and C.)^ ^(The M parameter must be +** a valid [SQLITE_CHECKPOINT_PASSIVE|checkpoint mode]:)^ ** **
**
SQLITE_CHECKPOINT_PASSIVE
-** Checkpoint as many frames as possible without waiting for any database -** readers or writers to finish. Sync the db file if all frames in the log -** are checkpointed. This mode is the same as calling -** sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback] -** is never invoked. +** ^Checkpoint as many frames as possible without waiting for any database +** readers or writers to finish, then sync the database file if all frames +** in the log were checkpointed. ^This mode is the same as calling +** [sqlite3_wal_checkpoint()]. ^The [sqlite3_busy_handler|busy-handler callback] +** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. ^On the other hand, +** passive mode might leave the checkpoint unfinished if there are concurrent +** readers or writers. ** **
SQLITE_CHECKPOINT_FULL
-** This mode blocks (it invokes the +** ^This mode blocks (it invokes the ** [sqlite3_busy_handler|busy-handler callback]) until there is no ** database writer and all readers are reading from the most recent database -** snapshot. It then checkpoints all frames in the log file and syncs the -** database file. This call blocks database writers while it is running, -** but not database readers. +** snapshot. ^It then checkpoints all frames in the log file and syncs the +** database file. ^This mode blocks new database writers while it is pending, +** but new database readers are allowed to continue unimpeded. ** **
SQLITE_CHECKPOINT_RESTART
-** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after -** checkpointing the log file it blocks (calls the +** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition +** that after checkpointing the log file it blocks (calls the ** [sqlite3_busy_handler|busy-handler callback]) -** until all readers are reading from the database file only. This ensures -** that the next client to write to the database file restarts the log file -** from the beginning. This call blocks database writers while it is running, -** but not database readers. +** until all readers are reading from the database file only. ^This ensures +** that the next writer will restart the log file from the beginning. +** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new +** database writer attempts while it is pending, but does not impede readers. ** **
SQLITE_CHECKPOINT_TRUNCATE
-** This mode works the same way as SQLITE_CHECKPOINT_RESTART except that, -** if successful, it also truncates the log file to zero bytes in size. +** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the addition +** that it also truncates the log file to zero bytes just prior to a successful +** return. **
** -** If pnLog is not NULL, then *pnLog is set to the total number of frames in -** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to -** the total number of checkpointed frames (including any that were already -** checkpointed when this function is called). *pnLog and *pnCkpt may be -** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK. -** If no values are available because of an error, they are both set to -1 -** before returning to communicate this to the caller. +** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in +** the log file before returning or to -1 if the checkpoint could not run because +** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not NULL, +** then *pnCkpt is set to the total number of checkpointed frames (including any +** that were already checkpointed before the function was called) or to -1 if the +** checkpoint could not run due to an error or because the database is not in +** WAL mode. ** -** All calls obtain an exclusive "checkpoint" lock on the database file. If +** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If ** any other process is running a checkpoint operation at the same time, the -** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a +** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a ** busy-handler configured, it will not be invoked in this case. ** -** The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the -** exclusive "writer" lock on the database file. If the writer lock cannot be +** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the +** exclusive "writer" lock on the database file. ^If the writer lock cannot be ** obtained immediately, and a busy-handler is configured, it is invoked and ** the writer lock retried until either the busy-handler returns 0 or the lock -** is successfully obtained. The busy-handler is also invoked while waiting for -** database readers as described above. If the busy-handler returns 0 before +** is successfully obtained. ^The busy-handler is also invoked while waiting for +** database readers as described above. ^If the busy-handler returns 0 before ** the writer lock is obtained or while waiting for database readers, the ** checkpoint operation proceeds from that point in the same way as ** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible -** without blocking any further. SQLITE_BUSY is returned in this case. +** without blocking any further. ^SQLITE_BUSY is returned in this case. ** -** If parameter zDb is NULL or points to a zero length string, then the -** specified operation is attempted on all WAL databases. In this case the -** values written to output parameters *pnLog and *pnCkpt are undefined. If +** ^If parameter zDb is NULL or points to a zero length string, then the +** specified operation is attempted on all WAL databases [attached] to +** [database connection] db. In this case the +** values written to output parameters *pnLog and *pnCkpt are undefined. ^If ** an SQLITE_BUSY error is encountered when processing one or more of the ** attached WAL databases, the operation is still attempted on any remaining -** attached databases and SQLITE_BUSY is returned to the caller. If any other +** attached databases and SQLITE_BUSY is returned at the end. ^If any other ** error occurs while processing an attached database, processing is abandoned -** and the error code returned to the caller immediately. If no error +** and the error code is returned to the caller immediately. ^If no error ** (SQLITE_BUSY or otherwise) is encountered while processing the attached ** databases, SQLITE_OK is returned. ** -** If database zDb is the name of an attached database that is not in WAL -** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If +** ^If database zDb is the name of an attached database that is not in WAL +** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If ** zDb is not NULL (or a zero length string) and is not the name of any ** attached database, SQLITE_ERROR is returned to the caller. +** +** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface +** from SQL. */ int sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ @@ -7346,17 +7354,18 @@ int sqlite3_wal_checkpoint_v2( ); /* -** CAPI3REF: Checkpoint operation parameters +** CAPI3REF: Checkpoint Mode Values +** KEYWORDS: {checkpoint mode} ** -** These constants can be used as the 3rd parameter to -** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()] -** documentation for additional information about the meaning and use of -** each of these values. +** These constants define all valid values for the "checkpoint mode" passed +** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface. +** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the +** meaning of each of these checkpoint modes. */ -#define SQLITE_CHECKPOINT_PASSIVE 0 -#define SQLITE_CHECKPOINT_FULL 1 -#define SQLITE_CHECKPOINT_RESTART 2 -#define SQLITE_CHECKPOINT_TRUNCATE 3 +#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible without blocking */ +#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers to finish, then checkpoint */ +#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but afterwards block for readers */ +#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate the WAL file */ /* ** CAPI3REF: Virtual Table Interface Configuration From 5b875311a3f99aae9f489bd30ffe9d9a2295d981 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Dec 2014 16:30:27 +0000 Subject: [PATCH 04/13] Futher tweaks to the sqlite3_wal_checkpoint_v2() documentation. FossilOrigin-Name: 7d284d047b0677fb4532df5aae06f5bad997f5e9 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 17 ++++++++++++----- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 97c3ddfce2..e54424a2c5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sto\sthe\sdocumentation\sfor\ssqlite3_wal_checkpoint_v2()\sand\srelated\ninterfaces,\sincluding\sadding\smany\srequirements\smarks. -D 2014-12-03T15:50:09.223 +C Futher\stweaks\sto\sthe\ssqlite3_wal_checkpoint_v2()\sdocumentation. +D 2014-12-03T16:30:27.252 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -230,7 +230,7 @@ F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 428165951748151e87a15295b7357221433e311b F src/shell.c 45d9c9bd7cde07845af957f2d849933b990773cf -F src/sqlite.h.in 7d33b94a32b013832b53ad86be543168f87f8eb7 +F src/sqlite.h.in 8c881e8d225167a878ed7d78a776b372304823a9 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d F src/sqliteInt.h c9e95b8fa9aee30d46387735c5be73fa58886e38 @@ -1223,7 +1223,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 edda2b9e7a15ed486de81b10dd9bacd39c571d3f -R d436425f6a4681c70264f79cf1bfa41d +P 1e212d9899387344fd62c7b6fbcc59ea885b6d7c +R e9765e182534ca03b14c9167cc7abee7 U drh -Z 881f6486595c3b0d62652277de190ac9 +Z 0ecdc98d536d1a5e17e6fc5f0fd27d98 diff --git a/manifest.uuid b/manifest.uuid index 74bdbd7193..b754092001 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1e212d9899387344fd62c7b6fbcc59ea885b6d7c \ No newline at end of file +7d284d047b0677fb4532df5aae06f5bad997f5e9 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 74c59f9257..09ba5038dd 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7302,12 +7302,14 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); ** ** ** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in -** the log file before returning or to -1 if the checkpoint could not run because +** the log file or to -1 if the checkpoint could not run because ** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not NULL, -** then *pnCkpt is set to the total number of checkpointed frames (including any -** that were already checkpointed before the function was called) or to -1 if the -** checkpoint could not run due to an error or because the database is not in -** WAL mode. +** then *pnCkpt is set to the total number of checkpointed frames in the log file +** (including any that were already checkpointed before the function was called) +** or to -1 if the checkpoint could not run due to an error or because the +** database is not in WAL mode. ^Note that upon successful completion of +** an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been truncated to +** zero bytes and so both *pnLog and *pnCkpt will be set to zero. ** ** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If ** any other process is running a checkpoint operation at the same time, the @@ -7342,6 +7344,11 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); ** zDb is not NULL (or a zero length string) and is not the name of any ** attached database, SQLITE_ERROR is returned to the caller. ** +** ^Unless it returns SQLITE_MISUSE, +** the sqlite3_wal_checkpoint_v2() interface +** sets the error information that is queried by +** [sqlite3_errcode()] and [sqlite3_errmsg()]. +** ** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface ** from SQL. */ From bb9a378df37dca03893bca2eff8a8182d87eb7db Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Dec 2014 18:32:47 +0000 Subject: [PATCH 05/13] Simplify the sqlite3_wal_checkpoint() documentation. Add some source code evidence marks. FossilOrigin-Name: 026c44ff2c092b14faa19985dd46873aeb8727dc --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/main.c | 6 +++++- src/sqlite.h.in | 30 ++++++++++++++---------------- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index e54424a2c5..350040c926 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Futher\stweaks\sto\sthe\ssqlite3_wal_checkpoint_v2()\sdocumentation. -D 2014-12-03T16:30:27.252 +C Simplify\sthe\ssqlite3_wal_checkpoint()\sdocumentation.\s\sAdd\ssome\ssource\scode\nevidence\smarks. +D 2014-12-03T18:32:47.200 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -195,7 +195,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770 F src/loadext.c de741e66e5ddc1598d904d7289239696e40ed994 -F src/main.c 34b895b5ebfc73cd690dcd9ac6d0eecb28ce729f +F src/main.c 84cc0fc4861bd2b06c286b38bf03bce604a0a66a F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c faf615aafd8be74a71494dfa027c113ea5c6615f @@ -230,7 +230,7 @@ F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 428165951748151e87a15295b7357221433e311b F src/shell.c 45d9c9bd7cde07845af957f2d849933b990773cf -F src/sqlite.h.in 8c881e8d225167a878ed7d78a776b372304823a9 +F src/sqlite.h.in dd3721b533e9608677203917aa18bb477aede13d F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d F src/sqliteInt.h c9e95b8fa9aee30d46387735c5be73fa58886e38 @@ -1223,7 +1223,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 1e212d9899387344fd62c7b6fbcc59ea885b6d7c -R e9765e182534ca03b14c9167cc7abee7 +P 7d284d047b0677fb4532df5aae06f5bad997f5e9 +R 0867d5ea698016229ebc4122ede6b104 U drh -Z 0ecdc98d536d1a5e17e6fc5f0fd27d98 +Z a6f1638a8e5b63a53571b9743845c380 diff --git a/manifest.uuid b/manifest.uuid index b754092001..0243d4de58 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7d284d047b0677fb4532df5aae06f5bad997f5e9 \ No newline at end of file +026c44ff2c092b14faa19985dd46873aeb8727dc \ No newline at end of file diff --git a/src/main.c b/src/main.c index 9ac3fde733..f7a0b1f7fd 100644 --- a/src/main.c +++ b/src/main.c @@ -1941,6 +1941,8 @@ int sqlite3_wal_checkpoint_v2( assert( SQLITE_CHECKPOINT_RESTART==2 ); assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); if( eModeSQLITE_CHECKPOINT_TRUNCATE ){ + /* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint + ** mode: */ return SQLITE_MISUSE; } @@ -1968,7 +1970,9 @@ int sqlite3_wal_checkpoint_v2( ** checkpointed. */ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ - return sqlite3_wal_checkpoint_v2(db, zDb, SQLITE_CHECKPOINT_PASSIVE, 0, 0); + /* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to + ** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */ + return sqlite3_wal_checkpoint_v2(db,zDb,SQLITE_CHECKPOINT_PASSIVE,0,0); } #ifndef SQLITE_OMIT_WAL diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 09ba5038dd..6c44ffefd6 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7241,22 +7241,21 @@ int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database ** -** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X -** on [database connection] D to be [checkpointed]. ^If X is NULL or an -** empty string, then a checkpoint is run on all databases of -** connection D. ^If the database connection D is not in -** [WAL | write-ahead log mode] then this interface is a harmless no-op. -** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a -** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint. -** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL -** or RESET or TRUNCATE checkpoint. +** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to +** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ ** -** ^The [wal_checkpoint pragma] can be used to invoke this interface -** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the -** [wal_autocheckpoint pragma] can be used to cause this interface to be -** run whenever the WAL reaches a certain size threshold. +** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the +** [write-ahead log] for database X on [database connection] D to be +** transferred into the database file and for the write-ahead log to +** be reset. See the [checkpointing] documentation for addition +** information. ** -** See also: [sqlite3_wal_checkpoint_v2()] +** This interface used to be the only way to cause a checkpoint to +** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()] +** interface was added. This interface is retained for backwards +** compatibility and as a convenience for applications that need to manually +** start a callback but which do not need the full power (and corresponding +** complication) of [sqlite3_wal_checkpoint_v2()]. */ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); @@ -7272,8 +7271,7 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); **
SQLITE_CHECKPOINT_PASSIVE
** ^Checkpoint as many frames as possible without waiting for any database ** readers or writers to finish, then sync the database file if all frames -** in the log were checkpointed. ^This mode is the same as calling -** [sqlite3_wal_checkpoint()]. ^The [sqlite3_busy_handler|busy-handler callback] +** in the log were checkpointed. ^The [sqlite3_busy_handler|busy-handler callback] ** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. ^On the other hand, ** passive mode might leave the checkpoint unfinished if there are concurrent ** readers or writers. From 86e166a77823c437c051540895c33380cc3d6229 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Dec 2014 19:08:00 +0000 Subject: [PATCH 06/13] Fix over-length comment lines in sqlite.h.in. No changes to code. FossilOrigin-Name: cbd357fd8c25c9c6043063710a3e2a89ff8b4575 --- manifest | 12 +++--- manifest.uuid | 2 +- src/sqlite.h.in | 107 +++++++++++++++++++++++++----------------------- 3 files changed, 63 insertions(+), 58 deletions(-) diff --git a/manifest b/manifest index 350040c926..7aebe335e2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplify\sthe\ssqlite3_wal_checkpoint()\sdocumentation.\s\sAdd\ssome\ssource\scode\nevidence\smarks. -D 2014-12-03T18:32:47.200 +C Fix\sover-length\scomment\slines\sin\ssqlite.h.in.\s\sNo\schanges\sto\scode. +D 2014-12-03T19:08:00.822 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -230,7 +230,7 @@ F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 428165951748151e87a15295b7357221433e311b F src/shell.c 45d9c9bd7cde07845af957f2d849933b990773cf -F src/sqlite.h.in dd3721b533e9608677203917aa18bb477aede13d +F src/sqlite.h.in f16487cd0b8f363faf08ad6009d5222e56d78b66 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d F src/sqliteInt.h c9e95b8fa9aee30d46387735c5be73fa58886e38 @@ -1223,7 +1223,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 7d284d047b0677fb4532df5aae06f5bad997f5e9 -R 0867d5ea698016229ebc4122ede6b104 +P 026c44ff2c092b14faa19985dd46873aeb8727dc +R 4ed5b70763e0743b0e322aa2df0b85da U drh -Z a6f1638a8e5b63a53571b9743845c380 +Z 6507e8b7c8c2131b9414f714dc2b9292 diff --git a/manifest.uuid b/manifest.uuid index 0243d4de58..21ea5c4e23 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -026c44ff2c092b14faa19985dd46873aeb8727dc \ No newline at end of file +cbd357fd8c25c9c6043063710a3e2a89ff8b4575 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 6c44ffefd6..6a04972559 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1519,8 +1519,8 @@ struct sqlite3_mem_methods { ** [[SQLITE_CONFIG_MEMSTATUS]]
SQLITE_CONFIG_MEMSTATUS
**
^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, ** interpreted as a boolean, which enables or disables the collection of -** memory allocation statistics. ^(When memory allocation statistics are disabled, the -** following SQLite interfaces become non-operational: +** memory allocation statistics. ^(When memory allocation statistics are +** disabled, the following SQLite interfaces become non-operational: **
    **
  • [sqlite3_memory_used()] **
  • [sqlite3_memory_highwater()] @@ -1561,7 +1561,8 @@ struct sqlite3_mem_methods { ** This configuration should not be used if an application-define page ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] ** configuration option. -** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned +** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to +** 8-byte aligned ** memory, the size of each page buffer (sz), and the number of pages (N). ** The sz argument should be the size of the largest database page ** (a power of two between 512 and 32768) plus some extra bytes for each @@ -1581,7 +1582,8 @@ struct sqlite3_mem_methods { ** [[SQLITE_CONFIG_HEAP]]
    SQLITE_CONFIG_HEAP
    **
    ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer ** that SQLite will use for all of its dynamic memory allocation needs -** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. +** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and +** [SQLITE_CONFIG_PAGECACHE]. ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns ** [SQLITE_ERROR] if invoked otherwise. @@ -1601,9 +1603,9 @@ struct sqlite3_mem_methods { ** [[SQLITE_CONFIG_MUTEX]]
    SQLITE_CONFIG_MUTEX
    **
    ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a ** pointer to an instance of the [sqlite3_mutex_methods] structure. -** The argument specifies alternative low-level mutex routines to be used in place -** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the -** content of the [sqlite3_mutex_methods] structure before the call to +** The argument specifies alternative low-level mutex routines to be used +** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of +** the content of the [sqlite3_mutex_methods] structure before the call to ** [sqlite3_config()] returns. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** the entire mutexing subsystem is omitted from the build and hence calls to @@ -1641,8 +1643,8 @@ struct sqlite3_mem_methods { ** ** [[SQLITE_CONFIG_GETPCACHE2]]
    SQLITE_CONFIG_GETPCACHE2
    **
    ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which -** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of the current -** page cache implementation into that object.)^
    +** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of +** the current page cache implementation into that object.)^
** ** [[SQLITE_CONFIG_LOG]]
SQLITE_CONFIG_LOG
**
The SQLITE_CONFIG_LOG option is used to configure the SQLite @@ -1667,8 +1669,9 @@ struct sqlite3_mem_methods { ** [[SQLITE_CONFIG_URI]]
SQLITE_CONFIG_URI **
^(The SQLITE_CONFIG_URI option takes a single argument of type int. ** If non-zero, then URI handling is globally enabled. If the parameter is zero, -** then URI handling is globally disabled.)^ ^If URI handling is globally enabled, -** all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or +** then URI handling is globally disabled.)^ ^If URI handling is globally +** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], +** [sqlite3_open16()] or ** specified as part of [ATTACH] commands are interpreted as URIs, regardless ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database ** connection is opened. ^If it is globally disabled, filenames are @@ -1730,8 +1733,8 @@ struct sqlite3_mem_methods { ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] **
SQLITE_CONFIG_WIN32_HEAPSIZE **
^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is -** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro defined. -** ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value +** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro +** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value ** that specifies the maximum size of the created heap. ** ** @@ -1739,8 +1742,8 @@ struct sqlite3_mem_methods { **
SQLITE_CONFIG_PCACHE_HDRSZ **
^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which ** is a pointer to an integer and writes into that integer the number of extra -** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. The amount of -** extra space required can change depending on the compiler, +** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. +** The amount of extra space required can change depending on the compiler, ** target platform, and SQLite version. ** */ @@ -2044,6 +2047,7 @@ int sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors +** KEYWORDS: {busy-handler callback} {busy handler} ** ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X ** that might be invoked with argument P whenever @@ -4515,7 +4519,8 @@ typedef void (*sqlite3_destructor_type)(void*); ** the [sqlite3_context] pointer, the results are undefined. */ void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_blob64(sqlite3_context*,const void*,sqlite3_uint64,void(*)(void*)); +void sqlite3_result_blob64(sqlite3_context*,const void*, + sqlite3_uint64,void(*)(void*)); void sqlite3_result_double(sqlite3_context*, double); void sqlite3_result_error(sqlite3_context*, const char*, int); void sqlite3_result_error16(sqlite3_context*, const void*, int); @@ -7262,19 +7267,19 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Checkpoint a database ** -** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint operation -** on database X of [database connection] D in mode M. Status information is -** written back into integers pointed to by L and C.)^ ^(The M parameter must be -** a valid [SQLITE_CHECKPOINT_PASSIVE|checkpoint mode]:)^ +** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint +** operation on database X of [database connection] D in mode M. Status +** information is written back into integers pointed to by L and C.)^ +** ^(The M parameter must be a valid [checkpoint mode]:)^ ** **
**
SQLITE_CHECKPOINT_PASSIVE
** ^Checkpoint as many frames as possible without waiting for any database ** readers or writers to finish, then sync the database file if all frames -** in the log were checkpointed. ^The [sqlite3_busy_handler|busy-handler callback] -** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. ^On the other hand, -** passive mode might leave the checkpoint unfinished if there are concurrent -** readers or writers. +** in the log were checkpointed. ^The [busy-handler callback] +** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. +** ^On the other hand, passive mode might leave the checkpoint unfinished +** if there are concurrent readers or writers. ** **
SQLITE_CHECKPOINT_FULL
** ^This mode blocks (it invokes the @@ -7287,27 +7292,27 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); **
SQLITE_CHECKPOINT_RESTART
** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition ** that after checkpointing the log file it blocks (calls the -** [sqlite3_busy_handler|busy-handler callback]) +** [busy-handler callback]) ** until all readers are reading from the database file only. ^This ensures ** that the next writer will restart the log file from the beginning. ** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new ** database writer attempts while it is pending, but does not impede readers. ** **
SQLITE_CHECKPOINT_TRUNCATE
-** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the addition -** that it also truncates the log file to zero bytes just prior to a successful -** return. +** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the +** addition that it also truncates the log file to zero bytes just prior +** to a successful return. **
** ** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in ** the log file or to -1 if the checkpoint could not run because -** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not NULL, -** then *pnCkpt is set to the total number of checkpointed frames in the log file -** (including any that were already checkpointed before the function was called) -** or to -1 if the checkpoint could not run due to an error or because the -** database is not in WAL mode. ^Note that upon successful completion of -** an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been truncated to -** zero bytes and so both *pnLog and *pnCkpt will be set to zero. +** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not +** NULL,then *pnCkpt is set to the total number of checkpointed frames in the +** log file (including any that were already checkpointed before the function +** was called) or to -1 if the checkpoint could not run due to an error or +** because the database is not in WAL mode. ^Note that upon successful +** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been +** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero. ** ** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If ** any other process is running a checkpoint operation at the same time, the @@ -7367,10 +7372,10 @@ int sqlite3_wal_checkpoint_v2( ** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the ** meaning of each of these checkpoint modes. */ -#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible without blocking */ -#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers to finish, then checkpoint */ -#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but afterwards block for readers */ -#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate the WAL file */ +#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ +#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ +#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */ +#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ /* ** CAPI3REF: Virtual Table Interface Configuration @@ -7469,12 +7474,12 @@ int sqlite3_vtab_on_conflict(sqlite3 *); ** **
** [[SQLITE_SCANSTAT_NLOOP]]
SQLITE_SCANSTAT_NLOOP
-**
^The [sqlite3_int64] variable pointed to by the T parameter will be set to the -** total number of times that the X-th loop has run.
+**
^The [sqlite3_int64] variable pointed to by the T parameter will be +** set to the total number of times that the X-th loop has run.
** ** [[SQLITE_SCANSTAT_NVISIT]]
SQLITE_SCANSTAT_NVISIT
-**
^The [sqlite3_int64] variable pointed to by the T parameter will be set to the -** total number of rows examined by all iterations of the X-th loop.
+**
^The [sqlite3_int64] variable pointed to by the T parameter will be set +** to the total number of rows examined by all iterations of the X-th loop.
** ** [[SQLITE_SCANSTAT_EST]]
SQLITE_SCANSTAT_EST
**
^The "double" variable pointed to by the T parameter will be set to the @@ -7485,14 +7490,14 @@ int sqlite3_vtab_on_conflict(sqlite3 *); ** be the NLOOP value for the current loop. ** ** [[SQLITE_SCANSTAT_NAME]]
SQLITE_SCANSTAT_NAME
-**
^The "const char *" variable pointed to by the T parameter will be set to -** a zero-terminated UTF-8 string containing the name of the index or table used -** for the X-th loop. +**
^The "const char *" variable pointed to by the T parameter will be set +** to a zero-terminated UTF-8 string containing the name of the index or table +** used for the X-th loop. ** ** [[SQLITE_SCANSTAT_EXPLAIN]]
SQLITE_SCANSTAT_EXPLAIN
-**
^The "const char *" variable pointed to by the T parameter will be set to -** a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] description -** for the X-th loop. +**
^The "const char *" variable pointed to by the T parameter will be set +** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] +** description for the X-th loop. ** ** [[SQLITE_SCANSTAT_SELECTID]]
SQLITE_SCANSTAT_SELECT
**
^The "int" variable pointed to by the T parameter will be set to the @@ -7515,8 +7520,8 @@ int sqlite3_vtab_on_conflict(sqlite3 *); ** Return status data for a single loop within query pStmt. ** ** The "iScanStatusOp" parameter determines which status information to return. -** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior of -** this interface is undefined. +** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior +** of this interface is undefined. ** ^The requested measurement is written into a variable pointed to by ** the "pOut" parameter. ** Parameter "idx" identifies the specific loop to retrieve statistics for. From dd90d7ee819b0a33d832ba3bc9bda8880b38b94a Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Dec 2014 19:25:41 +0000 Subject: [PATCH 07/13] Add evidence marks and assert()s used as evidence for checkpoint requirements. FossilOrigin-Name: b2da8afc7657266fbe8e683c6e50fe18216cbcf3 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/pager.c | 3 ++- src/wal.c | 45 ++++++++++++++++++++++++++++++--------------- 4 files changed, 40 insertions(+), 24 deletions(-) diff --git a/manifest b/manifest index 7aebe335e2..d4db2a78e1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sover-length\scomment\slines\sin\ssqlite.h.in.\s\sNo\schanges\sto\scode. -D 2014-12-03T19:08:00.822 +C Add\sevidence\smarks\sand\sassert()s\sused\sas\sevidence\sfor\scheckpoint\srequirements. +D 2014-12-03T19:25:41.425 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -216,7 +216,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c fb587121840f690101336879adfa6d0b2cd0e8c7 F src/os_win.c a9e500dd963fb1f67d7860e58b5772abe6123862 F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21 -F src/pager.c b8764f90c135482988268eec93d7f5cdb89d687a +F src/pager.c 7a5c5bc0e29b9b16834f5558a9d5d22bbae59a08 F src/pager.h d1eee3c3f741be247ce6d82752a178515fc8578b F src/parse.y 5dfead8aed90cb0c7c1115898ee2266804daff45 F src/pcache.c ace1b67632deeaa84859b4c16c27711dfb7db3d4 @@ -301,7 +301,7 @@ F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f F src/vdbesort.c 42c166f7ca78cb643c7f4e4bdfa83c59d363d1a6 F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 F src/vtab.c c08ec66f45919eaa726bf88aa53eb08379d607f9 -F src/wal.c e396f31038aa01b9de95584b703692716275aedc +F src/wal.c fc62ec9dc7dfa08dbe08801332230cf28130a159 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 F src/where.c a0b16f9d78321cb340a977287d19f826555c7d3b @@ -1223,7 +1223,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 026c44ff2c092b14faa19985dd46873aeb8727dc -R 4ed5b70763e0743b0e322aa2df0b85da +P cbd357fd8c25c9c6043063710a3e2a89ff8b4575 +R bf75abced12e09ba377b1add0a3ea61a U drh -Z 6507e8b7c8c2131b9414f714dc2b9292 +Z 0545aa7eaccc2c8413582324bb7aef19 diff --git a/manifest.uuid b/manifest.uuid index 21ea5c4e23..e429b5d1e1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cbd357fd8c25c9c6043063710a3e2a89ff8b4575 \ No newline at end of file +b2da8afc7657266fbe8e683c6e50fe18216cbcf3 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index e0ede87f07..a2ae9cc410 100644 --- a/src/pager.c +++ b/src/pager.c @@ -7075,7 +7075,8 @@ int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ int rc = SQLITE_OK; if( pPager->pWal ){ rc = sqlite3WalCheckpoint(pPager->pWal, eMode, - pPager->xBusyHandler, pPager->pBusyHandlerArg, + (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), + pPager->pBusyHandlerArg, pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, pnLog, pnCkpt ); diff --git a/src/wal.c b/src/wal.c index b88ece88b8..8ba5ce823f 100644 --- a/src/wal.c +++ b/src/wal.c @@ -1689,7 +1689,7 @@ static void walRestartHdr(Wal *pWal, u32 salt1){ static int walCheckpoint( Wal *pWal, /* Wal connection */ int eMode, /* One of PASSIVE, FULL or RESTART */ - int (*xBusyCall)(void*), /* Function to call when busy */ + int (*xBusy)(void*), /* Function to call when busy */ void *pBusyArg, /* Context argument for xBusyHandler */ int sync_flags, /* Flags for OsSync() (or 0) */ u8 *zBuf /* Temporary buffer to use */ @@ -1703,7 +1703,6 @@ static int walCheckpoint( u32 mxPage; /* Max database page to write */ int i; /* Loop counter */ volatile WalCkptInfo *pInfo; /* The checkpoint status information */ - int (*xBusy)(void*) = 0; /* Function to call when waiting for locks */ szPage = walPagesize(pWal); testcase( szPage<=32768 ); @@ -1718,7 +1717,9 @@ static int walCheckpoint( } assert( pIter ); - if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall; + /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked + ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ + assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); /* Compute in mxSafeFrame the index of the last frame of the WAL that is ** safe to write into the database. Frames beyond mxSafeFrame might @@ -2943,7 +2944,7 @@ int sqlite3WalFrames( */ int sqlite3WalCheckpoint( Wal *pWal, /* Wal connection */ - int eMode, /* PASSIVE, FULL or RESTART */ + int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ int (*xBusy)(void*), /* Function to call when busy */ void *pBusyArg, /* Context argument for xBusyHandler */ int sync_flags, /* Flags to sync db file with (or 0) */ @@ -2955,29 +2956,42 @@ int sqlite3WalCheckpoint( int rc; /* Return code */ int isChanged = 0; /* True if a new wal-index header is loaded */ int eMode2 = eMode; /* Mode to pass to walCheckpoint() */ + int (*xBusy2)(void*) = xBusy; /* Busy handler for eMode2 */ assert( pWal->ckptLock==0 ); assert( pWal->writeLock==0 ); + /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked + ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ + assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); + if( pWal->readOnly ) return SQLITE_READONLY; WALTRACE(("WAL%p: checkpoint begins\n", pWal)); + + /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive + ** "checkpoint" lock on the database file. */ rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); if( rc ){ - /* Usually this is SQLITE_BUSY meaning that another thread or process - ** is already running a checkpoint, or maybe a recovery. But it might - ** also be SQLITE_IOERR. */ + /* EVIDENCE-OF: R-10421-19736 If any other process is running a + ** checkpoint operation at the same time, the lock cannot be obtained and + ** SQLITE_BUSY is returned. + ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured, + ** it will not be invoked in this case. + */ + testcase( rc==SQLITE_BUSY ); + testcase( xBusy!=0 ); return rc; } pWal->ckptLock = 1; - /* If this is a blocking-checkpoint, then obtain the write-lock as well - ** to prevent any writers from running while the checkpoint is underway. - ** This has to be done before the call to walIndexReadHdr() below. + /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and + ** TRUNCATE modes also obtain the exclusive "writer" lock on the database + ** file. ** - ** If the writer lock cannot be obtained, then a passive checkpoint is - ** run instead. Since the checkpointer is not holding the writer lock, - ** there is no point in blocking waiting for any readers. Assuming no - ** other error occurs, this function will return SQLITE_BUSY to the caller. + ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained + ** immediately, and a busy-handler is configured, it is invoked and the + ** writer lock retried until either the busy-handler returns 0 or the + ** lock is successfully obtained. */ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); @@ -2985,6 +2999,7 @@ int sqlite3WalCheckpoint( pWal->writeLock = 1; }else if( rc==SQLITE_BUSY ){ eMode2 = SQLITE_CHECKPOINT_PASSIVE; + xBusy2 = 0; rc = SQLITE_OK; } } @@ -3002,7 +3017,7 @@ int sqlite3WalCheckpoint( if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ rc = SQLITE_CORRUPT_BKPT; }else{ - rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf); + rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); } /* If no error occurred, set the output variables. */ From a25165fa6852e71b3346e6d9457a50bd8332e0e8 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Dec 2014 04:50:59 +0000 Subject: [PATCH 08/13] Add an implementation mark and fix a comment describing the OP_Checkpoint opcode. FossilOrigin-Name: 7475b90c558157802b036162376fceacc1b9ab4a --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbe.c | 4 ++-- src/wal.c | 6 ++++-- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index d4db2a78e1..07b9de4c3d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sevidence\smarks\sand\sassert()s\sused\sas\sevidence\sfor\scheckpoint\srequirements. -D 2014-12-03T19:25:41.425 +C Add\san\simplementation\smark\sand\sfix\sa\scomment\sdescribing\sthe\sOP_Checkpoint\nopcode. +D 2014-12-04T04:50:59.682 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -291,7 +291,7 @@ F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c 3b627daa45c7308c1e36e3dbaa3f9ce7e5c7fa73 F src/vacuum.c 9b30ec729337dd012ed88d4c292922c8ef9cf00c -F src/vdbe.c 60217f3b8ab984b2e2bb9e3965276dd29e5efe5d +F src/vdbe.c 1a9e671c9cfc259e4d2affc71f7df4a4c00a842c F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3 F src/vdbeInt.h 9bb69ff2447c34b6ccc58b34ec35b615f86ead78 F src/vdbeapi.c 07acb615d1e4170e71fc1b0d087f3c53a1ad8e83 @@ -301,7 +301,7 @@ F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f F src/vdbesort.c 42c166f7ca78cb643c7f4e4bdfa83c59d363d1a6 F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 F src/vtab.c c08ec66f45919eaa726bf88aa53eb08379d607f9 -F src/wal.c fc62ec9dc7dfa08dbe08801332230cf28130a159 +F src/wal.c 847692349eb6e1fb8543dbc97e69ddbfa4cc7ea7 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 F src/where.c a0b16f9d78321cb340a977287d19f826555c7d3b @@ -1223,7 +1223,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 cbd357fd8c25c9c6043063710a3e2a89ff8b4575 -R bf75abced12e09ba377b1add0a3ea61a +P b2da8afc7657266fbe8e683c6e50fe18216cbcf3 +R f07d202428c907151b75d8e97783127c U drh -Z 0545aa7eaccc2c8413582324bb7aef19 +Z fc5c85b33aac137327215d4078c65229 diff --git a/manifest.uuid b/manifest.uuid index e429b5d1e1..8653d4ff34 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b2da8afc7657266fbe8e683c6e50fe18216cbcf3 \ No newline at end of file +7475b90c558157802b036162376fceacc1b9ab4a \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 7f661b42b1..3dac74dfd4 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5705,8 +5705,8 @@ case OP_AggFinal: { /* Opcode: Checkpoint P1 P2 P3 * * ** ** Checkpoint database P1. This is a no-op if P1 is not currently in -** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL -** or RESTART. Write 1 or 0 into mem[P3] if the checkpoint returns +** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL, +** RESTART, or TRUNCATE. Write 1 or 0 into mem[P3] if the checkpoint returns ** SQLITE_BUSY or not, respectively. Write the number of pages in the ** WAL after the checkpoint into mem[P3+1] and the number of pages ** in the WAL that have been checkpointed after the checkpoint diff --git a/src/wal.c b/src/wal.c index 8ba5ce823f..2b80c7a95e 100644 --- a/src/wal.c +++ b/src/wal.c @@ -1824,8 +1824,10 @@ static int walCheckpoint( rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); if( rc==SQLITE_OK ){ if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){ - /* If this is a TRUNCATE checkpoint, also truncate the wal file - ** to zero bytes in size on disk. + /* IMPLEMENTATION-OF: R-44699-57140 This mode works the same way as + ** SQLITE_CHECKPOINT_RESTART with the addition that it also + ** truncates the log file to zero bytes just prior to a + ** successful return. ** ** In theory, it might be safe to do this without updating the ** wal-index header in shared memory, as all subsequent reader or From 063970a15f317e156d4e2ee59059502fa326ee3b Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Dec 2014 14:01:39 +0000 Subject: [PATCH 09/13] Fix comment typos reported on the mailing list. No changes to code. FossilOrigin-Name: 93a71c9f058b58d11187293a1e8d5324d0911880 --- ext/fts3/fts3_porter.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/fts3/fts3_porter.c b/ext/fts3/fts3_porter.c index db175acdbb..8fb4c25daa 100644 --- a/ext/fts3/fts3_porter.c +++ b/ext/fts3/fts3_porter.c @@ -183,7 +183,7 @@ static int isVowel(const char *z){ ** by a consonant. ** ** In this routine z[] is in reverse order. So we are really looking -** for an instance of of a consonant followed by a vowel. +** for an instance of a consonant followed by a vowel. */ static int m_gt_0(const char *z){ while( isVowel(z) ){ z++; } diff --git a/manifest b/manifest index 07b9de4c3d..0404ece72e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\simplementation\smark\sand\sfix\sa\scomment\sdescribing\sthe\sOP_Checkpoint\nopcode. -D 2014-12-04T04:50:59.682 +C Fix\scomment\stypos\sreported\son\sthe\smailing\slist.\s\sNo\schanges\sto\scode. +D 2014-12-04T14:01:39.082 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -86,7 +86,7 @@ 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 -F ext/fts3/fts3_porter.c 7f8b4bf5af7c0f20f73b8e87e14fa9298f52e290 +F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009 F ext/fts3/fts3_snippet.c 51beb5c1498176fd9caccaf1c75b55cb803a985a F ext/fts3/fts3_term.c a521f75132f9a495bdca1bdd45949b3191c52763 F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038 @@ -230,7 +230,7 @@ F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 428165951748151e87a15295b7357221433e311b F src/shell.c 45d9c9bd7cde07845af957f2d849933b990773cf -F src/sqlite.h.in f16487cd0b8f363faf08ad6009d5222e56d78b66 +F src/sqlite.h.in acc4d70043f508311c6b9df277f7afe43506863c F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d F src/sqliteInt.h c9e95b8fa9aee30d46387735c5be73fa58886e38 @@ -1223,7 +1223,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 b2da8afc7657266fbe8e683c6e50fe18216cbcf3 -R f07d202428c907151b75d8e97783127c +P 7475b90c558157802b036162376fceacc1b9ab4a +R 397f3e2a10a22093a2e147bbeaeacc16 U drh -Z fc5c85b33aac137327215d4078c65229 +Z d46deb1796c364e4a21ca2d8fe0413fe diff --git a/manifest.uuid b/manifest.uuid index 8653d4ff34..53519b35c8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7475b90c558157802b036162376fceacc1b9ab4a \ No newline at end of file +93a71c9f058b58d11187293a1e8d5324d0911880 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 6a04972559..e6470042b5 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1216,7 +1216,7 @@ struct sqlite3_vfs { ** ** ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as -** was given no the corresponding lock. +** was given on the corresponding lock. ** ** The xShmLock method can transition between unlocked and SHARED or ** between unlocked and EXCLUSIVE. It cannot transition between SHARED From d8922052b27a3d2d62ccf3cf0ef1ea9b7272124d Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Dec 2014 15:02:03 +0000 Subject: [PATCH 10/13] Clarification of the meaning of the second parameter to the busy-handler callback. No changes to code. FossilOrigin-Name: 1e2bc484f8e7766a493bfeab04d82e50f37217b8 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 0404ece72e..806771a618 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scomment\stypos\sreported\son\sthe\smailing\slist.\s\sNo\schanges\sto\scode. -D 2014-12-04T14:01:39.082 +C Clarification\sof\sthe\smeaning\sof\sthe\ssecond\sparameter\sto\sthe\sbusy-handler\ncallback.\s\sNo\schanges\sto\scode. +D 2014-12-04T15:02:03.058 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -230,7 +230,7 @@ F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 428165951748151e87a15295b7357221433e311b F src/shell.c 45d9c9bd7cde07845af957f2d849933b990773cf -F src/sqlite.h.in acc4d70043f508311c6b9df277f7afe43506863c +F src/sqlite.h.in 6ec654324cb490ea3d8a7be28b8c7d37fe4ad282 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d F src/sqliteInt.h c9e95b8fa9aee30d46387735c5be73fa58886e38 @@ -1223,7 +1223,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 7475b90c558157802b036162376fceacc1b9ab4a -R 397f3e2a10a22093a2e147bbeaeacc16 +P 93a71c9f058b58d11187293a1e8d5324d0911880 +R 00727a6ee41feaad0f3193ccd0896958 U drh -Z d46deb1796c364e4a21ca2d8fe0413fe +Z c85dc24a7d66e411a436a86d655a083a diff --git a/manifest.uuid b/manifest.uuid index 53519b35c8..c993290f19 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -93a71c9f058b58d11187293a1e8d5324d0911880 \ No newline at end of file +1e2bc484f8e7766a493bfeab04d82e50f37217b8 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index e6470042b5..e889b2670f 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -2064,7 +2064,7 @@ int sqlite3_complete16(const void *sql); ** ^The first argument to the busy handler is a copy of the void* pointer which ** is the third argument to sqlite3_busy_handler(). ^The second argument to ** the busy handler callback is the number of times that the busy handler has -** been invoked for the same locking event. ^If the +** been invoked previously for the same locking event. ^If the ** busy callback returns 0, then no additional attempts are made to ** access the database and [SQLITE_BUSY] is returned ** to the application. From 72673a24e2d38c1699d911cfca0203f5e545f78c Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Dec 2014 16:27:17 +0000 Subject: [PATCH 11/13] If a table is the right operand of a LEFT JOIN, then any column of that table can be NULL even if that column as a NOT NULL constraint. Fix for ticket [6f2222d550f5b0ee7ed]. FossilOrigin-Name: 6f6fcbe4736b9468a495c684d5eebc8bfe5c566a --- manifest | 18 ++++++++--------- manifest.uuid | 2 +- src/expr.c | 3 ++- src/resolve.c | 4 ++++ src/sqliteInt.h | 3 ++- test/join5.test | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 72 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 806771a618..4f3131ec66 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Clarification\sof\sthe\smeaning\sof\sthe\ssecond\sparameter\sto\sthe\sbusy-handler\ncallback.\s\sNo\schanges\sto\scode. -D 2014-12-04T15:02:03.058 +C If\sa\stable\sis\sthe\sright\soperand\sof\sa\sLEFT\sJOIN,\sthen\sany\scolumn\sof\sthat\ntable\scan\sbe\sNULL\seven\sif\sthat\scolumn\sas\sa\sNOT\sNULL\sconstraint.\nFix\sfor\sticket\s[6f2222d550f5b0ee7ed]. +D 2014-12-04T16:27:17.993 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -182,7 +182,7 @@ F src/complete.c c4ba6e0626bb94bc77a0861735f3382fcf7cc818 F src/ctime.c df19848891c8a553c80e6f5a035e768280952d1a F src/date.c 93594514aae68de117ca4a2a0d6cc63eddf26744 F src/delete.c 0750b1eb4d96cd3fb2c798599a3a7c85e92f1417 -F src/expr.c 73de4c0da2eed6b149d40a05c589dfeb2c4a87a1 +F src/expr.c 00da3072f362b06f39ce4052baa1d4ce2bb36d1c F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c da985ae673efef2c712caef825a5d2edb087ead7 F src/func.c 6d3c4ebd72aa7923ce9b110a7dc15f9b8c548430 @@ -226,14 +226,14 @@ F src/pragma.c d54cdd40b63d608f2d95b7482c710690e3593a73 F src/prepare.c b7b7bf020bd4c962f7c8aed5a3c542c7dfe9f9c7 F src/printf.c 9e75a6a0b55bf61cfff7d7e19d89834a1b938236 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 -F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952 +F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 428165951748151e87a15295b7357221433e311b F src/shell.c 45d9c9bd7cde07845af957f2d849933b990773cf F src/sqlite.h.in 6ec654324cb490ea3d8a7be28b8c7d37fe4ad282 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d -F src/sqliteInt.h c9e95b8fa9aee30d46387735c5be73fa58886e38 +F src/sqliteInt.h 28049b803b74a7f73242a8226915ea00ebb1309f F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 81712116e826b0089bb221b018929536b2b5406f F src/table.c f142bba7903e93ca8d113a5b8877a108ad1a27dc @@ -670,7 +670,7 @@ F test/join.test 52d4d49f86d0cf46926672878c4eaf0da399104a F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 -F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe +F test/join5.test 5df23eba184f159ed9705a954957e765a10c141d F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577 F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1 @@ -1223,7 +1223,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 93a71c9f058b58d11187293a1e8d5324d0911880 -R 00727a6ee41feaad0f3193ccd0896958 +P 1e2bc484f8e7766a493bfeab04d82e50f37217b8 +R 6261b2c66938591ba7d193856851eb02 U drh -Z c85dc24a7d66e411a436a86d655a083a +Z d631884fbd9f9cb654155b89b69f5e28 diff --git a/manifest.uuid b/manifest.uuid index c993290f19..abaad9a04b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1e2bc484f8e7766a493bfeab04d82e50f37217b8 \ No newline at end of file +6f6fcbe4736b9468a495c684d5eebc8bfe5c566a \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index c28f196221..817975ab3a 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1414,7 +1414,8 @@ int sqlite3ExprCanBeNull(const Expr *p){ return 0; case TK_COLUMN: assert( p->pTab!=0 ); - return p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0; + return ExprHasProperty(p, EP_CanBeNull) || + (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); default: return 1; } diff --git a/src/resolve.c b/src/resolve.c index 8fb580b3a1..d4bd548c93 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -320,6 +320,10 @@ static int lookupName( if( pMatch ){ pExpr->iTable = pMatch->iCursor; pExpr->pTab = pMatch->pTab; + assert( (pMatch->jointype & JT_RIGHT)==0 ); /* RIGHT JOIN not (yet) supported */ + if( (pMatch->jointype & JT_LEFT)!=0 ){ + ExprSetProperty(pExpr, EP_CanBeNull); + } pSchema = pExpr->pTab->pSchema; } } /* if( pSrcList ) */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f3d6ce015e..3498517f25 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2015,7 +2015,7 @@ struct Expr { /* ** The following are the meanings of bits in the Expr.flags field. */ -#define EP_FromJoin 0x000001 /* Originated in ON or USING clause of a join */ +#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x000008 /* Expression contains one or more errors */ @@ -2035,6 +2035,7 @@ struct Expr { #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ #define EP_Constant 0x080000 /* Node is a constant */ +#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ /* ** These macros can be used to test, set, or clear bits in the diff --git a/test/join5.test b/test/join5.test index 45d8a31596..b0b0df4f9d 100644 --- a/test/join5.test +++ b/test/join5.test @@ -106,5 +106,59 @@ do_test join5-2.12 { execsql {SELECT * FROM xy LEFT JOIN ab ON NULL WHERE NULL} } {} +# Ticket https://www.sqlite.org/src/tktview/6f2222d550f5b0ee7ed37601 +# Incorrect output on a LEFT JOIN. +# +do_execsql_test join5-3.1 { + DROP TABLE IF EXISTS t1; + DROP TABLE IF EXISTS t2; + DROP TABLE IF EXISTS t3; + CREATE TABLE x1(a); + INSERT INTO x1 VALUES(1); + CREATE TABLE x2(b NOT NULL); + CREATE TABLE x3(c, d); + INSERT INTO x3 VALUES('a', NULL); + INSERT INTO x3 VALUES('b', NULL); + INSERT INTO x3 VALUES('c', NULL); + SELECT * FROM x1 LEFT JOIN x2 LEFT JOIN x3 ON x3.d = x2.b; +} {1 {} {} {}} +do_execsql_test join5-3.2 { + DROP TABLE IF EXISTS t1; + DROP TABLE IF EXISTS t2; + DROP TABLE IF EXISTS t3; + DROP TABLE IF EXISTS t4; + DROP TABLE IF EXISTS t5; + CREATE TABLE t1(x text NOT NULL, y text); + CREATE TABLE t2(u text NOT NULL, x text NOT NULL); + CREATE TABLE t3(w text NOT NULL, v text); + CREATE TABLE t4(w text NOT NULL, z text NOT NULL); + CREATE TABLE t5(z text NOT NULL, m text); + INSERT INTO t1 VALUES('f6d7661f-4efe-4c90-87b5-858e61cd178b',NULL); + INSERT INTO t1 VALUES('f6ea82c3-2cad-45ce-ae8f-3ddca4fb2f48',NULL); + INSERT INTO t1 VALUES('f6f47499-ecb4-474b-9a02-35be73c235e5',NULL); + INSERT INTO t1 VALUES('56f47499-ecb4-474b-9a02-35be73c235e5',NULL); + INSERT INTO t3 VALUES('007f2033-cb20-494c-b135-a1e4eb66130c', + 'f6d7661f-4efe-4c90-87b5-858e61cd178b'); + SELECT * + FROM t3 + INNER JOIN t1 ON t1.x= t3.v AND t1.y IS NULL + LEFT JOIN t4 ON t4.w = t3.w + LEFT JOIN t5 ON t5.z = t4.z + LEFT JOIN t2 ON t2.u = t5.m + LEFT JOIN t1 xyz ON xyz.y = t2.x; +} {007f2033-cb20-494c-b135-a1e4eb66130c f6d7661f-4efe-4c90-87b5-858e61cd178b f6d7661f-4efe-4c90-87b5-858e61cd178b {} {} {} {} {} {} {} {} {}} +do_execsql_test join5-3.3 { + DROP TABLE IF EXISTS x1; + DROP TABLE IF EXISTS x2; + DROP TABLE IF EXISTS x3; + CREATE TABLE x1(a); + INSERT INTO x1 VALUES(1); + CREATE TABLE x2(b NOT NULL); + CREATE TABLE x3(c, d); + INSERT INTO x3 VALUES('a', NULL); + INSERT INTO x3 VALUES('b', NULL); + INSERT INTO x3 VALUES('c', NULL); + SELECT * FROM x1 LEFT JOIN x2 JOIN x3 WHERE x3.d = x2.b; +} {} finish_test From 1d324880370ae70e7c9af187f59c3f3c351b0ef4 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Dec 2014 20:24:50 +0000 Subject: [PATCH 12/13] Performance enhancement for single-table queries with many OR-connected WHERE clause terms and multiple indexes with the same left-most columns. FossilOrigin-Name: 1461d543ac8a3e4a54405067893146c74576bb4e --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 5 ++--- test/whereJ.test | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 4f3131ec66..ddc85c1040 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\sa\stable\sis\sthe\sright\soperand\sof\sa\sLEFT\sJOIN,\sthen\sany\scolumn\sof\sthat\ntable\scan\sbe\sNULL\seven\sif\sthat\scolumn\sas\sa\sNOT\sNULL\sconstraint.\nFix\sfor\sticket\s[6f2222d550f5b0ee7ed]. -D 2014-12-04T16:27:17.993 +C Performance\senhancement\sfor\ssingle-table\squeries\swith\smany\sOR-connected\nWHERE\sclause\sterms\sand\smultiple\sindexes\swith\sthe\ssame\sleft-most\scolumns. +D 2014-12-04T20:24:50.938 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -304,7 +304,7 @@ F src/vtab.c c08ec66f45919eaa726bf88aa53eb08379d607f9 F src/wal.c 847692349eb6e1fb8543dbc97e69ddbfa4cc7ea7 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 -F src/where.c a0b16f9d78321cb340a977287d19f826555c7d3b +F src/where.c d67fe69dd1bb32ad3d488a8c5bc803a29814f357 F src/whereInt.h d3633e9b592103241b74b0ec76185f3e5b8b62e0 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1154,7 +1154,7 @@ F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3 F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622 -F test/whereJ.test 63599653dfefe4e74ebb358db753417fe0aa8a49 +F test/whereJ.test 55a3221706a7ab706293f17cc8f96da563bf0767 F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c @@ -1223,7 +1223,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 1e2bc484f8e7766a493bfeab04d82e50f37217b8 -R 6261b2c66938591ba7d193856851eb02 +P 6f6fcbe4736b9468a495c684d5eebc8bfe5c566a +R 5428d48e129f2db3029319e68ae21b70 U drh -Z d631884fbd9f9cb654155b89b69f5e28 +Z 008a44be7133b3164f9b1ac313df9791 diff --git a/manifest.uuid b/manifest.uuid index abaad9a04b..b913e108c5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6f6fcbe4736b9468a495c684d5eebc8bfe5c566a \ No newline at end of file +1461d543ac8a3e4a54405067893146c74576bb4e \ No newline at end of file diff --git a/src/where.c b/src/where.c index 277c8833e8..bda2a801ea 100644 --- a/src/where.c +++ b/src/where.c @@ -3591,10 +3591,9 @@ static Bitmask codeOneLoopStart( Expr *pExpr = pWC->a[iTerm].pExpr; if( &pWC->a[iTerm] == pTerm ) continue; if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; - testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); - testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); - if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue; + if( (pWC->a[iTerm].wtFlags & TERM_VIRTUAL)!=0 ) continue; if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; + testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); pExpr = sqlite3ExprDup(db, pExpr, 0); pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); } diff --git a/test/whereJ.test b/test/whereJ.test index 8431c3a4b0..48924d0fcf 100644 --- a/test/whereJ.test +++ b/test/whereJ.test @@ -640,4 +640,39 @@ do_execsql_test 4.2 { } {/.*SCAN TABLE cx.*SEARCH TABLE px.*SEARCH TABLE le.*/} +# The following test is derived from a performance problem reported from +# the field. Notice the multiple indexes with the same initial tables, +# and the unusual WHERE clause terms. +# +do_test 5.1 { + set res [db eval { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a,b,c,d,e,f,g,h); + CREATE INDEX t1abc ON t1(a,b,c); + CREATE INDEX t1abe ON t1(a,b,e); + CREATE INDEX t1abf ON t1(a,b,f); + ANALYZE; + DROP TABLE IF EXISTS sqlite_stat4; + DROP TABLE IF EXISTS sqlite_stat3; + DELETE FROM sqlite_stat1; + INSERT INTO sqlite_stat1(tbl,idx,stat) + VALUES('t1','t1abc','2000000 8000 1600 800'), + ('t1','t1abe','2000000 8000 1600 150'), + ('t1','t1abf','2000000 8000 1600 150'); + ANALYZE sqlite_master; + + EXPLAIN QUERY PLAN + SELECT * FROM t1 + WHERE (a=1 OR a=2) + AND (b=3 OR b=4) + AND (d>=5 AND d<=5) + AND ((e>=7 AND e<=7) OR (f>=8 AND f<=8)) + AND g>0; + }] +} {~/ANY/} +do_test 5.2 {set res} {/USING INDEX t1abe/} +do_test 5.3 {set res} {/USING INDEX t1abf/} + + + finish_test From dea7d70d1b9516956a7550d0ffde1b4560fc77ca Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Dec 2014 21:54:58 +0000 Subject: [PATCH 13/13] Make sure that a DISTINCT query with an ORDER BY works correctly even if it uses a descending index. Fix for ticket [c5ea805691bfc4204b1cb9e]. FossilOrigin-Name: 0d3aef97ebddf422b8bdcbc5878970c6129e3f54 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/select.c | 3 +-- test/distinct.test | 30 ++++++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index ddc85c1040..e3691737da 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\senhancement\sfor\ssingle-table\squeries\swith\smany\sOR-connected\nWHERE\sclause\sterms\sand\smultiple\sindexes\swith\sthe\ssame\sleft-most\scolumns. -D 2014-12-04T20:24:50.938 +C Make\ssure\sthat\sa\sDISTINCT\squery\swith\san\sORDER\sBY\sworks\scorrectly\seven\sif\nit\suses\sa\sdescending\sindex.\s\sFix\sfor\sticket\s[c5ea805691bfc4204b1cb9e]. +D 2014-12-04T21:54:58.307 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -228,7 +228,7 @@ F src/printf.c 9e75a6a0b55bf61cfff7d7e19d89834a1b938236 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c 428165951748151e87a15295b7357221433e311b +F src/select.c f377fb8a5c73c10678ea74f3400f7913943e3d75 F src/shell.c 45d9c9bd7cde07845af957f2d849933b990773cf F src/sqlite.h.in 6ec654324cb490ea3d8a7be28b8c7d37fe4ad282 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad @@ -454,7 +454,7 @@ F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240 F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2 F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e -F test/distinct.test 086e70c765f172e8974e9f83b9ac5ca03c154e77 +F test/distinct.test 175d49ee783febaf368192dfe7f5afbc68910230 F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376 F test/e_blobbytes.test 9bea1d3e2b20f3010b04abba58f6ba172301f49f F test/e_blobclose.test df756753f571bc30e42e3a6cba2807576e49e716 @@ -1223,7 +1223,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 6f6fcbe4736b9468a495c684d5eebc8bfe5c566a -R 5428d48e129f2db3029319e68ae21b70 +P 1461d543ac8a3e4a54405067893146c74576bb4e +R fc5b0159564faa200a156d134ab758df U drh -Z 008a44be7133b3164f9b1ac313df9791 +Z 018f1b0eb45096a13f52fc7d70ef2bc6 diff --git a/manifest.uuid b/manifest.uuid index b913e108c5..7416b1cda3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1461d543ac8a3e4a54405067893146c74576bb4e \ No newline at end of file +0d3aef97ebddf422b8bdcbc5878970c6129e3f54 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 3b422f1100..070ac00410 100644 --- a/src/select.c +++ b/src/select.c @@ -4829,7 +4829,7 @@ int sqlite3Select( ** ** is transformed to: ** - ** SELECT xyz FROM ... GROUP BY xyz + ** SELECT xyz FROM ... GROUP BY xyz ORDER BY xyz ** ** The second form is preferred as a single index (or temp-table) may be ** used for both the ORDER BY and DISTINCT processing. As originally @@ -4842,7 +4842,6 @@ int sqlite3Select( p->selFlags &= ~SF_Distinct; p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0); pGroupBy = p->pGroupBy; - sSort.pOrderBy = 0; /* Notice that even thought SF_Distinct has been cleared from p->selFlags, ** the sDistinct.isTnct is still set. Hence, isTnct represents the ** original setting of the SF_Distinct flag, not the current setting */ diff --git a/test/distinct.test b/test/distinct.test index 78c2c1df36..2fb90dc3e3 100644 --- a/test/distinct.test +++ b/test/distinct.test @@ -222,4 +222,34 @@ do_execsql_test 4.1 { SELECT quote(x) FROM t2 ORDER BY 1; } {'xyzzy' X'0000000000'} +#---------------------------------------------------------------------------- +# Ticket [c5ea805691bfc4204b1cb9e9aa0103bd48bc7d34] (2014-12-04) +# Make sure that DISTINCT works together with ORDER BY and descending +# indexes. +# +do_execsql_test 5.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x); + INSERT INTO t1(x) VALUES(3),(1),(5),(2),(6),(4),(5),(1),(3); + CREATE INDEX t1x ON t1(x DESC); + SELECT DISTINCT x FROM t1 ORDER BY x ASC; +} {1 2 3 4 5 6} +do_execsql_test 5.2 { + SELECT DISTINCT x FROM t1 ORDER BY x DESC; +} {6 5 4 3 2 1} +do_execsql_test 5.3 { + SELECT DISTINCT x FROM t1 ORDER BY x; +} {1 2 3 4 5 6} +do_execsql_test 5.4 { + DROP INDEX t1x; + CREATE INDEX t1x ON t1(x ASC); + SELECT DISTINCT x FROM t1 ORDER BY x ASC; +} {1 2 3 4 5 6} +do_execsql_test 5.5 { + SELECT DISTINCT x FROM t1 ORDER BY x DESC; +} {6 5 4 3 2 1} +do_execsql_test 5.6 { + SELECT DISTINCT x FROM t1 ORDER BY x; +} {1 2 3 4 5 6} + finish_test