From 41e13e1268e1d9edeb3a0fff552ed4a2cc7b900e Mon Sep 17 00:00:00 2001 From: drh <drh@noemail.net> Date: Thu, 7 Nov 2013 14:09:39 +0000 Subject: [PATCH] Make sure cached KeyInfo objects are only valid for a single database connection. Clear all cached KeyInfo objects on any collating sequence change. FossilOrigin-Name: 55eea1782aead6a6aaf93f14d85486f8fd2209ad --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/build.c | 15 ++++++++++----- src/main.c | 27 +++++++++++++++++++++++++++ src/select.c | 3 +-- src/vdbe.c | 19 +++++++++++-------- 6 files changed, 59 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index f47df63713..21d31fb94d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Reference\scount\sthe\sKeyInfo\sobject.\s\sCache\sa\scopy\sof\san\sappropriate\sKeyInfo\nfor\seach\sindex\sin\sthe\sIndex\sobject,\sand\sreuse\sthat\sone\scopy\sas\smuch\sas\spossible. -D 2013-11-06T19:59:23.699 +C Make\ssure\scached\sKeyInfo\sobjects\sare\sonly\svalid\sfor\sa\ssingle\sdatabase\nconnection.\s\sClear\sall\scached\sKeyInfo\sobjects\son\sany\scollating\ssequence\s\nchange. +D 2013-11-07T14:09:39.090 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -168,7 +168,7 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c 260dedc13119e6fb7930380bd3d294b98362bf5a F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0 -F src/build.c a74889231fc0bb9196f88e8ae29551e65461446a +F src/build.c d4d5ceedf196a7da36d6dd15f4d073cb68c8f079 F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c @@ -187,7 +187,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303 -F src/main.c 9bcfc400b5f727dd562996d0bdf507bfbcf31583 +F src/main.c 32bf1e6e164a6fa0ddf1bf2616c6eafbefd6e9b0 F src/malloc.c 543a8eb5508eaf4cadf55a9b503379eba2088128 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 437c7c4af964895d4650f29881df63535caaa1fa @@ -218,7 +218,7 @@ F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 F src/resolve.c e729889b2c7a680ba4aa7296efa72c09369956d8 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c 76477fe7f07bb04891378d9b11ff701807565923 +F src/select.c 60af46f5f6bc3803c27af3edd8881ed2d0c3f19f F src/shell.c 03d8d9b4052430343ff30d646334621f980f1202 F src/sqlite.h.in a8cad179541b8d171fed425a737084702ef462ef F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e @@ -279,7 +279,7 @@ F src/update.c 516e0ea0f853bfb852e098f3b643a3f2bfd423ef F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918 F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 3493de8d6214aa290d793c7a4062f32bb3d35742 +F src/vdbe.c ff0170cd3c5fea68386818cbd19a23bbfc711364 F src/vdbe.h 8d5a7351024d80374fc0acdbbe3cfe65c51ba8b6 F src/vdbeInt.h f2fa3ceccceeb757773921fb08af7c6e9f3caa1c F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed @@ -1134,7 +1134,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 474555002d45f8741faceea599c057eef4e7931e -R 11b6d6465d5ad443e1f3ccfcc5b7af21 +P defd5205a7cc3543cdd18f906f568e943b8b3a2c +R 0a7295680bb25731824803a052760874 U drh -Z ed3df5fd60cd920e736dadf48c637db6 +Z 813173a99e20e783c085a6d86fb32041 diff --git a/manifest.uuid b/manifest.uuid index 1f612a840b..01ab178fce 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -defd5205a7cc3543cdd18f906f568e943b8b3a2c \ No newline at end of file +55eea1782aead6a6aaf93f14d85486f8fd2209ad \ No newline at end of file diff --git a/src/build.c b/src/build.c index 11de95eaf3..27ea43e2f3 100644 --- a/src/build.c +++ b/src/build.c @@ -4154,13 +4154,18 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ ** when it has finished using it. */ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ - int i; - int nCol = pIdx->nColumn; - int nKey = pIdx->nKeyCol; - KeyInfo *pKey; - if( pParse->nErr ) return 0; +#ifndef SQLITE_OMIT_SHARED_CACHE + if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){ + sqlite3KeyInfoUnref(pIdx->pKeyInfo); + pIdx->pKeyInfo = 0; + } +#endif if( pIdx->pKeyInfo==0 ){ + int i; + int nCol = pIdx->nColumn; + int nKey = pIdx->nKeyCol; + KeyInfo *pKey; if( pIdx->uniqNotNull ){ pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); }else{ diff --git a/src/main.c b/src/main.c index a8b6c84ec0..5e03662d38 100644 --- a/src/main.c +++ b/src/main.c @@ -1951,6 +1951,32 @@ const char *sqlite3_errstr(int rc){ return sqlite3ErrStr(rc); } +/* +** Invalidate all cached KeyInfo objects for database connection "db" +*/ +static void invalidateCachedKeyInfo(sqlite3 *db){ + Db *pDb; /* A single database */ + int iDb; /* The database index number */ + HashElem *k; /* For looping over tables in pDb */ + Table *pTab; /* A table in the database */ + Index *pIdx; /* Each index */ + + for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ + if( pDb->pBt==0 ) continue; + sqlite3BtreeEnter(pDb->pBt); + for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ + pTab = (Table*)sqliteHashData(k); + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){ + sqlite3KeyInfoUnref(pIdx->pKeyInfo); + pIdx->pKeyInfo = 0; + } + } + } + sqlite3BtreeLeave(pDb->pBt); + } +} + /* ** Create a new collating function for database "db". The name is zName ** and the encoding is enc. @@ -1995,6 +2021,7 @@ static int createCollation( return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); + invalidateCachedKeyInfo(db); /* If collation sequence pColl was created directly by a call to ** sqlite3_create_collation, and not generated by synthCollSeq(), diff --git a/src/select.c b/src/select.c index 2d985d6c30..cab161fd2d 100644 --- a/src/select.c +++ b/src/select.c @@ -828,9 +828,8 @@ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ void sqlite3KeyInfoUnref(KeyInfo *p){ if( p ){ assert( p->nRef>0 ); - assert( p->db==0 || p->db->pnBytesFreed==0 ); p->nRef--; - if( p->nRef==0 ) sqlite3DbFree(p->db, p); + if( p->nRef==0 ) sqlite3_free(p); } } diff --git a/src/vdbe.c b/src/vdbe.c index 9851f4a33c..97b35196d3 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3288,7 +3288,8 @@ case OP_OpenWrite: { } if( pOp->p4type==P4_KEYINFO ){ pKeyInfo = pOp->p4.pKeyInfo; - pKeyInfo->enc = ENC(p->db); + assert( pKeyInfo->enc==ENC(db) ); + assert( pKeyInfo->db==db ); nField = pKeyInfo->nField+pKeyInfo->nXField; }else if( pOp->p4type==P4_INT32 ){ nField = pOp->p4.i; @@ -3345,13 +3346,14 @@ case OP_OpenWrite: { case OP_OpenAutoindex: case OP_OpenEphemeral: { VdbeCursor *pCx; + KeyInfo *pKeyInfo; + static const int vfsFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TRANSIENT_DB; - assert( pOp->p1>=0 ); pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); if( pCx==0 ) goto no_mem; @@ -3367,16 +3369,16 @@ case OP_OpenEphemeral: { ** opening it. If a transient table is required, just use the ** automatically created table with root-page 1 (an BLOB_INTKEY table). */ - if( pOp->p4.pKeyInfo ){ + if( (pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ int pgno; assert( pOp->p4type==P4_KEYINFO ); rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); - rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, - (KeyInfo*)pOp->p4.z, pCx->pCursor); - pCx->pKeyInfo = pOp->p4.pKeyInfo; - pCx->pKeyInfo->enc = ENC(p->db); + assert( pKeyInfo->db==db ); + assert( pKeyInfo->enc==ENC(db) ); + pCx->pKeyInfo = pKeyInfo; + rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, pKeyInfo, pCx->pCursor); } pCx->isTable = 0; }else{ @@ -3401,7 +3403,8 @@ case OP_SorterOpen: { pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); if( pCx==0 ) goto no_mem; pCx->pKeyInfo = pOp->p4.pKeyInfo; - pCx->pKeyInfo->enc = ENC(p->db); + assert( pCx->pKeyInfo->db==db ); + assert( pCx->pKeyInfo->enc==ENC(db) ); pCx->isSorter = 1; rc = sqlite3VdbeSorterInit(db, pCx); break;