Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions crates/datastore/src/locking_tx_datastore/state_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use core::ops::RangeBounds;
use spacetimedb_lib::ConnectionId;
use spacetimedb_primitives::{ColList, TableId};
use spacetimedb_sats::AlgebraicValue;
use spacetimedb_schema::schema::{ColumnSchema, TableSchema, ViewDefInfo};
use spacetimedb_schema::schema::{ColumnSchema, IndexSchema, TableSchema, ViewDefInfo};
use spacetimedb_table::table::IndexScanPointIter;
use spacetimedb_table::{
blob_store::HashMapBlobStore,
Expand Down Expand Up @@ -120,6 +120,22 @@ pub trait StateView {
.transpose()
}

/// Look up an `st_index_accessor` row by its canonical index name.
fn find_st_index_accessor_row_by_index_name(&self, index_name: &str) -> Result<Option<StIndexAccessorRow>> {
match self.iter_by_col_eq(
ST_INDEX_ACCESSOR_ID,
StIndexAccessorFields::IndexName,
&index_name.into(),
) {
Ok(mut iter) => iter.next().map(StIndexAccessorRow::try_from).transpose(),
// `schema_for_table_raw` is called while restoring snapshots,
// before `migrate_system_tables` creates newer system tables.
// Treat a missing `st_index_accessor` as "no aliases yet" here.
Err(DatastoreError::Table(TableError::IdNotFound(..))) => Ok(None),
Err(e) => Err(e),
}
}

/// Look up an `st_column_accessor` row by its canonical table and column names
fn find_st_column_accessor_row(&self, table_name: &str, col_name: &str) -> Result<Option<StColumnAccessorRow>> {
match self.iter_by_col_eq(
Expand Down Expand Up @@ -187,7 +203,14 @@ pub trait StateView {
// Look up the indexes for the table in question.
let indexes = self
.iter_by_col_eq(ST_INDEX_ID, StIndexFields::TableId, value_eq)?
.map(|row| StIndexRow::try_from(row).map(Into::into))
.map(|row| {
let row = StIndexRow::try_from(row)?;
let mut index_schema = IndexSchema::from(row);
index_schema.alias = self
.find_st_index_accessor_row_by_index_name(index_schema.index_name.as_ref())?
.map(|row| row.accessor_name);
Comment thread
joshua-spacetime marked this conversation as resolved.
Ok(index_schema)
})
.collect::<Result<Vec<_>>>()?;

let schedule = self
Expand Down
1 change: 1 addition & 0 deletions crates/smoketests/tests/smoketests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ mod sql;
mod sql_connect_hook;
mod templates;
mod timestamp_route;
mod typescript_index_source_name;
mod views;
105 changes: 105 additions & 0 deletions crates/smoketests/tests/smoketests/typescript_index_source_name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use spacetimedb_smoketests::{random_string, require_local_server, require_pnpm, Smoketest};

const TYPESCRIPT_MODULE_WITHOUT_NEW_COLUMNS: &str = r#"import { schema, table, t } from "spacetimedb/server";
const AppUsers = table(
{ name: "users", public: false },
{
id: t.u64().primaryKey().autoInc(),
name: t.string(),
emailAddress: t.string().index("btree"),
},
);
const spacetimedb = schema({
AppUsers,
});
export default spacetimedb;
export const insert_user = spacetimedb.reducer(
{
name: t.string(),
emailAddress: t.string(),
},
(ctx, { name, emailAddress }) => {
ctx.db.AppUsers.insert({
id: 0n,
name,
emailAddress,
});
},
);
"#;

const TYPESCRIPT_MODULE_WITH_NEW_COLUMNS: &str = r#"import { schema, table, t } from "spacetimedb/server";
const AppUsers = table(
{ name: "users", public: false },
Comment thread
joshua-spacetime marked this conversation as resolved.
{
id: t.u64().primaryKey().autoInc(),
name: t.string(),
emailAddress: t.string().index("btree"),
age: t.number().optional().default(undefined),
isActive: t.bool().default(false).index(),
},
);
const spacetimedb = schema({
AppUsers,
});
export default spacetimedb;
export const find_user_by_email = spacetimedb.reducer(
{ emailAddress: t.string() },
(ctx, { emailAddress }) => {
let count = 0;
for (const _row of ctx.db.AppUsers.emailAddress.filter(emailAddress)) {
count += 1;
}
console.info(`matched ${count}`);
},
);
export const find_users_by_active_status = spacetimedb.reducer(
{ isActive: t.bool() },
(ctx, { isActive }) => {
let count = 0;
for (const _row of ctx.db.AppUsers.isActive.filter(isActive)) {
count += 1;
}
console.info(`matched active users ${count}`);
},
);
"#;

#[test]
fn test_typescript_add_optional_columns() {
require_pnpm!();
require_local_server!();

let mut test = Smoketest::builder().autopublish(false).build();
let module_name = format!("typescript-add-optional-columns-{}", random_string());

let database_identity = test
.publish_typescript_module_source(
"typescript-add-optional-columns-v1",
&module_name,
TYPESCRIPT_MODULE_WITHOUT_NEW_COLUMNS,
)
.unwrap();

test.call("insert_user", &["Alice", "alice@example.com"]).unwrap();

test.restart_server();

test.publish_typescript_module_source_clear(
"typescript-add-optional-columns-v2",
&database_identity,
TYPESCRIPT_MODULE_WITH_NEW_COLUMNS,
false,
)
.unwrap();

test.call("find_user_by_email", &["alice@example.com"]).unwrap();
test.call("find_users_by_active_status", &["false"]).unwrap();
}
Loading