Skip to content

Commit 510acfb

Browse files
committed
after_update: only update db_version when rows are inserted into clock tbls
1 parent 517ce11 commit 510acfb

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

core/rs/core/src/local_writes/after_update.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,20 @@ fn after_update(
7171
non_pks_new: &[*mut value],
7272
non_pks_old: &[*mut value],
7373
) -> Result<ResultCode, String> {
74-
let next_db_version = crate::db_version::next_db_version(db, ext_data)?;
74+
let next_db_version: i64 = crate::db_version::peek_next_db_version(db, ext_data)?;
7575
let new_key = tbl_info
7676
.get_or_create_key_via_raw_values(db, pks_new)
7777
.map_err(|_| "failed geteting or creating lookaside key")?;
7878

79+
let mut changed = false;
7980
// Changing a primary key column to a new value is the same thing as deleting the row
8081
// previously identified by the primary key.
8182
if crate::compare_values::any_value_changed(pks_new, pks_old)? {
8283
let old_key = tbl_info
8384
.get_or_create_key_via_raw_values(db, pks_old)
8485
.map_err(|_| "failed geteting or creating lookaside key")?;
8586
let next_seq = super::bump_seq(ext_data);
87+
changed = true;
8688
// Record the delete of the row identified by the old primary keys
8789
after_update__mark_old_pk_row_deleted(db, tbl_info, old_key, next_db_version, next_seq)?;
8890
let next_seq = super::bump_seq(ext_data);
@@ -110,6 +112,7 @@ fn after_update(
110112
.zip(tbl_info.non_pks.iter())
111113
{
112114
if crsql_compare_sqlite_values(*new, *old) != 0 {
115+
changed = true;
113116
let next_seq = super::bump_seq(ext_data);
114117
// we had a difference in new and old values
115118
// we need to track crdt metadata
@@ -124,6 +127,12 @@ fn after_update(
124127
}
125128
}
126129

130+
// actually set the db_version
131+
if changed {
132+
// TODO: assert this is same as next_db_version
133+
crate::db_version::next_db_version(db, ext_data)?;
134+
}
135+
127136
Ok(ResultCode::OK)
128137
}
129138

py/correctness/tests/test_update_rows.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,66 @@ def get_site_id(db):
6565

6666
db2_foo = db2.execute("SELECT * FROM foo").fetchall()
6767
assert (db2_foo == db1_foo)
68+
69+
70+
def test_empty_update_doesnt_change_db_version():
71+
def create_db():
72+
db = connect(":memory:")
73+
db.execute("CREATE TABLE foo (id INTEGER PRIMARY KEY NOT NULL, a, b)")
74+
db.execute("SELECT crsql_as_crr('foo');")
75+
db.commit()
76+
return db
77+
78+
def get_site_id(db):
79+
return db.execute("SELECT crsql_site_id()").fetchone()[0]
80+
81+
db1 = create_db()
82+
db2 = create_db()
83+
84+
db1_site_id = get_site_id(db1)
85+
db2_site_id = get_site_id(db2)
86+
87+
db1.execute("INSERT INTO foo (id, a, b) VALUES (1, 2, 3)")
88+
db1.commit()
89+
90+
db1.execute("INSERT INTO foo (id, a, b) VALUES (2, 5, 6)")
91+
db1.commit()
92+
93+
sync_left_to_right(db1, db2, 0)
94+
95+
db1_changes = db1.execute("SELECT * FROM crsql_changes").fetchall()
96+
97+
assert (db1_changes == [('foo', b'\x01\t\x01', 'a', 2, 1, 1, db1_site_id, 1, 0),
98+
('foo', b'\x01\t\x01', 'b', 3, 1, 1, db1_site_id, 1, 1),
99+
('foo', b'\x01\t\x02', 'a', 5, 1, 2, db1_site_id, 1, 0),
100+
('foo', b'\x01\t\x02', 'b', 6, 1, 2, db1_site_id, 1, 1)])
101+
102+
db2_changes = db2.execute("SELECT * FROM crsql_changes").fetchall()
103+
assert (db2_changes == db1_changes)
104+
105+
db1_db_version = db1.execute("SELECT crsql_db_version()").fetchone()[0]
106+
assert (db1_db_version == 2)
107+
108+
# update row
109+
db1.execute("INSERT INTO foo (id, a, b) VALUES (2, 5, 6) ON CONFLICT (id) DO UPDATE SET a = 5, b = 6")
110+
db1.commit()
111+
112+
# update row
113+
db1.execute("INSERT INTO foo (id, a, b) VALUES (1, 2, 3) ON CONFLICT (id) DO UPDATE SET a = 2, b = 3")
114+
db1.commit()
115+
116+
db1_db_version = db1.execute("SELECT crsql_db_version()").fetchone()[0]
117+
assert (db1_db_version == 2)
118+
119+
db1_changes = db1.execute("SELECT * FROM crsql_changes").fetchall()
120+
assert (db1_changes == [('foo', b'\x01\t\x01', 'a', 2, 1, 1, db1_site_id, 1, 0),
121+
('foo', b'\x01\t\x01', 'b', 3, 1, 1, db1_site_id, 1, 1),
122+
('foo', b'\x01\t\x02', 'a', 5, 1, 2, db1_site_id, 1, 0),
123+
('foo', b'\x01\t\x02', 'b', 6, 1, 2, db1_site_id, 1, 1)])
124+
125+
# do an actual update
126+
db1.execute("UPDATE foo SET a = 10 WHERE id = 1")
127+
db1.commit()
128+
129+
db1_db_version = db1.execute("SELECT crsql_db_version()").fetchone()[0]
130+
assert (db1_db_version == 3)

0 commit comments

Comments
 (0)