@@ -10,7 +10,7 @@ use powersync_sqlite_nostd as sqlite;
1010use powersync_sqlite_nostd:: { Connection , Context } ;
1111use sqlite:: { ResultCode , Value } ;
1212
13- use crate :: error:: PowerSyncError ;
13+ use crate :: error:: { PSResult , PowerSyncError } ;
1414use crate :: migrations:: { LATEST_VERSION , powersync_migrate} ;
1515use crate :: schema:: inspection:: ExistingView ;
1616use crate :: state:: DatabaseState ;
@@ -75,7 +75,7 @@ fn powersync_clear_impl(
7575 // speed up the next sync.
7676 local_db. exec_safe ( "DELETE FROM ps_oplog; DELETE FROM ps_buckets" ) ?;
7777 } else {
78- local_db . exec_safe ( "UPDATE ps_buckets SET last_applied_op = 0" ) ?;
78+ trigger_resync ( local_db , state ) ?;
7979 local_db. exec_safe ( "DELETE FROM ps_buckets WHERE name = '$local'" ) ?;
8080 }
8181
@@ -86,10 +86,10 @@ DELETE FROM ps_crud;
8686DELETE FROM ps_untyped;
8787DELETE FROM ps_updated_rows;
8888DELETE FROM ps_kv WHERE key != 'client_id';
89- DELETE FROM ps_sync_state;
9089DELETE FROM ps_stream_subscriptions;
9190" ,
9291 ) ?;
92+ clear_has_synced ( local_db) ?;
9393
9494 let table_glob = if flags. clear_local ( ) {
9595 "ps_data_*"
@@ -138,6 +138,52 @@ DELETE FROM {table};",
138138 Ok ( String :: from ( "" ) )
139139}
140140
141+ fn trigger_resync ( db : * mut sqlite:: sqlite3 , state : & DatabaseState ) -> Result < ( ) , PowerSyncError > {
142+ {
143+ let client = state. sync_client . borrow ( ) ;
144+ if let Some ( client) = client. as_ref ( )
145+ && client. has_sync_iteration ( )
146+ {
147+ return Err ( PowerSyncError :: argument_error (
148+ "Cannot clear or trigger resync while a sync iteration is active." ,
149+ ) ) ;
150+ }
151+ }
152+
153+ db. exec_safe ( "UPDATE ps_buckets SET last_applied_op = 0 WHERE name != '$local'" )
154+ . into_db_result ( db) ?;
155+ Ok ( Default :: default ( ) )
156+ }
157+
158+ fn clear_has_synced ( db : * mut sqlite:: sqlite3 ) -> Result < ( ) , PowerSyncError > {
159+ db. exec_safe ( "DELETE FROM ps_sync_state;" ) ?;
160+ db. exec_safe ( "UPDATE ps_stream_subscriptions SET last_synced_at = NULL" ) ?;
161+ Ok ( ( ) )
162+ }
163+
164+ fn powersync_trigger_resync_impl (
165+ ctx : * mut sqlite:: context ,
166+ args : & [ * mut sqlite:: value ] ,
167+ ) -> Result < String , PowerSyncError > {
168+ let local_db = ctx. db_handle ( ) ;
169+ let state = unsafe { DatabaseState :: from_context ( & ctx) } ;
170+ trigger_resync ( local_db, state) ?;
171+
172+ let clear_progress = args[ 0 ] . int ( ) != 0 ;
173+ if clear_progress {
174+ clear_has_synced ( local_db) ?;
175+ }
176+
177+ Ok ( Default :: default ( ) )
178+ }
179+
180+ create_auto_tx_function ! ( powersync_trigger_resync_tx, powersync_trigger_resync_impl) ;
181+ create_sqlite_text_fn ! (
182+ powersync_trigger_resync,
183+ powersync_trigger_resync_tx,
184+ "powersync_trigger_resync"
185+ ) ;
186+
141187#[ derive( Clone , Copy ) ]
142188struct PowerSyncClearFlags ( i32 ) ;
143189
@@ -199,12 +245,23 @@ pub fn register(db: *mut sqlite::sqlite3, state: Rc<DatabaseState>) -> Result<()
199245 "powersync_clear" ,
200246 1 ,
201247 sqlite:: UTF8 ,
202- Some ( Rc :: into_raw ( state) as * mut c_void ) ,
248+ Some ( Rc :: into_raw ( state. clone ( ) ) as * mut c_void ) ,
203249 Some ( powersync_clear) ,
204250 None ,
205251 None ,
206252 Some ( DatabaseState :: destroy_rc) ,
207253 ) ?;
208254
255+ db. create_function_v2 (
256+ "powersync_trigger_resync" ,
257+ 1 ,
258+ sqlite:: UTF8 ,
259+ Some ( Rc :: into_raw ( state) as * mut c_void ) ,
260+ Some ( powersync_trigger_resync) ,
261+ None ,
262+ None ,
263+ Some ( DatabaseState :: destroy_rc) ,
264+ ) ?;
265+
209266 Ok ( ( ) )
210267}
0 commit comments