Skip to content

Commit 6f5e33a

Browse files
authored
update_database: is_unique should only use the table's constraints (#2915)
1 parent 06ba529 commit 6f5e33a

File tree

8 files changed

+212
-100
lines changed

8 files changed

+212
-100
lines changed

crates/core/src/db/datastore/locking_tx_datastore/datastore.rs

Lines changed: 36 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,13 +1857,13 @@ mod tests {
18571857
let mut tx = begin_mut_tx(&datastore);
18581858
let schema = datastore.schema_for_table_mut_tx(&tx, table_id)?;
18591859

1860-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
1860+
assert_eq!(tx.pending_schema_changes(), []);
18611861
let mut dropped_indexes = 0;
18621862
for (pos, index) in schema.indexes.iter().enumerate() {
18631863
datastore.drop_index_mut_tx(&mut tx, index.index_id)?;
18641864
dropped_indexes += 1;
18651865

1866-
let psc = &tx.tx_state.pending_schema_changes[pos];
1866+
let psc = &tx.pending_schema_changes()[pos];
18671867
let PendingSchemaChange::IndexRemoved(tid, iid, _, schema) = psc else {
18681868
panic!("wrong pending schema change: {psc:?}");
18691869
};
@@ -1878,7 +1878,7 @@ mod tests {
18781878
datastore.commit_mut_tx(tx)?;
18791879

18801880
let mut tx = begin_mut_tx(&datastore);
1881-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
1881+
assert_eq!(tx.pending_schema_changes(), []);
18821882
assert!(
18831883
datastore.schema_for_table_mut_tx(&tx, table_id)?.indexes.is_empty(),
18841884
"no indexes should be left in the schema post-commit"
@@ -1897,7 +1897,7 @@ mod tests {
18971897
true,
18981898
)?;
18991899
assert_matches!(
1900-
&*tx.tx_state.pending_schema_changes,
1900+
tx.pending_schema_changes(),
19011901
[PendingSchemaChange::IndexAdded(tid, _, Some(_))]
19021902
if *tid == table_id
19031903
);
@@ -1920,7 +1920,7 @@ mod tests {
19201920
datastore.commit_mut_tx(tx)?;
19211921

19221922
let tx = begin_mut_tx(&datastore);
1923-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
1923+
assert_eq!(tx.pending_schema_changes(), []);
19241924
assert_eq!(
19251925
datastore.schema_for_table_mut_tx(&tx, table_id)?.indexes,
19261926
expected_indexes,
@@ -1935,10 +1935,10 @@ mod tests {
19351935
#[test]
19361936
fn test_schema_for_table_rollback() -> ResultTest<()> {
19371937
let (datastore, tx, table_id) = setup_table()?;
1938-
assert_eq!(tx.tx_state.pending_schema_changes.len(), 6);
1938+
assert_eq!(tx.pending_schema_changes().len(), 6);
19391939
let _ = datastore.rollback_mut_tx(tx);
19401940
let tx = begin_mut_tx(&datastore);
1941-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
1941+
assert_eq!(tx.pending_schema_changes(), []);
19421942
let schema = datastore.schema_for_table_mut_tx(&tx, table_id);
19431943
assert!(schema.is_err());
19441944
Ok(())
@@ -2165,12 +2165,9 @@ mod tests {
21652165
commit(&datastore, tx)?;
21662166

21672167
let mut tx = begin_mut_tx(&datastore);
2168-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
2168+
assert_eq!(tx.pending_schema_changes(), []);
21692169
create_foo_age_idx_btree(&datastore, &mut tx, table_id)?;
2170-
assert_matches!(
2171-
&*tx.tx_state.pending_schema_changes,
2172-
[PendingSchemaChange::IndexAdded(.., None)]
2173-
);
2170+
assert_matches!(tx.pending_schema_changes(), [PendingSchemaChange::IndexAdded(.., None)]);
21742171
assert_st_indices(&tx, true)?;
21752172
let row = u32_str_u32(0, "Bar", 18); // 0 will be ignored.
21762173
let result = insert(&datastore, &mut tx, table_id, &row);
@@ -2195,7 +2192,7 @@ mod tests {
21952192
commit(&datastore, tx)?;
21962193

21972194
let mut tx = begin_mut_tx(&datastore);
2198-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
2195+
assert_eq!(tx.pending_schema_changes(), []);
21992196
assert_st_indices(&tx, true)?;
22002197
let row = u32_str_u32(0, "Bar", 18); // 0 will be ignored.
22012198
let result = insert(&datastore, &mut tx, table_id, &row);
@@ -2235,16 +2232,13 @@ mod tests {
22352232
// Start a transaction. Schema changes empty so far.
22362233
let datastore = get_datastore()?;
22372234
let mut tx = begin_mut_tx(&datastore);
2238-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
2235+
assert_eq!(tx.pending_schema_changes(), []);
22392236

22402237
// Make the table and witness `TableAdded`. Commit.
22412238
let column = ColumnSchema::for_test(0, "id", AlgebraicType::I32);
22422239
let schema = user_public_table([column], [], [], [], None, None);
22432240
let table_id = datastore.create_table_mut_tx(&mut tx, schema)?;
2244-
assert_matches!(
2245-
&*tx.tx_state.pending_schema_changes,
2246-
[PendingSchemaChange::TableAdded(..)]
2247-
);
2241+
assert_matches!(tx.pending_schema_changes(), [PendingSchemaChange::TableAdded(..)]);
22482242
commit(&datastore, tx)?;
22492243

22502244
// Start a new tx. Insert a row and witness that a sequence isn't used.
@@ -2274,7 +2268,7 @@ mod tests {
22742268
};
22752269
let seq_id = datastore.create_sequence_mut_tx(&mut tx, sequence.clone())?;
22762270
assert_matches!(
2277-
&*tx.tx_state.pending_schema_changes,
2271+
tx.pending_schema_changes(),
22782272
[PendingSchemaChange::SequenceAdded(_, added_seq_id)]
22792273
if *added_seq_id == seq_id
22802274
);
@@ -2283,7 +2277,7 @@ mod tests {
22832277
// Drop the uncommitted sequence.
22842278
datastore.drop_sequence_mut_tx(&mut tx, seq_id)?;
22852279
assert_matches!(
2286-
&*tx.tx_state.pending_schema_changes,
2280+
tx.pending_schema_changes(),
22872281
[
22882282
PendingSchemaChange::SequenceAdded(..),
22892283
PendingSchemaChange::SequenceRemoved(.., schema),
@@ -2295,7 +2289,7 @@ mod tests {
22952289
// Add the sequence again and rollback, witnessing that this had no effect in the next tx.
22962290
let seq_id = datastore.create_sequence_mut_tx(&mut tx, sequence.clone())?;
22972291
assert_matches!(
2298-
&*tx.tx_state.pending_schema_changes,
2292+
tx.pending_schema_changes(),
22992293
[
23002294
PendingSchemaChange::SequenceAdded(..),
23012295
PendingSchemaChange::SequenceRemoved(..),
@@ -2305,45 +2299,39 @@ mod tests {
23052299
);
23062300
let _ = datastore.rollback_mut_tx(tx);
23072301
let mut tx: MutTxId = begin_mut_tx(&datastore);
2308-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
2302+
assert_eq!(tx.pending_schema_changes(), []);
23092303
insert_assert_and_remove(&mut tx, &zero, &zero)?;
23102304

23112305
// Add the sequence and this time actually commit. Check that it exists in next tx.
2312-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
2306+
assert_eq!(tx.pending_schema_changes(), []);
23132307
let seq_id = datastore.create_sequence_mut_tx(&mut tx, sequence.clone())?;
23142308
assert_matches!(
2315-
&*tx.tx_state.pending_schema_changes,
2309+
tx.pending_schema_changes(),
23162310
[PendingSchemaChange::SequenceAdded(_, added_seq_id)]
23172311
if *added_seq_id == seq_id
23182312
);
23192313
commit(&datastore, tx)?;
23202314
let mut tx = begin_mut_tx(&datastore);
2321-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
2315+
assert_eq!(tx.pending_schema_changes(), []);
23222316
insert_assert_and_remove(&mut tx, &zero, &one)?;
23232317

23242318
// We have the sequence in committed state.
23252319
// Drop it and then rollback, so in the next tx the seq is still there.
23262320
datastore.drop_sequence_mut_tx(&mut tx, seq_id)?;
2327-
assert_matches!(
2328-
&*tx.tx_state.pending_schema_changes,
2329-
[PendingSchemaChange::SequenceRemoved(..)]
2330-
);
2321+
assert_matches!(tx.pending_schema_changes(), [PendingSchemaChange::SequenceRemoved(..)]);
23312322
insert_assert_and_remove(&mut tx, &zero, &zero)?;
23322323
let _ = datastore.rollback_mut_tx(tx);
23332324
let mut tx = begin_mut_tx(&datastore);
2334-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
2325+
assert_eq!(tx.pending_schema_changes(), []);
23352326
insert_assert_and_remove(&mut tx, &zero, &product![2])?;
23362327

23372328
// Drop the seq and commit this time around. In the next tx, we witness that there's no seq.
23382329
datastore.drop_sequence_mut_tx(&mut tx, seq_id)?;
2339-
assert_matches!(
2340-
&*tx.tx_state.pending_schema_changes,
2341-
[PendingSchemaChange::SequenceRemoved(..)]
2342-
);
2330+
assert_matches!(tx.pending_schema_changes(), [PendingSchemaChange::SequenceRemoved(..)]);
23432331
insert_assert_and_remove(&mut tx, &zero, &zero)?;
23442332
commit(&datastore, tx)?;
23452333
let mut tx = begin_mut_tx(&datastore);
2346-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
2334+
assert_eq!(tx.pending_schema_changes(), []);
23472335
insert_assert_and_remove(&mut tx, &zero, &zero)?;
23482336

23492337
Ok(())
@@ -2570,16 +2558,16 @@ mod tests {
25702558
fn test_update_no_such_index_because_deleted() -> ResultTest<()> {
25712559
// Setup and immediately commit.
25722560
let (datastore, tx, table_id) = setup_table()?;
2573-
assert_eq!(tx.tx_state.pending_schema_changes.len(), 6);
2561+
assert_eq!(tx.pending_schema_changes().len(), 6);
25742562
commit(&datastore, tx)?;
25752563

25762564
// Remove index in tx state.
25772565
let mut tx = begin_mut_tx(&datastore);
2578-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
2566+
assert_eq!(tx.pending_schema_changes(), []);
25792567
let index_id = extract_index_id(&datastore, &tx, &basic_indices()[0])?;
25802568
tx.drop_index(index_id)?;
25812569
assert_matches!(
2582-
&*tx.tx_state.pending_schema_changes,
2570+
tx.pending_schema_changes(),
25832571
[PendingSchemaChange::IndexRemoved(tid, iid, _, _)]
25842572
if *tid == table_id && *iid == index_id
25852573
);
@@ -2654,7 +2642,7 @@ mod tests {
26542642
fn test_update_no_such_row_because_deleted_new_index_in_tx() -> ResultTest<()> {
26552643
let (datastore, mut tx, table_id) = setup_table_with_indices([], [])?;
26562644
assert_matches!(
2657-
&*tx.tx_state.pending_schema_changes,
2645+
tx.pending_schema_changes(),
26582646
[
26592647
PendingSchemaChange::TableAdded(_),
26602648
PendingSchemaChange::SequenceAdded(..),
@@ -2668,13 +2656,13 @@ mod tests {
26682656

26692657
// Now add the indices and then delete the row.
26702658
let mut tx = begin_mut_tx(&datastore);
2671-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
2659+
assert_eq!(tx.pending_schema_changes(), []);
26722660
let mut indices = basic_indices();
26732661
for (pos, index) in indices.iter_mut().enumerate() {
26742662
index.table_id = table_id;
26752663
index.index_id = datastore.create_index_mut_tx(&mut tx, index.clone(), true)?;
26762664
assert_matches!(
2677-
&tx.tx_state.pending_schema_changes[pos],
2665+
&tx.pending_schema_changes()[pos],
26782666
PendingSchemaChange::IndexAdded(_, iid, _)
26792667
if *iid == index.index_id
26802668
);
@@ -3087,10 +3075,10 @@ mod tests {
30873075

30883076
// Create a transaction and drop the table and roll back.
30893077
let mut tx = begin_mut_tx(&datastore);
3090-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
3078+
assert_eq!(tx.pending_schema_changes(), []);
30913079
assert!(datastore.drop_table_mut_tx(&mut tx, table_id).is_ok());
30923080
assert_matches!(
3093-
&*tx.tx_state.pending_schema_changes,
3081+
tx.pending_schema_changes(),
30943082
[
30953083
PendingSchemaChange::IndexRemoved(..),
30963084
PendingSchemaChange::IndexRemoved(..),
@@ -3105,7 +3093,7 @@ mod tests {
31053093

31063094
// Ensure the table still exists in the next transaction.
31073095
let tx = begin_mut_tx(&datastore);
3108-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
3096+
assert_eq!(tx.pending_schema_changes(), []);
31093097
assert!(
31103098
datastore.table_id_exists_mut_tx(&tx, &table_id),
31113099
"Table should still exist",
@@ -3120,7 +3108,7 @@ mod tests {
31203108
// Create a table in a failed transaction.
31213109
let (datastore, tx, table_id) = setup_table()?;
31223110
assert_matches!(
3123-
&*tx.tx_state.pending_schema_changes,
3111+
tx.pending_schema_changes(),
31243112
[
31253113
PendingSchemaChange::TableAdded(added_table_id),
31263114
PendingSchemaChange::IndexAdded(.., Some(_)),
@@ -3135,7 +3123,7 @@ mod tests {
31353123

31363124
// Nothing should have happened.
31373125
let tx = begin_mut_tx(&datastore);
3138-
assert_eq!(&*tx.tx_state.pending_schema_changes, []);
3126+
assert_eq!(tx.pending_schema_changes(), []);
31393127
assert!(
31403128
!datastore.table_id_exists_mut_tx(&tx, &table_id),
31413129
"Table should not exist"
@@ -3156,7 +3144,7 @@ mod tests {
31563144
assert_access(&tx, StAccess::Public);
31573145
tx.alter_table_access(table_id, StAccess::Private)?;
31583146
assert_eq!(
3159-
&*tx.tx_state.pending_schema_changes,
3147+
tx.pending_schema_changes(),
31603148
[PendingSchemaChange::TableAlterAccess(table_id, StAccess::Public)]
31613149
);
31623150
let _ = datastore.rollback_mut_tx(tx);
@@ -3260,7 +3248,7 @@ mod tests {
32603248
let mut tx = begin_mut_tx(&datastore);
32613249
datastore.alter_table_row_type_mut_tx(&mut tx, table_id, columns.clone())?;
32623250
assert_eq!(
3263-
&*tx.tx_state.pending_schema_changes,
3251+
tx.pending_schema_changes(),
32643252
[PendingSchemaChange::TableAlterRowType(
32653253
table_id,
32663254
columns_original.clone()

crates/core/src/db/datastore/locking_tx_datastore/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ pub use state_view::{IterByColEqTx, IterByColRangeTx};
1010
pub mod delete_table;
1111
pub(crate) mod tx;
1212
mod tx_state;
13+
#[cfg(test)]
14+
pub(crate) use tx_state::PendingSchemaChange;
1315

1416
use parking_lot::{
1517
lock_api::{ArcMutexGuard, ArcRwLockReadGuard, ArcRwLockWriteGuard},

crates/core/src/db/datastore/locking_tx_datastore/mut_tx.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ impl MutTxId {
150150
self.tx_state.pending_schema_changes.push(change);
151151
}
152152

153+
/// Get the list of current pending schema changes, for testing.
154+
#[cfg(test)]
155+
pub(crate) fn pending_schema_changes(&self) -> &[PendingSchemaChange] {
156+
&self.tx_state.pending_schema_changes
157+
}
158+
153159
/// Deletes all the rows in table with `table_id`
154160
/// where the column with `col_pos` equals `value`.
155161
fn delete_col_eq(&mut self, table_id: TableId, col_pos: ColId, value: &AlgebraicValue) -> Result<()> {

crates/core/src/db/datastore/locking_tx_datastore/sequence.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use spacetimedb_sats::memory_usage::MemoryUsage;
44
use spacetimedb_schema::schema::SequenceSchema;
55

66
#[derive(Debug, PartialEq)]
7-
pub(super) struct Sequence {
7+
pub(crate) struct Sequence {
88
schema: SequenceSchema,
99
pub(super) value: i128,
1010
}

crates/core/src/db/datastore/locking_tx_datastore/tx_state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ pub(super) struct TxState {
8787
/// Architecting this way should benefit performance both during transactions and merge.
8888
/// On rollback, it should be fairly cheap to e.g., just re-add an index or drop it on the floor.
8989
#[derive(Debug, PartialEq)]
90-
pub(super) enum PendingSchemaChange {
90+
pub(crate) enum PendingSchemaChange {
9191
/// The [`TableIndex`] / [`IndexSchema`] with `IndexId`
9292
/// was removed from the table with [`TableId`].
9393
IndexRemoved(TableId, IndexId, TableIndex, IndexSchema),

0 commit comments

Comments
 (0)