-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add migration to remove any dangling rows.
- Loading branch information
Showing
8 changed files
with
219 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use alloc::format; | ||
|
||
use crate::error::{PSResult, SQLiteError}; | ||
use sqlite_nostd as sqlite; | ||
use sqlite_nostd::{Connection, ResultCode}; | ||
|
||
use crate::ext::SafeManagedStmt; | ||
use crate::util::quote_identifier; | ||
|
||
// Apply a data migration to fix any existing data affected by the issue | ||
// fixed in v0.3.5. | ||
// | ||
// The issue was that the `ps_updated_rows` table was not being populated | ||
// with remove operations in some cases. This causes the rows to be removed | ||
// from ps_oplog, but not from the ps_data__tables, resulting in dangling rows. | ||
// | ||
// The fix here is to find these dangling rows, and add them to ps_updated_rows. | ||
// The next time the sync_local operation is run, these rows will be removed. | ||
pub fn apply_v035_fix(db: *mut sqlite::sqlite3) -> Result<i64, SQLiteError> { | ||
// language=SQLite | ||
let statement = db | ||
.prepare_v2("SELECT name, powersync_external_table_name(name) FROM sqlite_master WHERE type='table' AND name GLOB 'ps_data__*'") | ||
.into_db_result(db)?; | ||
|
||
while statement.step()? == ResultCode::ROW { | ||
let full_name = statement.column_text(0)?; | ||
let short_name = statement.column_text(1)?; | ||
let quoted = quote_identifier(full_name); | ||
|
||
// language=SQLite | ||
let statement = db.prepare_v2(&format!( | ||
" | ||
INSERT OR IGNORE INTO ps_updated_rows(row_type, row_id) | ||
SELECT ?1, id FROM {} | ||
WHERE NOT EXISTS ( | ||
SELECT 1 FROM ps_oplog | ||
WHERE row_type = ?1 AND row_id = {}.id | ||
);", | ||
quoted, quoted | ||
))?; | ||
statement.bind_text(1, short_name, sqlite::Destructor::STATIC)?; | ||
|
||
statement.exec()?; | ||
} | ||
|
||
Ok(1) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ mod crud_vtab; | |
mod diff; | ||
mod error; | ||
mod ext; | ||
mod fix035; | ||
mod kv; | ||
mod macros; | ||
mod migrations; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/// Data with some records in actual tables but not in ps_oplog | ||
const dataBroken = ''' | ||
;INSERT INTO ps_buckets(id, name, last_applied_op, last_op, target_op, add_checksum, op_checksum, pending_delete) VALUES | ||
(1, 'b1', 0, 0, 0, 0, 120, 0), | ||
(2, 'b2', 0, 0, 0, 0, 3, 0) | ||
;INSERT INTO ps_oplog(bucket, op_id, row_type, row_id, key, data, hash) VALUES | ||
(1, 1, 'todos', 't1', '', '{}', 100), | ||
(1, 2, 'todos', 't2', '', '{}', 20), | ||
(2, 3, 'lists', 'l1', '', '{}', 3) | ||
;INSERT INTO ps_data__lists(id, data) VALUES | ||
('l1', '{}'), | ||
('l3', '{}') | ||
;INSERT INTO ps_data__todos(id, data) VALUES | ||
('t1', '{}'), | ||
('t2', '{}'), | ||
('t3', '{}') | ||
'''; | ||
|
||
/// Data after applying the migration fix, but before sync_local | ||
const dataMigrated = ''' | ||
;INSERT INTO ps_buckets(id, name, last_applied_op, last_op, target_op, add_checksum, op_checksum, pending_delete) VALUES | ||
(1, 'b1', 0, 0, 0, 0, 120, 0), | ||
(2, 'b2', 0, 0, 0, 0, 3, 0) | ||
;INSERT INTO ps_oplog(bucket, op_id, row_type, row_id, key, data, hash) VALUES | ||
(1, 1, 'todos', 't1', '', '{}', 100), | ||
(1, 2, 'todos', 't2', '', '{}', 20), | ||
(2, 3, 'lists', 'l1', '', '{}', 3) | ||
;INSERT INTO ps_updated_rows(row_type, row_id) VALUES | ||
('lists', 'l3'), | ||
('todos', 't3') | ||
;INSERT INTO ps_data__lists(id, data) VALUES | ||
('l1', '{}'), | ||
('l3', '{}') | ||
;INSERT INTO ps_data__todos(id, data) VALUES | ||
('t1', '{}'), | ||
('t2', '{}'), | ||
('t3', '{}') | ||
'''; | ||
|
||
/// Data after applying the migration fix and sync_local | ||
const dataFixed = ''' | ||
;INSERT INTO ps_buckets(id, name, last_applied_op, last_op, target_op, add_checksum, op_checksum, pending_delete) VALUES | ||
(1, 'b1', 0, 0, 0, 0, 120, 0), | ||
(2, 'b2', 0, 0, 0, 0, 3, 0) | ||
;INSERT INTO ps_oplog(bucket, op_id, row_type, row_id, key, data, hash) VALUES | ||
(1, 1, 'todos', 't1', '', '{}', 100), | ||
(1, 2, 'todos', 't2', '', '{}', 20), | ||
(2, 3, 'lists', 'l1', '', '{}', 3) | ||
;INSERT INTO ps_data__lists(id, data) VALUES | ||
('l1', '{}') | ||
;INSERT INTO ps_data__todos(id, data) VALUES | ||
('t1', '{}'), | ||
('t2', '{}') | ||
'''; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters