Skip to content

Commit 2f13b68

Browse files
committed
Persisted down migrations for version 5.
1 parent be2003c commit 2f13b68

File tree

3 files changed

+67
-93
lines changed

3 files changed

+67
-93
lines changed

crates/core/src/view_admin.rs

Lines changed: 25 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -146,65 +146,6 @@ CREATE TABLE IF NOT EXISTS ps_migration(id INTEGER PRIMARY KEY, down_migrations
146146
down_sql.push(sql.to_string());
147147
}
148148

149-
if current_version == 5 {
150-
down_sql.push(
151-
"\
152-
-- Drop all existing views (and triggers)
153-
SELECT powersync_drop_view(view.name)
154-
FROM sqlite_master view
155-
WHERE view.type = 'view'
156-
AND view.sql GLOB '*-- powersync-auto-generated';
157-
158-
ALTER TABLE ps_buckets RENAME TO ps_buckets_5;
159-
ALTER TABLE ps_oplog RENAME TO ps_oplog_5;
160-
161-
CREATE TABLE ps_buckets(
162-
name TEXT PRIMARY KEY,
163-
last_applied_op INTEGER NOT NULL DEFAULT 0,
164-
last_op INTEGER NOT NULL DEFAULT 0,
165-
target_op INTEGER NOT NULL DEFAULT 0,
166-
add_checksum INTEGER NOT NULL DEFAULT 0,
167-
pending_delete INTEGER NOT NULL DEFAULT 0
168-
, op_checksum INTEGER NOT NULL DEFAULT 0, remove_operations INTEGER NOT NULL DEFAULT 0);
169-
170-
INSERT INTO ps_buckets(name, last_applied_op, last_op, target_op, add_checksum, op_checksum, pending_delete)
171-
SELECT name, last_applied_op, last_op, target_op, add_checksum, op_checksum, pending_delete FROM ps_buckets_5;
172-
173-
CREATE TABLE ps_oplog(
174-
bucket TEXT NOT NULL,
175-
op_id INTEGER NOT NULL,
176-
op INTEGER NOT NULL,
177-
row_type TEXT,
178-
row_id TEXT,
179-
key TEXT,
180-
data TEXT,
181-
hash INTEGER NOT NULL,
182-
superseded INTEGER NOT NULL);
183-
184-
CREATE INDEX ps_oplog_by_row ON ps_oplog (row_type, row_id) WHERE superseded = 0;
185-
CREATE INDEX ps_oplog_by_opid ON ps_oplog (bucket, op_id);
186-
CREATE INDEX ps_oplog_by_key ON ps_oplog (bucket, key) WHERE superseded = 0;
187-
188-
INSERT INTO ps_oplog(bucket, op_id, op, row_type, row_id, key, data, hash, superseded)
189-
SELECT ps_buckets_5.name, oplog.op_id, 3, oplog.row_type, oplog.row_id, oplog.key, oplog.data, oplog.hash, 0
190-
FROM ps_oplog_5 oplog
191-
JOIN ps_buckets_5
192-
ON ps_buckets_5.id = oplog.bucket;
193-
194-
DROP TABLE ps_oplog_5;
195-
DROP TABLE ps_buckets_5;
196-
197-
INSERT INTO ps_oplog(bucket, op_id, op, row_type, row_id, hash, superseded)
198-
SELECT '$local', 1, 4, r.row_type, r.row_id, 0, 0
199-
FROM ps_updated_rows r;
200-
INSERT OR REPLACE INTO ps_buckets(name, pending_delete, last_op, target_op) VALUES('$local', 1, 0, 9223372036854775807);
201-
202-
DROP TABLE ps_updated_rows
203-
"
204-
.to_string(),
205-
);
206-
}
207-
208149
for sql in down_sql {
209150
let rs = local_db.exec_safe(&sql);
210151
if let Err(code) = rs {
@@ -328,11 +269,17 @@ INSERT INTO ps_migration(id, down_migrations)
328269
}
329270

330271
if current_version < 5 && target_version >= 5 {
272+
// Start by dropping all existing views and triggers (but not tables).
273+
// This is because the triggers are restructured in this version, and
274+
// need to be re-created from scratch. Not dropping them can make it
275+
// refer to tables or columns not existing anymore, which can case
276+
// issues later on.
277+
// The same applies for the down migration.
278+
331279
// language=SQLite
332280
local_db
333281
.exec_safe(
334282
"\
335-
-- Drop all existing views (and triggers)
336283
SELECT powersync_drop_view(view.name)
337284
FROM sqlite_master view
338285
WHERE view.type = 'view'
@@ -410,6 +357,24 @@ DROP TABLE ps_oplog_old;
410357
INSERT INTO ps_migration(id, down_migrations)
411358
VALUES(5,
412359
json_array(
360+
-- Drop existing views and triggers if any
361+
json_object('sql', 'SELECT powersync_drop_view(view.name)\n FROM sqlite_master view\n WHERE view.type = ''view''\n AND view.sql GLOB ''*-- powersync-auto-generated'''),
362+
363+
json_object('sql', 'ALTER TABLE ps_buckets RENAME TO ps_buckets_5'),
364+
json_object('sql', 'ALTER TABLE ps_oplog RENAME TO ps_oplog_5'),
365+
json_object('sql', 'CREATE TABLE ps_buckets(\n name TEXT PRIMARY KEY,\n last_applied_op INTEGER NOT NULL DEFAULT 0,\n last_op INTEGER NOT NULL DEFAULT 0,\n target_op INTEGER NOT NULL DEFAULT 0,\n add_checksum INTEGER NOT NULL DEFAULT 0,\n pending_delete INTEGER NOT NULL DEFAULT 0\n, op_checksum INTEGER NOT NULL DEFAULT 0, remove_operations INTEGER NOT NULL DEFAULT 0)'),
366+
json_object('sql', 'INSERT INTO ps_buckets(name, last_applied_op, last_op, target_op, add_checksum, op_checksum, pending_delete)\n SELECT name, last_applied_op, last_op, target_op, add_checksum, op_checksum, pending_delete FROM ps_buckets_5'),
367+
json_object('sql', 'CREATE TABLE ps_oplog(\n bucket TEXT NOT NULL,\n op_id INTEGER NOT NULL,\n op INTEGER NOT NULL,\n row_type TEXT,\n row_id TEXT,\n key TEXT,\n data TEXT,\n hash INTEGER NOT NULL,\n superseded INTEGER NOT NULL)'),
368+
json_object('sql', 'CREATE INDEX ps_oplog_by_row ON ps_oplog (row_type, row_id) WHERE superseded = 0'),
369+
json_object('sql', 'CREATE INDEX ps_oplog_by_opid ON ps_oplog (bucket, op_id)'),
370+
json_object('sql', 'CREATE INDEX ps_oplog_by_key ON ps_oplog (bucket, key) WHERE superseded = 0'),
371+
json_object('sql', 'INSERT INTO ps_oplog(bucket, op_id, op, row_type, row_id, key, data, hash, superseded)\n SELECT ps_buckets_5.name, oplog.op_id, 3, oplog.row_type, oplog.row_id, oplog.key, oplog.data, oplog.hash, 0\n FROM ps_oplog_5 oplog\n JOIN ps_buckets_5\n ON ps_buckets_5.id = oplog.bucket'),
372+
json_object('sql', 'DROP TABLE ps_oplog_5'),
373+
json_object('sql', 'DROP TABLE ps_buckets_5'),
374+
json_object('sql', 'INSERT INTO ps_oplog(bucket, op_id, op, row_type, row_id, hash, superseded)\n SELECT ''$local'', 1, 4, r.row_type, r.row_id, 0, 0\n FROM ps_updated_rows r'),
375+
json_object('sql', 'INSERT OR REPLACE INTO ps_buckets(name, pending_delete, last_op, target_op) VALUES(''$local'', 1, 0, 9223372036854775807)'),
376+
json_object('sql', 'DROP TABLE ps_updated_rows'),
377+
413378
json_object('sql', 'DELETE FROM ps_migration WHERE id >= 5')
414379
));
415380
",

dart/test/migration_test.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,19 @@ void main() {
3737
fixtures.expectedState.keys.last, equals(fixtures.databaseVersion));
3838
});
3939

40+
/// Test the basic database setup (no migrations from other versions).
41+
/// Get this test passing before any others below, since it tests the
42+
/// finalState fixture, which is an input in other tests.
4043
test('create database from scratch', () async {
4144
db.select('select powersync_init()');
4245
final schema = '${getSchema(db)}\n${getMigrations(db)}';
43-
expect(schema, equals(fixtures.finalState.trim()));
46+
final expected = fixtures.finalState.trim();
47+
if (expected != schema) {
48+
// This gives more usable output if the test fails
49+
print('-- CURRENT SCHEMA:');
50+
print(schema);
51+
}
52+
expect(schema, equals(expected));
4453
});
4554

4655
// We test that we can _start_ at any state, and get to

0 commit comments

Comments
 (0)