Skip to content

Commit 542d26d

Browse files
add system tables for views (#3419)
# Description of Changes <!-- Please describe your change, mention any related tickets, and so on here. --> This patch defines the system table schemas for views and allocates IDs for them. It **does not** populate these tables. # API and ABI breaking changes <!-- If this is an API or ABI breaking change, please apply the corresponding GitHub label. --> None # Expected complexity level and risk <!-- How complicated do you think these changes are? Grade on a scale from 1 to 5, where 1 is a trivial change, and 5 is a deep-reaching and complex change. This complexity rating applies not only to the complexity apparent in the diff, but also to its interactions with existing and future code. If you answered more than a 2, explain what is complex about the PR, and what other components it interacts with in potentially concerning ways. --> 1 # Testing <!-- Describe any testing you've done, and any testing you'd like your reviewers to do, so that you're confident that all the changes work as expected! --> Tests will be added in the patch that populates these tables
1 parent 0d2a0ed commit 542d26d

10 files changed

Lines changed: 218 additions & 14 deletions

File tree

crates/datastore/src/locking_tx_datastore/committed_state.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ use super::{
66
tx_state::{IndexIdMap, PendingSchemaChange, TxState},
77
IterByColEqTx,
88
};
9-
use crate::system_tables::{ST_CONNECTION_CREDENTIALS_ID, ST_CONNECTION_CREDENTIALS_IDX};
9+
use crate::system_tables::{
10+
ST_CONNECTION_CREDENTIALS_ID, ST_CONNECTION_CREDENTIALS_IDX, ST_VIEW_COLUMN_ID, ST_VIEW_COLUMN_IDX, ST_VIEW_ID,
11+
ST_VIEW_IDX, ST_VIEW_PARAM_ID, ST_VIEW_PARAM_IDX,
12+
};
1013
use crate::{
1114
db_metrics::DB_METRICS,
1215
error::{DatastoreError, IndexError, TableError},
@@ -253,6 +256,10 @@ impl CommittedState {
253256
schemas[ST_CONNECTION_CREDENTIALS_IDX].clone(),
254257
);
255258

259+
self.create_table(ST_VIEW_ID, schemas[ST_VIEW_IDX].clone());
260+
self.create_table(ST_VIEW_PARAM_ID, schemas[ST_VIEW_PARAM_IDX].clone());
261+
self.create_table(ST_VIEW_COLUMN_ID, schemas[ST_VIEW_COLUMN_IDX].clone());
262+
256263
// Insert the sequences into `st_sequences`
257264
let (st_sequences, blob_store, pool) =
258265
self.get_table_and_blob_store_or_create(ST_SEQUENCE_ID, &schemas[ST_SEQUENCE_IDX]);

crates/datastore/src/locking_tx_datastore/datastore.rs

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,11 +1247,12 @@ mod tests {
12471247
use crate::system_tables::{
12481248
system_tables, StColumnRow, StConnectionCredentialsFields, StConstraintData, StConstraintFields,
12491249
StConstraintRow, StIndexAlgorithm, StIndexFields, StIndexRow, StRowLevelSecurityFields, StScheduledFields,
1250-
StSequenceFields, StSequenceRow, StTableRow, StVarFields, ST_CLIENT_NAME, ST_COLUMN_ID, ST_COLUMN_NAME,
1251-
ST_CONNECTION_CREDENTIALS_ID, ST_CONNECTION_CREDENTIALS_NAME, ST_CONSTRAINT_ID, ST_CONSTRAINT_NAME,
1252-
ST_INDEX_ID, ST_INDEX_NAME, ST_MODULE_NAME, ST_RESERVED_SEQUENCE_RANGE, ST_ROW_LEVEL_SECURITY_ID,
1253-
ST_ROW_LEVEL_SECURITY_NAME, ST_SCHEDULED_ID, ST_SCHEDULED_NAME, ST_SEQUENCE_ID, ST_SEQUENCE_NAME,
1254-
ST_TABLE_NAME, ST_VAR_ID, ST_VAR_NAME,
1250+
StSequenceFields, StSequenceRow, StTableRow, StVarFields, StViewFields, ST_CLIENT_NAME, ST_COLUMN_ID,
1251+
ST_COLUMN_NAME, ST_CONNECTION_CREDENTIALS_ID, ST_CONNECTION_CREDENTIALS_NAME, ST_CONSTRAINT_ID,
1252+
ST_CONSTRAINT_NAME, ST_INDEX_ID, ST_INDEX_NAME, ST_MODULE_NAME, ST_RESERVED_SEQUENCE_RANGE,
1253+
ST_ROW_LEVEL_SECURITY_ID, ST_ROW_LEVEL_SECURITY_NAME, ST_SCHEDULED_ID, ST_SCHEDULED_NAME, ST_SEQUENCE_ID,
1254+
ST_SEQUENCE_NAME, ST_TABLE_NAME, ST_VAR_ID, ST_VAR_NAME, ST_VIEW_COLUMN_ID, ST_VIEW_COLUMN_NAME, ST_VIEW_ID,
1255+
ST_VIEW_NAME, ST_VIEW_PARAM_ID, ST_VIEW_PARAM_NAME,
12551256
};
12561257
use crate::traits::{IsolationLevel, MutTx};
12571258
use crate::Result;
@@ -1265,7 +1266,7 @@ mod tests {
12651266
use spacetimedb_lib::error::ResultTest;
12661267
use spacetimedb_lib::st_var::StVarValue;
12671268
use spacetimedb_lib::{resolved_type_via_v9, ScheduleAt, TimeDuration};
1268-
use spacetimedb_primitives::{col_list, ColId, ScheduleId};
1269+
use spacetimedb_primitives::{col_list, ColId, ScheduleId, ViewId};
12691270
use spacetimedb_sats::algebraic_value::ser::value_serialize;
12701271
use spacetimedb_sats::bsatn::ToBsatn;
12711272
use spacetimedb_sats::layout::RowTypeLayout;
@@ -1704,6 +1705,10 @@ mod tests {
17041705
TableRow { id: ST_SCHEDULED_ID.into(), name: ST_SCHEDULED_NAME, ty: StTableType::System, access: StAccess::Public, primary_key: Some(StScheduledFields::ScheduleId.into()) },
17051706
TableRow { id: ST_ROW_LEVEL_SECURITY_ID.into(), name: ST_ROW_LEVEL_SECURITY_NAME, ty: StTableType::System, access: StAccess::Public, primary_key: Some(StRowLevelSecurityFields::Sql.into()) },
17061707
TableRow { id: ST_CONNECTION_CREDENTIALS_ID.into(), name: ST_CONNECTION_CREDENTIALS_NAME, ty: StTableType::System, access: StAccess::Private, primary_key: Some(StConnectionCredentialsFields::ConnectionId.into()) },
1708+
TableRow { id: ST_VIEW_ID.into(), name: ST_VIEW_NAME, ty: StTableType::System, access: StAccess::Public, primary_key: Some(StViewFields::ViewId.into()) },
1709+
TableRow { id: ST_VIEW_PARAM_ID.into(), name: ST_VIEW_PARAM_NAME, ty: StTableType::System, access: StAccess::Public, primary_key: None },
1710+
TableRow { id: ST_VIEW_COLUMN_ID.into(), name: ST_VIEW_COLUMN_NAME, ty: StTableType::System, access: StAccess::Public, primary_key: None },
1711+
17071712
]));
17081713
#[rustfmt::skip]
17091714
assert_eq!(query.scan_st_columns()?, map_array([
@@ -1762,6 +1767,22 @@ mod tests {
17621767

17631768
ColRow { table: ST_CONNECTION_CREDENTIALS_ID.into(), pos: 0, name: "connection_id", ty: AlgebraicType::U128 },
17641769
ColRow { table: ST_CONNECTION_CREDENTIALS_ID.into(), pos: 1, name: "jwt_payload", ty: AlgebraicType::String },
1770+
1771+
ColRow { table: ST_VIEW_ID.into(), pos: 0, name: "view_id", ty: ViewId::get_type() },
1772+
ColRow { table: ST_VIEW_ID.into(), pos: 1, name: "view_name", ty: AlgebraicType::String },
1773+
ColRow { table: ST_VIEW_ID.into(), pos: 2, name: "table_id", ty: AlgebraicType::option(TableId::get_type()) },
1774+
ColRow { table: ST_VIEW_ID.into(), pos: 3, name: "is_public", ty: AlgebraicType::Bool },
1775+
ColRow { table: ST_VIEW_ID.into(), pos: 4, name: "is_anonymous", ty: AlgebraicType::Bool },
1776+
1777+
ColRow { table: ST_VIEW_PARAM_ID.into(), pos: 0, name: "view_id", ty: ViewId::get_type() },
1778+
ColRow { table: ST_VIEW_PARAM_ID.into(), pos: 1, name: "param_pos", ty: ColId::get_type() },
1779+
ColRow { table: ST_VIEW_PARAM_ID.into(), pos: 2, name: "param_name", ty: AlgebraicType::String },
1780+
ColRow { table: ST_VIEW_PARAM_ID.into(), pos: 3, name: "param_type", ty: AlgebraicType::bytes() },
1781+
1782+
ColRow { table: ST_VIEW_COLUMN_ID.into(), pos: 0, name: "view_id", ty: ViewId::get_type() },
1783+
ColRow { table: ST_VIEW_COLUMN_ID.into(), pos: 1, name: "col_pos", ty: ColId::get_type() },
1784+
ColRow { table: ST_VIEW_COLUMN_ID.into(), pos: 2, name: "col_name", ty: AlgebraicType::String },
1785+
ColRow { table: ST_VIEW_COLUMN_ID.into(), pos: 3, name: "col_type", ty: AlgebraicType::bytes() },
17651786
]));
17661787
#[rustfmt::skip]
17671788
assert_eq!(query.scan_st_indexes()?, map_array([
@@ -1778,6 +1799,10 @@ mod tests {
17781799
IndexRow { id: 11, table: ST_ROW_LEVEL_SECURITY_ID.into(), col: col(0), name: "st_row_level_security_table_id_idx_btree", },
17791800
IndexRow { id: 12, table: ST_ROW_LEVEL_SECURITY_ID.into(), col: col(1), name: "st_row_level_security_sql_idx_btree", },
17801801
IndexRow { id: 13, table: ST_CONNECTION_CREDENTIALS_ID.into(), col: col(0), name: "st_connection_credentials_connection_id_idx_btree", },
1802+
IndexRow { id: 14, table: ST_VIEW_ID.into(), col: col(0), name: "st_view_view_id_idx_btree", },
1803+
IndexRow { id: 15, table: ST_VIEW_ID.into(), col: col(1), name: "st_view_view_name_idx_btree", },
1804+
IndexRow { id: 16, table: ST_VIEW_PARAM_ID.into(), col: col_list![0, 1], name: "st_view_param_view_id_param_pos_idx_btree", },
1805+
IndexRow { id: 17, table: ST_VIEW_COLUMN_ID.into(), col: col_list![0, 1], name: "st_view_column_view_id_col_pos_idx_btree", },
17811806
]));
17821807
let start = ST_RESERVED_SEQUENCE_RANGE as i128 + 1;
17831808
#[rustfmt::skip]
@@ -1788,6 +1813,7 @@ mod tests {
17881813
SequenceRow { id: 2, table: ST_INDEX_ID.into(), col_pos: 0, name: "st_index_index_id_seq", start },
17891814
SequenceRow { id: 3, table: ST_CONSTRAINT_ID.into(), col_pos: 0, name: "st_constraint_constraint_id_seq", start },
17901815
SequenceRow { id: 4, table: ST_SCHEDULED_ID.into(), col_pos: 0, name: "st_scheduled_schedule_id_seq", start },
1816+
SequenceRow { id: 6, table: ST_VIEW_ID.into(), col_pos: 0, name: "st_view_view_id_seq", start },
17911817
],
17921818
|row| StSequenceRow {
17931819
allocated: start - 1,
@@ -1808,7 +1834,11 @@ mod tests {
18081834
ConstraintRow { constraint_id: 10, table_id: ST_SCHEDULED_ID.into(), unique_columns: col(1), constraint_name: "st_scheduled_table_id_key", },
18091835
ConstraintRow { constraint_id: 11, table_id: ST_ROW_LEVEL_SECURITY_ID.into(), unique_columns: col(1), constraint_name: "st_row_level_security_sql_key", },
18101836
ConstraintRow { constraint_id: 12, table_id: ST_CONNECTION_CREDENTIALS_ID.into(), unique_columns: col(0), constraint_name: "st_connection_credentials_connection_id_key", },
1811-
]));
1837+
ConstraintRow { constraint_id: 13, table_id: ST_VIEW_ID.into(), unique_columns: col(0), constraint_name: "st_view_view_id_key", },
1838+
ConstraintRow { constraint_id: 14, table_id: ST_VIEW_ID.into(), unique_columns: col(1), constraint_name: "st_view_view_name_key", },
1839+
ConstraintRow { constraint_id: 15, table_id: ST_VIEW_PARAM_ID.into(), unique_columns: col_list![0, 1], constraint_name: "st_view_param_view_id_param_pos_key", },
1840+
ConstraintRow { constraint_id: 16, table_id: ST_VIEW_COLUMN_ID.into(), unique_columns: col_list![0, 1], constraint_name: "st_view_column_view_id_col_pos_key", },
1841+
]));
18121842

