aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build.c4
-rw-r--r--src/callback.c5
-rw-r--r--src/sqliteInt.h1
-rw-r--r--src/vdbe.c11
-rw-r--r--src/vdbeblob.c1
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);