Fix hash index round-trip through st_indexes (#4336)

## Description of Changes

One-line fix in `system_tables.rs`: when reading indexes back from
`st_index`, `StIndexAlgorithm::Hash` was incorrectly converted to
`BTreeAlgorithm` instead of `HashAlgorithm`.

This caused `check_compatible` to fail with `Index algorithm mismatch`
on **any** republish of a module containing hash indexes — the database
schema would report BTree while the module def specified Hash.
Effectively, any database with a hash index was stuck and could not be
updated.

### Root Cause

`system_tables.rs:1234` in the `From<StIndexAlgorithm> for
IndexAlgorithm` impl:
```rust
// Before (bug — introduced in #3976):
StIndexAlgorithm::Hash { columns } => BTreeAlgorithm { columns }.into(),

// After (fix):
StIndexAlgorithm::Hash { columns } => HashAlgorithm { columns }.into(),
```

The PR that added hash indices (#3976) imported `HashAlgorithm` but used
`BTreeAlgorithm` for the Hash variant conversion.

## API and ABI breaking changes

None.

## Expected complexity level and risk

1 — single word change, restores correct behavior.

## Testing

Existing schema tests cover index round-trips. The bug was caught by
attempting to republish a module with hash indexes.

---------

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
This commit is contained in:
clockwork-labs-bot
2026-02-18 01:14:34 -05:00
committed by GitHub
parent 6622e2f975
commit 0cb23814d3
+29 -1
View File
@@ -1231,7 +1231,7 @@ impl From<StIndexAlgorithm> for IndexAlgorithm {
fn from(algorithm: StIndexAlgorithm) -> Self {
match algorithm {
StIndexAlgorithm::BTree { columns } => BTreeAlgorithm { columns }.into(),
StIndexAlgorithm::Hash { columns } => BTreeAlgorithm { columns }.into(),
StIndexAlgorithm::Hash { columns } => HashAlgorithm { columns }.into(),
StIndexAlgorithm::Direct { column } => DirectAlgorithm { column }.into(),
algo => unreachable!("unexpected `{algo:?}` in system table `st_indexes`"),
}
@@ -2046,4 +2046,32 @@ mod tests {
"number of system sequences exceeds reserved sequence range"
);
}
/// Regression test: StIndexAlgorithm round-trips must preserve the algorithm.
/// A bug in #3976 converted Hash -> BTreeAlgorithm on read-back, which caused
/// `check_compatible` to fail on any republish of a module with hash indexes
/// after a server restart.
#[test]
fn test_index_algorithm_roundtrip() {
use spacetimedb_primitives::col_list;
let cases = [
IndexAlgorithm::BTree(BTreeAlgorithm {
columns: col_list![0, 1],
}),
IndexAlgorithm::Hash(HashAlgorithm {
columns: col_list![2, 3],
}),
IndexAlgorithm::Direct(DirectAlgorithm { column: ColId(0) }),
];
for original in &cases {
let st: StIndexAlgorithm = original.clone().into();
let roundtripped: IndexAlgorithm = st.into();
assert_eq!(
*original, roundtripped,
"IndexAlgorithm round-trip failed: {original:?} -> {roundtripped:?}"
);
}
}
}