18131843
// Verify we get back the tables correctly with the proper ids...
18141844
let cols = query.scan_st_columns()?;
@@ -2224,6 +2254,10 @@ mod tests {
22242254
IndexRow { id: 11, table: ST_ROW_LEVEL_SECURITY_ID.into(), col: col(0), name: "st_row_level_security_table_id_idx_btree", },
22252255
IndexRow { id: 12, table: ST_ROW_LEVEL_SECURITY_ID.into(), col: col(1), name: "st_row_level_security_sql_idx_btree", },
22262256
IndexRow { id: 13, table: ST_CONNECTION_CREDENTIALS_ID.into(), col: col(0), name: "st_connection_credentials_connection_id_idx_btree", },
2257+
IndexRow { id: 14, table: ST_VIEW_ID.into(), col: col(0), name: "st_view_view_id_idx_btree", },
2258+
IndexRow { id: 15, table: ST_VIEW_ID.into(), col: col(1), name: "st_view_view_name_idx_btree", },
2259+
IndexRow { id: 16, table: ST_VIEW_PARAM_ID.into(), col: col_list![0, 1], name: "st_view_param_view_id_param_pos_idx_btree", },
2260+
IndexRow { id: 17, table: ST_VIEW_COLUMN_ID.into(), col: col_list![0, 1], name: "st_view_column_view_id_col_pos_idx_btree", },
22272261
IndexRow { id: seq_start, table: FIRST_NON_SYSTEM_ID, col: col(0), name: "Foo_id_idx_btree", },
22282262
IndexRow { id: seq_start + 1, table: FIRST_NON_SYSTEM_ID, col: col(1), name: "Foo_name_idx_btree", },
22292263
IndexRow { id: seq_start + 2, table: FIRST_NON_SYSTEM_ID, col: col(2), name: "Foo_age_idx_btree", },

crates/datastore/src/locking_tx_datastore/mut_tx.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,14 +1004,19 @@ impl MutTxId {
10041004
/// - The sequence metadata is inserted into the system tables (and other data structures reflecting them).
10051005
/// - The returned ID is unique and not `SequenceId::SENTINEL`.
10061006
pub fn create_sequence(&mut self, seq: SequenceSchema) -> Result<SequenceId> {
1007-
if seq.sequence_id != SequenceId::SENTINEL {
1008-
return Err(anyhow::anyhow!("`sequence_id` must be `SequenceId::SENTINEL` in `{:#?}`", seq).into());
1009-
}
10101007
if seq.table_id == TableId::SENTINEL {
10111008
return Err(anyhow::anyhow!("`table_id` must not be `TableId::SENTINEL` in `{:#?}`", seq).into());
10121009
}
10131010

10141011
let table_id = seq.table_id;
1012+
let matching_system_table_schema = system_tables().iter().find(|s| s.table_id == table_id).cloned();
1013+
1014+
if seq.sequence_id != SequenceId::SENTINEL && matching_system_table_schema.is_none() {
1015+
return Err(anyhow::anyhow!("`sequence_id` must be `SequenceId::SENTINEL` in `{:#?}`", seq).into());
1016+
}
1017+
1018+
let sequence_id = seq.sequence_id;
1019+
10151020
log::trace!(
10161021
"SEQUENCE CREATING: {} for table: {} and col: {}",
10171022
seq.sequence_name,
@@ -1023,7 +1028,7 @@ impl MutTxId {
10231028
// NOTE: Because st_sequences has a unique index on sequence_name, this will
10241029
// fail if the table already exists.
10251030
let mut sequence_row = StSequenceRow {
1026-
sequence_id: SequenceId::SENTINEL,
1031+
sequence_id,
10271032
sequence_name: seq.sequence_name,
10281033
table_id,
10291034
col_pos: seq.col_pos,

0 commit comments

Comments
 (0)