Merge the latest trunk changes into the sessions branch.

FossilOrigin-Name: 83705e90a54bad462a5b7fbca70cc129998f871c
This commit is contained in:
drh 2011-04-09 18:07:51 +00:00
commit 9e3fbc0157
28 changed files with 480 additions and 259 deletions

View File

@ -1,5 +1,5 @@
C Add\sa\smissing\s"extern\sC"\sterminator\sto\sthe\send\sof\ssqlite3session.h.
D 2011-04-06T23:40:28.737
C Merge\sthe\slatest\strunk\schanges\sinto\sthe\ssessions\sbranch.
D 2011-04-09T18:07:51.034
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -124,19 +124,19 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c 280f5c04b11b492703a342222b3de0a999445280
F src/analyze.c a1ad9f4d8aac055c4a4bbd99073e2e78fe66129c
F src/attach.c 7cae2cf0c14762ce14c074a860ec52890a973a56
F src/analyze.c a425d62e8fa9ebcb4359ab84ff0c62c6563d2e2a
F src/attach.c 7f97ca76ef2453440170929531a9c778267c0830
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c b7529a6691f0fd534ae8ff622203c46a7f1b626b
F src/backup.c 986c15232757f2873dff35ee3b35cbf935fc573c
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 4fcad108b612a4d33dac568b11d26e4d38ccbe35
F src/btree.c 6a9164af8a2ef4612ee30b253635a9bd8e5e1b1b
F src/btree.h 11753dd46597a20702bca8746cb4caa4486a82b5
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
F src/build.c b7c993274ee2a029937b0bc4815bdef80b330017
F src/build.c f09c46c66a1e7668c6ee25c9a2518aaa6842044c
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01
F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4
F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b
F src/delete.c ad9fa1cbf91a83ec6990d0aecb7e21cd5ff07e71
F src/expr.c e3cf0957c6b8faaaf7386a3bc69e53c0dc9705be
@ -147,12 +147,12 @@ F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c ef33ce1522a77f6d8077f0bdb6ab22d306900950
F src/insert.c 8796ca3f9209b699cb8120fc44290fc97ac26abe
F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
F src/loadext.c 3ae0d52da013a6326310655be6473fd472347b85
F src/main.c 37608a8346394e52690368742d734f7b01330aaa
F src/main.c 8b97db74cb876bf34ca4fb3720b18e4ffdcf9fd5
F src/malloc.c 788f2ed928786dfe305b6783d551d6b1a9080976
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
@ -180,16 +180,16 @@ F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
F src/pcache1.c d548e31beafa792d1994b663a29a5303569efc4e
F src/pragma.c 49c90ab27a4339d4b5bc0b03c08cbcf20ed8d454
F src/prepare.c 206e1f06479fb5f756592bded468bd3ece3f41d4
F src/prepare.c e64261559a3187698a3e7e6c8b001a4f4f98dab4
F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c 649a6f10f7eb7b52a5a28847773cb9968a828ae8
F src/shell.c a73b30067ec15f116d5d0c28880179898fbe3d0b
F src/sqlite.h.in 235300cdca517ce148385d3ab816e7e8cf9e1ff3
F src/shell.c 9c8389796764f65d4506bcd614ac8061f4160d5c
F src/sqlite.h.in 9cff46ef60540f044c1b665db606aa63ba67048f
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
F src/sqliteInt.h 0873a71099f763cdf24cfabf04a237ad100e20d0
F src/sqliteInt.h 9a29e5bb82f3abef6b4af91e18d637050fa3c883
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@ -207,7 +207,7 @@ F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad
F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e
F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2
F src/test_config.c 3050df9faf023fb52937f7e9998004c2415d4122
F src/test_config.c 25a4128c2dc9e1dbebafcb7e8c61d45f09f7fbc3
F src/test_demovfs.c 31050680fa6925b4f677cfd4fa965b5f19195e50
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5
@ -239,7 +239,7 @@ F src/test_vfstrace.c 2265c9895f350c8d3c39b079998fbe7481505cc1
F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
F src/trigger.c d5bc8b9ffa2b54569ce635084765c6e41aa9d174
F src/trigger.c 144cc18bb701f3286484aae4292a9531f09278c8
F src/update.c 3f3f3bb734a0da1dffd0ed33e504642b35ed3605
F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60
F src/util.c cd997077bad039efc0597eb027c929658f93c018
@ -256,7 +256,7 @@ F src/vtab.c b0abc931f95af94c9ffdf9f747eb191cda953123
F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794
F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c 71e6808f74b9df913b5cdf242419b0edaf768310
F src/where.c 55403ce19c506be6a321c7f129aff693d6103db5
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 51756962d522e474338e9b2ebb26e7364d4aa125
@ -269,9 +269,9 @@ F test/analyze.test c8cb89e8736336f1f0646c8123e6028a14c7b55e
F test/analyze2.test 8f2b1534d43f5547ce9a6b736c021d4192c75be3
F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b
F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045
F test/analyze5.test adc89b92fc9fee5ca1cb0bc8512f3206ad0fe5aa
F test/analyze5.test 1de8d66b11aae5a1453aa042d62e834a476bac9c
F test/analyze6.test c125622a813325bba1b4999040ddc213773c2290
F test/analyze7.test 9cbca440bebc5142a875ad23947797ff52f7b37c
F test/analyze7.test 5508e7828164ea0b518ed219bed7320a481863d4
F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
@ -280,7 +280,7 @@ F test/async5.test f3592d79c84d6e83a5f50d3fd500445f7d97dfdf
F test/attach.test 2bb09073d7d5499127db00f50780766dcea913e1
F test/attach2.test a295d2d7061adcee5884ef4a93c7c96a82765437
F test/attach3.test bd9830bc3a0d22ed1310c9bff6896927937017dc
F test/attach4.test d58859e62e0a70f17481eed01bf94995f72fea7f
F test/attach4.test 31f9eb0ca7bdbc393cc4657b877903a226a83d4b
F test/attachmalloc.test 1d5b821a676f7bf0b00d87cc106b78966789ba57
F test/auth.test b047105c32da7db70b842fd24056723125ecc2ff
F test/auth2.test 270baddc8b9c273682760cffba6739d907bd2882
@ -290,7 +290,7 @@ F test/autoindex1.test 860fc83f4fefb0c68ad062afc3ff43faa1534fc4
F test/autovacuum.test bb7c0885e6f8f1d633045de48f2b66082162766d
F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
F test/backcompat.test 541314d69ec9db3e03630b7616696ddc5048efb1
F test/backcompat.test 0f23ff8d516acdf42f3d866a66d85306de2d02bc
F test/backup.test 004d3b78bffd990741ab50133ed4347c25c172b1
F test/backup2.test b7c69f937c912e85ac8a5dbd1e1cf290302b2d49
F test/backup_ioerr.test 1f012e692f42c0442ae652443258f70e9f20fa38
@ -397,6 +397,7 @@ F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
F test/exclusive.test 53e1841b422e554cecf0160f937c473d6d0e3062
F test/exclusive2.test 343d55130c12c67b8bf10407acec043a6c26c86b
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 81363f6982ea49dfd820a50845466390e60a4a0c
F test/expr.test 19e8ac40313e2282a47b586d11c4892040990d3a
F test/fallocate.test 43dc34b8c24be6baffadc3b4401ee15710ce83c6
F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e
@ -503,7 +504,7 @@ F test/incrblob3.test aedbb35ea1b6450c33b98f2b6ed98e5020be8dc7
F test/incrblob_err.test c577c91d4ed9e8336cdb188b15d6ee2a6fe9604e
F test/incrblobfault.test 917c0292224c64a56ef7215fd633a3a82f805be0
F test/incrvacuum.test 453d1e490d8f5ad2c9b3a54282a0690d6ae56462
F test/incrvacuum2.test 9e22a794899c91b7d8c8e12eaacac8df249faafe
F test/incrvacuum2.test ae04573b73ad52179f56e194fff0fbe43b509d23
F test/incrvacuum_ioerr.test 57d2f5777ab13fa03b87b262a4ea1bad5cfc0291
F test/index.test b5429732b3b983fa810e3ac867d7ca85dae35097
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
@ -602,7 +603,6 @@ F test/notify2.test 195a467e021f74197be2c4fb02d6dee644b8d8db
F test/notify3.test d60923e186e0900f4812a845fcdfd8eea096e33a
F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
F test/null.test a8b09b8ed87852742343b33441a9240022108993
F test/omitunique.test bbb2ec4345d9125d9ee21cd9488d97a163020d5f
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
F test/oserror.test 498d8337e9d15543eb7b004fef8594bf204ff43c
F test/pager1.test d8672fd0af5f4f9b99b06283d00f01547809bebe
@ -702,9 +702,9 @@ F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
F test/thread004.test f51dfc3936184aaf73ee85f315224baad272a87f
F test/thread005.test bf5c374ca65dd89fd56c8fe511ccfb46875bda5e
F test/thread1.test 862dd006d189e8b0946935db17399dcac2f8ef91
F test/thread2.test e08034b83fe9693ade77049732518e5b3d2d700d
F test/thread_common.tcl 2aa6f2fdcd4d6e461169c3e5ca098eebf643b863
F test/thread1.test df115faa10a4ba1d456e9d4d9ec165016903eae4
F test/thread2.test f35d2106452b77523b3a2b7d1dcde2e5ee8f9e46
F test/thread_common.tcl 334639cadcb9f912bf82aa73f49efd5282e6cadd
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
F test/threadtest2.c ace893054fa134af3fc8d6e7cfecddb8e3acefb9
F test/threadtest3.c 0ed13e09690f6204d7455fac3b0e8ece490f6eef
@ -871,7 +871,7 @@ F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
F test/wal.test bac92a13276ce9b65d3d5c9ff3411d24c795826c
F test/wal.test 5617ad308bfdb8a8885220d8a261a6096a8d7e57
F test/wal2.test e561a8c6fdd1c2cd1876f3e39757934e7b7361f8
F test/wal3.test 5c396cc22497244d627306f4c1d360167353f8dd
F test/wal4.test 3404b048fa5e10605facaf70384e6d2943412e30
@ -937,7 +937,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 7b7c8d366c51e89aefc6efc9dcffe3f62c7e1d25
R 35a03a7ffb44f2b52e4ebaca11ffd944
P 29090b695a95feaba1b74f9894997083a060263a 1c2f0f8477bcf251fe874a2cfae4d7a403cb88ff
R a40e5f171b5b8b5d469c7b8e3eba3790
U drh
Z efe884ab8aaf8c7e1eec316d7a2437f1
Z 7e220d1108384435c7d9af48b2056273

