Skip to content

Commit 48f9943

Browse files
committed
Only pass filtered columns to powersync_diff
1 parent 7b289e9 commit 48f9943

File tree

4 files changed

+73
-84
lines changed

4 files changed

+73
-84
lines changed

crates/core/src/diff.rs

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ extern crate alloc;
33
use alloc::format;
44
use alloc::string::{String, ToString};
55
use core::ffi::c_int;
6+
use core::slice;
67

78
use sqlite::ResultCode;
89
use sqlite_nostd as sqlite;
@@ -19,20 +20,11 @@ fn powersync_diff_impl(
1920
) -> Result<String, SQLiteError> {
2021
let data_old = args[0].text();
2122
let data_new = args[1].text();
22-
let ignore_removed = args.get(2).map_or(false, |v| v.int() != 0);
2323

24-
diff_objects_with_options(data_old, data_new, ignore_removed)
24+
diff_objects(data_old, data_new)
2525
}
2626

27-
/// Returns a JSON object containing entries from [data_new] that are not present in [data_old].
28-
///
29-
/// When [ignore_removed_columns] is set, columns that are present in [data_old] but not in
30-
/// [data_new] will not be present in the returned object. Otherwise, they will be set to `null`.
31-
fn diff_objects_with_options(
32-
data_old: &str,
33-
data_new: &str,
34-
ignore_removed_columns: bool,
35-
) -> Result<String, SQLiteError> {
27+
pub fn diff_objects(data_old: &str, data_new: &str) -> Result<String, SQLiteError> {
3628
let v_new: json::Value = json::from_str(data_new)?;
3729
let v_old: json::Value = json::from_str(data_old)?;
3830

@@ -47,11 +39,9 @@ fn diff_objects_with_options(
4739
}
4840

4941
// Add missing nulls to left
50-
if !ignore_removed_columns {
51-
for key in right.keys() {
52-
if !left.contains_key(key) {
53-
left.insert(key.clone(), json::Value::Null);
54-
}
42+
for key in right.keys() {
43+
if !left.contains_key(key) {
44+
left.insert(key.clone(), json::Value::Null);
5545
}
5646
}
5747

@@ -86,28 +76,13 @@ pub fn register(db: *mut sqlite::sqlite3) -> Result<(), ResultCode> {
8676
None,
8777
)?;
8878

89-
db.create_function_v2(
90-
"powersync_diff",
91-
3,
92-
sqlite::UTF8 | sqlite::DETERMINISTIC,
93-
None,
94-
Some(powersync_diff),
95-
None,
96-
None,
97-
None,
98-
)?;
99-
10079
Ok(())
10180
}
10281

10382
#[cfg(test)]
10483
mod tests {
10584
use super::*;
10685

107-
fn diff_objects(data_old: &str, data_new: &str) -> Result<String, SQLiteError> {
108-
diff_objects_with_options(data_old, data_new, false)
109-
}
110-
11186
#[test]
11287
fn basic_diff_test() {
11388
assert_eq!(diff_objects("{}", "{}").unwrap(), "{}");

crates/core/src/schema/table_info.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl TableInfo {
5050
flags = flags.set_flag(TableInfoFlags::INSERT_ONLY, insert_only);
5151
flags = flags.set_flag(TableInfoFlags::INCLUDE_METADATA, include_metadata);
5252
flags = flags.set_flag(
53-
TableInfoFlags::INCLUDE_OLD_ONLY_IF_CHANGED,
53+
TableInfoFlags::INCLUDE_OLD_ONLY_WHEN_CHANGED,
5454
include_old_only_when_changed,
5555
);
5656

@@ -104,7 +104,7 @@ impl TableInfoFlags {
104104
pub const LOCAL_ONLY: u32 = 1;
105105
pub const INSERT_ONLY: u32 = 2;
106106
pub const INCLUDE_METADATA: u32 = 4;
107-
pub const INCLUDE_OLD_ONLY_IF_CHANGED: u32 = 8;
107+
pub const INCLUDE_OLD_ONLY_WHEN_CHANGED: u32 = 8;
108108

109109
pub const fn local_only(self) -> bool {
110110
self.0 & Self::LOCAL_ONLY != 0
@@ -118,8 +118,8 @@ impl TableInfoFlags {
118118
self.0 & Self::INCLUDE_METADATA != 0
119119
}
120120

121-
pub const fn include_old_only_if_changed(self) -> bool {
122-
self.0 & Self::INCLUDE_OLD_ONLY_IF_CHANGED != 0
121+
pub const fn include_old_only_when_changed(self) -> bool {
122+
self.0 & Self::INCLUDE_OLD_ONLY_WHEN_CHANGED != 0
123123
}
124124

125125
const fn with_flag(self, flag: u32) -> Self {

crates/core/src/views.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -291,11 +291,30 @@ fn powersync_trigger_update_sql_impl(
291291
}
292292
};
293293

294-
if table_info.flags.include_old_only_if_changed() {
295-
// We're setting ignore_removed_columns here because values that are present in the new
296-
// values but not in the old values should not lead to a null entry.
297-
old_values_fragment = old_values_fragment
298-
.map(|f| format!("json(powersync_diff({json_fragment_new}, {f}, TRUE))"));
294+
if table_info.flags.include_old_only_when_changed() {
295+
old_values_fragment = match old_values_fragment {
296+
None => None,
297+
Some(f) => {
298+
let filtered_new_fragment = match &table_info.diff_include_old {
299+
// When include_old_only_when_changed is combined with a column filter, make sure we
300+
// only include the powersync_diff of columns matched by the filter.
301+
Some(DiffIncludeOld::OnlyForColumns { columns }) => {
302+
let mut iterator = columns.iter();
303+
let mut columns =
304+
streaming_iterator::from_fn(|| -> Option<Result<&str, ResultCode>> {
305+
Some(Ok(iterator.next()?.as_str()))
306+
});
307+
308+
Cow::Owned(json_object_fragment("NEW", &mut columns)?)
309+
}
310+
_ => Cow::Borrowed(json_fragment_new.as_str()),
311+
};
312+
313+
Some(format!(
314+
"json(powersync_diff({filtered_new_fragment}, {f}))"
315+
))
316+
}
317+
}
299318
}
300319

301320
let old_fragment: Cow<'static, str> = match old_values_fragment {

dart/pubspec.lock

Lines changed: 39 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,34 @@ packages:
55
dependency: transitive
66
description:
77
name: _fe_analyzer_shared
8-
sha256: "03f6da266a27a4538a69295ec142cb5717d7d4e5727b84658b63e1e1509bac9c"
8+
sha256: e55636ed79578b9abca5fecf9437947798f5ef7456308b5cb85720b793eac92f
99
url: "https://pub.dev"
1010
source: hosted
11-
version: "79.0.0"
12-
_macros:
13-
dependency: transitive
14-
description: dart
15-
source: sdk
16-
version: "0.3.3"
11+
version: "82.0.0"
1712
analyzer:
1813
dependency: transitive
1914
description:
2015
name: analyzer
21-
sha256: c9040fc56483c22a5e04a9f6a251313118b1a3c42423770623128fa484115643
16+
sha256: "13c1e6c6fd460522ea840abec3f677cc226f5fec7872c04ad7b425517ccf54f7"
2217
url: "https://pub.dev"
2318
source: hosted
24-
version: "7.2.0"
19+
version: "7.4.4"
2520
args:
2621
dependency: transitive
2722
description:
2823
name: args
29-
sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
24+
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
3025
url: "https://pub.dev"
3126
source: hosted
32-
version: "2.6.0"
27+
version: "2.7.0"
3328
async:
3429
dependency: transitive
3530
description:
3631
name: async
37-
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
32+
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
3833
url: "https://pub.dev"
3934
source: hosted
40-
version: "2.12.0"
35+
version: "2.13.0"
4136
boolean_selector:
4237
dependency: transitive
4338
description:
@@ -46,6 +41,14 @@ packages:
4641
url: "https://pub.dev"
4742
source: hosted
4843
version: "2.1.2"
44+
cli_config:
45+
dependency: transitive
46+
description:
47+
name: cli_config
48+
sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec
49+
url: "https://pub.dev"
50+
source: hosted
51+
version: "0.2.0"
4952
collection:
5053
dependency: transitive
5154
description:
@@ -66,10 +69,10 @@ packages:
6669
dependency: transitive
6770
description:
6871
name: coverage
69-
sha256: e3493833ea012784c740e341952298f1cc77f1f01b1bbc3eb4eecf6984fb7f43
72+
sha256: "9086475ef2da7102a0c0a4e37e1e30707e7fb7b6d28c209f559a9c5f8ce42016"
7073
url: "https://pub.dev"
7174
source: hosted
72-
version: "1.11.1"
75+
version: "1.12.0"
7376
crypto:
7477
dependency: transitive
7578
description:
@@ -82,10 +85,10 @@ packages:
8285
dependency: transitive
8386
description:
8487
name: ffi
85-
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
88+
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
8689
url: "https://pub.dev"
8790
source: hosted
88-
version: "2.1.3"
91+
version: "2.1.4"
8992
file:
9093
dependency: transitive
9194
description:
@@ -138,10 +141,10 @@ packages:
138141
dependency: transitive
139142
description:
140143
name: js
141-
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
144+
sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc"
142145
url: "https://pub.dev"
143146
source: hosted
144-
version: "0.7.1"
147+
version: "0.7.2"
145148
logging:
146149
dependency: transitive
147150
description:
@@ -150,14 +153,6 @@ packages:
150153
url: "https://pub.dev"
151154
source: hosted
152155
version: "1.3.0"
153-
macros:
154-
dependency: transitive
155-
description:
156-
name: macros
157-
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
158-
url: "https://pub.dev"
159-
source: hosted
160-
version: "0.1.3-main.0"
161156
matcher:
162157
dependency: transitive
163158
description:
@@ -194,10 +189,10 @@ packages:
194189
dependency: transitive
195190
description:
196191
name: package_config
197-
sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67"
192+
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
198193
url: "https://pub.dev"
199194
source: hosted
200-
version: "2.1.1"
195+
version: "2.2.0"
201196
path:
202197
dependency: transitive
203198
description:
@@ -218,10 +213,10 @@ packages:
218213
dependency: transitive
219214
description:
220215
name: pub_semver
221-
sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd"
216+
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
222217
url: "https://pub.dev"
223218
source: hosted
224-
version: "2.1.5"
219+
version: "2.2.0"
225220
shelf:
226221
dependency: transitive
227222
description:
@@ -250,10 +245,10 @@ packages:
250245
dependency: transitive
251246
description:
252247
name: shelf_web_socket
253-
sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67
248+
sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925"
254249
url: "https://pub.dev"
255250
source: hosted
256-
version: "2.0.1"
251+
version: "3.0.0"
257252
source_map_stack_trace:
258253
dependency: transitive
259254
description:
@@ -282,10 +277,10 @@ packages:
282277
dependency: "direct main"
283278
description:
284279
name: sqlite3
285-
sha256: "35d3726fe18ab1463403a5cc8d97dbc81f2a0b08082e8173851363fcc97b6627"
280+
sha256: "310af39c40dd0bb2058538333c9d9840a2725ae0b9f77e4fd09ad6696aa8f66e"
286281
url: "https://pub.dev"
287282
source: hosted
288-
version: "2.7.2"
283+
version: "2.7.5"
289284
stack_trace:
290285
dependency: transitive
291286
description:
@@ -322,10 +317,10 @@ packages:
322317
dependency: "direct dev"
323318
description:
324319
name: test
325-
sha256: "8391fbe68d520daf2314121764d38e37f934c02fd7301ad18307bd93bd6b725d"
320+
sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e"
326321
url: "https://pub.dev"
327322
source: hosted
328-
version: "1.25.14"
323+
version: "1.25.15"
329324
test_api:
330325
dependency: transitive
331326
description:
@@ -370,26 +365,26 @@ packages:
370365
dependency: transitive
371366
description:
372367
name: web
373-
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
368+
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
374369
url: "https://pub.dev"
375370
source: hosted
376-
version: "1.1.0"
371+
version: "1.1.1"
377372
web_socket:
378373
dependency: transitive
379374
description:
380375
name: web_socket
381-
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
376+
sha256: bfe6f435f6ec49cb6c01da1e275ae4228719e59a6b067048c51e72d9d63bcc4b
382377
url: "https://pub.dev"
383378
source: hosted
384-
version: "0.1.6"
379+
version: "1.0.0"
385380
web_socket_channel:
386381
dependency: transitive
387382
description:
388383
name: web_socket_channel
389-
sha256: "0b8e2457400d8a859b7b2030786835a28a8e80836ef64402abef392ff4f1d0e5"
384+
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
390385
url: "https://pub.dev"
391386
source: hosted
392-
version: "3.0.2"
387+
version: "3.0.3"
393388
webkit_inspection_protocol:
394389
dependency: transitive
395390
description:
@@ -407,4 +402,4 @@ packages:
407402
source: hosted
408403
version: "3.1.3"
409404
sdks:
410-
dart: ">=3.5.0 <4.0.0"
405+
dart: ">=3.7.0 <4.0.0"

0 commit comments

Comments
 (0)