Skip to content

Commit bf13bc1

Browse files
authored
Merge pull request #69 from powersync-ja/update-options-update
Expand support for update metadata and tracking old values
2 parents 17b7f46 + 72da6d7 commit bf13bc1

24 files changed

+774
-185
lines changed

.github/workflows/android.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
java-version: "17"
1919

2020
- name: Validate Gradle wrapper
21-
uses: gradle/wrapper-validation-action@ccb4328a959376b642e027874838f60f8e596de3
21+
uses: gradle/actions/wrapper-validation@v4
2222

2323
- name: Setup
2424
run: |

.gitmodules

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[submodule "sqlite-rs-embedded"]
22
path = sqlite-rs-embedded
3-
url = https://github.com/vlcn-io/sqlite-rs-embedded.git
3+
url = https://github.com/powersync-ja/sqlite-rs-embedded.git

Cargo.lock

+45-16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/core/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ num-traits = { version = "0.2.15", default-features = false }
1919
num-derive = "0.3"
2020
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
2121
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
22+
streaming-iterator = { version = "0.1.9", default-features = false, features = ["alloc"] }
2223

2324
[dependencies.uuid]
2425
version = "1.4.1"

crates/core/src/checkpoint.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use alloc::format;
44
use alloc::string::String;
55
use alloc::vec::Vec;
66
use core::ffi::c_int;
7-
use core::slice;
87

