@@ -45,6 +45,79 @@ void main() {
4545 greaterThan (versionAfter2['schema_version' ] as int ));
4646 });
4747
48+ group ('migrate tables' , () {
49+ final local = {
50+ "tables" : [
51+ {
52+ "name" : "users" ,
53+ "local_only" : true ,
54+ "insert_only" : false ,
55+ "columns" : [
56+ {"name" : "name" , "type" : "TEXT" },
57+ ],
58+ },
59+ ]
60+ };
61+
62+ final synced = {
63+ "tables" : [
64+ {
65+ "name" : "users" ,
66+ "local_only" : false ,
67+ "insert_only" : false ,
68+ "columns" : [
69+ {"name" : "name" , "type" : "TEXT" },
70+ ],
71+ },
72+ ]
73+ };
74+
75+ test ('from synced to local' , () {
76+ // Start with synced table, and sync row
77+ db.execute ('SELECT powersync_replace_schema(?)' , [json.encode (synced)]);
78+ db.execute (
79+ 'INSERT INTO ps_data__users (id, data) VALUES (?, ?)' ,
80+ [
81+ 'synced-id' ,
82+ json.encode ({'name' : 'name' })
83+ ],
84+ );
85+
86+ // Migrate to local table.
87+ db.execute ('SELECT powersync_replace_schema(?)' , [json.encode (local)]);
88+
89+ // The synced table should not exist anymore.
90+ expect (() => db.select ('SELECT * FROM ps_data__users' ),
91+ throwsA (isA <SqliteException >()));
92+
93+ // Data should still be there.
94+ expect (db.select ('SELECT * FROM users' ), [
95+ {'id' : 'synced-id' , 'name' : 'name' }
96+ ]);
97+
98+ // Inserting into local-only table should not record CRUD item.
99+ db.execute (
100+ 'INSERT INTO users (id, name) VALUES (uuid(), ?)' , ['local' ]);
101+ expect (db.select ('SELECT * FROM ps_crud' ), isEmpty);
102+ });
103+
104+ test ('from local to synced' , () {
105+ // Start with local table, and local row
106+ db.execute ('SELECT powersync_replace_schema(?)' , [json.encode (local)]);
107+ db.execute (
108+ 'INSERT INTO users (id, name) VALUES (uuid(), ?)' , ['local' ]);
109+
110+ // Migrate to synced table. Because the previous local write would never
111+ // get uploaded, this clears local data.
112+ db.execute ('SELECT powersync_replace_schema(?)' , [json.encode (synced)]);
113+ expect (db.select ('SELECT * FROM users' ), isEmpty);
114+
115+ // The local table should not exist anymore.
116+ expect (() => db.select ('SELECT * FROM ps_data_local__users' ),
117+ throwsA (isA <SqliteException >()));
118+ });
119+ });
120+
48121 group ('metadata' , () {
49122 // This is a special because we have two delete triggers when
50123 // include_metadata is true (one for actual `DELETE` statements and one
0 commit comments