Skip to content

Commit

Permalink
write config settings to crsql_master table to persist some of them
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromegn committed Dec 22, 2023
1 parent 110df2d commit 07bdb38
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 33 deletions.
46 changes: 23 additions & 23 deletions core/rs/core/src/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<crsql_ExtData> = ::core::mem::MaybeUninit::uninit();
const UNINIT: ::std::mem::MaybeUninit<crsql_ExtData> = ::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
::core::mem::size_of::<crsql_ExtData>(),
::std::mem::size_of::<crsql_ExtData>(),
136usize,
concat!("Size of: ", stringify!(crsql_ExtData))
);
assert_eq!(
::core::mem::align_of::<crsql_ExtData>(),
::std::mem::align_of::<crsql_ExtData>(),
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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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!(
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand All @@ -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: ",
Expand Down
67 changes: 61 additions & 6 deletions core/rs/core/src/config.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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;
}
}
}
18 changes: 17 additions & 1 deletion core/rs/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,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};
Expand Down Expand Up @@ -454,6 +454,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;
}

Expand Down
38 changes: 35 additions & 3 deletions core/src/ext-data.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "ext-data.h"

#include <stdio.h>

#include "consts.h"

void crsql_clear_stmt_cache(crsql_ExtData *pExtData);
Expand Down Expand Up @@ -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;
}

Expand Down
14 changes: 14 additions & 0 deletions py/correctness/tests/test_config.py
Original file line number Diff line number Diff line change
@@ -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,))

0 comments on commit 07bdb38

Please sign in to comment.