From cb9a7bfee5a68efd6f171340203fa1e58da6af2c Mon Sep 17 00:00:00 2001 From: Jerome Gravel-Niquet Date: Thu, 21 Dec 2023 14:00:13 -0500 Subject: [PATCH 1/9] wip: compare site_id if values are the same and option is turned on --- core/rs/core/src/c.rs | 1 + core/rs/core/src/changes_vtab_write.rs | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/core/rs/core/src/c.rs b/core/rs/core/src/c.rs index de116be49..018b31479 100644 --- a/core/rs/core/src/c.rs +++ b/core/rs/core/src/c.rs @@ -67,6 +67,7 @@ pub struct crsql_ExtData { pub pSetSiteIdOrdinalStmt: *mut sqlite::stmt, pub pSelectSiteIdOrdinalStmt: *mut sqlite::stmt, pub pSelectClockTablesStmt: *mut sqlite::stmt, + pub tieBreakSameColValue: bool, } #[repr(C)] diff --git a/core/rs/core/src/changes_vtab_write.rs b/core/rs/core/src/changes_vtab_write.rs index de9b0b965..c71b4329c 100644 --- a/core/rs/core/src/changes_vtab_write.rs +++ b/core/rs/core/src/changes_vtab_write.rs @@ -19,19 +19,21 @@ use crate::util::slab_rowid; /** * did_cid_win does not take into account the causal length. - * The expectation is that all cuasal length concerns have already been handle + * The expectation is that all causal length concerns have already been handle * via: * - early return because insert_cl < local_cl * - automatic win because insert_cl > local_cl - * - come here to did_cid_win iff insert_cl = local_cl + * - come here to did_cid_win if insert_cl = local_cl */ fn did_cid_win( db: *mut sqlite3, + ext_data: *mut crsql_ExtData, insert_tbl: &str, tbl_info: &TableInfo, unpacked_pks: &Vec, key: sqlite::int64, insert_val: *mut sqlite::value, + insert_site_id: &[u8], col_name: &str, col_version: sqlite::int64, errmsg: *mut *mut c_char, @@ -89,10 +91,15 @@ fn did_cid_win( match step_result { Ok(ResultCode::ROW) => { let local_value = col_val_stmt.column_value(0)?; - let ret = crsql_compare_sqlite_values(insert_val, local_value); + let mut ret = crsql_compare_sqlite_values(insert_val, local_value); reset_cached_stmt(col_val_stmt.stmt)?; - // value won, take value - // if values are the same (ret == 0) then we return false and do not take the update + if ret == 0 && unsafe { (*ext_data).tieBreakSameColValue } { + // values are the same (ret == 0) and the option to tie break on site_id is true + ret = unsafe { + let my_site_id = core::slice::from_raw_parts((*ext_data).siteId, 16); + insert_site_id.cmp(my_site_id) as c_int + }; + } return Ok(ret > 0); } _ => { @@ -586,17 +593,19 @@ unsafe fn merge_insert( || !row_exists_locally || did_cid_win( db, + (*tab).pExtData, insert_tbl, &tbl_info, &unpacked_pks, key, insert_val, + insert_site_id, insert_col, insert_col_vrsn, errmsg, )?; - if does_cid_win == false { + if !does_cid_win { // doesCidWin == 0? compared against our clocks, nothing wins. OK and // Done. return Ok(ResultCode::OK); From 7cf8277dcad4625e13f9919124b77d0ba1d40d09 Mon Sep 17 00:00:00 2001 From: Jerome Gravel-Niquet Date: Thu, 21 Dec 2023 14:22:54 -0500 Subject: [PATCH 2/9] add crsql_config_set function --- core/rs/core/src/c.rs | 12 ++++++++- core/rs/core/src/config.rs | 30 +++++++++++++++++++++++ core/rs/core/src/lib.rs | 18 ++++++++++++++ core/rs/fractindex-core/Cargo.lock | 39 +++++++++++++++++++----------- 4 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 core/rs/core/src/config.rs diff --git a/core/rs/core/src/c.rs b/core/rs/core/src/c.rs index 018b31479..9edab1b44 100644 --- a/core/rs/core/src/c.rs +++ b/core/rs/core/src/c.rs @@ -263,7 +263,7 @@ fn bindgen_test_layout_crsql_ExtData() { let ptr = UNINIT.as_ptr(); assert_eq!( ::core::mem::size_of::(), - 128usize, + 136usize, concat!("Size of: ", stringify!(crsql_ExtData)) ); assert_eq!( @@ -453,4 +453,14 @@ fn bindgen_test_layout_crsql_ExtData() { stringify!(pSelectClockTablesStmt) ) ); + assert_eq!( + unsafe { ::core::ptr::addr_of!((*ptr).tieBreakSameColValue) as usize - ptr as usize }, + 128usize, + concat!( + "Offset of field: ", + stringify!(crsql_ExtData), + "::", + stringify!(tieBreakSameColValue) + ) + ); } diff --git a/core/rs/core/src/config.rs b/core/rs/core/src/config.rs new file mode 100644 index 000000000..9445b20ff --- /dev/null +++ b/core/rs/core/src/config.rs @@ -0,0 +1,30 @@ +use sqlite::Context; +use sqlite_nostd as sqlite; +use sqlite_nostd::{ResultCode, Value}; + +use crate::c::crsql_ExtData; + +pub extern "C" fn crsql_config_set( + ctx: *mut sqlite::context, + argc: i32, + argv: *mut *mut sqlite::value, +) { + let args = sqlite::args!(argc, argv); + + let name = args[0].text(); + + match name { + "always-declare-winner" => { + let value = args[1].int() == 1; + let ext_data = ctx.user_data() as *mut crsql_ExtData; + unsafe { (*ext_data).tieBreakSameColValue = value }; + } + _ => { + ctx.result_error("Unknown setting name"); + ctx.result_error_code(ResultCode::ERROR); + return; + } + } + + ctx.result_error_code(ResultCode::OK); +} diff --git a/core/rs/core/src/lib.rs b/core/rs/core/src/lib.rs index b7f699d51..9e19e0c76 100644 --- a/core/rs/core/src/lib.rs +++ b/core/rs/core/src/lib.rs @@ -18,6 +18,7 @@ mod changes_vtab; mod changes_vtab_read; mod changes_vtab_write; mod compare_values; +mod config; mod consts; mod create_cl_set_vtab; mod create_crr; @@ -53,6 +54,7 @@ use alter::crsql_compact_post_alter; use automigrate::*; use backfill::*; use c::{crsql_freeExtData, crsql_newExtData}; +use config::crsql_config_set; use core::ffi::{c_int, c_void, CStr}; use create_crr::create_crr; use db_version::{crsql_fill_db_version_if_needed, crsql_next_db_version}; @@ -154,6 +156,22 @@ pub extern "C" fn sqlite3_crsqlcore_init( return null_mut(); } + let rc = db + .create_function_v2( + "crsql_config_set", + 2, + sqlite::UTF8, + None, + Some(crsql_config_set), + None, + None, + None, + ) + .unwrap_or(sqlite::ResultCode::ERROR); + if rc != ResultCode::OK { + return null_mut(); + } + let rc = unpack_columns_vtab::create_module(db).unwrap_or(sqlite::ResultCode::ERROR); if rc != ResultCode::OK { return null_mut(); diff --git a/core/rs/fractindex-core/Cargo.lock b/core/rs/fractindex-core/Cargo.lock index cf2f953f0..0635768d0 100644 --- a/core/rs/fractindex-core/Cargo.lock +++ b/core/rs/fractindex-core/Cargo.lock @@ -10,9 +10,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bindgen" -version = "0.63.0" +version = "0.68.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" +checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078" dependencies = [ "bitflags", "cexpr", @@ -21,6 +21,7 @@ dependencies = [ "lazycell", "log", "peeking_take_while", + "prettyplease", "proc-macro2", "quote", "regex", @@ -32,9 +33,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.3.2" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "cexpr" @@ -154,9 +155,9 @@ dependencies = [ [[package]] name = "num-derive" -version = "0.3.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" dependencies = [ "proc-macro2", "quote", @@ -165,9 +166,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] @@ -190,20 +191,30 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.23" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -291,9 +302,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.107" +version = "2.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8" dependencies = [ "proc-macro2", "quote", From 6863bacbe4fd82eaf8bb276de6b7605ebdf9d71a Mon Sep 17 00:00:00 2001 From: Jerome Gravel-Niquet Date: Thu, 21 Dec 2023 14:32:29 -0500 Subject: [PATCH 3/9] I guess we keep this struct in 2 places --- core/src/ext-data.c | 3 +++ core/src/ext-data.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/core/src/ext-data.c b/core/src/ext-data.c index 34c06b777..fc14406c3 100644 --- a/core/src/ext-data.c +++ b/core/src/ext-data.c @@ -58,6 +58,9 @@ crsql_ExtData *crsql_newExtData(sqlite3 *db, unsigned char *siteIdBuffer) { return 0; } + // default to not tie-breaking + pExtData->tieBreakSameColValue = 0; + return pExtData; } diff --git a/core/src/ext-data.h b/core/src/ext-data.h index a24f61836..c7379de47 100644 --- a/core/src/ext-data.h +++ b/core/src/ext-data.h @@ -42,6 +42,8 @@ struct crsql_ExtData { sqlite3_stmt *pSetSiteIdOrdinalStmt; sqlite3_stmt *pSelectSiteIdOrdinalStmt; sqlite3_stmt *pSelectClockTablesStmt; + + int tieBreakSameColValue; }; crsql_ExtData *crsql_newExtData(sqlite3 *db, unsigned char *siteIdBuffer); From 36e069c5eb887fc843f1de7efcf635ade20f83c1 Mon Sep 17 00:00:00 2001 From: Jerome Gravel-Niquet Date: Thu, 21 Dec 2023 15:10:36 -0500 Subject: [PATCH 4/9] add tie-breaker test --- core/rs/core/src/c.rs | 2 +- core/rs/core/src/changes_vtab_write.rs | 2 +- core/rs/core/src/config.rs | 4 +- core/rs/core/src/lib.rs | 32 +++++++------- .../crsql_correctness.egg-info/SOURCES.txt | 3 ++ py/correctness/tests/test_sync.py | 42 +++++++++++++++++++ 6 files changed, 65 insertions(+), 20 deletions(-) diff --git a/core/rs/core/src/c.rs b/core/rs/core/src/c.rs index 9edab1b44..ffe556fe3 100644 --- a/core/rs/core/src/c.rs +++ b/core/rs/core/src/c.rs @@ -67,7 +67,7 @@ pub struct crsql_ExtData { pub pSetSiteIdOrdinalStmt: *mut sqlite::stmt, pub pSelectSiteIdOrdinalStmt: *mut sqlite::stmt, pub pSelectClockTablesStmt: *mut sqlite::stmt, - pub tieBreakSameColValue: bool, + pub tieBreakSameColValue: ::core::ffi::c_int, } #[repr(C)] diff --git a/core/rs/core/src/changes_vtab_write.rs b/core/rs/core/src/changes_vtab_write.rs index c71b4329c..e4fca3d52 100644 --- a/core/rs/core/src/changes_vtab_write.rs +++ b/core/rs/core/src/changes_vtab_write.rs @@ -93,7 +93,7 @@ fn did_cid_win( let local_value = col_val_stmt.column_value(0)?; let mut ret = crsql_compare_sqlite_values(insert_val, local_value); reset_cached_stmt(col_val_stmt.stmt)?; - if ret == 0 && unsafe { (*ext_data).tieBreakSameColValue } { + if ret == 0 && unsafe { (*ext_data).tieBreakSameColValue == 1 } { // values are the same (ret == 0) and the option to tie break on site_id is true ret = unsafe { let my_site_id = core::slice::from_raw_parts((*ext_data).siteId, 16); diff --git a/core/rs/core/src/config.rs b/core/rs/core/src/config.rs index 9445b20ff..e8ee0bd32 100644 --- a/core/rs/core/src/config.rs +++ b/core/rs/core/src/config.rs @@ -14,8 +14,8 @@ pub extern "C" fn crsql_config_set( let name = args[0].text(); match name { - "always-declare-winner" => { - let value = args[1].int() == 1; + "merge-equal-values" => { + let value = args[1].int(); let ext_data = ctx.user_data() as *mut crsql_ExtData; unsafe { (*ext_data).tieBreakSameColValue = value }; } diff --git a/core/rs/core/src/lib.rs b/core/rs/core/src/lib.rs index 9e19e0c76..2e475481e 100644 --- a/core/rs/core/src/lib.rs +++ b/core/rs/core/src/lib.rs @@ -156,22 +156,6 @@ pub extern "C" fn sqlite3_crsqlcore_init( return null_mut(); } - let rc = db - .create_function_v2( - "crsql_config_set", - 2, - sqlite::UTF8, - None, - Some(crsql_config_set), - None, - None, - None, - ) - .unwrap_or(sqlite::ResultCode::ERROR); - if rc != ResultCode::OK { - return null_mut(); - } - let rc = unpack_columns_vtab::create_module(db).unwrap_or(sqlite::ResultCode::ERROR); if rc != ResultCode::OK { return null_mut(); @@ -489,6 +473,22 @@ pub extern "C" fn sqlite3_crsqlcore_init( return null_mut(); } + let rc = db + .create_function_v2( + "crsql_config_set", + 2, + sqlite::UTF8, + Some(ext_data as *mut c_void), + Some(crsql_config_set), + None, + None, + None, + ) + .unwrap_or(sqlite::ResultCode::ERROR); + if rc != ResultCode::OK { + return null_mut(); + } + return ext_data as *mut c_void; } diff --git a/py/correctness/src/crsql_correctness.egg-info/SOURCES.txt b/py/correctness/src/crsql_correctness.egg-info/SOURCES.txt index 42eedac20..b1ec0f626 100644 --- a/py/correctness/src/crsql_correctness.egg-info/SOURCES.txt +++ b/py/correctness/src/crsql_correctness.egg-info/SOURCES.txt @@ -7,9 +7,11 @@ src/crsql_correctness.egg-info/top_level.txt tests/test_as_ordered.py tests/test_cl_merging.py tests/test_cl_triggers.py +tests/test_commit_alter_perf.py tests/test_crsql_changes_filters.py tests/test_dbversion.py tests/test_insert_new_rows.py +tests/test_lookaside_key_creation.py tests/test_prior_versions.py tests/test_sandbox.py tests/test_schema_modification.py @@ -18,5 +20,6 @@ tests/test_seq.py tests/test_site_id_lookaside.py tests/test_siteid.py tests/test_sync.py +tests/test_sync_bit.py tests/test_sync_prop.py tests/test_update_rows.py \ No newline at end of file diff --git a/py/correctness/tests/test_sync.py b/py/correctness/tests/test_sync.py index c7f801ff4..d223aeae2 100644 --- a/py/correctness/tests/test_sync.py +++ b/py/correctness/tests/test_sync.py @@ -380,6 +380,48 @@ def make_dbs(): site_id = get_site_id(db2) assert (changes == [('foo', b'\x01\t\x01', 'b', 2, 1, 1, site_id, 1, 0)]) +def test_merge_same_w_tie_breaker(): + def make_dbs(): + db1 = create_basic_db() + db2 = create_basic_db() + + db1.execute("INSERT INTO foo (a,b) VALUES (1,2);") + db1.execute("SELECT crsql_config_set('merge-equal-values', 1);") + db1.commit() + + db2.execute("INSERT INTO foo (a,b) VALUES (1,2);") + db2.execute("SELECT crsql_config_set('merge-equal-values', 1);") + db2.commit() + return (db1, db2) + + (db1, db2) = make_dbs() + sync_left_to_right(db1, db2, 0) + changes = db2.execute("SELECT * FROM crsql_changes").fetchall() + + site_id1 = get_site_id(db1) + site_id2 = get_site_id(db2) + + max_site_id = max(site_id1, site_id2) + version = 1; + if max_site_id != site_id1: + version = 2 + + assert (changes == [('foo', b'\x01\t\x01', 'b', 2, 1, version, max_site_id, 1, 0)]) + + (db1, db2) = make_dbs() + sync_left_to_right(db2, db1, 0) + changes = db2.execute("SELECT * FROM crsql_changes").fetchall() + + site_id1 = get_site_id(db1) + site_id2 = get_site_id(db2) + + max_site_id = max(site_id1, site_id2) + version = 1; + if max_site_id != site_id2: + version = 2 + + assert (changes == [('foo', b'\x01\t\x01', 'b', 2, 1, version, max_site_id, 1, 0)]) + def test_merge_matching_clocks_lesser_value(): def make_dbs(): From 104a0df8913a535eca321e886743b8735d036749 Mon Sep 17 00:00:00 2001 From: Jerome Gravel-Niquet Date: Thu, 21 Dec 2023 15:27:25 -0500 Subject: [PATCH 5/9] fix test_merge_same_w_tie_breaker --- py/correctness/tests/test_sync.py | 44 ++++++++----------------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/py/correctness/tests/test_sync.py b/py/correctness/tests/test_sync.py index d223aeae2..a1d74d916 100644 --- a/py/correctness/tests/test_sync.py +++ b/py/correctness/tests/test_sync.py @@ -381,46 +381,24 @@ def make_dbs(): assert (changes == [('foo', b'\x01\t\x01', 'b', 2, 1, 1, site_id, 1, 0)]) def test_merge_same_w_tie_breaker(): - def make_dbs(): - db1 = create_basic_db() - db2 = create_basic_db() + db1 = create_basic_db() + db2 = create_basic_db() - db1.execute("INSERT INTO foo (a,b) VALUES (1,2);") - db1.execute("SELECT crsql_config_set('merge-equal-values', 1);") - db1.commit() + db1.execute("INSERT INTO foo (a,b) VALUES (1,2);") + db1.execute("SELECT crsql_config_set('merge-equal-values', 1);") + db1.commit() - db2.execute("INSERT INTO foo (a,b) VALUES (1,2);") - db2.execute("SELECT crsql_config_set('merge-equal-values', 1);") - db2.commit() - return (db1, db2) + db2.execute("INSERT INTO foo (a,b) VALUES (1,2);") + db2.execute("SELECT crsql_config_set('merge-equal-values', 1);") + db2.commit() - (db1, db2) = make_dbs() sync_left_to_right(db1, db2, 0) - changes = db2.execute("SELECT * FROM crsql_changes").fetchall() + changes12 = db2.execute("SELECT \"table\", pk, cid, val, col_version, site_id FROM crsql_changes").fetchall() - site_id1 = get_site_id(db1) - site_id2 = get_site_id(db2) - - max_site_id = max(site_id1, site_id2) - version = 1; - if max_site_id != site_id1: - version = 2 - - assert (changes == [('foo', b'\x01\t\x01', 'b', 2, 1, version, max_site_id, 1, 0)]) - - (db1, db2) = make_dbs() sync_left_to_right(db2, db1, 0) - changes = db2.execute("SELECT * FROM crsql_changes").fetchall() - - site_id1 = get_site_id(db1) - site_id2 = get_site_id(db2) - - max_site_id = max(site_id1, site_id2) - version = 1; - if max_site_id != site_id2: - version = 2 + changes21 = db1.execute("SELECT \"table\", pk, cid, val, col_version, site_id FROM crsql_changes").fetchall() - assert (changes == [('foo', b'\x01\t\x01', 'b', 2, 1, version, max_site_id, 1, 0)]) + assert (changes12 == changes21) def test_merge_matching_clocks_lesser_value(): From 3a01980562615001d765eec61e3ed58147a93f93 Mon Sep 17 00:00:00 2001 From: Jerome Gravel-Niquet Date: Fri, 22 Dec 2023 12:20:37 -0500 Subject: [PATCH 6/9] write config settings to crsql_master table to persist some of them --- core/rs/core/src/c.rs | 46 ++++++++++---------- core/rs/core/src/config.rs | 67 ++++++++++++++++++++++++++--- core/rs/core/src/lib.rs | 18 +++++++- core/src/ext-data.c | 38 ++++++++++++++-- py/correctness/tests/test_config.py | 14 ++++++ 5 files changed, 150 insertions(+), 33 deletions(-) create mode 100644 py/correctness/tests/test_config.py diff --git a/core/rs/core/src/c.rs b/core/rs/core/src/c.rs index ffe556fe3..b93686035 100644 --- a/core/rs/core/src/c.rs +++ b/core/rs/core/src/c.rs @@ -46,8 +46,8 @@ pub enum ChangeRowType { } #[repr(C)] -#[derive(Debug, Copy, Clone)] #[allow(non_snake_case, non_camel_case_types)] +#[derive(Debug, Copy, Clone)] pub struct crsql_ExtData { pub pPragmaSchemaVersionStmt: *mut sqlite::stmt, pub pPragmaDataVersionStmt: *mut sqlite::stmt, @@ -259,20 +259,20 @@ fn bindgen_test_layout_crsql_Changes_cursor() { #[test] #[allow(non_snake_case)] fn bindgen_test_layout_crsql_ExtData() { - const UNINIT: ::core::mem::MaybeUninit = ::core::mem::MaybeUninit::uninit(); + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( - ::core::mem::size_of::(), + ::std::mem::size_of::(), 136usize, concat!("Size of: ", stringify!(crsql_ExtData)) ); assert_eq!( - ::core::mem::align_of::(), + ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(crsql_ExtData)) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).pPragmaSchemaVersionStmt) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).pPragmaSchemaVersionStmt) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", @@ -282,7 +282,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).pPragmaDataVersionStmt) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).pPragmaDataVersionStmt) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", @@ -292,7 +292,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).pragmaDataVersion) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).pragmaDataVersion) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", @@ -302,7 +302,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).dbVersion) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).dbVersion) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", @@ -312,7 +312,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).pendingDbVersion) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).pendingDbVersion) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", @@ -322,7 +322,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).pragmaSchemaVersion) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).pragmaSchemaVersion) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", @@ -332,7 +332,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).updatedTableInfosThisTx) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).updatedTableInfosThisTx) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", @@ -343,7 +343,7 @@ fn bindgen_test_layout_crsql_ExtData() { ); assert_eq!( unsafe { - ::core::ptr::addr_of!((*ptr).pragmaSchemaVersionForTableInfos) as usize - ptr as usize + ::std::ptr::addr_of!((*ptr).pragmaSchemaVersionForTableInfos) as usize - ptr as usize }, 48usize, concat!( @@ -354,7 +354,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).siteId) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).siteId) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", @@ -364,7 +364,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).pDbVersionStmt) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).pDbVersionStmt) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", @@ -374,7 +374,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).tableInfos) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).tableInfos) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", @@ -384,7 +384,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).rowsImpacted) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).rowsImpacted) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", @@ -394,7 +394,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).seq) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).seq) as usize - ptr as usize }, 84usize, concat!( "Offset of field: ", @@ -404,7 +404,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).pSetSyncBitStmt) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).pSetSyncBitStmt) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", @@ -414,7 +414,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).pClearSyncBitStmt) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).pClearSyncBitStmt) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", @@ -424,7 +424,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).pSetSiteIdOrdinalStmt) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).pSetSiteIdOrdinalStmt) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", @@ -434,7 +434,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).pSelectSiteIdOrdinalStmt) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).pSelectSiteIdOrdinalStmt) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", @@ -444,7 +444,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).pSelectClockTablesStmt) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).pSelectClockTablesStmt) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", @@ -454,7 +454,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::core::ptr::addr_of!((*ptr).tieBreakSameColValue) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).tieBreakSameColValue) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", diff --git a/core/rs/core/src/config.rs b/core/rs/core/src/config.rs index e8ee0bd32..81961a863 100644 --- a/core/rs/core/src/config.rs +++ b/core/rs/core/src/config.rs @@ -1,9 +1,13 @@ -use sqlite::Context; +use alloc::format; + +use sqlite::{Connection, Context}; use sqlite_nostd as sqlite; use sqlite_nostd::{ResultCode, Value}; use crate::c::crsql_ExtData; +pub const MERGE_EQUAL_VALUES: &str = "merge-equal-values"; + pub extern "C" fn crsql_config_set( ctx: *mut sqlite::context, argc: i32, @@ -13,18 +17,69 @@ pub extern "C" fn crsql_config_set( let name = args[0].text(); - match name { - "merge-equal-values" => { - let value = args[1].int(); + let value = match name { + MERGE_EQUAL_VALUES => { + let value = args[1]; let ext_data = ctx.user_data() as *mut crsql_ExtData; - unsafe { (*ext_data).tieBreakSameColValue = value }; + unsafe { (*ext_data).tieBreakSameColValue = value.int() }; + value } _ => { ctx.result_error("Unknown setting name"); ctx.result_error_code(ResultCode::ERROR); return; } + }; + + let db = ctx.db_handle(); + match insert_config_setting(db, name, value) { + Ok(value) => { + ctx.result_value(value); + } + Err(rc) => { + ctx.result_error("Could not persist config in database"); + ctx.result_error_code(rc); + return; + } } +} + +fn insert_config_setting( + db: *mut sqlite_nostd::sqlite3, + name: &str, + value: *mut sqlite::value, +) -> Result<*mut sqlite::value, ResultCode> { + let stmt = + db.prepare_v2("INSERT OR REPLACE INTO crsql_master VALUES (?, ?) RETURNING value")?; + + stmt.bind_text(1, &format!("config.{name}"), sqlite::Destructor::TRANSIENT)?; + stmt.bind_value(2, value)?; + + if let ResultCode::ROW = stmt.step()? { + stmt.column_value(0) + } else { + Err(ResultCode::ERROR) + } +} + +pub extern "C" fn crsql_config_get( + ctx: *mut sqlite::context, + argc: i32, + argv: *mut *mut sqlite::value, +) { + let args = sqlite::args!(argc, argv); - ctx.result_error_code(ResultCode::OK); + let name = args[0].text(); + + match name { + MERGE_EQUAL_VALUES => { + let ext_data = ctx.user_data() as *mut crsql_ExtData; + ctx.result_int(unsafe { (*ext_data).tieBreakSameColValue }); + } + _ => { + ctx.result_error("Unknown setting name"); + ctx.result_error_code(ResultCode::ERROR); + return; + } + } } diff --git a/core/rs/core/src/lib.rs b/core/rs/core/src/lib.rs index 2e475481e..57f38b6c5 100644 --- a/core/rs/core/src/lib.rs +++ b/core/rs/core/src/lib.rs @@ -54,7 +54,7 @@ use alter::crsql_compact_post_alter; use automigrate::*; use backfill::*; use c::{crsql_freeExtData, crsql_newExtData}; -use config::crsql_config_set; +use config::{crsql_config_get, crsql_config_set}; use core::ffi::{c_int, c_void, CStr}; use create_crr::create_crr; use db_version::{crsql_fill_db_version_if_needed, crsql_next_db_version}; @@ -489,6 +489,22 @@ pub extern "C" fn sqlite3_crsqlcore_init( return null_mut(); } + let rc = db + .create_function_v2( + "crsql_config_get", + 1, + sqlite::UTF8, + Some(ext_data as *mut c_void), + Some(crsql_config_get), + None, + None, + None, + ) + .unwrap_or(sqlite::ResultCode::ERROR); + if rc != ResultCode::OK { + return null_mut(); + } + return ext_data as *mut c_void; } diff --git a/core/src/ext-data.c b/core/src/ext-data.c index fc14406c3..db82feba0 100644 --- a/core/src/ext-data.c +++ b/core/src/ext-data.c @@ -1,5 +1,7 @@ #include "ext-data.h" +#include + #include "consts.h" void crsql_clear_stmt_cache(crsql_ExtData *pExtData); @@ -52,15 +54,45 @@ crsql_ExtData *crsql_newExtData(sqlite3 *db, unsigned char *siteIdBuffer) { pExtData->updatedTableInfosThisTx = 0; crsql_init_table_info_vec(pExtData); - int pv = crsql_fetchPragmaDataVersion(db, pExtData); - if (pv == -1 || rc != SQLITE_OK) { + sqlite3_stmt *pStmt; + + rc += sqlite3_prepare_v2(db, + "SELECT ltrim(key, 'config.'), value FROM " + "crsql_master WHERE key LIKE 'config.%';", + -1, &pStmt, 0); + + if (rc != SQLITE_OK) { crsql_freeExtData(pExtData); return 0; } - // default to not tie-breaking + // set defaults! pExtData->tieBreakSameColValue = 0; + while (sqlite3_step(pStmt) == SQLITE_ROW) { + const unsigned char *name = sqlite3_column_text(pStmt, 1); + if (sqlite3_stricmp(name, "merge-equal-values")) { + if (sqlite3_column_type(pStmt, 2) == SQLITE_INTEGER) { + const int value = sqlite3_column_int(pStmt, 2); + pExtData->tieBreakSameColValue = value; + } else { + // broken setting... + crsql_freeExtData(pExtData); + return 0; + } + } else { + // unhandled config setting + } + } + + sqlite3_finalize(pStmt); + + int pv = crsql_fetchPragmaDataVersion(db, pExtData); + if (pv == -1 || rc != SQLITE_OK) { + crsql_freeExtData(pExtData); + return 0; + } + return pExtData; } diff --git a/py/correctness/tests/test_config.py b/py/correctness/tests/test_config.py new file mode 100644 index 000000000..012680816 --- /dev/null +++ b/py/correctness/tests/test_config.py @@ -0,0 +1,14 @@ +from crsql_correctness import connect, close, get_site_id +import pprint + +def test_config_merge_equal_values(): + db = connect(":memory:") + value = db.execute("SELECT crsql_config_set('merge-equal-values', 1);").fetchone() + assert (value == (1,)) + db.commit() + + value = db.execute("SELECT value FROM crsql_master WHERE key = 'config.merge-equal-values'").fetchone() + assert (value == (1,)) + + value = db.execute("SELECT crsql_config_get('merge-equal-values');").fetchone() + assert (value == (1,)) \ No newline at end of file From bdc07101fa72bb5ed79209c03533c5d130215d4c Mon Sep 17 00:00:00 2001 From: Jerome Gravel-Niquet Date: Tue, 26 Dec 2023 16:22:15 -0500 Subject: [PATCH 7/9] fix config not being loaded properly on init --- core/rs/bundle/Cargo.lock | 4 ++-- core/rs/core/Cargo.lock | 4 ++-- core/rs/core/src/c.rs | 6 +++--- core/rs/core/src/changes_vtab_write.rs | 2 +- core/rs/core/src/config.rs | 4 ++-- core/rs/core/src/lib.rs | 4 +++- core/rs/core/src/sha.rs | 2 +- core/src/ext-data.c | 18 +++++++++++------- core/src/ext-data.h | 2 +- py/correctness/tests/test_config.py | 19 +++++++++++++++---- 10 files changed, 41 insertions(+), 24 deletions(-) diff --git a/core/rs/bundle/Cargo.lock b/core/rs/bundle/Cargo.lock index e1f4bdb01..8b964eb60 100644 --- a/core/rs/bundle/Cargo.lock +++ b/core/rs/bundle/Cargo.lock @@ -121,9 +121,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libloading" diff --git a/core/rs/core/Cargo.lock b/core/rs/core/Cargo.lock index 244a76aa7..d2006ae23 100644 --- a/core/rs/core/Cargo.lock +++ b/core/rs/core/Cargo.lock @@ -105,9 +105,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.140" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libloading" diff --git a/core/rs/core/src/c.rs b/core/rs/core/src/c.rs index b93686035..a053b8882 100644 --- a/core/rs/core/src/c.rs +++ b/core/rs/core/src/c.rs @@ -67,7 +67,7 @@ pub struct crsql_ExtData { pub pSetSiteIdOrdinalStmt: *mut sqlite::stmt, pub pSelectSiteIdOrdinalStmt: *mut sqlite::stmt, pub pSelectClockTablesStmt: *mut sqlite::stmt, - pub tieBreakSameColValue: ::core::ffi::c_int, + pub mergeEqualValues: ::core::ffi::c_int, } #[repr(C)] @@ -454,13 +454,13 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).tieBreakSameColValue) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).mergeEqualValues) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", stringify!(crsql_ExtData), "::", - stringify!(tieBreakSameColValue) + stringify!(mergeEqualValues) ) ); } diff --git a/core/rs/core/src/changes_vtab_write.rs b/core/rs/core/src/changes_vtab_write.rs index e4fca3d52..3f26b07ab 100644 --- a/core/rs/core/src/changes_vtab_write.rs +++ b/core/rs/core/src/changes_vtab_write.rs @@ -93,7 +93,7 @@ fn did_cid_win( let local_value = col_val_stmt.column_value(0)?; let mut ret = crsql_compare_sqlite_values(insert_val, local_value); reset_cached_stmt(col_val_stmt.stmt)?; - if ret == 0 && unsafe { (*ext_data).tieBreakSameColValue == 1 } { + if ret == 0 && unsafe { (*ext_data).mergeEqualValues == 1 } { // values are the same (ret == 0) and the option to tie break on site_id is true ret = unsafe { let my_site_id = core::slice::from_raw_parts((*ext_data).siteId, 16); diff --git a/core/rs/core/src/config.rs b/core/rs/core/src/config.rs index 81961a863..e53fc3336 100644 --- a/core/rs/core/src/config.rs +++ b/core/rs/core/src/config.rs @@ -21,7 +21,7 @@ pub extern "C" fn crsql_config_set( MERGE_EQUAL_VALUES => { let value = args[1]; let ext_data = ctx.user_data() as *mut crsql_ExtData; - unsafe { (*ext_data).tieBreakSameColValue = value.int() }; + unsafe { (*ext_data).mergeEqualValues = value.int() }; value } _ => { @@ -74,7 +74,7 @@ pub extern "C" fn crsql_config_get( match name { MERGE_EQUAL_VALUES => { let ext_data = ctx.user_data() as *mut crsql_ExtData; - ctx.result_int(unsafe { (*ext_data).tieBreakSameColValue }); + ctx.result_int(unsafe { (*ext_data).mergeEqualValues }); } _ => { ctx.result_error("Unknown setting name"); diff --git a/core/rs/core/src/lib.rs b/core/rs/core/src/lib.rs index 57f38b6c5..0aafa90fb 100644 --- a/core/rs/core/src/lib.rs +++ b/core/rs/core/src/lib.rs @@ -214,7 +214,7 @@ pub extern "C" fn sqlite3_crsqlcore_init( let ext_data = unsafe { crsql_newExtData(db, site_id_buffer as *mut c_char) }; if ext_data.is_null() { - sqlite::free(site_id_buffer as *mut c_void); + // no need to free the site id buffer here, this is cleaned up already. return null_mut(); } @@ -486,6 +486,7 @@ pub extern "C" fn sqlite3_crsqlcore_init( ) .unwrap_or(sqlite::ResultCode::ERROR); if rc != ResultCode::OK { + unsafe { crsql_freeExtData(ext_data) }; return null_mut(); } @@ -502,6 +503,7 @@ pub extern "C" fn sqlite3_crsqlcore_init( ) .unwrap_or(sqlite::ResultCode::ERROR); if rc != ResultCode::OK { + unsafe { crsql_freeExtData(ext_data) }; return null_mut(); } diff --git a/core/rs/core/src/sha.rs b/core/rs/core/src/sha.rs index df78688cf..496cb4ccf 100644 --- a/core/rs/core/src/sha.rs +++ b/core/rs/core/src/sha.rs @@ -1,2 +1,2 @@ // The sha of the commit that this version of crsqlite was built from. -pub const SHA: &'static str = ""; +pub const SHA: &'static str = "3a01980562615001d765eec61e3ed58147a93f93"; diff --git a/core/src/ext-data.c b/core/src/ext-data.c index db82feba0..f8715f4f9 100644 --- a/core/src/ext-data.c +++ b/core/src/ext-data.c @@ -1,6 +1,7 @@ #include "ext-data.h" #include +#include #include "consts.h" @@ -11,6 +12,8 @@ void crsql_drop_table_info_vec(crsql_ExtData *pExtData); crsql_ExtData *crsql_newExtData(sqlite3 *db, unsigned char *siteIdBuffer) { crsql_ExtData *pExtData = sqlite3_malloc(sizeof *pExtData); + pExtData->siteId = siteIdBuffer; + pExtData->pPragmaSchemaVersionStmt = 0; int rc = sqlite3_prepare_v3(db, "PRAGMA schema_version", -1, SQLITE_PREPARE_PERSISTENT, @@ -47,7 +50,6 @@ crsql_ExtData *crsql_newExtData(sqlite3 *db, unsigned char *siteIdBuffer) { pExtData->pragmaSchemaVersion = -1; pExtData->pragmaDataVersion = -1; pExtData->pragmaSchemaVersionForTableInfos = -1; - pExtData->siteId = siteIdBuffer; pExtData->pDbVersionStmt = 0; pExtData->tableInfos = 0; pExtData->rowsImpacted = 0; @@ -67,14 +69,16 @@ crsql_ExtData *crsql_newExtData(sqlite3 *db, unsigned char *siteIdBuffer) { } // set defaults! - pExtData->tieBreakSameColValue = 0; + pExtData->mergeEqualValues = 0; while (sqlite3_step(pStmt) == SQLITE_ROW) { - const unsigned char *name = sqlite3_column_text(pStmt, 1); - if (sqlite3_stricmp(name, "merge-equal-values")) { - if (sqlite3_column_type(pStmt, 2) == SQLITE_INTEGER) { - const int value = sqlite3_column_int(pStmt, 2); - pExtData->tieBreakSameColValue = value; + const unsigned char *name = sqlite3_column_text(pStmt, 0); + int colType = sqlite3_column_type(pStmt, 1); + + if (strcmp("merge-equal-values", (char *)name) == 0) { + if (colType == SQLITE_INTEGER) { + const int value = sqlite3_column_int(pStmt, 1); + pExtData->mergeEqualValues = value; } else { // broken setting... crsql_freeExtData(pExtData); diff --git a/core/src/ext-data.h b/core/src/ext-data.h index c7379de47..c4ff801d0 100644 --- a/core/src/ext-data.h +++ b/core/src/ext-data.h @@ -43,7 +43,7 @@ struct crsql_ExtData { sqlite3_stmt *pSelectSiteIdOrdinalStmt; sqlite3_stmt *pSelectClockTablesStmt; - int tieBreakSameColValue; + int mergeEqualValues; }; crsql_ExtData *crsql_newExtData(sqlite3 *db, unsigned char *siteIdBuffer); diff --git a/py/correctness/tests/test_config.py b/py/correctness/tests/test_config.py index 012680816..3291000d2 100644 --- a/py/correctness/tests/test_config.py +++ b/py/correctness/tests/test_config.py @@ -1,8 +1,10 @@ -from crsql_correctness import connect, close, get_site_id -import pprint +from crsql_correctness import connect, close +import pathlib def test_config_merge_equal_values(): - db = connect(":memory:") + dbfile = "./config.db" + pathlib.Path(dbfile).unlink(missing_ok=True) + db = connect(dbfile) value = db.execute("SELECT crsql_config_set('merge-equal-values', 1);").fetchone() assert (value == (1,)) db.commit() @@ -11,4 +13,13 @@ def test_config_merge_equal_values(): assert (value == (1,)) value = db.execute("SELECT crsql_config_get('merge-equal-values');").fetchone() - assert (value == (1,)) \ No newline at end of file + assert (value == (1,)) + + close(db) + db = connect(dbfile) + + value = db.execute("SELECT value FROM crsql_master WHERE key = 'config.merge-equal-values'").fetchone() + assert (value == (1,)) + + value = db.execute("SELECT crsql_config_get('merge-equal-values')").fetchone() + assert (value == (1,)) From af73ad197eff6789495d0ae544c1de079f3c0980 Mon Sep 17 00:00:00 2001 From: Jerome Gravel-Niquet Date: Tue, 26 Dec 2023 16:51:27 -0500 Subject: [PATCH 8/9] re-generate bindings to use core instead of std --- core/rs/core/src/c.rs | 44 +++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/core/rs/core/src/c.rs b/core/rs/core/src/c.rs index a053b8882..333fbb372 100644 --- a/core/rs/core/src/c.rs +++ b/core/rs/core/src/c.rs @@ -259,20 +259,20 @@ fn bindgen_test_layout_crsql_Changes_cursor() { #[test] #[allow(non_snake_case)] fn bindgen_test_layout_crsql_ExtData() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + const UNINIT: ::core::mem::MaybeUninit = ::core::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( - ::std::mem::size_of::(), + ::core::mem::size_of::(), 136usize, concat!("Size of: ", stringify!(crsql_ExtData)) ); assert_eq!( - ::std::mem::align_of::(), + ::core::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(crsql_ExtData)) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pPragmaSchemaVersionStmt) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).pPragmaSchemaVersionStmt) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", @@ -282,7 +282,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pPragmaDataVersionStmt) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).pPragmaDataVersionStmt) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", @@ -292,7 +292,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pragmaDataVersion) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).pragmaDataVersion) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", @@ -302,7 +302,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).dbVersion) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).dbVersion) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", @@ -312,7 +312,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pendingDbVersion) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).pendingDbVersion) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", @@ -322,7 +322,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pragmaSchemaVersion) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).pragmaSchemaVersion) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", @@ -332,7 +332,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).updatedTableInfosThisTx) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).updatedTableInfosThisTx) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", @@ -343,7 +343,7 @@ fn bindgen_test_layout_crsql_ExtData() { ); assert_eq!( unsafe { - ::std::ptr::addr_of!((*ptr).pragmaSchemaVersionForTableInfos) as usize - ptr as usize + ::core::ptr::addr_of!((*ptr).pragmaSchemaVersionForTableInfos) as usize - ptr as usize }, 48usize, concat!( @@ -354,7 +354,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).siteId) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).siteId) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", @@ -364,7 +364,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pDbVersionStmt) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).pDbVersionStmt) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", @@ -374,7 +374,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).tableInfos) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).tableInfos) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", @@ -384,7 +384,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).rowsImpacted) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).rowsImpacted) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", @@ -394,7 +394,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).seq) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).seq) as usize - ptr as usize }, 84usize, concat!( "Offset of field: ", @@ -404,7 +404,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pSetSyncBitStmt) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).pSetSyncBitStmt) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", @@ -414,7 +414,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pClearSyncBitStmt) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).pClearSyncBitStmt) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", @@ -424,7 +424,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pSetSiteIdOrdinalStmt) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).pSetSiteIdOrdinalStmt) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", @@ -434,7 +434,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pSelectSiteIdOrdinalStmt) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).pSelectSiteIdOrdinalStmt) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", @@ -444,7 +444,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pSelectClockTablesStmt) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).pSelectClockTablesStmt) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", @@ -454,7 +454,7 @@ fn bindgen_test_layout_crsql_ExtData() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).mergeEqualValues) as usize - ptr as usize }, + unsafe { ::core::ptr::addr_of!((*ptr).mergeEqualValues) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", From e2297377be4a4004b23104e8f55be931f838f250 Mon Sep 17 00:00:00 2001 From: Jerome Gravel-Niquet Date: Tue, 26 Dec 2023 16:51:45 -0500 Subject: [PATCH 9/9] add INNOCUOUS and DETERMINISTIC to crsql_config_get --- core/rs/core/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/rs/core/src/lib.rs b/core/rs/core/src/lib.rs index 0aafa90fb..17b1ec49d 100644 --- a/core/rs/core/src/lib.rs +++ b/core/rs/core/src/lib.rs @@ -494,7 +494,7 @@ pub extern "C" fn sqlite3_crsqlcore_init( .create_function_v2( "crsql_config_get", 1, - sqlite::UTF8, + sqlite::UTF8 | sqlite::INNOCUOUS | sqlite::DETERMINISTIC, Some(ext_data as *mut c_void), Some(crsql_config_get), None,