@@ -44,6 +44,7 @@ use spacetimedb_table::{
44
44
} ;
45
45
use std:: collections:: BTreeMap ;
46
46
use std:: sync:: Arc ;
47
+ use thin_vec:: ThinVec ;
47
48
48
49
/// Contains the live, in-memory snapshot of a database. This structure
49
50
/// is exposed in order to support tools wanting to process the commit
@@ -593,12 +594,23 @@ impl CommittedState {
593
594
pub ( super ) fn merge ( & mut self , tx_state : TxState , ctx : & ExecutionContext ) -> TxData {
594
595
let mut tx_data = TxData :: default ( ) ;
595
596
597
+ // This transaction may have dropped tables.
598
+ // After applying `merge_apply_deletes` and `merge_apply_inserts`,
599
+ // any tables no longer referenced by `st_table` should be
600
+ // removed from the committed state.
601
+ let mut tables_to_drop = thin_vec:: ThinVec :: < TableId > :: new ( ) ;
602
+
596
603
// First, apply deletes. This will free up space in the committed tables.
597
- self . merge_apply_deletes ( & mut tx_data, tx_state. delete_tables ) ;
604
+ self . merge_apply_deletes ( & mut tx_data, & mut tables_to_drop , tx_state. delete_tables ) ;
598
605
599
606
// Then, apply inserts. This will re-fill the holes freed by deletions
600
607
// before allocating new pages.
601
- self . merge_apply_inserts ( & mut tx_data, tx_state. insert_tables , tx_state. blob_store ) ;
608
+ self . merge_apply_inserts (
609
+ & mut tx_data,
610
+ & mut tables_to_drop,
611
+ tx_state. insert_tables ,
612
+ tx_state. blob_store ,
613
+ ) ;
602
614
603
615
// If the TX will be logged, record its projected tx offset,
604
616
// then increment the counter.
@@ -607,10 +619,19 @@ impl CommittedState {
607
619
self . next_tx_offset += 1 ;
608
620
}
609
621
622
+ for table_id in tables_to_drop {
623
+ self . tables . remove ( & table_id) ;
624
+ }
625
+
610
626
tx_data
611
627
}
612
628
613
- fn merge_apply_deletes ( & mut self , tx_data : & mut TxData , delete_tables : BTreeMap < TableId , DeleteTable > ) {
629
+ fn merge_apply_deletes (
630
+ & mut self ,
631
+ tx_data : & mut TxData ,
632
+ dropped_table_ids : & mut ThinVec < TableId > ,
633
+ delete_tables : BTreeMap < TableId , DeleteTable > ,
634
+ ) {
614
635
for ( table_id, row_ptrs) in delete_tables {
615
636
if let ( Some ( table) , blob_store, _) = self . get_table_and_blob_store_mut ( table_id) {
616
637
let mut deletes = Vec :: with_capacity ( row_ptrs. len ( ) ) ;
@@ -626,6 +647,14 @@ impl CommittedState {
626
647
let pv = table
627
648
. delete ( blob_store, row_ptr, |row| row. to_product_value ( ) )
628
649
. expect ( "Delete for non-existent row!" ) ;
650
+
651
+ if table_id == ST_TABLE_ID {
652
+ let st_table_row =
653
+ StTableRow :: deserialize ( ValueDeserializer :: from_ref ( & AlgebraicValue :: Product ( pv. clone ( ) ) ) )
654
+ . expect ( "st_table row should deserialize" ) ;
655
+ dropped_table_ids. push ( st_table_row. table_id ) ;
656
+ }
657
+
629
658
deletes. push ( pv) ;
630
659
}
631
660
@@ -642,6 +671,7 @@ impl CommittedState {
642
671
fn merge_apply_inserts (
643
672
& mut self ,
644
673
tx_data : & mut TxData ,
674
+ dropped_table_ids : & mut ThinVec < TableId > ,
645
675
insert_tables : BTreeMap < TableId , Table > ,
646
676
tx_blob_store : impl BlobStore ,
647
677
) {
@@ -665,6 +695,15 @@ impl CommittedState {
665
695
. insert ( page_pool, commit_blob_store, & pv)
666
696
. expect ( "Failed to insert when merging commit" ) ;
667
697
698
+ // If we inserted a row back into `st_table`,
699
+ // it means transaction only updates a row and do not drop the table.
700
+ if table_id == ST_TABLE_ID {
701
+ let st_table_row =
702
+ StTableRow :: deserialize ( ValueDeserializer :: from_ref ( & AlgebraicValue :: Product ( pv. clone ( ) ) ) )
703
+ . expect ( "st_table row should deserialize" ) ;
704
+ dropped_table_ids. retain ( |& id| id != st_table_row. table_id ) ;
705
+ }
706
+
668
707
inserts. push ( pv) ;
669
708
}
670
709
@@ -717,13 +756,6 @@ impl CommittedState {
717
756
table. with_mut_schema ( |s| s. remove_index ( index_id) ) ;
718
757
self . index_id_map . remove ( & index_id) ;
719
758
}
720
- // A table was removed. Add it back.
721
- TableRemoved ( table_id, table) => {
722
- // We don't need to deal with sub-components.
723
- // That is, we don't need to add back indices and such.
724
- // Instead, there will be separate pending schema changes like `IndexRemoved`.
725
- self . tables . insert ( table_id, table) ;
726
- }
727
759
// A table was added. Remove it.
728
760
TableAdded ( table_id) => {
729
761
// We don't need to deal with sub-components.
0 commit comments