Skip to content

Commit e93f16c

Browse files
committed
Adopt for updates
1 parent c1ff271 commit e93f16c

File tree

2 files changed

+27
-15
lines changed

2 files changed

+27
-15
lines changed

crates/core/src/crud_vtab.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const SIMPLE_NAME: &CStr = c"powersync_crud";
2323

2424
// Structure:
2525
// CREATE TABLE powersync_crud_(data TEXT, options INT HIDDEN);
26-
// CREATE TABLE powersync_crud(op TEXT, id TEXT, type TEXT, data TEXT, old_values TEXT, metadata TEXT);
26+
// CREATE TABLE powersync_crud(op TEXT, id TEXT, type TEXT, data TEXT, old_values TEXT, metadata TEXT, options INT HIDDEN);
2727
//
2828
// This is a insert-only virtual table. It generates transaction ids in ps_tx, and inserts data in
2929
// ps_crud(tx_id, data).
@@ -98,11 +98,24 @@ impl VirtualTable {
9898
set_updated_rows,
9999
update_local_bucket,
100100
} => {
101-
// Columns are (op TEXT, id TEXT, type TEXT, data TEXT, old_values TEXT, metadata TEXT)
102-
let metadata = args[5];
101+
// Columns are (op TEXT, id TEXT, type TEXT, data TEXT, old_values TEXT, metadata TEXT, options INT HIDDEN)
102+
let flags = match args[6].value_type() {
103+
sqlite_nostd::ColumnType::Null => TableInfoFlags::default(),
104+
_ => TableInfoFlags(args[1].int() as u32),
105+
};
103106
let op = args[0].text();
104107
let id = args[1].text();
105108
let row_type = args[2].text();
109+
let metadata = args[5];
110+
let data = Self::value_to_json(&args[3]);
111+
112+
if flags.include_old_only_when_changed()
113+
&& op == "PATCH"
114+
&& data.map(|r| r.get()) == Some("{}")
115+
{
116+
// Ignore this empty update
117+
return Ok(());
118+
}
106119

107120
#[derive(Serialize)]
108121
struct CrudEntry<'a> {
@@ -121,11 +134,12 @@ impl VirtualTable {
121134
// First, we insert into ps_crud like the manual vtab would too. We have to create
122135
// the JSON out of the individual components for that.
123136
stmt.bind_int64(1, current_tx.tx_id)?;
137+
124138
let serialized = serde_json::to_string(&CrudEntry {
125139
op,
126140
id,
127141
row_type,
128-
data: Self::value_to_json(&args[3]),
142+
data: data,
129143
old: Self::value_to_json(&args[4]),
130144
metadata: if metadata.value_type() == ColumnType::Text {
131145
Some(metadata.text())
@@ -214,7 +228,7 @@ extern "C" fn connect(
214228
let is_simple = name == SIMPLE_NAME;
215229

216230
let sql = if is_simple {
217-
"CREATE TABLE powersync_crud(op TEXT, id TEXT, type TEXT, data TEXT, old_values TEXT, metadata TEXT);"
231+
"CREATE TABLE powersync_crud(op TEXT, id TEXT, type TEXT, data TEXT, old_values TEXT, metadata TEXT, options INT HIDDEN);"
218232
} else {
219233
"CREATE TABLE powersync_crud_(data TEXT, options INT HIDDEN);"
220234
};

crates/core/src/views.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -279,15 +279,15 @@ fn powersync_trigger_update_sql_impl(
279279
}
280280
}
281281

282-
let old_fragment: Cow<'static, str> = match old_values_fragment {
283-
Some(f) => format!(", 'old', {f}").into(),
284-
None => "".into(),
282+
let (old_key, old_value): (&'static str, Cow<'static, str>) = match old_values_fragment {
283+
Some(f) => (",old_values", format!(",{f}").into()),
284+
None => ("", "".into()),
285285
};
286286

287-
let metadata_fragment = if table_info.flags.include_metadata() {
288-
", 'metadata', NEW._metadata"
287+
let (metadata_key, metadata_value) = if table_info.flags.include_metadata() {
288+
(",metadata", ",NEW._metadata")
289289
} else {
290-
""
290+
("", "")
291291
};
292292

293293
return if !local_only && !insert_only {
@@ -313,10 +313,8 @@ BEGIN
313313
UPDATE {internal_name}
314314
SET data = {json_fragment_new}
315315
WHERE id = NEW.id;
316-
INSERT INTO powersync_crud_(data, options) VALUES(json_object('op', 'PATCH', 'type', {:}, 'id', NEW.id, 'data', json(powersync_diff({:}, {:})){:}{:}), {flags});
317-
INSERT OR IGNORE INTO ps_updated_rows(row_type, row_id) VALUES({type_string}, NEW.id);
318-
INSERT OR REPLACE INTO ps_buckets(name, last_op, target_op) VALUES('$local', 0, {MAX_OP_ID});
319-
END", type_string, json_fragment_old, json_fragment_new, old_fragment, metadata_fragment);
316+
INSERT INTO powersync_crud(op,type,id,data,options{old_key}{metadata_key}) VALUES ('PATCH',{type_string},NEW.id,json(powersync_diff({:}, {:})),{flags}{old_value}{metadata_value});
317+
END", json_fragment_old, json_fragment_new);
320318
Ok(trigger)
321319
} else if local_only {
322320
debug_assert!(!table_info.flags.include_metadata());

0 commit comments

Comments
 (0)