core/vdbe: AutoCommit instruction

This commit is contained in:
Pekka Enberg
2025-02-14 09:47:50 +02:00
parent 248a369afc
commit 34b0c7c09a
7 changed files with 55 additions and 5 deletions

View File

@@ -412,7 +412,7 @@ Modifiers:
| AggStep | Yes | |
| AggStep | Yes | |
| And | Yes | |
| AutoCommit | No | |
| AutoCommit | Yes | |
| BitAnd | Yes | |
| BitNot | Yes | |
| BitOr | Yes | |

View File

@@ -19,6 +19,8 @@ pub enum LimboError {
ConversionError(String),
#[error("Env variable error: {0}")]
EnvVarError(#[from] std::env::VarError),
#[error("Transaction error: {0}")]
TxError(String),
#[error("I/O error: {0}")]
IOError(#[from] std::io::Error),
#[cfg(all(target_os = "linux", feature = "io_uring"))]

View File

@@ -161,6 +161,7 @@ impl Database {
pager,
schema: schema.clone(),
header,
auto_commit: RefCell::new(true),
transaction_state: RefCell::new(TransactionState::None),
last_insert_rowid: Cell::new(0),
last_change: Cell::new(0),
@@ -179,6 +180,7 @@ impl Database {
schema: self.schema.clone(),
header: self.header.clone(),
last_insert_rowid: Cell::new(0),
auto_commit: RefCell::new(true),
transaction_state: RefCell::new(TransactionState::None),
last_change: Cell::new(0),
total_changes: Cell::new(0),
@@ -263,6 +265,7 @@ pub struct Connection {
pager: Rc<Pager>,
schema: Rc<RefCell<Schema>>,
header: Rc<RefCell<DatabaseHeader>>,
auto_commit: RefCell<bool>,
transaction_state: RefCell<TransactionState>,
last_insert_rowid: Cell<u64>,
last_change: Cell<i64>,

View File

@@ -448,7 +448,6 @@ impl ProgramBuilder {
database_header,
comments: self.comments,
connection,
auto_commit: true,
parameters: self.parameters,
n_change: Cell::new(0),
change_cnt_on,

View File

@@ -1238,6 +1238,18 @@ pub fn insn_to_str(
0,
"".to_string(),
),
Insn::AutoCommit {
auto_commit,
rollback,
} => (
"AutoCommit",
*auto_commit as i32,
*rollback as i32,
0,
OwnedValue::build_text(""),
0,
format!("auto_commit={}, rollback={}", auto_commit, rollback),
),
};
format!(
"{:<4} {:<17} {:<4} {:<4} {:<4} {:<13} {:<2} {}",

View File

@@ -320,6 +320,12 @@ pub enum Insn {
write: bool,
},
// Set database auto-commit mode and potentially rollback.
AutoCommit {
auto_commit: bool,
rollback: bool,
},
// Branch to the given PC.
Goto {
target_pc: BranchOffset,

View File

@@ -411,7 +411,6 @@ pub struct Program {
pub comments: Option<HashMap<InsnReference, &'static str>>,
pub parameters: crate::parameters::Parameters,
pub connection: Weak<Connection>,
pub auto_commit: bool,
pub n_change: Cell<i64>,
pub change_cnt_on: bool,
pub result_columns: Vec<ResultSetColumn>,
@@ -1131,17 +1130,18 @@ impl Program {
)));
}
}
tracing::trace!("Halt auto_commit {}", self.auto_commit);
let connection = self
.connection
.upgrade()
.expect("only weak ref to connection?");
let auto_commit = *connection.auto_commit.borrow();
tracing::trace!("Halt auto_commit {}", auto_commit);
let current_state = connection.transaction_state.borrow().clone();
if current_state == TransactionState::Read {
pager.end_read_tx()?;
return Ok(StepResult::Done);
}
return if self.auto_commit {
return if auto_commit {
match pager.end_tx() {
Ok(crate::storage::wal::CheckpointStatus::IO) => Ok(StepResult::IO),
Ok(crate::storage::wal::CheckpointStatus::Done(_)) => {
@@ -1195,6 +1195,34 @@ impl Program {
}
state.pc += 1;
}
Insn::AutoCommit {
auto_commit,
rollback,
} => {
let conn = self.connection.upgrade().unwrap();
if *auto_commit != *conn.auto_commit.borrow() {
if *rollback {
todo!("Rollback is not implemented");
} else {
conn.auto_commit.replace(*auto_commit);
}
} else {
if !*auto_commit {
return Err(LimboError::TxError(
"cannot start a transaction within a transaction".to_string(),
));
} else if *rollback {
return Err(LimboError::TxError(
"cannot rollback - no transaction is active".to_string(),
));
} else {
return Err(LimboError::TxError(
"cannot commit - no transaction is active".to_string(),
));
}
}
state.pc += 1;
}
Insn::Goto { target_pc } => {
assert!(target_pc.is_offset());
state.pc = target_pc.to_offset_int();