98
use serde::{Deserialize, Serialize};
109
use serde_json as json;
@@ -59,9 +58,9 @@ GROUP BY bucket_list.bucket",
5958
while statement.step()? == ResultCode::ROW {
6059
let name = statement.column_text(0)?;
6160
// checksums with column_int are wrapped to i32 by SQLite
62-
let add_checksum = statement.column_int(1)?;
63-
let oplog_checksum = statement.column_int(2)?;
64-
let expected_checksum = statement.column_int(3)?;
61+
let add_checksum = statement.column_int(1);
62+
let oplog_checksum = statement.column_int(2);
63+
let expected_checksum = statement.column_int(3);
6564

6665
// wrapping add is like +, but safely overflows
6766
let checksum = oplog_checksum.wrapping_add(add_checksum);

crates/core/src/crud_vtab.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ extern crate alloc;
33
use alloc::boxed::Box;
44
use alloc::string::String;
55
use core::ffi::{c_char, c_int, c_void};
6-
use core::slice;
76

87
use sqlite::{Connection, ResultCode, Value};
98
use sqlite_nostd as sqlite;
@@ -29,7 +28,7 @@ struct VirtualTable {
2928
base: sqlite::vtab,
3029
db: *mut sqlite::sqlite3,
3130
current_tx: Option<i64>,
32-
insert_statement: Option<ManagedStmt>
31+
insert_statement: Option<ManagedStmt>,
3332
}
3433

3534
extern "C" fn connect(
@@ -40,8 +39,7 @@ extern "C" fn connect(
4039
vtab: *mut *mut sqlite::vtab,
4140
_err: *mut *mut c_char,
4241
) -> c_int {
43-
if let Err(rc) = sqlite::declare_vtab(db, "CREATE TABLE powersync_crud_(data TEXT);")
44-
{
42+
if let Err(rc) = sqlite::declare_vtab(db, "CREATE TABLE powersync_crud_(data TEXT);") {
4543
return rc as c_int;
4644
}
4745

@@ -54,7 +52,7 @@ extern "C" fn connect(
5452
},
5553
db,
5654
current_tx: None,
57-
insert_statement: None
55+
insert_statement: None,
5856
}));
5957
*vtab = tab.cast::<sqlite::vtab>();
6058
let _ = sqlite::vtab_config(db, 0);
@@ -69,17 +67,17 @@ extern "C" fn disconnect(vtab: *mut sqlite::vtab) -> c_int {
6967
ResultCode::OK as c_int
7068
}
7169

72-
7370
fn begin_impl(tab: &mut VirtualTable) -> Result<(), SQLiteError> {
7471
let db = tab.db;
7572

7673
let insert_statement = db.prepare_v3("INSERT INTO ps_crud(tx_id, data) VALUES (?1, ?2)", 0)?;
7774
tab.insert_statement = Some(insert_statement);
7875

7976
// language=SQLite
80-
let statement = db.prepare_v2("UPDATE ps_tx SET next_tx = next_tx + 1 WHERE id = 1 RETURNING next_tx")?;
77+
let statement =
78+
db.prepare_v2("UPDATE ps_tx SET next_tx = next_tx + 1 WHERE id = 1 RETURNING next_tx")?;
8179
if statement.step()? == ResultCode::ROW {
82-
let tx_id = statement.column_int64(0)? - 1;
80+
let tx_id = statement.column_int64(0) - 1;
8381
tab.current_tx = Some(tx_id);
8482
} else {
8583
return Err(SQLiteError::from(ResultCode::ABORT));
@@ -109,23 +107,27 @@ extern "C" fn rollback(vtab: *mut sqlite::vtab) -> c_int {
109107
ResultCode::OK as c_int
110108
}
111109

112-
fn insert_operation(
113-
vtab: *mut sqlite::vtab, data: &str) -> Result<(), SQLiteError> {
110+
fn insert_operation(vtab: *mut sqlite::vtab, data: &str) -> Result<(), SQLiteError> {
114111
let tab = unsafe { &mut *(vtab.cast::<VirtualTable>()) };
115112
if tab.current_tx.is_none() {
116-
return Err(SQLiteError(ResultCode::MISUSE, Some(String::from("No tx_id"))));
113+
return Err(SQLiteError(
114+
ResultCode::MISUSE,
115+
Some(String::from("No tx_id")),
116+
));
117117
}
118118
let current_tx = tab.current_tx.unwrap();
119119
// language=SQLite
120-
let statement = tab.insert_statement.as_ref().ok_or(SQLiteError::from(NULL))?;
120+
let statement = tab
121+
.insert_statement
122+
.as_ref()
123+
.ok_or(SQLiteError::from(NULL))?;
121124
statement.bind_int64(1, current_tx)?;
122125
statement.bind_text(2, data, sqlite::Destructor::STATIC)?;
123126
statement.exec()?;
124127

125128
Ok(())
126129
}
127130

128-
129131
extern "C" fn update(
130132
vtab: *mut sqlite::vtab,
131133
argc: c_int,
@@ -178,6 +180,7 @@ static MODULE: sqlite_nostd::module = sqlite_nostd::module {
178180
xRelease: None,
179181
xRollbackTo: None,
180182
xShadowName: None,
183+
xIntegrity: None,
181184
};
182185

183186
pub fn register(db: *mut sqlite::sqlite3) -> Result<(), ResultCode> {

crates/core/src/json_merge.rs

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ extern crate alloc;
33
use alloc::format;
44
use alloc::string::{String, ToString};
55
use core::ffi::c_int;
6-
use core::slice;
76

87
use sqlite::ResultCode;
98
use sqlite_nostd as sqlite;

crates/core/src/kv.rs

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ extern crate alloc;
33
use alloc::format;
44
use alloc::string::{String, ToString};
55
use core::ffi::c_int;
6-
use core::slice;
76

87
use sqlite::ResultCode;
98
use sqlite_nostd as sqlite;

crates/core/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ mod macros;
2525
mod migrations;
2626
mod operations;
2727
mod operations_vtab;
28-
mod schema_management;
28+
mod schema;
2929
mod sync_local;
3030
mod sync_types;
3131
mod util;
@@ -62,7 +62,7 @@ fn init_extension(db: *mut sqlite::sqlite3) -> Result<(), ResultCode> {
6262
crate::checkpoint::register(db)?;
6363
crate::kv::register(db)?;
6464

65-
crate::schema_management::register(db)?;
65+
crate::schema::register(db)?;
6666
crate::operations_vtab::register(db)?;
6767
crate::crud_vtab::register(db)?;
6868

crates/core/src/migrations.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ CREATE TABLE IF NOT EXISTS ps_migration(id INTEGER PRIMARY KEY, down_migrations
3434
return Err(SQLiteError::from(ResultCode::ABORT));
3535
}
3636

37-
let mut current_version = current_version_stmt.column_int(0)?;
37+
let mut current_version = current_version_stmt.column_int(0);
3838

3939
while current_version > target_version {
4040
// Run down migrations.
@@ -78,7 +78,7 @@ CREATE TABLE IF NOT EXISTS ps_migration(id INTEGER PRIMARY KEY, down_migrations
7878
Some("Down migration failed - could not get version".to_string()),
7979
));
8080
}
81-
let new_version = current_version_stmt.column_int(0)?;
81+
let new_version = current_version_stmt.column_int(0);
8282
if new_version >= current_version {
8383
// Database down from version $currentVersion to $version failed - version not updated after dow migration
8484
return Err(SQLiteError(

crates/core/src/operations.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ FROM json_each(?) e",
6969
bucket_statement.bind_text(1, bucket, sqlite::Destructor::STATIC)?;
7070
bucket_statement.step()?;
7171

72-
let bucket_id = bucket_statement.column_int64(0)?;
72+
let bucket_id = bucket_statement.column_int64(0);
7373

7474
// This is an optimization for initial sync - we can avoid persisting individual REMOVE
7575
// operations when last_applied_op = 0.
7676
// We do still need to do the "supersede_statement" step for this case, since a REMOVE
7777
// operation can supersede another PUT operation we're syncing at the same time.
78-
let mut is_empty = bucket_statement.column_int64(1)? == 0;
78+
let mut is_empty = bucket_statement.column_int64(1) == 0;
7979

8080
// Statement to supersede (replace) operations with the same key.
8181
// language=SQLite
@@ -106,11 +106,11 @@ INSERT OR IGNORE INTO ps_updated_rows(row_type, row_id) VALUES(?1, ?2)",
106106
let mut added_ops: i32 = 0;
107107

108108
while iterate_statement.step()? == ResultCode::ROW {
109-
let op_id = iterate_statement.column_int64(0)?;
109+
let op_id = iterate_statement.column_int64(0);
110110
let op = iterate_statement.column_text(1)?;
111111
let object_type = iterate_statement.column_text(2);
112112
let object_id = iterate_statement.column_text(3);
113-
let checksum = iterate_statement.column_int(4)?;
113+
let checksum = iterate_statement.column_int(4);
114114
let op_data = iterate_statement.column_text(5);
115115

116116
last_op = Some(op_id);
@@ -131,7 +131,7 @@ INSERT OR IGNORE INTO ps_updated_rows(row_type, row_id) VALUES(?1, ?2)",
131131

132132
while supersede_statement.step()? == ResultCode::ROW {
133133
// Superseded (deleted) a previous operation, add the checksum
134-
let supersede_checksum = supersede_statement.column_int(1)?;
134+
let supersede_checksum = supersede_statement.column_int(1);
135135
add_checksum = add_checksum.wrapping_add(supersede_checksum);
136136
op_checksum = op_checksum.wrapping_sub(supersede_checksum);
137137

@@ -272,7 +272,7 @@ pub fn delete_bucket(db: *mut sqlite::sqlite3, name: &str) -> Result<(), SQLiteE
272272
statement.bind_text(1, name, sqlite::Destructor::STATIC)?;
273273

274274
if statement.step()? == ResultCode::ROW {
275-
let bucket_id = statement.column_int64(0)?;
275+
let bucket_id = statement.column_int64(0);
276276

277277
// language=SQLite
278278
let updated_statement = db.prepare_v2(

0 commit comments

Comments
 (0)