From c7792fa052499f7ff04adaa787a957eb3f6b5e47 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 2 Apr 2011 16:28:52 +0000 Subject: [PATCH 1/7] Begin a series of changes designed to reduce the scope and frequency of invalidating schemas. Design goals are that the internal schema should never be deleted out from under a prepared statement that is running and that all prepared statements should be expired if the schema is invalidated. At the same time, minimize the number of schema invalidations. This change merely revises the sqlite3ResetInternalSchema() function to use -1 as the wildcard for "all" rather than 0, so that we can reset the main schema independently of all the others. FossilOrigin-Name: 6a8ad6e31e0d2b8a5ace38faf0efd805155ee5f3 --- manifest | 36 ++++++++++++++++++++---------------- manifest.uuid | 2 +- src/attach.c | 4 ++-- src/backup.c | 2 +- src/build.c | 24 ++++++++++++++++-------- src/main.c | 6 +++--- src/pragma.c | 2 +- src/prepare.c | 4 ++-- src/vacuum.c | 3 ++- src/vdbe.c | 4 ++-- src/vdbeaux.c | 2 +- src/vtab.c | 2 +- 12 files changed, 52 insertions(+), 39 deletions(-) diff --git a/manifest b/manifest index 8411b2239f..2df9766380 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\srace\scondition\sin\sOP_ParseSchema. -D 2011-04-02T09:44:43 +C Begin\sa\sseries\sof\schanges\sdesigned\sto\sreduce\sthe\sscope\sand\sfrequency\sof\ninvalidating\sschemas.\s\sDesign\sgoals\sare\sthat\sthe\sinternal\sschema\sshould\nnever\sbe\sdeleted\sout\sfrom\sunder\sa\sprepared\sstatement\sthat\sis\srunning\sand\nthat\sall\sprepared\sstatements\sshould\sbe\sexpired\sif\sthe\sschema\sis\sinvalidated.\nAt\sthe\ssame\stime,\sminimize\sthe\snumber\sof\sschema\sinvalidations.\s\sThis\schange\nmerely\srevises\sthe\ssqlite3ResetInternalSchema()\sfunction\sto\suse\s-1\sas\sthe\nwildcard\sfor\s"all"\srather\sthan\s0,\sso\sthat\swe\scan\sreset\sthe\smain\sschema\nindependently\sof\sall\sthe\sothers. +D 2011-04-02T16:28:52.034 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -116,15 +116,15 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad F src/alter.c 280f5c04b11b492703a342222b3de0a999445280 F src/analyze.c d0a673d303f611690fc7a3293aaefed57cccc5c8 -F src/attach.c 438ea6f6b5d5961c1f49b737f2ce0f14ce7c6877 +F src/attach.c 7cae2cf0c14762ce14c074a860ec52890a973a56 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 -F src/backup.c 537f89c7ef5021cb580f31f782e556ffffcb2ed1 +F src/backup.c b7529a6691f0fd534ae8ff622203c46a7f1b626b F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff F src/btree.c 2b9c81ff64da339a67dda4f94c0d763627be0b67 F src/btree.h 8d36f774ec4b1d0027b8966f8c03d9a72a518c14 F src/btreeInt.h 20f73dc93b1eeb83afd7259fbc6bd7dcf2df7fe4 -F src/build.c 6c490fe14dedb094a202f559e3b29a276abffcf8 +F src/build.c 9dca3dc000b85753cff822c69151f88d913f3b3e F src/callback.c 5069f224882cbdccd559f591271d28d7f37745bc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01 @@ -143,7 +143,7 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e F src/loadext.c 8af9fcc75708d60b88636ccba38b4a7b3c155c3e -F src/main.c c23c62e53d120c5eee086c0e2cc96cc9a691c50e +F src/main.c 14c019b381b76ea378ee8629d1ed861a3899e075 F src/malloc.c 92d59a007d7a42857d4e9454aa25b6b703286be1 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206 @@ -170,8 +170,8 @@ F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58 F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050 F src/pcache1.c d548e31beafa792d1994b663a29a5303569efc4e -F src/pragma.c 4221eb822d7cdb1fb69be555b189e15e5a24b6b5 -F src/prepare.c eb4944d9f7bfa13eb42a7416ed9aaed4de4d0bf3 +F src/pragma.c 672c5e453d6321fdcfd76ffe346d99cae54fcddb +F src/prepare.c cec63cb151fcaeee00006ec5376698310caea56a F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 @@ -234,16 +234,16 @@ F src/trigger.c ec4813709e990a169b6923293e839fa5dfd64282 F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9 F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 F src/util.c cd997077bad039efc0597eb027c929658f93c018 -F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c a45a6a0daf2161797d50b3b5b8a3e0e4debf2d2b +F src/vacuum.c 3b2b0998f4f277e4bc61469c2d78d8424d02899b +F src/vdbe.c 6b15a8fb9bb5d5abd232fbc72cc6410c2fd70c1b F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h e1c6254641168507d25b46affb6dfb53c782f553 F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c -F src/vdbeaux.c 77921792f7ebae267490816deb6a9488f938fa85 +F src/vdbeaux.c e97565fb2fea822a2e853370c440b493ef09d7e7 F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 -F src/vtab.c e1edca38c4c4310710635bb91bb3c87fdf60f21d +F src/vtab.c 341ae69e949ce583c1729b0177f62ab821e8b42f F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794 F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f @@ -926,7 +926,11 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 20afd81a4cf4d23962ec841bbd375f36a5156fb6 -R 25d34b3e2efbdd1c8e0ceadec6512306 -U dan -Z 659aea6fa897bf521b0a686e5d197299 +P 71a799b02a3b3cf2e12758dea29fd2465bbec3e1 +R 5fca8a4df9fe5cb6d589b9d60d83b4fc +T *bgcolor * #d3a8bc +T *branch * schema-parse-refactor +T *sym-schema-parse-refactor * +T -sym-trunk * +U drh +Z 80e5b841d301ef316c4772ca966c9795 diff --git a/manifest.uuid b/manifest.uuid index fa61c3c651..8ad8e8fd35 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -71a799b02a3b3cf2e12758dea29fd2465bbec3e1 \ No newline at end of file +6a8ad6e31e0d2b8a5ace38faf0efd805155ee5f3 \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 37b61935f3..fe88aa73cd 100644 --- a/src/attach.c +++ b/src/attach.c @@ -200,7 +200,7 @@ static void attachFunc( db->aDb[iDb].pBt = 0; db->aDb[iDb].pSchema = 0; } - sqlite3ResetInternalSchema(db, 0); + sqlite3ResetInternalSchema(db, -1); db->nDb = iDb; if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ db->mallocFailed = 1; @@ -272,7 +272,7 @@ static void detachFunc( sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; pDb->pSchema = 0; - sqlite3ResetInternalSchema(db, 0); + sqlite3ResetInternalSchema(db, -1); return; detach_error: diff --git a/src/backup.c b/src/backup.c index 82be9635b1..c062744c5c 100644 --- a/src/backup.c +++ b/src/backup.c @@ -401,7 +401,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ int nDestTruncate; if( p->pDestDb ){ - sqlite3ResetInternalSchema(p->pDestDb, 0); + sqlite3ResetInternalSchema(p->pDestDb, -1); } /* Set nDestTruncate to the final number of pages in the destination diff --git a/src/build.c b/src/build.c index bf3273fc84..c7cd6363d9 100644 --- a/src/build.c +++ b/src/build.c @@ -393,26 +393,34 @@ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ ** if there were schema changes during the transaction or if a ** schema-cookie mismatch occurs. ** -** If iDb==0 then reset the internal schema tables for all database -** files. If iDb>=1 then reset the internal schema for only the +** If iDb<0 then reset the internal schema tables for all database +** files. If iDb>=0 then reset the internal schema for only the ** single file indicated. */ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ int i, j; - assert( iDb>=0 && iDbnDb ); + assert( iDbnDb ); - if( iDb==0 ){ - sqlite3BtreeEnterAll(db); + if( iDb>=0 ){ + /* Case 1: Reset the single schema identified by iDb */ + Db *pDb = &db->aDb[iDb]; + if( pDb->pSchema ){ + assert(iDb==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt))); + sqlite3SchemaFree(pDb->pSchema); + } + return; } - for(i=iDb; inDb; i++){ + /* Case 2 (from here to the end): Reset all schemas for all attached + ** databases. */ + assert( iDb<0 ); + sqlite3BtreeEnterAll(db); + for(i=0; inDb; i++){ Db *pDb = &db->aDb[i]; if( pDb->pSchema ){ assert(i==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt))); sqlite3SchemaFree(pDb->pSchema); } - if( iDb>0 ) return; } - assert( iDb==0 ); db->flags &= ~SQLITE_InternChanges; sqlite3VtabUnlockList(db); sqlite3BtreeLeaveAll(db); diff --git a/src/main.c b/src/main.c index 03097498c5..ca862edc7f 100644 --- a/src/main.c +++ b/src/main.c @@ -687,7 +687,7 @@ int sqlite3_close(sqlite3 *db){ } sqlite3_mutex_enter(db->mutex); - sqlite3ResetInternalSchema(db, 0); + sqlite3ResetInternalSchema(db, -1); /* If a transaction is open, the ResetInternalSchema() call above ** will not have called the xDisconnect() method on any virtual @@ -730,7 +730,7 @@ int sqlite3_close(sqlite3 *db){ } } } - sqlite3ResetInternalSchema(db, 0); + sqlite3ResetInternalSchema(db, -1); /* Tell the code in notify.c that the connection no longer holds any ** locks and does not require any further unlock-notify callbacks. @@ -821,7 +821,7 @@ void sqlite3RollbackAll(sqlite3 *db){ if( db->flags&SQLITE_InternChanges ){ sqlite3ExpirePreparedStatements(db); - sqlite3ResetInternalSchema(db, 0); + sqlite3ResetInternalSchema(db, -1); } /* Any deferred constraint violations have now been resolved. */ diff --git a/src/pragma.c b/src/pragma.c index db55e4bb41..0a092e8c3e 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -115,7 +115,7 @@ static int invalidateTempStorage(Parse *pParse){ } sqlite3BtreeClose(db->aDb[1].pBt); db->aDb[1].pBt = 0; - sqlite3ResetInternalSchema(db, 0); + sqlite3ResetInternalSchema(db, -1); } return SQLITE_OK; } diff --git a/src/prepare.c b/src/prepare.c index 45654ecfca..0687ddea42 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -338,7 +338,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ } if( db->mallocFailed ){ rc = SQLITE_NOMEM; - sqlite3ResetInternalSchema(db, 0); + sqlite3ResetInternalSchema(db, -1); } if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){ /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider @@ -613,7 +613,7 @@ static int sqlite3Prepare( schemaIsValid(pParse); } if( pParse->rc==SQLITE_SCHEMA ){ - sqlite3ResetInternalSchema(db, 0); + sqlite3ResetInternalSchema(db, -1); } if( db->mallocFailed ){ pParse->rc = SQLITE_NOMEM; diff --git a/src/vacuum.c b/src/vacuum.c index 4babf5b409..5ca39ae1e0 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -335,8 +335,9 @@ end_of_vacuum: pDb->pSchema = 0; } - sqlite3ResetInternalSchema(db, 0); + sqlite3ResetInternalSchema(db, -1); return rc; } + #endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */ diff --git a/src/vdbe.c b/src/vdbe.c index ddf507ee9d..0c790d6502 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2649,7 +2649,7 @@ case OP_Savepoint: { } if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ sqlite3ExpirePreparedStatements(db); - sqlite3ResetInternalSchema(db, 0); + sqlite3ResetInternalSchema(db, -1); db->flags = (db->flags | SQLITE_InternChanges); } } @@ -5946,7 +5946,7 @@ vdbe_error_halt: sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; rc = SQLITE_ERROR; - if( resetSchemaOnFault ) sqlite3ResetInternalSchema(db, 0); + if( resetSchemaOnFault ) sqlite3ResetInternalSchema(db, -1); /* This is the only way out of this procedure. We have to ** release the mutexes on btrees that were acquired at the diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 7cab12f78d..a2f4a2b484 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2191,7 +2191,7 @@ int sqlite3VdbeHalt(Vdbe *p){ /* Rollback or commit any schema changes that occurred. */ if( p->rc!=SQLITE_OK && db->flags&SQLITE_InternChanges ){ - sqlite3ResetInternalSchema(db, 0); + sqlite3ResetInternalSchema(db, -1); db->flags = (db->flags | SQLITE_InternChanges); } diff --git a/src/vtab.c b/src/vtab.c index b9f1e6f348..30e302deaf 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -48,7 +48,7 @@ static int createModule( if( pDel==pMod ){ db->mallocFailed = 1; } - sqlite3ResetInternalSchema(db, 0); + sqlite3ResetInternalSchema(db, -1); }else if( xDestroy ){ xDestroy(pAux); } From ff2e14b93fe1eed5ce64d713b3571f5ffc9419a3 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 2 Apr 2011 16:50:25 +0000 Subject: [PATCH 2/7] When resetting any non-TEMP schema, also reset the TEMP schema since it might be holding references to the non-TEMP schema that just got reset. FossilOrigin-Name: 211d5dde1f9c15048c65d1d700141aa7b2491011 --- manifest | 16 ++++++---------- manifest.uuid | 2 +- src/build.c | 7 +++++++ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 2df9766380..6eb669650b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Begin\sa\sseries\sof\schanges\sdesigned\sto\sreduce\sthe\sscope\sand\sfrequency\sof\ninvalidating\sschemas.\s\sDesign\sgoals\sare\sthat\sthe\sinternal\sschema\sshould\nnever\sbe\sdeleted\sout\sfrom\sunder\sa\sprepared\sstatement\sthat\sis\srunning\sand\nthat\sall\sprepared\sstatements\sshould\sbe\sexpired\sif\sthe\sschema\sis\sinvalidated.\nAt\sthe\ssame\stime,\sminimize\sthe\snumber\sof\sschema\sinvalidations.\s\sThis\schange\nmerely\srevises\sthe\ssqlite3ResetInternalSchema()\sfunction\sto\suse\s-1\sas\sthe\nwildcard\sfor\s"all"\srather\sthan\s0,\sso\sthat\swe\scan\sreset\sthe\smain\sschema\nindependently\sof\sall\sthe\sothers. -D 2011-04-02T16:28:52.034 +C When\sresetting\sany\snon-TEMP\sschema,\salso\sreset\sthe\sTEMP\sschema\ssince\sit\smight\nbe\sholding\sreferences\sto\sthe\snon-TEMP\sschema\sthat\sjust\sgot\sreset. +D 2011-04-02T16:50:25.018 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -124,7 +124,7 @@ F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff F src/btree.c 2b9c81ff64da339a67dda4f94c0d763627be0b67 F src/btree.h 8d36f774ec4b1d0027b8966f8c03d9a72a518c14 F src/btreeInt.h 20f73dc93b1eeb83afd7259fbc6bd7dcf2df7fe4 -F src/build.c 9dca3dc000b85753cff822c69151f88d913f3b3e +F src/build.c fcdd8f47361261432fb10d0e7234ba617025d1f2 F src/callback.c 5069f224882cbdccd559f591271d28d7f37745bc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01 @@ -926,11 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 71a799b02a3b3cf2e12758dea29fd2465bbec3e1 -R 5fca8a4df9fe5cb6d589b9d60d83b4fc -T *bgcolor * #d3a8bc -T *branch * schema-parse-refactor -T *sym-schema-parse-refactor * -T -sym-trunk * +P 6a8ad6e31e0d2b8a5ace38faf0efd805155ee5f3 +R bc8973ff15cc98898e96282e6b2f93e3 U drh -Z 80e5b841d301ef316c4772ca966c9795 +Z af325c6ab15f4448779a96c9a9fe8dd3 diff --git a/manifest.uuid b/manifest.uuid index 8ad8e8fd35..d2609b2f9d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6a8ad6e31e0d2b8a5ace38faf0efd805155ee5f3 \ No newline at end of file +211d5dde1f9c15048c65d1d700141aa7b2491011 \ No newline at end of file diff --git a/src/build.c b/src/build.c index c7cd6363d9..7c4735c063 100644 --- a/src/build.c +++ b/src/build.c @@ -408,6 +408,13 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ assert(iDb==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt))); sqlite3SchemaFree(pDb->pSchema); } + /* If any database other than TEMP is reset, then also reset TEMP + ** since TEMP might be holding triggers that reference tables in the + ** other database. + */ + if( iDb!=1 && (pDb = &db->aDb[1])!=0 && pDb->pSchema ){ + sqlite3SchemaFree(pDb->pSchema); + } return; } /* Case 2 (from here to the end): Reset all schemas for all attached From b6ee66072ea24b06d91bedc74b64c2f795b3b9e5 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2011 13:40:53 +0000 Subject: [PATCH 3/7] Rename sqlite3SchemaFree() to sqlite3SchemaClear() to more accurately reflect its function. FossilOrigin-Name: 71d7440023f67760d0bff4bd7459fe88bd226f30 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/build.c | 6 +++--- src/callback.c | 6 +++--- src/sqliteInt.h | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index bc2cf93e78..350d81657e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sin\sthe\slatest\schanges\sfrom\strunk. -D 2011-04-04T13:07:02.051 +C Rename\ssqlite3SchemaFree()\sto\ssqlite3SchemaClear()\sto\smore\saccurately\sreflect\nits\sfunction. +D 2011-04-04T13:40:53.775 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -124,8 +124,8 @@ F src/btmutex.c 3e595ee1bb99e3a1f16824137b435ffc97c98e5f F src/btree.c 107723ed4f9bdb55213ba6164c30c49af75f4bf9 F src/btree.h a840a20c1969391f98ee06960d5ee2dc460186b3 F src/btreeInt.h 6714ce2f5e879eb9a904a6a4575dc4faa4f29991 -F src/build.c 0dd1fd5a9d38534e99d7ed70c325647917e571c5 -F src/callback.c 5069f224882cbdccd559f591271d28d7f37745bc +F src/build.c 3377719d96750d6a64b46237f81c6763220e7662 +F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01 F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b @@ -180,7 +180,7 @@ F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 9dc0b4bb59290c0a35256d278cab0f314987ad6a F src/sqlite.h.in e047f69a61d604d4f8be6cf1d1bdfc68be9ba7e5 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h d45b0b1db417d5308e3bf9c8983aaf2d06e7cd36 +F src/sqliteInt.h 56a866476ad9b6907ce1e12fef5e97288cb68b0f F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 0d99229a7a58da07748072326f6261c533c1958f 425e3edb146c497817855dd741878709a25c8b98 -R 0ccaf0f101b400777a3c1e84b0615efa +P 47b79c40cf07048f682c44bfef533d4764b20c4d +R 7d7c24df127ba94f05b0be76158e8cae U drh -Z 3368f164313f101c42a8e8263501ee32 +Z 2de83a94583ece938e6b46c216a1a66c diff --git a/manifest.uuid b/manifest.uuid index b7ce1af1d7..210b142d75 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -47b79c40cf07048f682c44bfef533d4764b20c4d \ No newline at end of file +71d7440023f67760d0bff4bd7459fe88bd226f30 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 39b6e84a75..41e7c799c4 100644 --- a/src/build.c +++ b/src/build.c @@ -406,14 +406,14 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ Db *pDb = &db->aDb[iDb]; if( pDb->pSchema ){ assert(iDb==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt))); - sqlite3SchemaFree(pDb->pSchema); + sqlite3SchemaClear(pDb->pSchema); } /* If any database other than TEMP is reset, then also reset TEMP ** since TEMP might be holding triggers that reference tables in the ** other database. */ if( iDb!=1 && (pDb = &db->aDb[1])!=0 && pDb->pSchema ){ - sqlite3SchemaFree(pDb->pSchema); + sqlite3SchemaClear(pDb->pSchema); } return; } @@ -425,7 +425,7 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ Db *pDb = &db->aDb[i]; if( pDb->pSchema ){ assert(i==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt))); - sqlite3SchemaFree(pDb->pSchema); + sqlite3SchemaClear(pDb->pSchema); } } db->flags &= ~SQLITE_InternChanges; diff --git a/src/callback.c b/src/callback.c index fdee9bc09c..ce849085c2 100644 --- a/src/callback.c +++ b/src/callback.c @@ -400,12 +400,12 @@ FuncDef *sqlite3FindFunction( /* ** Free all resources held by the schema structure. The void* argument points ** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the -** pointer itself, it just cleans up subsiduary resources (i.e. the contents +** pointer itself, it just cleans up subsidiary resources (i.e. the contents ** of the schema hash tables). ** ** The Schema.cache_size variable is not cleared. */ -void sqlite3SchemaFree(void *p){ +void sqlite3SchemaClear(void *p){ Hash temp1; Hash temp2; HashElem *pElem; @@ -440,7 +440,7 @@ void sqlite3SchemaFree(void *p){ Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ Schema * p; if( pBt ){ - p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaFree); + p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear); }else{ p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ba5552dba4..f7700b740a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2969,7 +2969,7 @@ void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); void sqlite3MinimumFileFormat(Parse*, int, int); -void sqlite3SchemaFree(void *); +void sqlite3SchemaClear(void *); Schema *sqlite3SchemaGet(sqlite3 *, Btree *); int sqlite3SchemaToIndex(sqlite3 *db, Schema *); KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *); From 2120608e0f1186788a4f900f77b6c2418c3835e6 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2011 18:22:02 +0000 Subject: [PATCH 4/7] Add a description of access rules for the Schema object and lots of asserts to verify that the access rules are followed. FossilOrigin-Name: ae8374af057b6e6546e9265148cfffe32fcb0849 --- manifest | 38 +++++++++++++++++++------------------- manifest.uuid | 2 +- src/analyze.c | 4 +++- src/btmutex.c | 25 +++++++++++++++++++++++++ src/btree.h | 2 ++ src/build.c | 31 ++++++++++++++++++++++++++----- src/fkey.c | 1 + src/insert.c | 2 ++ src/pragma.c | 3 +++ src/prepare.c | 1 + src/sqliteInt.h | 14 ++++++++++++++ src/status.c | 2 ++ src/trigger.c | 10 +++++++++- src/vdbe.c | 3 +++ src/vtab.c | 1 + 15 files changed, 112 insertions(+), 27 deletions(-) diff --git a/manifest b/manifest index a0193c477f..d4526b8119 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\stest_syscall.c\sfix\sfrom\sthe\strunk. -D 2011-04-04T14:05:39.172 +C Add\sa\sdescription\sof\saccess\srules\sfor\sthe\sSchema\sobject\sand\slots\sof\sasserts\nto\sverify\sthat\sthe\saccess\srules\sare\sfollowed. +D 2011-04-04T18:22:02.782 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -115,16 +115,16 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad F src/alter.c 280f5c04b11b492703a342222b3de0a999445280 -F src/analyze.c d0a673d303f611690fc7a3293aaefed57cccc5c8 +F src/analyze.c a1ad9f4d8aac055c4a4bbd99073e2e78fe66129c F src/attach.c 7cae2cf0c14762ce14c074a860ec52890a973a56 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c b7529a6691f0fd534ae8ff622203c46a7f1b626b F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef -F src/btmutex.c 3e595ee1bb99e3a1f16824137b435ffc97c98e5f +F src/btmutex.c b81062220a4f91b0bd785d13d57205d68449be88 F src/btree.c 107723ed4f9bdb55213ba6164c30c49af75f4bf9 -F src/btree.h a840a20c1969391f98ee06960d5ee2dc460186b3 +F src/btree.h c0e0ff5c85effe9fc757e3085bbdded6d1cca000 F src/btreeInt.h 6714ce2f5e879eb9a904a6a4575dc4faa4f29991 -F src/build.c 3377719d96750d6a64b46237f81c6763220e7662 +F src/build.c 63465c86f7d5919fddb112ec6d38342863e8e8b3 F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01 @@ -132,13 +132,13 @@ F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b F src/delete.c 7ed8a8c8b5f748ece92df173d7e0f7810c899ebd F src/expr.c 00817c672af554321fd67c44325afd7cef0e4648 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 418b840007c873975fd0d071746d952f8bca20ce +F src/fkey.c 387c9b458eba388538922591dddf4fa032a39dcb F src/func.c 3a8cb2fb2de3e3aed7f39106daf4878d9d17fcce F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 8ffb544ff516669aa84a6f13d05dbf5c93bdb1ea +F src/insert.c 081d0dc22f8264093057e6358365681036a95309 F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e @@ -170,8 +170,8 @@ F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58 F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050 F src/pcache1.c d548e31beafa792d1994b663a29a5303569efc4e -F src/pragma.c 672c5e453d6321fdcfd76ffe346d99cae54fcddb -F src/prepare.c cec63cb151fcaeee00006ec5376698310caea56a +F src/pragma.c 36eec9129bfea2dbcdc1694d362f17330132697d +F src/prepare.c a4d8ac347b39e317d2f463c36b22c650e00b7126 F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 @@ -180,9 +180,9 @@ F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 9dc0b4bb59290c0a35256d278cab0f314987ad6a F src/sqlite.h.in e047f69a61d604d4f8be6cf1d1bdfc68be9ba7e5 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h 56a866476ad9b6907ce1e12fef5e97288cb68b0f +F src/sqliteInt.h 9a944a2d9b12b30b186a0f1236a97eb01f1e50bb F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 -F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc +F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/tclsqlite.c 501c9a200fd998a268be475be5858febc90b725b F src/test1.c 9ca440e80e16e53920904a0a5ac7feffb9b2c9a1 @@ -230,12 +230,12 @@ 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 ec4813709e990a169b6923293e839fa5dfd64282 +F src/trigger.c bb68c3d1feff3e1335c55a7acf195b9c96ae91ec F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9 F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 F src/util.c cd997077bad039efc0597eb027c929658f93c018 F src/vacuum.c 3b2b0998f4f277e4bc61469c2d78d8424d02899b -F src/vdbe.c 48fe95bd84b7cdeb155c4d2b825c7d19a65c5b3d +F src/vdbe.c 1e62a4f18500f86137fda77416c5e55f7336d1d1 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 7e2f028ecc1a9faa6f253e7aa8d89cae03662bae F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c @@ -243,7 +243,7 @@ F src/vdbeaux.c e1ea6edc07b4f33a339cc45a2fbe0a36067d2d8b F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 -F src/vtab.c 341ae69e949ce583c1729b0177f62ab821e8b42f +F src/vtab.c 672f8dadd6ce9ab984af81e3dfb1b5b38715e7b7 F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794 F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 71d7440023f67760d0bff4bd7459fe88bd226f30 fda8fadd837e399d3fab7a9e6894617a5788d679 -R 3fc8950d604a8bfbce215b1e441b51de -U dan -Z 197ed95a6588fec32711fa656edc064b +P 1e1a23cc56563d512b28288256c34f05ea15b4aa +R 977144757d60ff253970ffcce55b348e +U drh +Z 03b0de28f2209300e8cd6e160282b5b5 diff --git a/manifest.uuid b/manifest.uuid index 7c08d4cfd5..1a879c861a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1e1a23cc56563d512b28288256c34f05ea15b4aa \ No newline at end of file +ae8374af057b6e6546e9265148cfffe32fcb0849 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 231d414314..fd040a7ec2 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -149,6 +149,7 @@ static void analyzeOneTable( assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb>=0 ); + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, db->aDb[iDb].zName ) ){ @@ -390,6 +391,7 @@ static void analyzeDatabase(Parse *pParse, int iDb){ pParse->nTab += 2; openStatTable(pParse, iDb, iStatCur, 0, 0); iMem = pParse->nMem+1; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ Table *pTab = (Table*)sqliteHashData(k); analyzeOneTable(pParse, pTab, 0, iStatCur, iMem); @@ -600,9 +602,9 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ assert( iDb>=0 && iDbnDb ); assert( db->aDb[iDb].pBt!=0 ); - assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); /* Clear any prior statistics */ + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); sqlite3DefaultRowEst(pIdx); diff --git a/src/btmutex.c b/src/btmutex.c index 42d0bdcbc7..33b9f86a0c 100644 --- a/src/btmutex.c +++ b/src/btmutex.c @@ -288,6 +288,31 @@ int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ } #endif /* NDEBUG */ +#ifndef NDEBUG +/* +** Return true if the correct mutexes are held for accessing the +** db->aDb[iDb].pSchema structure. The mutexes required for schema +** access are: +** +** (1) The mutex on db +** (2) if iDb!=1, then the mutex on db->aDb[iDb].pBt. +** +** If pSchema is not NULL, then iDb is computed from pSchema and +** db using sqlite3SchemaToIndex(). +*/ +int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){ + Btree *p; + assert( db!=0 ); + if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema); + assert( iDb>=0 && iDbnDb ); + if( !sqlite3_mutex_held(db->mutex) ) return 0; + if( iDb==1 ) return 1; + p = db->aDb[iDb].pBt; + assert( p!=0 ); + return p->sharable==0 || p->locked==1; +} +#endif /* NDEBUG */ + #else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */ /* ** The following are special cases for mutex enter routines for use diff --git a/src/btree.h b/src/btree.h index 4fd4f67685..3eebfe20b5 100644 --- a/src/btree.h +++ b/src/btree.h @@ -220,6 +220,7 @@ void sqlite3BtreeCursorList(Btree*); /* These routines are used inside assert() statements only. */ int sqlite3BtreeHoldsMutex(Btree*); int sqlite3BtreeHoldsAllMutexes(sqlite3*); + int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*); u32 sqlite3BtreeMutexCounter(Btree*); #endif #else @@ -232,6 +233,7 @@ void sqlite3BtreeCursorList(Btree*); # define sqlite3BtreeHoldsMutex(X) 1 # define sqlite3BtreeHoldsAllMutexes(X) 1 +# define sqlite3BtreeSchemaMutexHeld(X,Y) 1 #endif diff --git a/src/build.c b/src/build.c index 41e7c799c4..51b790586b 100644 --- a/src/build.c +++ b/src/build.c @@ -156,6 +156,7 @@ void sqlite3FinishCoding(Parse *pParse){ sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0); if( db->init.busy==0 ){ + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); sqlite3VdbeAddOp3(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb], db->aDb[iDb].pSchema->iGeneration); @@ -271,9 +272,12 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ int nName; assert( zName!=0 ); nName = sqlite3Strlen30(zName); + /* All mutexes are required for schema access. Make sure we hold them. */ + assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; + assert( sqlite3SchemaMutexHeld(db, j, 0) ); p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, nName); if( p ) break; } @@ -333,11 +337,14 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ Index *p = 0; int i; int nName = sqlite3Strlen30(zName); + /* All mutexes are required for schema access. Make sure we hold them. */ + assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ Schema *pSchema = db->aDb[j].pSchema; assert( pSchema ); if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; + assert( sqlite3SchemaMutexHeld(db, j, 0) ); p = sqlite3HashFind(&pSchema->idxHash, zName, nName); if( p ) break; } @@ -364,8 +371,10 @@ static void freeIndex(sqlite3 *db, Index *p){ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ Index *pIndex; int len; - Hash *pHash = &db->aDb[iDb].pSchema->idxHash; + Hash *pHash; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + pHash = &db->aDb[iDb].pSchema->idxHash; len = sqlite3Strlen30(zIdxName); pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0); if( ALWAYS(pIndex) ){ @@ -404,15 +413,15 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ if( iDb>=0 ){ /* Case 1: Reset the single schema identified by iDb */ Db *pDb = &db->aDb[iDb]; - if( pDb->pSchema ){ - assert(iDb==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt))); + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + if( ALWAYS(pDb->pSchema) ){ sqlite3SchemaClear(pDb->pSchema); } /* If any database other than TEMP is reset, then also reset TEMP ** since TEMP might be holding triggers that reference tables in the ** other database. */ - if( iDb!=1 && (pDb = &db->aDb[1])!=0 && pDb->pSchema ){ + if( iDb!=1 && (pDb = &db->aDb[1])!=0 && ALWAYS(pDb->pSchema) ){ sqlite3SchemaClear(pDb->pSchema); } return; @@ -424,7 +433,6 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ for(i=0; inDb; i++){ Db *pDb = &db->aDb[i]; if( pDb->pSchema ){ - assert(i==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt))); sqlite3SchemaClear(pDb->pSchema); } } @@ -513,6 +521,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ TESTONLY ( Index *pOld = ) sqlite3HashInsert( &pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0 ); + assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); assert( pOld==pIndex || pOld==0 ); } freeIndex(db, pIndex); @@ -547,6 +556,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ assert( db!=0 ); assert( iDb>=0 && iDbnDb ); assert( zTabName ); + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */ pDb = &db->aDb[iDb]; p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, @@ -831,6 +841,7 @@ void sqlite3StartTable( */ #ifndef SQLITE_OMIT_AUTOINCREMENT if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){ + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pTable->pSchema->pSeqTab = pTable; } #endif @@ -1291,6 +1302,7 @@ void sqlite3ChangeCookie(Parse *pParse, int iDb){ int r1 = sqlite3GetTempReg(pParse); sqlite3 *db = pParse->db; Vdbe *v = pParse->pVdbe; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, r1); sqlite3ReleaseTempReg(pParse, r1); @@ -1593,6 +1605,7 @@ void sqlite3EndTable( */ if( p->tabFlags & TF_Autoincrement ){ Db *pDb = &db->aDb[iDb]; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( pDb->pSchema->pSeqTab==0 ){ sqlite3NestedParse(pParse, "CREATE TABLE %Q.sqlite_sequence(name,seq)", @@ -1613,6 +1626,7 @@ void sqlite3EndTable( if( db->init.busy ){ Table *pOld; Schema *pSchema = p->pSchema; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, sqlite3Strlen30(p->zName),p); if( pOld ){ @@ -1797,6 +1811,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ pSelTab->nCol = 0; pSelTab->aCol = 0; sqlite3DeleteTable(db, pSelTab); + assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) ); pTable->pSchema->flags |= DB_UnresetViews; }else{ pTable->nCol = 0; @@ -1817,6 +1832,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ */ static void sqliteViewResetAll(sqlite3 *db, int idx){ HashElem *i; + assert( sqlite3SchemaMutexHeld(db, idx, 0) ); if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); @@ -2227,6 +2243,7 @@ void sqlite3CreateForeignKey( pFKey->aAction[0] = (u8)(flags & 0xff); /* ON DELETE action */ pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff); /* ON UPDATE action */ + assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey ); @@ -2582,6 +2599,7 @@ Index *sqlite3CreateIndex( pIndex->onError = (u8)onError; pIndex->autoIndex = (u8)(pName==0); pIndex->pSchema = db->aDb[iDb].pSchema; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); /* Check to see if we should honor DESC requests on index columns */ @@ -2711,6 +2729,7 @@ Index *sqlite3CreateIndex( */ if( db->init.busy ){ Index *p; + assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); p = sqlite3HashInsert(&pIndex->pSchema->idxHash, pIndex->zName, sqlite3Strlen30(pIndex->zName), pIndex); @@ -3464,6 +3483,7 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ assert( iDbnDb ); assert( db->aDb[iDb].pBt!=0 || iDb==1 ); assert( iDbcookieMask & mask)==0 ){ pToplevel->cookieMask |= mask; @@ -3591,6 +3611,7 @@ static void reindexDatabases(Parse *pParse, char const *zColl){ HashElem *k; /* For looping over tables in pDb */ Table *pTab; /* A table in the database */ + assert( sqlite3BtreeHoldsAllMutexes(db) ); /* Needed for schema access */ for(iDb=0, pDb=db->aDb; iDbnDb; iDb++, pDb++){ assert( pDb!=0 ); for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ diff --git a/src/fkey.c b/src/fkey.c index 653cc1833a..14b2db5159 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -1154,6 +1154,7 @@ void sqlite3FkDelete(sqlite3 *db, Table *pTab){ FKey *pFKey; /* Iterator variable */ FKey *pNext; /* Copy of pFKey->pNextFrom */ + assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) ); for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){ /* Remove the FK from the fkeyHash hash table. */ diff --git a/src/insert.c b/src/insert.c index a4efcf2bf3..77f55822f9 100644 --- a/src/insert.c +++ b/src/insert.c @@ -237,6 +237,7 @@ void sqlite3AutoincrementBegin(Parse *pParse){ for(p = pParse->pAinc; p; p = p->pNext){ pDb = &db->aDb[p->iDb]; memId = p->regCtr; + assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); addr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0); @@ -287,6 +288,7 @@ void sqlite3AutoincrementEnd(Parse *pParse){ int memId = p->regCtr; iRec = sqlite3GetTempReg(pParse); + assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); j2 = sqlite3VdbeAddOp0(v, OP_Rewind); diff --git a/src/pragma.c b/src/pragma.c index 0a092e8c3e..5537bcf49e 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -388,6 +388,7 @@ void sqlite3Pragma( sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3VdbeAddOp2(v, OP_Integer, size, 1); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1); + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pDb->pSchema->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } @@ -690,6 +691,7 @@ void sqlite3Pragma( */ if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( !zRight ){ returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); }else{ @@ -1110,6 +1112,7 @@ void sqlite3Pragma( ** Begin by filling registers 2, 3, ... with the root pages numbers ** for all tables and indices in the database. */ + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pTbls = &db->aDb[i].pSchema->tblHash; for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); diff --git a/src/prepare.c b/src/prepare.c index 0687ddea42..aad2bc0b6e 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -470,6 +470,7 @@ static void schemaIsValid(Parse *pParse){ ** value stored as part of the in-memory schema representation, ** set Parse.rc to SQLITE_SCHEMA. */ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie); + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){ pParse->rc = SQLITE_SCHEMA; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f7700b740a..ac6f76bda5 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -668,6 +668,20 @@ struct Db { /* ** An instance of the following structure stores a database schema. +** +** Most Schema objects are associated with a Btree. The exception is +** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing. +** In shared cache mode, a single Schema object can be shared by multiple +** Btrees that refer to the same underlying BtShared object. +** +** Schema objects are automatically deallocated when the last Btree that +** references them is destroyed. The TEMP Schema is manually freed by +** sqlite3_close(). +* +** A thread must be holding a mutex on the corresponding Btree in order +** to access Schema content. This implies that the thread must also be +** holding a mutex on the sqlite3 connection pointer that owns the Btree. +** For a TEMP Schema, on the connection mutex is required. */ struct Schema { int schema_cookie; /* Database schema version number for this file */ diff --git a/src/status.c b/src/status.c index 96759fda7e..b8c1d58df7 100644 --- a/src/status.c +++ b/src/status.c @@ -163,6 +163,7 @@ int sqlite3_db_status( int i; /* Used to iterate through schemas */ int nByte = 0; /* Used to accumulate return value */ + sqlite3BtreeEnterAll(db); db->pnBytesFreed = &nByte; for(i=0; inDb; i++){ Schema *pSchema = db->aDb[i].pSchema; @@ -189,6 +190,7 @@ int sqlite3_db_status( } } db->pnBytesFreed = 0; + sqlite3BtreeLeaveAll(db); *pHighwater = 0; *pCurrent = nByte; diff --git a/src/trigger.c b/src/trigger.c index f66833522b..38efd5d68b 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -54,6 +54,7 @@ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){ if( pTmpSchema!=pTab->pSchema ){ HashElem *p; + assert( sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) ); for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){ Trigger *pTrig = (Trigger *)sqliteHashData(p); if( pTrig->pTabSchema==pTab->pSchema @@ -165,6 +166,7 @@ void sqlite3BeginTrigger( if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto trigger_cleanup; } + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName, sqlite3Strlen30(zName)) ){ if( !noErr ){ @@ -304,6 +306,7 @@ void sqlite3FinishTrigger( if( db->init.busy ){ Trigger *pLink = pTrig; Hash *pHash = &db->aDb[iDb].pSchema->trigHash; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pTrig = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), pTrig); if( pTrig ){ db->mallocFailed = 1; @@ -485,9 +488,11 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ zDb = pName->a[0].zDatabase; zName = pName->a[0].zName; nName = sqlite3Strlen30(zName); + assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; + assert( sqlite3SchemaMutexHeld(db, j, 0) ); pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); if( pTrigger ) break; } @@ -576,8 +581,11 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ ** Remove a trigger from the hash tables of the sqlite* pointer. */ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ - Hash *pHash = &(db->aDb[iDb].pSchema->trigHash); Trigger *pTrigger; + Hash *pHash; + + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + pHash = &(db->aDb[iDb].pSchema->trigHash); pTrigger = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), 0); if( ALWAYS(pTrigger) ){ if( pTrigger->pSchema==pTrigger->pTabSchema ){ diff --git a/src/vdbe.c b/src/vdbe.c index 560ca34319..6dc305dcc5 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2880,6 +2880,7 @@ case OP_SetCookie: { /* in3 */ assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); + assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); pIn3 = &aMem[pOp->p3]; sqlite3VdbeMemIntegerify(pIn3); /* See note about index shifting on OP_ReadCookie */ @@ -2926,6 +2927,7 @@ case OP_VerifyCookie: { assert( pOp->p1>=0 && pOp->p1nDb ); assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); + assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); @@ -3036,6 +3038,7 @@ case OP_OpenWrite: { assert( pX!=0 ); if( pOp->opcode==OP_OpenWrite ){ wrFlag = 1; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( pDb->pSchema->file_format < p->minWriteFileFormat ){ p->minWriteFileFormat = pDb->pSchema->file_format; } diff --git a/src/vtab.c b/src/vtab.c index 30e302deaf..37a63af875 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -387,6 +387,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ Schema *pSchema = pTab->pSchema; const char *zName = pTab->zName; int nName = sqlite3Strlen30(zName); + assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab); if( pOld ){ db->mallocFailed = 1; From 9bbc2e283e4a9212d9b85c82c8d1d3c6d03dadb8 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2011 20:40:22 +0000 Subject: [PATCH 5/7] Minor comment typo corrections. Simplify an assert. No functional changes. FossilOrigin-Name: 82c2316240345167a571507d9392dfb6445ef523 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/main.c | 1 + src/sqliteInt.h | 2 +- src/vtab.c | 7 +++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index d4526b8119..b3c7e0606a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\sdescription\sof\saccess\srules\sfor\sthe\sSchema\sobject\sand\slots\sof\sasserts\nto\sverify\sthat\sthe\saccess\srules\sare\sfollowed. -D 2011-04-04T18:22:02.782 +C Minor\scomment\stypo\scorrections.\s\sSimplify\san\sassert.\s\sNo\sfunctional\schanges. +D 2011-04-04T20:40:22.086 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -143,7 +143,7 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e F src/loadext.c 8af9fcc75708d60b88636ccba38b4a7b3c155c3e -F src/main.c 14c019b381b76ea378ee8629d1ed861a3899e075 +F src/main.c 83cb6a9f1404d59b4dc06ef58cf20401ac1f2261 F src/malloc.c 92d59a007d7a42857d4e9454aa25b6b703286be1 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206 @@ -180,7 +180,7 @@ F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 9dc0b4bb59290c0a35256d278cab0f314987ad6a F src/sqlite.h.in e047f69a61d604d4f8be6cf1d1bdfc68be9ba7e5 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h 9a944a2d9b12b30b186a0f1236a97eb01f1e50bb +F src/sqliteInt.h 4db35e6a25a424d40bf19b0a818f3e9c78e9e7e2 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -243,7 +243,7 @@ F src/vdbeaux.c e1ea6edc07b4f33a339cc45a2fbe0a36067d2d8b F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 -F src/vtab.c 672f8dadd6ce9ab984af81e3dfb1b5b38715e7b7 +F src/vtab.c b0abc931f95af94c9ffdf9f747eb191cda953123 F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794 F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 1e1a23cc56563d512b28288256c34f05ea15b4aa -R 977144757d60ff253970ffcce55b348e +P ae8374af057b6e6546e9265148cfffe32fcb0849 +R b2220f2e44fb0854f9cc6a8a89a03fab U drh -Z 03b0de28f2209300e8cd6e160282b5b5 +Z 3ca4bebd3aef258bcff81de8a689c390 diff --git a/manifest.uuid b/manifest.uuid index 1a879c861a..fc406390db 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ae8374af057b6e6546e9265148cfffe32fcb0849 \ No newline at end of file +82c2316240345167a571507d9392dfb6445ef523 \ No newline at end of file diff --git a/src/main.c b/src/main.c index ca862edc7f..e05c3885b0 100644 --- a/src/main.c +++ b/src/main.c @@ -687,6 +687,7 @@ int sqlite3_close(sqlite3 *db){ } sqlite3_mutex_enter(db->mutex); + /* Force xDestroy calls on all virtual tables */ sqlite3ResetInternalSchema(db, -1); /* If a transaction is open, the ResetInternalSchema() call above diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ac6f76bda5..1d8194a1eb 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1198,7 +1198,7 @@ struct CollSeq { ** schema is shared, as the implementation often stores the database ** connection handle passed to it via the xConnect() or xCreate() method ** during initialization internally. This database connection handle may -** then used by the virtual table implementation to access real tables +** then be used by the virtual table implementation to access real tables ** within the database. So that they appear as part of the callers ** transaction, these accesses need to be made via the same database ** connection as that used to execute SQL operations on the virtual table. diff --git a/src/vtab.c b/src/vtab.c index 37a63af875..b052de23a5 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -145,10 +145,9 @@ static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){ ** that contains table p is held by the caller. See header comments ** above function sqlite3VtabUnlockList() for an explanation of why ** this makes it safe to access the sqlite3.pDisconnect list of any - ** database connection that may have an entry in the p->pVTable list. */ - assert( db==0 || - sqlite3BtreeHoldsMutex(db->aDb[sqlite3SchemaToIndex(db, p->pSchema)].pBt) - ); + ** database connection that may have an entry in the p->pVTable list. + */ + assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); while( pVTable ){ sqlite3 *db2 = pVTable->db; From cdf011dcc4bb61236e9664f299a177d41172e4be Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2011 21:25:28 +0000 Subject: [PATCH 6/7] Additional schema mutex checks for sqlite3RootPageMoved(). Reduce the scope of sqlite3ResetInternalSchema() in a few places. FossilOrigin-Name: 39c00907833413c0d97d3e06fdda967b825d23ea --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/build.c | 5 ++++- src/prepare.c | 4 +--- src/sqliteInt.h | 2 +- src/vdbe.c | 14 +++++++------- 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/manifest b/manifest index b3c7e0606a..c71c3e41f8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\scomment\stypo\scorrections.\s\sSimplify\san\sassert.\s\sNo\sfunctional\schanges. -D 2011-04-04T20:40:22.086 +C Additional\sschema\smutex\schecks\sfor\ssqlite3RootPageMoved().\nReduce\sthe\sscope\sof\ssqlite3ResetInternalSchema()\sin\sa\sfew\splaces. +D 2011-04-04T21:25:28.533 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -124,7 +124,7 @@ F src/btmutex.c b81062220a4f91b0bd785d13d57205d68449be88 F src/btree.c 107723ed4f9bdb55213ba6164c30c49af75f4bf9 F src/btree.h c0e0ff5c85effe9fc757e3085bbdded6d1cca000 F src/btreeInt.h 6714ce2f5e879eb9a904a6a4575dc4faa4f29991 -F src/build.c 63465c86f7d5919fddb112ec6d38342863e8e8b3 +F src/build.c d809f57250b10e83586bc23921de02055890b239 F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01 @@ -171,7 +171,7 @@ F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050 F src/pcache1.c d548e31beafa792d1994b663a29a5303569efc4e F src/pragma.c 36eec9129bfea2dbcdc1694d362f17330132697d -F src/prepare.c a4d8ac347b39e317d2f463c36b22c650e00b7126 +F src/prepare.c 206e1f06479fb5f756592bded468bd3ece3f41d4 F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 @@ -180,7 +180,7 @@ F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 9dc0b4bb59290c0a35256d278cab0f314987ad6a F src/sqlite.h.in e047f69a61d604d4f8be6cf1d1bdfc68be9ba7e5 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h 4db35e6a25a424d40bf19b0a818f3e9c78e9e7e2 +F src/sqliteInt.h 7b0150bfdab049b11bb2d055d065051ff734d113 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -235,7 +235,7 @@ F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9 F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 F src/util.c cd997077bad039efc0597eb027c929658f93c018 F src/vacuum.c 3b2b0998f4f277e4bc61469c2d78d8424d02899b -F src/vdbe.c 1e62a4f18500f86137fda77416c5e55f7336d1d1 +F src/vdbe.c 0140a57f9cbd50351219bfc4e44ef3de64bd65b8 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 7e2f028ecc1a9faa6f253e7aa8d89cae03662bae F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P ae8374af057b6e6546e9265148cfffe32fcb0849 -R b2220f2e44fb0854f9cc6a8a89a03fab +P 82c2316240345167a571507d9392dfb6445ef523 +R 7c6dcb957e59966f9f4fd72f4c665ab1 U drh -Z 3ca4bebd3aef258bcff81de8a689c390 +Z 5433fdc0cc3ff75407dd2b1ee53a6522 diff --git a/manifest.uuid b/manifest.uuid index fc406390db..18b6d137fd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -82c2316240345167a571507d9392dfb6445ef523 \ No newline at end of file +39c00907833413c0d97d3e06fdda967b825d23ea \ No newline at end of file diff --git a/src/build.c b/src/build.c index 51b790586b..7e73b6a8eb 100644 --- a/src/build.c +++ b/src/build.c @@ -1866,10 +1866,13 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){ ** in order to be certain that we got the right one. */ #ifndef SQLITE_OMIT_AUTOVACUUM -void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){ +void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){ HashElem *pElem; Hash *pHash; + Db *pDb; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + pDb = &db->aDb[iDb]; pHash = &pDb->pSchema->tblHash; for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); diff --git a/src/prepare.c b/src/prepare.c index aad2bc0b6e..b5edaf5032 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -472,6 +472,7 @@ static void schemaIsValid(Parse *pParse){ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie); assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){ + sqlite3ResetInternalSchema(db, iDb); pParse->rc = SQLITE_SCHEMA; } @@ -613,9 +614,6 @@ static int sqlite3Prepare( if( pParse->checkSchema ){ schemaIsValid(pParse); } - if( pParse->rc==SQLITE_SCHEMA ){ - sqlite3ResetInternalSchema(db, -1); - } if( db->mallocFailed ){ pParse->rc = SQLITE_NOMEM; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 1d8194a1eb..b874c5e038 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2956,7 +2956,7 @@ extern SQLITE_WSD FuncDefHash sqlite3GlobalFunctions; extern int sqlite3PendingByte; #endif #endif -void sqlite3RootPageMoved(Db*, int, int); +void sqlite3RootPageMoved(sqlite3*, int, int, int); void sqlite3Reindex(Parse*, Token*, Token*); void sqlite3AlterFunctions(void); void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); diff --git a/src/vdbe.c b/src/vdbe.c index 6dc305dcc5..94fd0ff62b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -551,7 +551,7 @@ int sqlite3VdbeExec( Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ - u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */ + u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int checkProgress; /* True if progress callbacks are enabled */ @@ -2953,7 +2953,6 @@ case OP_VerifyCookie: { */ if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){ sqlite3ResetInternalSchema(db, pOp->p1); - sqlite3VdbeMutexResync(p); } p->expired = 1; @@ -4534,8 +4533,10 @@ case OP_Destroy: { /* out2-prerelease */ pOut->u.i = iMoved; #ifndef SQLITE_OMIT_AUTOVACUUM if( rc==SQLITE_OK && iMoved!=0 ){ - sqlite3RootPageMoved(&db->aDb[iDb], iMoved, pOp->p1); - resetSchemaOnFault = 1; + sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1); + /* All OP_Destroy operations occur on the same btree */ + assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 ); + resetSchemaOnFault = iDb+1; } #endif } @@ -5969,9 +5970,8 @@ vdbe_error_halt: sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; rc = SQLITE_ERROR; - if( resetSchemaOnFault ){ - sqlite3ResetInternalSchema(db, 0); - sqlite3VdbeMutexResync(p); + if( resetSchemaOnFault>0 ){ + sqlite3ResetInternalSchema(db, resetSchemaOnFault-1); } /* This is the only way out of this procedure. We have to From 03faf63b57a76c925c0e46e8bcb3b86cfe098590 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2011 23:08:14 +0000 Subject: [PATCH 7/7] Add a comment to the VACUUM implementation explaining when all schemas are reset and not just the "main" schema. FossilOrigin-Name: 2aff1b0ca87a99b8ec80e696b9e8a48bb43db2c2 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vacuum.c | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index c71c3e41f8..e06a7959a3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Additional\sschema\smutex\schecks\sfor\ssqlite3RootPageMoved().\nReduce\sthe\sscope\sof\ssqlite3ResetInternalSchema()\sin\sa\sfew\splaces. -D 2011-04-04T21:25:28.533 +C Add\sa\scomment\sto\sthe\sVACUUM\simplementation\sexplaining\swhen\sall\sschemas\sare\nreset\sand\snot\sjust\sthe\s"main"\sschema. +D 2011-04-04T23:08:14.941 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -234,7 +234,7 @@ F src/trigger.c bb68c3d1feff3e1335c55a7acf195b9c96ae91ec F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9 F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 F src/util.c cd997077bad039efc0597eb027c929658f93c018 -F src/vacuum.c 3b2b0998f4f277e4bc61469c2d78d8424d02899b +F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e F src/vdbe.c 0140a57f9cbd50351219bfc4e44ef3de64bd65b8 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 7e2f028ecc1a9faa6f253e7aa8d89cae03662bae @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 82c2316240345167a571507d9392dfb6445ef523 -R 7c6dcb957e59966f9f4fd72f4c665ab1 +P 39c00907833413c0d97d3e06fdda967b825d23ea +R 649858c83395859d3a968f120123364a U drh -Z 5433fdc0cc3ff75407dd2b1ee53a6522 +Z 182c2bca240b7634d123c22091b55227 diff --git a/manifest.uuid b/manifest.uuid index 18b6d137fd..ac9178d675 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -39c00907833413c0d97d3e06fdda967b825d23ea \ No newline at end of file +2aff1b0ca87a99b8ec80e696b9e8a48bb43db2c2 \ No newline at end of file diff --git a/src/vacuum.c b/src/vacuum.c index 5ca39ae1e0..5a4ed32052 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -335,6 +335,8 @@ end_of_vacuum: pDb->pSchema = 0; } + /* This both clears the schemas and reduces the size of the db->aDb[] + ** array. */ sqlite3ResetInternalSchema(db, -1); return rc;