mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
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
This commit is contained in:
38
manifest
38
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Merge\stest_syscall.c\sfix\sfrom\sthe\strunk.
|
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-04T14:05:39.172
|
D 2011-04-04T18:22:02.782
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2
|
F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -115,16 +115,16 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
|||||||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||||
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
||||||
F src/alter.c 280f5c04b11b492703a342222b3de0a999445280
|
F src/alter.c 280f5c04b11b492703a342222b3de0a999445280
|
||||||
F src/analyze.c d0a673d303f611690fc7a3293aaefed57cccc5c8
|
F src/analyze.c a1ad9f4d8aac055c4a4bbd99073e2e78fe66129c
|
||||||
F src/attach.c 7cae2cf0c14762ce14c074a860ec52890a973a56
|
F src/attach.c 7cae2cf0c14762ce14c074a860ec52890a973a56
|
||||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||||
F src/backup.c b7529a6691f0fd534ae8ff622203c46a7f1b626b
|
F src/backup.c b7529a6691f0fd534ae8ff622203c46a7f1b626b
|
||||||
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
|
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
|
||||||
F src/btmutex.c 3e595ee1bb99e3a1f16824137b435ffc97c98e5f
|
F src/btmutex.c b81062220a4f91b0bd785d13d57205d68449be88
|
||||||
F src/btree.c 107723ed4f9bdb55213ba6164c30c49af75f4bf9
|
F src/btree.c 107723ed4f9bdb55213ba6164c30c49af75f4bf9
|
||||||
F src/btree.h a840a20c1969391f98ee06960d5ee2dc460186b3
|
F src/btree.h c0e0ff5c85effe9fc757e3085bbdded6d1cca000
|
||||||
F src/btreeInt.h 6714ce2f5e879eb9a904a6a4575dc4faa4f29991
|
F src/btreeInt.h 6714ce2f5e879eb9a904a6a4575dc4faa4f29991
|
||||||
F src/build.c 3377719d96750d6a64b46237f81c6763220e7662
|
F src/build.c 63465c86f7d5919fddb112ec6d38342863e8e8b3
|
||||||
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
|
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
|
||||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||||
F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01
|
F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01
|
||||||
@@ -132,13 +132,13 @@ F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b
|
|||||||
F src/delete.c 7ed8a8c8b5f748ece92df173d7e0f7810c899ebd
|
F src/delete.c 7ed8a8c8b5f748ece92df173d7e0f7810c899ebd
|
||||||
F src/expr.c 00817c672af554321fd67c44325afd7cef0e4648
|
F src/expr.c 00817c672af554321fd67c44325afd7cef0e4648
|
||||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||||
F src/fkey.c 418b840007c873975fd0d071746d952f8bca20ce
|
F src/fkey.c 387c9b458eba388538922591dddf4fa032a39dcb
|
||||||
F src/func.c 3a8cb2fb2de3e3aed7f39106daf4878d9d17fcce
|
F src/func.c 3a8cb2fb2de3e3aed7f39106daf4878d9d17fcce
|
||||||
F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3
|
F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3
|
||||||
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
|
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
|
||||||
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
|
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
|
||||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||||
F src/insert.c 8ffb544ff516669aa84a6f13d05dbf5c93bdb1ea
|
F src/insert.c 081d0dc22f8264093057e6358365681036a95309
|
||||||
F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
|
F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
|
||||||
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
|
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
|
||||||
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
|
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
|
||||||
@@ -170,8 +170,8 @@ F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
|
|||||||
F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
|
F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
|
||||||
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
|
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
|
||||||
F src/pcache1.c d548e31beafa792d1994b663a29a5303569efc4e
|
F src/pcache1.c d548e31beafa792d1994b663a29a5303569efc4e
|
||||||
F src/pragma.c 672c5e453d6321fdcfd76ffe346d99cae54fcddb
|
F src/pragma.c 36eec9129bfea2dbcdc1694d362f17330132697d
|
||||||
F src/prepare.c cec63cb151fcaeee00006ec5376698310caea56a
|
F src/prepare.c a4d8ac347b39e317d2f463c36b22c650e00b7126
|
||||||
F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1
|
F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1
|
||||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||||
F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
|
F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
|
||||||
@@ -180,9 +180,9 @@ F src/select.c d24406c45dd2442eb2eeaac413439066b149c944
|
|||||||
F src/shell.c 9dc0b4bb59290c0a35256d278cab0f314987ad6a
|
F src/shell.c 9dc0b4bb59290c0a35256d278cab0f314987ad6a
|
||||||
F src/sqlite.h.in e047f69a61d604d4f8be6cf1d1bdfc68be9ba7e5
|
F src/sqlite.h.in e047f69a61d604d4f8be6cf1d1bdfc68be9ba7e5
|
||||||
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
|
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
|
||||||
F src/sqliteInt.h 56a866476ad9b6907ce1e12fef5e97288cb68b0f
|
F src/sqliteInt.h 9a944a2d9b12b30b186a0f1236a97eb01f1e50bb
|
||||||
F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44
|
F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44
|
||||||
F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc
|
F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
|
||||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||||
F src/tclsqlite.c 501c9a200fd998a268be475be5858febc90b725b
|
F src/tclsqlite.c 501c9a200fd998a268be475be5858febc90b725b
|
||||||
F src/test1.c 9ca440e80e16e53920904a0a5ac7feffb9b2c9a1
|
F src/test1.c 9ca440e80e16e53920904a0a5ac7feffb9b2c9a1
|
||||||
@@ -230,12 +230,12 @@ F src/test_vfstrace.c 2265c9895f350c8d3c39b079998fbe7481505cc1
|
|||||||
F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
|
F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
|
||||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||||
F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
|
F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
|
||||||
F src/trigger.c ec4813709e990a169b6923293e839fa5dfd64282
|
F src/trigger.c bb68c3d1feff3e1335c55a7acf195b9c96ae91ec
|
||||||
F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9
|
F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9
|
||||||
F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60
|
F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60
|
||||||
F src/util.c cd997077bad039efc0597eb027c929658f93c018
|
F src/util.c cd997077bad039efc0597eb027c929658f93c018
|
||||||
F src/vacuum.c 3b2b0998f4f277e4bc61469c2d78d8424d02899b
|
F src/vacuum.c 3b2b0998f4f277e4bc61469c2d78d8424d02899b
|
||||||
F src/vdbe.c 48fe95bd84b7cdeb155c4d2b825c7d19a65c5b3d
|
F src/vdbe.c 1e62a4f18500f86137fda77416c5e55f7336d1d1
|
||||||
F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2
|
F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2
|
||||||
F src/vdbeInt.h 7e2f028ecc1a9faa6f253e7aa8d89cae03662bae
|
F src/vdbeInt.h 7e2f028ecc1a9faa6f253e7aa8d89cae03662bae
|
||||||
F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c
|
F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c
|
||||||
@@ -243,7 +243,7 @@ F src/vdbeaux.c e1ea6edc07b4f33a339cc45a2fbe0a36067d2d8b
|
|||||||
F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
|
F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
|
||||||
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
|
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
|
||||||
F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5
|
F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5
|
||||||
F src/vtab.c 341ae69e949ce583c1729b0177f62ab821e8b42f
|
F src/vtab.c 672f8dadd6ce9ab984af81e3dfb1b5b38715e7b7
|
||||||
F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794
|
F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794
|
||||||
F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840
|
F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840
|
||||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||||
@@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
|||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||||
P 71d7440023f67760d0bff4bd7459fe88bd226f30 fda8fadd837e399d3fab7a9e6894617a5788d679
|
P 1e1a23cc56563d512b28288256c34f05ea15b4aa
|
||||||
R 3fc8950d604a8bfbce215b1e441b51de
|
R 977144757d60ff253970ffcce55b348e
|
||||||
U dan
|
U drh
|
||||||
Z 197ed95a6588fec32711fa656edc064b
|
Z 03b0de28f2209300e8cd6e160282b5b5
|
||||||
|
@@ -1 +1 @@
|
|||||||
1e1a23cc56563d512b28288256c34f05ea15b4aa
|
ae8374af057b6e6546e9265148cfffe32fcb0849
|
@@ -149,6 +149,7 @@ static void analyzeOneTable(
|
|||||||
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||||
assert( iDb>=0 );
|
assert( iDb>=0 );
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||||
if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
|
if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
|
||||||
db->aDb[iDb].zName ) ){
|
db->aDb[iDb].zName ) ){
|
||||||
@@ -390,6 +391,7 @@ static void analyzeDatabase(Parse *pParse, int iDb){
|
|||||||
pParse->nTab += 2;
|
pParse->nTab += 2;
|
||||||
openStatTable(pParse, iDb, iStatCur, 0, 0);
|
openStatTable(pParse, iDb, iStatCur, 0, 0);
|
||||||
iMem = pParse->nMem+1;
|
iMem = pParse->nMem+1;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
|
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
|
||||||
Table *pTab = (Table*)sqliteHashData(k);
|
Table *pTab = (Table*)sqliteHashData(k);
|
||||||
analyzeOneTable(pParse, pTab, 0, iStatCur, iMem);
|
analyzeOneTable(pParse, pTab, 0, iStatCur, iMem);
|
||||||
@@ -600,9 +602,9 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
|||||||
|
|
||||||
assert( iDb>=0 && iDb<db->nDb );
|
assert( iDb>=0 && iDb<db->nDb );
|
||||||
assert( db->aDb[iDb].pBt!=0 );
|
assert( db->aDb[iDb].pBt!=0 );
|
||||||
assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
|
|
||||||
|
|
||||||
/* Clear any prior statistics */
|
/* Clear any prior statistics */
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
|
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
|
||||||
Index *pIdx = sqliteHashData(i);
|
Index *pIdx = sqliteHashData(i);
|
||||||
sqlite3DefaultRowEst(pIdx);
|
sqlite3DefaultRowEst(pIdx);
|
||||||
|
@@ -288,6 +288,31 @@ int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
|
|||||||
}
|
}
|
||||||
#endif /* NDEBUG */
|
#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 && iDb<db->nDb );
|
||||||
|
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 */
|
#else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */
|
||||||
/*
|
/*
|
||||||
** The following are special cases for mutex enter routines for use
|
** The following are special cases for mutex enter routines for use
|
||||||
|
@@ -220,6 +220,7 @@ void sqlite3BtreeCursorList(Btree*);
|
|||||||
/* These routines are used inside assert() statements only. */
|
/* These routines are used inside assert() statements only. */
|
||||||
int sqlite3BtreeHoldsMutex(Btree*);
|
int sqlite3BtreeHoldsMutex(Btree*);
|
||||||
int sqlite3BtreeHoldsAllMutexes(sqlite3*);
|
int sqlite3BtreeHoldsAllMutexes(sqlite3*);
|
||||||
|
int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*);
|
||||||
u32 sqlite3BtreeMutexCounter(Btree*);
|
u32 sqlite3BtreeMutexCounter(Btree*);
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
@@ -232,6 +233,7 @@ void sqlite3BtreeCursorList(Btree*);
|
|||||||
|
|
||||||
# define sqlite3BtreeHoldsMutex(X) 1
|
# define sqlite3BtreeHoldsMutex(X) 1
|
||||||
# define sqlite3BtreeHoldsAllMutexes(X) 1
|
# define sqlite3BtreeHoldsAllMutexes(X) 1
|
||||||
|
# define sqlite3BtreeSchemaMutexHeld(X,Y) 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
31
src/build.c
31
src/build.c
@@ -156,6 +156,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
|||||||
sqlite3VdbeUsesBtree(v, iDb);
|
sqlite3VdbeUsesBtree(v, iDb);
|
||||||
sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
|
sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
|
||||||
if( db->init.busy==0 ){
|
if( db->init.busy==0 ){
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
sqlite3VdbeAddOp3(v, OP_VerifyCookie,
|
sqlite3VdbeAddOp3(v, OP_VerifyCookie,
|
||||||
iDb, pParse->cookieValue[iDb],
|
iDb, pParse->cookieValue[iDb],
|
||||||
db->aDb[iDb].pSchema->iGeneration);
|
db->aDb[iDb].pSchema->iGeneration);
|
||||||
@@ -271,9 +272,12 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
|
|||||||
int nName;
|
int nName;
|
||||||
assert( zName!=0 );
|
assert( zName!=0 );
|
||||||
nName = sqlite3Strlen30(zName);
|
nName = sqlite3Strlen30(zName);
|
||||||
|
/* All mutexes are required for schema access. Make sure we hold them. */
|
||||||
|
assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
|
||||||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||||
if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
|
if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
||||||
p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, nName);
|
p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, nName);
|
||||||
if( p ) break;
|
if( p ) break;
|
||||||
}
|
}
|
||||||
@@ -333,11 +337,14 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
|
|||||||
Index *p = 0;
|
Index *p = 0;
|
||||||
int i;
|
int i;
|
||||||
int nName = sqlite3Strlen30(zName);
|
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; i<db->nDb; i++){
|
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||||
Schema *pSchema = db->aDb[j].pSchema;
|
Schema *pSchema = db->aDb[j].pSchema;
|
||||||
assert( pSchema );
|
assert( pSchema );
|
||||||
if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue;
|
if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
||||||
p = sqlite3HashFind(&pSchema->idxHash, zName, nName);
|
p = sqlite3HashFind(&pSchema->idxHash, zName, nName);
|
||||||
if( p ) break;
|
if( p ) break;
|
||||||
}
|
}
|
||||||
@@ -364,8 +371,10 @@ static void freeIndex(sqlite3 *db, Index *p){
|
|||||||
void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
|
void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
|
||||||
Index *pIndex;
|
Index *pIndex;
|
||||||
int len;
|
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);
|
len = sqlite3Strlen30(zIdxName);
|
||||||
pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0);
|
pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0);
|
||||||
if( ALWAYS(pIndex) ){
|
if( ALWAYS(pIndex) ){
|
||||||
@@ -404,15 +413,15 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
|
|||||||
if( iDb>=0 ){
|
if( iDb>=0 ){
|
||||||
/* Case 1: Reset the single schema identified by iDb */
|
/* Case 1: Reset the single schema identified by iDb */
|
||||||
Db *pDb = &db->aDb[iDb];
|
Db *pDb = &db->aDb[iDb];
|
||||||
if( pDb->pSchema ){
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
assert(iDb==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt)));
|
if( ALWAYS(pDb->pSchema) ){
|
||||||
sqlite3SchemaClear(pDb->pSchema);
|
sqlite3SchemaClear(pDb->pSchema);
|
||||||
}
|
}
|
||||||
/* If any database other than TEMP is reset, then also reset TEMP
|
/* If any database other than TEMP is reset, then also reset TEMP
|
||||||
** since TEMP might be holding triggers that reference tables in the
|
** since TEMP might be holding triggers that reference tables in the
|
||||||
** other database.
|
** 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);
|
sqlite3SchemaClear(pDb->pSchema);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -424,7 +433,6 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
|
|||||||
for(i=0; i<db->nDb; i++){
|
for(i=0; i<db->nDb; i++){
|
||||||
Db *pDb = &db->aDb[i];
|
Db *pDb = &db->aDb[i];
|
||||||
if( pDb->pSchema ){
|
if( pDb->pSchema ){
|
||||||
assert(i==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt)));
|
|
||||||
sqlite3SchemaClear(pDb->pSchema);
|
sqlite3SchemaClear(pDb->pSchema);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -513,6 +521,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
|
|||||||
TESTONLY ( Index *pOld = ) sqlite3HashInsert(
|
TESTONLY ( Index *pOld = ) sqlite3HashInsert(
|
||||||
&pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
|
&pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
|
||||||
);
|
);
|
||||||
|
assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
|
||||||
assert( pOld==pIndex || pOld==0 );
|
assert( pOld==pIndex || pOld==0 );
|
||||||
}
|
}
|
||||||
freeIndex(db, pIndex);
|
freeIndex(db, pIndex);
|
||||||
@@ -547,6 +556,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
|
|||||||
assert( db!=0 );
|
assert( db!=0 );
|
||||||
assert( iDb>=0 && iDb<db->nDb );
|
assert( iDb>=0 && iDb<db->nDb );
|
||||||
assert( zTabName );
|
assert( zTabName );
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */
|
testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */
|
||||||
pDb = &db->aDb[iDb];
|
pDb = &db->aDb[iDb];
|
||||||
p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName,
|
p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName,
|
||||||
@@ -831,6 +841,7 @@ void sqlite3StartTable(
|
|||||||
*/
|
*/
|
||||||
#ifndef SQLITE_OMIT_AUTOINCREMENT
|
#ifndef SQLITE_OMIT_AUTOINCREMENT
|
||||||
if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){
|
if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
pTable->pSchema->pSeqTab = pTable;
|
pTable->pSchema->pSeqTab = pTable;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1291,6 +1302,7 @@ void sqlite3ChangeCookie(Parse *pParse, int iDb){
|
|||||||
int r1 = sqlite3GetTempReg(pParse);
|
int r1 = sqlite3GetTempReg(pParse);
|
||||||
sqlite3 *db = pParse->db;
|
sqlite3 *db = pParse->db;
|
||||||
Vdbe *v = pParse->pVdbe;
|
Vdbe *v = pParse->pVdbe;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1);
|
sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1);
|
||||||
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, r1);
|
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, r1);
|
||||||
sqlite3ReleaseTempReg(pParse, r1);
|
sqlite3ReleaseTempReg(pParse, r1);
|
||||||
@@ -1593,6 +1605,7 @@ void sqlite3EndTable(
|
|||||||
*/
|
*/
|
||||||
if( p->tabFlags & TF_Autoincrement ){
|
if( p->tabFlags & TF_Autoincrement ){
|
||||||
Db *pDb = &db->aDb[iDb];
|
Db *pDb = &db->aDb[iDb];
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
if( pDb->pSchema->pSeqTab==0 ){
|
if( pDb->pSchema->pSeqTab==0 ){
|
||||||
sqlite3NestedParse(pParse,
|
sqlite3NestedParse(pParse,
|
||||||
"CREATE TABLE %Q.sqlite_sequence(name,seq)",
|
"CREATE TABLE %Q.sqlite_sequence(name,seq)",
|
||||||
@@ -1613,6 +1626,7 @@ void sqlite3EndTable(
|
|||||||
if( db->init.busy ){
|
if( db->init.busy ){
|
||||||
Table *pOld;
|
Table *pOld;
|
||||||
Schema *pSchema = p->pSchema;
|
Schema *pSchema = p->pSchema;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName,
|
pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName,
|
||||||
sqlite3Strlen30(p->zName),p);
|
sqlite3Strlen30(p->zName),p);
|
||||||
if( pOld ){
|
if( pOld ){
|
||||||
@@ -1797,6 +1811,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
|||||||
pSelTab->nCol = 0;
|
pSelTab->nCol = 0;
|
||||||
pSelTab->aCol = 0;
|
pSelTab->aCol = 0;
|
||||||
sqlite3DeleteTable(db, pSelTab);
|
sqlite3DeleteTable(db, pSelTab);
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
|
||||||
pTable->pSchema->flags |= DB_UnresetViews;
|
pTable->pSchema->flags |= DB_UnresetViews;
|
||||||
}else{
|
}else{
|
||||||
pTable->nCol = 0;
|
pTable->nCol = 0;
|
||||||
@@ -1817,6 +1832,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
|||||||
*/
|
*/
|
||||||
static void sqliteViewResetAll(sqlite3 *db, int idx){
|
static void sqliteViewResetAll(sqlite3 *db, int idx){
|
||||||
HashElem *i;
|
HashElem *i;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, idx, 0) );
|
||||||
if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
|
if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
|
||||||
for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
|
for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
|
||||||
Table *pTab = sqliteHashData(i);
|
Table *pTab = sqliteHashData(i);
|
||||||
@@ -2227,6 +2243,7 @@ void sqlite3CreateForeignKey(
|
|||||||
pFKey->aAction[0] = (u8)(flags & 0xff); /* ON DELETE action */
|
pFKey->aAction[0] = (u8)(flags & 0xff); /* ON DELETE action */
|
||||||
pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff); /* ON UPDATE action */
|
pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff); /* ON UPDATE action */
|
||||||
|
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
|
||||||
pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash,
|
pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash,
|
||||||
pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey
|
pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey
|
||||||
);
|
);
|
||||||
@@ -2582,6 +2599,7 @@ Index *sqlite3CreateIndex(
|
|||||||
pIndex->onError = (u8)onError;
|
pIndex->onError = (u8)onError;
|
||||||
pIndex->autoIndex = (u8)(pName==0);
|
pIndex->autoIndex = (u8)(pName==0);
|
||||||
pIndex->pSchema = db->aDb[iDb].pSchema;
|
pIndex->pSchema = db->aDb[iDb].pSchema;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
|
|
||||||
/* Check to see if we should honor DESC requests on index columns
|
/* Check to see if we should honor DESC requests on index columns
|
||||||
*/
|
*/
|
||||||
@@ -2711,6 +2729,7 @@ Index *sqlite3CreateIndex(
|
|||||||
*/
|
*/
|
||||||
if( db->init.busy ){
|
if( db->init.busy ){
|
||||||
Index *p;
|
Index *p;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
|
||||||
p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
|
p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
|
||||||
pIndex->zName, sqlite3Strlen30(pIndex->zName),
|
pIndex->zName, sqlite3Strlen30(pIndex->zName),
|
||||||
pIndex);
|
pIndex);
|
||||||
@@ -3464,6 +3483,7 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
|
|||||||
assert( iDb<db->nDb );
|
assert( iDb<db->nDb );
|
||||||
assert( db->aDb[iDb].pBt!=0 || iDb==1 );
|
assert( db->aDb[iDb].pBt!=0 || iDb==1 );
|
||||||
assert( iDb<SQLITE_MAX_ATTACHED+2 );
|
assert( iDb<SQLITE_MAX_ATTACHED+2 );
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
mask = ((yDbMask)1)<<iDb;
|
mask = ((yDbMask)1)<<iDb;
|
||||||
if( (pToplevel->cookieMask & mask)==0 ){
|
if( (pToplevel->cookieMask & mask)==0 ){
|
||||||
pToplevel->cookieMask |= mask;
|
pToplevel->cookieMask |= mask;
|
||||||
@@ -3591,6 +3611,7 @@ static void reindexDatabases(Parse *pParse, char const *zColl){
|
|||||||
HashElem *k; /* For looping over tables in pDb */
|
HashElem *k; /* For looping over tables in pDb */
|
||||||
Table *pTab; /* A table in the database */
|
Table *pTab; /* A table in the database */
|
||||||
|
|
||||||
|
assert( sqlite3BtreeHoldsAllMutexes(db) ); /* Needed for schema access */
|
||||||
for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
|
for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
|
||||||
assert( pDb!=0 );
|
assert( pDb!=0 );
|
||||||
for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
|
for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
|
||||||
|
@@ -1154,6 +1154,7 @@ void sqlite3FkDelete(sqlite3 *db, Table *pTab){
|
|||||||
FKey *pFKey; /* Iterator variable */
|
FKey *pFKey; /* Iterator variable */
|
||||||
FKey *pNext; /* Copy of pFKey->pNextFrom */
|
FKey *pNext; /* Copy of pFKey->pNextFrom */
|
||||||
|
|
||||||
|
assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
|
||||||
for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){
|
for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){
|
||||||
|
|
||||||
/* Remove the FK from the fkeyHash hash table. */
|
/* Remove the FK from the fkeyHash hash table. */
|
||||||
|
@@ -237,6 +237,7 @@ void sqlite3AutoincrementBegin(Parse *pParse){
|
|||||||
for(p = pParse->pAinc; p; p = p->pNext){
|
for(p = pParse->pAinc; p; p = p->pNext){
|
||||||
pDb = &db->aDb[p->iDb];
|
pDb = &db->aDb[p->iDb];
|
||||||
memId = p->regCtr;
|
memId = p->regCtr;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
|
||||||
sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
|
sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
|
||||||
addr = sqlite3VdbeCurrentAddr(v);
|
addr = sqlite3VdbeCurrentAddr(v);
|
||||||
sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0);
|
sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0);
|
||||||
@@ -287,6 +288,7 @@ void sqlite3AutoincrementEnd(Parse *pParse){
|
|||||||
int memId = p->regCtr;
|
int memId = p->regCtr;
|
||||||
|
|
||||||
iRec = sqlite3GetTempReg(pParse);
|
iRec = sqlite3GetTempReg(pParse);
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
|
||||||
sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
|
sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
|
||||||
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1);
|
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1);
|
||||||
j2 = sqlite3VdbeAddOp0(v, OP_Rewind);
|
j2 = sqlite3VdbeAddOp0(v, OP_Rewind);
|
||||||
|
@@ -388,6 +388,7 @@ void sqlite3Pragma(
|
|||||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, size, 1);
|
sqlite3VdbeAddOp2(v, OP_Integer, size, 1);
|
||||||
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1);
|
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1);
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
pDb->pSchema->cache_size = size;
|
pDb->pSchema->cache_size = size;
|
||||||
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
|
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
|
||||||
}
|
}
|
||||||
@@ -690,6 +691,7 @@ void sqlite3Pragma(
|
|||||||
*/
|
*/
|
||||||
if( sqlite3StrICmp(zLeft,"cache_size")==0 ){
|
if( sqlite3StrICmp(zLeft,"cache_size")==0 ){
|
||||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
if( !zRight ){
|
if( !zRight ){
|
||||||
returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
|
returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
|
||||||
}else{
|
}else{
|
||||||
@@ -1110,6 +1112,7 @@ void sqlite3Pragma(
|
|||||||
** Begin by filling registers 2, 3, ... with the root pages numbers
|
** Begin by filling registers 2, 3, ... with the root pages numbers
|
||||||
** for all tables and indices in the database.
|
** for all tables and indices in the database.
|
||||||
*/
|
*/
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
pTbls = &db->aDb[i].pSchema->tblHash;
|
pTbls = &db->aDb[i].pSchema->tblHash;
|
||||||
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
||||||
Table *pTab = sqliteHashData(x);
|
Table *pTab = sqliteHashData(x);
|
||||||
|
@@ -470,6 +470,7 @@ static void schemaIsValid(Parse *pParse){
|
|||||||
** value stored as part of the in-memory schema representation,
|
** value stored as part of the in-memory schema representation,
|
||||||
** set Parse.rc to SQLITE_SCHEMA. */
|
** set Parse.rc to SQLITE_SCHEMA. */
|
||||||
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
|
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
|
if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
|
||||||
pParse->rc = SQLITE_SCHEMA;
|
pParse->rc = SQLITE_SCHEMA;
|
||||||
}
|
}
|
||||||
|
@@ -668,6 +668,20 @@ struct Db {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** An instance of the following structure stores a database schema.
|
** 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 {
|
struct Schema {
|
||||||
int schema_cookie; /* Database schema version number for this file */
|
int schema_cookie; /* Database schema version number for this file */
|
||||||
|
@@ -163,6 +163,7 @@ int sqlite3_db_status(
|
|||||||
int i; /* Used to iterate through schemas */
|
int i; /* Used to iterate through schemas */
|
||||||
int nByte = 0; /* Used to accumulate return value */
|
int nByte = 0; /* Used to accumulate return value */
|
||||||
|
|
||||||
|
sqlite3BtreeEnterAll(db);
|
||||||
db->pnBytesFreed = &nByte;
|
db->pnBytesFreed = &nByte;
|
||||||
for(i=0; i<db->nDb; i++){
|
for(i=0; i<db->nDb; i++){
|
||||||
Schema *pSchema = db->aDb[i].pSchema;
|
Schema *pSchema = db->aDb[i].pSchema;
|
||||||
@@ -189,6 +190,7 @@ int sqlite3_db_status(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
db->pnBytesFreed = 0;
|
db->pnBytesFreed = 0;
|
||||||
|
sqlite3BtreeLeaveAll(db);
|
||||||
|
|
||||||
*pHighwater = 0;
|
*pHighwater = 0;
|
||||||
*pCurrent = nByte;
|
*pCurrent = nByte;
|
||||||
|
@@ -54,6 +54,7 @@ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
|
|||||||
|
|
||||||
if( pTmpSchema!=pTab->pSchema ){
|
if( pTmpSchema!=pTab->pSchema ){
|
||||||
HashElem *p;
|
HashElem *p;
|
||||||
|
assert( sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) );
|
||||||
for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
|
for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
|
||||||
Trigger *pTrig = (Trigger *)sqliteHashData(p);
|
Trigger *pTrig = (Trigger *)sqliteHashData(p);
|
||||||
if( pTrig->pTabSchema==pTab->pSchema
|
if( pTrig->pTabSchema==pTab->pSchema
|
||||||
@@ -165,6 +166,7 @@ void sqlite3BeginTrigger(
|
|||||||
if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
|
if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
|
||||||
goto trigger_cleanup;
|
goto trigger_cleanup;
|
||||||
}
|
}
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),
|
if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),
|
||||||
zName, sqlite3Strlen30(zName)) ){
|
zName, sqlite3Strlen30(zName)) ){
|
||||||
if( !noErr ){
|
if( !noErr ){
|
||||||
@@ -304,6 +306,7 @@ void sqlite3FinishTrigger(
|
|||||||
if( db->init.busy ){
|
if( db->init.busy ){
|
||||||
Trigger *pLink = pTrig;
|
Trigger *pLink = pTrig;
|
||||||
Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
|
Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
pTrig = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), pTrig);
|
pTrig = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), pTrig);
|
||||||
if( pTrig ){
|
if( pTrig ){
|
||||||
db->mallocFailed = 1;
|
db->mallocFailed = 1;
|
||||||
@@ -485,9 +488,11 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
|
|||||||
zDb = pName->a[0].zDatabase;
|
zDb = pName->a[0].zDatabase;
|
||||||
zName = pName->a[0].zName;
|
zName = pName->a[0].zName;
|
||||||
nName = sqlite3Strlen30(zName);
|
nName = sqlite3Strlen30(zName);
|
||||||
|
assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
|
||||||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||||
if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
|
if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
||||||
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName);
|
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName);
|
||||||
if( pTrigger ) break;
|
if( pTrigger ) break;
|
||||||
}
|
}
|
||||||
@@ -576,8 +581,11 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
|
|||||||
** Remove a trigger from the hash tables of the sqlite* pointer.
|
** Remove a trigger from the hash tables of the sqlite* pointer.
|
||||||
*/
|
*/
|
||||||
void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
|
void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
|
||||||
Hash *pHash = &(db->aDb[iDb].pSchema->trigHash);
|
|
||||||
Trigger *pTrigger;
|
Trigger *pTrigger;
|
||||||
|
Hash *pHash;
|
||||||
|
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
|
pHash = &(db->aDb[iDb].pSchema->trigHash);
|
||||||
pTrigger = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), 0);
|
pTrigger = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), 0);
|
||||||
if( ALWAYS(pTrigger) ){
|
if( ALWAYS(pTrigger) ){
|
||||||
if( pTrigger->pSchema==pTrigger->pTabSchema ){
|
if( pTrigger->pSchema==pTrigger->pTabSchema ){
|
||||||
|
@@ -2880,6 +2880,7 @@ case OP_SetCookie: { /* in3 */
|
|||||||
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
|
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
|
||||||
pDb = &db->aDb[pOp->p1];
|
pDb = &db->aDb[pOp->p1];
|
||||||
assert( pDb->pBt!=0 );
|
assert( pDb->pBt!=0 );
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
|
||||||
pIn3 = &aMem[pOp->p3];
|
pIn3 = &aMem[pOp->p3];
|
||||||
sqlite3VdbeMemIntegerify(pIn3);
|
sqlite3VdbeMemIntegerify(pIn3);
|
||||||
/* See note about index shifting on OP_ReadCookie */
|
/* See note about index shifting on OP_ReadCookie */
|
||||||
@@ -2926,6 +2927,7 @@ case OP_VerifyCookie: {
|
|||||||
|
|
||||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||||
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
|
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
|
||||||
pBt = db->aDb[pOp->p1].pBt;
|
pBt = db->aDb[pOp->p1].pBt;
|
||||||
if( pBt ){
|
if( pBt ){
|
||||||
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
|
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
|
||||||
@@ -3036,6 +3038,7 @@ case OP_OpenWrite: {
|
|||||||
assert( pX!=0 );
|
assert( pX!=0 );
|
||||||
if( pOp->opcode==OP_OpenWrite ){
|
if( pOp->opcode==OP_OpenWrite ){
|
||||||
wrFlag = 1;
|
wrFlag = 1;
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||||
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
|
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
|
||||||
p->minWriteFileFormat = pDb->pSchema->file_format;
|
p->minWriteFileFormat = pDb->pSchema->file_format;
|
||||||
}
|
}
|
||||||
|
@@ -387,6 +387,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
|
|||||||
Schema *pSchema = pTab->pSchema;
|
Schema *pSchema = pTab->pSchema;
|
||||||
const char *zName = pTab->zName;
|
const char *zName = pTab->zName;
|
||||||
int nName = sqlite3Strlen30(zName);
|
int nName = sqlite3Strlen30(zName);
|
||||||
|
assert( sqlite3SchemaMutexHeld(db, 0, pSchema) );
|
||||||
pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);
|
pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);
|
||||||
if( pOld ){
|
if( pOld ){
|
||||||
db->mallocFailed = 1;
|
db->mallocFailed = 1;
|
||||||
|
Reference in New Issue
Block a user