diff --git a/Cargo.lock b/Cargo.lock index 6ed83e61eb0..fa76aebc3ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2078,6 +2078,16 @@ dependencies = [ "serde", ] +[[package]] +name = "event-table-client" +version = "2.0.0" +dependencies = [ + "anyhow", + "env_logger 0.10.2", + "spacetimedb-sdk", + "test-counter", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -6870,6 +6880,13 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sdk-test-event-table-module" +version = "0.1.0" +dependencies = [ + "spacetimedb 2.0.0", +] + [[package]] name = "sdk-test-module" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 4c94938a7db..3f7e3e5679e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,11 +49,13 @@ members = [ "modules/sdk-test-connect-disconnect", "modules/sdk-test-procedure", "modules/sdk-test-view", + "modules/sdk-test-event-table", "sdks/rust/tests/test-client", "sdks/rust/tests/test-counter", "sdks/rust/tests/connect_disconnect_client", "sdks/rust/tests/procedure-client", "sdks/rust/tests/view-client", + "sdks/rust/tests/event-table-client", "tools/ci", "tools/upgrade-version", "tools/license-check", diff --git a/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawMiscModuleExportV9.g.h b/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawMiscModuleExportV9.g.h index 494243dd470..b8e391591df 100644 --- a/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawMiscModuleExportV9.g.h +++ b/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawMiscModuleExportV9.g.h @@ -12,9 +12,9 @@ #include #include "../autogen_base.h" #include "spacetimedb/bsatn/bsatn.h" +#include "RawViewDefV9.g.h" #include "RawColumnDefaultValueV9.g.h" #include "RawProcedureDefV9.g.h" -#include "RawViewDefV9.g.h" namespace SpacetimeDB::Internal { diff --git a/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawModuleDefV9.g.h b/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawModuleDefV9.g.h index d0e9c7024a6..f2fdde5a32d 100644 --- a/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawModuleDefV9.g.h +++ b/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawModuleDefV9.g.h @@ -13,11 +13,11 @@ #include "../autogen_base.h" #include "spacetimedb/bsatn/bsatn.h" #include "RawMiscModuleExportV9.g.h" -#include "RawReducerDefV9.g.h" +#include "RawTypeDefV9.g.h" #include "RawTableDefV9.g.h" -#include "Typespace.g.h" #include "RawRowLevelSecurityDefV9.g.h" -#include "RawTypeDefV9.g.h" +#include "RawReducerDefV9.g.h" +#include "Typespace.g.h" namespace SpacetimeDB::Internal { diff --git a/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawProcedureDefV9.g.h b/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawProcedureDefV9.g.h index 667d9864a2a..a49d9d78970 100644 --- a/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawProcedureDefV9.g.h +++ b/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawProcedureDefV9.g.h @@ -12,8 +12,8 @@ #include #include "../autogen_base.h" #include "spacetimedb/bsatn/bsatn.h" -#include "ProductType.g.h" #include "AlgebraicType.g.h" +#include "ProductType.g.h" namespace SpacetimeDB::Internal { diff --git a/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawTableDefV9.g.h b/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawTableDefV9.g.h index 44a798abf66..8daa1883319 100644 --- a/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawTableDefV9.g.h +++ b/crates/bindings-cpp/include/spacetimedb/internal/autogen/RawTableDefV9.g.h @@ -12,12 +12,12 @@ #include #include "../autogen_base.h" #include "spacetimedb/bsatn/bsatn.h" -#include "RawScheduleDefV9.g.h" #include "TableAccess.g.h" #include "RawConstraintDefV9.g.h" +#include "RawIndexDefV9.g.h" #include "TableType.g.h" #include "RawSequenceDefV9.g.h" -#include "RawIndexDefV9.g.h" +#include "RawScheduleDefV9.g.h" namespace SpacetimeDB::Internal { diff --git a/crates/bindings-macro/src/lib.rs b/crates/bindings-macro/src/lib.rs index 52b13f00267..50da833bae1 100644 --- a/crates/bindings-macro/src/lib.rs +++ b/crates/bindings-macro/src/lib.rs @@ -61,6 +61,7 @@ mod sym { symbol!(unique); symbol!(update); symbol!(default); + symbol!(event); symbol!(u8); symbol!(i8); diff --git a/crates/bindings-macro/src/table.rs b/crates/bindings-macro/src/table.rs index 9d8143fce6f..b93f907ec90 100644 --- a/crates/bindings-macro/src/table.rs +++ b/crates/bindings-macro/src/table.rs @@ -19,6 +19,7 @@ pub(crate) struct TableArgs { scheduled: Option, name: Ident, indices: Vec, + event: Option, } enum TableAccess { @@ -71,6 +72,7 @@ impl TableArgs { let mut scheduled = None; let mut name = None; let mut indices = Vec::new(); + let mut event = None; syn::meta::parser(|meta| { match_meta!(match meta { sym::public => { @@ -91,6 +93,10 @@ impl TableArgs { check_duplicate(&scheduled, &meta)?; scheduled = Some(ScheduledArg::parse_meta(meta)?); } + sym::event => { + check_duplicate(&event, &meta)?; + event = Some(meta.path.span()); + } }); Ok(()) }) @@ -107,6 +113,7 @@ impl TableArgs { scheduled, name, indices, + event, }) } } @@ -852,6 +859,18 @@ pub(crate) fn table_impl(mut args: TableArgs, item: &syn::DeriveInput) -> syn::R ); let table_access = args.access.iter().map(|acc| acc.to_value()); + let is_event = args.event.iter().map(|_| { + quote!( + const IS_EVENT: bool = true; + ) + }); + let can_be_lookup_impl = if args.event.is_none() { + quote! { + impl spacetimedb::query_builder::CanBeLookupTable for #original_struct_ident {} + } + } else { + quote! {} + }; let unique_col_ids = unique_columns.iter().map(|col| col.index); let primary_col_id = primary_key_column.clone().into_iter().map(|col| col.index); let sequence_col_ids = sequenced_columns.iter().map(|col| col.index); @@ -977,6 +996,7 @@ pub(crate) fn table_impl(mut args: TableArgs, item: &syn::DeriveInput) -> syn::R const TABLE_NAME: &'static str = #table_name; // the default value if not specified is Private #(const TABLE_ACCESS: spacetimedb::table::TableAccess = #table_access;)* + #(#is_event)* const UNIQUE_COLUMNS: &'static [u16] = &[#(#unique_col_ids),*]; const INDEXES: &'static [spacetimedb::table::IndexDesc<'static>] = &[#(#index_descs),*]; #(const PRIMARY_KEY: Option = Some(#primary_col_id);)* @@ -1088,6 +1108,8 @@ pub(crate) fn table_impl(mut args: TableArgs, item: &syn::DeriveInput) -> syn::R } } + #can_be_lookup_impl + }; let table_query_handle_def = quote! { diff --git a/crates/bindings-typescript/src/lib/schema.ts b/crates/bindings-typescript/src/lib/schema.ts index 818c3279be7..c755b876a14 100644 --- a/crates/bindings-typescript/src/lib/schema.ts +++ b/crates/bindings-typescript/src/lib/schema.ts @@ -117,6 +117,7 @@ export function tableToSchema< }; }) as T['idxs'], tableDef, + ...(tableDef.isEvent ? { isEvent: true } : {}), }; } diff --git a/crates/bindings-typescript/src/lib/table.ts b/crates/bindings-typescript/src/lib/table.ts index 2ab05b9ea8f..8ade4e9b94a 100644 --- a/crates/bindings-typescript/src/lib/table.ts +++ b/crates/bindings-typescript/src/lib/table.ts @@ -117,6 +117,7 @@ export type UntypedTableDef = { indexes: readonly IndexOpts[]; constraints: readonly ConstraintOpts[]; tableDef: Infer; + isEvent?: boolean; }; /** @@ -179,6 +180,7 @@ export type TableOpts = { { [k: string]: RowBuilder }, ReturnType >; + event?: boolean; }; /** @@ -301,6 +303,7 @@ export function table>( public: isPublic = false, indexes: userIndexes = [], scheduled, + event: isEvent = false, } = opts; // 1. column catalogue + helpers @@ -476,7 +479,7 @@ export function table>( tableType: { tag: 'User' }, tableAccess: { tag: isPublic ? 'Public' : 'Private' }, defaultValues, - isEvent: false, + isEvent, }; }, idxs: {} as OptsIndices, diff --git a/crates/bindings-typescript/src/sdk/client_table.ts b/crates/bindings-typescript/src/sdk/client_table.ts index 2e4e102301b..b6cd2c1a56d 100644 --- a/crates/bindings-typescript/src/sdk/client_table.ts +++ b/crates/bindings-typescript/src/sdk/client_table.ts @@ -42,7 +42,7 @@ export type ClientTablePrimaryKeyMethods< ): void; }; -export type ClientTableMethods< +export type ClientTableInsertMethods< RemoteModule extends UntypedRemoteModule, TableName extends TableNamesOf, > = { @@ -66,7 +66,12 @@ export type ClientTableMethods< row: Prettify>> ) => void ): void; +}; +export type ClientTableDeleteMethods< + RemoteModule extends UntypedRemoteModule, + TableName extends TableNamesOf, +> = { /** * Registers a callback to be invoked when a row is deleted from the table. */ @@ -89,6 +94,12 @@ export type ClientTableMethods< ): void; }; +export type ClientTableMethods< + RemoteModule extends UntypedRemoteModule, + TableName extends TableNamesOf, +> = ClientTableInsertMethods & + ClientTableDeleteMethods; + /** * Table * @@ -107,6 +118,12 @@ export type ClientTable< > >; +type IsEventTable = TableDef extends { + isEvent: true; +} + ? true + : false; + type HasPrimaryKey = ColumnsHavePrimaryKey< TableDef['columns'] >; @@ -142,13 +159,21 @@ export type ClientTableCoreImplementable< /** * Core methods of ClientTable, without the indexes mixed in. - * Includes only staticly known methods. + * Includes only statically known methods. + * + * Event tables only expose insert callbacks (no delete or update), + * matching the Rust SDK's `EventTable` trait. */ export type ClientTableCore< RemoteModule extends UntypedRemoteModule, TableName extends TableNamesOf, > = ReadonlyTableMethods> & - ClientTableMethods & - (HasPrimaryKey> extends true - ? ClientTablePrimaryKeyMethods - : {}); + ClientTableInsertMethods & + (IsEventTable> extends true + ? {} + : ClientTableDeleteMethods & + (HasPrimaryKey< + TableDefForTableName + > extends true + ? ClientTablePrimaryKeyMethods + : {})); diff --git a/crates/bindings-typescript/src/sdk/db_connection_impl.ts b/crates/bindings-typescript/src/sdk/db_connection_impl.ts index 96f959f14a8..344a9dbc4a9 100644 --- a/crates/bindings-typescript/src/sdk/db_connection_impl.ts +++ b/crates/bindings-typescript/src/sdk/db_connection_impl.ts @@ -510,7 +510,8 @@ export class DbConnectionImpl return inserts.concat(deletes); } if (rows.tag === 'EventTable') { - // TODO: Decide how event tables should be merged into the cache. + // Event table rows are insert-only. The table cache handles skipping + // storage for event tables and only firing on_insert callbacks. return this.#parseRowList('insert', tableName, rows.value.events); } return []; diff --git a/crates/bindings-typescript/src/sdk/table_cache.ts b/crates/bindings-typescript/src/sdk/table_cache.ts index 947ce304c32..9f04ccad0c2 100644 --- a/crates/bindings-typescript/src/sdk/table_cache.ts +++ b/crates/bindings-typescript/src/sdk/table_cache.ts @@ -261,6 +261,23 @@ export class TableCacheImpl< ctx: EventContextInterface ): PendingCallback[] => { const pendingCallbacks: PendingCallback[] = []; + + // Event tables: fire on_insert callbacks but don't store rows in the cache. + if (this.tableDef.isEvent) { + for (const op of operations) { + if (op.type === 'insert') { + pendingCallbacks.push({ + type: 'insert', + table: this.tableDef.sourceName, + cb: () => { + this.emitter.emit('insert', ctx, op.row); + }, + }); + } + } + return pendingCallbacks; + } + // TODO: performance const hasPrimaryKey = Object.values(this.tableDef.columns).some( col => col.columnMetadata.isPrimaryKey === true diff --git a/crates/bindings-typescript/test-react-router-app/src/module_bindings/index.ts b/crates/bindings-typescript/test-react-router-app/src/module_bindings/index.ts index 5954d92c0bf..dce7e5eee76 100644 --- a/crates/bindings-typescript/test-react-router-app/src/module_bindings/index.ts +++ b/crates/bindings-typescript/test-react-router-app/src/module_bindings/index.ts @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.11.0 (commit 93c0015f51af4afaf9489b92191d6e6d838af8a9). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). /* eslint-disable */ /* tslint:disable */ @@ -10,7 +10,9 @@ import { DbConnectionImpl as __DbConnectionImpl, SubscriptionBuilderImpl as __SubscriptionBuilderImpl, TypeBuilder as __TypeBuilder, + Uuid as __Uuid, convertToAccessorMap as __convertToAccessorMap, + makeQueryBuilder as __makeQueryBuilder, procedureSchema as __procedureSchema, procedures as __procedures, reducerSchema as __reducerSchema, @@ -24,41 +26,29 @@ import { type Event as __Event, type EventContextInterface as __EventContextInterface, type Infer as __Infer, + type QueryBuilder as __QueryBuilder, type ReducerEventContextInterface as __ReducerEventContextInterface, type RemoteModule as __RemoteModule, type SubscriptionEventContextInterface as __SubscriptionEventContextInterface, type SubscriptionHandleImpl as __SubscriptionHandleImpl, } from '../../../src/index'; -// Import and reexport all reducer arg types -import ClearCounter from './clear_counter_reducer'; -export { ClearCounter }; -import ClientConnected from './client_connected_reducer'; -export { ClientConnected }; -import ClientDisconnected from './client_disconnected_reducer'; -export { ClientDisconnected }; -import IncrementCounter from './increment_counter_reducer'; -export { IncrementCounter }; +// Import all reducer arg schemas +import ClearCounterReducer from './clear_counter_reducer'; +import IncrementCounterReducer from './increment_counter_reducer'; -// Import and reexport all procedure arg types +// Import all procedure arg schemas -// Import and reexport all table handle types +// Import all table schema definitions import CounterRow from './counter_table'; -export { CounterRow }; import OfflineUserRow from './offline_user_table'; -export { OfflineUserRow }; import UserRow from './user_table'; -export { UserRow }; -// Import and reexport all types -import Counter from './counter_type'; -export { Counter }; -import User from './user_type'; -export { User }; +/** Type-only namespace exports for generated type groups. */ /** The schema information for all tables in this module. This is defined the same was as the tables would have been defined in the server. */ -const tablesSchema = __schema( - __table( +const tablesSchema = __schema({ + counter: __table( { name: 'counter', indexes: [{ name: 'id', algorithm: 'btree', columns: ['id'] }], @@ -68,7 +58,7 @@ const tablesSchema = __schema( }, CounterRow ), - __table( + offline_user: __table( { name: 'offline_user', indexes: [ @@ -84,7 +74,7 @@ const tablesSchema = __schema( }, OfflineUserRow ), - __table( + user: __table( { name: 'user', indexes: [ @@ -99,13 +89,13 @@ const tablesSchema = __schema( ], }, UserRow - ) -); + ), +}); /** The schema information for all reducers in this module. This is defined the same way as the reducers would have been defined in the server, except the body of the reducer is omitted in code generation. */ const reducersSchema = __reducers( - __reducerSchema('clear_counter', ClearCounter), - __reducerSchema('increment_counter', IncrementCounter) + __reducerSchema('clear_counter', ClearCounterReducer), + __reducerSchema('increment_counter', IncrementCounterReducer) ); /** The schema information for all procedures in this module. This is defined the same way as the procedures would have been defined in the server. */ @@ -114,7 +104,7 @@ const proceduresSchema = __procedures(); /** The remote SpacetimeDB module schema, both runtime and type information. */ const REMOTE_MODULE = { versionInfo: { - cliVersion: '1.11.0' as const, + cliVersion: '2.0.0' as const, }, tables: tablesSchema.schemaType.tables, reducers: reducersSchema.reducersType.reducers, @@ -125,8 +115,9 @@ const REMOTE_MODULE = { typeof proceduresSchema >; -/** The tables available in this remote SpacetimeDB module. */ -export const tables = __convertToAccessorMap(tablesSchema.schemaType.tables); +/** The tables available in this remote SpacetimeDB module. Each table reference doubles as a query builder. */ +export const tables: __QueryBuilder = + __makeQueryBuilder(tablesSchema.schemaType); /** The reducers available in this remote SpacetimeDB module. */ export const reducers = __convertToAccessorMap( diff --git a/crates/bindings-typescript/test-react-router-app/src/module_bindings/offline_user_table.ts b/crates/bindings-typescript/test-react-router-app/src/module_bindings/offline_user_table.ts index cb2103b54f5..66041140a28 100644 --- a/crates/bindings-typescript/test-react-router-app/src/module_bindings/offline_user_table.ts +++ b/crates/bindings-typescript/test-react-router-app/src/module_bindings/offline_user_table.ts @@ -12,5 +12,5 @@ import { export default __t.row({ identity: __t.identity().primaryKey(), - hasIncrementedCount: __t.u32(), + hasIncrementedCount: __t.u32().name('has_incremented_count'), }); diff --git a/crates/bindings-typescript/test-react-router-app/src/module_bindings/user_table.ts b/crates/bindings-typescript/test-react-router-app/src/module_bindings/user_table.ts index cb2103b54f5..66041140a28 100644 --- a/crates/bindings-typescript/test-react-router-app/src/module_bindings/user_table.ts +++ b/crates/bindings-typescript/test-react-router-app/src/module_bindings/user_table.ts @@ -12,5 +12,5 @@ import { export default __t.row({ identity: __t.identity().primaryKey(), - hasIncrementedCount: __t.u32(), + hasIncrementedCount: __t.u32().name('has_incremented_count'), }); diff --git a/crates/bindings/src/rt.rs b/crates/bindings/src/rt.rs index 4c2ec69254d..d2d690d14e1 100644 --- a/crates/bindings/src/rt.rs +++ b/crates/bindings/src/rt.rs @@ -740,7 +740,8 @@ pub fn register_table() { .inner .build_table(T::TABLE_NAME, product_type_ref) .with_type(TableType::User) - .with_access(T::TABLE_ACCESS); + .with_access(T::TABLE_ACCESS) + .with_event(T::IS_EVENT); for &col in T::UNIQUE_COLUMNS { table = table.with_unique_constraint(col); diff --git a/crates/bindings/src/table.rs b/crates/bindings/src/table.rs index 394d2bfdf8d..850f31e625a 100644 --- a/crates/bindings/src/table.rs +++ b/crates/bindings/src/table.rs @@ -128,6 +128,7 @@ pub trait TableInternal: Sized { const PRIMARY_KEY: Option = None; const SEQUENCES: &'static [u16]; const SCHEDULE: Option> = None; + const IS_EVENT: bool = false; /// Returns the ID of this table. fn table_id() -> TableId; diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs index 7873b794848..a2fd23af34c 100644 --- a/crates/codegen/src/csharp.rs +++ b/crates/codegen/src/csharp.rs @@ -521,9 +521,14 @@ impl Lang for Csharp<'_> { let csharp_table_class_name = csharp_table_name.clone() + "Handle"; let table_type = type_ref_name(module, table.product_type_ref); + let base_class = if table.is_event { + "RemoteEventTableHandle" + } else { + "RemoteTableHandle" + }; writeln!( output, - "public sealed class {csharp_table_class_name} : RemoteTableHandle" + "public sealed class {csharp_table_class_name} : {base_class}" ); indented_block(output, |output| { writeln!( diff --git a/crates/codegen/src/rust.rs b/crates/codegen/src/rust.rs index a55abbbd54d..f4e3ec1996c 100644 --- a/crates/codegen/src/rust.rs +++ b/crates/codegen/src/rust.rs @@ -169,7 +169,50 @@ impl {accessor_trait} for super::RemoteTables {{ }} pub struct {insert_callback_id}(__sdk::CallbackId); -pub struct {delete_callback_id}(__sdk::CallbackId); +" + ); + + if table.is_event { + // Event tables: implement the `EventTable` trait, which exposes only on-insert callbacks, + // not on-delete or on-update. + // on-update callbacks aren't meaningful for event tables, + // as they never have resident rows, so they can never update an existing row. + // on-delete callbacks are meaningful, but exactly equivalent to the on-insert callbacks, + // so not particularly useful. + // Also, don't emit unique index accessors: no resident rows means these would always be empty, + // so no reason to have them. + write!( + out, + " +impl<'ctx> __sdk::EventTable for {table_handle}<'ctx> {{ + type Row = {row_type}; + type EventContext = super::EventContext; + + fn count(&self) -> u64 {{ self.imp.count() }} + fn iter(&self) -> impl Iterator + '_ {{ self.imp.iter() }} + + type InsertCallbackId = {insert_callback_id}; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> {insert_callback_id} {{ + {insert_callback_id}(self.imp.on_insert(Box::new(callback))) + }} + + fn remove_on_insert(&self, callback: {insert_callback_id}) {{ + self.imp.remove_on_insert(callback.0) + }} +}} +" + ); + } else { + // Non-event tables: implement the `Table` trait, which exposes on-insert and on-delete callbacks. + // Also possibly implement `TableWithPrimrayKey`, which exposes on-update callbacks, + // and emit accessors for unique columns. + write!( + out, + "pub struct {delete_callback_id}(__sdk::CallbackId); impl<'ctx> __sdk::Table for {table_handle}<'ctx> {{ type Row = {row_type}; @@ -205,32 +248,15 @@ impl<'ctx> __sdk::Table for {table_handle}<'ctx> {{ }} }} " - ); - - out.delimited_block( - " -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { -", - |out| { - writeln!(out, "let _table = client_cache.get_or_make_table::<{row_type}>({table_name:?});"); - for (unique_field_ident, unique_field_type_use) in iter_unique_cols(module.typespace_for_generate(), &schema, product_def) { - let unique_field_name = unique_field_ident.deref().to_case(Case::Snake); - let unique_field_type = type_name(module, unique_field_type_use); - writeln!( - out, - "_table.add_unique_constraint::<{unique_field_type}>({unique_field_name:?}, |row| &row.{unique_field_name});", - ); - } - }, - "}", - ); + ); - if table.primary_key.is_some() { - let update_callback_id = table_name_pascalcase.clone() + "UpdateCallbackId"; - write!( - out, - " + if table.primary_key.is_some() { + // If the table has a primary key, implement the `TableWithPrimaryKey` trait + // to expose on-update callbacks. + let update_callback_id = table_name_pascalcase.clone() + "UpdateCallbackId"; + write!( + out, + " pub struct {update_callback_id}(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for {table_handle}<'ctx> {{ @@ -248,40 +274,22 @@ impl<'ctx> __sdk::TableWithPrimaryKey for {table_handle}<'ctx> {{ }} }} " - ); - } - - out.newline(); - - write!( - out, - " -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::v2::TableUpdate, -) -> __sdk::Result<__sdk::TableUpdate<{row_type}>> {{ - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {{ - __sdk::InternalError::failed_parse( - \"TableUpdate<{row_type}>\", - \"TableUpdate\", - ).with_cause(e).into() - }}) -}} -" - ); + ); + } - for (unique_field_ident, unique_field_type_use) in - iter_unique_cols(module.typespace_for_generate(), &schema, product_def) - { - let unique_field_name = unique_field_ident.deref().to_case(Case::Snake); - let unique_field_name_pascalcase = unique_field_name.to_case(Case::Pascal); + // Emit unique index accessors for all of the table's unique fields. + for (unique_field_ident, unique_field_type_use) in + iter_unique_cols(module.typespace_for_generate(), &schema, product_def) + { + let unique_field_name = unique_field_ident.deref().to_case(Case::Snake); + let unique_field_name_pascalcase = unique_field_name.to_case(Case::Pascal); - let unique_constraint = table_name_pascalcase.clone() + &unique_field_name_pascalcase + "Unique"; - let unique_field_type = type_name(module, unique_field_type_use); + let unique_constraint = table_name_pascalcase.clone() + &unique_field_name_pascalcase + "Unique"; + let unique_field_type = type_name(module, unique_field_type_use); - write!( - out, - " + write!( + out, + " /// Access to the `{unique_field_name}` unique index on the table `{table_name}`, /// which allows point queries on the field of the same name /// via the [`{unique_constraint}::find`] method. @@ -312,12 +320,52 @@ pub(super) fn parse_table_update( }} }} " - ); + ); + } + + // TODO: expose non-unique indices. } - implement_query_table_accessor(table, out, &row_type).expect("failed to implement query table accessor"); + // Regardless of event-ness, emit `register_table` and `parse_table_update`. + out.delimited_block( + " +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { +", + |out| { + writeln!(out, "let _table = client_cache.get_or_make_table::<{row_type}>({table_name:?});"); + for (unique_field_ident, unique_field_type_use) in iter_unique_cols(module.typespace_for_generate(), &schema, product_def) { + let unique_field_name = unique_field_ident.deref().to_case(Case::Snake); + let unique_field_type = type_name(module, unique_field_type_use); + writeln!( + out, + "_table.add_unique_constraint::<{unique_field_type}>({unique_field_name:?}, |row| &row.{unique_field_name});", + ); + } + }, + "}", + ); - // TODO: expose non-unique indices. + out.newline(); + + write!( + out, + " +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate<{row_type}>> {{ + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {{ + __sdk::InternalError::failed_parse( + \"TableUpdate<{row_type}>\", + \"TableUpdate\", + ).with_cause(e).into() + }}) +}} +" + ); + + implement_query_table_accessor(table, out, &row_type).expect("failed to implement query table accessor"); OutputFile { filename: table_module_name(&table.name) + ".rs", @@ -728,7 +776,17 @@ impl __sdk::__query_builder::HasIxCols for {struct_name} {{ }} }} }}"# - ) + )?; + + // Event tables cannot be used as lookup tables in semijoins. + if !table.is_event { + writeln!( + out, + "\nimpl __sdk::__query_builder::CanBeLookupTable for {struct_name} {{}}" + )?; + } + + Ok(()) } pub fn implement_query_table_accessor(table: &TableDef, out: &mut impl Write, struct_name: &String) -> fmt::Result { @@ -1324,21 +1382,31 @@ impl __sdk::InModule for DbUpdate {{ ", |out| { for table in iter_tables(module, visibility) { - let with_updates = table - .primary_key - .map(|col| { - let pk_field = table.get_column(col).unwrap().name.deref().to_case(Case::Snake); - format!(".with_updates_by_pk(|row| &row.{pk_field})") - }) - .unwrap_or_default(); - let field_name = table_method_name(&table.name); - writeln!( - out, - "diff.{field_name} = cache.apply_diff_to_table::<{}>({:?}, &self.{field_name}){with_updates};", - type_ref_name(module, table.product_type_ref), - table.name.deref(), - ); + if table.is_event { + // Event tables bypass the client cache entirely. + // We construct an applied diff directly from the inserts, + // which will fire on_insert callbacks without storing rows. + writeln!( + out, + "diff.{field_name} = self.{field_name}.into_event_diff();", + ); + } else { + let with_updates = table + .primary_key + .map(|col| { + let pk_field = table.get_column(col).unwrap().name.deref().to_case(Case::Snake); + format!(".with_updates_by_pk(|row| &row.{pk_field})") + }) + .unwrap_or_default(); + + writeln!( + out, + "diff.{field_name} = cache.apply_diff_to_table::<{}>({:?}, &self.{field_name}){with_updates};", + type_ref_name(module, table.product_type_ref), + table.name.deref(), + ); + } } for view in iter_views(module) { let field_name = table_method_name(&view.name); diff --git a/crates/codegen/src/typescript.rs b/crates/codegen/src/typescript.rs index 59c80dfd8ff..32444a82ab6 100644 --- a/crates/codegen/src/typescript.rs +++ b/crates/codegen/src/typescript.rs @@ -260,6 +260,7 @@ impl Lang for TypeScript { &table.name, iter_indexes(table), iter_constraints(table), + table.is_event, ); out.dedent(1); writeln!(out, "}}, {}Row),", table_name_pascalcase); @@ -269,7 +270,7 @@ impl Lang for TypeScript { let view_name_pascalcase = view.name.deref().to_case(Case::Pascal); writeln!(out, "{}: __table({{", view.name); out.indent(1); - write_table_opts(module, out, type_ref, &view.name, iter::empty(), iter::empty()); + write_table_opts(module, out, type_ref, &view.name, iter::empty(), iter::empty(), false); out.dedent(1); writeln!(out, "}}, {}Row),", view_name_pascalcase); } @@ -688,6 +689,7 @@ fn write_table_opts<'a>( name: &Identifier, indexes: impl Iterator, constraints: impl Iterator, + is_event: bool, ) { let product_def = module.typespace_for_generate()[type_ref].as_product().unwrap(); writeln!(out, "name: '{}',", name.deref()); @@ -754,6 +756,9 @@ fn write_table_opts<'a>( } out.dedent(1); writeln!(out, "],"); + if is_event { + writeln!(out, "event: true,"); + } } /// e.g. diff --git a/crates/codegen/tests/snapshots/codegen__codegen_rust.snap b/crates/codegen/tests/snapshots/codegen__codegen_rust.snap index c4889a17bd8..53ea2c7b113 100644 --- a/crates/codegen/tests/snapshots/codegen__codegen_rust.snap +++ b/crates/codegen/tests/snapshots/codegen__codegen_rust.snap @@ -634,6 +634,8 @@ impl __sdk::__query_builder::HasIxCols for HasSpecialStuff { } } +impl __sdk::__query_builder::CanBeLookupTable for HasSpecialStuff {} + ''' "list_over_age_reducer.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -865,14 +867,6 @@ impl<'ctx> __sdk::Table for LoggedOutPlayerTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - - let _table = client_cache.get_or_make_table::("logged_out_player"); - _table.add_unique_constraint::<__sdk::Identity>("identity", |row| &row.identity); - _table.add_unique_constraint::("player_id", |row| &row.player_id); - _table.add_unique_constraint::("name", |row| &row.name); -} pub struct LoggedOutPlayerUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for LoggedOutPlayerTableHandle<'ctx> { @@ -890,19 +884,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for LoggedOutPlayerTableHandle<'ctx> { } } - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::v2::TableUpdate, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse( - "TableUpdate", - "TableUpdate", - ).with_cause(e).into() - }) -} - /// Access to the `identity` unique index on the table `logged_out_player`, /// which allows point queries on the field of the same name /// via the [`LoggedOutPlayerIdentityUnique::find`] method. @@ -993,6 +974,27 @@ pub(super) fn parse_table_update( } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + + let _table = client_cache.get_or_make_table::("logged_out_player"); + _table.add_unique_constraint::<__sdk::Identity>("identity", |row| &row.identity); + _table.add_unique_constraint::("player_id", |row| &row.player_id); + _table.add_unique_constraint::("name", |row| &row.name); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse( + "TableUpdate", + "TableUpdate", + ).with_cause(e).into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `Player`. /// @@ -2256,12 +2258,6 @@ impl<'ctx> __sdk::Table for PersonTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - - let _table = client_cache.get_or_make_table::("person"); - _table.add_unique_constraint::("id", |row| &row.id); -} pub struct PersonUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PersonTableHandle<'ctx> { @@ -2279,19 +2275,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PersonTableHandle<'ctx> { } } - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::v2::TableUpdate, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse( - "TableUpdate", - "TableUpdate", - ).with_cause(e).into() - }) -} - /// Access to the `id` unique index on the table `person`, /// which allows point queries on the field of the same name /// via the [`PersonIdUnique::find`] method. @@ -2322,6 +2305,25 @@ pub(super) fn parse_table_update( } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + + let _table = client_cache.get_or_make_table::("person"); + _table.add_unique_constraint::("id", |row| &row.id); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse( + "TableUpdate", + "TableUpdate", + ).with_cause(e).into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `Person`. /// @@ -2406,6 +2408,8 @@ impl __sdk::__query_builder::HasIxCols for Person { } } +impl __sdk::__query_builder::CanBeLookupTable for Person {} + ''' "pk_multi_identity_type.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -2471,6 +2475,8 @@ impl __sdk::__query_builder::HasIxCols for PkMultiIdentity { } } +impl __sdk::__query_builder::CanBeLookupTable for PkMultiIdentity {} + ''' "player_table.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -2554,14 +2560,6 @@ impl<'ctx> __sdk::Table for PlayerTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - - let _table = client_cache.get_or_make_table::("player"); - _table.add_unique_constraint::<__sdk::Identity>("identity", |row| &row.identity); - _table.add_unique_constraint::("player_id", |row| &row.player_id); - _table.add_unique_constraint::("name", |row| &row.name); -} pub struct PlayerUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PlayerTableHandle<'ctx> { @@ -2579,19 +2577,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PlayerTableHandle<'ctx> { } } - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::v2::TableUpdate, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse( - "TableUpdate", - "TableUpdate", - ).with_cause(e).into() - }) -} - /// Access to the `identity` unique index on the table `player`, /// which allows point queries on the field of the same name /// via the [`PlayerIdentityUnique::find`] method. @@ -2682,6 +2667,27 @@ pub(super) fn parse_table_update( } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + + let _table = client_cache.get_or_make_table::("player"); + _table.add_unique_constraint::<__sdk::Identity>("identity", |row| &row.identity); + _table.add_unique_constraint::("player_id", |row| &row.player_id); + _table.add_unique_constraint::("name", |row| &row.name); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse( + "TableUpdate", + "TableUpdate", + ).with_cause(e).into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `Player`. /// @@ -2768,6 +2774,8 @@ impl __sdk::__query_builder::HasIxCols for Player { } } +impl __sdk::__query_builder::CanBeLookupTable for Player {} + ''' "point_type.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -2829,6 +2837,8 @@ impl __sdk::__query_builder::HasIxCols for Point { } } +impl __sdk::__query_builder::CanBeLookupTable for Point {} + ''' "private_table_type.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -2887,6 +2897,8 @@ impl __sdk::__query_builder::HasIxCols for PrivateTable { } } +impl __sdk::__query_builder::CanBeLookupTable for PrivateTable {} + ''' "query_private_reducer.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -3016,6 +3028,8 @@ impl __sdk::__query_builder::HasIxCols for RemoveTable { } } +impl __sdk::__query_builder::CanBeLookupTable for RemoveTable {} + ''' "repeating_test_arg_type.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -3082,6 +3096,8 @@ impl __sdk::__query_builder::HasIxCols for RepeatingTestArg { } } +impl __sdk::__query_builder::CanBeLookupTable for RepeatingTestArg {} + ''' "return_value_procedure.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -3332,6 +3348,8 @@ impl __sdk::__query_builder::HasIxCols for TestA { } } +impl __sdk::__query_builder::CanBeLookupTable for TestA {} + ''' "test_b_type.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -3605,6 +3623,8 @@ impl __sdk::__query_builder::HasIxCols for TestD { } } +impl __sdk::__query_builder::CanBeLookupTable for TestD {} + ''' "test_e_type.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -3670,6 +3690,8 @@ impl __sdk::__query_builder::HasIxCols for TestE { } } +impl __sdk::__query_builder::CanBeLookupTable for TestE {} + ''' "test_f_table.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -3847,6 +3869,8 @@ impl __sdk::__query_builder::HasIxCols for TestFoobar { } } +impl __sdk::__query_builder::CanBeLookupTable for TestFoobar {} + ''' "test_reducer.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE diff --git a/crates/core/src/subscription/module_subscription_actor.rs b/crates/core/src/subscription/module_subscription_actor.rs index f9d8a4c3663..c3248ae979f 100644 --- a/crates/core/src/subscription/module_subscription_actor.rs +++ b/crates/core/src/subscription/module_subscription_actor.rs @@ -654,6 +654,17 @@ impl ModuleSubscriptions { send_err_msg ); + // V1 clients must not subscribe to event tables. + // Old codegen doesn't understand event tables and would accumulate rows in the client cache. + if query.returns_event_table() { + let _ = send_err_msg( + "Subscribing to event tables requires WebSocket v2. \ + Please upgrade your client SDK and regenerate your module bindings." + .into(), + ); + return Ok((None, false)); + } + let mut_tx = ScopeGuard::::into_inner(mut_tx); let (tx, tx_offset, trapped) = @@ -1312,6 +1323,18 @@ impl ModuleSubscriptions { send_err_msg, (None, false) ); + + // V1 clients must not subscribe to event tables. + // Old codegen doesn't understand event tables and would accumulate rows in the client cache. + if queries.iter().any(|q| q.returns_event_table()) { + send_err_msg( + "Subscribing to event tables requires WebSocket v2. \ + Please upgrade your client SDK and regenerate your module bindings." + .into(), + ); + return Ok((None, false)); + } + let (mut_tx, _) = self.guard_mut_tx(mut_tx, <_>::default()); // We minimize locking so that other clients can add subscriptions concurrently. diff --git a/crates/core/src/subscription/module_subscription_manager.rs b/crates/core/src/subscription/module_subscription_manager.rs index 1e0ebe86e73..4cdacd39ff4 100644 --- a/crates/core/src/subscription/module_subscription_manager.rs +++ b/crates/core/src/subscription/module_subscription_manager.rs @@ -142,6 +142,11 @@ impl Plan { pub fn sql(&self) -> &str { &self.sql } + + /// Does this plan return rows from an event table? + pub fn returns_event_table(&self) -> bool { + self.plans.iter().any(|p| p.returns_event_table()) + } } /// For each client, we hold a handle for sending messages, and we track the queries they are subscribed to. @@ -1405,22 +1410,31 @@ impl SubscriptionManager { updates: &UpdatesRelValue<'_>, metrics: &mut ExecutionMetrics, rlb_pool: &impl RowListBuilderSource, + is_event_table: bool, ) -> TableUpdateRows { - let (deletes, nr_del) = ::encode_list( - rlb_pool.take_row_list_builder(), - updates.deletes.iter(), - ); let (inserts, nr_ins) = ::encode_list( rlb_pool.take_row_list_builder(), updates.inserts.iter(), ); - // TODO: Fix metrics. We only encode once, then we clone for other clients, so this isn't the place - // to report the metrics. - let _num_rows = nr_del + nr_ins; - let num_bytes = deletes.num_bytes() + inserts.num_bytes(); - metrics.bytes_scanned += num_bytes; - metrics.bytes_sent_to_clients += num_bytes; - TableUpdateRows::PersistentTable(ws_v2::PersistentTableRows { inserts, deletes }) + if is_event_table { + // Event tables only have inserts (events); no deletes. + debug_assert!(updates.deletes.is_empty(), "event tables should not produce deletes"); + metrics.bytes_scanned += inserts.num_bytes(); + metrics.bytes_sent_to_clients += inserts.num_bytes(); + TableUpdateRows::EventTable(ws_v2::EventTableRows { events: inserts }) + } else { + let (deletes, nr_del) = ::encode_list( + rlb_pool.take_row_list_builder(), + updates.deletes.iter(), + ); + // TODO: Fix metrics. We only encode once, then we clone for other clients, so this isn't the place + // to report the metrics. + let _num_rows = nr_del + nr_ins; + let num_bytes = deletes.num_bytes() + inserts.num_bytes(); + metrics.bytes_scanned += num_bytes; + metrics.bytes_sent_to_clients += num_bytes; + TableUpdateRows::PersistentTable(ws_v2::PersistentTableRows { inserts, deletes }) + } } let FoldState { updates, errs, metrics } = tables @@ -1468,7 +1482,12 @@ impl SubscriptionManager { } Ok(None) => {} Ok(Some(delta_updates)) => { - let rows = encode_v2_rows(&delta_updates, &mut acc.metrics, bsatn_rlb_pool); + let rows = encode_v2_rows( + &delta_updates, + &mut acc.metrics, + bsatn_rlb_pool, + plan.returns_event_table(), + ); for &(client_id, query_set_id) in qstate.v2_subscriptions.iter() { acc.updates.push(V2ClientUpdate { id: client_id, diff --git a/crates/core/src/subscription/subscription.rs b/crates/core/src/subscription/subscription.rs index 8d24db68a11..b27dd5e1ce1 100644 --- a/crates/core/src/subscription/subscription.rs +++ b/crates/core/src/subscription/subscription.rs @@ -624,7 +624,7 @@ where I: Iterator>, { Ok(get_all_tables(relational_db, tx)? - .filter(|t| t.table_type == StTableType::User && auth.has_read_access(t.table_access)) + .filter(|t| t.table_type == StTableType::User && auth.has_read_access(t.table_access) && !t.is_event) .map(|schema| { let sql = format!("SELECT * FROM {}", schema.table_name); let tx = SchemaViewer::new(tx, auth); @@ -662,7 +662,7 @@ pub(crate) fn legacy_get_all( .get_all_tables(tx)? .iter() .map(Deref::deref) - .filter(|t| t.table_type == StTableType::User && auth.has_read_access(t.table_access)) + .filter(|t| t.table_type == StTableType::User && auth.has_read_access(t.table_access) && !t.is_event) .map(|src| SupportedQuery { kind: query::Supported::Select, expr: QueryExpr::new(src), diff --git a/crates/datastore/src/locking_tx_datastore/datastore.rs b/crates/datastore/src/locking_tx_datastore/datastore.rs index ec63dbcce0e..7741b6e319f 100644 --- a/crates/datastore/src/locking_tx_datastore/datastore.rs +++ b/crates/datastore/src/locking_tx_datastore/datastore.rs @@ -3832,4 +3832,111 @@ mod tests { ); Ok(()) } + + /// Inserting a duplicate primary key within the same transaction should fail for event tables. + #[test] + fn test_event_table_primary_key_enforced_within_tx() -> ResultTest<()> { + let datastore = get_datastore()?; + let mut tx = begin_mut_tx(&datastore); + let mut schema = basic_table_schema_with_indices(basic_indices(), basic_constraints()); + schema.is_event = true; + schema.primary_key = Some(0.into()); // PK on column 0 (id) + let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; + commit(&datastore, tx)?; + + let mut tx = begin_mut_tx(&datastore); + let row1 = u32_str_u32(1, "Alice", 30); + insert(&datastore, &mut tx, table_id, &row1)?; + + // Duplicate PK in same TX should error (unique constraint on col 0). + let row2 = u32_str_u32(1, "Bob", 25); + let result = insert(&datastore, &mut tx, table_id, &row2); + assert!(result.is_err(), "duplicate PK in same TX should be rejected"); + Ok(()) + } + + /// Inserting a duplicate unique column value within the same transaction should fail for event tables. + #[test] + fn test_event_table_unique_constraint_within_tx() -> ResultTest<()> { + let (datastore, tx, table_id) = setup_event_table()?; + commit(&datastore, tx)?; + + let mut tx = begin_mut_tx(&datastore); + let row1 = u32_str_u32(1, "Alice", 30); + insert(&datastore, &mut tx, table_id, &row1)?; + + // Duplicate unique name in same TX should error (unique constraint on col 1). + let row2 = u32_str_u32(2, "Alice", 25); + let result = insert(&datastore, &mut tx, table_id, &row2); + assert!(result.is_err(), "duplicate unique column in same TX should be rejected"); + Ok(()) + } + + /// Btree index lookups should work within a transaction for event tables. + /// We verify this indirectly: if the index works, an update via that index succeeds. + #[test] + fn test_event_table_index_lookup_within_tx() -> ResultTest<()> { + let (datastore, tx, table_id) = setup_event_table()?; + commit(&datastore, tx)?; + + let mut tx = begin_mut_tx(&datastore); + let row1 = u32_str_u32(1, "Alice", 30); + let row2 = u32_str_u32(2, "Bob", 25); + insert(&datastore, &mut tx, table_id, &row1)?; + insert(&datastore, &mut tx, table_id, &row2)?; + + // Update via the btree index on column 0 (id) — this exercises index lookup. + let idx = extract_index_id(&datastore, &tx, &basic_indices()[0])?; + let row1_updated = u32_str_u32(1, "Alice", 31); + update(&datastore, &mut tx, table_id, idx, &row1_updated)?; + + // Verify both rows are visible in the tx. + let rows = all_rows(&datastore, &tx, table_id); + assert_eq!(rows.len(), 2, "should have 2 rows after insert+update"); + assert!(rows.contains(&row1_updated), "updated row should be present"); + assert!(rows.contains(&row2), "other row should be present"); + Ok(()) + } + + /// Auto-increment should generate distinct values within a single transaction for event tables. + #[test] + fn test_event_table_auto_inc_within_tx() -> ResultTest<()> { + let (datastore, tx, table_id) = setup_event_table()?; + commit(&datastore, tx)?; + + let mut tx = begin_mut_tx(&datastore); + // Insert with id=0 to trigger auto_inc on column 0. + let row1 = u32_str_u32(0, "Alice", 30); + let (gen1, _) = insert(&datastore, &mut tx, table_id, &row1)?; + let row2 = u32_str_u32(0, "Bob", 25); + let (gen2, _) = insert(&datastore, &mut tx, table_id, &row2)?; + + // Both auto-incremented ids should be distinct. + assert_ne!(gen1, gen2, "auto_inc should produce distinct values within the same TX"); + Ok(()) + } + + /// Constraints on event tables should reset across transactions (no committed state carryover). + #[test] + fn test_event_table_constraints_reset_across_txs() -> ResultTest<()> { + let (datastore, tx, table_id) = setup_event_table()?; + commit(&datastore, tx)?; + + // TX1: insert row with id=1. + let mut tx1 = begin_mut_tx(&datastore); + let row = u32_str_u32(1, "Alice", 30); + insert(&datastore, &mut tx1, table_id, &row)?; + commit(&datastore, tx1)?; + + // TX2: insert row with same id=1 — should succeed because event tables + // don't carry committed state. + let mut tx2 = begin_mut_tx(&datastore); + let row = u32_str_u32(1, "Bob", 25); + let result = insert(&datastore, &mut tx2, table_id, &row); + assert!( + result.is_ok(), + "same PK in a new TX should succeed for event tables (no committed state)" + ); + Ok(()) + } } diff --git a/crates/physical-plan/src/plan.rs b/crates/physical-plan/src/plan.rs index 92593e293f8..d284c2f76ff 100644 --- a/crates/physical-plan/src/plan.rs +++ b/crates/physical-plan/src/plan.rs @@ -121,6 +121,13 @@ impl ProjectPlan { Self::None(plan) | Self::Name(plan, ..) => plan.reads_from_view(anonymous), } } + + /// Does this plan use an event table as the lookup (rhs) table in a semi-join? + pub fn reads_from_event_table(&self) -> bool { + match self { + Self::None(plan) | Self::Name(plan, ..) => plan.reads_from_event_table(), + } + } } /// Physical plans always terminate with a projection. @@ -228,6 +235,15 @@ impl ProjectListPlan { Self::List(plans, ..) | Self::Agg(plans, ..) => plans.iter().any(|plan| plan.reads_from_view(anonymous)), } } + + /// Does this plan use an event table as the lookup (rhs) table in a semi-join? + pub fn reads_from_event_table(&self) -> bool { + match self { + Self::Limit(plan, _) => plan.reads_from_event_table(), + Self::Name(plans) => plans.iter().any(|plan| plan.reads_from_event_table()), + Self::List(plans, ..) | Self::Agg(plans, ..) => plans.iter().any(|plan| plan.reads_from_event_table()), + } + } } /// Query operators return tuples of rows. @@ -1150,6 +1166,17 @@ impl PhysicalPlan { _ => false, }) } + + /// Does this plan use an event table as the lookup (rhs) table in a semi-join? + /// + /// Note, we only care about index joins because this method is only relevant for subscriptions, + /// and index joins are the only type of join allowed in subscriptions. + pub fn reads_from_event_table(&self) -> bool { + self.any(&|plan| match plan { + Self::IxJoin(join, _) => join.rhs.is_event, + _ => false, + }) + } } /// Scan a table row by row, returning row ids diff --git a/crates/query-builder/src/join.rs b/crates/query-builder/src/join.rs index f72a3942514..e38af5f0248 100644 --- a/crates/query-builder/src/join.rs +++ b/crates/query-builder/src/join.rs @@ -2,7 +2,7 @@ use crate::TableNameStr; use super::{ expr::{format_expr, BoolExpr}, - table::{ColumnRef, HasCols, HasIxCols, Table}, + table::{CanBeLookupTable, ColumnRef, HasCols, HasIxCols, Table}, Query, RawQuery, }; use std::marker::PhantomData; @@ -66,7 +66,7 @@ pub struct RightSemiJoin { } impl Table { - pub fn left_semijoin( + pub fn left_semijoin( self, right: Table, on: impl Fn(&L::IxCols, &R::IxCols) -> IxJoinEq, @@ -80,7 +80,7 @@ impl Table { } } - pub fn right_semijoin( + pub fn right_semijoin( self, right: Table, on: impl Fn(&L::IxCols, &R::IxCols) -> IxJoinEq, @@ -97,7 +97,7 @@ impl Table { } impl super::FromWhere { - pub fn left_semijoin( + pub fn left_semijoin( self, right: Table, on: impl Fn(&L::IxCols, &R::IxCols) -> IxJoinEq, @@ -111,7 +111,7 @@ impl super::FromWhere { } } - pub fn right_semijoin( + pub fn right_semijoin( self, right: Table, on: impl Fn(&L::IxCols, &R::IxCols) -> IxJoinEq, diff --git a/crates/query-builder/src/lib.rs b/crates/query-builder/src/lib.rs index 2621b759487..9b5382967c5 100644 --- a/crates/query-builder/src/lib.rs +++ b/crates/query-builder/src/lib.rs @@ -109,6 +109,8 @@ mod tests { } } } + impl CanBeLookupTable for User {} + impl CanBeLookupTable for Other {} fn norm(s: &str) -> String { s.split_whitespace().collect::>().join(" ") } diff --git a/crates/query-builder/src/table.rs b/crates/query-builder/src/table.rs index e2f126355ac..3d9fb588d93 100644 --- a/crates/query-builder/src/table.rs +++ b/crates/query-builder/src/table.rs @@ -16,6 +16,11 @@ pub trait HasIxCols { fn ix_cols(name: TableNameStr) -> Self::IxCols; } +/// Marker trait for tables that can appear as the right/inner/lookup +/// table in a semi-join. Event tables do NOT implement this trait, +/// preventing them from being used as the lookup side of a join. +pub trait CanBeLookupTable: HasIxCols {} + pub struct Table { pub(super) table_name: TableNameStr, _marker: PhantomData, diff --git a/crates/smoketests/tests/namespaces.rs b/crates/smoketests/tests/namespaces.rs index b9582749e73..96cdd9eab42 100644 --- a/crates/smoketests/tests/namespaces.rs +++ b/crates/smoketests/tests/namespaces.rs @@ -53,8 +53,8 @@ fn test_spacetimedb_ns_csharp() { let namespace = "SpacetimeDB.Types"; assert_eq!( count_matches(tmpdir.path(), &format!("namespace {}", namespace)), - 7, - "Expected 7 occurrences of 'namespace {}'", + 5, + "Expected 5 occurrences of 'namespace {}'", namespace ); assert_eq!( @@ -92,13 +92,13 @@ fn test_custom_ns_csharp() { assert_eq!( count_matches(tmpdir.path(), &format!("namespace {}", namespace)), - 7, - "Expected 7 occurrences of 'namespace {}'", + 5, + "Expected 5 occurrences of 'namespace {}'", namespace ); assert_eq!( count_matches(tmpdir.path(), "using SpacetimeDB;"), - 7, - "Expected 7 occurrences of 'using SpacetimeDB;'" + 5, + "Expected 5 occurrences of 'using SpacetimeDB;'" ); } diff --git a/crates/standalone/src/subcommands/extract_schema.rs b/crates/standalone/src/subcommands/extract_schema.rs index 9b85e57059a..c9b35369957 100644 --- a/crates/standalone/src/subcommands/extract_schema.rs +++ b/crates/standalone/src/subcommands/extract_schema.rs @@ -67,7 +67,7 @@ pub async fn exec(args: &ArgMatches) -> anyhow::Result<()> { let module_def = extract_schema(program_bytes.into(), host_type.into()).await?; - let raw_def = RawModuleDef::V9(module_def.into()); + let raw_def = RawModuleDef::V10(module_def.into()); serde_json::to_writer(std::io::stdout().lock(), &sats::serde::SerdeWrapper(raw_def))?; diff --git a/crates/subscription/src/lib.rs b/crates/subscription/src/lib.rs index 20708a694c2..ca0ef5b63e3 100644 --- a/crates/subscription/src/lib.rs +++ b/crates/subscription/src/lib.rs @@ -340,6 +340,11 @@ impl SubscriptionPlan { self.plan_opt.returns_view_table() } + /// Does this plan return rows from an event table? + pub fn returns_event_table(&self) -> bool { + self.plan_opt.return_table().is_some_and(|schema| schema.is_event) + } + /// The number of columns returned. /// Only relevant if [`Self::is_view`] is true. pub fn num_cols(&self) -> usize { @@ -514,6 +519,10 @@ impl SubscriptionPlan { bail!("Subscriptions require indexes on join columns") } + if plan_opt.reads_from_event_table() { + bail!("Event tables cannot be used as the lookup table in subscription joins") + } + let (table_ids, table_aliases) = table_ids_for_plan(&plan); let fragments = Fragments::compile_from_plan(&plan, &table_aliases, auth)?; diff --git a/demo/Blackholio/client-unity/Assets/Scripts/EntityController.cs b/demo/Blackholio/client-unity/Assets/Scripts/EntityController.cs index 8e23f92a24e..cc960cb3a8b 100644 --- a/demo/Blackholio/client-unity/Assets/Scripts/EntityController.cs +++ b/demo/Blackholio/client-unity/Assets/Scripts/EntityController.cs @@ -44,17 +44,6 @@ public virtual void OnEntityUpdated(Entity newVal) public virtual void OnDelete(EventContext context) { - if (context.Event is SpacetimeDB.Event.Reducer reducer && - reducer.ReducerEvent.Reducer is Reducer.ConsumeEntity consume) - { - var consumerId = consume.Request.ConsumerEntityId; - if (GameManager.Entities.TryGetValue(consumerId, out var consumerEntity)) - { - StartCoroutine(DespawnCoroutine(consumerEntity.transform)); - return; - } - } - Destroy(gameObject); } diff --git a/demo/Blackholio/client-unity/Assets/Scripts/GameManager.cs b/demo/Blackholio/client-unity/Assets/Scripts/GameManager.cs index 37548d7a943..76f32372602 100644 --- a/demo/Blackholio/client-unity/Assets/Scripts/GameManager.cs +++ b/demo/Blackholio/client-unity/Assets/Scripts/GameManager.cs @@ -27,11 +27,14 @@ public class GameManager : MonoBehaviour public static Dictionary Entities = new Dictionary(); public static Dictionary Players = new Dictionary(); + private static HashSet _pendingConsumeAnimations = new(); + private void Start() { // Clear game state in case we've disconnected and reconnected Entities.Clear(); Players.Clear(); + _pendingConsumeAnimations.Clear(); Instance = this; Application.targetFrameRate = 60; @@ -75,6 +78,7 @@ void HandleConnect(DbConnection conn, Identity identity, string token) conn.Db.Food.OnInsert += FoodOnInsert; conn.Db.Player.OnInsert += PlayerOnInsert; conn.Db.Player.OnDelete += PlayerOnDelete; + conn.Db.ConsumeEntityEvent.OnInsert += ConsumeEntityEventOnInsert; OnConnected?.Invoke(); @@ -190,10 +194,25 @@ private static void EntityOnDelete(EventContext context, Entity oldEntity) { if (Entities.Remove(oldEntity.EntityId, out var entityController)) { + if (_pendingConsumeAnimations.Remove(oldEntity.EntityId)) + { + // Already being animated by ConsumeEntityEventOnInsert — don't destroy yet + return; + } entityController.OnDelete(context); } } + private static void ConsumeEntityEventOnInsert(EventContext context, ConsumeEntityEvent evt) + { + if (Entities.TryGetValue(evt.ConsumedEntityId, out var consumedEntity) && + Entities.TryGetValue(evt.ConsumerEntityId, out var consumerEntity)) + { + _pendingConsumeAnimations.Add(evt.ConsumedEntityId); + consumedEntity.StartCoroutine(consumedEntity.DespawnCoroutine(consumerEntity.transform)); + } + } + private static void FoodOnInsert(EventContext context, Food insertedValue) { var entityController = PrefabManager.SpawnFood(insertedValue); diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/CircleDecay.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/CircleDecay.g.cs deleted file mode 100644 index 2006c816d75..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/CircleDecay.g.cs +++ /dev/null @@ -1,67 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteReducers : RemoteBase - { - public delegate void CircleDecayHandler(ReducerEventContext ctx, SpacetimeDB.Types.CircleDecayTimer timer); - public event CircleDecayHandler? OnCircleDecay; - - public void CircleDecay(SpacetimeDB.Types.CircleDecayTimer timer) - { - conn.InternalCallReducer(new Reducer.CircleDecay(timer)); - } - - public bool InvokeCircleDecay(ReducerEventContext ctx, Reducer.CircleDecay args) - { - if (OnCircleDecay == null) - { - if (InternalOnUnhandledReducerError != null) - { - switch (ctx.Event.Status) - { - case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; - case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; - } - } - return false; - } - OnCircleDecay( - ctx, - args.Timer - ); - return true; - } - } - - public abstract partial class Reducer - { - [SpacetimeDB.Type] - [DataContract] - public sealed partial class CircleDecay : Reducer, IReducerArgs - { - [DataMember(Name = "_timer")] - public CircleDecayTimer Timer; - - public CircleDecay(CircleDecayTimer Timer) - { - this.Timer = Timer; - } - - public CircleDecay() - { - this.Timer = new(); - } - - string IReducerArgs.ReducerName => "circle_decay"; - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/CircleRecombine.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/CircleRecombine.g.cs deleted file mode 100644 index 1738c237489..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/CircleRecombine.g.cs +++ /dev/null @@ -1,67 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteReducers : RemoteBase - { - public delegate void CircleRecombineHandler(ReducerEventContext ctx, SpacetimeDB.Types.CircleRecombineTimer timer); - public event CircleRecombineHandler? OnCircleRecombine; - - public void CircleRecombine(SpacetimeDB.Types.CircleRecombineTimer timer) - { - conn.InternalCallReducer(new Reducer.CircleRecombine(timer)); - } - - public bool InvokeCircleRecombine(ReducerEventContext ctx, Reducer.CircleRecombine args) - { - if (OnCircleRecombine == null) - { - if (InternalOnUnhandledReducerError != null) - { - switch (ctx.Event.Status) - { - case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; - case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; - } - } - return false; - } - OnCircleRecombine( - ctx, - args.Timer - ); - return true; - } - } - - public abstract partial class Reducer - { - [SpacetimeDB.Type] - [DataContract] - public sealed partial class CircleRecombine : Reducer, IReducerArgs - { - [DataMember(Name = "timer")] - public CircleRecombineTimer Timer; - - public CircleRecombine(CircleRecombineTimer Timer) - { - this.Timer = Timer; - } - - public CircleRecombine() - { - this.Timer = new(); - } - - string IReducerArgs.ReducerName => "circle_recombine"; - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/CircleRecombine.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/CircleRecombine.g.cs.meta deleted file mode 100644 index 080bb38d655..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/CircleRecombine.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: af62a50bbddd30c4691de48550ecfb23 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/Connect.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/Connect.g.cs deleted file mode 100644 index ed31c1614f3..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/Connect.g.cs +++ /dev/null @@ -1,48 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteReducers : RemoteBase - { - public delegate void ConnectHandler(ReducerEventContext ctx); - public event ConnectHandler? OnConnect; - - public bool InvokeConnect(ReducerEventContext ctx, Reducer.Connect args) - { - if (OnConnect == null) - { - if (InternalOnUnhandledReducerError != null) - { - switch (ctx.Event.Status) - { - case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; - case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; - } - } - return false; - } - OnConnect( - ctx - ); - return true; - } - } - - public abstract partial class Reducer - { - [SpacetimeDB.Type] - [DataContract] - public sealed partial class Connect : Reducer, IReducerArgs - { - string IReducerArgs.ReducerName => "connect"; - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/ConsumeEntity.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/ConsumeEntity.g.cs.meta deleted file mode 100644 index cc8d4c8cc2f..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/ConsumeEntity.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fdd3eba64fff07c4db7d4112a8d1af38 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/Disconnect.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/Disconnect.g.cs deleted file mode 100644 index 4a64b0ad0bd..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/Disconnect.g.cs +++ /dev/null @@ -1,48 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteReducers : RemoteBase - { - public delegate void DisconnectHandler(ReducerEventContext ctx); - public event DisconnectHandler? OnDisconnect; - - public bool InvokeDisconnect(ReducerEventContext ctx, Reducer.Disconnect args) - { - if (OnDisconnect == null) - { - if (InternalOnUnhandledReducerError != null) - { - switch (ctx.Event.Status) - { - case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; - case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; - } - } - return false; - } - OnDisconnect( - ctx - ); - return true; - } - } - - public abstract partial class Reducer - { - [SpacetimeDB.Type] - [DataContract] - public sealed partial class Disconnect : Reducer, IReducerArgs - { - string IReducerArgs.ReducerName => "disconnect"; - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/Disconnect.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/Disconnect.g.cs.meta deleted file mode 100644 index f633768e82a..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/Disconnect.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8e1569d9cfc81fe45bd19a448d7c8777 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/MoveAllPlayers.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/MoveAllPlayers.g.cs deleted file mode 100644 index 3dafd3779bd..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/MoveAllPlayers.g.cs +++ /dev/null @@ -1,67 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteReducers : RemoteBase - { - public delegate void MoveAllPlayersHandler(ReducerEventContext ctx, SpacetimeDB.Types.MoveAllPlayersTimer timer); - public event MoveAllPlayersHandler? OnMoveAllPlayers; - - public void MoveAllPlayers(SpacetimeDB.Types.MoveAllPlayersTimer timer) - { - conn.InternalCallReducer(new Reducer.MoveAllPlayers(timer)); - } - - public bool InvokeMoveAllPlayers(ReducerEventContext ctx, Reducer.MoveAllPlayers args) - { - if (OnMoveAllPlayers == null) - { - if (InternalOnUnhandledReducerError != null) - { - switch (ctx.Event.Status) - { - case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; - case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; - } - } - return false; - } - OnMoveAllPlayers( - ctx, - args.Timer - ); - return true; - } - } - - public abstract partial class Reducer - { - [SpacetimeDB.Type] - [DataContract] - public sealed partial class MoveAllPlayers : Reducer, IReducerArgs - { - [DataMember(Name = "_timer")] - public MoveAllPlayersTimer Timer; - - public MoveAllPlayers(MoveAllPlayersTimer Timer) - { - this.Timer = Timer; - } - - public MoveAllPlayers() - { - this.Timer = new(); - } - - string IReducerArgs.ReducerName => "move_all_players"; - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/MoveAllPlayers.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/MoveAllPlayers.g.cs.meta deleted file mode 100644 index abb234a63c7..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/MoveAllPlayers.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a452ce1270574d34a888a3f16987b74c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/SpawnFood.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/SpawnFood.g.cs deleted file mode 100644 index d7339f061d2..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/SpawnFood.g.cs +++ /dev/null @@ -1,67 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteReducers : RemoteBase - { - public delegate void SpawnFoodHandler(ReducerEventContext ctx, SpacetimeDB.Types.SpawnFoodTimer timer); - public event SpawnFoodHandler? OnSpawnFood; - - public void SpawnFood(SpacetimeDB.Types.SpawnFoodTimer timer) - { - conn.InternalCallReducer(new Reducer.SpawnFood(timer)); - } - - public bool InvokeSpawnFood(ReducerEventContext ctx, Reducer.SpawnFood args) - { - if (OnSpawnFood == null) - { - if (InternalOnUnhandledReducerError != null) - { - switch (ctx.Event.Status) - { - case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; - case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; - } - } - return false; - } - OnSpawnFood( - ctx, - args.Timer - ); - return true; - } - } - - public abstract partial class Reducer - { - [SpacetimeDB.Type] - [DataContract] - public sealed partial class SpawnFood : Reducer, IReducerArgs - { - [DataMember(Name = "_timer")] - public SpawnFoodTimer Timer; - - public SpawnFood(SpawnFoodTimer Timer) - { - this.Timer = Timer; - } - - public SpawnFood() - { - this.Timer = new(); - } - - string IReducerArgs.ReducerName => "spawn_food"; - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/SpawnFood.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/SpawnFood.g.cs.meta deleted file mode 100644 index 12f56b0e854..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/SpawnFood.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 38f8775dc9616e64db7a90f5370de352 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/SpacetimeDBClient.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/SpacetimeDBClient.g.cs index 1dc447a063a..90582de9c72 100644 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/SpacetimeDBClient.g.cs +++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 18e8d1958a9e9cb62ca15cc849d35c1a17f9982c). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). #nullable enable @@ -29,6 +29,7 @@ public RemoteTables(DbConnection conn) { AddTable(Circle = new(conn)); AddTable(Config = new(conn)); + AddTable(ConsumeEntityEvent = new(conn)); AddTable(Entity = new(conn)); AddTable(Food = new(conn)); AddTable(Player = new(conn)); @@ -530,6 +531,7 @@ public sealed class QueryBuilder { new QueryBuilder().From.Circle().ToSql(), new QueryBuilder().From.Config().ToSql(), + new QueryBuilder().From.ConsumeEntityEvent().ToSql(), new QueryBuilder().From.Entity().ToSql(), new QueryBuilder().From.Food().ToSql(), new QueryBuilder().From.Player().ToSql(), @@ -541,6 +543,7 @@ public sealed class From { public global::SpacetimeDB.Table Circle() => new("circle", new CircleCols("circle"), new CircleIxCols("circle")); public global::SpacetimeDB.Table Config() => new("config", new ConfigCols("config"), new ConfigIxCols("config")); + public global::SpacetimeDB.Table ConsumeEntityEvent() => new("consume_entity_event", new ConsumeEntityEventCols("consume_entity_event"), new ConsumeEntityEventIxCols("consume_entity_event")); public global::SpacetimeDB.Table Entity() => new("entity", new EntityCols("entity"), new EntityIxCols("entity")); public global::SpacetimeDB.Table Food() => new("food", new FoodCols("food"), new FoodIxCols("food")); public global::SpacetimeDB.Table Player() => new("player", new PlayerCols("player"), new PlayerIxCols("player")); @@ -625,16 +628,9 @@ protected override bool Dispatch(IReducerEventContext context, Reducer reducer) var eventContext = (ReducerEventContext)context; return reducer switch { - Reducer.CircleDecay args => Reducers.InvokeCircleDecay(eventContext, args), - Reducer.CircleRecombine args => Reducers.InvokeCircleRecombine(eventContext, args), - Reducer.Connect args => Reducers.InvokeConnect(eventContext, args), - Reducer.ConsumeEntity args => Reducers.InvokeConsumeEntity(eventContext, args), - Reducer.Disconnect args => Reducers.InvokeDisconnect(eventContext, args), Reducer.EnterGame args => Reducers.InvokeEnterGame(eventContext, args), - Reducer.MoveAllPlayers args => Reducers.InvokeMoveAllPlayers(eventContext, args), Reducer.PlayerSplit args => Reducers.InvokePlayerSplit(eventContext, args), Reducer.Respawn args => Reducers.InvokeRespawn(eventContext, args), - Reducer.SpawnFood args => Reducers.InvokeSpawnFood(eventContext, args), Reducer.Suicide args => Reducers.InvokeSuicide(eventContext, args), Reducer.UpdatePlayerInput args => Reducers.InvokeUpdatePlayerInput(eventContext, args), _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityEvent.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityEvent.g.cs new file mode 100644 index 00000000000..3bd52a92934 --- /dev/null +++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityEvent.g.cs @@ -0,0 +1,47 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class ConsumeEntityEventHandle : RemoteEventTableHandle + { + protected override string RemoteTableName => "consume_entity_event"; + + internal ConsumeEntityEventHandle(DbConnection conn) : base(conn) + { + } + } + + public readonly ConsumeEntityEventHandle ConsumeEntityEvent; + } + + public sealed class ConsumeEntityEventCols + { + public global::SpacetimeDB.Col ConsumedEntityId { get; } + public global::SpacetimeDB.Col ConsumerEntityId { get; } + + public ConsumeEntityEventCols(string tableName) + { + ConsumedEntityId = new global::SpacetimeDB.Col(tableName, "consumed_entity_id"); + ConsumerEntityId = new global::SpacetimeDB.Col(tableName, "consumer_entity_id"); + } + } + + public sealed class ConsumeEntityEventIxCols + { + + public ConsumeEntityEventIxCols(string tableName) + { + } + } +} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/Connect.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityEvent.g.cs.meta similarity index 83% rename from demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/Connect.g.cs.meta rename to demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityEvent.g.cs.meta index e4947377fb7..85d213972e3 100644 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/Connect.g.cs.meta +++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityEvent.g.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 80093a18a56cbb541a82bdafa8c12ccd +guid: 9a493521b6d6175418bcc2067df0e4ad MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Types/ConsumeEntityEvent.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Types/ConsumeEntityEvent.g.cs new file mode 100644 index 00000000000..66a958137b3 --- /dev/null +++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Types/ConsumeEntityEvent.g.cs @@ -0,0 +1,34 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ConsumeEntityEvent + { + [DataMember(Name = "consumed_entity_id")] + public int ConsumedEntityId; + [DataMember(Name = "consumer_entity_id")] + public int ConsumerEntityId; + + public ConsumeEntityEvent( + int ConsumedEntityId, + int ConsumerEntityId + ) + { + this.ConsumedEntityId = ConsumedEntityId; + this.ConsumerEntityId = ConsumerEntityId; + } + + public ConsumeEntityEvent() + { + } + } +} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/CircleDecay.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Types/ConsumeEntityEvent.g.cs.meta similarity index 83% rename from demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/CircleDecay.g.cs.meta rename to demo/Blackholio/client-unity/Assets/Scripts/autogen/Types/ConsumeEntityEvent.g.cs.meta index fbedf95edf4..cffc58f8e14 100644 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/CircleDecay.g.cs.meta +++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Types/ConsumeEntityEvent.g.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: ac1b2381309d41e4aa05575b5e1181ba +guid: a89671ae0e12ca84bb48321262377eab MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/SpacetimeDBClient.g.cpp index cb9ada83974..471fac9e789 100644 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/SpacetimeDBClient.g.cpp +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -14,48 +14,12 @@ static FReducer DecodeReducer(const FReducerEvent& Event) { const FString& ReducerName = Event.ReducerCall.ReducerName; - if (ReducerName == TEXT("circle_decay")) - { - FCircleDecayArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); - return FReducer::CircleDecay(Args); - } - - if (ReducerName == TEXT("circle_recombine")) - { - FCircleRecombineArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); - return FReducer::CircleRecombine(Args); - } - - if (ReducerName == TEXT("connect")) - { - FConnectArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); - return FReducer::Connect(Args); - } - - if (ReducerName == TEXT("consume_entity")) - { - FConsumeEntityArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); - return FReducer::ConsumeEntity(Args); - } - - if (ReducerName == TEXT("disconnect")) - { - FDisconnectArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); - return FReducer::Disconnect(Args); - } - if (ReducerName == TEXT("enter_game")) { FEnterGameArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); return FReducer::EnterGame(Args); } - if (ReducerName == TEXT("move_all_players")) - { - FMoveAllPlayersArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); - return FReducer::MoveAllPlayers(Args); - } - if (ReducerName == TEXT("player_split")) { FPlayerSplitArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); @@ -68,12 +32,6 @@ static FReducer DecodeReducer(const FReducerEvent& Event) return FReducer::Respawn(Args); } - if (ReducerName == TEXT("spawn_food")) - { - FSpawnFoodArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); - return FReducer::SpawnFood(Args); - } - if (ReducerName == TEXT("suicide")) { FSuicideArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); @@ -159,34 +117,10 @@ void URemoteTables::Initialize() /**/ } -void USetReducerFlags::CircleDecay(ECallReducerFlags Flag) -{ - FlagMap.Add("CircleDecay", Flag); -} -void USetReducerFlags::CircleRecombine(ECallReducerFlags Flag) -{ - FlagMap.Add("CircleRecombine", Flag); -} -void USetReducerFlags::Connect(ECallReducerFlags Flag) -{ - FlagMap.Add("Connect", Flag); -} -void USetReducerFlags::ConsumeEntity(ECallReducerFlags Flag) -{ - FlagMap.Add("ConsumeEntity", Flag); -} -void USetReducerFlags::Disconnect(ECallReducerFlags Flag) -{ - FlagMap.Add("Disconnect", Flag); -} void USetReducerFlags::EnterGame(ECallReducerFlags Flag) { FlagMap.Add("EnterGame", Flag); } -void USetReducerFlags::MoveAllPlayers(ECallReducerFlags Flag) -{ - FlagMap.Add("MoveAllPlayers", Flag); -} void USetReducerFlags::PlayerSplit(ECallReducerFlags Flag) { FlagMap.Add("PlayerSplit", Flag); @@ -195,10 +129,6 @@ void USetReducerFlags::Respawn(ECallReducerFlags Flag) { FlagMap.Add("Respawn", Flag); } -void USetReducerFlags::SpawnFood(ECallReducerFlags Flag) -{ - FlagMap.Add("SpawnFood", Flag); -} void USetReducerFlags::Suicide(ECallReducerFlags Flag) { FlagMap.Add("Suicide", Flag); @@ -208,226 +138,6 @@ void USetReducerFlags::UpdatePlayerInput(ECallReducerFlags Flag) FlagMap.Add("UpdatePlayerInput", Flag); } -void URemoteReducers::CircleDecay(const FCircleDecayTimerType& Timer) -{ - if (!Conn) - { - UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); - return; - } - - Conn->CallReducerTyped(TEXT("circle_decay"), FCircleDecayArgs(Timer), SetCallReducerFlags); -} - -bool URemoteReducers::InvokeCircleDecay(const FReducerEventContext& Context, const UCircleDecayReducer* Args) -{ - if (!OnCircleDecay.IsBound()) - { - // Handle unhandled reducer error - if (InternalOnUnhandledReducerError.IsBound()) - { - // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases - // For now, just broadcast any error - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for CircleDecay")); - } - return false; - } - - OnCircleDecay.Broadcast(Context, Args->Timer); - return true; -} - -bool URemoteReducers::InvokeCircleDecayWithArgs(const FReducerEventContext& Context, const FCircleDecayArgs& Args) -{ - if (!OnCircleDecay.IsBound()) - { - if (InternalOnUnhandledReducerError.IsBound()) - { - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for CircleDecay")); - } - return false; - } - - OnCircleDecay.Broadcast(Context, Args.Timer); - return true; -} - -void URemoteReducers::CircleRecombine(const FCircleRecombineTimerType& Timer) -{ - if (!Conn) - { - UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); - return; - } - - Conn->CallReducerTyped(TEXT("circle_recombine"), FCircleRecombineArgs(Timer), SetCallReducerFlags); -} - -bool URemoteReducers::InvokeCircleRecombine(const FReducerEventContext& Context, const UCircleRecombineReducer* Args) -{ - if (!OnCircleRecombine.IsBound()) - { - // Handle unhandled reducer error - if (InternalOnUnhandledReducerError.IsBound()) - { - // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases - // For now, just broadcast any error - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for CircleRecombine")); - } - return false; - } - - OnCircleRecombine.Broadcast(Context, Args->Timer); - return true; -} - -bool URemoteReducers::InvokeCircleRecombineWithArgs(const FReducerEventContext& Context, const FCircleRecombineArgs& Args) -{ - if (!OnCircleRecombine.IsBound()) - { - if (InternalOnUnhandledReducerError.IsBound()) - { - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for CircleRecombine")); - } - return false; - } - - OnCircleRecombine.Broadcast(Context, Args.Timer); - return true; -} - -void URemoteReducers::Connect() -{ - if (!Conn) - { - UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); - return; - } - - Conn->CallReducerTyped(TEXT("connect"), FConnectArgs(), SetCallReducerFlags); -} - -bool URemoteReducers::InvokeConnect(const FReducerEventContext& Context, const UConnectReducer* Args) -{ - if (!OnConnect.IsBound()) - { - // Handle unhandled reducer error - if (InternalOnUnhandledReducerError.IsBound()) - { - // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases - // For now, just broadcast any error - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for Connect")); - } - return false; - } - - OnConnect.Broadcast(Context); - return true; -} - -bool URemoteReducers::InvokeConnectWithArgs(const FReducerEventContext& Context, const FConnectArgs& Args) -{ - if (!OnConnect.IsBound()) - { - if (InternalOnUnhandledReducerError.IsBound()) - { - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for Connect")); - } - return false; - } - - OnConnect.Broadcast(Context); - return true; -} - -void URemoteReducers::ConsumeEntity(const FConsumeEntityTimerType& Request) -{ - if (!Conn) - { - UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); - return; - } - - Conn->CallReducerTyped(TEXT("consume_entity"), FConsumeEntityArgs(Request), SetCallReducerFlags); -} - -bool URemoteReducers::InvokeConsumeEntity(const FReducerEventContext& Context, const UConsumeEntityReducer* Args) -{ - if (!OnConsumeEntity.IsBound()) - { - // Handle unhandled reducer error - if (InternalOnUnhandledReducerError.IsBound()) - { - // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases - // For now, just broadcast any error - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for ConsumeEntity")); - } - return false; - } - - OnConsumeEntity.Broadcast(Context, Args->Request); - return true; -} - -bool URemoteReducers::InvokeConsumeEntityWithArgs(const FReducerEventContext& Context, const FConsumeEntityArgs& Args) -{ - if (!OnConsumeEntity.IsBound()) - { - if (InternalOnUnhandledReducerError.IsBound()) - { - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for ConsumeEntity")); - } - return false; - } - - OnConsumeEntity.Broadcast(Context, Args.Request); - return true; -} - -void URemoteReducers::Disconnect() -{ - if (!Conn) - { - UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); - return; - } - - Conn->CallReducerTyped(TEXT("disconnect"), FDisconnectArgs(), SetCallReducerFlags); -} - -bool URemoteReducers::InvokeDisconnect(const FReducerEventContext& Context, const UDisconnectReducer* Args) -{ - if (!OnDisconnect.IsBound()) - { - // Handle unhandled reducer error - if (InternalOnUnhandledReducerError.IsBound()) - { - // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases - // For now, just broadcast any error - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for Disconnect")); - } - return false; - } - - OnDisconnect.Broadcast(Context); - return true; -} - -bool URemoteReducers::InvokeDisconnectWithArgs(const FReducerEventContext& Context, const FDisconnectArgs& Args) -{ - if (!OnDisconnect.IsBound()) - { - if (InternalOnUnhandledReducerError.IsBound()) - { - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for Disconnect")); - } - return false; - } - - OnDisconnect.Broadcast(Context); - return true; -} - void URemoteReducers::EnterGame(const FString& Name) { if (!Conn) @@ -472,50 +182,6 @@ bool URemoteReducers::InvokeEnterGameWithArgs(const FReducerEventContext& Contex return true; } -void URemoteReducers::MoveAllPlayers(const FMoveAllPlayersTimerType& Timer) -{ - if (!Conn) - { - UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); - return; - } - - Conn->CallReducerTyped(TEXT("move_all_players"), FMoveAllPlayersArgs(Timer), SetCallReducerFlags); -} - -bool URemoteReducers::InvokeMoveAllPlayers(const FReducerEventContext& Context, const UMoveAllPlayersReducer* Args) -{ - if (!OnMoveAllPlayers.IsBound()) - { - // Handle unhandled reducer error - if (InternalOnUnhandledReducerError.IsBound()) - { - // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases - // For now, just broadcast any error - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for MoveAllPlayers")); - } - return false; - } - - OnMoveAllPlayers.Broadcast(Context, Args->Timer); - return true; -} - -bool URemoteReducers::InvokeMoveAllPlayersWithArgs(const FReducerEventContext& Context, const FMoveAllPlayersArgs& Args) -{ - if (!OnMoveAllPlayers.IsBound()) - { - if (InternalOnUnhandledReducerError.IsBound()) - { - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for MoveAllPlayers")); - } - return false; - } - - OnMoveAllPlayers.Broadcast(Context, Args.Timer); - return true; -} - void URemoteReducers::PlayerSplit() { if (!Conn) @@ -604,50 +270,6 @@ bool URemoteReducers::InvokeRespawnWithArgs(const FReducerEventContext& Context, return true; } -void URemoteReducers::SpawnFood(const FSpawnFoodTimerType& Timer) -{ - if (!Conn) - { - UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); - return; - } - - Conn->CallReducerTyped(TEXT("spawn_food"), FSpawnFoodArgs(Timer), SetCallReducerFlags); -} - -bool URemoteReducers::InvokeSpawnFood(const FReducerEventContext& Context, const USpawnFoodReducer* Args) -{ - if (!OnSpawnFood.IsBound()) - { - // Handle unhandled reducer error - if (InternalOnUnhandledReducerError.IsBound()) - { - // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases - // For now, just broadcast any error - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for SpawnFood")); - } - return false; - } - - OnSpawnFood.Broadcast(Context, Args->Timer); - return true; -} - -bool URemoteReducers::InvokeSpawnFoodWithArgs(const FReducerEventContext& Context, const FSpawnFoodArgs& Args) -{ - if (!OnSpawnFood.IsBound()) - { - if (InternalOnUnhandledReducerError.IsBound()) - { - InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for SpawnFood")); - } - return false; - } - - OnSpawnFood.Broadcast(Context, Args.Timer); - return true; -} - void URemoteReducers::Suicide() { if (!Conn) @@ -790,48 +412,12 @@ void UDbConnection::ReducerEvent(const FReducerEvent& Event) // Use hardcoded string matching for reducer dispatching const FString& ReducerName = Event.ReducerCall.ReducerName; - if (ReducerName == TEXT("circle_decay")) - { - FCircleDecayArgs Args = ReducerEvent.Reducer.GetAsCircleDecay(); - Reducers->InvokeCircleDecayWithArgs(Context, Args); - return; - } - if (ReducerName == TEXT("circle_recombine")) - { - FCircleRecombineArgs Args = ReducerEvent.Reducer.GetAsCircleRecombine(); - Reducers->InvokeCircleRecombineWithArgs(Context, Args); - return; - } - if (ReducerName == TEXT("connect")) - { - FConnectArgs Args = ReducerEvent.Reducer.GetAsConnect(); - Reducers->InvokeConnectWithArgs(Context, Args); - return; - } - if (ReducerName == TEXT("consume_entity")) - { - FConsumeEntityArgs Args = ReducerEvent.Reducer.GetAsConsumeEntity(); - Reducers->InvokeConsumeEntityWithArgs(Context, Args); - return; - } - if (ReducerName == TEXT("disconnect")) - { - FDisconnectArgs Args = ReducerEvent.Reducer.GetAsDisconnect(); - Reducers->InvokeDisconnectWithArgs(Context, Args); - return; - } if (ReducerName == TEXT("enter_game")) { FEnterGameArgs Args = ReducerEvent.Reducer.GetAsEnterGame(); Reducers->InvokeEnterGameWithArgs(Context, Args); return; } - if (ReducerName == TEXT("move_all_players")) - { - FMoveAllPlayersArgs Args = ReducerEvent.Reducer.GetAsMoveAllPlayers(); - Reducers->InvokeMoveAllPlayersWithArgs(Context, Args); - return; - } if (ReducerName == TEXT("player_split")) { FPlayerSplitArgs Args = ReducerEvent.Reducer.GetAsPlayerSplit(); @@ -844,12 +430,6 @@ void UDbConnection::ReducerEvent(const FReducerEvent& Event) Reducers->InvokeRespawnWithArgs(Context, Args); return; } - if (ReducerName == TEXT("spawn_food")) - { - FSpawnFoodArgs Args = ReducerEvent.Reducer.GetAsSpawnFood(); - Reducers->InvokeSpawnFoodWithArgs(Context, Args); - return; - } if (ReducerName == TEXT("suicide")) { FSuicideArgs Args = ReducerEvent.Reducer.GetAsSuicide(); diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/CircleDecay.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/CircleDecay.g.h deleted file mode 100644 index d2f2106c566..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/CircleDecay.g.h +++ /dev/null @@ -1,54 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#pragma once -#include "CoreMinimal.h" -#include "BSATN/UESpacetimeDB.h" -#include "ModuleBindings/ReducerBase.g.h" -#include "ModuleBindings/Types/CircleDecayTimerType.g.h" -#include "CircleDecay.g.generated.h" - -// Reducer arguments struct for CircleDecay -USTRUCT(BlueprintType) -struct CLIENT_UNREAL_API FCircleDecayArgs -{ - GENERATED_BODY() - - UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") - FCircleDecayTimerType Timer; - - FCircleDecayArgs() = default; - - FCircleDecayArgs(const FCircleDecayTimerType& InTimer) - : Timer(InTimer) - {} - - - FORCEINLINE bool operator==(const FCircleDecayArgs& Other) const - { - return Timer == Other.Timer; - } - FORCEINLINE bool operator!=(const FCircleDecayArgs& Other) const - { - return !(*this == Other); - } -}; - -namespace UE::SpacetimeDB -{ - UE_SPACETIMEDB_STRUCT(FCircleDecayArgs, Timer); -} - -// Reducer class for internal dispatching -UCLASS(BlueprintType) -class CLIENT_UNREAL_API UCircleDecayReducer : public UReducerBase -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - FCircleDecayTimerType Timer; - -}; - - diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/CircleRecombine.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/CircleRecombine.g.h deleted file mode 100644 index 411925d3334..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/CircleRecombine.g.h +++ /dev/null @@ -1,54 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#pragma once -#include "CoreMinimal.h" -#include "BSATN/UESpacetimeDB.h" -#include "ModuleBindings/ReducerBase.g.h" -#include "ModuleBindings/Types/CircleRecombineTimerType.g.h" -#include "CircleRecombine.g.generated.h" - -// Reducer arguments struct for CircleRecombine -USTRUCT(BlueprintType) -struct CLIENT_UNREAL_API FCircleRecombineArgs -{ - GENERATED_BODY() - - UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") - FCircleRecombineTimerType Timer; - - FCircleRecombineArgs() = default; - - FCircleRecombineArgs(const FCircleRecombineTimerType& InTimer) - : Timer(InTimer) - {} - - - FORCEINLINE bool operator==(const FCircleRecombineArgs& Other) const - { - return Timer == Other.Timer; - } - FORCEINLINE bool operator!=(const FCircleRecombineArgs& Other) const - { - return !(*this == Other); - } -}; - -namespace UE::SpacetimeDB -{ - UE_SPACETIMEDB_STRUCT(FCircleRecombineArgs, Timer); -} - -// Reducer class for internal dispatching -UCLASS(BlueprintType) -class CLIENT_UNREAL_API UCircleRecombineReducer : public UReducerBase -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - FCircleRecombineTimerType Timer; - -}; - - diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Connect.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Connect.g.h deleted file mode 100644 index 3f4aa4d29d0..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Connect.g.h +++ /dev/null @@ -1,43 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#pragma once -#include "CoreMinimal.h" -#include "BSATN/UESpacetimeDB.h" -#include "ModuleBindings/ReducerBase.g.h" -#include "Connect.g.generated.h" - -// Reducer arguments struct for Connect -USTRUCT(BlueprintType) -struct CLIENT_UNREAL_API FConnectArgs -{ - GENERATED_BODY() - - FConnectArgs() = default; - - - FORCEINLINE bool operator==(const FConnectArgs& Other) const - { - return true; - } - FORCEINLINE bool operator!=(const FConnectArgs& Other) const - { - return !(*this == Other); - } -}; - -namespace UE::SpacetimeDB -{ - UE_SPACETIMEDB_STRUCT_EMPTY(FConnectArgs); -} - -// Reducer class for internal dispatching -UCLASS(BlueprintType) -class CLIENT_UNREAL_API UConnectReducer : public UReducerBase -{ - GENERATED_BODY() - -public: -}; - - diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/ConsumeEntity.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/ConsumeEntity.g.h deleted file mode 100644 index c51fb1909da..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/ConsumeEntity.g.h +++ /dev/null @@ -1,54 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#pragma once -#include "CoreMinimal.h" -#include "BSATN/UESpacetimeDB.h" -#include "ModuleBindings/ReducerBase.g.h" -#include "ModuleBindings/Types/ConsumeEntityTimerType.g.h" -#include "ConsumeEntity.g.generated.h" - -// Reducer arguments struct for ConsumeEntity -USTRUCT(BlueprintType) -struct CLIENT_UNREAL_API FConsumeEntityArgs -{ - GENERATED_BODY() - - UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") - FConsumeEntityTimerType Request; - - FConsumeEntityArgs() = default; - - FConsumeEntityArgs(const FConsumeEntityTimerType& InRequest) - : Request(InRequest) - {} - - - FORCEINLINE bool operator==(const FConsumeEntityArgs& Other) const - { - return Request == Other.Request; - } - FORCEINLINE bool operator!=(const FConsumeEntityArgs& Other) const - { - return !(*this == Other); - } -}; - -namespace UE::SpacetimeDB -{ - UE_SPACETIMEDB_STRUCT(FConsumeEntityArgs, Request); -} - -// Reducer class for internal dispatching -UCLASS(BlueprintType) -class CLIENT_UNREAL_API UConsumeEntityReducer : public UReducerBase -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - FConsumeEntityTimerType Request; - -}; - - diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Disconnect.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Disconnect.g.h deleted file mode 100644 index 1149cdb400e..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Disconnect.g.h +++ /dev/null @@ -1,43 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#pragma once -#include "CoreMinimal.h" -#include "BSATN/UESpacetimeDB.h" -#include "ModuleBindings/ReducerBase.g.h" -#include "Disconnect.g.generated.h" - -// Reducer arguments struct for Disconnect -USTRUCT(BlueprintType) -struct CLIENT_UNREAL_API FDisconnectArgs -{ - GENERATED_BODY() - - FDisconnectArgs() = default; - - - FORCEINLINE bool operator==(const FDisconnectArgs& Other) const - { - return true; - } - FORCEINLINE bool operator!=(const FDisconnectArgs& Other) const - { - return !(*this == Other); - } -}; - -namespace UE::SpacetimeDB -{ - UE_SPACETIMEDB_STRUCT_EMPTY(FDisconnectArgs); -} - -// Reducer class for internal dispatching -UCLASS(BlueprintType) -class CLIENT_UNREAL_API UDisconnectReducer : public UReducerBase -{ - GENERATED_BODY() - -public: -}; - - diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/MoveAllPlayers.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/MoveAllPlayers.g.h deleted file mode 100644 index 421c680f6ee..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/MoveAllPlayers.g.h +++ /dev/null @@ -1,54 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#pragma once -#include "CoreMinimal.h" -#include "BSATN/UESpacetimeDB.h" -#include "ModuleBindings/ReducerBase.g.h" -#include "ModuleBindings/Types/MoveAllPlayersTimerType.g.h" -#include "MoveAllPlayers.g.generated.h" - -// Reducer arguments struct for MoveAllPlayers -USTRUCT(BlueprintType) -struct CLIENT_UNREAL_API FMoveAllPlayersArgs -{ - GENERATED_BODY() - - UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") - FMoveAllPlayersTimerType Timer; - - FMoveAllPlayersArgs() = default; - - FMoveAllPlayersArgs(const FMoveAllPlayersTimerType& InTimer) - : Timer(InTimer) - {} - - - FORCEINLINE bool operator==(const FMoveAllPlayersArgs& Other) const - { - return Timer == Other.Timer; - } - FORCEINLINE bool operator!=(const FMoveAllPlayersArgs& Other) const - { - return !(*this == Other); - } -}; - -namespace UE::SpacetimeDB -{ - UE_SPACETIMEDB_STRUCT(FMoveAllPlayersArgs, Timer); -} - -// Reducer class for internal dispatching -UCLASS(BlueprintType) -class CLIENT_UNREAL_API UMoveAllPlayersReducer : public UReducerBase -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - FMoveAllPlayersTimerType Timer; - -}; - - diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/SpawnFood.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/SpawnFood.g.h deleted file mode 100644 index f3aaaa6c777..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/SpawnFood.g.h +++ /dev/null @@ -1,54 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#pragma once -#include "CoreMinimal.h" -#include "BSATN/UESpacetimeDB.h" -#include "ModuleBindings/ReducerBase.g.h" -#include "ModuleBindings/Types/SpawnFoodTimerType.g.h" -#include "SpawnFood.g.generated.h" - -// Reducer arguments struct for SpawnFood -USTRUCT(BlueprintType) -struct CLIENT_UNREAL_API FSpawnFoodArgs -{ - GENERATED_BODY() - - UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") - FSpawnFoodTimerType Timer; - - FSpawnFoodArgs() = default; - - FSpawnFoodArgs(const FSpawnFoodTimerType& InTimer) - : Timer(InTimer) - {} - - - FORCEINLINE bool operator==(const FSpawnFoodArgs& Other) const - { - return Timer == Other.Timer; - } - FORCEINLINE bool operator!=(const FSpawnFoodArgs& Other) const - { - return !(*this == Other); - } -}; - -namespace UE::SpacetimeDB -{ - UE_SPACETIMEDB_STRUCT(FSpawnFoodArgs, Timer); -} - -// Reducer class for internal dispatching -UCLASS(BlueprintType) -class CLIENT_UNREAL_API USpawnFoodReducer : public UReducerBase -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - FSpawnFoodTimerType Timer; - -}; - - diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/SpacetimeDBClient.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/SpacetimeDBClient.g.h index 8092d9eb856..0ba004f7427 100644 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.12.0 (commit 5da121d888d60ce178c202e54816252d2e4d4451). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). #pragma once #include "CoreMinimal.h" @@ -13,24 +13,12 @@ #include "Connection/Subscription.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "ModuleBindings/ReducerBase.g.h" -#include "ModuleBindings/Reducers/CircleDecay.g.h" -#include "ModuleBindings/Reducers/CircleRecombine.g.h" -#include "ModuleBindings/Reducers/Connect.g.h" -#include "ModuleBindings/Reducers/ConsumeEntity.g.h" -#include "ModuleBindings/Reducers/Disconnect.g.h" #include "ModuleBindings/Reducers/EnterGame.g.h" -#include "ModuleBindings/Reducers/MoveAllPlayers.g.h" #include "ModuleBindings/Reducers/PlayerSplit.g.h" #include "ModuleBindings/Reducers/Respawn.g.h" -#include "ModuleBindings/Reducers/SpawnFood.g.h" #include "ModuleBindings/Reducers/Suicide.g.h" #include "ModuleBindings/Reducers/UpdatePlayerInput.g.h" -#include "ModuleBindings/Types/CircleDecayTimerType.g.h" -#include "ModuleBindings/Types/CircleRecombineTimerType.g.h" -#include "ModuleBindings/Types/ConsumeEntityTimerType.g.h" #include "ModuleBindings/Types/DbVector2Type.g.h" -#include "ModuleBindings/Types/MoveAllPlayersTimerType.g.h" -#include "ModuleBindings/Types/SpawnFoodTimerType.g.h" #include "Types/Builtins.h" #include "SpacetimeDBClient.g.generated.h" @@ -123,16 +111,9 @@ class CLIENT_UNREAL_API UContextBaseBpLib : public UBlueprintFunctionLibrary UENUM(BlueprintType, Category = "SpacetimeDB") enum class EReducerTag : uint8 { - CircleDecay, - CircleRecombine, - Connect, - ConsumeEntity, - Disconnect, EnterGame, - MoveAllPlayers, PlayerSplit, Respawn, - SpawnFood, Suicide, UpdatePlayerInput }; @@ -146,7 +127,7 @@ struct CLIENT_UNREAL_API FReducer UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") EReducerTag Tag = static_cast(0); - TVariant Data; + TVariant Data; // Optional metadata UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") @@ -154,86 +135,6 @@ struct CLIENT_UNREAL_API FReducer uint32 ReducerId = 0; uint32 RequestId = 0; - static FReducer CircleDecay(const FCircleDecayArgs& Value) - { - FReducer Out; - Out.Tag = EReducerTag::CircleDecay; - Out.Data.Set(Value); - Out.ReducerName = TEXT("circle_decay"); - return Out; - } - - FORCEINLINE bool IsCircleDecay() const { return Tag == EReducerTag::CircleDecay; } - FORCEINLINE FCircleDecayArgs GetAsCircleDecay() const - { - ensureMsgf(IsCircleDecay(), TEXT("Reducer does not hold CircleDecay!")); - return Data.Get(); - } - - static FReducer CircleRecombine(const FCircleRecombineArgs& Value) - { - FReducer Out; - Out.Tag = EReducerTag::CircleRecombine; - Out.Data.Set(Value); - Out.ReducerName = TEXT("circle_recombine"); - return Out; - } - - FORCEINLINE bool IsCircleRecombine() const { return Tag == EReducerTag::CircleRecombine; } - FORCEINLINE FCircleRecombineArgs GetAsCircleRecombine() const - { - ensureMsgf(IsCircleRecombine(), TEXT("Reducer does not hold CircleRecombine!")); - return Data.Get(); - } - - static FReducer Connect(const FConnectArgs& Value) - { - FReducer Out; - Out.Tag = EReducerTag::Connect; - Out.Data.Set(Value); - Out.ReducerName = TEXT("connect"); - return Out; - } - - FORCEINLINE bool IsConnect() const { return Tag == EReducerTag::Connect; } - FORCEINLINE FConnectArgs GetAsConnect() const - { - ensureMsgf(IsConnect(), TEXT("Reducer does not hold Connect!")); - return Data.Get(); - } - - static FReducer ConsumeEntity(const FConsumeEntityArgs& Value) - { - FReducer Out; - Out.Tag = EReducerTag::ConsumeEntity; - Out.Data.Set(Value); - Out.ReducerName = TEXT("consume_entity"); - return Out; - } - - FORCEINLINE bool IsConsumeEntity() const { return Tag == EReducerTag::ConsumeEntity; } - FORCEINLINE FConsumeEntityArgs GetAsConsumeEntity() const - { - ensureMsgf(IsConsumeEntity(), TEXT("Reducer does not hold ConsumeEntity!")); - return Data.Get(); - } - - static FReducer Disconnect(const FDisconnectArgs& Value) - { - FReducer Out; - Out.Tag = EReducerTag::Disconnect; - Out.Data.Set(Value); - Out.ReducerName = TEXT("disconnect"); - return Out; - } - - FORCEINLINE bool IsDisconnect() const { return Tag == EReducerTag::Disconnect; } - FORCEINLINE FDisconnectArgs GetAsDisconnect() const - { - ensureMsgf(IsDisconnect(), TEXT("Reducer does not hold Disconnect!")); - return Data.Get(); - } - static FReducer EnterGame(const FEnterGameArgs& Value) { FReducer Out; @@ -250,22 +151,6 @@ struct CLIENT_UNREAL_API FReducer return Data.Get(); } - static FReducer MoveAllPlayers(const FMoveAllPlayersArgs& Value) - { - FReducer Out; - Out.Tag = EReducerTag::MoveAllPlayers; - Out.Data.Set(Value); - Out.ReducerName = TEXT("move_all_players"); - return Out; - } - - FORCEINLINE bool IsMoveAllPlayers() const { return Tag == EReducerTag::MoveAllPlayers; } - FORCEINLINE FMoveAllPlayersArgs GetAsMoveAllPlayers() const - { - ensureMsgf(IsMoveAllPlayers(), TEXT("Reducer does not hold MoveAllPlayers!")); - return Data.Get(); - } - static FReducer PlayerSplit(const FPlayerSplitArgs& Value) { FReducer Out; @@ -298,22 +183,6 @@ struct CLIENT_UNREAL_API FReducer return Data.Get(); } - static FReducer SpawnFood(const FSpawnFoodArgs& Value) - { - FReducer Out; - Out.Tag = EReducerTag::SpawnFood; - Out.Data.Set(Value); - Out.ReducerName = TEXT("spawn_food"); - return Out; - } - - FORCEINLINE bool IsSpawnFood() const { return Tag == EReducerTag::SpawnFood; } - FORCEINLINE FSpawnFoodArgs GetAsSpawnFood() const - { - ensureMsgf(IsSpawnFood(), TEXT("Reducer does not hold SpawnFood!")); - return Data.Get(); - } - static FReducer Suicide(const FSuicideArgs& Value) { FReducer Out; @@ -351,26 +220,12 @@ struct CLIENT_UNREAL_API FReducer if (Tag != Other.Tag || ReducerId != Other.ReducerId || RequestId != Other.RequestId || ReducerName != Other.ReducerName) return false; switch (Tag) { - case EReducerTag::CircleDecay: - return GetAsCircleDecay() == Other.GetAsCircleDecay(); - case EReducerTag::CircleRecombine: - return GetAsCircleRecombine() == Other.GetAsCircleRecombine(); - case EReducerTag::Connect: - return GetAsConnect() == Other.GetAsConnect(); - case EReducerTag::ConsumeEntity: - return GetAsConsumeEntity() == Other.GetAsConsumeEntity(); - case EReducerTag::Disconnect: - return GetAsDisconnect() == Other.GetAsDisconnect(); case EReducerTag::EnterGame: return GetAsEnterGame() == Other.GetAsEnterGame(); - case EReducerTag::MoveAllPlayers: - return GetAsMoveAllPlayers() == Other.GetAsMoveAllPlayers(); case EReducerTag::PlayerSplit: return GetAsPlayerSplit() == Other.GetAsPlayerSplit(); case EReducerTag::Respawn: return GetAsRespawn() == Other.GetAsRespawn(); - case EReducerTag::SpawnFood: - return GetAsSpawnFood() == Other.GetAsSpawnFood(); case EReducerTag::Suicide: return GetAsSuicide() == Other.GetAsSuicide(); case EReducerTag::UpdatePlayerInput: @@ -388,71 +243,6 @@ class CLIENT_UNREAL_API UReducerBpLib : public UBlueprintFunctionLibrary private: - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") - static FReducer CircleDecay(const FCircleDecayArgs& Value) { - return FReducer::CircleDecay(Value); - } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static bool IsCircleDecay(const FReducer& Reducer) { return Reducer.IsCircleDecay(); } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static FCircleDecayArgs GetAsCircleDecay(const FReducer& Reducer) { - return Reducer.GetAsCircleDecay(); - } - - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") - static FReducer CircleRecombine(const FCircleRecombineArgs& Value) { - return FReducer::CircleRecombine(Value); - } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static bool IsCircleRecombine(const FReducer& Reducer) { return Reducer.IsCircleRecombine(); } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static FCircleRecombineArgs GetAsCircleRecombine(const FReducer& Reducer) { - return Reducer.GetAsCircleRecombine(); - } - - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") - static FReducer Connect(const FConnectArgs& Value) { - return FReducer::Connect(Value); - } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static bool IsConnect(const FReducer& Reducer) { return Reducer.IsConnect(); } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static FConnectArgs GetAsConnect(const FReducer& Reducer) { - return Reducer.GetAsConnect(); - } - - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") - static FReducer ConsumeEntity(const FConsumeEntityArgs& Value) { - return FReducer::ConsumeEntity(Value); - } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static bool IsConsumeEntity(const FReducer& Reducer) { return Reducer.IsConsumeEntity(); } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static FConsumeEntityArgs GetAsConsumeEntity(const FReducer& Reducer) { - return Reducer.GetAsConsumeEntity(); - } - - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") - static FReducer Disconnect(const FDisconnectArgs& Value) { - return FReducer::Disconnect(Value); - } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static bool IsDisconnect(const FReducer& Reducer) { return Reducer.IsDisconnect(); } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static FDisconnectArgs GetAsDisconnect(const FReducer& Reducer) { - return Reducer.GetAsDisconnect(); - } - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") static FReducer EnterGame(const FEnterGameArgs& Value) { return FReducer::EnterGame(Value); @@ -466,19 +256,6 @@ class CLIENT_UNREAL_API UReducerBpLib : public UBlueprintFunctionLibrary return Reducer.GetAsEnterGame(); } - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") - static FReducer MoveAllPlayers(const FMoveAllPlayersArgs& Value) { - return FReducer::MoveAllPlayers(Value); - } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static bool IsMoveAllPlayers(const FReducer& Reducer) { return Reducer.IsMoveAllPlayers(); } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static FMoveAllPlayersArgs GetAsMoveAllPlayers(const FReducer& Reducer) { - return Reducer.GetAsMoveAllPlayers(); - } - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") static FReducer PlayerSplit(const FPlayerSplitArgs& Value) { return FReducer::PlayerSplit(Value); @@ -505,19 +282,6 @@ class CLIENT_UNREAL_API UReducerBpLib : public UBlueprintFunctionLibrary return Reducer.GetAsRespawn(); } - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") - static FReducer SpawnFood(const FSpawnFoodArgs& Value) { - return FReducer::SpawnFood(Value); - } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static bool IsSpawnFood(const FReducer& Reducer) { return Reducer.IsSpawnFood(); } - - UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") - static FSpawnFoodArgs GetAsSpawnFood(const FReducer& Reducer) { - return Reducer.GetAsSpawnFood(); - } - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") static FReducer Suicide(const FSuicideArgs& Value) { return FReducer::Suicide(Value); @@ -923,27 +687,13 @@ class CLIENT_UNREAL_API USetReducerFlags : public USetReducerFlagsBase GENERATED_BODY() public: - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - void CircleDecay(ECallReducerFlags Flag); - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - void CircleRecombine(ECallReducerFlags Flag); - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - void Connect(ECallReducerFlags Flag); - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - void ConsumeEntity(ECallReducerFlags Flag); - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - void Disconnect(ECallReducerFlags Flag); UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") void EnterGame(ECallReducerFlags Flag); UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - void MoveAllPlayers(ECallReducerFlags Flag); - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") void PlayerSplit(ECallReducerFlags Flag); UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") void Respawn(ECallReducerFlags Flag); UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - void SpawnFood(ECallReducerFlags Flag); - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") void Suicide(ECallReducerFlags Flag); UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") void UpdatePlayerInput(ECallReducerFlags Flag); @@ -984,74 +734,6 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject public: - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FCircleDecayHandler, - const FReducerEventContext&, Context, - const FCircleDecayTimerType&, Timer - ); - UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") - FCircleDecayHandler OnCircleDecay; - - UFUNCTION(BlueprintCallable, Category="SpacetimeDB") - void CircleDecay(const FCircleDecayTimerType& Timer); - - bool InvokeCircleDecay(const FReducerEventContext& Context, const UCircleDecayReducer* Args); - bool InvokeCircleDecayWithArgs(const FReducerEventContext& Context, const FCircleDecayArgs& Args); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FCircleRecombineHandler, - const FReducerEventContext&, Context, - const FCircleRecombineTimerType&, Timer - ); - UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") - FCircleRecombineHandler OnCircleRecombine; - - UFUNCTION(BlueprintCallable, Category="SpacetimeDB") - void CircleRecombine(const FCircleRecombineTimerType& Timer); - - bool InvokeCircleRecombine(const FReducerEventContext& Context, const UCircleRecombineReducer* Args); - bool InvokeCircleRecombineWithArgs(const FReducerEventContext& Context, const FCircleRecombineArgs& Args); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( - FConnectHandler, - const FReducerEventContext&, Context - ); - UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") - FConnectHandler OnConnect; - - UFUNCTION(BlueprintCallable, Category="SpacetimeDB") - void Connect(); - - bool InvokeConnect(const FReducerEventContext& Context, const UConnectReducer* Args); - bool InvokeConnectWithArgs(const FReducerEventContext& Context, const FConnectArgs& Args); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FConsumeEntityHandler, - const FReducerEventContext&, Context, - const FConsumeEntityTimerType&, Request - ); - UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") - FConsumeEntityHandler OnConsumeEntity; - - UFUNCTION(BlueprintCallable, Category="SpacetimeDB") - void ConsumeEntity(const FConsumeEntityTimerType& Request); - - bool InvokeConsumeEntity(const FReducerEventContext& Context, const UConsumeEntityReducer* Args); - bool InvokeConsumeEntityWithArgs(const FReducerEventContext& Context, const FConsumeEntityArgs& Args); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( - FDisconnectHandler, - const FReducerEventContext&, Context - ); - UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") - FDisconnectHandler OnDisconnect; - - UFUNCTION(BlueprintCallable, Category="SpacetimeDB") - void Disconnect(); - - bool InvokeDisconnect(const FReducerEventContext& Context, const UDisconnectReducer* Args); - bool InvokeDisconnectWithArgs(const FReducerEventContext& Context, const FDisconnectArgs& Args); - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( FEnterGameHandler, const FReducerEventContext&, Context, @@ -1066,20 +748,6 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject bool InvokeEnterGame(const FReducerEventContext& Context, const UEnterGameReducer* Args); bool InvokeEnterGameWithArgs(const FReducerEventContext& Context, const FEnterGameArgs& Args); - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FMoveAllPlayersHandler, - const FReducerEventContext&, Context, - const FMoveAllPlayersTimerType&, Timer - ); - UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") - FMoveAllPlayersHandler OnMoveAllPlayers; - - UFUNCTION(BlueprintCallable, Category="SpacetimeDB") - void MoveAllPlayers(const FMoveAllPlayersTimerType& Timer); - - bool InvokeMoveAllPlayers(const FReducerEventContext& Context, const UMoveAllPlayersReducer* Args); - bool InvokeMoveAllPlayersWithArgs(const FReducerEventContext& Context, const FMoveAllPlayersArgs& Args); - DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( FPlayerSplitHandler, const FReducerEventContext&, Context @@ -1106,20 +774,6 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject bool InvokeRespawn(const FReducerEventContext& Context, const URespawnReducer* Args); bool InvokeRespawnWithArgs(const FReducerEventContext& Context, const FRespawnArgs& Args); - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FSpawnFoodHandler, - const FReducerEventContext&, Context, - const FSpawnFoodTimerType&, Timer - ); - UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") - FSpawnFoodHandler OnSpawnFood; - - UFUNCTION(BlueprintCallable, Category="SpacetimeDB") - void SpawnFood(const FSpawnFoodTimerType& Timer); - - bool InvokeSpawnFood(const FReducerEventContext& Context, const USpawnFoodReducer* Args); - bool InvokeSpawnFoodWithArgs(const FReducerEventContext& Context, const FSpawnFoodArgs& Args); - DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( FSuicideHandler, const FReducerEventContext&, Context diff --git a/demo/Blackholio/server-rust/src/lib.rs b/demo/Blackholio/server-rust/src/lib.rs index f12d554cf3f..062b8286fb3 100644 --- a/demo/Blackholio/server-rust/src/lib.rs +++ b/demo/Blackholio/server-rust/src/lib.rs @@ -109,6 +109,12 @@ pub struct CircleRecombineTimer { player_id: i32, } +#[spacetimedb::table(name = consume_entity_event, public, event)] +pub struct ConsumeEntityEvent { + consumed_entity_id: i32, + consumer_entity_id: i32, +} + #[spacetimedb::table(name = consume_entity_timer, scheduled(consume_entity))] pub struct ConsumeEntityTimer { #[primary_key] @@ -456,6 +462,11 @@ pub fn consume_entity(ctx: &ReducerContext, request: ConsumeEntityTimer) -> Resu let consumed_entity = consumed_entity.unwrap(); let mut consumer_entity = consumer_entity.unwrap(); + ctx.db.consume_entity_event().insert(ConsumeEntityEvent { + consumed_entity_id: consumed_entity.entity_id, + consumer_entity_id: consumer_entity.entity_id, + }); + consumer_entity.mass += consumed_entity.mass; destroy_entity(ctx, consumed_entity.entity_id)?; ctx.db.entity().entity_id().update(consumer_entity); diff --git a/docs/docs/00200-core-concepts/00300-tables/00550-event-tables.md b/docs/docs/00200-core-concepts/00300-tables/00550-event-tables.md new file mode 100644 index 00000000000..a0d381d16aa --- /dev/null +++ b/docs/docs/00200-core-concepts/00300-tables/00550-event-tables.md @@ -0,0 +1,209 @@ +--- +title: Event Tables +slug: /tables/event-tables +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +In many applications, particularly games and real-time systems, modules need to notify clients about things that happened without storing that information permanently. A combat system might need to tell clients "entity X took 50 damage" so they can display a floating damage number, but there is no reason to keep that record in the database after the moment has passed. + +Event tables provide exactly this capability. An event table is a table whose rows are inserted and then immediately deleted by the database: they exist only for the duration of the transaction that created them. When the transaction commits, the rows are broadcast to subscribed clients and then deleted from the table. Between transactions, the table is always empty. + +From the module's perspective, event tables behave like regular tables during a reducer's execution. You insert rows, query them, and apply constraints just as you would with any other table. The difference is purely in what happens after the transaction completes: rather than merging the rows into the committed database state, SpacetimeDB publishes them to subscribers and deletes them from the table. The inserts are still recorded in the commitlog, so a full history of events is preserved. + +## Defining an Event Table + +To declare a table as an event table, add the `event` attribute to the table definition. Event tables support all the same column types, constraints, indexes, and auto-increment fields as regular tables. + + + + +```typescript +const damageEvent = table({ + public: true, + event: true, +}, { + entity_id: t.identity(), + damage: t.u32(), + source: t.string(), +}); +``` + + + + +```csharp +[SpacetimeDB.Table(Public = true, Event = true)] +public partial struct DamageEvent +{ + public Identity EntityId; + public uint Damage; + public string Source; +} +``` + + + + +```rust +#[spacetimedb::table(name = damage_event, public, event)] +pub struct DamageEvent { + pub entity_id: Identity, + pub damage: u32, + pub source: String, +} +``` + + + + +:::note Changing the event flag +Once a table has been published as an event table (or a regular table), the `event` flag cannot be changed in a subsequent module update. Attempting to convert a regular table to an event table or vice versa will produce a migration error. +::: + +## Publishing Events + +To publish an event, simply insert a row into the event table from within a reducer. The insertion works exactly like inserting into a regular table. The row is visible within the current transaction and can be queried or used in constraints. When the transaction commits successfully, the row is broadcast to all subscribed clients. If the reducer panics or the transaction is rolled back, no events are sent. + + + + +```typescript +export const attack = spacetimedb.reducer( + { target_id: t.identity(), damage: t.u32() }, + (ctx, { target_id, damage }) => { + // Game logic... + + // Publish the event + ctx.db.damageEvent.insert({ + entity_id: target_id, + damage, + source: "melee_attack", + }); + } +); +``` + + + + +```csharp +[SpacetimeDB.Reducer] +public static void Attack(ReducerContext ctx, Identity targetId, uint damage) +{ + // Game logic... + + // Publish the event + ctx.Db.DamageEvent.Insert(new DamageEvent + { + EntityId = targetId, + Damage = damage, + Source = "melee_attack" + }); +} +``` + + + + +```rust +#[spacetimedb::reducer] +fn attack(ctx: &ReducerContext, target_id: Identity, damage: u32) { + // Game logic... + + // Publish the event + ctx.db.damage_event().insert(DamageEvent { + entity_id: target_id, + damage, + source: "melee_attack".to_string(), + }); +} +``` + + + + +Because events are just table inserts, you can publish the same event type from any number of reducers. A `DamageEvent` might be inserted by a melee attack reducer, a spell reducer, and an environmental hazard reducer and clients receive the same event regardless of what triggered it. + +## Constraints and Indexes + +Primary keys, unique constraints, indexes, sequences, and auto-increment columns all work on event tables. The key difference is that these constraints are enforced only within a single transaction and reset between transactions. + +For example, if an event table has a primary key column, inserting two rows with the same primary key within the same transaction will produce an error, just as it would for a regular table. However, inserting a row with primary key `1` in one transaction and another row with primary key `1` in a later transaction will both succeed, because the table is empty at the start of each transaction. + +This behavior follows naturally from the fact that event table rows are never merged into the committed state. Each transaction begins with an empty table. + +## Subscribing to Events + +On the client side, event tables are subscribed to in the same way as regular tables. The important difference is that event table rows are never stored in the client cache. Calling `count()` on an event table always returns 0, and `iter()` always yields no rows. Instead, you observe events through `on_insert` callbacks, which fire for each row that was inserted during the transaction. + +Because event table rows are ephemeral, only `on_insert` callbacks are available. There are no `on_delete`, `on_update`, or `on_before_delete` callbacks, since rows are never present in the client state to be deleted or updated. + + + + +```typescript +conn.db.damageEvent.onInsert((ctx, event) => { + console.log(`Entity ${event.entityId} took ${event.damage} damage from ${event.source}`); +}); +``` + + + + +```csharp +conn.Db.DamageEvent.OnInsert += (ctx, damageEvent) => +{ + Debug.Log($"Entity {damageEvent.EntityId} took {damageEvent.Damage} damage from {damageEvent.Source}"); +}; +``` + + + + +```rust +conn.db.damage_event().on_insert(|ctx, event| { + println!("Entity {} took {} damage from {}", event.entity_id, event.damage, event.source); +}); +``` + + + + +## How It Works + +Conceptually, every insert into an event table is a **noop**: an insert paired with an automatic delete. The result is that the table state never changes; it is always the empty set. This model has several consequences for how SpacetimeDB handles event tables internally. + +**Wire format.** Event tables require the v2 WebSocket protocol. Clients connected via the v1 protocol that attempt to subscribe to an event table will receive an error message directing them to upgrade. + +:::tip Migrating from reducer callbacks +If you previously used `ctx.reducers.on_()` callbacks to receive transient data, event tables are the recommended replacement. Define an event table with the fields you want to publish, insert a row in your reducer, and register an `on_insert` callback on the client via `ctx.db.().on_insert(...)`. See the [migration guide](/how-to/migrating-to-2-0) for details. +::: + +## Row-Level Security + +Row-level security applies to event tables with the same semantics as regular tables. This means you can use RLS rules to control which clients receive which events based on their identity. For example, you could restrict a `DamageEvent` so that only clients whose identity matches the `entity_id` field receive the event, preventing players from seeing damage dealt to other players. + +## Current Limitations + +Event tables are fully functional for the use cases described above, but a few capabilities are intentionally restricted for the initial release: + +- **Subscription joins.** Event tables cannot currently be used as the lookup (right/inner) table in a subscription join. While this is well-defined (the noop semantics make joined results behave as event tables too), it is restricted for ease of implementation and will be relaxed in a future release. +- **Views.** Event tables cannot currently be accessed within view functions. Although the proposal defines clear semantics for this (event-table-ness is "infectious," meaning a view that joins on an event table itself becomes an event table), this is deferred to a future release. + +## Use Cases + +Event tables are well-suited to any situation where the module needs to notify clients about something that happened without storing a permanent record: + +- **Combat and damage events.** Floating damage numbers, hit indicators, and kill notifications. +- **Chat messages.** Real-time chat where messages are displayed on arrival but don't need server-side persistence. +- **Notifications.** Transient UI messages like "Player joined", "Achievement unlocked", or "Trade completed". +- **Sound and visual effects.** Triggering client-side effects such as explosions, particles, or audio cues at the right moment. +- **Telemetry and debugging.** Streaming diagnostic data to a connected developer client without accumulating it in the database. + +## Next Steps + +- Learn about [Tables](/tables) for persistent data storage +- Explore [Schedule Tables](/tables/schedule-tables) for time-triggered actions +- See [Row-Level Security](/tables/access-permissions) for controlling data visibility diff --git a/docs/docs/00300-resources/00100-how-to/00600-migrating-to-2.0.md b/docs/docs/00300-resources/00100-how-to/00600-migrating-to-2.0.md new file mode 100644 index 00000000000..089169b5aee --- /dev/null +++ b/docs/docs/00300-resources/00100-how-to/00600-migrating-to-2.0.md @@ -0,0 +1,217 @@ +--- +title: Migrating from 1.0 to 2.0 +slug: /how-to/migrating-to-2-0 +--- + +# Migrating from SpacetimeDB 1.0 to 2.0 + +This guide covers the breaking changes between SpacetimeDB 1.0 and 2.0 and how to update your code. + +## Overview of Changes + +SpacetimeDB 2.0 introduces a new WebSocket protocol (v2) and SDK with several breaking changes aimed at simplifying the programming model and improving security: + +1. **Reducer callbacks removed** -- replaced by event tables and per-call `_then()` callbacks +2. **`light_mode` removed** -- no longer necessary since reducer events are no longer broadcast +3. **`CallReducerFlags` removed** -- `NoSuccessNotify` and `set_reducer_flags()` are gone +4. **Event tables introduced** -- a new table type for publishing transient events to subscribers + +## Reducer Callbacks + +### What changed + +In 1.0, you could register global callbacks on reducers that would fire whenever *any* client called that reducer and you were subscribed to affected rows: + +```rust +// 1.0 -- REMOVED in 2.0 +conn.reducers.on_insert_one_u_8(|ctx, arg| { + println!("Someone called insert_one_u_8 with arg: {}", arg); +}); +``` + +In 2.0, global reducer callbacks no longer exist. The server does not broadcast reducer argument data to other clients. Instead, you have two options: + +### Option A: Per-call result callbacks (`_then()`) + +If you only need to know the result of a reducer *you* called, use the `_then()` variant: + +```rust +// 2.0 -- per-call callback +ctx.reducers.insert_one_u_8_then(42, |ctx, result| { + match result { + Ok(Ok(())) => println!("Reducer succeeded"), + Ok(Err(err)) => println!("Reducer failed: {err}"), + Err(internal) => println!("Internal error: {internal:?}"), + } +}).unwrap(); +``` + +The fire-and-forget form still works: + +```rust +// 2.0 -- fire and forget (unchanged) +ctx.reducers.insert_one_u_8(42).unwrap(); +``` + +### Option B: Event tables (recommended for most use cases) + +If you need *other* clients to observe that something happened (the primary use case for 1.0 reducer callbacks), create an event table and insert into it from your reducer. + +**Server (module) -- before:** +```rust +// 1.0 server -- reducer args were automatically broadcast +#[reducer] +fn deal_damage(ctx: &ReducerContext, target: Identity, amount: u32) { + // update game state... +} +``` + +**Server (module) -- after:** +```rust +// 2.0 server -- explicitly publish events via an event table +#[spacetimedb::table(name = damage_event, public, event)] +pub struct DamageEvent { + pub target: Identity, + pub amount: u32, +} + +#[reducer] +fn deal_damage(ctx: &ReducerContext, target: Identity, amount: u32) { + // update game state... + ctx.db.damage_event().insert(DamageEvent { target, amount }); +} +``` + +**Client -- before:** +```rust +// 1.0 client -- global reducer callback +conn.reducers.on_deal_damage(|ctx, target, amount| { + play_damage_animation(target, amount); +}); +``` + +**Client -- after:** +```rust +// 2.0 client -- event table callback +conn.db.damage_event().on_insert(|ctx, event| { + play_damage_animation(event.target, event.amount); +}); +``` + +### Why event tables are better + +- **Security**: You control exactly what data is published. In 1.0, reducer arguments were broadcast to any subscriber of affected rows, which could accidentally leak sensitive data. +- **Flexibility**: Multiple reducers can insert the same event type. In 1.0, events were tied 1:1 to a specific reducer. +- **Transactional**: Events are only published if the transaction commits. In 1.0, workarounds using scheduled reducers were not transactional. +- **Row-level security**: RLS rules apply to event tables, so you can control which clients see which events. +- **Queryable**: Event tables are subscribed to with standard SQL, and can be filtered per-client. + +### Event table details + +- Event tables are always empty outside of a transaction. They don't accumulate rows. +- On the client, `count()` always returns 0 and `iter()` is always empty. +- Only `on_insert` callbacks are generated (no `on_delete` or `on_update`). +- The `event` keyword in `#[table(..., event)]` marks the table as transient. +- Event tables must be subscribed to explicitly (they are excluded from `SELECT * FROM *`). + +## Light Mode + +### What changed + +In 1.0, `light_mode` prevented the server from sending reducer event data to a client (unless that client was the caller): + +```rust +// 1.0 -- REMOVED in 2.0 +DbConnection::builder() + .with_light_mode(true) + // ... +``` + +In 2.0, the server never broadcasts reducer argument data to any client, so `light_mode` is no longer necessary. Simply remove the call: + +```rust +// 2.0 +DbConnection::builder() + .with_uri(uri) + .with_module_name(name) + // no with_light_mode needed + .build() +``` + +## CallReducerFlags + +### What changed + +In 1.0, you could suppress success notifications for individual reducer calls: + +```rust +// 1.0 -- REMOVED in 2.0 +ctx.set_reducer_flags(CallReducerFlags::NoSuccessNotify); +ctx.reducers.my_reducer(args).unwrap(); +``` + +In 2.0, the success notification is lightweight (just `request_id` and `timestamp`, no reducer args or full event data), so there is no need to suppress it. Remove any `set_reducer_flags` calls and `CallReducerFlags` imports. + +## Event Type Changes + +### What changed + +In 1.0, table callbacks received `Event::Reducer` with full reducer information when a reducer caused a table change. Non-callers could also receive `Event::UnknownTransaction`. + +In 2.0, the event model is simplified: + +- **The caller** sees `Event::Reducer` with `ReducerEvent { timestamp, status, reducer }` in response to their own reducer calls. +- **Other clients** see `Event::Transaction` (no reducer details). +- `Event::UnknownTransaction` is removed. + +```rust +// 2.0 -- checking who caused a table change +conn.db.my_table().on_insert(|ctx, row| { + match &ctx.event { + Event::Reducer(reducer_event) => { + // This client called the reducer that caused this insert. + println!("Our reducer: {:?}", reducer_event.reducer); + } + Event::Transaction => { + // Another client's action caused this insert. + } + _ => {} + } +}); +``` + +## Subscription API + +The subscription API is largely unchanged: + +```rust +// 2.0 -- same as 1.0 +ctx.subscription_builder() + .on_applied(|ctx| { /* ... */ }) + .on_error(|ctx, error| { /* ... */ }) + .subscribe(["SELECT * FROM my_table"]); +``` + +Note that subscribing to event tables requires an explicit query: + +```rust +// Event tables are excluded from SELECT * FROM *, so subscribe explicitly: +ctx.subscription_builder() + .on_applied(|ctx| { /* ... */ }) + .subscribe(["SELECT * FROM damage_event"]); +``` + +## Quick Migration Checklist + +- [ ] Remove all `ctx.reducers.on_()` calls + - Replace with `_then()` callbacks for your own reducer calls + - Replace with event tables + `on_insert` for cross-client notifications +- [ ] Remove `with_light_mode()` from `DbConnectionBuilder` +- [ ] Remove `set_reducer_flags()` calls and `CallReducerFlags` imports +- [ ] Remove `unstable::CallReducerFlags` from imports +- [ ] Update `Event::UnknownTransaction` matches to `Event::Transaction` +- [ ] For each reducer whose args you were observing from other clients: + 1. Create an `#[table(..., event)]` on the server + 2. Insert into it from the reducer + 3. Subscribe to it on the client + 4. Use `on_insert` instead of the old reducer callback diff --git a/modules/sdk-test-event-table/.cargo/config.toml b/modules/sdk-test-event-table/.cargo/config.toml new file mode 100644 index 00000000000..f4e8c002fc2 --- /dev/null +++ b/modules/sdk-test-event-table/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "wasm32-unknown-unknown" diff --git a/modules/sdk-test-event-table/Cargo.toml b/modules/sdk-test-event-table/Cargo.toml new file mode 100644 index 00000000000..3dd8b22dbe4 --- /dev/null +++ b/modules/sdk-test-event-table/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "sdk-test-event-table-module" +version = "0.1.0" +edition.workspace = true + +[lib] +crate-type = ["cdylib"] + +[dependencies] +spacetimedb.workspace = true diff --git a/modules/sdk-test-event-table/src/lib.rs b/modules/sdk-test-event-table/src/lib.rs new file mode 100644 index 00000000000..05181098b52 --- /dev/null +++ b/modules/sdk-test-event-table/src/lib.rs @@ -0,0 +1,32 @@ +use spacetimedb::{ReducerContext, Table}; + +#[spacetimedb::table(name = test_event, public, event)] +pub struct TestEvent { + pub name: String, + pub value: u64, +} + +#[spacetimedb::reducer] +pub fn emit_test_event(ctx: &ReducerContext, name: String, value: u64) { + ctx.db.test_event().insert(TestEvent { name, value }); +} + +#[spacetimedb::reducer] +pub fn emit_multiple_test_events(ctx: &ReducerContext) { + ctx.db.test_event().insert(TestEvent { + name: "a".to_string(), + value: 1, + }); + ctx.db.test_event().insert(TestEvent { + name: "b".to_string(), + value: 2, + }); + ctx.db.test_event().insert(TestEvent { + name: "c".to_string(), + value: 3, + }); +} + +/// A no-op reducer that lets us observe a subsequent transaction. +#[spacetimedb::reducer] +pub fn noop(_ctx: &ReducerContext) {} diff --git a/sdks/csharp/examples~/regression-tests/client/Program.cs b/sdks/csharp/examples~/regression-tests/client/Program.cs index 3055bb8af42..61740321737 100644 --- a/sdks/csharp/examples~/regression-tests/client/Program.cs +++ b/sdks/csharp/examples~/regression-tests/client/Program.cs @@ -16,6 +16,8 @@ const string THROW_ERROR_MESSAGE = "this is an error"; const uint UPDATED_WHERE_TEST_VALUE = 42; const string UPDATED_WHERE_TEST_NAME = "this_name_was_updated"; +const string EXPECTED_TEST_EVENT_NAME = "hello"; +const ulong EXPECTED_TEST_EVENT_VALUE = 42; DbConnection ConnectToDB() { @@ -51,6 +53,7 @@ DbConnection ConnectToDB() uint waiting = 0; var applied = false; SubscriptionHandle? handle = null; +uint testEventInsertCount = 0; void OnConnected(DbConnection conn, Identity identity, string authToken) { @@ -72,6 +75,7 @@ void OnConnected(DbConnection conn, Identity identity, string authToken) .AddQuery(qb => qb.From.NullStringNonnullable().Build()) .AddQuery(qb => qb.From.NullStringNullable().Build()) .AddQuery(qb => qb.From.MyLog().Build()) + .AddQuery(qb => qb.From.TestEvent().Build()) .AddQuery(qb => qb.From.Admins().Build()) .AddQuery(qb => qb.From.NullableVecView().Build()) .AddQuery(qb => qb.From.WhereTest().Where(c => c.Value.Gt(10)).Build()) @@ -226,6 +230,58 @@ string name ValidateWhereSubscription(ctx, UPDATED_WHERE_TEST_NAME); ValidateWhereTestViews(ctx, UPDATED_WHERE_TEST_VALUE, UPDATED_WHERE_TEST_NAME); }; + + conn.Db.TestEvent.OnInsert += (EventContext ctx, TestEvent row) => + { + Log.Info($"Got TestEvent.OnInsert callback: {row.Name} / {row.Value}"); + testEventInsertCount++; + Debug.Assert( + row.Name == EXPECTED_TEST_EVENT_NAME, + $"Expected TestEvent.Name == {EXPECTED_TEST_EVENT_NAME}, got {row.Name}" + ); + Debug.Assert( + row.Value == EXPECTED_TEST_EVENT_VALUE, + $"Expected TestEvent.Value == {EXPECTED_TEST_EVENT_VALUE}, got {row.Value}" + ); + Debug.Assert( + ctx.Db.TestEvent.Count == 0, + $"Event table should not persist rows. Count was {ctx.Db.TestEvent.Count}" + ); + Debug.Assert( + !ctx.Db.TestEvent.Iter().Any(), + "Event table iterator should be empty after event delivery" + ); + }; + + conn.Reducers.OnEmitTestEvent += (ReducerEventContext ctx, string name, ulong value) => + { + Log.Info("Got EmitTestEvent callback"); + waiting--; + Debug.Assert( + ctx.Event.Status is Status.Committed, + $"EmitTestEvent should commit, got {ctx.Event.Status}" + ); + Debug.Assert(name == EXPECTED_TEST_EVENT_NAME, $"Expected name={EXPECTED_TEST_EVENT_NAME}, got {name}"); + Debug.Assert(value == EXPECTED_TEST_EVENT_VALUE, $"Expected value={EXPECTED_TEST_EVENT_VALUE}, got {value}"); + }; + + conn.Reducers.OnNoop += (ReducerEventContext ctx) => + { + Log.Info("Got Noop callback"); + waiting--; + Debug.Assert( + testEventInsertCount == 1, + $"Expected exactly one TestEvent insert callback after noop, got {testEventInsertCount}" + ); + Debug.Assert( + ctx.Db.TestEvent.Count == 0, + $"Event table should still be empty after noop. Count was {ctx.Db.TestEvent.Count}" + ); + Debug.Assert( + !ctx.Db.TestEvent.Iter().Any(), + "Event table iterator should remain empty after noop" + ); + }; } const uint MAX_ID = 10; @@ -646,6 +702,14 @@ void OnSubscriptionApplied(SubscriptionEventContext context) waiting++; context.Reducers.InsertNullStringIntoNullable(); + Log.Debug("Calling EmitTestEvent"); + waiting++; + context.Reducers.EmitTestEvent(EXPECTED_TEST_EVENT_NAME, EXPECTED_TEST_EVENT_VALUE); + + Log.Debug("Calling Noop after EmitTestEvent"); + waiting++; + context.Reducers.Noop(); + // Procedures tests Log.Debug("Calling ReadMySchemaViaHttp"); waiting++; diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/ConsumeEntity.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/EmitTestEvent.g.cs similarity index 53% rename from demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/ConsumeEntity.g.cs rename to sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/EmitTestEvent.g.cs index 8917fcf0ff6..ce0343964c0 100644 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Reducers/ConsumeEntity.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/EmitTestEvent.g.cs @@ -12,17 +12,17 @@ namespace SpacetimeDB.Types { public sealed partial class RemoteReducers : RemoteBase { - public delegate void ConsumeEntityHandler(ReducerEventContext ctx, SpacetimeDB.Types.ConsumeEntityTimer request); - public event ConsumeEntityHandler? OnConsumeEntity; + public delegate void EmitTestEventHandler(ReducerEventContext ctx, string name, ulong value); + public event EmitTestEventHandler? OnEmitTestEvent; - public void ConsumeEntity(SpacetimeDB.Types.ConsumeEntityTimer request) + public void EmitTestEvent(string name, ulong value) { - conn.InternalCallReducer(new Reducer.ConsumeEntity(request)); + conn.InternalCallReducer(new Reducer.EmitTestEvent(name, value)); } - public bool InvokeConsumeEntity(ReducerEventContext ctx, Reducer.ConsumeEntity args) + public bool InvokeEmitTestEvent(ReducerEventContext ctx, Reducer.EmitTestEvent args) { - if (OnConsumeEntity == null) + if (OnEmitTestEvent == null) { if (InternalOnUnhandledReducerError != null) { @@ -34,9 +34,10 @@ public bool InvokeConsumeEntity(ReducerEventContext ctx, Reducer.ConsumeEntity a } return false; } - OnConsumeEntity( + OnEmitTestEvent( ctx, - args.Request + args.Name, + args.Value ); return true; } @@ -46,22 +47,28 @@ public abstract partial class Reducer { [SpacetimeDB.Type] [DataContract] - public sealed partial class ConsumeEntity : Reducer, IReducerArgs + public sealed partial class EmitTestEvent : Reducer, IReducerArgs { - [DataMember(Name = "request")] - public ConsumeEntityTimer Request; + [DataMember(Name = "name")] + public string Name; + [DataMember(Name = "value")] + public ulong Value; - public ConsumeEntity(ConsumeEntityTimer Request) + public EmitTestEvent( + string Name, + ulong Value + ) { - this.Request = Request; + this.Name = Name; + this.Value = Value; } - public ConsumeEntity() + public EmitTestEvent() { - this.Request = new(); + this.Name = ""; } - string IReducerArgs.ReducerName => "consume_entity"; + string IReducerArgs.ReducerName => "EmitTestEvent"; } } } diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/ClientConnected.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Noop.g.cs similarity index 70% rename from sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/ClientConnected.g.cs rename to sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Noop.g.cs index a23c796730b..6bd734fccf5 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/ClientConnected.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Noop.g.cs @@ -12,12 +12,17 @@ namespace SpacetimeDB.Types { public sealed partial class RemoteReducers : RemoteBase { - public delegate void ClientConnectedHandler(ReducerEventContext ctx); - public event ClientConnectedHandler? OnClientConnected; + public delegate void NoopHandler(ReducerEventContext ctx); + public event NoopHandler? OnNoop; - public bool InvokeClientConnected(ReducerEventContext ctx, Reducer.ClientConnected args) + public void Noop() { - if (OnClientConnected == null) + conn.InternalCallReducer(new Reducer.Noop()); + } + + public bool InvokeNoop(ReducerEventContext ctx, Reducer.Noop args) + { + if (OnNoop == null) { if (InternalOnUnhandledReducerError != null) { @@ -29,7 +34,7 @@ public bool InvokeClientConnected(ReducerEventContext ctx, Reducer.ClientConnect } return false; } - OnClientConnected( + OnNoop( ctx ); return true; @@ -40,9 +45,9 @@ public abstract partial class Reducer { [SpacetimeDB.Type] [DataContract] - public sealed partial class ClientConnected : Reducer, IReducerArgs + public sealed partial class Noop : Reducer, IReducerArgs { - string IReducerArgs.ReducerName => "ClientConnected"; + string IReducerArgs.ReducerName => "Noop"; } } } diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs index b725b37552d..69271cdcc18 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 18e8d1958a9e9cb62ca15cc849d35c1a17f9982c). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). #nullable enable @@ -48,6 +48,7 @@ public RemoteTables(DbConnection conn) AddTable(ScoresPlayer123 = new(conn)); AddTable(ScoresPlayer123Level5 = new(conn)); AddTable(ScoresPlayer123Range = new(conn)); + AddTable(TestEvent = new(conn)); AddTable(User = new(conn)); AddTable(UsersAge1865 = new(conn)); AddTable(UsersAge18Plus = new(conn)); @@ -573,6 +574,7 @@ public sealed class QueryBuilder new QueryBuilder().From.ScoresPlayer123().ToSql(), new QueryBuilder().From.ScoresPlayer123Level5().ToSql(), new QueryBuilder().From.ScoresPlayer123Range().ToSql(), + new QueryBuilder().From.TestEvent().ToSql(), new QueryBuilder().From.User().ToSql(), new QueryBuilder().From.UsersAge1865().ToSql(), new QueryBuilder().From.UsersAge18Plus().ToSql(), @@ -608,6 +610,7 @@ public sealed class From public global::SpacetimeDB.Table ScoresPlayer123() => new("scores_player_123", new ScoresPlayer123Cols("scores_player_123"), new ScoresPlayer123IxCols("scores_player_123")); public global::SpacetimeDB.Table ScoresPlayer123Level5() => new("scores_player_123_level5", new ScoresPlayer123Level5Cols("scores_player_123_level5"), new ScoresPlayer123Level5IxCols("scores_player_123_level5")); public global::SpacetimeDB.Table ScoresPlayer123Range() => new("scores_player_123_range", new ScoresPlayer123RangeCols("scores_player_123_range"), new ScoresPlayer123RangeIxCols("scores_player_123_range")); + public global::SpacetimeDB.Table TestEvent() => new("test_event", new TestEventCols("test_event"), new TestEventIxCols("test_event")); public global::SpacetimeDB.Table User() => new("user", new UserCols("user"), new UserIxCols("user")); public global::SpacetimeDB.Table UsersAge1865() => new("users_age_18_65", new UsersAge1865Cols("users_age_18_65"), new UsersAge1865IxCols("users_age_18_65")); public global::SpacetimeDB.Table UsersAge18Plus() => new("users_age_18_plus", new UsersAge18PlusCols("users_age_18_plus"), new UsersAge18PlusIxCols("users_age_18_plus")); @@ -698,13 +701,14 @@ protected override bool Dispatch(IReducerEventContext context, Reducer reducer) return reducer switch { Reducer.Add args => Reducers.InvokeAdd(eventContext, args), - Reducer.ClientConnected args => Reducers.InvokeClientConnected(eventContext, args), Reducer.Delete args => Reducers.InvokeDelete(eventContext, args), + Reducer.EmitTestEvent args => Reducers.InvokeEmitTestEvent(eventContext, args), Reducer.InsertEmptyStringIntoNonNullable args => Reducers.InvokeInsertEmptyStringIntoNonNullable(eventContext, args), Reducer.InsertNullStringIntoNonNullable args => Reducers.InvokeInsertNullStringIntoNonNullable(eventContext, args), Reducer.InsertNullStringIntoNullable args => Reducers.InvokeInsertNullStringIntoNullable(eventContext, args), Reducer.InsertResult args => Reducers.InvokeInsertResult(eventContext, args), Reducer.InsertWhereTest args => Reducers.InvokeInsertWhereTest(eventContext, args), + Reducer.Noop args => Reducers.InvokeNoop(eventContext, args), Reducer.SetNullableVec args => Reducers.InvokeSetNullableVec(eventContext, args), Reducer.ThrowError args => Reducers.InvokeThrowError(eventContext, args), Reducer.UpdateWhereTest args => Reducers.InvokeUpdateWhereTest(eventContext, args), diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/TestEvent.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/TestEvent.g.cs new file mode 100644 index 00000000000..9b8f8f3d489 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/TestEvent.g.cs @@ -0,0 +1,47 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class TestEventHandle : RemoteEventTableHandle + { + protected override string RemoteTableName => "test_event"; + + internal TestEventHandle(DbConnection conn) : base(conn) + { + } + } + + public readonly TestEventHandle TestEvent; + } + + public sealed class TestEventCols + { + public global::SpacetimeDB.Col Name { get; } + public global::SpacetimeDB.Col Value { get; } + + public TestEventCols(string tableName) + { + Name = new global::SpacetimeDB.Col(tableName, "Name"); + Value = new global::SpacetimeDB.Col(tableName, "Value"); + } + } + + public sealed class TestEventIxCols + { + + public TestEventIxCols(string tableName) + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/TestEvent.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/TestEvent.g.cs new file mode 100644 index 00000000000..d9faeffc79d --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/TestEvent.g.cs @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class TestEvent + { + [DataMember(Name = "Name")] + public string Name; + [DataMember(Name = "Value")] + public ulong Value; + + public TestEvent( + string Name, + ulong Value + ) + { + this.Name = Name; + this.Value = Value; + } + + public TestEvent() + { + this.Name = ""; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/Procedures/ScheduledProc.g.cs b/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/Procedures/ScheduledProc.g.cs deleted file mode 100644 index 4d99bfe501c..00000000000 --- a/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/Procedures/ScheduledProc.g.cs +++ /dev/null @@ -1,77 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteProcedures : RemoteBase - { - public void ScheduledProc(SpacetimeDB.Types.ScheduledProcTable data, ProcedureCallback callback) - { - // Convert the clean callback to the wrapper callback - InternalScheduledProc(data, (ctx, result) => - { - if (result.IsSuccess && result.Value != null) - { - callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); - } - else - { - callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); - } - }); - } - - private void InternalScheduledProc(SpacetimeDB.Types.ScheduledProcTable data, ProcedureCallback callback) - { - conn.InternalCallProcedure(new Procedure.ScheduledProcArgs(data), callback); - } - - } - - public abstract partial class Procedure - { - [SpacetimeDB.Type] - [DataContract] - public sealed partial class ScheduledProc - { - [DataMember(Name = "Value")] - public SpacetimeDB.Unit Value; - - public ScheduledProc(SpacetimeDB.Unit Value) - { - this.Value = Value; - } - - public ScheduledProc() - { - } - } - [SpacetimeDB.Type] - [DataContract] - public sealed partial class ScheduledProcArgs : Procedure, IProcedureArgs - { - [DataMember(Name = "data")] - public ScheduledProcTable Data; - - public ScheduledProcArgs(ScheduledProcTable Data) - { - this.Data = Data; - } - - public ScheduledProcArgs() - { - this.Data = new(); - } - - string IProcedureArgs.ProcedureName => "scheduled_proc"; - } - - } -} diff --git a/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs index 188b733f976..59344f7ba69 100644 --- a/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 18e8d1958a9e9cb62ca15cc849d35c1a17f9982c). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). #nullable enable diff --git a/sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs index 88cc4336398..2e01c9cce00 100644 --- a/sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 18e8d1958a9e9cb62ca15cc849d35c1a17f9982c). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). #nullable enable diff --git a/sdks/csharp/examples~/regression-tests/server/Lib.cs b/sdks/csharp/examples~/regression-tests/server/Lib.cs index e4353f2cec5..47c62dc4b87 100644 --- a/sdks/csharp/examples~/regression-tests/server/Lib.cs +++ b/sdks/csharp/examples~/regression-tests/server/Lib.cs @@ -692,6 +692,13 @@ public partial class RetryLog public uint Attempts; } + [SpacetimeDB.Table(Name = "test_event", Public = true, Event = true)] + public partial struct TestEvent + { + public string Name; + public ulong Value; + } + [SpacetimeDB.Procedure] public static void InsertWithTxRetry(ProcedureContext ctx) { @@ -735,6 +742,15 @@ public static void InsertWithTxRetry(ProcedureContext ctx) Debug.Assert(outcome.IsSuccess, "Retry should have succeeded"); } + [SpacetimeDB.Reducer] + public static void EmitTestEvent(ReducerContext ctx, string name, ulong value) + { + ctx.Db.test_event.Insert(new TestEvent { Name = name, Value = value }); + } + + [SpacetimeDB.Reducer] + public static void Noop(ReducerContext ctx) { } + [SpacetimeDB.Procedure] public static void InsertWithTxPanic(ProcedureContext ctx) { diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerOutcome.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerOutcome.g.cs index 4ef8bb569e5..455062e09b0 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerOutcome.g.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerOutcome.g.cs @@ -10,7 +10,7 @@ namespace SpacetimeDB.ClientApi [SpacetimeDB.Type] public partial record ReducerOutcome : SpacetimeDB.TaggedEnum<( ReducerOk Ok, - SpacetimeDB.Unit Okmpty, + SpacetimeDB.Unit OkEmpty, System.Collections.Generic.List Err, string InternalError )>; diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index c612074ba41..ef202ed168b 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -500,7 +500,7 @@ ParsedMessage ParseMessage(UnparsedMessage unparsed) var reducerStatus = reducerResult.Result switch { ReducerOutcome.Ok => Committed, - ReducerOutcome.Okmpty => Committed, + ReducerOutcome.OkEmpty => Committed, ReducerOutcome.Err(var err) => new Status.Failed(DecodeReducerError(err)), ReducerOutcome.InternalError(var err) => new Status.Failed(err), _ => new Status.Failed("Unknown reducer result"), diff --git a/sdks/csharp/src/Table.cs b/sdks/csharp/src/Table.cs index d23a917b8dd..620d99fffd1 100644 --- a/sdks/csharp/src/Table.cs +++ b/sdks/csharp/src/Table.cs @@ -90,7 +90,7 @@ interface IParsedTableUpdate /// /// /// - public abstract class RemoteTableHandle : RemoteBase, IRemoteTableHandle + public abstract class RemoteTableHandleBase : RemoteBase, IRemoteTableHandle where EventContext : class, IEventContext where Row : class, IStructuralReadWrite, new() { @@ -110,7 +110,7 @@ public abstract class UniqueIndexBase : IndexBase { private readonly Dictionary cache = new(); - public UniqueIndexBase(RemoteTableHandle table) + public UniqueIndexBase(RemoteTableHandleBase table) { table.OnInternalInsert += row => cache.Add(GetKey(row), row); table.OnInternalDelete += row => cache.Remove(GetKey(row)); @@ -125,7 +125,7 @@ public abstract class BTreeIndexBase : IndexBase // TODO: change to SortedDictionary when adding support for range queries. private readonly Dictionary> cache = new(); - public BTreeIndexBase(RemoteTableHandle table) + public BTreeIndexBase(RemoteTableHandleBase table) { table.OnInternalInsert += row => { @@ -164,12 +164,26 @@ internal class ParsedTableUpdate : IParsedTableUpdate /// Stores the set of changes for the table, mapping primary keys to updated rows. /// internal MultiDictionaryDelta Delta = new(EqualityComparer.Default, EqualityComparer.Default); + + /// + /// For event tables: stores the event rows directly (bypassing delta merge). + /// + internal List? EventRows; } protected abstract string RemoteTableName { get; } string IRemoteTableHandle.RemoteTableName => RemoteTableName; - public RemoteTableHandle(IDbConnection conn) : base(conn) { } + /// + /// Whether this table is an event table. + /// Event tables don't persist rows in the client cache — they only fire insert callbacks. + /// + internal bool IsEventTable { get; } + + public RemoteTableHandleBase(IDbConnection conn, bool isEventTable = false) : base(conn) + { + IsEventTable = isEventTable; + } // This method needs to be overridden by autogen. protected virtual object? GetPrimaryKey(Row row) => null; @@ -195,7 +209,7 @@ private event Action OnInternalDelete // These are implementations of the type-erased interface. object? IRemoteTableHandle.GetPrimaryKey(IStructuralReadWrite row) => GetPrimaryKey((Row)row); - // These are provided by RemoteTableHandle. + // These are provided by RemoteTableHandleBase. Type IRemoteTableHandle.ClientTableType => typeof(Row); // THE DATA IN THE TABLE. @@ -288,9 +302,12 @@ void IRemoteTableHandle.ParseInsertOnly(TableUpdate update, ParsedDatabaseUpdate } else if (rowSet is TableUpdateRows.EventTable(var events)) { - if (events.Events.RowsData.Count > 0) + var (eventReader, eventRowCount) = CompressionHelpers.ParseRowList(events.Events); + delta.EventRows ??= new(); + for (var i = 0; i < eventRowCount; i++) { - Log.Warn($"Event-table rows are not yet supported by the C# SDK; ignoring insert-only event rows for table `{RemoteTableName}`."); + var obj = DecodeValue(eventReader); + delta.EventRows.Add(obj); } } } @@ -321,10 +338,7 @@ void IRemoteTableHandle.ParseDeleteOnly(TableUpdate update, ParsedDatabaseUpdate } else if (rowSet is TableUpdateRows.EventTable(var events)) { - if (events.Events.RowsData.Count > 0) - { - Log.Warn($"Event-table rows are not yet supported by the C# SDK; ignoring delete-only event rows for table `{RemoteTableName}`."); - } + // Event tables never have deletes; ignore event rows in delete-only context. } } } @@ -359,9 +373,12 @@ void IRemoteTableHandle.Parse(TableUpdate update, ParsedDatabaseUpdate dbOps) } else if (rowSet is TableUpdateRows.EventTable(var events)) { - if (events.Events.RowsData.Count > 0) + var (eventReader, eventRowCount) = CompressionHelpers.ParseRowList(events.Events); + delta.EventRows ??= new(); + for (var i = 0; i < eventRowCount; i++) { - Log.Warn($"Event-table rows are not yet supported by the C# SDK; ignoring event rows for table `{RemoteTableName}`."); + var obj = DecodeValue(eventReader); + delta.EventRows.Add(obj); } } } @@ -375,26 +392,7 @@ public event RowEventHandler OnInsert add => OnInsertHandler.AddListener(value); remove => OnInsertHandler.RemoveListener(value); } - private CustomRowEventHandler OnDeleteHandler { get; } = new(); - public event RowEventHandler OnDelete - { - add => OnDeleteHandler.AddListener(value); - remove => OnDeleteHandler.RemoveListener(value); - } - private CustomRowEventHandler OnBeforeDeleteHandler { get; } = new(); - public event RowEventHandler OnBeforeDelete - { - add => OnBeforeDeleteHandler.AddListener(value); - remove => OnBeforeDeleteHandler.RemoveListener(value); - } - public delegate void UpdateEventHandler(EventContext context, Row oldRow, Row newRow); - private CustomUpdateEventHandler OnUpdateHandler { get; } = new(); - public event UpdateEventHandler OnUpdate - { - add => OnUpdateHandler.AddListener(value); - remove => OnUpdateHandler.RemoveListener(value); - } public int Count => (int)Entries.CountDistinct; @@ -415,41 +413,11 @@ void InvokeInsert(IEventContext context, IStructuralReadWrite row) } } - void InvokeDelete(IEventContext context, IStructuralReadWrite row) - { - try - { - OnDeleteHandler.Invoke((EventContext)context, (Row)row); - } - catch (Exception e) - { - Log.Exception(e); - } - } + protected virtual void InvokeDelete(IEventContext context, IStructuralReadWrite row) { } - void InvokeBeforeDelete(IEventContext context, IStructuralReadWrite row) - { - try - { - OnBeforeDeleteHandler.Invoke((EventContext)context, (Row)row); - } - catch (Exception e) - { - Log.Exception(e); - } - } + protected virtual void InvokeBeforeDelete(IEventContext context, IStructuralReadWrite row) { } - void InvokeUpdate(IEventContext context, IStructuralReadWrite oldRow, IStructuralReadWrite newRow) - { - try - { - OnUpdateHandler.Invoke((EventContext)context, (Row)oldRow, (Row)newRow); - } - catch (Exception e) - { - Log.Exception(e); - } - } + protected virtual void InvokeUpdate(IEventContext context, IStructuralReadWrite oldRow, IStructuralReadWrite newRow) { } List> wasInserted = new(); List<(object key, Row oldValue, Row newValue)> wasUpdated = new(); @@ -464,6 +432,7 @@ void InvokeUpdate(IEventContext context, IStructuralReadWrite oldRow, IStructura void IRemoteTableHandle.PreApply(IEventContext context, IParsedTableUpdate parsedTableUpdate) { Debug.Assert(wasInserted.Count == 0 && wasUpdated.Count == 0 && wasRemoved.Count == 0, "Call Apply and PostApply before calling PreApply again"); + if (IsEventTable) return; // Event tables have no deletes. var delta = (ParsedTableUpdate)parsedTableUpdate; foreach (var (_, value) in Entries.WillRemove(delta.Delta)) { @@ -478,9 +447,24 @@ void IRemoteTableHandle.PreApply(IEventContext context, IParsedTableUpdate parse /// void IRemoteTableHandle.Apply(IEventContext context, IParsedTableUpdate parsedTableUpdate) { + var delta = (ParsedTableUpdate)parsedTableUpdate; + + if (IsEventTable) + { + // Event tables: don't store rows in the cache or update indices. + // Just collect the event rows so PostApply can fire OnInsert callbacks. + if (delta.EventRows != null) + { + foreach (var row in delta.EventRows) + { + wasInserted.Add(new KeyValuePair(row, row)); + } + } + return; + } + try { - var delta = (ParsedTableUpdate)parsedTableUpdate; Entries.Apply(delta.Delta, wasInserted, wasUpdated, wasRemoved); } catch (Exception e) @@ -552,13 +536,16 @@ void IRemoteTableHandle.PostApply(IEventContext context) { InvokeInsert(context, value); } - foreach (var (_, oldValue, newValue) in wasUpdated) - { - InvokeUpdate(context, oldValue, newValue); - } - foreach (var (_, value) in wasRemoved) + if (!IsEventTable) { - InvokeDelete(context, value); + foreach (var (_, oldValue, newValue) in wasUpdated) + { + InvokeUpdate(context, oldValue, newValue); + } + foreach (var (_, value) in wasRemoved) + { + InvokeDelete(context, value); + } } wasInserted.Clear(); wasUpdated.Clear(); @@ -566,7 +553,7 @@ void IRemoteTableHandle.PostApply(IEventContext context) } - private class CustomRowEventHandler + protected class CustomRowEventHandler { private EventListeners Listeners { get; } = new(); @@ -581,7 +568,7 @@ public void Invoke(EventContext ctx, Row row) public void AddListener(RowEventHandler listener) => Listeners.Add(listener); public void RemoveListener(RowEventHandler listener) => Listeners.Remove(listener); } - private class CustomUpdateEventHandler + protected class CustomUpdateEventHandler { private EventListeners Listeners { get; } = new(); @@ -597,5 +584,82 @@ public void Invoke(EventContext ctx, Row oldRow, Row newRow) public void RemoveListener(UpdateEventHandler listener) => Listeners.Remove(listener); } } + + /// + /// A table handle for persistent tables, exposing insert/delete/update callbacks. + /// + public abstract class RemoteTableHandle : RemoteTableHandleBase + where EventContext : class, IEventContext + where Row : class, IStructuralReadWrite, new() + { + protected RemoteTableHandle(IDbConnection conn) : base(conn) { } + + private CustomRowEventHandler OnDeleteHandler { get; } = new(); + public event RowEventHandler OnDelete + { + add => OnDeleteHandler.AddListener(value); + remove => OnDeleteHandler.RemoveListener(value); + } + private CustomRowEventHandler OnBeforeDeleteHandler { get; } = new(); + public event RowEventHandler OnBeforeDelete + { + add => OnBeforeDeleteHandler.AddListener(value); + remove => OnBeforeDeleteHandler.RemoveListener(value); + } + private CustomUpdateEventHandler OnUpdateHandler { get; } = new(); + public event UpdateEventHandler OnUpdate + { + add => OnUpdateHandler.AddListener(value); + remove => OnUpdateHandler.RemoveListener(value); + } + + protected override void InvokeDelete(IEventContext context, IStructuralReadWrite row) + { + try + { + OnDeleteHandler.Invoke((EventContext)context, (Row)row); + } + catch (Exception e) + { + Log.Exception(e); + } + } + + protected override void InvokeBeforeDelete(IEventContext context, IStructuralReadWrite row) + { + try + { + OnBeforeDeleteHandler.Invoke((EventContext)context, (Row)row); + } + catch (Exception e) + { + Log.Exception(e); + } + } + + protected override void InvokeUpdate(IEventContext context, IStructuralReadWrite oldRow, IStructuralReadWrite newRow) + { + try + { + OnUpdateHandler.Invoke((EventContext)context, (Row)oldRow, (Row)newRow); + } + catch (Exception e) + { + Log.Exception(e); + } + } + } + + /// + /// A table handle for event tables, which only expose OnInsert callbacks. + /// Event tables do not persist rows in the client cache and do not support + /// OnDelete, OnBeforeDelete, or OnUpdate callbacks. + /// + public abstract class RemoteEventTableHandle : RemoteTableHandleBase + where EventContext : class, IEventContext + where Row : class, IStructuralReadWrite, new() + { + protected RemoteEventTableHandle(IDbConnection conn) : base(conn, isEventTable: true) { } + } } #nullable disable diff --git a/sdks/rust/src/client_cache.rs b/sdks/rust/src/client_cache.rs index 4a5bbfc312c..22d9b4b69b2 100644 --- a/sdks/rust/src/client_cache.rs +++ b/sdks/rust/src/client_cache.rs @@ -105,6 +105,19 @@ impl Default for TableAppliedDiff<'_, Row> { } impl<'r, Row> TableAppliedDiff<'r, Row> { + /// For event tables: construct a `TableAppliedDiff` with just inserts, + /// without touching the client cache. + /// Each insert will fire `on_insert` callbacks. + pub(crate) fn from_event_inserts(inserts: &'r [WithBsatn]) -> Self { + let insert_map = inserts.iter().map(|wb| (wb.bsatn.as_ref(), &wb.row)).collect(); + Self { + inserts: insert_map, + deletes: Default::default(), + update_deletes: Vec::new(), + update_inserts: Vec::new(), + } + } + /// Returns the applied diff restructured /// with row updates where deletes and inserts are found according to `derive_pk`. pub fn with_updates_by_pk(mut self, derive_pk: impl Fn(&Row) -> &Pk) -> Self { diff --git a/sdks/rust/src/lib.rs b/sdks/rust/src/lib.rs index fe9b2d1fc71..d99447d440f 100644 --- a/sdks/rust/src/lib.rs +++ b/sdks/rust/src/lib.rs @@ -29,7 +29,7 @@ pub use db_connection::DbConnectionBuilder; pub use db_context::DbContext; pub use error::{Error, Result}; pub use event::{Event, ReducerEvent, Status}; -pub use table::{Table, TableWithPrimaryKey}; +pub use table::{EventTable, Table, TableWithPrimaryKey}; pub use spacetime_module::SubscriptionHandle; pub use spacetimedb_client_api_messages::websocket::v1::Compression; @@ -61,7 +61,7 @@ pub mod __codegen { }; pub use crate::subscription::{OnEndedCallback, SubscriptionBuilder, SubscriptionHandleImpl}; pub use crate::{ - ConnectionId, DbConnectionBuilder, DbContext, Event, Identity, ReducerEvent, ScheduleAt, Table, + ConnectionId, DbConnectionBuilder, DbContext, Event, EventTable, Identity, ReducerEvent, ScheduleAt, Table, TableWithPrimaryKey, TimeDuration, Timestamp, Uuid, }; } diff --git a/sdks/rust/src/spacetime_module.rs b/sdks/rust/src/spacetime_module.rs index f4f69c7ffae..e50a3a90dfd 100644 --- a/sdks/rust/src/spacetime_module.rs +++ b/sdks/rust/src/spacetime_module.rs @@ -245,6 +245,12 @@ impl TableUpdate { pub(crate) fn is_empty(&self) -> bool { self.inserts.is_empty() && self.deletes.is_empty() } + + /// For event tables: convert inserts directly to a `TableAppliedDiff` + /// without touching the client cache. Each insert fires `on_insert` callbacks. + pub fn into_event_diff(&self) -> crate::client_cache::TableAppliedDiff<'_, Row> { + crate::client_cache::TableAppliedDiff::from_event_inserts(&self.inserts) + } } impl TableUpdate { @@ -254,7 +260,9 @@ impl TableUpdate { let mut deletes = Vec::new(); for update in raw_updates.rows { match update { - ws::v2::TableUpdateRows::EventTable(_) => todo!("Event tables"), + ws::v2::TableUpdateRows::EventTable(update) => { + Self::parse_from_row_list(&mut inserts, &update.events)?; + } ws::v2::TableUpdateRows::PersistentTable(update) => { Self::parse_from_row_list(&mut deletes, &update.deletes)?; Self::parse_from_row_list(&mut inserts, &update.inserts)?; diff --git a/sdks/rust/src/table.rs b/sdks/rust/src/table.rs index 2198201cb6e..fe42c613a4a 100644 --- a/sdks/rust/src/table.rs +++ b/sdks/rust/src/table.rs @@ -10,6 +10,8 @@ /// Trait implemented by table handles, which mediate access to tables in the client cache. /// /// Obtain a table handle by calling a method on `ctx.db`, where `ctx` is a `DbConnection` or `EventContext`. +/// +/// For persistent (non-event) tables only. See [`EventTable`] for transient event tables. pub trait Table { /// The type of rows stored in this table. type Row: 'static; @@ -75,3 +77,35 @@ pub trait TableWithPrimaryKey: Table { /// Cancel a callback previously registered by [`Self::on_update`], causing it not to run in the future. fn remove_on_update(&self, callback: Self::UpdateCallbackId); } + +/// Trait for event tables, whose rows are transient and never persisted in the client cache. +/// +/// Event table rows are delivered as inserts but are not stored; +/// only `on_insert` callbacks fire, and `count`/`iter` always reflect an empty table. +/// +/// Obtain a table handle by calling a method on `ctx.db`, where `ctx` is a `DbConnection` or `EventContext`. +pub trait EventTable { + /// The type of rows in this table. + type Row: 'static; + + /// The `EventContext` type generated for the module which defines this table. + type EventContext; + + /// The number of subscribed rows in the client cache (always 0 for event tables). + fn count(&self) -> u64; + + /// An iterator over all the subscribed rows in the client cache (always empty for event tables). + fn iter(&self) -> impl Iterator + '_; + + type InsertCallbackId; + /// Register a callback to run whenever a row is inserted. + /// + /// The returned [`Self::InsertCallbackId`] can be passed to [`Self::remove_on_insert`] + /// to cancel the callback. + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> Self::InsertCallbackId; + /// Cancel a callback previously registered by [`Self::on_insert`], causing it not to run in the future. + fn remove_on_insert(&self, callback: Self::InsertCallbackId); +} diff --git a/sdks/rust/tests/connect_disconnect_client/src/module_bindings/connected_type.rs b/sdks/rust/tests/connect_disconnect_client/src/module_bindings/connected_type.rs index c762b7a6bcc..dc05c7d6bf5 100644 --- a/sdks/rust/tests/connect_disconnect_client/src/module_bindings/connected_type.rs +++ b/sdks/rust/tests/connect_disconnect_client/src/module_bindings/connected_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for Connected { ConnectedIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for Connected {} diff --git a/sdks/rust/tests/connect_disconnect_client/src/module_bindings/disconnected_type.rs b/sdks/rust/tests/connect_disconnect_client/src/module_bindings/disconnected_type.rs index 4349be485a7..b0d370c7fa4 100644 --- a/sdks/rust/tests/connect_disconnect_client/src/module_bindings/disconnected_type.rs +++ b/sdks/rust/tests/connect_disconnect_client/src/module_bindings/disconnected_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for Disconnected { DisconnectedIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for Disconnected {} diff --git a/sdks/rust/tests/connect_disconnect_client/src/module_bindings/mod.rs b/sdks/rust/tests/connect_disconnect_client/src/module_bindings/mod.rs index 0ee03e4d01b..90d0f869806 100644 --- a/sdks/rust/tests/connect_disconnect_client/src/module_bindings/mod.rs +++ b/sdks/rust/tests/connect_disconnect_client/src/module_bindings/mod.rs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.12.0 (commit 729b96fecd3ee7ab4f69443b80cafa6d39c2782e). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; diff --git a/sdks/rust/tests/event-table-client/Cargo.toml b/sdks/rust/tests/event-table-client/Cargo.toml new file mode 100644 index 00000000000..f6502644119 --- /dev/null +++ b/sdks/rust/tests/event-table-client/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "event-table-client" +version.workspace = true +edition.workspace = true + +[dependencies] +spacetimedb-sdk = { path = "../.." } +test-counter = { path = "../test-counter" } +anyhow.workspace = true +env_logger.workspace = true + +[lints] +workspace = true diff --git a/sdks/rust/tests/event-table-client/src/main.rs b/sdks/rust/tests/event-table-client/src/main.rs new file mode 100644 index 00000000000..5edb1fdfe0a --- /dev/null +++ b/sdks/rust/tests/event-table-client/src/main.rs @@ -0,0 +1,248 @@ +#[allow(clippy::too_many_arguments)] +#[allow(clippy::large_enum_variant)] +mod module_bindings; + +use module_bindings::*; + +use spacetimedb_sdk::{DbContext, Event, EventTable}; +use std::sync::atomic::{AtomicU32, Ordering}; +use test_counter::TestCounter; + +const LOCALHOST: &str = "http://localhost:3000"; + +fn db_name_or_panic() -> String { + std::env::var("SPACETIME_SDK_TEST_DB_NAME").expect("Failed to read db name from env") +} + +/// Register a panic hook which will exit the process whenever any thread panics. +/// +/// This allows us to fail tests by panicking in callbacks. +fn exit_on_panic() { + let default_hook = std::panic::take_hook(); + std::panic::set_hook(Box::new(move |panic_info| { + default_hook(panic_info); + std::process::exit(1); + })); +} + +macro_rules! assert_eq_or_bail { + ($expected:expr, $found:expr) => {{ + let expected = &$expected; + let found = &$found; + if expected != found { + anyhow::bail!( + "Expected {} => {:?} but found {} => {:?}", + stringify!($expected), + expected, + stringify!($found), + found + ); + } + }}; +} + +fn main() { + env_logger::init(); + exit_on_panic(); + + let test = std::env::args() + .nth(1) + .expect("Pass a test name as a command-line argument to the test client"); + + match &*test { + "event-table" => exec_event_table(), + "multiple-events" => exec_multiple_events(), + "events-dont-persist" => exec_events_dont_persist(), + "v1-rejects-event-table" => exec_v1_rejects_event_table(), + _ => panic!("Unknown test: {test}"), + } +} + +fn connect_then( + test_counter: &std::sync::Arc, + callback: impl FnOnce(&DbConnection) + Send + 'static, +) -> DbConnection { + let connected_result = test_counter.add_test("on_connect"); + let name = db_name_or_panic(); + let conn = DbConnection::builder() + .with_database_name(name) + .with_uri(LOCALHOST) + .on_connect(|ctx, _, _| { + callback(ctx); + connected_result(Ok(())); + }) + .on_connect_error(|_ctx, error| panic!("Connect errored: {error:?}")) + .build() + .unwrap(); + conn.run_threaded(); + conn +} + +fn subscribe_these_then( + ctx: &impl RemoteDbContext, + queries: &[&str], + callback: impl FnOnce(&SubscriptionEventContext) + Send + 'static, +) { + ctx.subscription_builder() + .on_applied(callback) + .on_error(|_ctx, error| panic!("Subscription errored: {error:?}")) + .subscribe(queries); +} + +fn exec_event_table() { + let test_counter = TestCounter::new(); + let sub_applied_result = test_counter.add_test("subscription_applied"); + let on_insert_result = test_counter.add_test("event-table-on-insert"); + let on_insert_result = std::sync::Mutex::new(Some(on_insert_result)); + + connect_then(&test_counter, { + move |ctx| { + subscribe_these_then(ctx, &["SELECT * FROM test_event;"], move |ctx| { + // Event table should be empty on subscription applied + assert_eq!(0usize, ctx.db.test_event().iter().count()); + sub_applied_result(Ok(())); + + ctx.db.test_event().on_insert(move |ctx, row| { + if let Some(set_result) = on_insert_result.lock().unwrap().take() { + let run_checks = || { + assert_eq_or_bail!("hello", row.name); + assert_eq_or_bail!(42u64, row.value); + + let Event::Reducer(reducer_event) = &ctx.event else { + anyhow::bail!("Expected a reducer event"); + }; + anyhow::ensure!( + matches!(reducer_event.reducer, Reducer::EmitTestEvent { .. }), + "Unexpected Reducer variant {:?}", + reducer_event.reducer, + ); + + // Event table rows are not cached + assert_eq_or_bail!(0u64, ctx.db.test_event().count()); + assert_eq_or_bail!(0usize, ctx.db.test_event().iter().count()); + + Ok(()) + }; + set_result(run_checks()); + } + }); + + ctx.reducers.emit_test_event("hello".to_string(), 42).unwrap(); + }); + } + }); + + test_counter.wait_for_all(); +} + +/// Test that multiple events emitted in a single reducer call all arrive as inserts. +fn exec_multiple_events() { + let test_counter = TestCounter::new(); + let sub_applied_result = test_counter.add_test("subscription_applied"); + let result = test_counter.add_test("multiple-events"); + let result = std::sync::Mutex::new(Some(result)); + + connect_then(&test_counter, { + move |ctx| { + subscribe_these_then(ctx, &["SELECT * FROM test_event;"], move |ctx| { + assert_eq!(0usize, ctx.db.test_event().iter().count()); + sub_applied_result(Ok(())); + + let received = std::sync::Arc::new(AtomicU32::new(0)); + + ctx.db.test_event().on_insert({ + let received = received.clone(); + move |_ctx, _row| { + let count = received.fetch_add(1, Ordering::SeqCst) + 1; + if count == 3 { + let set_result = result.lock().unwrap().take().unwrap(); + set_result(Ok(())); + } + } + }); + + ctx.reducers.emit_multiple_test_events().unwrap(); + }); + } + }); + + test_counter.wait_for_all(); +} + +/// Test that event table rows don't persist across transactions. +/// Emit events, then call a no-op reducer. After the no-op completes, +/// verify we didn't receive any additional event inserts. +fn exec_events_dont_persist() { + let test_counter = TestCounter::new(); + let sub_applied_result = test_counter.add_test("subscription_applied"); + let noop_result = test_counter.add_test("events-dont-persist"); + let noop_result = std::sync::Mutex::new(Some(noop_result)); + + connect_then(&test_counter, { + move |ctx| { + subscribe_these_then(ctx, &["SELECT * FROM test_event;"], move |ctx| { + assert_eq!(0usize, ctx.db.test_event().iter().count()); + sub_applied_result(Ok(())); + + let insert_count = std::sync::Arc::new(AtomicU32::new(0)); + + ctx.db.test_event().on_insert({ + let insert_count = insert_count.clone(); + move |_ctx, _row| { + insert_count.fetch_add(1, Ordering::SeqCst); + } + }); + + ctx.reducers.emit_test_event("hello".to_string(), 42).unwrap(); + + // After the noop reducer completes, the insert count should + // still be 1 from the emit_test_event call — no stale events. + ctx.reducers + .noop_then({ + let insert_count = insert_count.clone(); + move |_ctx, _result| { + let set_result = noop_result.lock().unwrap().take().unwrap(); + let count = insert_count.load(Ordering::SeqCst); + if count == 1 { + set_result(Ok(())); + } else { + set_result(Err(anyhow::anyhow!("Expected 1 event insert, but got {count}"))); + } + } + }) + .unwrap(); + }); + } + }); + + test_counter.wait_for_all(); +} + +/// Test that v1 WebSocket clients are rejected when subscribing to event tables. +/// The server should return a subscription error directing the developer to upgrade. +fn exec_v1_rejects_event_table() { + let test_counter = TestCounter::new(); + + connect_then(&test_counter, { + let test_counter = test_counter.clone(); + move |ctx| { + let error_result = test_counter.add_test("v1-rejects-event-table"); + + ctx.subscription_builder() + .on_applied(move |_ctx: &SubscriptionEventContext| { + panic!("Subscription to event table should not succeed over v1"); + }) + .on_error(move |_ctx, error| { + let msg = format!("{error:?}"); + if msg.contains("v2") || msg.contains("upgrade") || msg.contains("Upgrade") { + error_result(Ok(())); + } else { + error_result(Err(anyhow::anyhow!("Expected error about v2/upgrade, got: {msg}"))); + } + }) + .subscribe(["SELECT * FROM test_event;"]); + } + }); + + test_counter.wait_for_all(); +} diff --git a/templates/chat-console-rs/src/module_bindings/identity_disconnected_reducer.rs b/sdks/rust/tests/event-table-client/src/module_bindings/emit_multiple_test_events_reducer.rs similarity index 58% rename from templates/chat-console-rs/src/module_bindings/identity_disconnected_reducer.rs rename to sdks/rust/tests/event-table-client/src/module_bindings/emit_multiple_test_events_reducer.rs index 8cec050f73e..2ac3bcf9e2d 100644 --- a/templates/chat-console-rs/src/module_bindings/identity_disconnected_reducer.rs +++ b/sdks/rust/tests/event-table-client/src/module_bindings/emit_multiple_test_events_reducer.rs @@ -6,40 +6,40 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; #[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] #[sats(crate = __lib)] -pub(super) struct IdentityDisconnectedArgs {} +pub(super) struct EmitMultipleTestEventsArgs {} -impl From for super::Reducer { - fn from(args: IdentityDisconnectedArgs) -> Self { - Self::IdentityDisconnected +impl From for super::Reducer { + fn from(args: EmitMultipleTestEventsArgs) -> Self { + Self::EmitMultipleTestEvents } } -impl __sdk::InModule for IdentityDisconnectedArgs { +impl __sdk::InModule for EmitMultipleTestEventsArgs { type Module = super::RemoteModule; } #[allow(non_camel_case_types)] -/// Extension trait for access to the reducer `identity_disconnected`. +/// Extension trait for access to the reducer `emit_multiple_test_events`. /// /// Implemented for [`super::RemoteReducers`]. -pub trait identity_disconnected { - /// Request that the remote module invoke the reducer `identity_disconnected` to run as soon as possible. +pub trait emit_multiple_test_events { + /// Request that the remote module invoke the reducer `emit_multiple_test_events` to run as soon as possible. /// /// This method returns immediately, and errors only if we are unable to send the request. /// The reducer will run asynchronously in the future, /// and this method provides no way to listen for its completion status. - /// /// Use [`identity_disconnected:identity_disconnected_then`] to run a callback after the reducer completes. - fn identity_disconnected(&self) -> __sdk::Result<()> { - self.identity_disconnected_then(|_, _| {}) + /// /// Use [`emit_multiple_test_events:emit_multiple_test_events_then`] to run a callback after the reducer completes. + fn emit_multiple_test_events(&self) -> __sdk::Result<()> { + self.emit_multiple_test_events_then(|_, _| {}) } - /// Request that the remote module invoke the reducer `identity_disconnected` to run as soon as possible, + /// Request that the remote module invoke the reducer `emit_multiple_test_events` to run as soon as possible, /// registering `callback` to run when we are notified that the reducer completed. /// /// This method returns immediately, and errors only if we are unable to send the request. /// The reducer will run asynchronously in the future, /// and its status can be observed with the `callback`. - fn identity_disconnected_then( + fn emit_multiple_test_events_then( &self, callback: impl FnOnce(&super::ReducerEventContext, Result, __sdk::InternalError>) @@ -48,8 +48,8 @@ pub trait identity_disconnected { ) -> __sdk::Result<()>; } -impl identity_disconnected for super::RemoteReducers { - fn identity_disconnected_then( +impl emit_multiple_test_events for super::RemoteReducers { + fn emit_multiple_test_events_then( &self, callback: impl FnOnce(&super::ReducerEventContext, Result, __sdk::InternalError>) @@ -57,6 +57,6 @@ impl identity_disconnected for super::RemoteReducers { + 'static, ) -> __sdk::Result<()> { self.imp - .invoke_reducer_with_callback(IdentityDisconnectedArgs {}, callback) + .invoke_reducer_with_callback(EmitMultipleTestEventsArgs {}, callback) } } diff --git a/sdks/rust/tests/event-table-client/src/module_bindings/emit_test_event_reducer.rs b/sdks/rust/tests/event-table-client/src/module_bindings/emit_test_event_reducer.rs new file mode 100644 index 00000000000..d0e158e9e38 --- /dev/null +++ b/sdks/rust/tests/event-table-client/src/module_bindings/emit_test_event_reducer.rs @@ -0,0 +1,72 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub(super) struct EmitTestEventArgs { + pub name: String, + pub value: u64, +} + +impl From for super::Reducer { + fn from(args: EmitTestEventArgs) -> Self { + Self::EmitTestEvent { + name: args.name, + value: args.value, + } + } +} + +impl __sdk::InModule for EmitTestEventArgs { + type Module = super::RemoteModule; +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the reducer `emit_test_event`. +/// +/// Implemented for [`super::RemoteReducers`]. +pub trait emit_test_event { + /// Request that the remote module invoke the reducer `emit_test_event` to run as soon as possible. + /// + /// This method returns immediately, and errors only if we are unable to send the request. + /// The reducer will run asynchronously in the future, + /// and this method provides no way to listen for its completion status. + /// /// Use [`emit_test_event:emit_test_event_then`] to run a callback after the reducer completes. + fn emit_test_event(&self, name: String, value: u64) -> __sdk::Result<()> { + self.emit_test_event_then(name, value, |_, _| {}) + } + + /// Request that the remote module invoke the reducer `emit_test_event` to run as soon as possible, + /// registering `callback` to run when we are notified that the reducer completed. + /// + /// This method returns immediately, and errors only if we are unable to send the request. + /// The reducer will run asynchronously in the future, + /// and its status can be observed with the `callback`. + fn emit_test_event_then( + &self, + name: String, + value: u64, + + callback: impl FnOnce(&super::ReducerEventContext, Result, __sdk::InternalError>) + + Send + + 'static, + ) -> __sdk::Result<()>; +} + +impl emit_test_event for super::RemoteReducers { + fn emit_test_event_then( + &self, + name: String, + value: u64, + + callback: impl FnOnce(&super::ReducerEventContext, Result, __sdk::InternalError>) + + Send + + 'static, + ) -> __sdk::Result<()> { + self.imp + .invoke_reducer_with_callback(EmitTestEventArgs { name, value }, callback) + } +} diff --git a/sdks/rust/tests/event-table-client/src/module_bindings/mod.rs b/sdks/rust/tests/event-table-client/src/module_bindings/mod.rs new file mode 100644 index 00000000000..270a63fc8c2 --- /dev/null +++ b/sdks/rust/tests/event-table-client/src/module_bindings/mod.rs @@ -0,0 +1,795 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +// This was generated using spacetimedb cli version 2.0.0 (commit f9ecae027971fa57c15a8a38f49d2df66ee48026). + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +pub mod emit_multiple_test_events_reducer; +pub mod emit_test_event_reducer; +pub mod noop_reducer; +pub mod test_event_table; +pub mod test_event_type; + +pub use emit_multiple_test_events_reducer::emit_multiple_test_events; +pub use emit_test_event_reducer::emit_test_event; +pub use noop_reducer::noop; +pub use test_event_table::*; +pub use test_event_type::TestEvent; + +#[derive(Clone, PartialEq, Debug)] + +/// One of the reducers defined by this module. +/// +/// Contained within a [`__sdk::ReducerEvent`] in [`EventContext`]s for reducer events +/// to indicate which reducer caused the event. + +pub enum Reducer { + EmitMultipleTestEvents, + EmitTestEvent { name: String, value: u64 }, + Noop, +} + +impl __sdk::InModule for Reducer { + type Module = RemoteModule; +} + +impl __sdk::Reducer for Reducer { + fn reducer_name(&self) -> &'static str { + match self { + Reducer::EmitMultipleTestEvents => "emit_multiple_test_events", + Reducer::EmitTestEvent { .. } => "emit_test_event", + Reducer::Noop => "noop", + _ => unreachable!(), + } + } + #[allow(clippy::clone_on_copy)] + fn args_bsatn(&self) -> Result, __sats::bsatn::EncodeError> { + match self { + Reducer::EmitMultipleTestEvents => { + __sats::bsatn::to_vec(&emit_multiple_test_events_reducer::EmitMultipleTestEventsArgs {}) + } + Reducer::EmitTestEvent { name, value } => { + __sats::bsatn::to_vec(&emit_test_event_reducer::EmitTestEventArgs { + name: name.clone(), + value: value.clone(), + }) + } + Reducer::Noop => __sats::bsatn::to_vec(&noop_reducer::NoopArgs {}), + _ => unreachable!(), + } + } +} + +#[derive(Default)] +#[allow(non_snake_case)] +#[doc(hidden)] +pub struct DbUpdate { + test_event: __sdk::TableUpdate, +} + +impl TryFrom<__ws::v2::TransactionUpdate> for DbUpdate { + type Error = __sdk::Error; + fn try_from(raw: __ws::v2::TransactionUpdate) -> Result { + let mut db_update = DbUpdate::default(); + for table_update in __sdk::transaction_update_iter_table_updates(raw) { + match &table_update.table_name[..] { + "test_event" => db_update + .test_event + .append(test_event_table::parse_table_update(table_update)?), + + unknown => { + return Err(__sdk::InternalError::unknown_name("table", unknown, "DatabaseUpdate").into()); + } + } + } + Ok(db_update) + } +} + +impl __sdk::InModule for DbUpdate { + type Module = RemoteModule; +} + +impl __sdk::DbUpdate for DbUpdate { + fn apply_to_client_cache(&self, cache: &mut __sdk::ClientCache) -> AppliedDiff<'_> { + let mut diff = AppliedDiff::default(); + + diff.test_event = self.test_event.into_event_diff(); + + diff + } + fn parse_initial_rows(raw: __ws::v2::QueryRows) -> __sdk::Result { + let mut db_update = DbUpdate::default(); + for table_rows in raw.tables { + match &table_rows.table[..] { + "test_event" => db_update + .test_event + .append(__sdk::parse_row_list_as_inserts(table_rows.rows)?), + unknown => { + return Err(__sdk::InternalError::unknown_name("table", unknown, "QueryRows").into()); + } + } + } + Ok(db_update) + } + fn parse_unsubscribe_rows(raw: __ws::v2::QueryRows) -> __sdk::Result { + let mut db_update = DbUpdate::default(); + for table_rows in raw.tables { + match &table_rows.table[..] { + "test_event" => db_update + .test_event + .append(__sdk::parse_row_list_as_deletes(table_rows.rows)?), + unknown => { + return Err(__sdk::InternalError::unknown_name("table", unknown, "QueryRows").into()); + } + } + } + Ok(db_update) + } +} + +#[derive(Default)] +#[allow(non_snake_case)] +#[doc(hidden)] +pub struct AppliedDiff<'r> { + test_event: __sdk::TableAppliedDiff<'r, TestEvent>, + __unused: std::marker::PhantomData<&'r ()>, +} + +impl __sdk::InModule for AppliedDiff<'_> { + type Module = RemoteModule; +} + +impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> { + fn invoke_row_callbacks(&self, event: &EventContext, callbacks: &mut __sdk::DbCallbacks) { + callbacks.invoke_table_row_callbacks::("test_event", &self.test_event, event); + } +} + +#[doc(hidden)] +pub struct RemoteModule; + +impl __sdk::InModule for RemoteModule { + type Module = Self; +} + +/// The `reducers` field of [`EventContext`] and [`DbConnection`], +/// with methods provided by extension traits for each reducer defined by the module. +pub struct RemoteReducers { + imp: __sdk::DbContextImpl, +} + +impl __sdk::InModule for RemoteReducers { + type Module = RemoteModule; +} + +/// The `procedures` field of [`DbConnection`] and other [`DbContext`] types, +/// with methods provided by extension traits for each procedure defined by the module. +pub struct RemoteProcedures { + imp: __sdk::DbContextImpl, +} + +impl __sdk::InModule for RemoteProcedures { + type Module = RemoteModule; +} + +/// The `db` field of [`EventContext`] and [`DbConnection`], +/// with methods provided by extension traits for each table defined by the module. +pub struct RemoteTables { + imp: __sdk::DbContextImpl, +} + +impl __sdk::InModule for RemoteTables { + type Module = RemoteModule; +} + +/// A connection to a remote module, including a materialized view of a subset of the database. +/// +/// Connect to a remote module by calling [`DbConnection::builder`] +/// and using the [`__sdk::DbConnectionBuilder`] builder-pattern constructor. +/// +/// You must explicitly advance the connection by calling any one of: +/// +/// - [`DbConnection::frame_tick`]. +/// - [`DbConnection::run_threaded`]. +/// - [`DbConnection::run_async`]. +/// - [`DbConnection::advance_one_message`]. +/// - [`DbConnection::advance_one_message_blocking`]. +/// - [`DbConnection::advance_one_message_async`]. +/// +/// Which of these methods you should call depends on the specific needs of your application, +/// but you must call one of them, or else the connection will never progress. +pub struct DbConnection { + /// Access to tables defined by the module via extension traits implemented for [`RemoteTables`]. + pub db: RemoteTables, + /// Access to reducers defined by the module via extension traits implemented for [`RemoteReducers`]. + pub reducers: RemoteReducers, + #[doc(hidden)] + + /// Access to procedures defined by the module via extension traits implemented for [`RemoteProcedures`]. + pub procedures: RemoteProcedures, + + imp: __sdk::DbContextImpl, +} + +impl __sdk::InModule for DbConnection { + type Module = RemoteModule; +} + +impl __sdk::DbContext for DbConnection { + type DbView = RemoteTables; + type Reducers = RemoteReducers; + type Procedures = RemoteProcedures; + + fn db(&self) -> &Self::DbView { + &self.db + } + fn reducers(&self) -> &Self::Reducers { + &self.reducers + } + fn procedures(&self) -> &Self::Procedures { + &self.procedures + } + + fn is_active(&self) -> bool { + self.imp.is_active() + } + + fn disconnect(&self) -> __sdk::Result<()> { + self.imp.disconnect() + } + + type SubscriptionBuilder = __sdk::SubscriptionBuilder; + + fn subscription_builder(&self) -> Self::SubscriptionBuilder { + __sdk::SubscriptionBuilder::new(&self.imp) + } + + fn try_identity(&self) -> Option<__sdk::Identity> { + self.imp.try_identity() + } + fn connection_id(&self) -> __sdk::ConnectionId { + self.imp.connection_id() + } + fn try_connection_id(&self) -> Option<__sdk::ConnectionId> { + self.imp.try_connection_id() + } +} + +impl DbConnection { + /// Builder-pattern constructor for a connection to a remote module. + /// + /// See [`__sdk::DbConnectionBuilder`] for required and optional configuration for the new connection. + pub fn builder() -> __sdk::DbConnectionBuilder { + __sdk::DbConnectionBuilder::new() + } + + /// If any WebSocket messages are waiting, process one of them. + /// + /// Returns `true` if a message was processed, or `false` if the queue is empty. + /// Callers should invoke this message in a loop until it returns `false` + /// or for as much time is available to process messages. + /// + /// Returns an error if the connection is disconnected. + /// If the disconnection in question was normal, + /// i.e. the result of a call to [`__sdk::DbContext::disconnect`], + /// the returned error will be downcastable to [`__sdk::DisconnectedError`]. + /// + /// This is a low-level primitive exposed for power users who need significant control over scheduling. + /// Most applications should call [`Self::frame_tick`] each frame + /// to fully exhaust the queue whenever time is available. + pub fn advance_one_message(&self) -> __sdk::Result { + self.imp.advance_one_message() + } + + /// Process one WebSocket message, potentially blocking the current thread until one is received. + /// + /// Returns an error if the connection is disconnected. + /// If the disconnection in question was normal, + /// i.e. the result of a call to [`__sdk::DbContext::disconnect`], + /// the returned error will be downcastable to [`__sdk::DisconnectedError`]. + /// + /// This is a low-level primitive exposed for power users who need significant control over scheduling. + /// Most applications should call [`Self::run_threaded`] to spawn a thread + /// which advances the connection automatically. + pub fn advance_one_message_blocking(&self) -> __sdk::Result<()> { + self.imp.advance_one_message_blocking() + } + + /// Process one WebSocket message, `await`ing until one is received. + /// + /// Returns an error if the connection is disconnected. + /// If the disconnection in question was normal, + /// i.e. the result of a call to [`__sdk::DbContext::disconnect`], + /// the returned error will be downcastable to [`__sdk::DisconnectedError`]. + /// + /// This is a low-level primitive exposed for power users who need significant control over scheduling. + /// Most applications should call [`Self::run_async`] to run an `async` loop + /// which advances the connection when polled. + pub async fn advance_one_message_async(&self) -> __sdk::Result<()> { + self.imp.advance_one_message_async().await + } + + /// Process all WebSocket messages waiting in the queue, + /// then return without `await`ing or blocking the current thread. + pub fn frame_tick(&self) -> __sdk::Result<()> { + self.imp.frame_tick() + } + + /// Spawn a thread which processes WebSocket messages as they are received. + pub fn run_threaded(&self) -> std::thread::JoinHandle<()> { + self.imp.run_threaded() + } + + /// Run an `async` loop which processes WebSocket messages when polled. + pub async fn run_async(&self) -> __sdk::Result<()> { + self.imp.run_async().await + } +} + +impl __sdk::DbConnection for DbConnection { + fn new(imp: __sdk::DbContextImpl) -> Self { + Self { + db: RemoteTables { imp: imp.clone() }, + reducers: RemoteReducers { imp: imp.clone() }, + procedures: RemoteProcedures { imp: imp.clone() }, + imp, + } + } +} + +/// A handle on a subscribed query. +// TODO: Document this better after implementing the new subscription API. +#[derive(Clone)] +pub struct SubscriptionHandle { + imp: __sdk::SubscriptionHandleImpl, +} + +impl __sdk::InModule for SubscriptionHandle { + type Module = RemoteModule; +} + +impl __sdk::SubscriptionHandle for SubscriptionHandle { + fn new(imp: __sdk::SubscriptionHandleImpl) -> Self { + Self { imp } + } + + /// Returns true if this subscription has been terminated due to an unsubscribe call or an error. + fn is_ended(&self) -> bool { + self.imp.is_ended() + } + + /// Returns true if this subscription has been applied and has not yet been unsubscribed. + fn is_active(&self) -> bool { + self.imp.is_active() + } + + /// Unsubscribe from the query controlled by this `SubscriptionHandle`, + /// then run `on_end` when its rows are removed from the client cache. + fn unsubscribe_then(self, on_end: __sdk::OnEndedCallback) -> __sdk::Result<()> { + self.imp.unsubscribe_then(Some(on_end)) + } + + fn unsubscribe(self) -> __sdk::Result<()> { + self.imp.unsubscribe_then(None) + } +} + +/// Alias trait for a [`__sdk::DbContext`] connected to this module, +/// with that trait's associated types bounded to this module's concrete types. +/// +/// Users can use this trait as a boundary on definitions which should accept +/// either a [`DbConnection`] or an [`EventContext`] and operate on either. +pub trait RemoteDbContext: + __sdk::DbContext< + DbView = RemoteTables, + Reducers = RemoteReducers, + SubscriptionBuilder = __sdk::SubscriptionBuilder, +> +{ +} +impl< + Ctx: __sdk::DbContext< + DbView = RemoteTables, + Reducers = RemoteReducers, + SubscriptionBuilder = __sdk::SubscriptionBuilder, + >, + > RemoteDbContext for Ctx +{ +} + +/// An [`__sdk::DbContext`] augmented with a [`__sdk::Event`], +/// passed to [`__sdk::Table::on_insert`], [`__sdk::Table::on_delete`] and [`__sdk::TableWithPrimaryKey::on_update`] callbacks. +pub struct EventContext { + /// Access to tables defined by the module via extension traits implemented for [`RemoteTables`]. + pub db: RemoteTables, + /// Access to reducers defined by the module via extension traits implemented for [`RemoteReducers`]. + pub reducers: RemoteReducers, + /// Access to procedures defined by the module via extension traits implemented for [`RemoteProcedures`]. + pub procedures: RemoteProcedures, + /// The event which caused these callbacks to run. + pub event: __sdk::Event, + imp: __sdk::DbContextImpl, +} + +impl __sdk::AbstractEventContext for EventContext { + type Event = __sdk::Event; + fn event(&self) -> &Self::Event { + &self.event + } + fn new(imp: __sdk::DbContextImpl, event: Self::Event) -> Self { + Self { + db: RemoteTables { imp: imp.clone() }, + reducers: RemoteReducers { imp: imp.clone() }, + procedures: RemoteProcedures { imp: imp.clone() }, + event, + imp, + } + } +} + +impl __sdk::InModule for EventContext { + type Module = RemoteModule; +} + +impl __sdk::DbContext for EventContext { + type DbView = RemoteTables; + type Reducers = RemoteReducers; + type Procedures = RemoteProcedures; + + fn db(&self) -> &Self::DbView { + &self.db + } + fn reducers(&self) -> &Self::Reducers { + &self.reducers + } + fn procedures(&self) -> &Self::Procedures { + &self.procedures + } + + fn is_active(&self) -> bool { + self.imp.is_active() + } + + fn disconnect(&self) -> __sdk::Result<()> { + self.imp.disconnect() + } + + type SubscriptionBuilder = __sdk::SubscriptionBuilder; + + fn subscription_builder(&self) -> Self::SubscriptionBuilder { + __sdk::SubscriptionBuilder::new(&self.imp) + } + + fn try_identity(&self) -> Option<__sdk::Identity> { + self.imp.try_identity() + } + fn connection_id(&self) -> __sdk::ConnectionId { + self.imp.connection_id() + } + fn try_connection_id(&self) -> Option<__sdk::ConnectionId> { + self.imp.try_connection_id() + } +} + +impl __sdk::EventContext for EventContext {} + +/// An [`__sdk::DbContext`] augmented with a [`__sdk::ReducerEvent`], +/// passed to on-reducer callbacks. +pub struct ReducerEventContext { + /// Access to tables defined by the module via extension traits implemented for [`RemoteTables`]. + pub db: RemoteTables, + /// Access to reducers defined by the module via extension traits implemented for [`RemoteReducers`]. + pub reducers: RemoteReducers, + /// Access to procedures defined by the module via extension traits implemented for [`RemoteProcedures`]. + pub procedures: RemoteProcedures, + /// The event which caused these callbacks to run. + pub event: __sdk::ReducerEvent, + imp: __sdk::DbContextImpl, +} + +impl __sdk::AbstractEventContext for ReducerEventContext { + type Event = __sdk::ReducerEvent; + fn event(&self) -> &Self::Event { + &self.event + } + fn new(imp: __sdk::DbContextImpl, event: Self::Event) -> Self { + Self { + db: RemoteTables { imp: imp.clone() }, + reducers: RemoteReducers { imp: imp.clone() }, + procedures: RemoteProcedures { imp: imp.clone() }, + event, + imp, + } + } +} + +impl __sdk::InModule for ReducerEventContext { + type Module = RemoteModule; +} + +impl __sdk::DbContext for ReducerEventContext { + type DbView = RemoteTables; + type Reducers = RemoteReducers; + type Procedures = RemoteProcedures; + + fn db(&self) -> &Self::DbView { + &self.db + } + fn reducers(&self) -> &Self::Reducers { + &self.reducers + } + fn procedures(&self) -> &Self::Procedures { + &self.procedures + } + + fn is_active(&self) -> bool { + self.imp.is_active() + } + + fn disconnect(&self) -> __sdk::Result<()> { + self.imp.disconnect() + } + + type SubscriptionBuilder = __sdk::SubscriptionBuilder; + + fn subscription_builder(&self) -> Self::SubscriptionBuilder { + __sdk::SubscriptionBuilder::new(&self.imp) + } + + fn try_identity(&self) -> Option<__sdk::Identity> { + self.imp.try_identity() + } + fn connection_id(&self) -> __sdk::ConnectionId { + self.imp.connection_id() + } + fn try_connection_id(&self) -> Option<__sdk::ConnectionId> { + self.imp.try_connection_id() + } +} + +impl __sdk::ReducerEventContext for ReducerEventContext {} + +/// An [`__sdk::DbContext`] passed to procedure callbacks. +pub struct ProcedureEventContext { + /// Access to tables defined by the module via extension traits implemented for [`RemoteTables`]. + pub db: RemoteTables, + /// Access to reducers defined by the module via extension traits implemented for [`RemoteReducers`]. + pub reducers: RemoteReducers, + /// Access to procedures defined by the module via extension traits implemented for [`RemoteProcedures`]. + pub procedures: RemoteProcedures, + imp: __sdk::DbContextImpl, +} + +impl __sdk::AbstractEventContext for ProcedureEventContext { + type Event = (); + fn event(&self) -> &Self::Event { + &() + } + fn new(imp: __sdk::DbContextImpl, _event: Self::Event) -> Self { + Self { + db: RemoteTables { imp: imp.clone() }, + reducers: RemoteReducers { imp: imp.clone() }, + procedures: RemoteProcedures { imp: imp.clone() }, + imp, + } + } +} + +impl __sdk::InModule for ProcedureEventContext { + type Module = RemoteModule; +} + +impl __sdk::DbContext for ProcedureEventContext { + type DbView = RemoteTables; + type Reducers = RemoteReducers; + type Procedures = RemoteProcedures; + + fn db(&self) -> &Self::DbView { + &self.db + } + fn reducers(&self) -> &Self::Reducers { + &self.reducers + } + fn procedures(&self) -> &Self::Procedures { + &self.procedures + } + + fn is_active(&self) -> bool { + self.imp.is_active() + } + + fn disconnect(&self) -> __sdk::Result<()> { + self.imp.disconnect() + } + + type SubscriptionBuilder = __sdk::SubscriptionBuilder; + + fn subscription_builder(&self) -> Self::SubscriptionBuilder { + __sdk::SubscriptionBuilder::new(&self.imp) + } + + fn try_identity(&self) -> Option<__sdk::Identity> { + self.imp.try_identity() + } + fn connection_id(&self) -> __sdk::ConnectionId { + self.imp.connection_id() + } + fn try_connection_id(&self) -> Option<__sdk::ConnectionId> { + self.imp.try_connection_id() + } +} + +impl __sdk::ProcedureEventContext for ProcedureEventContext {} + +/// An [`__sdk::DbContext`] passed to [`__sdk::SubscriptionBuilder::on_applied`] and [`SubscriptionHandle::unsubscribe_then`] callbacks. +pub struct SubscriptionEventContext { + /// Access to tables defined by the module via extension traits implemented for [`RemoteTables`]. + pub db: RemoteTables, + /// Access to reducers defined by the module via extension traits implemented for [`RemoteReducers`]. + pub reducers: RemoteReducers, + /// Access to procedures defined by the module via extension traits implemented for [`RemoteProcedures`]. + pub procedures: RemoteProcedures, + imp: __sdk::DbContextImpl, +} + +impl __sdk::AbstractEventContext for SubscriptionEventContext { + type Event = (); + fn event(&self) -> &Self::Event { + &() + } + fn new(imp: __sdk::DbContextImpl, _event: Self::Event) -> Self { + Self { + db: RemoteTables { imp: imp.clone() }, + reducers: RemoteReducers { imp: imp.clone() }, + procedures: RemoteProcedures { imp: imp.clone() }, + imp, + } + } +} + +impl __sdk::InModule for SubscriptionEventContext { + type Module = RemoteModule; +} + +impl __sdk::DbContext for SubscriptionEventContext { + type DbView = RemoteTables; + type Reducers = RemoteReducers; + type Procedures = RemoteProcedures; + + fn db(&self) -> &Self::DbView { + &self.db + } + fn reducers(&self) -> &Self::Reducers { + &self.reducers + } + fn procedures(&self) -> &Self::Procedures { + &self.procedures + } + + fn is_active(&self) -> bool { + self.imp.is_active() + } + + fn disconnect(&self) -> __sdk::Result<()> { + self.imp.disconnect() + } + + type SubscriptionBuilder = __sdk::SubscriptionBuilder; + + fn subscription_builder(&self) -> Self::SubscriptionBuilder { + __sdk::SubscriptionBuilder::new(&self.imp) + } + + fn try_identity(&self) -> Option<__sdk::Identity> { + self.imp.try_identity() + } + fn connection_id(&self) -> __sdk::ConnectionId { + self.imp.connection_id() + } + fn try_connection_id(&self) -> Option<__sdk::ConnectionId> { + self.imp.try_connection_id() + } +} + +impl __sdk::SubscriptionEventContext for SubscriptionEventContext {} + +/// An [`__sdk::DbContext`] augmented with a [`__sdk::Error`], +/// passed to [`__sdk::DbConnectionBuilder::on_disconnect`], [`__sdk::DbConnectionBuilder::on_connect_error`] and [`__sdk::SubscriptionBuilder::on_error`] callbacks. +pub struct ErrorContext { + /// Access to tables defined by the module via extension traits implemented for [`RemoteTables`]. + pub db: RemoteTables, + /// Access to reducers defined by the module via extension traits implemented for [`RemoteReducers`]. + pub reducers: RemoteReducers, + /// Access to procedures defined by the module via extension traits implemented for [`RemoteProcedures`]. + pub procedures: RemoteProcedures, + /// The event which caused these callbacks to run. + pub event: Option<__sdk::Error>, + imp: __sdk::DbContextImpl, +} + +impl __sdk::AbstractEventContext for ErrorContext { + type Event = Option<__sdk::Error>; + fn event(&self) -> &Self::Event { + &self.event + } + fn new(imp: __sdk::DbContextImpl, event: Self::Event) -> Self { + Self { + db: RemoteTables { imp: imp.clone() }, + reducers: RemoteReducers { imp: imp.clone() }, + procedures: RemoteProcedures { imp: imp.clone() }, + event, + imp, + } + } +} + +impl __sdk::InModule for ErrorContext { + type Module = RemoteModule; +} + +impl __sdk::DbContext for ErrorContext { + type DbView = RemoteTables; + type Reducers = RemoteReducers; + type Procedures = RemoteProcedures; + + fn db(&self) -> &Self::DbView { + &self.db + } + fn reducers(&self) -> &Self::Reducers { + &self.reducers + } + fn procedures(&self) -> &Self::Procedures { + &self.procedures + } + + fn is_active(&self) -> bool { + self.imp.is_active() + } + + fn disconnect(&self) -> __sdk::Result<()> { + self.imp.disconnect() + } + + type SubscriptionBuilder = __sdk::SubscriptionBuilder; + + fn subscription_builder(&self) -> Self::SubscriptionBuilder { + __sdk::SubscriptionBuilder::new(&self.imp) + } + + fn try_identity(&self) -> Option<__sdk::Identity> { + self.imp.try_identity() + } + fn connection_id(&self) -> __sdk::ConnectionId { + self.imp.connection_id() + } + fn try_connection_id(&self) -> Option<__sdk::ConnectionId> { + self.imp.try_connection_id() + } +} + +impl __sdk::ErrorContext for ErrorContext {} + +impl __sdk::SpacetimeModule for RemoteModule { + type DbConnection = DbConnection; + type EventContext = EventContext; + type ReducerEventContext = ReducerEventContext; + type ProcedureEventContext = ProcedureEventContext; + type SubscriptionEventContext = SubscriptionEventContext; + type ErrorContext = ErrorContext; + type Reducer = Reducer; + type DbView = RemoteTables; + type Reducers = RemoteReducers; + type Procedures = RemoteProcedures; + type DbUpdate = DbUpdate; + type AppliedDiff<'r> = AppliedDiff<'r>; + type SubscriptionHandle = SubscriptionHandle; + type QueryBuilder = __sdk::QueryBuilder; + + fn register_tables(client_cache: &mut __sdk::ClientCache) { + test_event_table::register_table(client_cache); + } + const ALL_TABLE_NAMES: &'static [&'static str] = &["test_event"]; +} diff --git a/templates/chat-console-rs/src/module_bindings/identity_connected_reducer.rs b/sdks/rust/tests/event-table-client/src/module_bindings/noop_reducer.rs similarity index 59% rename from templates/chat-console-rs/src/module_bindings/identity_connected_reducer.rs rename to sdks/rust/tests/event-table-client/src/module_bindings/noop_reducer.rs index cfbf1d03d30..f999e055148 100644 --- a/templates/chat-console-rs/src/module_bindings/identity_connected_reducer.rs +++ b/sdks/rust/tests/event-table-client/src/module_bindings/noop_reducer.rs @@ -6,40 +6,40 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; #[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] #[sats(crate = __lib)] -pub(super) struct IdentityConnectedArgs {} +pub(super) struct NoopArgs {} -impl From for super::Reducer { - fn from(args: IdentityConnectedArgs) -> Self { - Self::IdentityConnected +impl From for super::Reducer { + fn from(args: NoopArgs) -> Self { + Self::Noop } } -impl __sdk::InModule for IdentityConnectedArgs { +impl __sdk::InModule for NoopArgs { type Module = super::RemoteModule; } #[allow(non_camel_case_types)] -/// Extension trait for access to the reducer `identity_connected`. +/// Extension trait for access to the reducer `noop`. /// /// Implemented for [`super::RemoteReducers`]. -pub trait identity_connected { - /// Request that the remote module invoke the reducer `identity_connected` to run as soon as possible. +pub trait noop { + /// Request that the remote module invoke the reducer `noop` to run as soon as possible. /// /// This method returns immediately, and errors only if we are unable to send the request. /// The reducer will run asynchronously in the future, /// and this method provides no way to listen for its completion status. - /// /// Use [`identity_connected:identity_connected_then`] to run a callback after the reducer completes. - fn identity_connected(&self) -> __sdk::Result<()> { - self.identity_connected_then(|_, _| {}) + /// /// Use [`noop:noop_then`] to run a callback after the reducer completes. + fn noop(&self) -> __sdk::Result<()> { + self.noop_then(|_, _| {}) } - /// Request that the remote module invoke the reducer `identity_connected` to run as soon as possible, + /// Request that the remote module invoke the reducer `noop` to run as soon as possible, /// registering `callback` to run when we are notified that the reducer completed. /// /// This method returns immediately, and errors only if we are unable to send the request. /// The reducer will run asynchronously in the future, /// and its status can be observed with the `callback`. - fn identity_connected_then( + fn noop_then( &self, callback: impl FnOnce(&super::ReducerEventContext, Result, __sdk::InternalError>) @@ -48,15 +48,14 @@ pub trait identity_connected { ) -> __sdk::Result<()>; } -impl identity_connected for super::RemoteReducers { - fn identity_connected_then( +impl noop for super::RemoteReducers { + fn noop_then( &self, callback: impl FnOnce(&super::ReducerEventContext, Result, __sdk::InternalError>) + Send + 'static, ) -> __sdk::Result<()> { - self.imp - .invoke_reducer_with_callback(IdentityConnectedArgs {}, callback) + self.imp.invoke_reducer_with_callback(NoopArgs {}, callback) } } diff --git a/sdks/rust/tests/event-table-client/src/module_bindings/test_event_table.rs b/sdks/rust/tests/event-table-client/src/module_bindings/test_event_table.rs new file mode 100644 index 00000000000..b6d14f66674 --- /dev/null +++ b/sdks/rust/tests/event-table-client/src/module_bindings/test_event_table.rs @@ -0,0 +1,95 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use super::test_event_type::TestEvent; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `test_event`. +/// +/// Obtain a handle from the [`TestEventTableAccess::test_event`] method on [`super::RemoteTables`], +/// like `ctx.db.test_event()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.test_event().on_insert(...)`. +pub struct TestEventTableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `test_event`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait TestEventTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`TestEventTableHandle`], which mediates access to the table `test_event`. + fn test_event(&self) -> TestEventTableHandle<'_>; +} + +impl TestEventTableAccess for super::RemoteTables { + fn test_event(&self) -> TestEventTableHandle<'_> { + TestEventTableHandle { + imp: self.imp.get_table::("test_event"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct TestEventInsertCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::EventTable for TestEventTableHandle<'ctx> { + type Row = TestEvent; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = TestEventInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> TestEventInsertCallbackId { + TestEventInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: TestEventInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("test_event"); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + +#[allow(non_camel_case_types)] +/// Extension trait for query builder access to the table `TestEvent`. +/// +/// Implemented for [`__sdk::QueryTableAccessor`]. +pub trait test_eventQueryTableAccess { + #[allow(non_snake_case)] + /// Get a query builder for the table `TestEvent`. + fn test_event(&self) -> __sdk::__query_builder::Table; +} + +impl test_eventQueryTableAccess for __sdk::QueryTableAccessor { + fn test_event(&self) -> __sdk::__query_builder::Table { + __sdk::__query_builder::Table::new("test_event") + } +} diff --git a/sdks/rust/tests/event-table-client/src/module_bindings/test_event_type.rs b/sdks/rust/tests/event-table-client/src/module_bindings/test_event_type.rs new file mode 100644 index 00000000000..03025351b0a --- /dev/null +++ b/sdks/rust/tests/event-table-client/src/module_bindings/test_event_type.rs @@ -0,0 +1,46 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#![allow(unused, clippy::all)] +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct TestEvent { + pub name: String, + pub value: u64, +} + +impl __sdk::InModule for TestEvent { + type Module = super::RemoteModule; +} + +/// Column accessor struct for the table `TestEvent`. +/// +/// Provides typed access to columns for query building. +pub struct TestEventCols { + pub name: __sdk::__query_builder::Col, + pub value: __sdk::__query_builder::Col, +} + +impl __sdk::__query_builder::HasCols for TestEvent { + type Cols = TestEventCols; + fn cols(table_name: &'static str) -> Self::Cols { + TestEventCols { + name: __sdk::__query_builder::Col::new(table_name, "name"), + value: __sdk::__query_builder::Col::new(table_name, "value"), + } + } +} + +/// Indexed column accessor struct for the table `TestEvent`. +/// +/// Provides typed access to indexed columns for query building. +pub struct TestEventIxCols {} + +impl __sdk::__query_builder::HasIxCols for TestEvent { + type IxCols = TestEventIxCols; + fn ix_cols(table_name: &'static str) -> Self::IxCols { + TestEventIxCols {} + } +} diff --git a/sdks/rust/tests/procedure-client/src/module_bindings/mod.rs b/sdks/rust/tests/procedure-client/src/module_bindings/mod.rs index 10a4b6f3e9a..48c7c60f064 100644 --- a/sdks/rust/tests/procedure-client/src/module_bindings/mod.rs +++ b/sdks/rust/tests/procedure-client/src/module_bindings/mod.rs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.12.0 (commit 729b96fecd3ee7ab4f69443b80cafa6d39c2782e). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; diff --git a/sdks/rust/tests/procedure-client/src/module_bindings/my_table_type.rs b/sdks/rust/tests/procedure-client/src/module_bindings/my_table_type.rs index 82cd36470f0..a360bcaab32 100644 --- a/sdks/rust/tests/procedure-client/src/module_bindings/my_table_type.rs +++ b/sdks/rust/tests/procedure-client/src/module_bindings/my_table_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for MyTable { MyTableIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for MyTable {} diff --git a/sdks/rust/tests/procedure-client/src/module_bindings/pk_uuid_type.rs b/sdks/rust/tests/procedure-client/src/module_bindings/pk_uuid_type.rs index 1012ac4e4d8..dcc8174a6b3 100644 --- a/sdks/rust/tests/procedure-client/src/module_bindings/pk_uuid_type.rs +++ b/sdks/rust/tests/procedure-client/src/module_bindings/pk_uuid_type.rs @@ -44,3 +44,5 @@ impl __sdk::__query_builder::HasIxCols for PkUuid { PkUuidIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for PkUuid {} diff --git a/sdks/rust/tests/procedure-client/src/module_bindings/proc_inserts_into_type.rs b/sdks/rust/tests/procedure-client/src/module_bindings/proc_inserts_into_type.rs index 05765b70b28..f06a33b31cb 100644 --- a/sdks/rust/tests/procedure-client/src/module_bindings/proc_inserts_into_type.rs +++ b/sdks/rust/tests/procedure-client/src/module_bindings/proc_inserts_into_type.rs @@ -50,3 +50,5 @@ impl __sdk::__query_builder::HasIxCols for ProcInsertsInto { ProcInsertsIntoIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for ProcInsertsInto {} diff --git a/sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_table_table.rs b/sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_table_table.rs index df400812211..03f3ea0fda9 100644 --- a/sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_table_table.rs +++ b/sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_table_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for ScheduledProcTableTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("scheduled_proc_table"); - _table.add_unique_constraint::("scheduled_id", |row| &row.scheduled_id); -} pub struct ScheduledProcTableUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for ScheduledProcTableTableHandle<'ctx> { @@ -100,17 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for ScheduledProcTableTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::v2::TableUpdate, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `scheduled_id` unique index on the table `scheduled_proc_table`, /// which allows point queries on the field of the same name /// via the [`ScheduledProcTableScheduledIdUnique::find`] method. @@ -141,6 +125,23 @@ impl<'ctx> ScheduledProcTableScheduledIdUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("scheduled_proc_table"); + _table.add_unique_constraint::("scheduled_id", |row| &row.scheduled_id); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `ScheduledProcTable`. /// diff --git a/sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_table_type.rs b/sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_table_type.rs index 18f17e192ab..63dc6bfa8c4 100644 --- a/sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_table_type.rs +++ b/sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_table_type.rs @@ -57,3 +57,5 @@ impl __sdk::__query_builder::HasIxCols for ScheduledProcTable { } } } + +impl __sdk::__query_builder::CanBeLookupTable for ScheduledProcTable {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/b_tree_u_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/b_tree_u_32_type.rs index 4697837f624..0453db7ae66 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/b_tree_u_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/b_tree_u_32_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for BTreeU32 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for BTreeU32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/indexed_simple_enum_type.rs b/sdks/rust/tests/test-client/src/module_bindings/indexed_simple_enum_type.rs index 36d13c5496a..58282b102a9 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/indexed_simple_enum_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/indexed_simple_enum_type.rs @@ -47,3 +47,5 @@ impl __sdk::__query_builder::HasIxCols for IndexedSimpleEnum { } } } + +impl __sdk::__query_builder::CanBeLookupTable for IndexedSimpleEnum {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/indexed_table_2_type.rs b/sdks/rust/tests/test-client/src/module_bindings/indexed_table_2_type.rs index b9c9a0abb67..368e21c6641 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/indexed_table_2_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/indexed_table_2_type.rs @@ -44,3 +44,5 @@ impl __sdk::__query_builder::HasIxCols for IndexedTable2 { IndexedTable2IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for IndexedTable2 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/indexed_table_type.rs b/sdks/rust/tests/test-client/src/module_bindings/indexed_table_type.rs index 3f889c780dd..ca74210d615 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/indexed_table_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/indexed_table_type.rs @@ -45,3 +45,5 @@ impl __sdk::__query_builder::HasIxCols for IndexedTable { } } } + +impl __sdk::__query_builder::CanBeLookupTable for IndexedTable {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/large_table_type.rs b/sdks/rust/tests/test-client/src/module_bindings/large_table_type.rs index 4fc4378d700..aa1581e17fa 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/large_table_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/large_table_type.rs @@ -111,3 +111,5 @@ impl __sdk::__query_builder::HasIxCols for LargeTable { LargeTableIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for LargeTable {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/mod.rs b/sdks/rust/tests/test-client/src/module_bindings/mod.rs index f121d15eeb9..aa02043ad19 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/mod.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/mod.rs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.12.0 (commit 729b96fecd3ee7ab4f69443b80cafa6d39c2782e). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_bool_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_bool_type.rs index 430f9301e6d..d91d401ebd9 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_bool_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_bool_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneBool { OneBoolIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneBool {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_byte_struct_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_byte_struct_type.rs index 351eee787d4..351c6443c7a 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_byte_struct_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_byte_struct_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for OneByteStruct { OneByteStructIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneByteStruct {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_connection_id_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_connection_id_type.rs index 2be3c7ee2ed..4b16ca7dfcd 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_connection_id_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_connection_id_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneConnectionId { OneConnectionIdIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneConnectionId {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_enum_with_payload_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_enum_with_payload_type.rs index 46096c40139..c544a9b52cc 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_enum_with_payload_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_enum_with_payload_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for OneEnumWithPayload { OneEnumWithPayloadIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneEnumWithPayload {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_every_primitive_struct_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_every_primitive_struct_type.rs index 1a96a23f4ae..688cc4efddd 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_every_primitive_struct_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_every_primitive_struct_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for OneEveryPrimitiveStruct { OneEveryPrimitiveStructIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneEveryPrimitiveStruct {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_every_vec_struct_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_every_vec_struct_type.rs index 03a7de83002..375e11e3c0e 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_every_vec_struct_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_every_vec_struct_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for OneEveryVecStruct { OneEveryVecStructIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneEveryVecStruct {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_f_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_f_32_type.rs index 34f2df8c2a5..ac2ee3e1110 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_f_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_f_32_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneF32 { OneF32IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneF32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_f_64_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_f_64_type.rs index 81569d91fd9..f023a2afbca 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_f_64_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_f_64_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneF64 { OneF64IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneF64 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_i_128_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_i_128_type.rs index 79f23eaf8d9..36a08cd03b3 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_i_128_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_i_128_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneI128 { OneI128IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneI128 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_i_16_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_i_16_type.rs index bcc3cf72cb5..051ceb7f677 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_i_16_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_i_16_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneI16 { OneI16IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneI16 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_i_256_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_i_256_type.rs index 7226d1ba3e8..68d94968af9 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_i_256_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_i_256_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneI256 { OneI256IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneI256 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_i_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_i_32_type.rs index 037740e9a37..91d98a75a3f 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_i_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_i_32_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneI32 { OneI32IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneI32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_i_64_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_i_64_type.rs index 4a5d7fc4937..20eea08bba2 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_i_64_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_i_64_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneI64 { OneI64IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneI64 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_i_8_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_i_8_type.rs index 9e5a5e9875e..886e0152acd 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_i_8_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_i_8_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneI8 { OneI8IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneI8 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_identity_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_identity_type.rs index cf084da63f6..c394cbe6b5c 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_identity_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_identity_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneIdentity { OneIdentityIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneIdentity {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_simple_enum_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_simple_enum_type.rs index 3a9fdec6366..709946fe51a 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_simple_enum_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_simple_enum_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for OneSimpleEnum { OneSimpleEnumIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneSimpleEnum {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_string_type.rs index b865038c2ad..483871a58ec 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_string_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_string_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneString { OneStringIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneString {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_timestamp_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_timestamp_type.rs index 627dc23f012..fb84d4f1f08 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_timestamp_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_timestamp_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneTimestamp { OneTimestampIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneTimestamp {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_u_128_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_u_128_type.rs index 37a5596dfb7..ebacc86601d 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_u_128_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_u_128_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneU128 { OneU128IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneU128 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_u_16_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_u_16_type.rs index 14d5ae4ca66..2326dfa3cdd 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_u_16_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_u_16_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneU16 { OneU16IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneU16 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_u_256_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_u_256_type.rs index f46374339c6..431897ed9f6 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_u_256_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_u_256_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneU256 { OneU256IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneU256 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_u_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_u_32_type.rs index 631a64eba6e..c0277eae098 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_u_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_u_32_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneU32 { OneU32IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneU32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_u_64_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_u_64_type.rs index d28962f0807..113b4cde7c7 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_u_64_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_u_64_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneU64 { OneU64IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneU64 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_u_8_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_u_8_type.rs index 2f2c371fc58..e145bafcf2b 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_u_8_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_u_8_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneU8 { OneU8IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneU8 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_unit_struct_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_unit_struct_type.rs index ca2a9f6aea8..86e0c90fc02 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_unit_struct_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_unit_struct_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for OneUnitStruct { OneUnitStructIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneUnitStruct {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/one_uuid_type.rs b/sdks/rust/tests/test-client/src/module_bindings/one_uuid_type.rs index 63ca43baa28..ffec937559d 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/one_uuid_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/one_uuid_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OneUuid { OneUuidIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OneUuid {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/option_every_primitive_struct_type.rs b/sdks/rust/tests/test-client/src/module_bindings/option_every_primitive_struct_type.rs index 48bcea2ef6c..d14c9a2af4f 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/option_every_primitive_struct_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/option_every_primitive_struct_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for OptionEveryPrimitiveStruct { OptionEveryPrimitiveStructIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OptionEveryPrimitiveStruct {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/option_i_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/option_i_32_type.rs index e037ef3fcae..11999e80687 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/option_i_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/option_i_32_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OptionI32 { OptionI32IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OptionI32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/option_identity_type.rs b/sdks/rust/tests/test-client/src/module_bindings/option_identity_type.rs index 7662160d308..cdef62b565a 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/option_identity_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/option_identity_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OptionIdentity { OptionIdentityIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OptionIdentity {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/option_simple_enum_type.rs b/sdks/rust/tests/test-client/src/module_bindings/option_simple_enum_type.rs index 22a0f637cfa..7a9677dc52f 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/option_simple_enum_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/option_simple_enum_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for OptionSimpleEnum { OptionSimpleEnumIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OptionSimpleEnum {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/option_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/option_string_type.rs index a15c40a4169..2ee9db0e75e 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/option_string_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/option_string_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OptionString { OptionStringIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OptionString {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/option_uuid_type.rs b/sdks/rust/tests/test-client/src/module_bindings/option_uuid_type.rs index eae9603c07a..d861e5d1dbb 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/option_uuid_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/option_uuid_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OptionUuid { OptionUuidIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OptionUuid {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/option_vec_option_i_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/option_vec_option_i_32_type.rs index c7ee8b31def..af5e6d52756 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/option_vec_option_i_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/option_vec_option_i_32_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for OptionVecOptionI32 { OptionVecOptionI32IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for OptionVecOptionI32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_bool_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_bool_table.rs index 71c3fc62fd8..56cfe6eb2c8 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_bool_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_bool_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkBoolTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_bool"); - _table.add_unique_constraint::("b", |row| &row.b); -} pub struct PkBoolUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkBoolTableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkBoolTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `b` unique index on the table `pk_bool`, /// which allows point queries on the field of the same name /// via the [`PkBoolBUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkBoolBUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_bool"); + _table.add_unique_constraint::("b", |row| &row.b); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkBool`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_bool_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_bool_type.rs index daee77e680e..9f4603ebe45 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_bool_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_bool_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkBool { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkBool {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_connection_id_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_connection_id_table.rs index 8ca6e6a653d..ef7c0081c54 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_connection_id_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_connection_id_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkConnectionIdTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_connection_id"); - _table.add_unique_constraint::<__sdk::ConnectionId>("a", |row| &row.a); -} pub struct PkConnectionIdUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkConnectionIdTableHandle<'ctx> { @@ -100,17 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkConnectionIdTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::v2::TableUpdate, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `a` unique index on the table `pk_connection_id`, /// which allows point queries on the field of the same name /// via the [`PkConnectionIdAUnique::find`] method. @@ -141,6 +125,23 @@ impl<'ctx> PkConnectionIdAUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_connection_id"); + _table.add_unique_constraint::<__sdk::ConnectionId>("a", |row| &row.a); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkConnectionId`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_connection_id_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_connection_id_type.rs index 485f6174a1c..b2bf86242c9 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_connection_id_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_connection_id_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkConnectionId { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkConnectionId {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_i_128_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_i_128_table.rs index 57721ecdb3c..5025af971c3 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_i_128_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_i_128_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkI128TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_i128"); - _table.add_unique_constraint::("n", |row| &row.n); -} pub struct PkI128UpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkI128TableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkI128TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_i128`, /// which allows point queries on the field of the same name /// via the [`PkI128NUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkI128NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_i128"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkI128`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_i_128_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_i_128_type.rs index e92583fc9ae..d44037ca6c3 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_i_128_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_i_128_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkI128 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkI128 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_i_16_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_i_16_table.rs index b99038fa72f..b507d0ff7b3 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_i_16_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_i_16_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkI16TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_i16"); - _table.add_unique_constraint::("n", |row| &row.n); -} pub struct PkI16UpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkI16TableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkI16TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_i16`, /// which allows point queries on the field of the same name /// via the [`PkI16NUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkI16NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_i16"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkI16`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_i_16_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_i_16_type.rs index b4f1dd4aae7..2487520d2b9 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_i_16_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_i_16_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkI16 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkI16 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_i_256_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_i_256_table.rs index e0ff02e49e6..4e0d7ec4824 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_i_256_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_i_256_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkI256TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_i256"); - _table.add_unique_constraint::<__sats::i256>("n", |row| &row.n); -} pub struct PkI256UpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkI256TableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkI256TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_i256`, /// which allows point queries on the field of the same name /// via the [`PkI256NUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkI256NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_i256"); + _table.add_unique_constraint::<__sats::i256>("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkI256`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_i_256_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_i_256_type.rs index 2efccf4bd1b..60c4ac60288 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_i_256_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_i_256_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkI256 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkI256 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_i_32_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_i_32_table.rs index 4f7377c6536..27306fc04f9 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_i_32_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_i_32_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkI32TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_i32"); - _table.add_unique_constraint::("n", |row| &row.n); -} pub struct PkI32UpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkI32TableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkI32TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_i32`, /// which allows point queries on the field of the same name /// via the [`PkI32NUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkI32NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_i32"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkI32`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_i_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_i_32_type.rs index cad072e3967..97e53a60b70 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_i_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_i_32_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkI32 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkI32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_i_64_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_i_64_table.rs index 0601896cd01..9a674e8bb88 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_i_64_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_i_64_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkI64TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_i64"); - _table.add_unique_constraint::("n", |row| &row.n); -} pub struct PkI64UpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkI64TableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkI64TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_i64`, /// which allows point queries on the field of the same name /// via the [`PkI64NUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkI64NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_i64"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkI64`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_i_64_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_i_64_type.rs index de77151dc75..58c9f73b0a8 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_i_64_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_i_64_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkI64 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkI64 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_i_8_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_i_8_table.rs index 8e6954d54ea..4579f0bc8fd 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_i_8_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_i_8_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkI8TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_i8"); - _table.add_unique_constraint::("n", |row| &row.n); -} pub struct PkI8UpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkI8TableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkI8TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_i8`, /// which allows point queries on the field of the same name /// via the [`PkI8NUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkI8NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_i8"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkI8`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_i_8_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_i_8_type.rs index 266a42838ac..00683d16fa2 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_i_8_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_i_8_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkI8 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkI8 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_identity_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_identity_table.rs index 60e73b3cdbd..6e52e47ea50 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_identity_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_identity_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkIdentityTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_identity"); - _table.add_unique_constraint::<__sdk::Identity>("i", |row| &row.i); -} pub struct PkIdentityUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkIdentityTableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkIdentityTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `i` unique index on the table `pk_identity`, /// which allows point queries on the field of the same name /// via the [`PkIdentityIUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkIdentityIUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_identity"); + _table.add_unique_constraint::<__sdk::Identity>("i", |row| &row.i); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkIdentity`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_identity_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_identity_type.rs index b3dd11bd37f..3b0d4700d57 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_identity_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_identity_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkIdentity { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkIdentity {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_simple_enum_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_simple_enum_table.rs index 867540b937a..5e51f22be69 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_simple_enum_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_simple_enum_table.rs @@ -79,11 +79,6 @@ impl<'ctx> __sdk::Table for PkSimpleEnumTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_simple_enum"); - _table.add_unique_constraint::("a", |row| &row.a); -} pub struct PkSimpleEnumUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkSimpleEnumTableHandle<'ctx> { @@ -101,17 +96,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkSimpleEnumTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::v2::TableUpdate, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `a` unique index on the table `pk_simple_enum`, /// which allows point queries on the field of the same name /// via the [`PkSimpleEnumAUnique::find`] method. @@ -142,6 +126,23 @@ impl<'ctx> PkSimpleEnumAUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_simple_enum"); + _table.add_unique_constraint::("a", |row| &row.a); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkSimpleEnum`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_simple_enum_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_simple_enum_type.rs index bd8c3a224db..33fe9505daf 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_simple_enum_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_simple_enum_type.rs @@ -50,3 +50,5 @@ impl __sdk::__query_builder::HasIxCols for PkSimpleEnum { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkSimpleEnum {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_string_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_string_table.rs index 01d7bba1681..8f31b1e280b 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_string_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_string_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkStringTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_string"); - _table.add_unique_constraint::("s", |row| &row.s); -} pub struct PkStringUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkStringTableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkStringTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `s` unique index on the table `pk_string`, /// which allows point queries on the field of the same name /// via the [`PkStringSUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkStringSUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_string"); + _table.add_unique_constraint::("s", |row| &row.s); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkString`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_string_type.rs index c0b1fd6dbcb..fc5700525e3 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_string_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_string_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkString { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkString {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_128_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_128_table.rs index a868358395a..c7766e76617 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_128_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_128_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkU128TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_u128"); - _table.add_unique_constraint::("n", |row| &row.n); -} pub struct PkU128UpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkU128TableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkU128TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_u128`, /// which allows point queries on the field of the same name /// via the [`PkU128NUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkU128NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_u128"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkU128`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_128_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_128_type.rs index 1dd77a89d92..4af2d8bf2b9 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_128_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_128_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkU128 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkU128 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_16_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_16_table.rs index ea81b161550..7763dbbb916 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_16_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_16_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkU16TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_u16"); - _table.add_unique_constraint::("n", |row| &row.n); -} pub struct PkU16UpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkU16TableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkU16TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_u16`, /// which allows point queries on the field of the same name /// via the [`PkU16NUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkU16NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_u16"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkU16`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_16_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_16_type.rs index 62dfd8240a2..7313b109bee 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_16_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_16_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkU16 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkU16 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_256_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_256_table.rs index d6f73b53b05..a32aea3b472 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_256_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_256_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkU256TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_u256"); - _table.add_unique_constraint::<__sats::u256>("n", |row| &row.n); -} pub struct PkU256UpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkU256TableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkU256TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_u256`, /// which allows point queries on the field of the same name /// via the [`PkU256NUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkU256NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_u256"); + _table.add_unique_constraint::<__sats::u256>("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkU256`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_256_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_256_type.rs index f5c16e98e8d..e46bba4b98c 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_256_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_256_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkU256 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkU256 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_table.rs index ca8e3f962ad..aa50934a320 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkU32TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_u32"); - _table.add_unique_constraint::("n", |row| &row.n); -} pub struct PkU32UpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkU32TableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkU32TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_u32`, /// which allows point queries on the field of the same name /// via the [`PkU32NUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkU32NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_u32"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkU32`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_two_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_two_table.rs index d8bba325aac..b44e33cd400 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_two_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_two_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkU32TwoTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_u32_two"); - _table.add_unique_constraint::("n", |row| &row.n); -} pub struct PkU32TwoUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkU32TwoTableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkU32TwoTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_u32_two`, /// which allows point queries on the field of the same name /// via the [`PkU32TwoNUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkU32TwoNUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_u32_two"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkU32Two`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_two_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_two_type.rs index 05845bc1fe2..5651bd8f752 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_two_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_two_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkU32Two { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkU32Two {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_type.rs index ae7339a90db..0305bb17994 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_32_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkU32 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkU32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_64_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_64_table.rs index 38ad392a4fc..cd00b4d151e 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_64_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_64_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkU64TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_u64"); - _table.add_unique_constraint::("n", |row| &row.n); -} pub struct PkU64UpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkU64TableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkU64TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_u64`, /// which allows point queries on the field of the same name /// via the [`PkU64NUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkU64NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_u64"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkU64`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_64_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_64_type.rs index bcfe7145e51..9f4c617cc12 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_64_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_64_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkU64 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkU64 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_8_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_8_table.rs index f1ce8b35c5f..183685f62c9 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_8_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_8_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for PkU8TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_u8"); - _table.add_unique_constraint::("n", |row| &row.n); -} pub struct PkU8UpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkU8TableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkU8TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `pk_u8`, /// which allows point queries on the field of the same name /// via the [`PkU8NUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> PkU8NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_u8"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PkU8`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_u_8_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_u_8_type.rs index 17f08e60179..04e2fc30b48 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_u_8_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_u_8_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkU8 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkU8 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_uuid_table.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_uuid_table.rs index 86a15ea2f3b..2e72f521768 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_uuid_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_uuid_table.rs @@ -78,10 +78,6 @@ impl<'ctx> __sdk::Table for PkUuidTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("pk_uuid"); -} pub struct PkUuidUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PkUuidTableHandle<'ctx> { @@ -99,6 +95,11 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PkUuidTableHandle<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("pk_uuid"); +} + #[doc(hidden)] pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { diff --git a/sdks/rust/tests/test-client/src/module_bindings/pk_uuid_type.rs b/sdks/rust/tests/test-client/src/module_bindings/pk_uuid_type.rs index b1c622d5da9..62acd5125be 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/pk_uuid_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/pk_uuid_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for PkUuid { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PkUuid {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_every_primitive_struct_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/result_every_primitive_struct_string_type.rs index 050a599e3df..92228597561 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/result_every_primitive_struct_string_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/result_every_primitive_struct_string_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for ResultEveryPrimitiveStructString { ResultEveryPrimitiveStructStringIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for ResultEveryPrimitiveStructString {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_i_32_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/result_i_32_string_type.rs index 17f2efd216b..dde3d94ca4a 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/result_i_32_string_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/result_i_32_string_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for ResultI32String { ResultI32StringIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for ResultI32String {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_identity_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/result_identity_string_type.rs index ab7e5cce456..1cdb485977e 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/result_identity_string_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/result_identity_string_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for ResultIdentityString { ResultIdentityStringIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for ResultIdentityString {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_simple_enum_i_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/result_simple_enum_i_32_type.rs index da5e7e14a14..e89806e4a7e 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/result_simple_enum_i_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/result_simple_enum_i_32_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for ResultSimpleEnumI32 { ResultSimpleEnumI32IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for ResultSimpleEnumI32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_string_i_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/result_string_i_32_type.rs index 1e1e92a35be..ab52954cf94 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/result_string_i_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/result_string_i_32_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for ResultStringI32 { ResultStringI32IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for ResultStringI32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/result_vec_i_32_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/result_vec_i_32_string_type.rs index a65bb19af11..66ce7a2d84d 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/result_vec_i_32_string_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/result_vec_i_32_string_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for ResultVecI32String { ResultVecI32StringIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for ResultVecI32String {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/scheduled_table_table.rs b/sdks/rust/tests/test-client/src/module_bindings/scheduled_table_table.rs index a7d4221cbaa..873aed85c1c 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/scheduled_table_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/scheduled_table_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for ScheduledTableTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("scheduled_table"); - _table.add_unique_constraint::("scheduled_id", |row| &row.scheduled_id); -} pub struct ScheduledTableUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for ScheduledTableTableHandle<'ctx> { @@ -100,17 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for ScheduledTableTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::v2::TableUpdate, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `scheduled_id` unique index on the table `scheduled_table`, /// which allows point queries on the field of the same name /// via the [`ScheduledTableScheduledIdUnique::find`] method. @@ -141,6 +125,23 @@ impl<'ctx> ScheduledTableScheduledIdUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("scheduled_table"); + _table.add_unique_constraint::("scheduled_id", |row| &row.scheduled_id); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `ScheduledTable`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/scheduled_table_type.rs b/sdks/rust/tests/test-client/src/module_bindings/scheduled_table_type.rs index 45b88ef0a35..671d9dbb9a8 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/scheduled_table_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/scheduled_table_type.rs @@ -51,3 +51,5 @@ impl __sdk::__query_builder::HasIxCols for ScheduledTable { } } } + +impl __sdk::__query_builder::CanBeLookupTable for ScheduledTable {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/table_holds_table_type.rs b/sdks/rust/tests/test-client/src/module_bindings/table_holds_table_type.rs index f2fcf482df9..6428bc12127 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/table_holds_table_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/table_holds_table_type.rs @@ -47,3 +47,5 @@ impl __sdk::__query_builder::HasIxCols for TableHoldsTable { TableHoldsTableIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for TableHoldsTable {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_bool_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_bool_table.rs index 2516775f308..cf53f787bc2 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_bool_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_bool_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueBoolTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_bool"); - _table.add_unique_constraint::("b", |row| &row.b); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `b` unique index on the table `unique_bool`, /// which allows point queries on the field of the same name /// via the [`UniqueBoolBUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueBoolBUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_bool"); + _table.add_unique_constraint::("b", |row| &row.b); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueBool`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_bool_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_bool_type.rs index 92652790a32..8dd6e742b46 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_bool_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_bool_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueBool { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueBool {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_connection_id_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_connection_id_table.rs index c1f6eb7a028..c5f1d74fd95 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_connection_id_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_connection_id_table.rs @@ -78,23 +78,6 @@ impl<'ctx> __sdk::Table for UniqueConnectionIdTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_connection_id"); - _table.add_unique_constraint::<__sdk::ConnectionId>("a", |row| &row.a); -} - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::v2::TableUpdate, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `a` unique index on the table `unique_connection_id`, /// which allows point queries on the field of the same name /// via the [`UniqueConnectionIdAUnique::find`] method. @@ -125,6 +108,23 @@ impl<'ctx> UniqueConnectionIdAUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_connection_id"); + _table.add_unique_constraint::<__sdk::ConnectionId>("a", |row| &row.a); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueConnectionId`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_connection_id_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_connection_id_type.rs index 17cff44a1bb..372dc63cd3d 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_connection_id_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_connection_id_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueConnectionId { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueConnectionId {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_i_128_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_i_128_table.rs index d76cc9fd93e..7ad9e27176f 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_i_128_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_i_128_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueI128TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_i128"); - _table.add_unique_constraint::("n", |row| &row.n); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `unique_i128`, /// which allows point queries on the field of the same name /// via the [`UniqueI128NUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueI128NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_i128"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueI128`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_i_128_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_i_128_type.rs index 4d89b720575..7861798ccb6 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_i_128_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_i_128_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueI128 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueI128 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_i_16_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_i_16_table.rs index 290afaa07c4..a7245d954f3 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_i_16_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_i_16_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueI16TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_i16"); - _table.add_unique_constraint::("n", |row| &row.n); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `unique_i16`, /// which allows point queries on the field of the same name /// via the [`UniqueI16NUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueI16NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_i16"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueI16`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_i_16_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_i_16_type.rs index 2743c6b2b45..54752636e8d 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_i_16_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_i_16_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueI16 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueI16 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_i_256_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_i_256_table.rs index 1a677816e80..03cb0811a6e 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_i_256_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_i_256_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueI256TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_i256"); - _table.add_unique_constraint::<__sats::i256>("n", |row| &row.n); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `unique_i256`, /// which allows point queries on the field of the same name /// via the [`UniqueI256NUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueI256NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_i256"); + _table.add_unique_constraint::<__sats::i256>("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueI256`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_i_256_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_i_256_type.rs index 6571e72c953..a7d37880089 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_i_256_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_i_256_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueI256 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueI256 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_i_32_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_i_32_table.rs index 64908d57710..d292344a203 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_i_32_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_i_32_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueI32TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_i32"); - _table.add_unique_constraint::("n", |row| &row.n); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `unique_i32`, /// which allows point queries on the field of the same name /// via the [`UniqueI32NUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueI32NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_i32"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueI32`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_i_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_i_32_type.rs index 2bc9b21003e..63af8b357a3 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_i_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_i_32_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueI32 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueI32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_i_64_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_i_64_table.rs index ca7a801cb5a..226d6f023c8 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_i_64_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_i_64_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueI64TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_i64"); - _table.add_unique_constraint::("n", |row| &row.n); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `unique_i64`, /// which allows point queries on the field of the same name /// via the [`UniqueI64NUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueI64NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_i64"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueI64`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_i_64_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_i_64_type.rs index 8d7bc39e42f..a61f2af8d5d 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_i_64_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_i_64_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueI64 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueI64 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_i_8_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_i_8_table.rs index 702ab8b2a55..ed6ba07f2fe 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_i_8_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_i_8_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueI8TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_i8"); - _table.add_unique_constraint::("n", |row| &row.n); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `unique_i8`, /// which allows point queries on the field of the same name /// via the [`UniqueI8NUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueI8NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_i8"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueI8`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_i_8_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_i_8_type.rs index fd47d0cd913..ee7d92f5a4e 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_i_8_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_i_8_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueI8 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueI8 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_identity_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_identity_table.rs index ceea4244bc4..69d3678c2a9 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_identity_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_identity_table.rs @@ -78,23 +78,6 @@ impl<'ctx> __sdk::Table for UniqueIdentityTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_identity"); - _table.add_unique_constraint::<__sdk::Identity>("i", |row| &row.i); -} - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::v2::TableUpdate, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `i` unique index on the table `unique_identity`, /// which allows point queries on the field of the same name /// via the [`UniqueIdentityIUnique::find`] method. @@ -125,6 +108,23 @@ impl<'ctx> UniqueIdentityIUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_identity"); + _table.add_unique_constraint::<__sdk::Identity>("i", |row| &row.i); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueIdentity`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_identity_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_identity_type.rs index 0a6e5554f82..550b4f355fd 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_identity_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_identity_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueIdentity { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueIdentity {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_string_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_string_table.rs index 24e807ae932..f5af15d05a6 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_string_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_string_table.rs @@ -78,23 +78,6 @@ impl<'ctx> __sdk::Table for UniqueStringTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_string"); - _table.add_unique_constraint::("s", |row| &row.s); -} - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::v2::TableUpdate, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `s` unique index on the table `unique_string`, /// which allows point queries on the field of the same name /// via the [`UniqueStringSUnique::find`] method. @@ -125,6 +108,23 @@ impl<'ctx> UniqueStringSUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_string"); + _table.add_unique_constraint::("s", |row| &row.s); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueString`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_string_type.rs index 603f60e8b57..3cb1224248c 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_string_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_string_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueString { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueString {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_u_128_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_u_128_table.rs index 50c0900b4d8..8a75ea28f5d 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_u_128_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_u_128_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueU128TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_u128"); - _table.add_unique_constraint::("n", |row| &row.n); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `unique_u128`, /// which allows point queries on the field of the same name /// via the [`UniqueU128NUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueU128NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_u128"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueU128`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_u_128_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_u_128_type.rs index e75ee09a2a3..ff8cb2d808b 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_u_128_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_u_128_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueU128 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueU128 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_u_16_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_u_16_table.rs index 2972f8f5fd5..9cfa0a347ba 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_u_16_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_u_16_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueU16TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_u16"); - _table.add_unique_constraint::("n", |row| &row.n); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `unique_u16`, /// which allows point queries on the field of the same name /// via the [`UniqueU16NUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueU16NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_u16"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueU16`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_u_16_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_u_16_type.rs index 571fb9ee4c0..d5346884c0d 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_u_16_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_u_16_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueU16 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueU16 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_u_256_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_u_256_table.rs index 1087cfdc51c..788e561b021 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_u_256_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_u_256_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueU256TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_u256"); - _table.add_unique_constraint::<__sats::u256>("n", |row| &row.n); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `unique_u256`, /// which allows point queries on the field of the same name /// via the [`UniqueU256NUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueU256NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_u256"); + _table.add_unique_constraint::<__sats::u256>("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueU256`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_u_256_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_u_256_type.rs index 2bd9da359cb..4f3011011d0 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_u_256_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_u_256_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueU256 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueU256 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_u_32_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_u_32_table.rs index 0f1f5b2f1e5..07c0825cd16 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_u_32_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_u_32_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueU32TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_u32"); - _table.add_unique_constraint::("n", |row| &row.n); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `unique_u32`, /// which allows point queries on the field of the same name /// via the [`UniqueU32NUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueU32NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_u32"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueU32`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_u_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_u_32_type.rs index 9f9d9bd501f..1b1b9a67db7 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_u_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_u_32_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueU32 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueU32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_u_64_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_u_64_table.rs index 0b2d79694fa..754067c8f72 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_u_64_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_u_64_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueU64TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_u64"); - _table.add_unique_constraint::("n", |row| &row.n); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `unique_u64`, /// which allows point queries on the field of the same name /// via the [`UniqueU64NUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueU64NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_u64"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueU64`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_u_64_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_u_64_type.rs index e4b29d0f09f..67dfa279a93 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_u_64_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_u_64_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueU64 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueU64 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_u_8_table.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_u_8_table.rs index 5be60e23b35..7581ffab840 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_u_8_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_u_8_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for UniqueU8TableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("unique_u8"); - _table.add_unique_constraint::("n", |row| &row.n); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `n` unique index on the table `unique_u8`, /// which allows point queries on the field of the same name /// via the [`UniqueU8NUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> UniqueU8NUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("unique_u8"); + _table.add_unique_constraint::("n", |row| &row.n); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `UniqueU8`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_u_8_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_u_8_type.rs index fec9b5736f2..244a5b4dfe3 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_u_8_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_u_8_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueU8 { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueU8 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/unique_uuid_type.rs b/sdks/rust/tests/test-client/src/module_bindings/unique_uuid_type.rs index 25c34119951..356e66a5c4e 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/unique_uuid_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/unique_uuid_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for UniqueUuid { } } } + +impl __sdk::__query_builder::CanBeLookupTable for UniqueUuid {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/users_table.rs b/sdks/rust/tests/test-client/src/module_bindings/users_table.rs index beeba920839..bb231ad743a 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/users_table.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/users_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for UsersTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("users"); - _table.add_unique_constraint::<__sdk::Identity>("identity", |row| &row.identity); -} pub struct UsersUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for UsersTableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for UsersTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `identity` unique index on the table `users`, /// which allows point queries on the field of the same name /// via the [`UsersIdentityUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> UsersIdentityUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("users"); + _table.add_unique_constraint::<__sdk::Identity>("identity", |row| &row.identity); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `Users`. /// diff --git a/sdks/rust/tests/test-client/src/module_bindings/users_type.rs b/sdks/rust/tests/test-client/src/module_bindings/users_type.rs index e9c256c2e28..8d0c5ec8726 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/users_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/users_type.rs @@ -48,3 +48,5 @@ impl __sdk::__query_builder::HasIxCols for Users { } } } + +impl __sdk::__query_builder::CanBeLookupTable for Users {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_bool_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_bool_type.rs index 85f50be571e..5b42fa0c9c0 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_bool_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_bool_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecBool { VecBoolIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecBool {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_byte_struct_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_byte_struct_type.rs index df8233ef624..3877d7a6531 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_byte_struct_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_byte_struct_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for VecByteStruct { VecByteStructIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecByteStruct {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_connection_id_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_connection_id_type.rs index 5205f48403e..faa6c9999a8 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_connection_id_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_connection_id_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecConnectionId { VecConnectionIdIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecConnectionId {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_enum_with_payload_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_enum_with_payload_type.rs index 9f012d949d7..d083b3daad9 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_enum_with_payload_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_enum_with_payload_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for VecEnumWithPayload { VecEnumWithPayloadIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecEnumWithPayload {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_every_primitive_struct_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_every_primitive_struct_type.rs index 52f9e17448d..3833b05fc25 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_every_primitive_struct_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_every_primitive_struct_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for VecEveryPrimitiveStruct { VecEveryPrimitiveStructIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecEveryPrimitiveStruct {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_every_vec_struct_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_every_vec_struct_type.rs index d28ce4a4307..532e4c16a7d 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_every_vec_struct_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_every_vec_struct_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for VecEveryVecStruct { VecEveryVecStructIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecEveryVecStruct {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_f_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_f_32_type.rs index 6cb53fa07a3..7bb2aa4d9b6 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_f_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_f_32_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecF32 { VecF32IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecF32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_f_64_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_f_64_type.rs index ef8b266dddf..c03a1171ebd 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_f_64_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_f_64_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecF64 { VecF64IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecF64 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_i_128_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_i_128_type.rs index f54dd3a07e6..283b8163148 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_i_128_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_i_128_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecI128 { VecI128IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecI128 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_i_16_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_i_16_type.rs index fea9dccb5d3..5bbc36d740e 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_i_16_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_i_16_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecI16 { VecI16IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecI16 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_i_256_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_i_256_type.rs index aa82923e382..8dc66bfd112 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_i_256_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_i_256_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecI256 { VecI256IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecI256 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_i_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_i_32_type.rs index 0e9e457df20..db7d3649739 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_i_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_i_32_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecI32 { VecI32IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecI32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_i_64_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_i_64_type.rs index df38c71ab81..3840fac9fba 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_i_64_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_i_64_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecI64 { VecI64IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecI64 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_i_8_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_i_8_type.rs index fd47b9ee861..70d9f1f86cc 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_i_8_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_i_8_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecI8 { VecI8IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecI8 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_identity_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_identity_type.rs index c2bb75f9554..0e2d4b04078 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_identity_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_identity_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecIdentity { VecIdentityIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecIdentity {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_simple_enum_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_simple_enum_type.rs index ec1cb92bb5b..59d1abed5c9 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_simple_enum_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_simple_enum_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for VecSimpleEnum { VecSimpleEnumIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecSimpleEnum {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_string_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_string_type.rs index 87082641a53..411e4042065 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_string_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_string_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecString { VecStringIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecString {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_timestamp_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_timestamp_type.rs index 721562993eb..33792f217dd 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_timestamp_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_timestamp_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecTimestamp { VecTimestampIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecTimestamp {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_u_128_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_u_128_type.rs index fdda362abad..d304ba0bdee 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_u_128_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_u_128_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecU128 { VecU128IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecU128 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_u_16_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_u_16_type.rs index 1ce29594cc3..0a4f63ce8ff 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_u_16_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_u_16_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecU16 { VecU16IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecU16 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_u_256_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_u_256_type.rs index db1e22d5ded..888de66026e 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_u_256_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_u_256_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecU256 { VecU256IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecU256 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_u_32_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_u_32_type.rs index 8a81945e8cf..807b976fa36 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_u_32_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_u_32_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecU32 { VecU32IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecU32 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_u_64_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_u_64_type.rs index 23283c48b23..fc9c942f587 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_u_64_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_u_64_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecU64 { VecU64IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecU64 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_u_8_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_u_8_type.rs index 0e324f60f30..634f4481802 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_u_8_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_u_8_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecU8 { VecU8IxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecU8 {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_unit_struct_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_unit_struct_type.rs index 2ee7e98c3cc..fdfdd6aa14e 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_unit_struct_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_unit_struct_type.rs @@ -43,3 +43,5 @@ impl __sdk::__query_builder::HasIxCols for VecUnitStruct { VecUnitStructIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecUnitStruct {} diff --git a/sdks/rust/tests/test-client/src/module_bindings/vec_uuid_type.rs b/sdks/rust/tests/test-client/src/module_bindings/vec_uuid_type.rs index 163a7b9aaec..4f9dbc4aea2 100644 --- a/sdks/rust/tests/test-client/src/module_bindings/vec_uuid_type.rs +++ b/sdks/rust/tests/test-client/src/module_bindings/vec_uuid_type.rs @@ -41,3 +41,5 @@ impl __sdk::__query_builder::HasIxCols for VecUuid { VecUuidIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for VecUuid {} diff --git a/sdks/rust/tests/test.rs b/sdks/rust/tests/test.rs index afc1e83487b..d6c5cac38ae 100644 --- a/sdks/rust/tests/test.rs +++ b/sdks/rust/tests/test.rs @@ -316,6 +316,44 @@ declare_tests_with_suffix!(typescript, "-ts"); declare_tests_with_suffix!(csharp, "-cs"); declare_tests_with_suffix!(cpp, "-cpp"); +/// Tests of event table functionality, using <./event-table-client> and <../../../modules/sdk-test>. +/// +/// These are separate from the existing client because as of writing (2026-02-07), +/// we do not have event table support in all of the module languages we have tested. +mod event_table_tests { + use spacetimedb_testing::sdk::Test; + + const MODULE: &str = "sdk-test-event-table"; + const CLIENT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/event-table-client"); + + fn make_test(subcommand: &str) -> Test { + Test::builder() + .with_name(subcommand) + .with_module(MODULE) + .with_client(CLIENT) + .with_language("rust") + .with_bindings_dir("src/module_bindings") + .with_compile_command("cargo build") + .with_run_command(format!("cargo run -- {}", subcommand)) + .build() + } + + #[test] + fn event_table() { + make_test("event-table").run(); + } + + #[test] + fn multiple_events() { + make_test("multiple-events").run(); + } + + #[test] + fn events_dont_persist() { + make_test("events-dont-persist").run(); + } +} + macro_rules! procedure_tests { ($mod_name:ident, $suffix:literal) => { mod $mod_name { diff --git a/sdks/rust/tests/view-client/src/module_bindings/mod.rs b/sdks/rust/tests/view-client/src/module_bindings/mod.rs index c5a296bc9b3..3af09da01cb 100644 --- a/sdks/rust/tests/view-client/src/module_bindings/mod.rs +++ b/sdks/rust/tests/view-client/src/module_bindings/mod.rs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.12.0 (commit 729b96fecd3ee7ab4f69443b80cafa6d39c2782e). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; diff --git a/sdks/rust/tests/view-client/src/module_bindings/player_level_table.rs b/sdks/rust/tests/view-client/src/module_bindings/player_level_table.rs index 7cd3eec5a85..2f092d15467 100644 --- a/sdks/rust/tests/view-client/src/module_bindings/player_level_table.rs +++ b/sdks/rust/tests/view-client/src/module_bindings/player_level_table.rs @@ -78,21 +78,6 @@ impl<'ctx> __sdk::Table for PlayerLevelTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("player_level"); - _table.add_unique_constraint::("entity_id", |row| &row.entity_id); -} - -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `entity_id` unique index on the table `player_level`, /// which allows point queries on the field of the same name /// via the [`PlayerLevelEntityIdUnique::find`] method. @@ -123,6 +108,21 @@ impl<'ctx> PlayerLevelEntityIdUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("player_level"); + _table.add_unique_constraint::("entity_id", |row| &row.entity_id); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PlayerLevel`. /// diff --git a/sdks/rust/tests/view-client/src/module_bindings/player_level_type.rs b/sdks/rust/tests/view-client/src/module_bindings/player_level_type.rs index 98b25e6a137..8a5ba6071e4 100644 --- a/sdks/rust/tests/view-client/src/module_bindings/player_level_type.rs +++ b/sdks/rust/tests/view-client/src/module_bindings/player_level_type.rs @@ -50,3 +50,5 @@ impl __sdk::__query_builder::HasIxCols for PlayerLevel { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PlayerLevel {} diff --git a/sdks/rust/tests/view-client/src/module_bindings/player_location_table.rs b/sdks/rust/tests/view-client/src/module_bindings/player_location_table.rs index efe15384b4d..6114b8bc3b5 100644 --- a/sdks/rust/tests/view-client/src/module_bindings/player_location_table.rs +++ b/sdks/rust/tests/view-client/src/module_bindings/player_location_table.rs @@ -78,23 +78,6 @@ impl<'ctx> __sdk::Table for PlayerLocationTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("player_location"); - _table.add_unique_constraint::("entity_id", |row| &row.entity_id); -} - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::v2::TableUpdate, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `entity_id` unique index on the table `player_location`, /// which allows point queries on the field of the same name /// via the [`PlayerLocationEntityIdUnique::find`] method. @@ -125,6 +108,23 @@ impl<'ctx> PlayerLocationEntityIdUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("player_location"); + _table.add_unique_constraint::("entity_id", |row| &row.entity_id); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `PlayerLocation`. /// diff --git a/sdks/rust/tests/view-client/src/module_bindings/player_location_type.rs b/sdks/rust/tests/view-client/src/module_bindings/player_location_type.rs index a2d29d18188..51e3d45390f 100644 --- a/sdks/rust/tests/view-client/src/module_bindings/player_location_type.rs +++ b/sdks/rust/tests/view-client/src/module_bindings/player_location_type.rs @@ -56,3 +56,5 @@ impl __sdk::__query_builder::HasIxCols for PlayerLocation { } } } + +impl __sdk::__query_builder::CanBeLookupTable for PlayerLocation {} diff --git a/sdks/rust/tests/view-client/src/module_bindings/player_table.rs b/sdks/rust/tests/view-client/src/module_bindings/player_table.rs index 916d5b5db4d..1214943ef52 100644 --- a/sdks/rust/tests/view-client/src/module_bindings/player_table.rs +++ b/sdks/rust/tests/view-client/src/module_bindings/player_table.rs @@ -78,12 +78,6 @@ impl<'ctx> __sdk::Table for PlayerTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("player"); - _table.add_unique_constraint::("entity_id", |row| &row.entity_id); - _table.add_unique_constraint::<__sdk::Identity>("identity", |row| &row.identity); -} pub struct PlayerUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for PlayerTableHandle<'ctx> { @@ -101,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for PlayerTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `entity_id` unique index on the table `player`, /// which allows point queries on the field of the same name /// via the [`PlayerEntityIdUnique::find`] method. @@ -170,6 +155,22 @@ impl<'ctx> PlayerIdentityUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("player"); + _table.add_unique_constraint::("entity_id", |row| &row.entity_id); + _table.add_unique_constraint::<__sdk::Identity>("identity", |row| &row.identity); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `Player`. /// diff --git a/sdks/rust/tests/view-client/src/module_bindings/player_type.rs b/sdks/rust/tests/view-client/src/module_bindings/player_type.rs index b99ac46acf3..57b07de9a0b 100644 --- a/sdks/rust/tests/view-client/src/module_bindings/player_type.rs +++ b/sdks/rust/tests/view-client/src/module_bindings/player_type.rs @@ -50,3 +50,5 @@ impl __sdk::__query_builder::HasIxCols for Player { } } } + +impl __sdk::__query_builder::CanBeLookupTable for Player {} diff --git a/smoketests/tests/namespaces.py b/smoketests/tests/namespaces.py index e0da0db729f..2cd2276876f 100644 --- a/smoketests/tests/namespaces.py +++ b/smoketests/tests/namespaces.py @@ -23,7 +23,7 @@ def test_spacetimedb_ns_csharp(self): with tempfile.TemporaryDirectory() as tmpdir: self.spacetime("generate", "--out-dir", tmpdir, "--lang=cs", "--project-path", self.project_path) - self.assertEqual(count_matches(tmpdir, f"namespace {namespace}"), 7) + self.assertEqual(count_matches(tmpdir, f"namespace {namespace}"), 5) self.assertEqual(count_matches(tmpdir, "using SpacetimeDB;"), 0) def test_custom_ns_csharp(self): @@ -34,5 +34,5 @@ def test_custom_ns_csharp(self): with tempfile.TemporaryDirectory() as tmpdir: self.spacetime("generate", "--out-dir", tmpdir, "--lang=cs", "--namespace", namespace, "--project-path", self.project_path) - self.assertEqual(count_matches(tmpdir, f"namespace {namespace}"), 7) - self.assertEqual(count_matches(tmpdir, "using SpacetimeDB;"), 7) + self.assertEqual(count_matches(tmpdir, f"namespace {namespace}"), 5) + self.assertEqual(count_matches(tmpdir, "using SpacetimeDB;"), 5) diff --git a/templates/chat-console-cs/module_bindings/Reducers/ClientConnected.g.cs b/templates/chat-console-cs/module_bindings/Reducers/ClientConnected.g.cs deleted file mode 100644 index a23c796730b..00000000000 --- a/templates/chat-console-cs/module_bindings/Reducers/ClientConnected.g.cs +++ /dev/null @@ -1,48 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteReducers : RemoteBase - { - public delegate void ClientConnectedHandler(ReducerEventContext ctx); - public event ClientConnectedHandler? OnClientConnected; - - public bool InvokeClientConnected(ReducerEventContext ctx, Reducer.ClientConnected args) - { - if (OnClientConnected == null) - { - if (InternalOnUnhandledReducerError != null) - { - switch (ctx.Event.Status) - { - case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; - case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; - } - } - return false; - } - OnClientConnected( - ctx - ); - return true; - } - } - - public abstract partial class Reducer - { - [SpacetimeDB.Type] - [DataContract] - public sealed partial class ClientConnected : Reducer, IReducerArgs - { - string IReducerArgs.ReducerName => "ClientConnected"; - } - } -} diff --git a/templates/chat-console-cs/module_bindings/Reducers/ClientDisconnected.g.cs b/templates/chat-console-cs/module_bindings/Reducers/ClientDisconnected.g.cs deleted file mode 100644 index 1011efda754..00000000000 --- a/templates/chat-console-cs/module_bindings/Reducers/ClientDisconnected.g.cs +++ /dev/null @@ -1,48 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteReducers : RemoteBase - { - public delegate void ClientDisconnectedHandler(ReducerEventContext ctx); - public event ClientDisconnectedHandler? OnClientDisconnected; - - public bool InvokeClientDisconnected(ReducerEventContext ctx, Reducer.ClientDisconnected args) - { - if (OnClientDisconnected == null) - { - if (InternalOnUnhandledReducerError != null) - { - switch (ctx.Event.Status) - { - case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; - case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; - } - } - return false; - } - OnClientDisconnected( - ctx - ); - return true; - } - } - - public abstract partial class Reducer - { - [SpacetimeDB.Type] - [DataContract] - public sealed partial class ClientDisconnected : Reducer, IReducerArgs - { - string IReducerArgs.ReducerName => "ClientDisconnected"; - } - } -} diff --git a/templates/chat-console-cs/module_bindings/SpacetimeDBClient.g.cs b/templates/chat-console-cs/module_bindings/SpacetimeDBClient.g.cs index 2d65e8d90e3..cc3901931dd 100644 --- a/templates/chat-console-cs/module_bindings/SpacetimeDBClient.g.cs +++ b/templates/chat-console-cs/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.12.0 (commit de7fdf72a6bf3a4436f52f6d369816b031414251). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). #nullable enable @@ -616,8 +616,6 @@ protected override bool Dispatch(IReducerEventContext context, Reducer reducer) var eventContext = (ReducerEventContext)context; return reducer switch { - Reducer.ClientConnected args => Reducers.InvokeClientConnected(eventContext, args), - Reducer.ClientDisconnected args => Reducers.InvokeClientDisconnected(eventContext, args), Reducer.SendMessage args => Reducers.InvokeSendMessage(eventContext, args), Reducer.SetName args => Reducers.InvokeSetName(eventContext, args), _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") diff --git a/templates/chat-console-rs/src/module_bindings/message_type.rs b/templates/chat-console-rs/src/module_bindings/message_type.rs index 0d60be134e9..2719e41940b 100644 --- a/templates/chat-console-rs/src/module_bindings/message_type.rs +++ b/templates/chat-console-rs/src/module_bindings/message_type.rs @@ -47,3 +47,5 @@ impl __sdk::__query_builder::HasIxCols for Message { MessageIxCols {} } } + +impl __sdk::__query_builder::CanBeLookupTable for Message {} diff --git a/templates/chat-console-rs/src/module_bindings/mod.rs b/templates/chat-console-rs/src/module_bindings/mod.rs index a7409113a7d..5503526e0a5 100644 --- a/templates/chat-console-rs/src/module_bindings/mod.rs +++ b/templates/chat-console-rs/src/module_bindings/mod.rs @@ -1,13 +1,11 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.12.0 (commit 9bb9560f7f1df58e373ea4ec6215546348e2e12d-dirty). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; -pub mod identity_connected_reducer; -pub mod identity_disconnected_reducer; pub mod message_table; pub mod message_type; pub mod send_message_reducer; @@ -15,8 +13,6 @@ pub mod set_name_reducer; pub mod user_table; pub mod user_type; -pub use identity_connected_reducer::identity_connected; -pub use identity_disconnected_reducer::identity_disconnected; pub use message_table::*; pub use message_type::Message; pub use send_message_reducer::send_message; @@ -32,8 +28,6 @@ pub use user_type::User; /// to indicate which reducer caused the event. pub enum Reducer { - IdentityConnected, - IdentityDisconnected, SendMessage { text: String }, SetName { name: String }, } @@ -45,8 +39,6 @@ impl __sdk::InModule for Reducer { impl __sdk::Reducer for Reducer { fn reducer_name(&self) -> &'static str { match self { - Reducer::IdentityConnected => "identity_connected", - Reducer::IdentityDisconnected => "identity_disconnected", Reducer::SendMessage { .. } => "send_message", Reducer::SetName { .. } => "set_name", _ => unreachable!(), @@ -55,10 +47,6 @@ impl __sdk::Reducer for Reducer { #[allow(clippy::clone_on_copy)] fn args_bsatn(&self) -> Result, __sats::bsatn::EncodeError> { match self { - Reducer::IdentityConnected => __sats::bsatn::to_vec(&identity_connected_reducer::IdentityConnectedArgs {}), - Reducer::IdentityDisconnected => { - __sats::bsatn::to_vec(&identity_disconnected_reducer::IdentityDisconnectedArgs {}) - } Reducer::SendMessage { text } => { __sats::bsatn::to_vec(&send_message_reducer::SendMessageArgs { text: text.clone() }) } @@ -811,4 +799,5 @@ impl __sdk::SpacetimeModule for RemoteModule { message_table::register_table(client_cache); user_table::register_table(client_cache); } + const ALL_TABLE_NAMES: &'static [&'static str] = &["message", "user"]; } diff --git a/templates/chat-console-rs/src/module_bindings/user_table.rs b/templates/chat-console-rs/src/module_bindings/user_table.rs index ed1f9638216..79240f2669e 100644 --- a/templates/chat-console-rs/src/module_bindings/user_table.rs +++ b/templates/chat-console-rs/src/module_bindings/user_table.rs @@ -78,11 +78,6 @@ impl<'ctx> __sdk::Table for UserTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("user"); - _table.add_unique_constraint::<__sdk::Identity>("identity", |row| &row.identity); -} pub struct UserUpdateCallbackId(__sdk::CallbackId); impl<'ctx> __sdk::TableWithPrimaryKey for UserTableHandle<'ctx> { @@ -100,15 +95,6 @@ impl<'ctx> __sdk::TableWithPrimaryKey for UserTableHandle<'ctx> { } } -#[doc(hidden)] -pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") - .with_cause(e) - .into() - }) -} - /// Access to the `identity` unique index on the table `user`, /// which allows point queries on the field of the same name /// via the [`UserIdentityUnique::find`] method. @@ -139,6 +125,21 @@ impl<'ctx> UserIdentityUnique<'ctx> { } } +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("user"); + _table.add_unique_constraint::<__sdk::Identity>("identity", |row| &row.identity); +} + +#[doc(hidden)] +pub(super) fn parse_table_update(raw_updates: __ws::v2::TableUpdate) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + #[allow(non_camel_case_types)] /// Extension trait for query builder access to the table `User`. /// diff --git a/templates/chat-console-rs/src/module_bindings/user_type.rs b/templates/chat-console-rs/src/module_bindings/user_type.rs index e3de10937b8..a17ebe2013b 100644 --- a/templates/chat-console-rs/src/module_bindings/user_type.rs +++ b/templates/chat-console-rs/src/module_bindings/user_type.rs @@ -51,3 +51,5 @@ impl __sdk::__query_builder::HasIxCols for User { } } } + +impl __sdk::__query_builder::CanBeLookupTable for User {} diff --git a/templates/chat-react-ts/src/module_bindings/types/reducers.ts b/templates/chat-react-ts/src/module_bindings/types/reducers.ts index f3ed1660bff..ff1fdae4337 100644 --- a/templates/chat-react-ts/src/module_bindings/types/reducers.ts +++ b/templates/chat-react-ts/src/module_bindings/types/reducers.ts @@ -6,12 +6,8 @@ import { type Infer as __Infer } from 'spacetimedb'; // Import all reducer arg schemas -import OnConnectReducer from '../on_connect_reducer'; -import OnDisconnectReducer from '../on_disconnect_reducer'; import SendMessageReducer from '../send_message_reducer'; import SetNameReducer from '../set_name_reducer'; -export type OnConnectParams = __Infer; -export type OnDisconnectParams = __Infer; export type SendMessageParams = __Infer; export type SetNameParams = __Infer; diff --git a/templates/deno-ts/src/module_bindings/index.ts b/templates/deno-ts/src/module_bindings/index.ts index 5e83bc75b20..b07b14691d8 100644 --- a/templates/deno-ts/src/module_bindings/index.ts +++ b/templates/deno-ts/src/module_bindings/index.ts @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.11.3 (commit f9bca6a8df856d950360b40cbce744fcbffc9a63). +// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). /* eslint-disable */ /* tslint:disable */ @@ -33,47 +33,28 @@ import { type SubscriptionHandleImpl as __SubscriptionHandleImpl, } from 'spacetimedb'; -// Import and reexport all reducer arg types -import OnConnectReducer from './on_connect_reducer.js'; -export { OnConnectReducer }; -import OnDisconnectReducer from './on_disconnect_reducer.js'; -export { OnDisconnectReducer }; -import AddReducer from './add_reducer.js'; -export { AddReducer }; -import SayHelloReducer from './say_hello_reducer.js'; -export { SayHelloReducer }; - -// Import and reexport all procedure arg types - -// Import and reexport all table handle types -import PersonRow from './person_table.js'; -export { PersonRow }; - -// Import and reexport all types -import Add from './add_type.js'; -export { Add }; -import Init from './init_type.js'; -export { Init }; -import OnConnect from './on_connect_type.js'; -export { OnConnect }; -import OnDisconnect from './on_disconnect_type.js'; -export { OnDisconnect }; -import Person from './person_type.js'; -export { Person }; -import SayHello from './say_hello_type.js'; -export { SayHello }; +// Import all reducer arg schemas +import AddReducer from './add_reducer'; +import SayHelloReducer from './say_hello_reducer'; + +// Import all procedure arg schemas + +// Import all table schema definitions +import PersonRow from './person_table'; + +/** Type-only namespace exports for generated type groups. */ /** The schema information for all tables in this module. This is defined the same was as the tables would have been defined in the server. */ -const tablesSchema = __schema( - __table( +const tablesSchema = __schema({ + person: __table( { name: 'person', indexes: [], constraints: [], }, PersonRow - ) -); + ), +}); /** The schema information for all reducers in this module. This is defined the same way as the reducers would have been defined in the server, except the body of the reducer is omitted in code generation. */ const reducersSchema = __reducers( @@ -87,7 +68,7 @@ const proceduresSchema = __procedures(); /** The remote SpacetimeDB module schema, both runtime and type information. */ const REMOTE_MODULE = { versionInfo: { - cliVersion: '1.11.3' as const, + cliVersion: '2.0.0' as const, }, tables: tablesSchema.schemaType.tables, reducers: reducersSchema.reducersType.reducers, @@ -98,11 +79,8 @@ const REMOTE_MODULE = { typeof proceduresSchema >; -/** The tables available in this remote SpacetimeDB module. */ -export const tables = __convertToAccessorMap(tablesSchema.schemaType.tables); - -/** A typed query builder for this remote SpacetimeDB module. */ -export const query: __QueryBuilder = +/** The tables available in this remote SpacetimeDB module. Each table reference doubles as a query builder. */ +export const tables: __QueryBuilder = __makeQueryBuilder(tablesSchema.schemaType); /** The reducers available in this remote SpacetimeDB module. */ diff --git a/templates/chat-react-ts/src/module_bindings/on_connect_reducer.ts b/templates/deno-ts/src/module_bindings/types/index.ts similarity index 53% rename from templates/chat-react-ts/src/module_bindings/on_connect_reducer.ts rename to templates/deno-ts/src/module_bindings/types/index.ts index 2ca99c88fea..06296d8bf15 100644 --- a/templates/chat-react-ts/src/module_bindings/on_connect_reducer.ts +++ b/templates/deno-ts/src/module_bindings/types/index.ts @@ -3,11 +3,9 @@ /* eslint-disable */ /* tslint:disable */ -import { - TypeBuilder as __TypeBuilder, - t as __t, - type AlgebraicTypeType as __AlgebraicTypeType, - type Infer as __Infer, -} from 'spacetimedb'; +import { type Infer as __Infer } from 'spacetimedb'; -export default {}; +// Import all non-reducer types +import Person from '../person_type'; + +export type Person = __Infer; diff --git a/templates/chat-react-ts/src/module_bindings/on_disconnect_reducer.ts b/templates/deno-ts/src/module_bindings/types/procedures.ts similarity index 53% rename from templates/chat-react-ts/src/module_bindings/on_disconnect_reducer.ts rename to templates/deno-ts/src/module_bindings/types/procedures.ts index 2ca99c88fea..b2102264f4d 100644 --- a/templates/chat-react-ts/src/module_bindings/on_disconnect_reducer.ts +++ b/templates/deno-ts/src/module_bindings/types/procedures.ts @@ -3,11 +3,6 @@ /* eslint-disable */ /* tslint:disable */ -import { - TypeBuilder as __TypeBuilder, - t as __t, - type AlgebraicTypeType as __AlgebraicTypeType, - type Infer as __Infer, -} from 'spacetimedb'; +import { type Infer as __Infer } from 'spacetimedb'; -export default {}; +// Import all procedure arg schemas diff --git a/templates/deno-ts/src/module_bindings/types/reducers.ts b/templates/deno-ts/src/module_bindings/types/reducers.ts new file mode 100644 index 00000000000..d8ceaeb2709 --- /dev/null +++ b/templates/deno-ts/src/module_bindings/types/reducers.ts @@ -0,0 +1,13 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +/* eslint-disable */ +/* tslint:disable */ +import { type Infer as __Infer } from 'spacetimedb'; + +// Import all reducer arg schemas +import AddReducer from '../add_reducer'; +import SayHelloReducer from '../say_hello_reducer'; + +export type AddParams = __Infer; +export type SayHelloParams = __Infer;