@@ -55,7 +55,7 @@ enum CrudTransactionMode {
5555 Simple {
5656 stmt : ManagedStmt ,
5757 set_updated_rows : ManagedStmt ,
58- update_local_bucket : ManagedStmt ,
58+ had_writes : bool ,
5959 } ,
6060}
6161
@@ -73,13 +73,13 @@ impl VirtualTable {
7373 }
7474 }
7575
76- fn handle_insert ( & self , args : & [ * mut sqlite:: value ] ) -> Result < ( ) , SQLiteError > {
76+ fn handle_insert ( & mut self , args : & [ * mut sqlite:: value ] ) -> Result < ( ) , SQLiteError > {
7777 let current_tx = self
7878 . current_tx
79- . as_ref ( )
79+ . as_mut ( )
8080 . ok_or_else ( || SQLiteError ( ResultCode :: MISUSE , Some ( String :: from ( "No tx_id" ) ) ) ) ?;
8181
82- match & current_tx. mode {
82+ match & mut current_tx. mode {
8383 CrudTransactionMode :: Manual { stmt } => {
8484 // Columns are (data TEXT, options INT HIDDEN)
8585 let data = args[ 0 ] . text ( ) ;
@@ -96,7 +96,7 @@ impl VirtualTable {
9696 CrudTransactionMode :: Simple {
9797 stmt,
9898 set_updated_rows,
99- update_local_bucket ,
99+ had_writes ,
100100 } => {
101101 // Columns are (op TEXT, id TEXT, type TEXT, data TEXT, old_values TEXT, metadata TEXT, options INT HIDDEN)
102102 let flags = match args[ 6 ] . value_type ( ) {
@@ -154,7 +154,7 @@ impl VirtualTable {
154154 set_updated_rows. bind_text ( 1 , row_type, sqlite:: Destructor :: STATIC ) ?;
155155 set_updated_rows. bind_text ( 2 , id, sqlite:: Destructor :: STATIC ) ?;
156156 set_updated_rows. exec ( ) ?;
157- update_local_bucket . exec ( ) ? ;
157+ * had_writes = true ;
158158 }
159159 }
160160
@@ -184,7 +184,7 @@ impl VirtualTable {
184184 "INSERT OR IGNORE INTO ps_updated_rows(row_type, row_id) VALUES(?, ?)" ,
185185 0 ,
186186 ) ?,
187- update_local_bucket : db . prepare_v3 ( formatcp ! ( "INSERT OR REPLACE INTO ps_buckets(name, last_op, target_op) VALUES('$local', 0, {MAX_OP_ID})" ) , 0 ) ? ,
187+ had_writes : false ,
188188 }
189189 } else {
190190 const SQL : & str = formatcp ! (
@@ -206,7 +206,30 @@ SELECT * FROM insertion WHERE (NOT (?3 & {})) OR data->>'op' != 'PATCH' OR data-
206206 Ok ( ( ) )
207207 }
208208
209- fn end_transaction ( & mut self ) {
209+ fn end_transaction ( & mut self ) -> Result < ( ) , SQLiteError > {
210+ let tx = self . current_tx . take ( ) ;
211+ if let Some ( tx) = tx {
212+ let needs_local_bucket_update = match tx. mode {
213+ CrudTransactionMode :: Manual { .. } => {
214+ // In manual mode, users need to update the $local bucket themselves.
215+ false
216+ }
217+ CrudTransactionMode :: Simple {
218+ had_writes,
219+ stmt : _,
220+ set_updated_rows : _,
221+ } => had_writes,
222+ } ;
223+
224+ if needs_local_bucket_update {
225+ self . db . exec_safe ( formatcp ! ( "INSERT OR REPLACE INTO ps_buckets(name, last_op, target_op) VALUES('$local', 0, {MAX_OP_ID})" ) ) ?;
226+ }
227+ }
228+
229+ Ok ( ( ) )
230+ }
231+
232+ fn clear_transaction_state ( & mut self ) {
210233 self . current_tx = None ;
211234 }
212235}
@@ -269,13 +292,12 @@ extern "C" fn begin(vtab: *mut sqlite::vtab) -> c_int {
269292
270293extern "C" fn commit ( vtab : * mut sqlite:: vtab ) -> c_int {
271294 let tab = unsafe { & mut * ( vtab. cast :: < VirtualTable > ( ) ) } ;
272- tab. end_transaction ( ) ;
273- ResultCode :: OK as c_int
295+ vtab_result ( vtab, tab. end_transaction ( ) )
274296}
275297
276298extern "C" fn rollback ( vtab : * mut sqlite:: vtab ) -> c_int {
277299 let tab = unsafe { & mut * ( vtab. cast :: < VirtualTable > ( ) ) } ;
278- tab. end_transaction ( ) ;
300+ tab. clear_transaction_state ( ) ;
279301 // ps_tx will be rolled back automatically
280302 ResultCode :: OK as c_int
281303}
@@ -295,7 +317,7 @@ extern "C" fn update(
295317 ResultCode :: MISUSE as c_int
296318 } else if rowid. value_type ( ) == sqlite:: ColumnType :: Null {
297319 // INSERT
298- let tab = unsafe { & * ( vtab. cast :: < VirtualTable > ( ) ) } ;
320+ let tab = unsafe { & mut * ( vtab. cast :: < VirtualTable > ( ) ) } ;
299321 let result = tab. handle_insert ( & args[ 2 ..] ) ;
300322 vtab_result ( vtab, result)
301323 } else {
0 commit comments