Skip to content

Commit 831ce35

Browse files
committed
Allow clearing raw tables
1 parent 04bee21 commit 831ce35

File tree

15 files changed

+151
-91
lines changed

15 files changed

+151
-91
lines changed

crates/core/src/crud_vtab.rs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
extern crate alloc;
22

33
use alloc::boxed::Box;
4-
use alloc::sync::Arc;
4+
use alloc::rc::Rc;
55
use const_format::formatcp;
66
use core::ffi::{CStr, c_char, c_int, c_void};
77
use core::sync::atomic::Ordering;
@@ -42,7 +42,7 @@ struct VirtualTable {
4242
db: *mut sqlite::sqlite3,
4343
current_tx: Option<ActiveCrudTransaction>,
4444
is_simple: bool,
45-
state: Arc<DatabaseState>,
45+
state: Rc<DatabaseState>,
4646
}
4747

4848
struct ActiveCrudTransaction {
@@ -301,14 +301,7 @@ extern "C" fn connect(
301301
pModule: core::ptr::null(),
302302
zErrMsg: core::ptr::null_mut(),
303303
},
304-
state: {
305-
// Increase refcount - we can't use from_raw alone because we don't own the aux
306-
// data (connect could be called multiple times).
307-
let state = Arc::from_raw(aux as *mut DatabaseState);
308-
let clone = state.clone();
309-
core::mem::forget(state);
310-
clone
311-
},
304+
state: DatabaseState::clone_from(aux),
312305
db,
313306
current_tx: None,
314307
is_simple,
@@ -321,7 +314,7 @@ extern "C" fn connect(
321314

322315
extern "C" fn disconnect(vtab: *mut sqlite::vtab) -> c_int {
323316
unsafe {
324-
drop(Box::from_raw(vtab));
317+
drop(Box::from_raw(vtab as *mut VirtualTable));
325318
}
326319
ResultCode::OK as c_int
327320
}
@@ -400,20 +393,20 @@ static MODULE: sqlite_nostd::module = sqlite_nostd::module {
400393
xIntegrity: None,
401394
};
402395

403-
pub fn register(db: *mut sqlite::sqlite3, state: Arc<DatabaseState>) -> Result<(), ResultCode> {
396+
pub fn register(db: *mut sqlite::sqlite3, state: Rc<DatabaseState>) -> Result<(), ResultCode> {
404397
sqlite::convert_rc(sqlite::create_module_v2(
405398
db,
406399
SIMPLE_NAME.as_ptr(),
407400
&MODULE,
408-
Arc::into_raw(state.clone()) as *mut c_void,
409-
Some(DatabaseState::destroy_arc),
401+
Rc::into_raw(state.clone()) as *mut c_void,
402+
Some(DatabaseState::destroy_rc),
410403
))?;
411404
sqlite::convert_rc(sqlite::create_module_v2(
412405
db,
413406
MANUAL_NAME.as_ptr(),
414407
&MODULE,
415-
Arc::into_raw(state) as *mut c_void,
416-
Some(DatabaseState::destroy_arc),
408+
Rc::into_raw(state) as *mut c_void,
409+
Some(DatabaseState::destroy_rc),
417410
))?;
418411

419412
Ok(())

crates/core/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extern crate alloc;
88

99
use core::ffi::{c_char, c_int};
1010

11-
use alloc::{ffi::CString, format, sync::Arc};
11+
use alloc::{ffi::CString, format, rc::Rc};
1212
use sqlite::ResultCode;
1313
use sqlite_nostd as sqlite;
1414

@@ -66,22 +66,22 @@ pub extern "C" fn sqlite3_powersync_init(
6666
fn init_extension(db: *mut sqlite::sqlite3) -> Result<(), PowerSyncError> {
6767
PowerSyncError::check_sqlite3_version()?;
6868

69-
let state = Arc::new(DatabaseState::new());
69+
let state = Rc::new(DatabaseState::new());
7070

7171
crate::version::register(db)?;
7272
crate::views::register(db)?;
7373
crate::uuid::register(db)?;
7474
crate::diff::register(db)?;
7575
crate::fix_data::register(db)?;
7676
crate::json_util::register(db)?;
77-
crate::view_admin::register(db)?;
77+
crate::view_admin::register(db, state.clone())?;
7878
crate::checkpoint::register(db)?;
7979
crate::kv::register(db)?;
8080
crate::state::register(db, state.clone())?;
8181
sync::register(db, state.clone())?;
8282
update_hooks::register(db, state.clone())?;
8383

84-
crate::schema::register(db)?;
84+
crate::schema::register(db, state.clone())?;
8585
crate::operations_vtab::register(db, state.clone())?;
8686
crate::crud_vtab::register(db, state)?;
8787

crates/core/src/migrations.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ CREATE TABLE IF NOT EXISTS ps_migration(id INTEGER PRIMARY KEY, down_migrations
2727
)?;
2828

2929
// language=SQLite
30-
let current_version_stmt =
31-
local_db.prepare_v2("SELECT ifnull(max(id), 0) as version FROM ps_migration")?;
30+
let current_version_stmt = local_db
31+
.prepare_v2("SELECT ifnull(max(id), 0) as version FROM ps_migration")
32+
.into_db_result(local_db)?;
3233
let rc = current_version_stmt.step()?;
3334
if rc != ResultCode::ROW {
3435
return Err(PowerSyncError::unknown_internal());

crates/core/src/operations_vtab.rs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
extern crate alloc;
22

33
use alloc::boxed::Box;
4-
use alloc::sync::Arc;
4+
use alloc::rc::Rc;
55
use core::ffi::{c_char, c_int, c_void};
66

77
use sqlite::{Connection, ResultCode, Value};
@@ -18,7 +18,7 @@ use crate::vtab_util::*;
1818
struct VirtualTable {
1919
base: sqlite::vtab,
2020
db: *mut sqlite::sqlite3,
21-
state: Arc<DatabaseState>,
21+
state: Rc<DatabaseState>,
2222

2323
target_applied: bool,
2424
target_validated: bool,
@@ -46,14 +46,7 @@ extern "C" fn connect(
4646
zErrMsg: core::ptr::null_mut(),
4747
},
4848
db,
49-
state: {
50-
// Increase refcount - we can't use from_raw alone because we don't own the aux
51-
// data (connect could be called multiple times).
52-
let state = Arc::from_raw(aux as *mut DatabaseState);
53-
let clone = state.clone();
54-
core::mem::forget(state);
55-
clone
56-
},
49+
state: DatabaseState::clone_from(aux),
5750
target_validated: false,
5851
target_applied: false,
5952
}));
@@ -65,7 +58,7 @@ extern "C" fn connect(
6558

6659
extern "C" fn disconnect(vtab: *mut sqlite::vtab) -> c_int {
6760
unsafe {
68-
drop(Box::from_raw(vtab));
61+
drop(Box::from_raw(vtab as *mut VirtualTable));
6962
}
7063
ResultCode::OK as c_int
7164
}
@@ -150,12 +143,12 @@ static MODULE: sqlite_nostd::module = sqlite_nostd::module {
150143
xIntegrity: None,
151144
};
152145

153-
pub fn register(db: *mut sqlite::sqlite3, state: Arc<DatabaseState>) -> Result<(), ResultCode> {
146+
pub fn register(db: *mut sqlite::sqlite3, state: Rc<DatabaseState>) -> Result<(), ResultCode> {
154147
db.create_module_v2(
155148
"powersync_operations",
156149
&MODULE,
157-
Some(Arc::into_raw(state) as *mut c_void),
158-
Some(DatabaseState::destroy_arc),
150+
Some(Rc::into_raw(state) as *mut c_void),
151+
Some(DatabaseState::destroy_rc),
159152
)?;
160153

161154
Ok(())

crates/core/src/schema/management.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
extern crate alloc;
22

3+
use alloc::rc::Rc;
34
use alloc::string::String;
45
use alloc::vec::Vec;
56
use alloc::{format, vec};
@@ -11,6 +12,7 @@ use sqlite_nostd::Context;
1112

1213
use crate::error::{PSResult, PowerSyncError};
1314
use crate::ext::ExtendedDatabase;
15+
use crate::state::DatabaseState;
1416
use crate::util::{quote_identifier, quote_json_path};
1517
use crate::{create_auto_tx_function, create_sqlite_text_fn};
1618

@@ -138,10 +140,8 @@ SELECT name, internal_name, local_only FROM powersync_tables WHERE name NOT IN (
138140
Ok(())
139141
}
140142

141-
fn update_indexes(db: *mut sqlite::sqlite3, schema: &str) -> Result<(), PowerSyncError> {
143+
fn update_indexes(db: *mut sqlite::sqlite3, schema: &Schema) -> Result<(), PowerSyncError> {
142144
let mut statements: Vec<String> = alloc::vec![];
143-
let schema =
144-
serde_json::from_str::<Schema>(schema).map_err(PowerSyncError::as_argument_error)?;
145145
let mut expected_index_names: Vec<String> = vec![];
146146

147147
{
@@ -298,15 +298,20 @@ fn powersync_replace_schema_impl(
298298
args: &[*mut sqlite::value],
299299
) -> Result<String, PowerSyncError> {
300300
let schema = args[0].text();
301+
let state = unsafe { DatabaseState::from_context(&ctx) };
302+
let parsed_schema =
303+
serde_json::from_str::<Schema>(schema).map_err(PowerSyncError::as_argument_error)?;
304+
301305
let db = ctx.db_handle();
302306

303307
// language=SQLite
304308
db.exec_safe("SELECT powersync_init()").into_db_result(db)?;
305309

306310
update_tables(db, schema)?;
307-
update_indexes(db, schema)?;
311+
update_indexes(db, &parsed_schema)?;
308312
update_views(db, schema)?;
309313

314+
state.set_schema(parsed_schema);
310315
Ok(String::from(""))
311316
}
312317

@@ -317,16 +322,16 @@ create_sqlite_text_fn!(
317322
"powersync_replace_schema"
318323
);
319324

320-
pub fn register(db: *mut sqlite::sqlite3) -> Result<(), ResultCode> {
325+
pub fn register(db: *mut sqlite::sqlite3, state: Rc<DatabaseState>) -> Result<(), ResultCode> {
321326
db.create_function_v2(
322327
"powersync_replace_schema",
323328
1,
324329
sqlite::UTF8,
325-
None,
330+
Some(Rc::into_raw(state) as *mut _),
326331
Some(powersync_replace_schema),
327332
None,
328333
None,
329-
None,
334+
Some(DatabaseState::destroy_rc),
330335
)?;
331336

332337
Ok(())

crates/core/src/schema/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
mod management;
22
mod table_info;
33

4-
use alloc::vec::Vec;
4+
use alloc::{rc::Rc, vec::Vec};
55
use serde::Deserialize;
66
use sqlite::ResultCode;
77
use sqlite_nostd as sqlite;
@@ -10,13 +10,15 @@ pub use table_info::{
1010
TableInfoFlags,
1111
};
1212

13+
use crate::state::DatabaseState;
14+
1315
#[derive(Deserialize, Default)]
1416
pub struct Schema {
1517
pub tables: Vec<table_info::Table>,
1618
#[serde(default)]
1719
pub raw_tables: Vec<table_info::RawTable>,
1820
}
1921

20-
pub fn register(db: *mut sqlite::sqlite3) -> Result<(), ResultCode> {
21-
management::register(db)
22+
pub fn register(db: *mut sqlite::sqlite3, state: Rc<DatabaseState>) -> Result<(), ResultCode> {
23+
management::register(db, state)
2224
}

crates/core/src/schema/table_info.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ pub struct RawTable {
2424
pub name: String,
2525
pub put: PendingStatement,
2626
pub delete: PendingStatement,
27+
#[serde(default)]
28+
pub clear: Option<String>,
2729
}
2830

2931
impl Table {

0 commit comments

Comments
 (0)