Skip to content

Commit

Permalink
Merge 'Improve changes() and total_changes() functions and add tests'…
Browse files Browse the repository at this point in the history
… from Ben Li

#144
- The previous `changes()` function returns 1 no matter what
- Modified `changes()` and `total_changes()` to be closer to the sqlite
implementation
    - Store local `n_change` counter in the `Program` struct
    - Update `last_change` and `total_changes` values in `Connection`
struct on halt
    - Add `change_cnt_on` flag to `Program` struct that is `true` for
insert and delete (also need later on for update)
- Added TCL tests

Closes #749
  • Loading branch information
penberg committed Jan 20, 2025
2 parents 02b8fb8 + 2ec52d1 commit 11551e8
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 10 deletions.
4 changes: 2 additions & 2 deletions COMPAT.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Feature support of [sqlite expr syntax](https://www.sqlite.org/lang_expr.html).
| Function | Status | Comment |
|------------------------------|--------|---------|
| abs(X) | Yes | |
| changes() | No | |
| changes() | Partial| Still need to support update statements and triggers |
| char(X1,X2,...,XN) | Yes | |
| coalesce(X,Y,...) | Yes | |
| concat(X,...) | Yes | |
Expand Down Expand Up @@ -158,7 +158,7 @@ Feature support of [sqlite expr syntax](https://www.sqlite.org/lang_expr.html).
| substr(X,Y) | Yes | |
| substring(X,Y,Z) | Yes | |
| substring(X,Y) | Yes | |
| total_changes() | No | |
| total_changes() | Partial| Still need to support update statements and triggers |
| trim(X) | Yes | |
| trim(X,Y) | Yes | |
| typeof(X) | Yes | |
Expand Down
6 changes: 6 additions & 0 deletions core/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,12 @@ impl Connection {
fn update_last_rowid(&self, rowid: u64) {
self.last_insert_rowid.set(rowid);
}

pub fn set_changes(&self, nchange: i64) {
self.last_change.set(nchange);
let prev_total_changes = self.total_changes.get();
self.total_changes.set(prev_total_changes + nchange);
}
}

pub struct Statement {
Expand Down
5 changes: 4 additions & 1 deletion core/translate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub fn translate(
syms: &SymbolTable,
) -> Result<Program> {
let mut program = ProgramBuilder::new();
let mut change_cnt_on = false;

match stmt {
ast::Stmt::AlterTable(_, _) => bail_parse_error!("ALTER TABLE not supported yet"),
Expand Down Expand Up @@ -79,6 +80,7 @@ pub fn translate(
limit,
..
} => {
change_cnt_on = true;
translate_delete(&mut program, schema, &tbl_name, where_clause, limit, syms)?;
}
ast::Stmt::Detach(_) => bail_parse_error!("DETACH not supported yet"),
Expand Down Expand Up @@ -106,6 +108,7 @@ pub fn translate(
body,
returning,
} => {
change_cnt_on = true;
translate_insert(
&mut program,
schema,
Expand All @@ -120,7 +123,7 @@ pub fn translate(
}
}

Ok(program.build(database_header, connection))
Ok(program.build(database_header, connection, change_cnt_on))
}

/* Example:
Expand Down
5 changes: 4 additions & 1 deletion core/vdbe/builder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{
cell::RefCell,
cell::{Cell, RefCell},
collections::HashMap,
rc::{Rc, Weak},
};
Expand Down Expand Up @@ -327,6 +327,7 @@ impl ProgramBuilder {
mut self,
database_header: Rc<RefCell<DatabaseHeader>>,
connection: Weak<Connection>,
change_cnt_on: bool,
) -> Program {
self.resolve_labels();
assert!(
Expand All @@ -343,6 +344,8 @@ impl ProgramBuilder {
connection,
auto_commit: true,
parameters: self.parameters,
n_change: Cell::new(0),
change_cnt_on,
}
}
}
27 changes: 21 additions & 6 deletions core/vdbe/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ use rand::{thread_rng, Rng};
use regex::{Regex, RegexBuilder};
use sorter::Sorter;
use std::borrow::BorrowMut;
use std::cell::RefCell;
use std::cell::{Cell, RefCell};
use std::collections::{BTreeMap, HashMap};
use std::num::NonZero;
use std::rc::{Rc, Weak};
Expand Down Expand Up @@ -282,6 +282,8 @@ pub struct Program {
pub parameters: crate::parameters::Parameters,
pub connection: Weak<Connection>,
pub auto_commit: bool,
pub n_change: Cell<i64>,
pub change_cnt_on: bool,
}

impl Program {
Expand Down Expand Up @@ -892,11 +894,23 @@ impl Program {
return if self.auto_commit {
match pager.end_tx() {
Ok(crate::storage::wal::CheckpointStatus::IO) => Ok(StepResult::IO),
Ok(crate::storage::wal::CheckpointStatus::Done) => Ok(StepResult::Done),
Ok(crate::storage::wal::CheckpointStatus::Done) => {
if self.change_cnt_on {
if let Some(conn) = self.connection.upgrade() {
conn.set_changes(self.n_change.get());
}
}
Ok(StepResult::Done)
}
Err(e) => Err(e),
}
} else {
Ok(StepResult::Done)
if self.change_cnt_on {
if let Some(conn) = self.connection.upgrade() {
conn.set_changes(self.n_change.get());
}
}
return Ok(StepResult::Done);
};
}
Insn::Transaction { write } => {
Expand Down Expand Up @@ -2076,10 +2090,9 @@ impl Program {
if let Some(rowid) = cursor.rowid()? {
if let Some(conn) = self.connection.upgrade() {
conn.update_last_rowid(rowid);
let prev_total_changes = conn.total_changes.get();
conn.last_change.set(1);
conn.total_changes.set(prev_total_changes + 1);
}
let prev_changes = self.n_change.get();
self.n_change.set(prev_changes + 1);
}
}
state.pc += 1;
Expand All @@ -2092,6 +2105,8 @@ impl Program {
Insn::DeleteAwait { cursor_id } => {
let cursor = btree_table_cursors.get_mut(cursor_id).unwrap();
cursor.wait_for_completion()?;
let prev_changes = self.n_change.get();
self.n_change.set(prev_changes + 1);
state.pc += 1;
}
Insn::NewRowid {
Expand Down
2 changes: 2 additions & 0 deletions testing/all.test
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ source $testdir/select.test
source $testdir/subquery.test
source $testdir/where.test
source $testdir/compare.test
source $testdir/changes.test
source $testdir/total-changes.test
23 changes: 23 additions & 0 deletions testing/changes.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env tclsh

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_execsql_test_on_specific_db {:memory:} changes-on-basic-insert {
create table temp (t1 integer, primary key (t1));
insert into temp values (1);
select changes();
} {1}

do_execsql_test_on_specific_db {:memory:} changes-on-multiple-row-insert {
create table temp (t1 integer, primary key (t1));
insert into temp values (1), (2), (3);
select changes();
} {3}

do_execsql_test_on_specific_db {:memory:} changes-shows-most-recent {
create table temp (t1 integer, primary key (t1));
insert into temp values (1), (2), (3);
insert into temp values (4), (5), (6), (7);
select changes();
} {4}
23 changes: 23 additions & 0 deletions testing/total-changes.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env tclsh

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_execsql_test_on_specific_db {:memory:} total-changes-on-basic-insert {
create table temp (t1 integer, primary key (t1));
insert into temp values (1);
select total_changes();
} {1}

do_execsql_test_on_specific_db {:memory:} total-changes-on-multiple-row-insert {
create table temp (t1 integer, primary key (t1));
insert into temp values (1), (2), (3);
select total_changes();
} {3}

do_execsql_test_on_specific_db {:memory:} total-changes-on-multiple-inserts {
create table temp (t1 integer, primary key (t1));
insert into temp values (1), (2), (3);
insert into temp values (4), (5), (6), (7);
select total_changes();
} {7}

0 comments on commit 11551e8

Please sign in to comment.