From c567636deb655415c1fce8daa323d18a22a892ae Mon Sep 17 00:00:00 2001 From: pedrocarlo Date: Mon, 21 Jul 2025 22:27:42 -0300 Subject: [PATCH] Adjust Transaction OpCode to accept schema cookie + check if cookie changed --- core/translate/mod.rs | 4 +++- core/translate/transaction.rs | 8 +++++++- core/vdbe/builder.rs | 7 ++++++- core/vdbe/execute.rs | 11 ++++++++++- core/vdbe/explain.rs | 4 ++-- core/vdbe/insn.rs | 5 +++-- 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/core/translate/mod.rs b/core/translate/mod.rs index badbaac3b..e3a2eb940 100644 --- a/core/translate/mod.rs +++ b/core/translate/mod.rs @@ -123,7 +123,9 @@ pub fn translate_inner( ast::Stmt::Attach { expr, db_name, key } => { attach::translate_attach(&expr, &db_name, &key, schema, syms, program)? } - ast::Stmt::Begin(tx_type, tx_name) => translate_tx_begin(tx_type, tx_name, program)?, + ast::Stmt::Begin(tx_type, tx_name) => { + translate_tx_begin(tx_type, tx_name, &schema, program)? + } ast::Stmt::Commit(tx_name) => translate_tx_commit(tx_name, program)?, ast::Stmt::CreateIndex { unique, diff --git a/core/translate/transaction.rs b/core/translate/transaction.rs index 47fdc3df8..8a4e6ab21 100644 --- a/core/translate/transaction.rs +++ b/core/translate/transaction.rs @@ -1,3 +1,4 @@ +use crate::schema::Schema; use crate::translate::{ProgramBuilder, ProgramBuilderOpts}; use crate::vdbe::insn::Insn; use crate::Result; @@ -6,6 +7,7 @@ use turso_sqlite3_parser::ast::{Name, TransactionType}; pub fn translate_tx_begin( tx_type: Option, _tx_name: Option, + schema: &Schema, mut program: ProgramBuilder, ) -> Result { program.extend(&ProgramBuilderOpts { @@ -22,7 +24,11 @@ pub fn translate_tx_begin( }); } TransactionType::Immediate | TransactionType::Exclusive => { - program.emit_insn(Insn::Transaction { db: 0, write: true }); + program.emit_insn(Insn::Transaction { + db: 0, + write: true, + schema_cookie: schema.schema_version, + }); // TODO: Emit transaction instruction on temporary tables when we support them. program.emit_insn(Insn::AutoCommit { auto_commit: false, diff --git a/core/vdbe/builder.rs b/core/vdbe/builder.rs index b9abed8ed..a71c01ceb 100644 --- a/core/vdbe/builder.rs +++ b/core/vdbe/builder.rs @@ -771,8 +771,13 @@ impl ProgramBuilder { TransactionMode::Read => self.emit_insn(Insn::Transaction { db: 0, write: false, + schema_cookie: 0, // TODO: placeholder until we have epilogue being called only in one place + }), + TransactionMode::Write => self.emit_insn(Insn::Transaction { + db: 0, + write: true, + schema_cookie: 0, // TODO: placeholder until we have epilogue being called only in one place }), - TransactionMode::Write => self.emit_insn(Insn::Transaction { db: 0, write: true }), TransactionMode::None => {} } diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index 56bb30e23..c3bb8d5eb 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -1989,9 +1989,18 @@ pub fn op_transaction( _pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Transaction { db, write } = insn else { + let Insn::Transaction { + db, + write, + schema_cookie, + } = insn + else { unreachable!("unexpected Insn {:?}", insn) }; + let header_schema_cookie = header_accessor::get_schema_cookie(pager)?; + if header_schema_cookie != *schema_cookie { + return Err(LimboError::SchemaUpdated); + } let conn = program.connection.clone(); if *write && conn._db.open_flags.contains(OpenFlags::ReadOnly) { return Err(LimboError::ReadOnly); diff --git a/core/vdbe/explain.rs b/core/vdbe/explain.rs index 0fefedcc2..b891632ae 100644 --- a/core/vdbe/explain.rs +++ b/core/vdbe/explain.rs @@ -647,11 +647,11 @@ pub fn insn_to_str( 0, "".to_string(), ), - Insn::Transaction { db, write } => ( + Insn::Transaction { db, write , schema_cookie} => ( "Transaction", *db as i32, *write as i32, - 0, + *schema_cookie as i32, Value::build_text(""), 0, format!("iDb={db} write={write}"), diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index 6b41d1900..d3a326943 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -459,8 +459,9 @@ pub enum Insn { /// Start a transaction. Transaction { - db: usize, // p1 - write: bool, // p2 + db: usize, // p1 + write: bool, // p2 + schema_cookie: u32, // p3 }, /// Set database auto-commit mode and potentially rollback.