diff --git a/core/lib.rs b/core/lib.rs index 75b85849d..f331a8952 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -47,6 +47,7 @@ use crate::types::{WalFrameInfo, WalState}; #[cfg(feature = "fs")] use crate::util::{OpenMode, OpenOptions}; use crate::vdbe::metrics::ConnectionMetrics; +use crate::vdbe::PROGRAM_STATE_DONE; use crate::vtab::VirtualTable; use crate::{incremental::view::AllViewsTxState, translate::emitter::TransactionMode}; use core::str; @@ -2572,6 +2573,7 @@ impl Statement { fn reprepare(&mut self) -> Result<()> { tracing::trace!("repreparing statement"); let conn = self.program.connection.clone(); + *conn.schema.write() = conn.db.clone_schema(); self.program = { let mut parser = Parser::new(self.program.sql.as_bytes()); @@ -2600,7 +2602,7 @@ impl Statement { QueryMode::Explain => (EXPLAIN_COLUMNS.len(), 0), QueryMode::ExplainQueryPlan => (EXPLAIN_QUERY_PLAN_COLUMNS.len(), 0), }; - self._reset(Some(max_registers), Some(cursor_count)); + self.reset_internal(Some(max_registers), Some(cursor_count)); // Load the parameters back into the state self.state.parameters = parameters; Ok(()) @@ -2714,10 +2716,16 @@ impl Statement { } pub fn reset(&mut self) { - self._reset(None, None); + self.reset_internal(None, None); } - pub fn _reset(&mut self, max_registers: Option, max_cursors: Option) { + pub(crate) fn mark_as_done(&self) { + self.program + .program_state + .store(PROGRAM_STATE_DONE, Ordering::SeqCst); + } + + fn reset_internal(&mut self, max_registers: Option, max_cursors: Option) { self.state.reset(max_registers, max_cursors); self.program .abort(self.mv_store.as_ref(), &self.pager, None); diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index ec5d6f3f9..d3ef412f1 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -8018,12 +8018,15 @@ pub fn op_drop_column( let schema = conn.schema.read(); for (view_name, view) in schema.views.iter() { let view_select_sql = format!("SELECT * FROM {view_name}"); - conn.prepare(view_select_sql.as_str()).map_err(|e| { + let stmt = conn.prepare(view_select_sql.as_str()).map_err(|e| { LimboError::ParseError(format!( "cannot drop column \"{}\": referenced in VIEW {view_name}: {}", column_name, view.sql, )) })?; + // this is internal statement running during active Program execution + // so, we must not interact with transaction state and explicitly mark this statement as done avoiding cleanup on reset + stmt.mark_as_done(); } } @@ -8149,12 +8152,15 @@ pub fn op_alter_column( for (view_name, view) in schema.views.iter() { let view_select_sql = format!("SELECT * FROM {view_name}"); // FIXME: this should rewrite the view to reference the new column name - conn.prepare(view_select_sql.as_str()).map_err(|e| { + let stmt = conn.prepare(view_select_sql.as_str()).map_err(|e| { LimboError::ParseError(format!( "cannot rename column \"{}\": referenced in VIEW {view_name}: {}", old_column_name, view.sql, )) })?; + // this is internal statement running during active Program execution + // so, we must not interact with transaction state and explicitly mark this statement as done avoiding cleanup on reset + stmt.mark_as_done(); } } diff --git a/core/vdbe/mod.rs b/core/vdbe/mod.rs index ed7fa4a12..ed09762e1 100644 --- a/core/vdbe/mod.rs +++ b/core/vdbe/mod.rs @@ -483,9 +483,9 @@ macro_rules! get_cursor { }; } -const PROGRAM_STATE_ACTIVE: u32 = 0; -const PROGRAM_STATE_ABORTED: u32 = 1; -const PROGRAM_STATE_DONE: u32 = 2; +pub(crate) const PROGRAM_STATE_ACTIVE: u32 = 1; +pub(crate) const PROGRAM_STATE_ABORTED: u32 = 2; +pub(crate) const PROGRAM_STATE_DONE: u32 = 3; pub struct Program { pub max_registers: usize,