View File

@ -1 +1 @@
29090b695a95feaba1b74f9894997083a060263a
83705e90a54bad462a5b7fbca70cc129998f871c

View File

@ -548,6 +548,10 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
if( pIndex==0 ) break;
pIndex->aiRowEst[i] = v;
if( *z==' ' ) z++;
if( memcmp(z, "unordered", 10)==0 ){
pIndex->bUnordered = 1;
break;
}
}
return 0;
}

View File

@ -176,7 +176,9 @@ static void attachFunc(
case SQLITE_NULL:
/* No key specified. Use the key from the main database */
sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
if( nKey>0 || sqlite3BtreeGetReserve(db->aDb[0].pBt)>0 ){
rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
}
break;
}
}

View File

@ -219,6 +219,10 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
const int nCopy = MIN(nSrcPgsz, nDestPgsz);
const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
#ifdef SQLITE_HAS_CODEC
int nSrcReserve = sqlite3BtreeGetReserve(p->pSrc);
int nDestReserve = sqlite3BtreeGetReserve(p->pDest);
#endif
int rc = SQLITE_OK;
i64 iOff;
@ -237,11 +241,22 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
#ifdef SQLITE_HAS_CODEC
/* Backup is not possible if the page size of the destination is changing
** a a codec is in use.
** and a codec is in use.
*/
if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){
rc = SQLITE_READONLY;
}
/* Backup is not possible if the number of bytes of reserve space differ
** between source and destination. If there is a difference, try to
** fix the destination to agree with the source. If that is not possible,
** then the backup cannot proceed.
*/
if( nSrcReserve!=nDestReserve ){
u32 newPgsz = nSrcPgsz;
rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve);
if( rc==SQLITE_OK && newPgsz!=nSrcPgsz ) rc = SQLITE_READONLY;
}
#endif
/* This loop runs once for each destination page spanned by the source
@ -607,7 +622,11 @@ void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){
** has been modified by a transaction on the source pager. Copy
** the new data into the backup.
*/
int rc = backupOnePage(p, iPage, aData);
int rc;
assert( p->pDestDb );
sqlite3_mutex_enter(p->pDestDb->mutex);
rc = backupOnePage(p, iPage, aData);
sqlite3_mutex_leave(p->pDestDb->mutex);
assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
if( rc!=SQLITE_OK ){
p->rc = rc;

View File

@ -4819,7 +4819,7 @@ static int allocateBtreePage(
goto end_allocate_page;
}
k = get4byte(&pTrunk->aData[4]);
k = get4byte(&pTrunk->aData[4]); /* # of leaves on this trunk page */
if( k==0 && !searchList ){
/* The trunk has no leaves and the list is not being searched.
** So extract the trunk page itself and use it as the newly
@ -4904,10 +4904,6 @@ static int allocateBtreePage(
u32 closest;
Pgno iPage;
unsigned char *aData = pTrunk->aData;
rc = sqlite3PagerWrite(pTrunk->pDbPage);
if( rc ){
goto end_allocate_page;
}
if( nearby>0 ){
u32 i;
int dist;
@ -4937,11 +4933,12 @@ static int allocateBtreePage(
TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
": %d more free pages\n",
*pPgno, closest+1, k, pTrunk->pgno, n-1));
rc = sqlite3PagerWrite(pTrunk->pDbPage);
if( rc ) goto end_allocate_page;
if( closest<k-1 ){
memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
}
put4byte(&aData[4], k-1);
assert( sqlite3PagerIswriteable(pTrunk->pDbPage) );
noContent = !btreeGetHasContent(pBt, *pPgno);
rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
if( rc==SQLITE_OK ){
@ -5010,6 +5007,7 @@ end_allocate_page:
}else{
*ppPage = 0;
}
assert( rc!=SQLITE_OK || sqlite3PagerIswriteable((*ppPage)->pDbPage) );
return rc;
}

View File

@ -813,6 +813,9 @@ void sqlite3StartTable(
if( pTable ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "table %T already exists", pName);
}else{
assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
}
goto begin_table_error;
}
@ -2000,6 +2003,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
if( noErr ) db->suppressErr--;
if( pTab==0 ){
if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
goto exit_drop_table;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@ -2518,6 +2522,9 @@ Index *sqlite3CreateIndex(
if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){
if( !ifNotExist ){
sqlite3ErrorMsg(pParse, "index %s already exists", zName);
}else{
assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
}
goto exit_create_index;
}
@ -2911,6 +2918,8 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
if( pIndex==0 ){
if( !ifExists ){
sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0);
}else{
sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
}
pParse->checkSchema = 1;
goto exit_drop_index;
@ -3500,6 +3509,21 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
}
}
/*
** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each
** attached database. Otherwise, invoke it for the database named zDb only.
*/
void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){
sqlite3 *db = pParse->db;
int i;
for(i=0; i<db->nDb; i++){
Db *pDb = &db->aDb[i];
if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zName)) ){
sqlite3CodeVerifySchema(pParse, i);
}
}
}
/*
** Generate VDBE code that prepares for doing an operation that
** might change the database.

View File

@ -302,9 +302,6 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
"OMIT_TRUNCATE_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_UNIQUE_ENFORCEMENT
"OMIT_UNIQUE_ENFORCEMENT",
#endif
#ifdef SQLITE_OMIT_UTF16
"OMIT_UTF16",
#endif

View File

@ -1322,9 +1322,8 @@ void sqlite3GenerateConstraintChecks(
*/
for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
int regIdx;
#ifndef SQLITE_OMIT_UNIQUE_ENFORCEMENT
int regR;
#endif
if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */
/* Create a key for accessing the index entry */
@ -1342,11 +1341,6 @@ void sqlite3GenerateConstraintChecks(
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT);
sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);
#ifdef SQLITE_OMIT_UNIQUE_ENFORCEMENT
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
continue; /* Treat pIdx as if it is not a UNIQUE index */
#else
/* Find out what action to take in case there is an indexing conflict */
onError = pIdx->onError;
if( onError==OE_None ){
@ -1420,7 +1414,6 @@ void sqlite3GenerateConstraintChecks(
}
sqlite3VdbeJumpHere(v, j3);
sqlite3ReleaseTempReg(pParse, regR);
#endif
}
if( pbMayReplace ){

View File

@ -515,7 +515,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
va_start(ap, op);
switch( op ){
case SQLITE_DBCONFIG_LOOKASIDE: {
void *pBuf = va_arg(ap, void*); /* IMP: R-21112-12275 */
void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */
int sz = va_arg(ap, int); /* IMP: R-47871-25994 */
int cnt = va_arg(ap, int); /* IMP: R-04460-53386 */
rc = setupLookaside(db, pBuf, sz, cnt);

View File

@ -34,7 +34,7 @@ static void corruptSchema(
"%s - %s", *pData->pzErrMsg, zExtra);
}
}
pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT;
pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT;
}
/*

View File

@ -2199,7 +2199,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
/* convert testctrl text option to value. allow any unique prefix
** of the option name, or a numerical value. */
n = strlen(azArg[1]);
n = strlen30(azArg[1]);
for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){
if( testctrl<0 ){

View File

@ -727,7 +727,7 @@ struct sqlite3_io_methods {
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
** VFSes do not need this signal and should silently ignore this opcode.
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specilized VFSes
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@ -1309,7 +1309,7 @@ struct sqlite3_mem_methods {
** <dt>SQLITE_CONFIG_SCRATCH</dt>
** <dd> ^This option specifies a static memory buffer that SQLite can use for
** scratch memory. There are three arguments: A pointer an 8-byte
** aligned memory buffer from which the scrach allocations will be
** aligned memory buffer from which the scratch allocations will be
** drawn, the size of each scratch allocation (sz),
** and the maximum number of scratch allocations (N). The sz
** argument must be a multiple of 16.
@ -1461,7 +1461,7 @@ struct sqlite3_mem_methods {
** <dd> ^This option takes three additional arguments that determine the
** [lookaside memory allocator] configuration for the [database connection].
** ^The first argument (the third parameter to [sqlite3_db_config()] is a
** pointer to an memory buffer to use for lookaside memory.
** pointer to a memory buffer to use for lookaside memory.
** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb
** may be NULL in which case SQLite will allocate the
** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the
@ -1493,7 +1493,7 @@ struct sqlite3_mem_methods {
** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers].
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable triggers,
** positive to enable trigers or negative to leave the setting unchanged.
** positive to enable triggers or negative to leave the setting unchanged.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether triggers are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
@ -2105,7 +2105,7 @@ void sqlite3_randomness(int N, void *P);
/*
** CAPI3REF: Compile-Time Authorization Callbacks
**
** ^This routine registers a authorizer callback with a particular
** ^This routine registers an authorizer callback with a particular
** [database connection], supplied in the first argument.
** ^The authorizer callback is invoked as SQL statements are being compiled
** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()],
@ -2751,7 +2751,7 @@ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
** whether or not it requires a protected sqlite3_value.
**
** The terms "protected" and "unprotected" refer to whether or not
** a mutex is held. A internal mutex is held for a protected
** a mutex is held. An internal mutex is held for a protected
** sqlite3_value object but no mutex is held for an unprotected
** sqlite3_value object. If SQLite is compiled to be single-threaded
** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0)
@ -3437,7 +3437,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
** are used to add SQL functions or aggregates or to redefine the behavior
** of existing SQL functions or aggregates. The only differences between
** these routines are the text encoding expected for
** the the second parameter (the name of the function being created)
** the second parameter (the name of the function being created)
** and the presence or absence of a destructor callback for
** the application data pointer.
**
@ -3482,7 +3482,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
** callback only; NULL pointers must be passed as the xStep and xFinal
** parameters. ^An aggregate SQL function requires an implementation of xStep
** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing
** SQL function or aggregate, pass NULL poiners for all three function
** SQL function or aggregate, pass NULL pointers for all three function
** callbacks.
**
** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL,
@ -3916,7 +3916,7 @@ void sqlite3_result_zeroblob(sqlite3_context*, int n);
** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin
** on an even byte address.
**
** ^The fourth argument, pArg, is a application data pointer that is passed
** ^The fourth argument, pArg, is an application data pointer that is passed
** through as the first argument to the collating function callback.
**
** ^The fifth argument, xCallback, is a pointer to the collating function.
@ -3932,7 +3932,7 @@ void sqlite3_result_zeroblob(sqlite3_context*, int n);
** by the eTextRep argument. The collating function must return an
** integer that is negative, zero, or positive
** if the first string is less than, equal to, or greater than the second,
** respectively. A collating function must alway return the same answer
** respectively. A collating function must always return the same answer
** given the same inputs. If two or more collating functions are registered
** to the same collation name (using different eTextRep values) then all
** must give an equivalent answer when invoked with equivalent strings.
@ -4344,7 +4344,7 @@ int sqlite3_release_memory(int);
** <li> Memory accounting is disabled using a combination of the
** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
** <li> An alternative page cache implementation is specifed using
** <li> An alternative page cache implementation is specified using
** [sqlite3_config]([SQLITE_CONFIG_PCACHE],...).
** <li> The page cache allocates from its own memory pool supplied
** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than
@ -4565,7 +4565,7 @@ typedef struct sqlite3_module sqlite3_module;
** CAPI3REF: Virtual Table Object
** KEYWORDS: sqlite3_module {virtual table module}
**
** This structure, sometimes called a a "virtual table module",
** This structure, sometimes called a "virtual table module",
** defines the implementation of a [virtual tables].
** This structure consists mostly of methods for the module.
**
@ -4877,7 +4877,7 @@ typedef struct sqlite3_blob sqlite3_blob;
** This is true if any column of the row is changed, even a column
** other than the one the BLOB handle is open on.)^
** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for
** a expired BLOB handle fail with an return code of [SQLITE_ABORT].
** an expired BLOB handle fail with a return code of [SQLITE_ABORT].
** ^(Changes written into a BLOB prior to the BLOB expiring are not
** rolled back by the expiration of the BLOB. Such changes will eventually
** commit if the transaction continues to completion.)^

View File

@ -1484,6 +1484,7 @@ struct Index {
int tnum; /* Page containing root of this index in database file */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */
u8 bUnordered; /* Use this index for == or IN queries only */
char *zColAff; /* String defining the affinity of each column */
Index *pNext; /* The next index associated with the same table */
Schema *pSchema; /* Schema containing this index */
@ -2776,6 +2777,7 @@ void sqlite3PrngRestoreState(void);
void sqlite3PrngResetState(void);
void sqlite3RollbackAll(sqlite3*);
void sqlite3CodeVerifySchema(Parse*, int);
void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
void sqlite3BeginTransaction(Parse*, int);
void sqlite3CommitTransaction(Parse*);
void sqlite3RollbackTransaction(Parse*);

View File

@ -97,6 +97,12 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "mutex", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_MUTEX_NOOP
Tcl_SetVar2(interp, "sqlite_options", "mutex_noop", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "mutex_noop", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_ALTERTABLE
Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY);
#else
@ -487,12 +493,6 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double",
Tcl_SetVar2(interp, "sqlite_options", "truncate_opt", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_UNIQUE_ENFORCEMENT
Tcl_SetVar2(interp, "sqlite_options", "unique_enforcement", "0", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "unique_enforcement", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_UTF16
Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
#else

View File

@ -171,6 +171,9 @@ void sqlite3BeginTrigger(
zName, sqlite3Strlen30(zName)) ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
}else{
assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
}
goto trigger_cleanup;
}
@ -499,6 +502,8 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
if( !pTrigger ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
}else{
sqlite3CodeVerifyNamedSchema(pParse, zDb);
}
pParse->checkSchema = 1;
goto drop_trigger_cleanup;

View File

@ -1342,7 +1342,10 @@ static void exprAnalyze(
** of the loop. Without the TERM_VNULL flag, the not-null check at
** the start of the loop will prevent any results from being returned.
*/
if( pExpr->op==TK_NOTNULL && pExpr->pLeft->iColumn>=0 ){
if( pExpr->op==TK_NOTNULL
&& pExpr->pLeft->op==TK_COLUMN
&& pExpr->pLeft->iColumn>=0
){
Expr *pNewExpr;
Expr *pLeft = pExpr->pLeft;
int idxNew;
@ -2532,7 +2535,7 @@ range_est_fallback:
** for a UTF conversion required for comparison. The error is stored
** in the pParse structure.
*/
int whereEqualScanEst(
static int whereEqualScanEst(
Parse *pParse, /* Parsing & code generating context */
Index *p, /* The index whose left-most column is pTerm */
Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */
@ -2589,7 +2592,7 @@ whereEqualScanEst_cancel:
** for a UTF conversion required for comparison. The error is stored
** in the pParse structure.
*/
int whereInScanEst(
static int whereInScanEst(
Parse *pParse, /* Parsing & code generating context */
Index *p, /* The index whose left-most column is pTerm */
ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */
@ -2860,7 +2863,7 @@ static void bestBtreeIndex(
}
/* Determine the value of estBound. */
if( nEq<pProbe->nColumn ){
if( nEq<pProbe->nColumn && pProbe->bUnordered==0 ){
int j = pProbe->aiColumn[nEq];
if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pIdx);
@ -2892,6 +2895,7 @@ static void bestBtreeIndex(
** will scan rows in a different order, set the bSort variable. */
if( pOrderBy ){
if( (wsFlags & WHERE_COLUMN_IN)==0
&& pProbe->bUnordered==0
&& isSortingIndex(pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy,
nEq, wsFlags, &rev)
){

View File

@ -209,6 +209,8 @@ foreach {testid where index rows} {
502 {x IS NULL} {} 100
503 {x=1} t1x 50
504 {x IS NOT NULL} t1x 25
505 {+x IS NOT NULL} {} 500
506 {upper(x) IS NOT NULL} {} 500
} {
# Verify that the expected index is used with the expected row count

View File

@ -87,7 +87,7 @@ ifcapable stat2 {
# row count for (c=2) than it does for (c=?).
do_test analyze7-3.2.2 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~102 rows)}}
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~51 rows)}}
} else {
# If ENABLE_STAT2 is not defined, the expected row count for (c=2) is the
# same as that for (c=?).

View File

@ -74,7 +74,11 @@ do_test 1.4 {
set L [list]
set S ""
foreach {name f} $files {
lappend L wal
if {[permutation] == "journaltest"} {
lappend L delete
} else {
lappend L wal
}
append S "
PRAGMA $name.journal_mode = WAL;
UPDATE $name.tbl SET x = '$name';

View File

@ -369,4 +369,77 @@ do_allbackcompat_test {
}
}
#-------------------------------------------------------------------------
# Test that Rtree tables may be read/written by different versions of
# SQLite.
#
set contents {
CREATE VIRTUAL TABLE t1 USING rtree(id, x1, x2, y1, y2);
}
foreach {id x1 x2 y1 y2} {
1 -47.64 43.87 33.86 34.42 2 -21.51 17.32 2.05 31.04
3 -43.67 -38.33 -19.79 3.43 4 32.41 35.16 9.12 19.82
5 33.28 34.87 14.78 28.26 6 49.31 116.59 -9.87 75.09
7 -14.93 34.51 -17.64 64.09 8 -43.05 23.43 -1.19 69.44
9 44.79 133.56 28.09 80.30 10 -2.66 81.47 -41.38 -10.46
11 -42.89 -3.54 15.76 71.63 12 -3.50 84.96 -11.64 64.95
13 -45.69 26.25 11.14 55.06 14 -44.09 11.23 17.52 44.45
15 36.23 133.49 -19.38 53.67 16 -17.89 81.54 14.64 50.61
17 -41.97 -24.04 -39.43 28.95 18 -5.85 7.76 -6.38 47.02
19 18.82 27.10 42.82 100.09 20 39.17 113.45 26.14 73.47
21 22.31 103.17 49.92 106.05 22 -43.06 40.38 -1.75 76.08
23 2.43 57.27 -14.19 -3.83 24 -47.57 -4.35 8.93 100.06
25 -37.47 49.14 -29.11 8.81 26 -7.86 75.72 49.34 107.42
27 1.53 45.49 20.36 49.74 28 -48.48 32.54 28.81 54.45
29 2.67 39.77 -4.05 13.67 30 4.11 62.88 -47.44 -5.72
31 -21.47 51.75 37.25 116.09 32 45.59 111.37 -6.43 43.64
33 35.23 48.29 23.54 113.33 34 16.61 68.35 -14.69 65.97
35 13.98 16.60 48.66 102.87 36 19.74 23.84 31.15 77.27
37 -27.61 24.43 7.96 94.91 38 -34.77 12.05 -22.60 -6.29
39 -25.83 8.71 -13.48 -12.53 40 -17.11 -1.01 18.06 67.89
41 14.13 71.72 -3.78 39.25 42 23.75 76.00 -16.30 8.23
43 -39.15 28.63 38.12 125.88 44 48.62 86.09 36.49 102.95
45 -31.39 -21.98 2.52 89.78 46 5.65 56.04 15.94 89.10
47 18.28 95.81 46.46 143.08 48 30.93 102.82 -20.08 37.36
49 -20.78 -3.48 -5.58 35.46 50 49.85 90.58 -24.48 46.29
} {
if {$x1 >= $x2 || $y1 >= $y2} { error "$x1 $x2 $y1 $y2" }
append contents "INSERT INTO t1 VALUES($id, $x1, $x2, $y1, $y2);"
}
set queries {
1 "SELECT id FROM t1 WHERE x1>10 AND x2<44"
2 "SELECT id FROM t1 WHERE y1<100"
3 "SELECT id FROM t1 WHERE y1<100 AND x1>0"
4 "SELECT id FROM t1 WHERE y1>10 AND x1>0 AND x2<50 AND y2<550"
}
do_allbackcompat_test {
if {[code1 {set ::sqlite_options(fts3)}]
&& [code2 {set ::sqlite_options(fts3)}]
} {
do_test backcompat-4.1 { sql1 $contents } {}
foreach {n q} $::queries {
do_test backcompat-4.2.$n [list sql1 $q] [sql2 $q]
}
do_test backcompat-4.3 { sql1 {
INSERT INTO t1 SELECT id+100, x1+10.0, x2+10.0, y1-10.0, y2-10.0 FROM t1;
} } {}
foreach {n q} $::queries {
do_test backcompat-4.4.$n [list sql1 $q] [sql2 $q]
}
do_test backcompat-4.5 { sql2 {
INSERT INTO t1 SELECT id+200, x1+20.0, x2+20.0, y1-20.0, y2-20.0 FROM t1;
} } {}
foreach {n q} $::queries {
do_test backcompat-4.6.$n [list sql1 $q] [sql2 $q]
}
}
}
finish_test

192
test/exists.test Normal file
View File

@ -0,0 +1,192 @@
# 2011 April 9
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the various schema modification statements
# that feature "IF EXISTS" or "IF NOT EXISTS" clauses.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix exists
# This block of tests is targeted at CREATE XXX IF NOT EXISTS statements.
#
do_multiclient_test tn {
# TABLE objects.
#
do_test 1.$tn.1.1 {
sql2 { CREATE TABLE t1(x) }
sql1 { CREATE TABLE IF NOT EXISTS t1(a, b) }
sql2 { DROP TABLE t1 }
sql1 { CREATE TABLE IF NOT EXISTS t1(a, b) }
sql2 { SELECT name FROM sqlite_master WHERE type = 'table' }
} {t1}
do_test 1.$tn.1.2 {
sql2 { CREATE TABLE t2(x) }
sql1 { CREATE TABLE IF NOT EXISTS t2 AS SELECT * FROM t1 }
sql2 { DROP TABLE t2 }
sql1 { CREATE TABLE IF NOT EXISTS t2 AS SELECT * FROM t1 }
sql2 { SELECT name FROM sqlite_master WHERE type = 'table' }
} {t1 t2}
# INDEX objects.
#
do_test 1.$tn.2 {
sql2 { CREATE INDEX i1 ON t1(a) }
sql1 { CREATE INDEX IF NOT EXISTS i1 ON t1(a, b) }
sql2 { DROP INDEX i1 }
sql1 { CREATE INDEX IF NOT EXISTS i1 ON t1(a, b) }
sql2 { SELECT name FROM sqlite_master WHERE type = 'index' }
} {i1}
# VIEW objects.
#
do_test 1.$tn.3 {
sql2 { CREATE VIEW v1 AS SELECT * FROM t1 }
sql1 { CREATE VIEW IF NOT EXISTS v1 AS SELECT * FROM t1 }
sql2 { DROP VIEW v1 }
sql1 { CREATE VIEW IF NOT EXISTS v1 AS SELECT * FROM t1 }
sql2 { SELECT name FROM sqlite_master WHERE type = 'view' }
} {v1}
# TRIGGER objects.
#
do_test $tn.4 {
sql2 { CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END }
sql1 { CREATE TRIGGER IF NOT EXISTS tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END }
sql2 { DROP TRIGGER tr1 }
sql1 { CREATE TRIGGER IF NOT EXISTS tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END }
sql2 { SELECT name FROM sqlite_master WHERE type = 'trigger' }
} {tr1}
}
# This block of tests is targeted at DROP XXX IF EXISTS statements.
#
do_multiclient_test tn {
# TABLE objects.
#
do_test 2.$tn.1 {
sql1 { DROP TABLE IF EXISTS t1 }
sql2 { CREATE TABLE t1(x) }
sql1 { DROP TABLE IF EXISTS t1 }
sql2 { SELECT name FROM sqlite_master WHERE type = 'table' }
} {}
# INDEX objects.
#
do_test 2.$tn.2 {
sql1 { CREATE TABLE t2(x) }
sql1 { DROP INDEX IF EXISTS i2 }
sql2 { CREATE INDEX i2 ON t2(x) }
sql1 { DROP INDEX IF EXISTS i2 }
sql2 { SELECT name FROM sqlite_master WHERE type = 'index' }
} {}
# VIEW objects.
#
do_test 2.$tn.3 {
sql1 { DROP VIEW IF EXISTS v1 }
sql2 { CREATE VIEW v1 AS SELECT * FROM t2 }
sql1 { DROP VIEW IF EXISTS v1 }
sql2 { SELECT name FROM sqlite_master WHERE type = 'view' }
} {}
# TRIGGER objects.
#
do_test 2.$tn.4 {
sql1 { DROP TRIGGER IF EXISTS tr1 }
sql2 { CREATE TRIGGER tr1 AFTER INSERT ON t2 BEGIN SELECT 1; END }
sql1 { DROP TRIGGER IF EXISTS tr1 }
sql2 { SELECT name FROM sqlite_master WHERE type = 'trigger' }
} {}
}
# This block of tests is targeted at DROP XXX IF EXISTS statements with
# attached databases.
#
do_multiclient_test tn {
forcedelete test.db2
do_test 3.$tn.0 {
sql1 { ATTACH 'test.db2' AS aux }
sql2 { ATTACH 'test.db2' AS aux }
} {}
# TABLE objects.
#
do_test 3.$tn.1.1 {
sql1 { DROP TABLE IF EXISTS aux.t1 }
sql2 { CREATE TABLE aux.t1(x) }
sql1 { DROP TABLE IF EXISTS aux.t1 }
sql2 { SELECT name FROM aux.sqlite_master WHERE type = 'table' }
} {}
do_test 3.$tn.1.2 {
sql1 { DROP TABLE IF EXISTS t1 }
sql2 { CREATE TABLE aux.t1(x) }
sql1 { DROP TABLE IF EXISTS t1 }
sql2 { SELECT name FROM aux.sqlite_master WHERE type = 'table' }
} {}
# INDEX objects.
#
do_test 3.$tn.2.1 {
sql1 { CREATE TABLE aux.t2(x) }
sql1 { DROP INDEX IF EXISTS aux.i2 }
sql2 { CREATE INDEX aux.i2 ON t2(x) }
sql1 { DROP INDEX IF EXISTS aux.i2 }
sql2 { SELECT name FROM aux.sqlite_master WHERE type = 'index' }
} {}
do_test 3.$tn.2.2 {
sql1 { DROP INDEX IF EXISTS i2 }
sql2 { CREATE INDEX aux.i2 ON t2(x) }
sql1 { DROP INDEX IF EXISTS i2 }
sql2 { SELECT name FROM aux.sqlite_master WHERE type = 'index' }
} {}
# VIEW objects.
#
do_test 3.$tn.3.1 {
sql1 { DROP VIEW IF EXISTS aux.v1 }
sql2 { CREATE VIEW aux.v1 AS SELECT * FROM t2 }
sql1 { DROP VIEW IF EXISTS aux.v1 }
sql2 { SELECT name FROM aux.sqlite_master WHERE type = 'view' }
} {}
do_test 3.$tn.3.2 {
sql1 { DROP VIEW IF EXISTS v1 }
sql2 { CREATE VIEW aux.v1 AS SELECT * FROM t2 }
sql1 { DROP VIEW IF EXISTS v1 }
sql2 { SELECT name FROM aux.sqlite_master WHERE type = 'view' }
} {}
# TRIGGER objects.
#
do_test 3.$tn.4.1 {
sql1 { DROP TRIGGER IF EXISTS aux.tr1 }
sql2 { CREATE TRIGGER aux.tr1 AFTER INSERT ON t2 BEGIN SELECT 1; END }
sql1 { DROP TRIGGER IF EXISTS aux.tr1 }
sql2 { SELECT name FROM aux.sqlite_master WHERE type = 'trigger' }
} {}
do_test 3.$tn.4.2 {
sql1 { DROP TRIGGER IF EXISTS tr1 }
sql2 { CREATE TRIGGER aux.tr1 AFTER INSERT ON t2 BEGIN SELECT 1; END }
sql1 { DROP TRIGGER IF EXISTS tr1 }
sql2 { SELECT name FROM aux.sqlite_master WHERE type = 'trigger' }
} {}
}
finish_test

View File

@ -23,6 +23,7 @@ ifcapable {!autovacuum || !pragma} {
return
}
set testprefix incrvacuum2
# Create a database in incremental vacuum mode that has many
# pages on the freelist.
@ -131,6 +132,80 @@ do_test incrvacuum2-3.2 {
}
} {}
integrity_check incremental2-3.3
integrity_check incrvacuum2-3.3
ifcapable wal {
# At one point, when a specific page was being extracted from the b-tree
# free-list (e.g. during an incremental-vacuum), all trunk pages that
# occurred before the specific page in the free-list trunk were being
# written to the journal or wal file. This is not necessary. Only the
# extracted page and the page that contains the pointer to it need to
# be journalled.
#
# This problem was fixed by [d03d63d77e] (just before 3.7.6 release).
#
# This test case builds a database containing many free pages. Then runs
# "PRAGMA incremental_vacuum(1)" until the db contains zero free pages.
# Each "PRAGMA incremental_vacuum(1)" should modify at most 4 pages. The
# worst case is when a trunk page is removed from the end of the db file.
# In this case pages written are:
#
# 1. The previous trunk page (that contains a pointer to the recycled
# trunk page), and
# 2. The leaf page transformed into a trunk page to replace the recycled
# page, and
# 3. The trunk page that contained a pointer to the leaf page used
# in (2), and
# 4. Page 1. Page 1 is always updated, even in WAL mode, since it contains
# the "number of free-list pages" field.
#
db close
forcedelete test.db
sqlite3 db test.db
do_execsql_test 4.1 {
PRAGMA page_size = 512;
PRAGMA auto_vacuum = 2;
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(randomblob(400));
INSERT INTO t1 SELECT * FROM t1; -- 2
INSERT INTO t1 SELECT * FROM t1; -- 4
INSERT INTO t1 SELECT * FROM t1; -- 8
INSERT INTO t1 SELECT * FROM t1; -- 16
INSERT INTO t1 SELECT * FROM t1; -- 32
INSERT INTO t1 SELECT * FROM t1; -- 128
INSERT INTO t1 SELECT * FROM t1; -- 256
INSERT INTO t1 SELECT * FROM t1; -- 512
INSERT INTO t1 SELECT * FROM t1; -- 1024
INSERT INTO t1 SELECT * FROM t1; -- 2048
INSERT INTO t1 SELECT * FROM t1; -- 4096
INSERT INTO t1 SELECT * FROM t1; -- 8192
DELETE FROM t1 WHERE oid>512;
DELETE FROM t1;
}
do_test 4.2 {
execsql {
PRAGMA journal_mode = WAL;
PRAGMA incremental_vacuum(1);
PRAGMA wal_checkpoint;
}
file size test.db-wal
} {1640}
do_test 4.3 {
db close
sqlite3 db test.db
set maxsz 0
while {[file size test.db] > [expr 512*3]} {
execsql { PRAGMA journal_mode = WAL }
execsql { PRAGMA wal_checkpoint }
execsql { PRAGMA incremental_vacuum(1) }
set newsz [file size test.db-wal]
if {$newsz>$maxsz} {set maxsz $newsz}
}
set maxsz
} {2176}
}
finish_test

View File

@ -1,170 +0,0 @@
# 2011 March 10
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the SQLITE_OMIT_UNIQUE_ENFORCEMENT
# compiler option.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set uniq_enforced 1
ifcapable !unique_enforcement {
set uniq_enforced 0
}
# table with UNIQUE keyword on column
do_test omitunique-1.1 {
catchsql { CREATE TABLE t1(a TEXT UNIQUE); }
} {0 {}}
# table with UNIQUE clause on column
do_test omitunique-1.2 {
catchsql { CREATE TABLE t2(a TEXT, UNIQUE(a)); }
} {0 {}}
# table with UNIQUE index on column
do_test omitunique-1.3 {
catchsql {
CREATE TABLE t3(a TEXT);
CREATE UNIQUE INDEX t3a ON t3(a);
}
} {0 {}}
# table with regular index on column
do_test omitunique-1.4 {
catchsql {
CREATE TABLE t4(a TEXT);
CREATE INDEX t4a ON t4(a);
}
} {0 {}}
# table with no index on column
do_test omitunique-1.5 {
catchsql { CREATE TABLE t5(a TEXT); }
} {0 {}}
# run our tests using several table/index forms
foreach {j tbl uniq cnt qp_est stat_enforce stat_omit } {
1 {t1} 1 1 1 {2 1} {9 9}
2 {t2} 1 1 1 {2 1} {9 9}
3 {t3} 1 1 1 {2 1} {9 9}
4 {t4} 0 9 10 {9 9} {9 9}
5 {t5} 0 9 100000 9 9
} {
do_test omitunique-2.0.$j.1 {
catchsql [ subst {INSERT INTO $tbl (a) VALUES('abc'); }]
} {0 {}}
do_test omitunique-2.0.$j.2 {
catchsql [ subst {INSERT INTO $tbl (a) VALUES('123'); }]
} {0 {}}
# check various INSERT commands
foreach {i cmd err} {
1 {INSERT} 1
2 {INSERT OR IGNORE} 0
3 {INSERT OR REPLACE} 0
4 {REPLACE} 0
5 {INSERT OR FAIL} 1
6 {INSERT OR ABORT} 1
7 {INSERT OR ROLLBACK} 1
} {
ifcapable explain {
set x [execsql [ subst { EXPLAIN $cmd INTO $tbl (a) VALUES('abc'); }]]
ifcapable unique_enforcement {
do_test omitunique-2.1.$j.$i.1 {
regexp { IsUnique } $x
} $uniq
}
ifcapable !unique_enforcement {
do_test omitunique-2.1.$j.$i.1 {
regexp { IsUnique } $x
} {0}
}
}
if { $uniq_enforced==0 || $uniq==0 || $err==0 } {
set msg {0 {}}
} {
set msg {1 {column a is not unique}}
}
do_test omitunique-2.1.$j.$i.3 {
catchsql [ subst {$cmd INTO $tbl (a) VALUES('abc'); }]
} $msg
}
# end foreach cmd
# check UPDATE command
ifcapable explain {
set x [execsql [ subst { EXPLAIN UPDATE $tbl SET a='abc'; }]]
ifcapable unique_enforcement {
do_test omitunique-2.2.$j.1 {
regexp { IsUnique } $x
} $uniq
}
ifcapable !unique_enforcement {
do_test omitunique-2.2.$j.1 {
regexp { IsUnique } $x
} {0}
}
}
if { $uniq_enforced==0 || $uniq==0 } {
set msg {0 {}}
} {
set msg {1 {column a is not unique}}
}
do_test omitunique-2.2.$j.3 {
catchsql [ subst { UPDATE $tbl SET a='abc'; }]
} $msg
# check record counts
do_test omitunique-2.3.$j {
execsql [ subst { SELECT count(*) FROM $tbl WHERE a='abc'; }]
} $cnt
# make sure the query planner row estimate not affected because of omit enforcement
ifcapable explain {
do_test omitunique-2.4.$j {
set x [ execsql [ subst { EXPLAIN QUERY PLAN SELECT count(*) FROM $tbl WHERE a='abc'; }]]
set y [ subst {~$qp_est row} ]
regexp $y $x
} {1}
}
# make sure we omit extra OP_Next opcodes when the UNIQUE constraints
# mean there will only be a single pass through the code
ifcapable explain {
set x [execsql [ subst { EXPLAIN SELECT * FROM $tbl WHERE a='abc'; }]]
do_test omitunique-2.5.$j {
if { [ regexp { Next } $x ] } { expr { 0 } } { expr { 1 } }
} $uniq
}
# make sure analyze index stats correct
ifcapable analyze {
if { $uniq_enforced==0 } {
set msg [ list $stat_omit ]
} {
set msg [ list $stat_enforce ]
}
do_test omitunique-2.6.$j {
execsql [ subst { ANALYZE $tbl; } ]
execsql [ subst { SELECT stat FROM sqlite_stat1 WHERE tbl='$tbl'; } ]
} $msg
}
}
# end foreach tbl
finish_test

View File

@ -19,10 +19,7 @@ source $testdir/tester.tcl
# Skip this whole file if the thread testing code is not enabled
#
ifcapable !mutex {
finish_test
return
}
if {[run_thread_tests]==0} { finish_test ; return }
if {[llength [info command thread_step]]==0 || [sqlite3 -has-codec]} {
finish_test
return

View File

@ -17,11 +17,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !mutex {
finish_test
return
}
if {[run_thread_tests]==0} { finish_test ; return }
# Skip this whole file if the thread testing code is not enabled
#

View File

@ -89,6 +89,9 @@ proc run_thread_tests {{print_warning 0}} {
ifcapable !mutex {
set zProblem "SQLite build is not threadsafe"
}
ifcapable mutex_noop {
set zProblem "SQLite build uses SQLITE_MUTEX_NOOP"
}
if {[info commands sqlthread] eq ""} {
set zProblem "SQLite build is not threadsafe"
}

View File

@ -1544,6 +1544,7 @@ ifcapable autovacuum {
} [expr 84 * 1024]
do_test 24.4 {
execsql {
PRAGMA cache_size = 200;
PRAGMA incremental_vacuum;
PRAGMA wal_checkpoint;
}