@@ -388,6 +388,38 @@ impl<Tbl: Table, Col: Index + Column<Table = Tbl>> UniqueColumn<Tbl, Col::ColTyp
388388 let buf = IterBuf :: take ( ) ;
389389 update :: < Tbl > ( Col :: index_id ( ) , new_row, buf)
390390 }
391+
392+ /// Inserts `new_row` into the table, first checking for an existing
393+ /// row with a matching value in the unique column and deleting it if present.
394+ ///
395+ /// Be careful: in case of a constraint violation, this method will return Err,
396+ /// but the previous row will be deleted. If you propagate the error, SpacetimeDB will
397+ /// rollback the transaction and the old row will be restored. If you ignore the error,
398+ /// the old row will be lost.
399+ #[ track_caller]
400+ #[ doc( alias = "try_upsert" ) ]
401+ #[ cfg( feature = "unstable" ) ]
402+ pub fn try_insert_or_update ( & self , new_row : Tbl :: Row ) -> Result < Tbl :: Row , TryInsertError < Tbl > > {
403+ let col_val = Col :: get_field ( & new_row) ;
404+ // If the row doesn't exist, delete will return false, which we ignore.
405+ let _ = self . delete ( col_val) ;
406+
407+ // Then, insert the new row.
408+ let buf = IterBuf :: take ( ) ;
409+ insert :: < Tbl > ( new_row, buf)
410+ }
411+
412+ /// Inserts `new_row` into the table, first checking for an existing
413+ /// row with a matching value in the unique column and deleting it if present.
414+ ///
415+ /// # Panics
416+ /// Panics if either the delete or the insertion would violate a constraint.
417+ #[ track_caller]
418+ #[ doc( alias = "upsert" ) ]
419+ #[ cfg( feature = "unstable" ) ]
420+ pub fn insert_or_update ( & self , new_row : Tbl :: Row ) -> Tbl :: Row {
421+ self . try_insert_or_update ( new_row) . unwrap_or_else ( |e| panic ! ( "{e}" ) )
422+ }
391423}
392424
393425pub trait Index {
0 commit comments