-
Notifications
You must be signed in to change notification settings - Fork 599
datastore: add columns support #3230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: centril/clear-table-and-fix-drop-table
Are you sure you want to change the base?
Changes from all commits
2a58cea
58e82f5
16f8d1e
5f9e2c7
b4bec5b
b7bb652
d7d94f9
ae14efe
03f6b7d
7ae2d4b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -313,6 +313,16 @@ impl Locking { | |
) -> Result<()> { | ||
tx.alter_table_row_type(table_id, column_schemas) | ||
} | ||
|
||
pub fn add_columns_to_table_mut_tx( | ||
&self, | ||
tx: &mut MutTxId, | ||
table_id: TableId, | ||
column_schemas: Vec<ColumnSchema>, | ||
defaults: Vec<AlgebraicValue>, | ||
) -> Result<TableId> { | ||
tx.add_columns_to_table(table_id, column_schemas, defaults) | ||
} | ||
} | ||
|
||
impl DataRow for Locking { | ||
|
@@ -1200,6 +1210,7 @@ mod tests { | |
use core::{fmt, mem}; | ||
use itertools::Itertools; | ||
use pretty_assertions::{assert_eq, assert_matches}; | ||
use spacetimedb_execution::dml::MutDatastore as _; | ||
use spacetimedb_execution::Datastore; | ||
use spacetimedb_lib::db::auth::{StAccess, StTableType}; | ||
use spacetimedb_lib::error::ResultTest; | ||
|
@@ -3361,8 +3372,202 @@ mod tests { | |
|
||
Ok(()) | ||
} | ||
|
||
// TODO: Add the following tests | ||
// - Create a tx that inserts 2000 rows with an auto_inc column | ||
// - Create a tx that inserts 2000 rows with an auto_inc column and then rolls back | ||
|
||
#[test] | ||
fn test_add_columns_to_table() -> ResultTest<()> { | ||
let datastore = get_datastore()?; | ||
|
||
let mut tx = begin_mut_tx(&datastore); | ||
|
||
let initial_sum_type = AlgebraicType::sum([("ba", AlgebraicType::U16)]); | ||
let initial_columns = [ | ||
ColumnSchema::for_test(0, "a", AlgebraicType::U64), | ||
ColumnSchema::for_test(1, "b", initial_sum_type.clone()), | ||
]; | ||
|
||
let initial_indices = [ | ||
IndexSchema::for_test("index_a", BTreeAlgorithm::from(0)), | ||
IndexSchema::for_test("index_b", BTreeAlgorithm::from(1)), | ||
]; | ||
|
||
let sequence = SequenceRow { | ||
id: SequenceId::SENTINEL.into(), | ||
table: 0, | ||
col_pos: 0, | ||
name: "Foo_id_seq", | ||
start: 5, | ||
}; | ||
|
||
let schema = user_public_table( | ||
initial_columns, | ||
initial_indices.clone(), | ||
[], | ||
map_array([sequence]), | ||
None, | ||
None, | ||
); | ||
|
||
let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; | ||
|
||
let mut columns_original = tx.get_schema(table_id).unwrap().columns.to_vec(); | ||
|
||
// Insert initial rows | ||
let initial_row = product![0u64, AlgebraicValue::sum(0, AlgebraicValue::U16(1))]; | ||
insert(&datastore, &mut tx, table_id, &initial_row).unwrap(); | ||
insert(&datastore, &mut tx, table_id, &initial_row).unwrap(); | ||
commit(&datastore, tx)?; | ||
|
||
// Alter Table: Add Variant and Column | ||
Shubham8287 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// | ||
// Change the `b` column, adding a variant. | ||
let vars_ref = &mut columns_original[1].col_type.as_sum_mut().unwrap().variants; | ||
let mut vars = Vec::from(mem::take(vars_ref)); | ||
vars.push(SumTypeVariant::new_named(AlgebraicType::U8, "bb")); | ||
*vars_ref = vars.into(); | ||
// Add column `c` | ||
let mut new_columns = columns_original.clone(); | ||
new_columns.push(ColumnSchema::for_test(2, "c", AlgebraicType::U8)); | ||
let defaults = vec![AlgebraicValue::U8(42)]; | ||
|
||
let mut tx = begin_mut_tx(&datastore); | ||
// insert a row in tx_state when before adding column | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When before? |
||
tx.insert_product_value(table_id, &initial_row).unwrap(); | ||
// add column and then rollback | ||
let rollback_table_id = | ||
datastore.add_columns_to_table_mut_tx(&mut tx, table_id, new_columns.clone(), defaults.clone())?; | ||
let _ = tx.rollback(); | ||
|
||
let old_rows = [ | ||
product![5u64, AlgebraicValue::sum(0, 1u16.into())], | ||
product![6u64, AlgebraicValue::sum(0, 1u16.into())], | ||
]; | ||
|
||
let mut tx = begin_mut_tx(&datastore); | ||
// check rollback was successful | ||
let rows = tx | ||
.table_scan(table_id) | ||
.unwrap() | ||
.map(|row| row.to_product_value()) | ||
.collect::<Vec<_>>(); | ||
assert_eq!(rows, old_rows, "Rows shouldn't be changed if rolledback"); | ||
let table = tx.table(rollback_table_id); | ||
assert!(table.is_none(), "new table shouldn't be created if rolledback"); | ||
|
||
// Add colum and actually commit this time | ||
tx.insert_product_value(table_id, &initial_row).unwrap(); | ||
let new_table_id = datastore.add_columns_to_table_mut_tx(&mut tx, table_id, new_columns.clone(), defaults)?; | ||
|
||
let tx_data = commit(&datastore, tx)?; | ||
|
||
assert_ne!( | ||
new_table_id, table_id, | ||
"New table ID after migration should differ from old one" | ||
); | ||
|
||
// Validate Commitlog Changes | ||
let (_, deletes) = tx_data | ||
.deletes() | ||
.find(|(id, _)| **id == table_id) | ||
.expect("Expected delete log for original table"); | ||
|
||
assert_eq!( | ||
&**deletes, &old_rows, | ||
"Unexpected delete entries after altering the table" | ||
); | ||
|
||
let inserted_rows = [ | ||
product![5u64, AlgebraicValue::sum(0, 1u16.into()), 42u8], | ||
product![6u64, AlgebraicValue::sum(0, 1u16.into()), 42u8], | ||
product![8u64, AlgebraicValue::sum(0, 1u16.into()), 42u8], | ||
]; | ||
|
||
let (_, inserts) = tx_data | ||
.inserts() | ||
.find(|(id, _)| **id == new_table_id) | ||
.expect("Expected insert log for new table"); | ||
|
||
assert_eq!( | ||
&**inserts, &inserted_rows, | ||
"Unexpected insert entries after altering the table" | ||
); | ||
|
||
// Insert Rows into New Table | ||
let mut tx = begin_mut_tx(&datastore); | ||
|
||
let new_row = product![0u64, AlgebraicValue::sum(0, 1u16.into()), 0u8]; | ||
tx.insert_product_value(new_table_id, &new_row).unwrap(); | ||
commit(&datastore, tx)?; | ||
|
||
// test for auto_inc feields | ||
let tx = begin_mut_tx(&datastore); | ||
let rows = tx.table_scan(new_table_id).unwrap().map(|row| row.to_product_value()); | ||
|
||
let mut last_row_auto_inc = 0; | ||
for row in rows { | ||
let auto_inc_col = row.get_field(0, None)?; | ||
if let AlgebraicValue::U64(val) = auto_inc_col { | ||
assert!(val > &last_row_auto_inc, "Auto-increment value did not increase"); | ||
last_row_auto_inc = *val; | ||
} | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
#[test] | ||
fn test_table_schemas_consistency() -> ResultTest<()> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add some comments to the test, for example explaining what it tests, why 5000 is used, etc? |
||
let datastore = get_datastore()?; | ||
|
||
let mut tx = begin_mut_tx(&datastore); | ||
|
||
let initial_sum_type = AlgebraicType::sum([("ba", AlgebraicType::U16)]); | ||
let initial_columns = [ | ||
ColumnSchema::for_test(0, "a", AlgebraicType::U64), | ||
ColumnSchema::for_test(1, "b", initial_sum_type.clone()), | ||
]; | ||
|
||
let initial_indices = [ | ||
IndexSchema::for_test("index_a", BTreeAlgorithm::from(0)), | ||
IndexSchema::for_test("index_b", BTreeAlgorithm::from(1)), | ||
]; | ||
|
||
let sequence = SequenceRow { | ||
id: SequenceId::SENTINEL.into(), | ||
table: 0, | ||
col_pos: 0, | ||
name: "Foo_id_seq", | ||
start: 5, | ||
}; | ||
|
||
let schema = user_public_table( | ||
initial_columns, | ||
initial_indices.clone(), | ||
[], | ||
map_array([sequence]), | ||
None, | ||
None, | ||
); | ||
|
||
let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; | ||
let initial_row = product![0u64, AlgebraicValue::sum(0, AlgebraicValue::U16(1))]; | ||
|
||
for _ in 0..5000 { | ||
insert(&datastore, &mut tx, table_id, &initial_row).unwrap(); | ||
} | ||
commit(&datastore, tx)?; | ||
|
||
let tx = begin_tx(&datastore); | ||
let table_schema = tx.schema_for_table(table_id).unwrap(); | ||
let table_schema_raw = tx.schema_for_table_raw(table_id).unwrap(); | ||
|
||
//TODO: Fix the bug and update the assert | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you file an issue for this and assign it to me? |
||
assert_ne!( | ||
table_schema.sequences[0].allocated, table_schema_raw.sequences[0].allocated, | ||
"Allocated sequence values are differ between schema and raw schema" | ||
); | ||
Ok(()) | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.