Skip to content

Commit bb49941

Browse files
committed
handle schema switch for auto-migrate
1 parent 18714ac commit bb49941

File tree

7 files changed

+176
-8
lines changed

7 files changed

+176
-8
lines changed

core/rs/core/src/automigrate.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub extern "C" fn crsql_automigrate(
4141

4242
let args = args!(argc, argv);
4343
if let Err(code) = automigrate_impl(ctx, args) {
44-
ctx.result_error("failed to apply the updated schema");
44+
ctx.result_error(&format!("failed to apply the updated schema {:?}", code));
4545
ctx.result_error_code(code);
4646
return;
4747
}
@@ -137,7 +137,10 @@ fn migrate_to(local_db: *mut sqlite3, mem_db: ManagedConnection) -> Result<Resul
137137
fn strip_crr_statements(schema: &str) -> String {
138138
schema
139139
.split("\n")
140-
.filter(|line| !line.to_lowercase().contains("crsql_as_crr"))
140+
.filter(|line| {
141+
!line.to_lowercase().contains("crsql_as_crr")
142+
&& !line.to_lowercase().contains("crsql_fract_as_ordered")
143+
})
141144
.collect::<Vec<_>>()
142145
.join("\n")
143146
}

core/rs/integration-check/tests/automigrate.rs

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use sqlite::{Connection, ManagedConnection, ResultCode};
22
use sqlite_nostd as sqlite;
33

44
// TODO: auto-calculate starting number
5-
integration_utils::counter_setup!(25);
5+
integration_utils::counter_setup!(26);
66

77
#[test]
88
fn empty_schema() {
@@ -141,6 +141,158 @@ fn no_default_value() {
141141
decrement_counter();
142142
}
143143

144+
#[test]
145+
fn strut_schema() {
146+
strut_schema_impl().unwrap();
147+
decrement_counter();
148+
}
149+
150+
fn strut_schema_impl() -> Result<(), ResultCode> {
151+
let db = integration_utils::opendb()?;
152+
let stmt = db.db.prepare_v2(
153+
r#"
154+
SELECT crsql_automigrate(?)"#,
155+
)?;
156+
stmt.bind_text(
157+
1,
158+
r#"
159+
CREATE TABLE IF NOT EXISTS "deck" (
160+
"id" INTEGER primary key,
161+
"title",
162+
"created",
163+
"modified",
164+
"theme_id",
165+
"chosen_presenter"
166+
);
167+
168+
CREATE TABLE IF NOT EXISTS "slide" (
169+
"id" INTEGER primary key,
170+
"deck_id",
171+
"order",
172+
"created",
173+
"modified",
174+
"x",
175+
"y",
176+
"z"
177+
);
178+
179+
CREATE INDEX IF NOT EXISTS "slide_deck_id" ON "slide" ("deck_id", "order");
180+
181+
CREATE TABLE IF NOT EXISTS "text_component" (
182+
"id" INTEGER primary key,
183+
"slide_id",
184+
"text",
185+
"styles",
186+
"x",
187+
"y"
188+
);
189+
190+
CREATE TABLE IF NOT EXISTS "embed_component" ("id" primary key, "slide_id", "src", "x", "y");
191+
192+
CREATE INDEX IF NOT EXISTS "embed_component_slide_id" ON "embed_component" ("slide_id");
193+
194+
CREATE TABLE IF NOT EXISTS "shape_component" (
195+
"id" INTEGER primary key,
196+
"slide_id",
197+
"type",
198+
"props",
199+
"x",
200+
"y"
201+
);
202+
203+
CREATE INDEX IF NOT EXISTS "shape_component_slide_id" ON "shape_component" ("slide_id");
204+
205+
CREATE TABLE IF NOT EXISTS "line_component" ("id" primary key, "slide_id", "props");
206+
207+
CREATE INDEX IF NOT EXISTS "line_component_slide_id" ON "line_component" ("slide_id");
208+
209+
CREATE TABLE IF NOT EXISTS "line_point" ("id" primary key, "line_id", "x", "y");
210+
211+
CREATE INDEX IF NOT EXISTS "line_point_line_id" ON "line_point" ("line_id");
212+
213+
CREATE INDEX IF NOT EXISTS "text_component_slide_id" ON "text_component" ("slide_id");
214+
215+
CREATE TABLE IF NOT EXISTS "theme" (
216+
"id" INTEGER primary key,
217+
"name",
218+
"bg_colorset",
219+
"fg_colorset",
220+
"fontset",
221+
"surface_color",
222+
"font_color"
223+
);
224+
225+
CREATE TABLE IF NOT EXISTS "recent_color" (
226+
"color" INTEGER primary key,
227+
"last_used",
228+
"first_used",
229+
"theme_id"
230+
);
231+
232+
CREATE TABLE IF NOT EXISTS "presenter" (
233+
"name" primary key,
234+
"available_transitions",
235+
"picked_transition"
236+
);
237+
238+
SELECT crsql_as_crr('deck');
239+
240+
SELECT crsql_as_crr('slide');
241+
242+
SELECT crsql_fract_as_ordered('slide', 'order', 'deck_id');
243+
244+
SELECT crsql_as_crr('text_component');
245+
246+
SELECT crsql_as_crr('embed_component');
247+
248+
SELECT crsql_as_crr('shape_component');
249+
250+
SELECT crsql_as_crr('line_component');
251+
252+
SELECT crsql_as_crr('line_point');
253+
254+
SELECT crsql_as_crr('theme');
255+
256+
SELECT crsql_as_crr('recent_color');
257+
258+
SELECT crsql_as_crr('presenter');
259+
260+
CREATE TABLE IF NOT EXISTS "selected_slide" (
261+
"deck_id",
262+
"slide_id",
263+
primary key ("deck_id", "slide_id")
264+
);
265+
266+
CREATE TABLE IF NOT EXISTS "selected_component" (
267+
"slide_id",
268+
"component_id",
269+
"component_type",
270+
primary key ("slide_id", "component_id")
271+
);
272+
273+
CREATE TABLE IF NOT EXISTS "undo_stack" (
274+
"deck_id",
275+
"operation",
276+
"order",
277+
primary key ("deck_id", "order")
278+
);
279+
280+
CREATE TABLE IF NOT EXISTS "redo_stack" (
281+
"deck_id",
282+
"operation",
283+
"order",
284+
primary key ("deck_id", "order")
285+
);"#,
286+
sqlite::Destructor::STATIC,
287+
)?;
288+
stmt.step()?;
289+
assert_eq!(stmt.column_text(0)?, "migration complete");
290+
stmt.reset()?;
291+
stmt.step()?;
292+
assert_eq!(stmt.column_text(0)?, "migration complete");
293+
Ok(())
294+
}
295+
144296
fn empty_schema_impl() -> Result<(), ResultCode> {
145297
let db = integration_utils::opendb()?;
146298
let stmt = db.db.prepare_v2("SELECT crsql_automigrate('')")?;

js/packages/crsqlite-wasm/src/DB.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,16 @@ export class DB implements DBAsync {
8686
: "migrate";
8787

8888
await this.tx(async (tx) => {
89-
if (storedVersion == null) {
89+
if (storedVersion == null || storedName !== schemaName) {
90+
if (storedName !== schemaName) {
91+
// drop all tables since a schema name change is a reformat of the db.
92+
const tables = await tx.execA(
93+
`SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE '%crsql_%'`
94+
);
95+
for (const table of tables) {
96+
await tx.exec(`DROP TABLE [${table[0]}]`);
97+
}
98+
}
9099
await tx.exec(schemaContent);
91100
} else {
92101
await tx.exec(`SELECT crsql_automigrate(?)`, [schemaContent]);
@@ -100,6 +109,7 @@ export class DB implements DBAsync {
100109
["schema_name", schemaName]
101110
);
102111
});
112+
await this.exec(`VACUUM;`);
103113

104114
return ret;
105115
}

js/packages/direct-connect-browser/src/WorkerInterface.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { DBID, Endpoints, FromWorkerMsg, SyncedRemoteMsg } from "./Types";
1+
import { Endpoints, FromWorkerMsg, SyncedRemoteMsg } from "./Types";
2+
import { DBID } from "@vlcn.io/xplat-api";
23
import tblrx, { Src } from "@vlcn.io/rx-tbl";
34

45
type AsUrls<T> = {

js/packages/direct-connect-browser/src/worker/DB.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import initWasm from "@vlcn.io/crsqlite-wasm";
22
import { DBAsync, StmtAsync } from "@vlcn.io/xplat-api";
33
import { TXAsync } from "@vlcn.io/xplat-api";
4-
import { DBID } from "../Types.js";
4+
import { DBID } from "@vlcn.io/xplat-api";
55
import {
66
SCHEMA_NAME,
77
SCHEMA_VERSION,

js/packages/direct-connect-browser/src/worker/Fetcher.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { DBID, Endpoints } from "../Types.js";
1+
import { Endpoints } from "../Types.js";
2+
import { DBID } from "@vlcn.io/xplat-api";
23
import {
34
ApplyChangesMsg,
45
ApplyChangesResponse,

js/packages/direct-connect-browser/src/worker/SyncedDB.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ISerializer, hexToBytes, tags } from "@vlcn.io/direct-connect-common";
2-
import { DBID, Endpoints } from "../Types.js";
2+
import { Endpoints } from "../Types.js";
3+
import { DBID } from "@vlcn.io/xplat-api";
34
import createDb, { DB } from "./DB.js";
45
import InboundStream from "./InboundStream.js";
56
import OutboundStream from "./OutboundStream.js";

0 commit comments

Comments
 (0)