diff options
author | drh <drh@noemail.net> | 2011-03-18 21:55:46 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2011-03-18 21:55:46 +0000 |
commit | c2a75551ef8a944e01df64511190bce9be6acb19 (patch) | |
tree | f0b4f4315f2a4a17a73d5d93315ad5300b939067 /src | |
parent | d416fe799569ff1a570009187d218e5d0dc7c86c (diff) | |
download | sqlite-c2a75551ef8a944e01df64511190bce9be6acb19.tar.gz sqlite-c2a75551ef8a944e01df64511190bce9be6acb19.zip |
Add a generation counter to the Schema object and enhance OP_VerifySchema
to also check the Schema generation. Fix for
ticket [f7b4edece25c99].
FossilOrigin-Name: 36c04dd1695f0899b53ce58738181b146fc005ed
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 4 | ||||
-rw-r--r-- | src/callback.c | 5 | ||||
-rw-r--r-- | src/sqliteInt.h | 1 | ||||
-rw-r--r-- | src/vdbe.c | 11 | ||||
-rw-r--r-- | src/vdbeblob.c | 1 |
5 files changed, 17 insertions, 5 deletions
diff --git a/src/build.c b/src/build.c index 2cfb1f45a..79ac436f0 100644 --- a/src/build.c +++ b/src/build.c @@ -156,7 +156,9 @@ void sqlite3FinishCoding(Parse *pParse){ sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0); if( db->init.busy==0 ){ - sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); + sqlite3VdbeAddOp3(v, OP_VerifyCookie, + iDb, pParse->cookieValue[iDb], + db->aDb[iDb].pSchema->iGeneration); } } #ifndef SQLITE_OMIT_VIRTUALTABLE diff --git a/src/callback.c b/src/callback.c index eaff6d0e0..fdee9bc09 100644 --- a/src/callback.c +++ b/src/callback.c @@ -427,7 +427,10 @@ void sqlite3SchemaFree(void *p){ sqlite3HashClear(&temp1); sqlite3HashClear(&pSchema->fkeyHash); pSchema->pSeqTab = 0; - pSchema->flags &= ~DB_SchemaLoaded; + if( pSchema->flags & DB_SchemaLoaded ){ + pSchema->iGeneration++; + pSchema->flags &= ~DB_SchemaLoaded; + } } /* diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 0142d1e9d..c2d4607be 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -671,6 +671,7 @@ struct Db { */ struct Schema { int schema_cookie; /* Database schema version number for this file */ + int iGeneration; /* Generation counter. Incremented with each change */ Hash tblHash; /* All tables indexed by name */ Hash idxHash; /* All (named) indices indexed by name */ Hash trigHash; /* All triggers indexed by name */ diff --git a/src/vdbe.c b/src/vdbe.c index 828baa529..b7dfd334f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2890,10 +2890,12 @@ case OP_SetCookie: { /* in3 */ break; } -/* Opcode: VerifyCookie P1 P2 * +/* Opcode: VerifyCookie P1 P2 P3 * * ** ** Check the value of global database parameter number 0 (the -** schema version) and make sure it is equal to P2. +** schema version) and make sure it is equal to P2 and that the +** generation counter on the local schema parse equals P3. +** ** P1 is the database number which is 0 for the main database file ** and 1 for the file holding temporary tables and some higher number ** for auxiliary databases. @@ -2908,16 +2910,19 @@ case OP_SetCookie: { /* in3 */ */ case OP_VerifyCookie: { int iMeta; + int iGen; Btree *pBt; + assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (1<<pOp->p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); + iGen = db->aDb[pOp->p1].pSchema->iGeneration; }else{ iMeta = 0; } - if( iMeta!=pOp->p2 ){ + if( iMeta!=pOp->p2 || iGen!=pOp->p3 ){ sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); /* If the schema-cookie from the database file matches the cookie diff --git a/src/vdbeblob.c b/src/vdbeblob.c index f26cc87ea..18fdd465a 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -266,6 +266,7 @@ int sqlite3_blob_open( /* Configure the OP_VerifyCookie */ sqlite3VdbeChangeP1(v, 1, iDb); sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie); + sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration); /* Make sure a mutex is held on the table to be accessed */ sqlite3VdbeUsesBtree(v, iDb); |