summaryrefslogtreecommitdiff
path: root/ext/pdo_sqlite/sqlite/src/vdbe.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/vdbe.c')
-rw-r--r--ext/pdo_sqlite/sqlite/src/vdbe.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/ext/pdo_sqlite/sqlite/src/vdbe.c b/ext/pdo_sqlite/sqlite/src/vdbe.c
index cab35069cc..9bbc65a2eb 100644
--- a/ext/pdo_sqlite/sqlite/src/vdbe.c
+++ b/ext/pdo_sqlite/sqlite/src/vdbe.c
@@ -2521,7 +2521,23 @@ case OP_VerifyCookie: { /* no-push */
}
if( rc==SQLITE_OK && iMeta!=pOp->p2 ){
sqlite3SetString(&p->zErrMsg, "database schema has changed", (char*)0);
- sqlite3ResetInternalSchema(db, pOp->p1);
+ /* If the schema-cookie from the database file matches the cookie
+ ** stored with the in-memory representation of the schema, do
+ ** not reload the schema from the database file.
+ **
+ ** If virtual-tables are in use, this is not just an optimisation.
+ ** Often, v-tables store their data in other SQLite tables, which
+ ** are queried from within xNext() and other v-table methods using
+ ** prepared queries. If such a query is out-of-date, we do not want to
+ ** discard the database schema, as the user code implementing the
+ ** v-table would have to be ready for the sqlite3_vtab structure itself
+ ** to be invalidated whenever sqlite3_step() is called from within
+ ** a v-table method.
+ */
+ if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
+ sqlite3ResetInternalSchema(db, pOp->p1);
+ }
+
sqlite3ExpirePreparedStatements(db);
rc = SQLITE_SCHEMA;
}
@@ -4881,7 +4897,7 @@ case OP_VUpdate: { /* no-push */
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
sqlite3VtabLock(pVtab);
rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
- sqlite3VtabUnlock(pVtab);
+ sqlite3VtabUnlock(db, pVtab);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( pOp->p1 && rc==SQLITE_OK ){
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );