Skip to content

Commit a06684b

Browse files
committed
Sync local: Refactor to avoid unwrap()
1 parent 8a1efcc commit a06684b

File tree

1 file changed

+84
-56
lines changed

1 file changed

+84
-56
lines changed

crates/core/src/sync_local.rs

Lines changed: 84 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,13 @@ impl<'a> SyncOperation<'a> {
136136
let statement = self.collect_full_operations()?;
137137

138138
// We cache the last insert and delete statements for each row
139-
let mut last_insert_table: Option<String> = None;
140-
let mut last_insert_statement: Option<ManagedStmt> = None;
139+
struct CachedStatement {
140+
table: String,
141+
statement: ManagedStmt,
142+
}
141143

142-
let mut last_delete_table: Option<String> = None;
143-
let mut last_delete_statement: Option<ManagedStmt> = None;
144+
let mut last_insert = None::<CachedStatement>;
145+
let mut last_delete = None::<CachedStatement>;
144146

145147
let mut untyped_delete_statement: Option<ManagedStmt> = None;
146148
let mut untyped_insert_statement: Option<ManagedStmt> = None;
@@ -173,35 +175,50 @@ impl<'a> SyncOperation<'a> {
173175
// NULL data means no PUT operations found, so we delete the row.
174176
if data.is_err() {
175177
// DELETE
176-
if last_delete_table.as_deref() != Some(&quoted) {
177-
// Prepare statement when the table changed
178-
last_delete_statement = Some(
179-
self.db
178+
let delete_statement = match &last_delete {
179+
Some(stmt) if &*stmt.table == &*quoted => &stmt.statement,
180+
_ => {
181+
// Prepare statement when the table changed
182+
let statement = self
183+
.db
180184
.prepare_v2(&format!("DELETE FROM {} WHERE id = ?", quoted))
181-
.into_db_result(self.db)?,
182-
);
183-
last_delete_table = Some(quoted.clone());
184-
}
185-
let delete_statement = last_delete_statement.as_mut().unwrap();
185+
.into_db_result(self.db)?;
186+
187+
&last_delete
188+
.insert(CachedStatement {
189+
table: quoted.clone(),
190+
statement,
191+
})
192+
.statement
193+
}
194+
};
186195

187196
delete_statement.reset()?;
188197
delete_statement.bind_text(1, id, sqlite::Destructor::STATIC)?;
189198
delete_statement.exec()?;
190199
} else {
191200
// INSERT/UPDATE
192-
if last_insert_table.as_deref() != Some(&quoted) {
193-
// Prepare statement when the table changed
194-
last_insert_statement = Some(
195-
self.db
201+
let insert_statement = match &last_insert {
202+
Some(stmt) if &*stmt.table == &*quoted => &stmt.statement,
203+
_ => {
204+
// Prepare statement when the table changed
205+
let statement = self
206+
.db
196207
.prepare_v2(&format!(
197208
"REPLACE INTO {}(id, data) VALUES(?, ?)",
198209
quoted
199210
))
200-
.into_db_result(self.db)?,
201-
);
202-
last_insert_table = Some(quoted.clone());
203-
}
204-
let insert_statement = last_insert_statement.as_mut().unwrap();
211+
.into_db_result(self.db)?;
212+
213+
&last_insert
214+
.insert(CachedStatement {
215+
table: quoted.clone(),
216+
statement,
217+
})
218+
.statement
219+
}
220+
};
221+
205222
insert_statement.reset()?;
206223
insert_statement.bind_text(1, id, sqlite::Destructor::STATIC)?;
207224
insert_statement.bind_text(2, data?, sqlite::Destructor::STATIC)?;
@@ -211,32 +228,38 @@ impl<'a> SyncOperation<'a> {
211228
} else {
212229
if data.is_err() {
213230
// DELETE
214-
if untyped_delete_statement.is_none() {
215-
// Prepare statement on first use
216-
untyped_delete_statement = Some(
217-
self.db
218-
.prepare_v2("DELETE FROM ps_untyped WHERE type = ? AND id = ?")
219-
.into_db_result(self.db)?,
220-
);
221-
}
222-
let delete_statement = untyped_delete_statement.as_mut().unwrap();
231+
let delete_statement = match &untyped_delete_statement {
232+
Some(stmt) => stmt,
233+
None => {
234+
// Prepare statement on first use
235+
untyped_delete_statement.insert(
236+
self.db
237+
.prepare_v2("DELETE FROM ps_untyped WHERE type = ? AND id = ?")
238+
.into_db_result(self.db)?,
239+
)
240+
}
241+
};
242+
223243
delete_statement.reset()?;
224244
delete_statement.bind_text(1, type_name, sqlite::Destructor::STATIC)?;
225245
delete_statement.bind_text(2, id, sqlite::Destructor::STATIC)?;
226246
delete_statement.exec()?;
227247
} else {
228248
// INSERT/UPDATE
229-
if untyped_insert_statement.is_none() {
230-
// Prepare statement on first use
231-
untyped_insert_statement = Some(
232-
self.db
233-
.prepare_v2(
234-
"REPLACE INTO ps_untyped(type, id, data) VALUES(?, ?, ?)",
235-
)
236-
.into_db_result(self.db)?,
237-
);
238-
}
239-
let insert_statement = untyped_insert_statement.as_mut().unwrap();
249+
let insert_statement = match &untyped_insert_statement {
250+
Some(stmt) => stmt,
251+
None => {
252+
// Prepare statement on first use
253+
untyped_insert_statement.insert(
254+
self.db
255+
.prepare_v2(
256+
"REPLACE INTO ps_untyped(type, id, data) VALUES(?, ?, ?)",
257+
)
258+
.into_db_result(self.db)?,
259+
)
260+
}
261+
};
262+
240263
insert_statement.reset()?;
241264
insert_statement.bind_text(1, type_name, sqlite::Destructor::STATIC)?;
242265
insert_statement.bind_text(2, id, sqlite::Destructor::STATIC)?;
@@ -449,30 +472,35 @@ struct RawTableWithCachedStatements<'a> {
449472
}
450473

451474
impl<'a> RawTableWithCachedStatements<'a> {
475+
fn prepare_lazily<'b>(
476+
db: *mut sqlite::sqlite3,
477+
slot: &'b mut Option<PreparedPendingStatement<'a>>,
478+
def: &'a PendingStatement,
479+
) -> Result<&'b PreparedPendingStatement<'a>, PowerSyncError>
480+
where
481+
'a: 'b,
482+
{
483+
Ok(match slot {
484+
Some(stmt) => stmt,
485+
None => {
486+
let stmt = PreparedPendingStatement::prepare(db, def)?;
487+
slot.insert(stmt)
488+
}
489+
})
490+
}
491+
452492
fn put_statement(
453493
&mut self,
454494
db: *mut sqlite::sqlite3,
455495
) -> Result<&PreparedPendingStatement, PowerSyncError> {
456-
let cache_slot = &mut self.cached_put;
457-
if let None = cache_slot {
458-
let stmt = PreparedPendingStatement::prepare(db, &self.definition.put)?;
459-
*cache_slot = Some(stmt);
460-
}
461-
462-
return Ok(cache_slot.as_ref().unwrap());
496+
Self::prepare_lazily(db, &mut self.cached_put, &self.definition.put)
463497
}
464498

465499
fn delete_statement(
466500
&mut self,
467501
db: *mut sqlite::sqlite3,
468502
) -> Result<&PreparedPendingStatement, PowerSyncError> {
469-
let cache_slot = &mut self.cached_delete;
470-
if let None = cache_slot {
471-
let stmt = PreparedPendingStatement::prepare(db, &self.definition.delete)?;
472-
*cache_slot = Some(stmt);
473-
}
474-
475-
return Ok(cache_slot.as_ref().unwrap());
503+
Self::prepare_lazily(db, &mut self.cached_delete, &self.definition.delete)
476504
}
477505
}
478506

0 commit comments

Comments
 (0)