Skip to content

Commit 58644fe

Browse files
committed
make index size reporting tests check all index kinds and uniqueness
1 parent 62357f2 commit 58644fe

File tree

3 files changed

+65
-32
lines changed

3 files changed

+65
-32
lines changed

crates/datastore/src/locking_tx_datastore/committed_state.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,8 @@ impl CommittedState {
888888

889889
let index = table.new_index(&algo, is_unique)?;
890890
// SAFETY: `index` was derived from `table`.
891-
unsafe { table.insert_index(blob_store, index_id, index) };
891+
unsafe { table.insert_index(blob_store, index_id, index) }
892+
.expect("rebuilding should not cause constraint violations");
892893
index_id_map.insert(index_id, table_id);
893894
}
894895
Ok(())

crates/table/benches/page_manager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ fn make_table_with_index<R: IndexedRow>(unique: bool) -> (Table, IndexId) {
763763
let algo = BTreeAlgorithm { columns: cols }.into();
764764
let idx = tbl.new_index(&algo, unique).unwrap();
765765
// SAFETY: index was derived from the table.
766-
unsafe { tbl.insert_index(&NullBlobStore, index_id, idx) };
766+
unsafe { tbl.insert_index(&NullBlobStore, index_id, idx) }.unwrap();
767767

768768
(tbl, index_id)
769769
}

crates/table/src/table.rs

