Skip to content

Commit

Permalink
code to update create records after local insertions
Browse files Browse the repository at this point in the history
  • Loading branch information
tantaman committed Sep 27, 2023
1 parent 67442e7 commit 1fc333a
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 7 deletions.
60 changes: 54 additions & 6 deletions core/rs/core/src/local_writes/after_insert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,37 @@ use alloc::string::String;
use core::ffi::c_int;
use sqlite::sqlite3;
use sqlite::value;
use sqlite::Context;
use sqlite::ResultCode;
use sqlite_nostd as sqlite;

use crate::db_version;
use crate::{c::crsql_ExtData, tableinfo::TableInfo};

use super::bump_seq;
use super::trigger_fn_preamble;

/**
* crsql_after_insert("table", pk_values...)
*/
#[no_mangle]
pub unsafe extern "C" fn crsql_after_insert(
ctx: *mut sqlite::context,
argc: c_int,
argv: *mut *mut sqlite::value,
) {
// let result = trigger_fn_preamble(ctx, argc, argv, |table_info, values, ext_data| {
// after_insert(table_info, values, ext_data)
// });
let result = trigger_fn_preamble(ctx, argc, argv, |table_info, values, ext_data| {
after_insert(ctx.db_handle(), ext_data, table_info, &values[1..])
});

match result {
Ok(_) => {
ctx.result_int64(0);
}
Err(msg) => {
ctx.result_error(&msg);
}
}
}

fn after_insert(
Expand All @@ -33,15 +47,49 @@ fn after_insert(
// just a sentinel record
return super::mark_new_pk_row_created(db, tbl_info, pks_new, db_version, seq);
} else {
let seq = bump_seq(ext_data);
// update the create record if it exists
// update_create_record_if_exists();
return Ok(ResultCode::OK);
update_create_record_if_exists(db, ext_data, tbl_info, pks_new, db_version, seq)?;
}

// now for each column, create the column record
// now for each non-pk column, create the column record
for col in tbl_info.non_pks.iter() {
let seq = bump_seq(ext_data);
// super::mark_new_column_row_created(db, tbl_info, col, val, db_version, seq)?;
}
Ok(ResultCode::OK)
}

fn update_create_record_if_exists(
db: *mut sqlite3,
ext_data: *mut crsql_ExtData,
tbl_info: &TableInfo,
pks_new: &[*mut value],
db_version: i64,
seq: i32,
) -> Result<ResultCode, String> {
let update_create_record_stmt_ref = tbl_info
.get_maybe_mark_locally_reinserted_stmt(db)
.or_else(|_e| Err("failed to get update_create_record_stmt"))?;
let update_create_record_stmt = update_create_record_stmt_ref
.as_ref()
.ok_or("Failed to deref update_create_record_stmt")?;

update_create_record_stmt
.bind_int64(1, db_version)
.and_then(|_| update_create_record_stmt.bind_int(2, seq))
.or_else(|_e| Err("failed binding to update_create_record_stmt"))?;

for (i, pk) in pks_new.iter().enumerate() {
update_create_record_stmt
.bind_value(i as i32 + 3, *pk)
.or_else(|_e| Err("failed to bind pks to update_create_record_stmt"))?;
}

update_create_record_stmt.bind_text(
pks_new.len() as i32 + 3,
crate::c::INSERT_SENTINEL,
sqlite::Destructor::STATIC,
);
Ok(ResultCode::OK)
}
2 changes: 1 addition & 1 deletion core/rs/core/src/local_writes/after_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub unsafe extern "C" fn crsql_after_update(

match result {
Ok(_) => {
ctx.result_int64(1);
ctx.result_int64(0);
}
Err(msg) => {
ctx.result_error(&msg);
Expand Down
29 changes: 29 additions & 0 deletions core/rs/core/src/tableinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub struct TableInfo {
move_non_sentinels_stmt: RefCell<Option<ManagedStmt>>,
mark_locally_created_stmt: RefCell<Option<ManagedStmt>>,
mark_locally_updated_stmt: RefCell<Option<ManagedStmt>>,
maybe_mark_locally_reinserted_stmt: RefCell<Option<ManagedStmt>>,
}

impl TableInfo {
Expand Down Expand Up @@ -315,6 +316,31 @@ impl TableInfo {
Ok(self.mark_locally_updated_stmt.try_borrow()?)
}

pub fn get_maybe_mark_locally_reinserted_stmt(
&self,
db: *mut sqlite3,
) -> Result<Ref<Option<ManagedStmt>>, ResultCode> {
if self
.maybe_mark_locally_reinserted_stmt
.try_borrow()?
.is_none()
{
let sql = format!(
"UPDATE \"{table_name}__crsql_clock\" SET
__crsql_col_version = CASE __crsql_col_version % 2 WHEN 0 THEN __crsql_col_version + 1 ELSE __crsql_col_version + 2 END,
__crsql_db_version = ?,
__crsql_seq = ?,
__crsql_site_id = NULL
WHERE {where_list} AND __crsql_col_name = ?",
table_name = crate::util::escape_ident(&self.tbl_name),
where_list = crate::util::where_list(&self.pks, None)?,
);
let ret = db.prepare_v3(&sql, sqlite::PREPARE_PERSISTENT)?;
*self.maybe_mark_locally_reinserted_stmt.try_borrow_mut()? = Some(ret);
}
Ok(self.maybe_mark_locally_reinserted_stmt.try_borrow()?)
}

pub fn get_col_value_stmt(
&self,
db: *mut sqlite3,
Expand Down Expand Up @@ -366,6 +392,8 @@ impl TableInfo {
stmt.take();
let mut stmt = self.mark_locally_updated_stmt.try_borrow_mut()?;
stmt.take();
let mut stmt = self.maybe_mark_locally_reinserted_stmt.try_borrow_mut()?;
stmt.take();

// primary key columns shouldn't have statements? right?
for col in &self.non_pks {
Expand Down Expand Up @@ -644,6 +672,7 @@ pub fn pull_table_info(
move_non_sentinels_stmt: RefCell::new(None),
mark_locally_created_stmt: RefCell::new(None),
mark_locally_updated_stmt: RefCell::new(None),
maybe_mark_locally_reinserted_stmt: RefCell::new(None),
});
}

Expand Down

0 comments on commit 1fc333a

Please sign in to comment.