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
This commit is contained in:
drh 2013-11-07 14:09:39 +00:00
parent 2ec2fb2269
commit 41e13e1268
6 changed files with 59 additions and 25 deletions

View File

@ -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

View File

@ -1 +1 @@
defd5205a7cc3543cdd18f906f568e943b8b3a2c
55eea1782aead6a6aaf93f14d85486f8fd2209ad

View File

@ -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{

View File

@ -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(),

View File

@ -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);
}
}

View File

@ -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;