Lines changed: 62 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,36 +1413,57 @@ impl Table {
14131413
/// # Safety
14141414
///
14151415
/// Caller must promise that `index` was constructed with the same row type/layout as this table.
1416-
pub unsafe fn insert_index(&mut self, blob_store: &dyn BlobStore, index_id: IndexId, mut index: TableIndex) {
1416+
pub unsafe fn insert_index(
1417+
&mut self,
1418+
blob_store: &dyn BlobStore,
1419+
index_id: IndexId,
1420+
mut index: TableIndex,
1421+
) -> Result<(), String> {
14171422
let rows = self.scan_rows(blob_store);
14181423
// SAFETY: Caller promised that table's row type/layout
14191424
// matches that which `index` was constructed with.
14201425
// It follows that this applies to any `rows`, as required.
14211426
let violation = unsafe { index.build_from_rows(rows) };
1422-
violation.unwrap_or_else(|ptr| {
1423-
let index_schema = &self.schema.indexes.iter().find(|index_schema| index_schema.index_id == index_id).expect("Index should exist");
1424-
let indexed_column = if let IndexAlgorithm::BTree(BTreeAlgorithm { columns }) = &index_schema.index_algorithm {
1425-
Some(columns)
1426-
} else { None };
1427-
let indexed_column = indexed_column.and_then(|columns| columns.as_singleton());
1428-
let indexed_column_info = indexed_column.and_then(|column| self.schema.get_column(column.idx()));
1427+
violation.map_err(|ptr| {
14291428
// SAFETY: `ptr` just came out of `self.scan_rows`, so it is present.
14301429
let row = unsafe { self.get_row_ref_unchecked(blob_store, ptr) }.to_product_value();
1431-
panic!(
1432-
"Adding index `{}` {:?} to table `{}` {:?} on column `{}` {:?} should cause no unique constraint violations.
1433-
1434-
Found violation at pointer {ptr:?} to row {:?}.",
1435-
index_schema.index_name,
1436-
index_schema.index_id,
1437-
self.schema.table_name,
1438-
self.schema.table_id,
1439-
indexed_column_info.map(|column| &column.col_name[..]).unwrap_or("unknown column"),
1440-
indexed_column,
1441-
row,
1442-
);
1443-
});
1430+
1431+
if let Some(index_schema) = self.schema.indexes.iter().find(|index_schema| index_schema.index_id == index_id) {
1432+
let indexed_column = if let IndexAlgorithm::BTree(BTreeAlgorithm { columns }) = &index_schema.index_algorithm {
1433+
Some(columns)
1434+
} else {
1435+
None
1436+
};
1437+
let indexed_column = indexed_column.and_then(|columns| columns.as_singleton());
1438+
let indexed_column_info = indexed_column.and_then(|column| self.schema.get_column(column.idx()));
1439+
1440+
format!(
1441+
"Adding index `{}` {:?} to table `{}` {:?} on column `{}` {:?} should cause no unique constraint violations.\
1442+
Found violation at pointer {ptr:?} to row {:?}.",
1443+
index_schema.index_name,
1444+
index_schema.index_id,
1445+
self.schema.table_name,
1446+
self.schema.table_id,
1447+
indexed_column_info.map(|column| &column.col_name[..]).unwrap_or("unknown column"),
1448+
indexed_column,
1449+
row,
1450+
)
1451+
} else {
1452+
format!(
1453+
"Adding index to table `{}` {:?} on columns `{:?}` with key type {:?} should cause no unique constraint violations.\
1454+
Found violation at pointer {ptr:?} to row {:?}.",
1455+
self.schema.table_name,
1456+
self.schema.table_id,
1457+
index.indexed_columns,
1458+
index.key_type,
1459+
row,
1460+
)
1461+
}
1462+
})?;
1463+
14441464
// SAFETY: Forward caller requirement.
14451465
unsafe { self.add_index(index_id, index) };
1466+
Ok(())
14461467
}
14471468

14481469
/// Adds an index to the table without populating.
@@ -2453,7 +2474,7 @@ pub(crate) mod test {
24532474

24542475
let index = table.new_index(&algo, true).unwrap();
24552476
// SAFETY: Index was derived from `table`.
2456-
unsafe { table.insert_index(&NullBlobStore, index_schema.index_id, index) };
2477+
unsafe { table.insert_index(&NullBlobStore, index_schema.index_id, index) }.unwrap();
24572478

24582479
// Reserve a page so that we can check the hash.
24592480
let pi = table.inner.pages.reserve_empty_page(&pool, table.row_size()).unwrap();
@@ -2553,6 +2574,8 @@ pub(crate) mod test {
25532574
ty: ProductType,
25542575
vals: Vec<ProductValue>,
25552576
indexed_columns: ColList,
2577+
index_kind: IndexKind,
2578+
is_unique: bool,
25562579
) -> Result<(), TestCaseError> {
25572580
let pool = PagePool::new_for_test();
25582581
let mut blob_store = HashMapBlobStore::default();
@@ -2565,13 +2588,13 @@ pub(crate) mod test {
25652588
// We haven't added any indexes yet, so there should be 0 rows in indexes.
25662589
prop_assert_eq!(table.num_rows_in_indexes(), 0);
25672590

2568-
let index_id = IndexId(0);
2591+
let index_id = IndexId::SENTINEL;
25692592

2570-
let index = TableIndex::new(&ty, indexed_columns.clone(), IndexKind::BTree, false).unwrap();
2593+
let index = TableIndex::new(&ty, indexed_columns.clone(), index_kind, is_unique).unwrap();
25712594
// Add an index on column 0.
25722595
// Safety:
25732596
// We're using `ty` as the row type for both `table` and the new index.
2574-
unsafe { table.insert_index(&blob_store, index_id, index) };
2597+
prop_assume!(unsafe { table.insert_index(&blob_store, index_id, index) }.is_ok());
25752598

25762599
// We have one index, which should be fully populated,
25772600
// so in total we should have the same number of rows in indexes as we have rows.
@@ -2602,7 +2625,8 @@ pub(crate) mod test {
26022625
// Add a duplicate of the same index, so we can check that all above quantities double.
26032626
// Safety:
26042627
// As above, we're using `ty` as the row type for both `table` and the new index.
2605-
unsafe { table.insert_index(&blob_store, IndexId(1), index) };
2628+
unsafe { table.insert_index(&blob_store, IndexId(1), index) }
2629+
.expect("already inserted this index, should not error");
26062630

26072631
prop_assert_eq!(table.num_rows_in_indexes(), table.num_rows() * 2);
26082632
prop_assert_eq!(table.bytes_used_by_index_keys(), key_size_in_pvs * 2);
@@ -2722,13 +2746,21 @@ pub(crate) mod test {
27222746
}
27232747

27242748
#[test]
2725-
fn index_size_reporting_matches_slow_implementations_single_column((ty, vals) in generate_typed_row_vec(1..SIZE, 128, 2048)) {
2726-
test_index_size_reporting(ty, vals, [0].into())?;
2749+
fn index_size_reporting_matches_slow_implementations_single_column(
2750+
(ty, vals) in generate_typed_row_vec(1..SIZE, 128, 2048),
2751+
index_kind: IndexKind,
2752+
is_unique: bool
2753+
) {
2754+
test_index_size_reporting(ty, vals, [0].into(), index_kind, is_unique)?;
27272755
}
27282756

27292757
#[test]
2730-
fn index_size_reporting_matches_slow_implementations_two_column((ty, vals) in generate_typed_row_vec(2..SIZE, 128, 2048)) {
2731-
test_index_size_reporting(ty, vals, [0, 1].into())?
2758+
fn index_size_reporting_matches_slow_implementations_two_column(
2759+
(ty, vals) in generate_typed_row_vec(2..SIZE, 128, 2048),
2760+
index_kind: IndexKind,
2761+
is_unique: bool
2762+
) {
2763+
test_index_size_reporting(ty, vals, [0, 1].into(), index_kind, is_unique)?
27322764
}
27332765
}
27342766

0 commit comments

Comments
 (0)