From 545bb7c31ac40fe453789b8cf634248bcdadd9e0 Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Fri, 23 Jan 2026 14:32:04 -0800 Subject: [PATCH 01/18] [2.0 Breaking]: Remove sender field from [Reducer|View|Procedure]Context (#4101) # Description of Changes Makes the `sender` field on `ViewContext` private and exposes a `sender()` method. Does the same for `ReducerContext` and `ProcedureContext`. The purpose of this change: So that the host can determine if/when a view invokes or reads the `sender`. Currently, because `sender` is a field, the host assumes that it is always read. This means views must be materialized per client, even if the view doesn't actually depend on `sender`, resulting in data duplication. The initial solution for this problem was `AnonymousViewContext` which doesn't have a `sender` field. The better solution is to make `sender` a method so that it can call into the host and record when it's actually invoked. Note, this patch only updates the module API, so the current implementation does not change. `ViewContext` views are still duplicated across clients. Changing this requires a new host syscall and for `sender()` to invoke that syscall. This however is backwards compatible and can be done anytime after the module APIs for the other languages (C#, TypeScript, C++) are updated. Also note that `ReducerContext` and `ProcedureContext` were updated purely for consistency. There are currently no plans to track reads of `sender` in these contexts. # API and ABI breaking changes Breaks the rust module api. # Expected complexity level and risk 1 # Testing N/A --- .../test-react-router-app/server/src/lib.rs | 12 +- crates/bindings/README.md | 2 +- crates/bindings/src/lib.rs | 30 +- demo/Blackholio/server-rust/src/lib.rs | 28 +- .../00400-key-architecture.md | 2 +- .../00300-tutorials/00100-chat-app.md | 12 +- .../00300-unity-tutorial/00300-part-2.md | 4 +- .../00300-unity-tutorial/00400-part-3.md | 8 +- .../00300-unity-tutorial/00500-part-4.md | 4 +- .../00400-unreal-tutorial/00300-part-2.md | 4 +- .../00400-unreal-tutorial/00400-part-3.md | 14 +- .../00400-unreal-tutorial/00500-part-4.md | 4 +- .../00100-databases/00500-cheat-sheet.md | 4 +- .../00300-incremental-migrations.md | 16 +- .../00300-reducers/00400-reducer-context.md | 4 +- .../00300-reducers/00500-lifecycle.md | 8 +- .../00200-functions/00500-views.md | 12 +- docs/docs/00200-core-concepts/00300-tables.md | 2 +- .../00300-tables/00210-file-storage.md | 2 +- .../00300-tables/00400-access-permissions.md | 10 +- .../00100-how-to/00300-logging.md | 4 +- docs/llms/docs-benchmark-analysis.md | 599 +++--- docs/llms/docs-benchmark-comment.md | 12 +- docs/llms/docs-benchmark-details.json | 1652 ++++++++--------- docs/llms/docs-benchmark-summary.json | 52 +- modules/module-test/src/lib.rs | 6 +- .../sdk-test-connect-disconnect/src/lib.rs | 4 +- modules/sdk-test-view/src/lib.rs | 10 +- modules/sdk-test/src/lib.rs | 10 +- smoketests/tests/rls.py | 4 +- smoketests/tests/views.py | 4 +- smoketests/tests/zz_docker.py | 4 +- .../chat-console-rs/spacetimedb/src/lib.rs | 16 +- 33 files changed, 1339 insertions(+), 1220 deletions(-) diff --git a/crates/bindings-typescript/test-react-router-app/server/src/lib.rs b/crates/bindings-typescript/test-react-router-app/server/src/lib.rs index 520e68eeaec..496acfd090f 100644 --- a/crates/bindings-typescript/test-react-router-app/server/src/lib.rs +++ b/crates/bindings-typescript/test-react-router-app/server/src/lib.rs @@ -22,23 +22,23 @@ fn init(ctx: &ReducerContext) { #[reducer(client_connected)] fn client_connected(ctx: &ReducerContext) { - let existing_user = ctx.db.offline_user().identity().find(ctx.sender); + let existing_user = ctx.db.offline_user().identity().find(ctx.sender()); if let Some(user) = existing_user { ctx.db.user().insert(user); - ctx.db.offline_user().identity().delete(ctx.sender); + ctx.db.offline_user().identity().delete(ctx.sender()); return; } ctx.db.offline_user().insert(User { - identity: ctx.sender, + identity: ctx.sender(), has_incremented_count: 0, }); } #[reducer(client_disconnected)] fn client_disconnected(ctx: &ReducerContext) -> Result<(), String> { - let existing_user = ctx.db.user().identity().find(ctx.sender).ok_or("User not found")?; + let existing_user = ctx.db.user().identity().find(ctx.sender()).ok_or("User not found")?; ctx.db.offline_user().insert(existing_user); - ctx.db.user().identity().delete(ctx.sender); + ctx.db.user().identity().delete(ctx.sender()); Ok(()) } @@ -48,7 +48,7 @@ fn increment_counter(ctx: &ReducerContext) -> Result<(), String> { counter.count += 1; ctx.db.counter().id().update(counter); - let mut user = ctx.db.user().identity().find(ctx.sender).ok_or("User not found")?; + let mut user = ctx.db.user().identity().find(ctx.sender()).ok_or("User not found")?; user.has_incremented_count += 1; ctx.db.user().identity().update(user); diff --git a/crates/bindings/README.md b/crates/bindings/README.md index a02a8ff0328..6374d9f79e9 100644 --- a/crates/bindings/README.md +++ b/crates/bindings/README.md @@ -608,7 +608,7 @@ struct PlayerAndLevel { // At-most-one row: return Option #[view(name = my_player, public)] fn my_player(ctx: &ViewContext) -> Option { - ctx.db.player().identity().find(ctx.sender) + ctx.db.player().identity().find(ctx.sender()) } // Multiple rows: return Vec diff --git a/crates/bindings/src/lib.rs b/crates/bindings/src/lib.rs index b8f59220776..ebe5f7075b3 100644 --- a/crates/bindings/src/lib.rs +++ b/crates/bindings/src/lib.rs @@ -662,7 +662,7 @@ pub use spacetimedb_bindings_macro::table; /// /// #[reducer] /// fn scheduled(ctx: &ReducerContext, args: ScheduledArgs) -> Result<(), String> { -/// if ctx.sender != ctx.identity() { +/// if ctx.sender() != ctx.identity() { /// return Err("Reducer `scheduled` may not be invoked by clients, only via scheduling.".into()); /// } /// // Reducer body... @@ -707,7 +707,7 @@ pub use spacetimedb_bindings_macro::reducer; /// #[procedure] /// fn return_value(ctx: &mut ProcedureContext, arg: MyArgument) -> MyReturnValue { /// MyReturnValue { -/// a: format!("Hello, {}", ctx.sender), +/// a: format!("Hello, {}", ctx.sender()), /// b: ctx.timestamp, /// } /// } @@ -816,13 +816,13 @@ pub use spacetimedb_bindings_macro::procedure; /// // A view that selects at most one row from a table /// #[view(name = my_player, public)] /// fn my_player(ctx: &ViewContext) -> Option { -/// ctx.db.player().identity().find(ctx.sender) +/// ctx.db.player().identity().find(ctx.sender()) /// } /// /// // An example of column projection /// #[view(name = my_player_id, public)] /// fn my_player_id(ctx: &ViewContext) -> Option { -/// ctx.db.player().identity().find(ctx.sender).map(|Player { id, .. }| PlayerId { id }) +/// ctx.db.player().identity().find(ctx.sender()).map(|Player { id, .. }| PlayerId { id }) /// } /// /// // An example that is analogous to a semijoin in sql @@ -894,7 +894,7 @@ impl Default for AnonymousViewContext { /// The other is [`AnonymousViewContext`]. /// Use this type if the view depends on the caller's identity. pub struct ViewContext { - pub sender: Identity, + sender: Identity, pub db: LocalReadOnly, pub from: QueryBuilder, } @@ -907,6 +907,11 @@ impl ViewContext { from: QueryBuilder {}, } } + + /// The `Identity` of the client that invoked the view. + pub fn sender(&self) -> Identity { + self.sender + } } /// The context that any reducer is provided with. @@ -924,7 +929,7 @@ impl ViewContext { #[non_exhaustive] pub struct ReducerContext { /// The `Identity` of the client that invoked the reducer. - pub sender: Identity, + sender: Identity, /// The time at which the reducer was started. pub timestamp: Timestamp, @@ -1014,6 +1019,11 @@ impl ReducerContext { } } + /// The `Identity` of the client that invoked the reducer. + pub fn sender(&self) -> Identity { + self.sender + } + /// Returns the authorization information for the caller of this reducer. pub fn sender_auth(&self) -> &AuthCtx { &self.sender_auth @@ -1124,7 +1134,7 @@ impl Deref for TxContext { #[cfg(feature = "unstable")] pub struct ProcedureContext { /// The `Identity` of the client that invoked the procedure. - pub sender: Identity, + sender: Identity, /// The time at which the procedure was started. pub timestamp: Timestamp, @@ -1162,6 +1172,12 @@ impl ProcedureContext { counter_uuid: Cell::new(0), } } + + /// The `Identity` of the client that invoked the procedure. + pub fn sender(&self) -> Identity { + self.sender + } + /// Read the current module's [`Identity`]. pub fn identity(&self) -> Identity { // Hypothetically, we *could* read the module identity out of the system tables. diff --git a/demo/Blackholio/server-rust/src/lib.rs b/demo/Blackholio/server-rust/src/lib.rs index 08a70a7a767..f12d554cf3f 100644 --- a/demo/Blackholio/server-rust/src/lib.rs +++ b/demo/Blackholio/server-rust/src/lib.rs @@ -143,7 +143,7 @@ pub fn init(ctx: &ReducerContext) -> Result<(), String> { #[spacetimedb::reducer(client_connected)] pub fn connect(ctx: &ReducerContext) -> Result<(), String> { - if let Some(player) = ctx.db.logged_out_player().identity().find(&ctx.sender) { + if let Some(player) = ctx.db.logged_out_player().identity().find(&ctx.sender()) { ctx.db.player().insert(player.clone()); ctx.db.logged_out_player().identity().delete(&player.identity); @@ -157,7 +157,7 @@ pub fn connect(ctx: &ReducerContext) -> Result<(), String> { } } else { ctx.db.player().try_insert(Player { - identity: ctx.sender, + identity: ctx.sender(), player_id: 0, name: String::new(), })?; @@ -167,10 +167,15 @@ pub fn connect(ctx: &ReducerContext) -> Result<(), String> { #[spacetimedb::reducer(client_disconnected)] pub fn disconnect(ctx: &ReducerContext) -> Result<(), String> { - let player = ctx.db.player().identity().find(&ctx.sender).ok_or("Player not found")?; + let player = ctx + .db + .player() + .identity() + .find(&ctx.sender()) + .ok_or("Player not found")?; let player_id = player.player_id; ctx.db.logged_out_player().insert(player); - ctx.db.player().identity().delete(&ctx.sender); + ctx.db.player().identity().delete(&ctx.sender()); // Move any circles from the arena into logged out tables for circle in ctx.db.circle().player_id().filter(&player_id) { @@ -187,7 +192,7 @@ pub fn disconnect(ctx: &ReducerContext) -> Result<(), String> { #[spacetimedb::reducer] pub fn enter_game(ctx: &ReducerContext, name: String) -> Result<(), String> { log::info!("Creating player with name {}", name); - let mut player: Player = ctx.db.player().identity().find(ctx.sender).ok_or("")?; + let mut player: Player = ctx.db.player().identity().find(ctx.sender()).ok_or("")?; let player_id = player.player_id; player.name = name; ctx.db.player().identity().update(player); @@ -234,7 +239,7 @@ pub fn respawn(ctx: &ReducerContext) -> Result<(), String> { .db .player() .identity() - .find(&ctx.sender) + .find(&ctx.sender()) .ok_or("No such player found")?; spawn_player_initial_circle(ctx, player.player_id)?; @@ -248,7 +253,7 @@ pub fn suicide(ctx: &ReducerContext) -> Result<(), String> { .db .player() .identity() - .find(&ctx.sender) + .find(&ctx.sender()) .ok_or("No such player found")?; for circle in ctx.db.circle().player_id().filter(&player.player_id) { @@ -260,7 +265,12 @@ pub fn suicide(ctx: &ReducerContext) -> Result<(), String> { #[spacetimedb::reducer] pub fn update_player_input(ctx: &ReducerContext, direction: DbVector2) -> Result<(), String> { - let player = ctx.db.player().identity().find(&ctx.sender).ok_or("Player not found")?; + let player = ctx + .db + .player() + .identity() + .find(&ctx.sender()) + .ok_or("Player not found")?; for mut circle in ctx.db.circle().player_id().filter(&player.player_id) { circle.direction = direction.normalized(); circle.speed = direction.magnitude().clamp(0.0, 1.0); @@ -467,7 +477,7 @@ pub fn player_split(ctx: &ReducerContext) -> Result<(), String> { .db .player() .identity() - .find(&ctx.sender) + .find(&ctx.sender()) .ok_or("Sender has no player")?; let circles: Vec = ctx.db.circle().player_id().filter(&player.player_id).collect(); let mut circle_count = circles.len() as i32; diff --git a/docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md b/docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md index d4fa03561bd..63eff91f7b0 100644 --- a/docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md +++ b/docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md @@ -451,7 +451,7 @@ A view can be written in Rust like so: ```rust #[spacetimedb::view(name = my_player, public)] fn my_player(ctx: &spacetimedb::ViewContext) -> Option { - ctx.db.player().identity().find(ctx.sender) + ctx.db.player().identity().find(ctx.sender()) } ``` diff --git a/docs/docs/00100-intro/00300-tutorials/00100-chat-app.md b/docs/docs/00100-intro/00300-tutorials/00100-chat-app.md index d1e6b2c3aae..06ef0c039ce 100644 --- a/docs/docs/00100-intro/00300-tutorials/00100-chat-app.md +++ b/docs/docs/00100-intro/00300-tutorials/00100-chat-app.md @@ -348,7 +348,7 @@ Add to `spacetimedb/src/lib.rs`: #[reducer] pub fn set_name(ctx: &ReducerContext, name: String) -> Result<(), String> { let name = validate_name(name)?; - if let Some(user) = ctx.db.user().identity().find(ctx.sender) { + if let Some(user) = ctx.db.user().identity().find(ctx.sender()) { ctx.db.user().identity().update(User { name: Some(name), ..user }); Ok(()) } else { @@ -439,7 +439,7 @@ pub fn send_message(ctx: &ReducerContext, text: String) -> Result<(), String> { let text = validate_message(text)?; log::info!("{}", text); ctx.db.message().insert(Message { - sender: ctx.sender, + sender: ctx.sender(), text, sent: ctx.timestamp, }); @@ -547,12 +547,12 @@ Add to `spacetimedb/src/lib.rs`: ```rust server #[reducer(client_connected)] pub fn client_connected(ctx: &ReducerContext) { - if let Some(user) = ctx.db.user().identity().find(ctx.sender) { + if let Some(user) = ctx.db.user().identity().find(ctx.sender()) { ctx.db.user().identity().update(User { online: true, ..user }); } else { ctx.db.user().insert(User { name: None, - identity: ctx.sender, + identity: ctx.sender(), online: true, }); } @@ -560,10 +560,10 @@ pub fn client_connected(ctx: &ReducerContext) { #[reducer(client_disconnected)] pub fn identity_disconnected(ctx: &ReducerContext) { - if let Some(user) = ctx.db.user().identity().find(ctx.sender) { + if let Some(user) = ctx.db.user().identity().find(ctx.sender()) { ctx.db.user().identity().update(User { online: false, ..user }); } else { - log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender); + log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender()); } } ``` diff --git a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md index 03c579a088a..b6766e12672 100644 --- a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md +++ b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md @@ -345,7 +345,7 @@ public static void Debug(ReducerContext ctx) ```rust #[spacetimedb::reducer] pub fn debug(ctx: &ReducerContext) -> Result<(), String> { - log::debug!("This reducer was called by {}.", ctx.sender); + log::debug!("This reducer was called by {}.", ctx.sender()); Ok(()) } ``` @@ -463,7 +463,7 @@ Next let's connect our client to our database. Let's start by modifying our `deb ```rust #[spacetimedb::reducer(client_connected)] pub fn connect(ctx: &ReducerContext) -> Result<(), String> { - log::debug!("{} just connected.", ctx.sender); + log::debug!("{} just connected.", ctx.sender()); Ok(()) } ``` diff --git a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md index a00681a6c49..ab95e71294d 100644 --- a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md +++ b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md @@ -391,7 +391,7 @@ Next, modify your `connect` reducer and add a new `disconnect` reducer below it: ```rust #[spacetimedb::reducer(client_connected)] pub fn connect(ctx: &ReducerContext) -> Result<(), String> { - if let Some(player) = ctx.db.logged_out_player().identity().find(&ctx.sender) { + if let Some(player) = ctx.db.logged_out_player().identity().find(&ctx.sender()) { ctx.db.player().insert(player.clone()); ctx.db .logged_out_player() @@ -399,7 +399,7 @@ pub fn connect(ctx: &ReducerContext) -> Result<(), String> { .delete(&player.identity); } else { ctx.db.player().try_insert(Player { - identity: ctx.sender, + identity: ctx.sender(), player_id: 0, name: String::new(), })?; @@ -413,11 +413,11 @@ pub fn disconnect(ctx: &ReducerContext) -> Result<(), String> { .db .player() .identity() - .find(&ctx.sender) + .find(&ctx.sender()) .ok_or("Player not found")?; let player_id = player.player_id; ctx.db.logged_out_player().insert(player); - ctx.db.player().identity().delete(&ctx.sender); + ctx.db.player().identity().delete(&ctx.sender()); Ok(()) } diff --git a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00500-part-4.md b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00500-part-4.md index d00bd48fcf9..647efe78bcb 100644 --- a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00500-part-4.md +++ b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00500-part-4.md @@ -207,7 +207,7 @@ pub fn update_player_input(ctx: &ReducerContext, direction: DbVector2) -> Result .db .player() .identity() - .find(&ctx.sender) + .find(&ctx.sender()) .ok_or("Player not found")?; for mut circle in ctx.db.circle().player_id().filter(&player.player_id) { circle.direction = direction.normalized(); @@ -218,7 +218,7 @@ pub fn update_player_input(ctx: &ReducerContext, direction: DbVector2) -> Result } ``` -This is a simple reducer that takes the movement input from the client and applies them to all circles that that player controls. Note that it is not possible for a player to move another player's circles using this reducer, because the `ctx.sender` value is not set by the client. Instead `ctx.sender` is set by SpacetimeDB after it has authenticated that sender. You can rest assured that the caller has been authenticated as that player by the time this reducer is called. +This is a simple reducer that takes the movement input from the client and applies them to all circles that that player controls. Note that it is not possible for a player to move another player's circles using this reducer, because the `ctx.sender()` value is not set by the client. Instead `ctx.sender()` is set by SpacetimeDB after it has authenticated that sender. You can rest assured that the caller has been authenticated as that player by the time this reducer is called. diff --git a/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00300-part-2.md b/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00300-part-2.md index 0502ab9f87f..bde4659ba26 100644 --- a/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00300-part-2.md +++ b/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00300-part-2.md @@ -343,7 +343,7 @@ public static void Debug(ReducerContext ctx) ```rust #[spacetimedb::reducer] pub fn debug(ctx: &ReducerContext) -> Result<(), String> { - log::debug!("This reducer was called by {}.", ctx.sender); + log::debug!("This reducer was called by {}.", ctx.sender()); Ok(()) } ``` @@ -459,7 +459,7 @@ Next let's connect our client to our database. Let's start by modifying our `deb ```rust #[spacetimedb::reducer(client_connected)] pub fn connect(ctx: &ReducerContext) -> Result<(), String> { - log::debug!("{} just connected.", ctx.sender); + log::debug!("{} just connected.", ctx.sender()); Ok(()) } ``` diff --git a/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00400-part-3.md b/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00400-part-3.md index 859ab5157e9..192c7d3ebc8 100644 --- a/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00400-part-3.md +++ b/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00400-part-3.md @@ -384,7 +384,7 @@ Next, modify your `connect` reducer and add a new `disconnect` reducer below it: ```rust #[spacetimedb::reducer(client_connected)] pub fn connect(ctx: &ReducerContext) -> Result<(), String> { - if let Some(player) = ctx.db.logged_out_player().identity().find(&ctx.sender) { + if let Some(player) = ctx.db.logged_out_player().identity().find(&ctx.sender()) { ctx.db.player().insert(player.clone()); ctx.db .logged_out_player() @@ -392,7 +392,7 @@ pub fn connect(ctx: &ReducerContext) -> Result<(), String> { .delete(&player.identity); } else { ctx.db.player().try_insert(Player { - identity: ctx.sender, + identity: ctx.sender(), player_id: 0, name: String::new(), })?; @@ -406,11 +406,11 @@ pub fn disconnect(ctx: &ReducerContext) -> Result<(), String> { .db .player() .identity() - .find(&ctx.sender) + .find(&ctx.sender()) .ok_or("Player not found")?; let player_id = player.player_id; ctx.db.logged_out_player().insert(player); - ctx.db.player().identity().delete(&ctx.sender); + ctx.db.player().identity().delete(&ctx.sender()); Ok(()) } @@ -499,7 +499,7 @@ const START_PLAYER_MASS: i32 = 15; #[spacetimedb::reducer] pub fn enter_game(ctx: &ReducerContext, name: String) -> Result<(), String> { log::info!("Creating player with name {}", name); - let mut player: Player = ctx.db.player().identity().find(ctx.sender).ok_or("")?; + let mut player: Player = ctx.db.player().identity().find(ctx.sender()).ok_or("")?; let player_id = player.player_id; player.name = name; ctx.db.player().identity().update(player); @@ -589,11 +589,11 @@ pub fn disconnect(ctx: &ReducerContext) -> Result<(), String> { .db .player() .identity() - .find(&ctx.sender) + .find(&ctx.sender()) .ok_or("Player not found")?; let player_id = player.player_id; ctx.db.logged_out_player().insert(player); - ctx.db.player().identity().delete(&ctx.sender); + ctx.db.player().identity().delete(&ctx.sender()); // Remove any circles from the arena for circle in ctx.db.circle().player_id().filter(&player_id) { diff --git a/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00500-part-4.md b/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00500-part-4.md index 643256545c2..ae8eb620633 100644 --- a/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00500-part-4.md +++ b/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00500-part-4.md @@ -207,7 +207,7 @@ pub fn update_player_input(ctx: &ReducerContext, direction: DbVector2) -> Result .db .player() .identity() - .find(&ctx.sender) + .find(&ctx.sender()) .ok_or("Player not found")?; for mut circle in ctx.db.circle().player_id().filter(&player.player_id) { circle.direction = direction.normalized(); @@ -218,7 +218,7 @@ pub fn update_player_input(ctx: &ReducerContext, direction: DbVector2) -> Result } ``` -This is a simple reducer that takes the movement input from the client and applies them to all circles that that player controls. Note that it is not possible for a player to move another player's circles using this reducer, because the `ctx.sender` value is not set by the client. Instead `ctx.sender` is set by SpacetimeDB after it has authenticated that sender. You can rest assured that the caller has been authenticated as that player by the time this reducer is called. +This is a simple reducer that takes the movement input from the client and applies them to all circles that that player controls. Note that it is not possible for a player to move another player's circles using this reducer, because the `ctx.sender()` value is not set by the client. Instead `ctx.sender()` is set by SpacetimeDB after it has authenticated that sender. You can rest assured that the caller has been authenticated as that player by the time this reducer is called. diff --git a/docs/docs/00200-core-concepts/00100-databases/00500-cheat-sheet.md b/docs/docs/00200-core-concepts/00100-databases/00500-cheat-sheet.md index 529e79d6ec4..e4754aca0e8 100644 --- a/docs/docs/00200-core-concepts/00100-databases/00500-cheat-sheet.md +++ b/docs/docs/00200-core-concepts/00100-databases/00500-cheat-sheet.md @@ -477,7 +477,7 @@ use spacetimedb::{view, ViewContext}; // Return single row #[view(name = my_player, public)] fn my_player(ctx: &ViewContext) -> Option { - ctx.db.player().identity().find(ctx.sender) + ctx.db.player().identity().find(ctx.sender()) } // Return multiple rows @@ -522,7 +522,7 @@ ctx.Rng // Random number generator ```rust ctx.db // Database access -ctx.sender // Identity of caller +ctx.sender() // Identity of caller ctx.connection_id // Option ctx.timestamp // Timestamp ctx.identity() // Module's identity diff --git a/docs/docs/00200-core-concepts/00100-databases/00500-migrations/00300-incremental-migrations.md b/docs/docs/00200-core-concepts/00100-databases/00500-migrations/00300-incremental-migrations.md index e8a2bcdd63c..692df88e501 100644 --- a/docs/docs/00200-core-concepts/00100-databases/00500-migrations/00300-incremental-migrations.md +++ b/docs/docs/00200-core-concepts/00100-databases/00500-migrations/00300-incremental-migrations.md @@ -46,7 +46,7 @@ fn create_character(ctx: &ReducerContext, class: Class, nickname: String) { "Creating new level 1 {class:?} named {nickname}", ); ctx.db.character().insert(Character { - player_id: ctx.sender, + player_id: ctx.sender(), nickname, level: 1, class, @@ -57,7 +57,7 @@ fn find_character_for_player(ctx: &ReducerContext) -> Character { ctx.db .character() .player_id() - .find(ctx.sender) + .find(ctx.sender()) .expect("Player has not created a character") } @@ -154,7 +154,7 @@ fn choose_alliance(ctx: &ReducerContext, alliance: Alliance) { "Setting {}'s alliance to {:?} for player {}", character.nickname, alliance, - ctx.sender, + ctx.sender(), ); update_character( ctx, @@ -194,18 +194,18 @@ When a new player creates a character, we'll make rows in both tables for them. fn create_character(ctx: &ReducerContext, class: Class, nickname: String) { log::info!( "Creating new level 1 {class:?} named {nickname} for player {}", - ctx.sender, + ctx.sender(), ); ctx.db.character().insert(Character { - player_id: ctx.sender, + player_id: ctx.sender(), nickname: nickname.clone(), level: 1, class, }); ctx.db.character_v2().insert(CharacterV2 { - player_id: ctx.sender, + player_id: ctx.sender(), nickname, level: 1, class, @@ -218,7 +218,7 @@ We'll update our helper functions so that they operate on `character_v2` rows. I ```rust fn find_character_for_player(ctx: &ReducerContext) -> CharacterV2 { - if let Some(character) = ctx.db.character_v2().player_id().find(ctx.sender) { + if let Some(character) = ctx.db.character_v2().player_id().find(ctx.sender()) { // Already migrated; just return the new player. return character; } @@ -228,7 +228,7 @@ fn find_character_for_player(ctx: &ReducerContext) -> CharacterV2 { .db .character() .player_id() - .find(ctx.sender) + .find(ctx.sender()) .expect("Player has not created a character"); ctx.db.character_v2().insert(CharacterV2 { diff --git a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00400-reducer-context.md b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00400-reducer-context.md index 32b96e5ed33..38f447125d4 100644 --- a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00400-reducer-context.md +++ b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00400-reducer-context.md @@ -174,7 +174,7 @@ pub struct Player { #[reducer] fn update_score(ctx: &ReducerContext, new_score: u32) { // Get the caller's identity - let caller = ctx.sender; + let caller = ctx.sender(); // Find and update their player record if let Some(mut player) = ctx.db.player().identity().find(caller) { @@ -290,7 +290,7 @@ pub struct ScheduledTask { #[reducer] fn send_reminder(ctx: &ReducerContext, task: ScheduledTask) { // Only allow the scheduler (module identity) to call this - if ctx.sender != ctx.identity() { + if ctx.sender() != ctx.identity() { panic!("This reducer can only be called by the scheduler"); } diff --git a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00500-lifecycle.md b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00500-lifecycle.md index 975f589b437..20f43bc8394 100644 --- a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00500-lifecycle.md +++ b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00500-lifecycle.md @@ -131,7 +131,7 @@ public static void OnConnect(ReducerContext ctx) ```rust #[reducer(client_connected)] pub fn on_connect(ctx: &ReducerContext) -> Result<(), String> { - log::info!("Client connected: {}", ctx.sender); + log::info!("Client connected: {}", ctx.sender()); // ctx.connection_id is guaranteed to be Some(...) let conn_id = ctx.connection_id.unwrap(); @@ -139,7 +139,7 @@ pub fn on_connect(ctx: &ReducerContext) -> Result<(), String> { // Initialize client session ctx.db.sessions().try_insert(Session { connection_id: conn_id, - identity: ctx.sender, + identity: ctx.sender(), connected_at: ctx.timestamp, })?; @@ -198,7 +198,7 @@ public static void OnDisconnect(ReducerContext ctx) ```rust #[reducer(client_disconnected)] pub fn on_disconnect(ctx: &ReducerContext) -> Result<(), String> { - log::info!("Client disconnected: {}", ctx.sender); + log::info!("Client disconnected: {}", ctx.sender()); // ctx.connection_id is guaranteed to be Some(...) let conn_id = ctx.connection_id.unwrap(); @@ -230,6 +230,6 @@ Reducers can be triggered at specific times using schedule tables. See [Schedule :::info Scheduled Reducer Context Scheduled reducer calls originate from SpacetimeDB itself, not from a client. Therefore: -- `ctx.sender` will be the module's own identity +- `ctx.sender()` will be the module's own identity - `ctx.connection_id` will be `None`/`null`/`undefined` ::: diff --git a/docs/docs/00200-core-concepts/00200-functions/00500-views.md b/docs/docs/00200-core-concepts/00200-functions/00500-views.md index 97ec7e2077f..0603fa97dad 100644 --- a/docs/docs/00200-core-concepts/00200-functions/00500-views.md +++ b/docs/docs/00200-core-concepts/00200-functions/00500-views.md @@ -55,7 +55,7 @@ spacetimedb.view( { name: 'my_player', public: true }, t.option(players.rowType), (ctx) => { - const row = ctx.db.players.identity.find(ctx.sender); + const row = ctx.db.players.identity.find(ctx.sender()); return row ?? undefined; } ); @@ -197,7 +197,7 @@ pub struct PlayerAndLevel { // At-most-one row: return Option #[view(name = my_player, public)] fn my_player(ctx: &ViewContext) -> Option { - ctx.db.player().identity().find(ctx.sender) + ctx.db.player().identity().find(ctx.sender()) } // Multiple rows: return Vec @@ -232,7 +232,7 @@ Views can return either `Option` for at-most-one row or `Vec` for multiple Views use one of two context types: -- **`ViewContext`**: Provides access to the caller's `Identity` through `ctx.sender`. Use this when the view depends on who is querying it. +- **`ViewContext`**: Provides access to the caller's `Identity` through `ctx.sender()`. Use this when the view depends on who is querying it. - **`AnonymousViewContext`**: Does not provide caller information. Use this when the view produces the same results regardless of who queries it. Both contexts provide read-only access to tables and indexes through `ctx.db`. @@ -243,7 +243,7 @@ The choice between `ViewContext` and `AnonymousViewContext` has significant perf **Anonymous views can be shared across all subscribers.** When a view uses `AnonymousViewContext`, SpacetimeDB knows the result is the same for every client. The database can materialize the view once and serve that same result to all subscribers. When the underlying data changes, it recomputes the view once and broadcasts the update to everyone. -**Per-user views require separate computation for each subscriber.** When a view uses `ViewContext`, the result depends on `ctx.sender`, so each client potentially sees different data. SpacetimeDB must compute and track the view separately for each subscriber. With 1,000 connected users, that's 1,000 separate view computations and 1,000 separate sets of change tracking. +**Per-user views require separate computation for each subscriber.** When a view uses `ViewContext` and invokes `ctx.sender()`, each client potentially sees different data. SpacetimeDB must compute and track the view separately for each subscriber. With 1,000 connected users, that's 1,000 separate view computations and 1,000 separate sets of change tracking. **Prefer `AnonymousViewContext` when possible.** Design your views to be caller-independent when the use case allows. For example: @@ -294,7 +294,7 @@ public static Player? MyPlayer(ViewContext ctx) // Per-user: each client sees their own player #[view(name = my_player, public)] fn my_player(ctx: &ViewContext) -> Option { - ctx.db.player().identity().find(&ctx.sender) + ctx.db.player().identity().find(&ctx.sender()) } ``` @@ -541,7 +541,7 @@ fn entities_in_origin_chunk(ctx: &AnonymousViewContext) -> Vec { // Per-user: returns entities in the chunk the player is currently in #[view(name = entities_in_my_chunk, public)] fn entities_in_my_chunk(ctx: &ViewContext) -> Vec { - let Some(player) = ctx.db.player().identity().find(&ctx.sender) else { + let Some(player) = ctx.db.player().identity().find(&ctx.sender()) else { return vec![]; }; let Some(chunk) = ctx.db.player_chunk().player_id().find(&player.id) else { diff --git a/docs/docs/00200-core-concepts/00300-tables.md b/docs/docs/00200-core-concepts/00300-tables.md index 763bbcd8df7..cf3727b18d8 100644 --- a/docs/docs/00200-core-concepts/00300-tables.md +++ b/docs/docs/00200-core-concepts/00300-tables.md @@ -382,7 +382,7 @@ ctx.db.player().insert(Player { /* ... */ }); ctx.db.logged_out_player().insert(Player { /* ... */ }); // Move a row between tables -if let Some(player) = ctx.db.logged_out_player().identity().find(&ctx.sender) { +if let Some(player) = ctx.db.logged_out_player().identity().find(&ctx.sender()) { ctx.db.player().insert(player.clone()); ctx.db.logged_out_player().identity().delete(&player.identity); } diff --git a/docs/docs/00200-core-concepts/00300-tables/00210-file-storage.md b/docs/docs/00200-core-concepts/00300-tables/00210-file-storage.md index 5e0f51551b4..33e617c542a 100644 --- a/docs/docs/00200-core-concepts/00300-tables/00210-file-storage.md +++ b/docs/docs/00200-core-concepts/00300-tables/00210-file-storage.md @@ -263,7 +263,7 @@ pub fn register_document( ) { ctx.db.document().insert(Document { id: 0, // auto-increment - owner_id: ctx.sender, + owner_id: ctx.sender(), filename, mime_type, size_bytes, diff --git a/docs/docs/00200-core-concepts/00300-tables/00400-access-permissions.md b/docs/docs/00200-core-concepts/00300-tables/00400-access-permissions.md index 08cb9ed04f1..0f3c83978ed 100644 --- a/docs/docs/00200-core-concepts/00300-tables/00400-access-permissions.md +++ b/docs/docs/00200-core-concepts/00300-tables/00400-access-permissions.md @@ -330,7 +330,7 @@ Views can only access table data through indexed lookups, not by scanning all ro ### Filtering Rows by Caller -Use views with `ViewContext` to return only the rows that belong to the caller. The view accesses the caller's identity through `ctx.sender` and uses it to look up rows via an index. +Use views with `ViewContext` to return only the rows that belong to the caller. The view accesses the caller's identity through `ctx.sender()` and uses it to look up rows via an index. @@ -426,8 +426,8 @@ pub struct Message { #[spacetimedb::view(name = my_messages, public)] fn my_messages(ctx: &ViewContext) -> Vec { // Look up messages by index where caller is sender or recipient - let sent: Vec<_> = ctx.db.message().sender().filter(&ctx.sender).collect(); - let received: Vec<_> = ctx.db.message().recipient().filter(&ctx.sender).collect(); + let sent: Vec<_> = ctx.db.message().sender().filter(&ctx.sender()).collect(); + let received: Vec<_> = ctx.db.message().recipient().filter(&ctx.sender()).collect(); sent.into_iter().chain(received).collect() } ``` @@ -574,7 +574,7 @@ pub struct PublicUserProfile { #[spacetimedb::view(name = my_profile, public)] fn my_profile(ctx: &ViewContext) -> Option { // Look up the caller's account by their identity (unique index) - let user = ctx.db.user_account().identity().find(&ctx.sender)?; + let user = ctx.db.user_account().identity().find(&ctx.sender())?; Some(PublicUserProfile { id: user.id, username: user.username, @@ -726,7 +726,7 @@ pub struct Colleague { #[spacetimedb::view(name = my_colleagues, public)] fn my_colleagues(ctx: &ViewContext) -> Vec { // Find the caller's employee record by identity (unique index) - let Some(me) = ctx.db.employee().identity().find(&ctx.sender) else { + let Some(me) = ctx.db.employee().identity().find(&ctx.sender()) else { return vec![]; }; diff --git a/docs/docs/00300-resources/00100-how-to/00300-logging.md b/docs/docs/00300-resources/00100-how-to/00300-logging.md index 83dd011566f..1958b01634e 100644 --- a/docs/docs/00300-resources/00100-how-to/00300-logging.md +++ b/docs/docs/00300-resources/00100-how-to/00300-logging.md @@ -102,7 +102,7 @@ pub fn process_data(ctx: &ReducerContext, value: u32) -> Result<(), String> { return Err("Value cannot be zero".to_string()); } - log::debug!("Debug information: ctx.sender = {:?}", ctx.sender); + log::debug!("Debug information: ctx.sender = {:?}", ctx.sender()); Ok(()) } @@ -220,7 +220,7 @@ use spacetimedb::log; pub fn transfer_credits(ctx: &ReducerContext, to_user: u64, amount: u32) -> Result<(), String> { log::info!( "Credit transfer: from={:?}, to={}, amount={}", - ctx.sender, + ctx.sender(), to_user, amount ); diff --git a/docs/llms/docs-benchmark-analysis.md b/docs/llms/docs-benchmark-analysis.md index faa301f26fc..fe284ef576a 100644 --- a/docs/llms/docs-benchmark-analysis.md +++ b/docs/llms/docs-benchmark-analysis.md @@ -4,247 +4,394 @@ Generated from: `/__w/SpacetimeDB/SpacetimeDB/tools/xtask-llm-benchmark/../../do ## Summary -- **Total failures analyzed**: 33 +- **Total failures analyzed**: 31 --- -## Analysis of SpacetimeDB Benchmark Test Failures - -### Rust / rustdoc_json Failures - -#### Compile/Publish Errors (2 Failures) - -##### Failure Group 1: `t_002_scheduled_table` and `t_017_scheduled_columns` -1. **The generated code**: - ```rust - use spacetimedb::{table, reducer, ReducerContext, Table, ScheduleAt}; - - #[table(name = tick_timer, schedule(reducer = tick, column = scheduled_at))] - pub struct TickTimer { - #[primary_key] - #[auto_inc] - scheduled_id: u64, - scheduled_at: ScheduleAt, - } - - #[reducer(init)] - pub fn init(ctx: &ReducerContext) { - if ctx.db.tick_timer().count() == 0 { - ctx.db.tick_timer().insert(TickTimer { - scheduled_id: 0, - scheduled_at: ScheduleAt::RepeatMicros(50_000), - }); - } - } - - #[reducer] - pub fn tick(_ctx: &ReducerContext, _row: TickTimer) { - } - ``` - -2. **The golden example**: - ```rust - use spacetimedb::{reducer, table, ReducerContext, ScheduleAt, Table}; - use std::time::Duration; - - #[table(name = tick_timer, scheduled(tick))] - pub struct TickTimer { - #[primary_key] - #[auto_inc] - pub scheduled_id: u64, - pub scheduled_at: ScheduleAt, - } - - #[reducer] - pub fn tick(_ctx: &ReducerContext, _schedule: TickTimer) { - } - - #[reducer(init)] - pub fn init(ctx: &ReducerContext) { - let every_50ms: ScheduleAt = Duration::from_millis(50).into(); - ctx.db.tick_timer().insert(TickTimer { - scheduled_id: 0, - scheduled_at: every_50ms, - }); - } - ``` - -3. **The error**: - - `publish_error: spacetime publish failed (exit=1)` - -4. **Explain the difference**: - - The generated code used `ScheduleAt::RepeatMicros(50_000)` instead of the correct `ScheduleAt::Interval(Duration::from_millis(50).into())`. The way the scheduling was set up was incorrect. - -5. **Root cause**: - - The documentation does not clearly specify the constructor syntax for `ScheduleAt` nor how to correctly set up the scheduled tasks in this context. - -6. **Recommendation**: - - Update documentation to provide examples of different constructors for `ScheduleAt`, specifically emphasizing how to define intervals correctly. +# Analysis of SpacetimeDB Benchmark Test Failures + +## Rust / rustdoc_json Failures + +### Compile/Publish Errors (3 Failures) + +#### 1. **t_002_scheduled_table** +- **Generated Code**: + ```rust + #[table(name = tick_timer, schedule(column = scheduled_at, reducer = tick))] + pub struct TickTimer { + #[primary_key] + #[auto_inc] + scheduled_id: u64, + scheduled_at: ScheduleAt, + } + ``` + +- **Golden Example**: + ```rust + #[table(name = tick_timer, scheduled(tick))] + pub struct TickTimer { + #[primary_key] + #[auto_inc] + pub scheduled_id: u64, + pub scheduled_at: ScheduleAt, + } + ``` + +- **Error**: `publish_error: spacetime publish failed (exit=1)` + +- **Explanation**: + The LLM used incorrect syntax for the `scheduled` attribute. It should be `scheduled(tick)` instead of `schedule(column = scheduled_at, reducer = tick)`. + +- **Root Cause**: The documentation may not clearly explain the syntax for the `scheduled` attribute. + +- **Recommendation**: Update documentation to emphasize that the `scheduled` attribute must be structured as `scheduled(reducer_name)`. --- -#### Other Failures (5 failures) - -##### Failure Group 2: `t_013_spacetime_sum_type`, `t_015_product_type_columns`, `t_016_sum_type_columns`, `t_018_constraints`, `t_020_ecs` -1. **The generated code**: - ```rust - use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType}; - - #[derive(SpacetimeType)] - pub struct Rect { - width: i32, - height: i32, - } - - #[table(name = result)] - pub struct ResultRow { - #[primary_key] - id: i32, - value: Shape, - } - - #[reducer] - pub fn set_circle(ctx: &ReducerContext, id: i32, radius: i32) { - ctx.db.result().insert(ResultRow { - id, - value: Shape::Circle(radius), - }); - } - ``` - -2. **The golden example**: - ```rust - use spacetimedb::{reducer, table, ReducerContext, SpacetimeType, Table}; - - #[derive(SpacetimeType, Clone, Debug)] - pub struct Rect { - pub width: i32, - pub height: i32, - } - - #[table(name = result)] - pub struct ResultRow { - #[primary_key] - pub id: i32, - pub value: Shape, - } - - #[reducer] - pub fn set_circle(ctx: &ReducerContext, id: i32, radius: i32) { - ctx.db.result().insert(ResultRow { id, value: Shape::Circle(radius) }); - } - ``` - -3. **The error**: - - `spacetime sql failed: no such table: result` - - `spacetime sql failed: no such table: profile` - - `spacetime sql failed: no such table: drawings` - -4. **Explain the difference**: - - The generated code omits the `pub` visibility keyword for fields and structs, which prevents proper access by the macros that generate the expected database schema. Additionally, the enum `Shape` wasn't declared correctly in the generated code. - -5. **Root cause**: - - Lack of proper visibility (missing `pub`) for structs and enum fields was not clearly emphasized in the documentation, leading to access issues. - -6. **Recommendation**: - - Provide clear guidelines in the documentation regarding the necessity of using `pub` for struct and enum fields when working with SpacetimeDB components. Include example schemas with visibility marked. +#### 2. **t_003_struct_in_table** +- **Generated Code**: + ```rust + #[spacetimedb::table(name = entity)] + pub struct Entity { + #[primary_key] + id: i32, + pos: Position, + } + ``` + +- **Golden Example**: + ```rust + #[table(name = entity)] + pub struct Entity { + #[primary_key] + pub id: i32, + pub pos: Position, + } + ``` + +- **Error**: `publish_error: spacetime publish failed (exit=1)` + +- **Explanation**: + The LLM did not use `pub` for struct fields which is required for visibility in SpacetimeDB. + +- **Root Cause**: The visibility rules for struct fields in Rust may need clearer explanation in the documentation. + +- **Recommendation**: Include specific examples indicating that all fields in SpacetimeDB tables should be public. --- -### Rust / docs Failures (22 total) +#### 3. **t_017_scheduled_columns** +- **Generated Code**: + ```rust + #[reducer(init)] + pub fn init(ctx: &ReducerContext) { + if ctx.db.tick_timer().count() == 0 { + ctx.db.tick_timer().insert(TickTimer { + scheduled_id: 0, + scheduled_at: ScheduleAt::repeat_micros(50_000), + }); + } + } + ``` + +- **Golden Example**: + ```rust + #[reducer(init)] + pub fn init(ctx: &ReducerContext) { + let every_50ms: ScheduleAt = Duration::from_millis(50).into(); + ctx.db.tick_timer().insert(TickTimer { + scheduled_id: 0, + scheduled_at: every_50ms, + }); + } + ``` + +- **Error**: `publish_error: spacetime publish failed (exit=1)` + +- **Explanation**: The method for initializing `scheduled_at` is incorrect. Instead of using `repeat_micros()`, the code should convert a `Duration` to `ScheduleAt`. + +- **Root Cause**: Misunderstanding of the proper way to initialize scheduled columns could be reflected in lacking documentation details. + +- **Recommendation**: Clarify the documentation regarding initializing `ScheduleAt`, emphasizing conversion from `Duration`. + +--- + +### Other Failures (2 Failures) + +#### 4. **t_016_sum_type_columns** +- **Generated Code**: + ```rust + #[spacetimedb::table(name = drawing)] + pub struct Drawing { + #[primary_key] + id: i32, + a: Shape, + b: Shape, + } + ``` + +- **Golden Example**: + ```rust + #[table(name = drawing)] + pub struct Drawing { + #[primary_key] + pub id: i32, + pub a: Shape, + pub b: Shape, + } + ``` + +- **Error**: Errors regarding tables not found. -#### Timeout Issues (1 failure) +- **Explanation**: Missing the `pub` attribute on struct fields results in failure to compile. -1. **Failure Group**: `t_015_product_type_columns` - - **Expected**: Modify the query logic to ensure no unnecessary long-running operations exist. - - **Recommendation**: Provide timeout considerations in the documentation to ensure optimization options are explored to prevent long-running tasks. +- **Root Cause**: Lack of clarity on the use of visibility attributes (`pub`) in struct definitions. + +- **Recommendation**: Revise documentation to instruct that fields must be public to work within SpacetimeDB. + +--- + +#### 5. **t_020_ecs** +- **Generated Code**: + ```rust + #[spacetimedb::table(name = entity)] + pub struct Entity { + #[primary_key] + id: i32, + } + + #[spacetimedb::table(name = position)] + pub struct Position { + #[primary_key] + entity_id: i32, + x: i32, + y: i32, + } + ``` + +- **Golden Example**: + ```rust + #[table(name = entity)] + pub struct Entity { + #[primary_key] + pub id: i32, + } + + #[table(name = position)] + pub struct Position { + #[primary_key] + pub entity_id: i32, + pub x: i32, + pub y: i32, + } + ``` + +- **Error**: Errors regarding tables not found. + +- **Explanation**: Missing the `pub` attribute leads to the struct not being properly registered with SpacetimeDB. + +- **Root Cause**: Similar to previous errors, the need for public access to struct fields is unclear. + +- **Recommendation**: Ensure documentation explicitly states that public access is necessary for all fields in SpacetimeDB structs. + +--- + +## Rust / docs Failures (22 total) + +### Timeout Issues (8 Failures) + +- **Failures**: Various tasks timed out, indicating potential performance or configuration issues. + +- **Root Cause**: Specifics of timeout settings and performance optimization strategies should be more explicit in the documentation. + +- **Recommendation**: Include guidelines on optimizing performance for long-running tasks or emphasize best practices for structuring queries and data handling. + +--- + +### Other Failures (14 Failures) + +#### 6. **t_000_empty_reducers** +- **Generated Code**: + ```rust + #[spacetimedb::reducer] + pub fn empty_reducer_no_args(_ctx: &spacetimedb::ReducerContext) { + } + ``` + +- **Golden Example**: + ```rust + #[reducer] + pub fn empty_reducer_no_args(ctx: &ReducerContext) -> Result<(), String> { + Ok(()) + } + ``` + +- **Error**: Schema-related errors due to missing return type and proper handling. + +- **Explanation**: Missing return type (`Result<(), String>`) was not implemented. + +- **Root Cause**: The documentation may not explicitly mention that reducers should return results. + +- **Recommendation**: Adjust the documentation to specify that reducer functions must include appropriate return types. + +--- + +#### 7. **t_001_basic_tables** +- **Generated Code**: + ```rust + #[spacetimedb::table(name = user)] + pub struct User { + #[primary_key] + id: i32, + name: String, + age: i32, + active: bool, + } + ``` + +- **Golden Example**: + ```rust + #[table(name = user)] + pub struct User { + #[primary_key] + pub id: i32, + pub name: String, + pub age: i32, + pub active: bool, + } + ``` + +- **Error**: Schema-related errors due to missing `pub` modifiers. + +- **Explanation**: Missing public access modifiers on struct fields prevented expected behavior. + +- **Root Cause**: Visibility rules may not have been adequately covered in the documentation. + +- **Recommendation**: Ensure the documentation includes examples with visibility modifiers. --- ### C# / docs Failures (4 total) -#### C# Failure Group: `t_014_elementary_columns`, `t_016_sum_type_columns`, `t_017_scheduled_columns`, `t_020_ecs` -1. **The generated code**: - ```csharp - using SpacetimeDB; - - public static partial class Module - { - [SpacetimeDB.Table(Name = "Primitive", Public = true)] - public partial struct Primitive - { - [SpacetimeDB.PrimaryKey] - public int Id; - public int Count; - public long Total; - public float Price; - public double Ratio; - public bool Active; - public string Name; - } - - [SpacetimeDB.Reducer] - public static void Seed(ReducerContext ctx) - { - ctx.Db.Primitive.Insert(new Primitive - { - Id = 1, - Count = 2, - Total = 3000000000L, - Price = 1.5f, - Ratio = 2.25, - Active = true, - Name = "Alice" - }); - } - } - ``` - -2. **The golden example**: - ```csharp - using SpacetimeDB; - - public static partial class Module - { - [Table(Name = "Primitive")] - public partial struct Primitive - { - [PrimaryKey] public int Id; - public int Count; - public long Total; - public float Price; - public double Ratio; - public bool Active; - public string Name; - } - - [Reducer] - public static void Seed(ReducerContext ctx) - { - ctx.Db.Primitive.Insert(new Primitive { - Id = 1, - Count = 2, - Total = 3000000000, - Price = 1.5f, - Ratio = 2.25, - Active = true, - Name = "Alice" - }); - } - } - ``` - -3. **The error**: `no such table: primitive` - -4. **Explain the difference**: - - Missing the `public` access modifier in the declaration of the `Table` attribute. The expected syntax properly utilizes attributes defined in the library. - -5. **Root cause**: - - Documentation may lack clarity about access modifiers, especially when it comes to how they affect visibility in entities. - -6. **Recommendation**: - - Ensure C# documentation includes explicit examples where `public` is required in class and struct declarations to prevent access issues with tables. +#### Other Failures (4 Failures) ---- +#### 8. **t_014_elementary_columns** +- **Generated Code**: + ```csharp + [SpacetimeDB.Table(Name = "Primitive", Public = true)] + public partial struct Primitive + { + [SpacetimeDB.PrimaryKey] + public int Id; + public int Count; + ... + } + ``` + +- **Golden Example**: + ```csharp + [Table(Name = "Primitive")] + public partial struct Primitive + { + [PrimaryKey] public int Id; + public int Count; + ... + } + ``` + +- **Error**: Table not found during sql operations. + +- **Explanation**: The `Public` attribute's use was incorrect; it's not necessary in the struct definition. + +- **Root Cause**: Confusion over the purpose and necessity of attributes. + +- **Recommendation**: Update documentation to clarify attributes' roles in table definitions, removing unnecessary ones for struct exposure. + +--- + +#### 9. **t_016_sum_type_columns** +- **Generated Code**: + ```csharp + [SpacetimeDB.Table(Name = "Drawing", Public = true)] + public partial struct Drawing + { + [SpacetimeDB.PrimaryKey] + public int Id; + } + ``` + +- **Golden Example**: + ```csharp + [Table(Name = "Drawing")] + public partial struct Drawing + { + [PrimaryKey] public int Id; + } + ``` + +- **Error**: Table not found during sql operations. + +- **Explanation**: Similar to the previous failure, the `Public` attribute was misapplied. + +- **Root Cause**: Misalignment between understood attribute requirements and actual usage. + +- **Recommendation**: Further clarification of when and where to apply attributes in C# constructs related to SpacetimeDB. + +--- + +#### 10. **t_017_scheduled_columns** +- **Generated Code**: + ```csharp + [Table(Name = "TickTimer", Scheduled = nameof(Tick), ScheduledAt = nameof(ScheduledAt))] + public partial struct TickTimer + { + [PrimaryKey, AutoInc] + public ulong ScheduledId; + public ScheduleAt ScheduledAt; + } + ``` + +- **Golden Example**: + ```csharp + [Table(Name = "TickTimer", Scheduled = nameof(Tick), ScheduledAt = nameof(ScheduledAt))] + public partial struct TickTimer + { + [PrimaryKey, AutoInc] public ulong ScheduledId; + public ScheduleAt ScheduledAt; + } + ``` + +- **Error**: Table not found during sql operations. + +- **Explanation**: The field definitions and relationships were incorrectly configured. + +- **Root Cause**: Possible gaps in documentation regarding definitions of scheduled columns and expected real structures. + +- **Recommendation**: Revise documentation to ensure clear expectations about table configuration and proper struct setup. + +--- + +#### 11. **t_020_ecs** +- **Generated Code**: + ```csharp + [SpacetimeDB.Table(Name = "Entity", Public = true)] + public partial struct Entity { [SpacetimeDB.PrimaryKey] public int Id; } + ``` + +- **Golden Example**: + ```csharp + [Table(Name = "Entity")] + public partial struct Entity { [PrimaryKey] public int Id; } + ``` + +- **Error**: Errors related to missing tables. + +- **Explanation**: Public attributes were misused in creating struct definitions for the tables. + +- **Root Cause**: Attribute usage may be causing confusion in use cases. + +- **Recommendation**: Ensure documentation includes proper usage guidelines for attributes in defining entities. + +--- -By addressing the above gaps in documentation and ensuring that generated samples adhere to the expected outcomes, we can significantly reduce the number of failures in future benchmarks. +By addressing the aforementioned discrepancies and gaps in documentation, developers can improve their implementation of SpacetimeDB, leading to smoother integrations and reduced error rates during execution. diff --git a/docs/llms/docs-benchmark-comment.md b/docs/llms/docs-benchmark-comment.md index b26d4820585..37272389e0d 100644 --- a/docs/llms/docs-benchmark-comment.md +++ b/docs/llms/docs-benchmark-comment.md @@ -2,16 +2,16 @@ | Language | Mode | Category | Tests Passed | Task Pass % | |----------|------|----------|--------------|-------------| -| Rust | rustdoc_json | basics | 26/27 | 91.7% ⬆️ +8.3% | -| Rust | rustdoc_json | schema | 23/34 | 65.3% ⬆️ +10.0% | -| Rust | rustdoc_json | **total** | 49/61 | **79.7%** ⬆️ +9.1% | +| Rust | rustdoc_json | basics | 25/27 | 83.3% ⬆️ +9.0% | +| Rust | rustdoc_json | schema | 26/34 | 75.3% ⬆️ +10.0% | +| Rust | rustdoc_json | **total** | 51/61 | **79.7%** ⬆️ +9.5% | | Rust | docs | basics | 5/27 | 11.1% | -| Rust | docs | schema | 8/32 | 20.5% ⬆️ +8.0% | -| Rust | docs | **total** | 13/59 | **15.4%** ⬆️ +3.6% | +| Rust | docs | schema | 0/14 | 0.0% ⬇️ -20.5% | +| Rust | docs | **total** | 5/41 | **6.1%** ⬇️ -9.3% | | C# | docs | basics | 27/27 | 100.0% | | C# | docs | schema | 25/34 | 73.7% | | C# | docs | **total** | 52/61 | **88.0%** | _Compared against master branch baseline_ -Generated at: 2026-01-27T20:01:19.767Z +Generated at: 2026-01-23T20:21:59.670Z diff --git a/docs/llms/docs-benchmark-details.json b/docs/llms/docs-benchmark-details.json index 5d08c34e832..1a8a6449ec1 100644 --- a/docs/llms/docs-benchmark-details.json +++ b/docs/llms/docs-benchmark-details.json @@ -5,21 +5,21 @@ "modes": [ { "mode": "rustdoc_json", - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "models": [ { "name": "GPT-5", "route_api_model": "gpt-5", "tasks": { "t_000_empty_reducers": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_000_empty_reducers", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 1, "passed_tests": 1, - "llm_output": "use spacetimedb::ReducerContext;\n\n#[spacetimedb::reducer]\npub fn empty_reducer_no_args(_ctx: &ReducerContext) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_int(_ctx: &ReducerContext, count: i32) {\n let _ = count;\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_string(_ctx: &ReducerContext, name: String) {\n let _ = name;\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_two_args(_ctx: &ReducerContext, count: i32, name: String) {\n let _ = (count, name);\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_three_args(_ctx: &ReducerContext, active: bool, ratio: f32, label: String) {\n let _ = (active, ratio, label);\n}", + "llm_output": "use spacetimedb::ReducerContext;\n\n#[spacetimedb::reducer]\nfn empty_reducer_no_args(_ctx: &ReducerContext) {\n}\n\n#[spacetimedb::reducer]\nfn empty_reducer_with_int(_ctx: &ReducerContext, _count: i32) {\n}\n\n#[spacetimedb::reducer]\nfn empty_reducer_with_string(_ctx: &ReducerContext, _name: String) {\n}\n\n#[spacetimedb::reducer]\nfn empty_reducer_with_two_args(_ctx: &ReducerContext, _count: i32, _name: String) {\n}\n\n#[spacetimedb::reducer]\nfn empty_reducer_with_three_args(_ctx: &ReducerContext, _active: bool, _ratio: f32, _label: String) {\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-000-empty-reducers-golden", @@ -35,18 +35,18 @@ "llm_db": "basics-t-000-empty-reducers-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:50:33.923590167Z", - "finished_at": "2026-01-27T19:51:02.622615452Z" + "started_at": "2026-01-23T20:09:12.144740177Z", + "finished_at": "2026-01-23T20:09:46.065291337Z" }, "t_001_basic_tables": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_001_basic_tables", "lang": "rust", "golden_published": true, @@ -69,25 +69,25 @@ "llm_db": "basics-t-001-basic-tables-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:50:58.838771838Z", - "finished_at": "2026-01-27T19:51:33.707208916Z" + "started_at": "2026-01-23T20:09:14.464369753Z", + "finished_at": "2026-01-23T20:09:44.014749235Z" }, "t_002_scheduled_table": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_002_scheduled_table", "lang": "rust", "golden_published": false, "model_name": "GPT-5", "total_tests": 1, "passed_tests": 0, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, ScheduleAt};\n\n#[table(name = tick_timer, schedule(reducer = tick, column = scheduled_at))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[reducer(init)]\npub fn init(ctx: &ReducerContext) {\n if ctx.db.tick_timer().count() == 0 {\n ctx.db\n .tick_timer()\n .insert(TickTimer { scheduled_id: 0, scheduled_at: ScheduleAt::repeat_micros(50_000) });\n }\n}\n\n#[reducer]\npub fn tick(_ctx: &ReducerContext) {\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, ScheduleAt, Table};\n\n#[table(name = tick_timer, schedule(column = scheduled_at, reducer = tick))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[reducer]\npub fn tick(_ctx: &ReducerContext) {}\n\n#[reducer(init)]\npub fn init(ctx: &ReducerContext) {\n if ctx.db.tick_timer().count() == 0 {\n ctx.db.tick_timer().insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::repeat_micros(50_000),\n });\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-002-scheduled-table-golden", @@ -99,24 +99,24 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime publish failed (exit=1)\n--- stderr ---\n Updating crates.io index\n Locking 72 packages to latest compatible versions\n Adding generic-array v0.14.7 (available: v0.14.9)\n Adding spacetimedb v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-macro v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-sys v1.11.1 (available: v1.11.3)\n Adding spacetimedb-lib v1.11.1 (available: v1.11.3)\n Adding spacetimedb-primitives v1.11.1 (available: v1.11.3)\n Adding spacetimedb-sats v1.11.1 (available: v1.11.3)\n Compiling proc-macro2 v1.0.106\n Compiling quote v1.0.44\n Compiling unicode-ident v1.0.22\n Compiling typenum v1.19.0\n Compiling version_check v0.9.5\n Compiling autocfg v1.5.0\n Compiling serde_core v1.0.228\n Compiling heck v0.5.0\n Compiling cfg-if v1.0.4\n Compiling shlex v1.3.0\n Compiling either v1.15.0\n Compiling serde v1.0.228\n Compiling find-msvc-tools v0.1.8\n Compiling zerocopy v0.8.34\n Compiling thiserror v1.0.69\n Compiling bitflags v2.10.0\n Compiling nohash-hasher v0.2.0\n Compiling anyhow v1.0.100\n Compiling keccak v0.1.5\n Compiling bytes v1.11.0\n Compiling humantime v2.3.0\n Compiling convert_case v0.4.0\n Compiling zmij v1.0.17\n Compiling heck v0.4.1\n Compiling arrayvec v0.7.6\n Compiling second-stack v0.3.5\n Compiling serde_json v1.0.149\n Compiling hex v0.4.3\n Compiling bytemuck v1.24.0\n Compiling getrandom v0.2.17\n Compiling itoa v1.0.17\n Compiling smallvec v1.15.1\n Compiling arrayref v0.3.9\n Compiling itertools v0.12.1\n Compiling spacetimedb-lib v1.11.1\n Compiling constant_time_eq v0.4.2\n Compiling log v0.4.29\n Compiling memchr v2.7.6\n Compiling rand_core v0.6.4\n Compiling cc v1.2.54\n Compiling scoped-tls v1.0.1\n Compiling generic-array v0.14.7\n Compiling num-traits v0.2.19\n Compiling syn v2.0.114\n Compiling http v1.4.0\n Compiling approx v0.3.2\n Compiling chrono v0.4.43\n Compiling decorum v0.3.1\n Compiling blake3 v1.8.3\n Compiling crypto-common v0.1.7\n Compiling block-buffer v0.10.4\n Compiling digest v0.10.7\n Compiling sha3 v0.10.8\n Compiling ppv-lite86 v0.2.21\n Compiling ethnum v1.5.2\n Compiling rand_chacha v0.3.1\n Compiling rand v0.8.5\n Compiling enum-as-inner v0.6.1\n Compiling thiserror-impl v1.0.69\n Compiling derive_more v0.99.20\n Compiling spacetimedb-primitives v1.11.1\n Compiling spacetimedb-bindings-macro v1.11.1\n Compiling spacetimedb-bindings-sys v1.11.1\n Compiling spacetimedb-sats v1.11.1\n Compiling spacetimedb v1.11.1\n Compiling spacetime-module v0.1.0 (/__w/SpacetimeDB/SpacetimeDB/target/llm-runs/basics/t_002_scheduled_table/rust/server/gpt-5/llm)\nerror: expected one of: `public`, `private`, `name`, `index`, `scheduled`\n --> src/lib.rs:4:28\n |\n4 | #[table(name = tick_timer, schedule(reducer = tick, column = scheduled_at))]\n | ^^^^^^^^\n\nerror[E0422]: cannot find struct, variant or union type `TickTimer` in this scope\n --> src/lib.rs:17:21\n |\n17 | .insert(TickTimer { scheduled_id: 0, scheduled_at: ScheduleAt::repeat_micros(50_000) });\n | ^^^^^^^^^ not found in this scope\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:14:15\n |\n14 | if ctx.db.tick_timer().count() == 0 {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:16:14\n |\n15 | / ctx.db\n16 | | .tick_timer()\n | | -^^^^^^^^^^ method not found in `Local`\n | |_____________|\n |\n\nerror[E0599]: no variant or associated item named `repeat_micros` found for enum `ScheduleAt` in the current scope\n --> src/lib.rs:17:76\n |\n17 | .insert(TickTimer { scheduled_id: 0, scheduled_at: ScheduleAt::repeat_micros(50_000) });\n | ^^^^^^^^^^^^^ variant or associated item not found in `ScheduleAt`\n\nSome errors have detailed explanations: E0422, E0599.\nFor more information about an error, try `rustc --explain E0422`.\nerror: could not compile `spacetime-module` (lib) due to 5 previous errors\nError: command [\"cargo\", \"build\", \"--config=net.git-fetch-with-cli=true\", \"--target=wasm32-unknown-unknown\", \"--release\", \"--message-format=json-render-diagnostics\"] exited with code 101\n\n--- stdout ---\n", + "error": "spacetime publish failed (exit=1)\n--- stderr ---\n Updating crates.io index\n Locking 72 packages to latest compatible versions\n Adding generic-array v0.14.7 (available: v0.14.9)\n Adding spacetimedb v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-macro v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-sys v1.11.1 (available: v1.11.3)\n Adding spacetimedb-lib v1.11.1 (available: v1.11.3)\n Adding spacetimedb-primitives v1.11.1 (available: v1.11.3)\n Adding spacetimedb-sats v1.11.1 (available: v1.11.3)\n Compiling proc-macro2 v1.0.106\n Compiling quote v1.0.44\n Compiling unicode-ident v1.0.22\n Compiling typenum v1.19.0\n Compiling version_check v0.9.5\n Compiling autocfg v1.5.0\n Compiling serde_core v1.0.228\n Compiling heck v0.5.0\n Compiling cfg-if v1.0.4\n Compiling serde v1.0.228\n Compiling zerocopy v0.8.33\n Compiling either v1.15.0\n Compiling shlex v1.3.0\n Compiling find-msvc-tools v0.1.8\n Compiling bitflags v2.10.0\n Compiling nohash-hasher v0.2.0\n Compiling anyhow v1.0.100\n Compiling thiserror v1.0.69\n Compiling zmij v1.0.16\n Compiling keccak v0.1.5\n Compiling heck v0.4.1\n Compiling arrayvec v0.7.6\n Compiling bytes v1.11.0\n Compiling humantime v2.3.0\n Compiling convert_case v0.4.0\n Compiling itoa v1.0.17\n Compiling second-stack v0.3.5\n Compiling serde_json v1.0.149\n Compiling constant_time_eq v0.4.2\n Compiling getrandom v0.2.17\n Compiling smallvec v1.15.1\n Compiling hex v0.4.3\n Compiling cc v1.2.54\n Compiling bytemuck v1.24.0\n Compiling arrayref v0.3.9\n Compiling spacetimedb-lib v1.11.1\n Compiling itertools v0.12.1\n Compiling memchr v2.7.6\n Compiling log v0.4.29\n Compiling rand_core v0.6.4\n Compiling scoped-tls v1.0.1\n Compiling generic-array v0.14.7\n Compiling num-traits v0.2.19\n Compiling http v1.4.0\n Compiling syn v2.0.114\n Compiling approx v0.3.2\n Compiling chrono v0.4.43\n Compiling blake3 v1.8.3\n Compiling decorum v0.3.1\n Compiling block-buffer v0.10.4\n Compiling crypto-common v0.1.7\n Compiling digest v0.10.7\n Compiling sha3 v0.10.8\n Compiling ppv-lite86 v0.2.21\n Compiling rand_chacha v0.3.1\n Compiling rand v0.8.5\n Compiling ethnum v1.5.2\n Compiling enum-as-inner v0.6.1\n Compiling thiserror-impl v1.0.69\n Compiling derive_more v0.99.20\n Compiling spacetimedb-primitives v1.11.1\n Compiling spacetimedb-bindings-sys v1.11.1\n Compiling spacetimedb-bindings-macro v1.11.1\n Compiling spacetimedb-sats v1.11.1\n Compiling spacetimedb v1.11.1\n Compiling spacetime-module v0.1.0 (/__w/SpacetimeDB/SpacetimeDB/target/llm-runs/basics/t_002_scheduled_table/rust/server/gpt-5/llm)\nerror: expected one of: `public`, `private`, `name`, `index`, `scheduled`\n --> src/lib.rs:4:28\n |\n4 | #[table(name = tick_timer, schedule(column = scheduled_at, reducer = tick))]\n | ^^^^^^^^\n\nerror[E0422]: cannot find struct, variant or union type `TickTimer` in this scope\n --> src/lib.rs:18:36\n |\n18 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^ not found in this scope\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:17:15\n |\n17 | if ctx.db.tick_timer().count() == 0 {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:18:16\n |\n18 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no variant or associated item named `repeat_micros` found for enum `ScheduleAt` in the current scope\n --> src/lib.rs:20:39\n |\n20 | scheduled_at: ScheduleAt::repeat_micros(50_000),\n | ^^^^^^^^^^^^^ variant or associated item not found in `ScheduleAt`\n\nSome errors have detailed explanations: E0422, E0599.\nFor more information about an error, try `rustc --explain E0422`.\nerror: could not compile `spacetime-module` (lib) due to 5 previous errors\nError: command [\"cargo\", \"build\", \"--config=net.git-fetch-with-cli=true\", \"--target=wasm32-unknown-unknown\", \"--release\", \"--message-format=json-render-diagnostics\"] exited with code 101\n\n--- stdout ---\n", "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:51:00.465423417Z", - "finished_at": "2026-01-27T19:51:47.339587032Z" + "started_at": "2026-01-23T20:09:35.992436277Z", + "finished_at": "2026-01-23T20:10:39.770857477Z" }, "t_003_struct_in_table": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_003_struct_in_table", "lang": "rust", - "golden_published": true, + "golden_published": false, "model_name": "GPT-5", "total_tests": 1, - "passed_tests": 1, - "llm_output": "use spacetimedb::SpacetimeType;\n\n#[derive(SpacetimeType)]\npub struct Position {\n x: i32,\n y: i32,\n}\n\n#[spacetimedb::table(name = entity)]\npub struct Entity {\n #[primary_key]\n id: i32,\n pos: Position,\n}", + "passed_tests": 0, + "llm_output": "use spacetimedb::ReducerContext;\n\n#[derive(spacetimedb::SpacetimeType)]\npub struct Position {\n x: i32,\n y: i32,\n}\n\n#[spacetimedb::table(name = entity)]\npub struct Entity {\n #[primary_key]\n id: i32,\n pos: Position,\n}\n\n#[spacetimedb::reducer]\npub fn add_entity(ctx: &ReducerContext, id: i32, x: i32, y: i32) {\n let pos = Position { x, y };\n ctx.db.entity().insert(Entity { id, pos });\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-003-struct-in-table-golden", @@ -124,26 +124,21 @@ "work_dir_golden": "target/llm-runs/basics/t_003_struct_in_table/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_003_struct_in_table/rust/server/gpt-5/llm", "scorer_details": { - "schema_parity": { - "pass": true, - "partial": 1.0, + "publish_error": { + "pass": false, + "partial": 0.0, "notes": { - "golden_db": "basics-t-003-struct-in-table-golden", - "llm_db": "basics-t-003-struct-in-table-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:33615", - "tables_diff": null, - "tables_equal": true + "error": "spacetime publish failed (exit=1)\n--- stderr ---\n Updating crates.io index\n Locking 72 packages to latest compatible versions\n Adding generic-array v0.14.7 (available: v0.14.9)\n Adding spacetimedb v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-macro v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-sys v1.11.1 (available: v1.11.3)\n Adding spacetimedb-lib v1.11.1 (available: v1.11.3)\n Adding spacetimedb-primitives v1.11.1 (available: v1.11.3)\n Adding spacetimedb-sats v1.11.1 (available: v1.11.3)\n Compiling proc-macro2 v1.0.106\n Compiling unicode-ident v1.0.22\n Compiling quote v1.0.44\n Compiling version_check v0.9.5\n Compiling typenum v1.19.0\n Compiling autocfg v1.5.0\n Compiling serde_core v1.0.228\n Compiling heck v0.5.0\n Compiling cfg-if v1.0.4\n Compiling zerocopy v0.8.33\n Compiling serde v1.0.228\n Compiling shlex v1.3.0\n Compiling either v1.15.0\n Compiling find-msvc-tools v0.1.8\n Compiling anyhow v1.0.100\n Compiling nohash-hasher v0.2.0\n Compiling bitflags v2.10.0\n Compiling thiserror v1.0.69\n Compiling bytes v1.11.0\n Compiling heck v0.4.1\n Compiling humantime v2.3.0\n Compiling zmij v1.0.16\n Compiling keccak v0.1.5\n Compiling arrayvec v0.7.6\n Compiling convert_case v0.4.0\n Compiling hex v0.4.3\n Compiling bytemuck v1.24.0\n Compiling second-stack v0.3.5\n Compiling arrayref v0.3.9\n Compiling getrandom v0.2.17\n Compiling spacetimedb-lib v1.11.1\n Compiling itoa v1.0.17\n Compiling itertools v0.12.1\n Compiling constant_time_eq v0.4.2\n Compiling smallvec v1.15.1\n Compiling serde_json v1.0.149\n Compiling log v0.4.29\n Compiling memchr v2.7.6\n Compiling rand_core v0.6.4\n Compiling scoped-tls v1.0.1\n Compiling cc v1.2.54\n Compiling generic-array v0.14.7\n Compiling num-traits v0.2.19\n Compiling http v1.4.0\n Compiling syn v2.0.114\n Compiling blake3 v1.8.3\n Compiling approx v0.3.2\n Compiling chrono v0.4.43\n Compiling decorum v0.3.1\n Compiling block-buffer v0.10.4\n Compiling crypto-common v0.1.7\n Compiling digest v0.10.7\n Compiling sha3 v0.10.8\n Compiling ppv-lite86 v0.2.21\n Compiling rand_chacha v0.3.1\n Compiling rand v0.8.5\n Compiling ethnum v1.5.2\n Compiling enum-as-inner v0.6.1\n Compiling thiserror-impl v1.0.69\n Compiling derive_more v0.99.20\n Compiling spacetimedb-primitives v1.11.1\n Compiling spacetimedb-bindings-sys v1.11.1\n Compiling spacetimedb-bindings-macro v1.11.1\n Compiling spacetimedb-sats v1.11.1\n Compiling spacetimedb v1.11.1\n Compiling spacetime-module v0.1.0 (/__w/SpacetimeDB/SpacetimeDB/target/llm-runs/basics/t_003_struct_in_table/rust/server/gpt-5/llm)\nerror[E0599]: no method named `insert` found for reference `&entity__TableHandle` in the current scope\n --> src/lib.rs:20:21\n |\n20 | ctx.db.entity().insert(Entity { id, pos });\n | ^^^^^^\n |\n = help: items from traits can only be used if the trait is in scope\nhelp: trait `Table` which provides `insert` is implemented but not in scope; perhaps you want to import it\n |\n 2 + use spacetimedb::Table;\n |\nhelp: there is a method `try_insert` with a similar name\n |\n20 | ctx.db.entity().try_insert(Entity { id, pos });\n | ++++\n\nFor more information about this error, try `rustc --explain E0599`.\nerror: could not compile `spacetime-module` (lib) due to 1 previous error\nError: command [\"cargo\", \"build\", \"--config=net.git-fetch-with-cli=true\", \"--target=wasm32-unknown-unknown\", \"--release\", \"--message-format=json-render-diagnostics\"] exited with code 101\n\n--- stdout ---\n", + "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:50:43.120116357Z", - "finished_at": "2026-01-27T19:51:34.789700080Z" + "started_at": "2026-01-23T20:09:14.464130029Z", + "finished_at": "2026-01-23T20:09:54.314351498Z" }, "t_004_insert": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_004_insert", "lang": "rust", "golden_published": true, @@ -158,19 +153,6 @@ "work_dir_golden": "target/llm-runs/basics/t_004_insert/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_004_insert/rust/server/gpt-5/llm", "scorer_details": { - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "basics-t-004-insert-golden", - "llm_db": "basics-t-004-insert-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:33615", - "tables_diff": null, - "tables_equal": true - } - }, "data_parity_insert_user": { "pass": true, "partial": 1.0, @@ -187,16 +169,29 @@ "llm_out": "id | name | age | active ----+---------+-----+-------- 1 | \"Alice\" | 30 | true", "query": "SELECT id, name, age, active FROM user WHERE id=1", "reducer": "insert_user", - "server": "http://127.0.0.1:33615" + "server": "http://127.0.0.1:41115" + } + }, + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "basics-t-004-insert-golden", + "llm_db": "basics-t-004-insert-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41115", + "tables_diff": null, + "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:51:00.012104606Z", - "finished_at": "2026-01-27T19:51:27.169795394Z" + "started_at": "2026-01-23T20:09:14.983974693Z", + "finished_at": "2026-01-23T20:09:35.992396086Z" }, "t_005_update": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_005_update", "lang": "rust", "golden_published": true, @@ -211,17 +206,11 @@ "work_dir_golden": "target/llm-runs/basics/t_005_update/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_005_update/rust/server/gpt-5/llm", "scorer_details": { - "schema_parity": { + "seed_users_row": { "pass": true, "partial": 1.0, "notes": { - "golden_db": "basics-t-005-update-golden", - "llm_db": "basics-t-005-update-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:33615", - "tables_diff": null, - "tables_equal": true + "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" } }, "data_parity_update_user": { @@ -240,30 +229,36 @@ "llm_out": "id | name | age | active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", "query": "SELECT id, name, age, active FROM user WHERE id=1", "reducer": "update_user", - "server": "http://127.0.0.1:33615" + "server": "http://127.0.0.1:41115" } }, - "seed_users_row": { + "schema_parity": { "pass": true, "partial": 1.0, "notes": { - "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" + "golden_db": "basics-t-005-update-golden", + "llm_db": "basics-t-005-update-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41115", + "tables_diff": null, + "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:50:22.268945837Z", - "finished_at": "2026-01-27T19:51:01.660325703Z" + "started_at": "2026-01-23T20:08:57.792213429Z", + "finished_at": "2026-01-23T20:09:53.091667873Z" }, "t_006_delete": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_006_delete", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[reducer]\npub fn delete_user(ctx: &ReducerContext, id: i32) {\n ctx.db.user().id().delete(&id);\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[reducer]\npub fn delete_user(ctx: &ReducerContext, id: i32) {\n ctx.db.user().id().delete(&id);\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-006-delete-golden", @@ -271,11 +266,13 @@ "work_dir_golden": "target/llm-runs/basics/t_006_delete/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_006_delete/rust/server/gpt-5/llm", "scorer_details": { - "seed_users_row": { + "delete_user_count_zero": { "pass": true, "partial": 1.0, "notes": { - "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" + "actual": 0, + "expected": 0, + "sql": "SELECT COUNT(*) AS n FROM user WHERE id=1" } }, "schema_parity": { @@ -286,34 +283,32 @@ "llm_db": "basics-t-006-delete-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } }, - "delete_user_count_zero": { + "seed_users_row": { "pass": true, "partial": 1.0, "notes": { - "actual": 0, - "expected": 0, - "sql": "SELECT COUNT(*) AS n FROM user WHERE id=1" + "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:50:18.814239252Z", - "finished_at": "2026-01-27T19:51:00.465380864Z" + "started_at": "2026-01-23T20:08:35.084889228Z", + "finished_at": "2026-01-23T20:09:14.643664761Z" }, "t_007_crud": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_007_crud", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 4, "passed_tests": 4, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[reducer]\npub fn crud(ctx: &ReducerContext) {\n let users = ctx.db.user();\n\n // insert (id=1, name=\"Alice\", age=30, active=true)\n users.insert(User {\n id: 1,\n name: \"Alice\".to_string(),\n age: 30,\n active: true,\n });\n\n // insert (id=2, name=\"Bob\", age=22, active=false)\n users.insert(User {\n id: 2,\n name: \"Bob\".to_string(),\n age: 22,\n active: false,\n });\n\n // update (id=1, name=\"Alice2\", age=31, active=false)\n users.id().update(User {\n id: 1,\n name: \"Alice2\".to_string(),\n age: 31,\n active: false,\n });\n\n // delete id=2\n users.id().delete(&2);\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, UniqueColumn};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[reducer]\npub fn crud(ctx: &ReducerContext) {\n let users = ctx.db.user();\n\n let mut u1 = users.insert(User {\n id: 1,\n name: \"Alice\".to_string(),\n age: 30,\n active: true,\n });\n\n let _u2 = users.insert(User {\n id: 2,\n name: \"Bob\".to_string(),\n age: 22,\n active: false,\n });\n\n u1.name = \"Alice2\".to_string();\n u1.age = 31;\n u1.active = false;\n let _u1_updated = users.id().update(u1);\n\n users.id().delete(&2);\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-007-crud-golden", @@ -330,17 +325,18 @@ "sql": "SELECT COUNT(*) AS n FROM user WHERE id=2" } }, - "schema_parity": { + "crud_row_id1_parity": { "pass": true, "partial": 1.0, "notes": { + "args": [], "golden_db": "basics-t-007-crud-golden", + "golden_out": "id | name | age | active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", "llm_db": "basics-t-007-crud-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:33615", - "tables_diff": null, - "tables_equal": true + "llm_out": "id | name | age | active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", + "query": "SELECT id, name, age, active FROM user WHERE id=1", + "reducer": "crud", + "server": "http://127.0.0.1:41115" } }, "crud_total_count_one": { @@ -352,34 +348,33 @@ "sql": "SELECT COUNT(*) AS n FROM user" } }, - "crud_row_id1_parity": { + "schema_parity": { "pass": true, "partial": 1.0, "notes": { - "args": [], "golden_db": "basics-t-007-crud-golden", - "golden_out": "id | name | age | active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", "llm_db": "basics-t-007-crud-gpt-5-llm", - "llm_out": "id | name | age | active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", - "query": "SELECT id, name, age, active FROM user WHERE id=1", - "reducer": "crud", - "server": "http://127.0.0.1:33615" + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41115", + "tables_diff": null, + "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:50:19.572189963Z", - "finished_at": "2026-01-27T19:51:00.012056746Z" + "started_at": "2026-01-23T20:08:56.057273916Z", + "finished_at": "2026-01-23T20:09:48.569368820Z" }, "t_008_index_lookup": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_008_index_lookup", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n name: String,\n}\n\n#[reducer]\npub fn lookup_user_name(ctx: &ReducerContext, id: i32) {\n if let Some(user) = ctx.db.user().id().find(id) {\n let _ = ctx.db.result().try_insert(ResultRow {\n id: user.id,\n name: user.name.clone(),\n });\n }\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n name: String,\n}\n\n#[reducer]\npub fn lookup_user_name(ctx: &ReducerContext, id: i32) {\n if let Some(u) = ctx.db.user().id().find(id) {\n let User { id, name, .. } = u;\n ctx.db.result().id().delete(&id);\n ctx.db.result().insert(ResultRow { id, name });\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-008-index-lookup-golden", @@ -394,19 +389,6 @@ "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" } }, - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "basics-t-008-index-lookup-golden", - "llm_db": "basics-t-008-index-lookup-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:33615", - "tables_diff": null, - "tables_equal": true - } - }, "index_lookup_projection_parity": { "pass": true, "partial": 1.0, @@ -420,23 +402,36 @@ "llm_out": "id | name ----+--------- 1 | \"Alice\"", "query": "SELECT id, name FROM result WHERE id=1", "reducer": "lookup_user_name", - "server": "http://127.0.0.1:33615" + "server": "http://127.0.0.1:41115" + } + }, + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "basics-t-008-index-lookup-golden", + "llm_db": "basics-t-008-index-lookup-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41115", + "tables_diff": null, + "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:50:59.032238062Z", - "finished_at": "2026-01-27T19:51:34.520084103Z" + "started_at": "2026-01-23T20:09:14.643699808Z", + "finished_at": "2026-01-23T20:09:52.566672855Z" }, "t_009_init": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_009_init", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 4, "passed_tests": 4, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[spacetimedb::reducer(init)]\npub fn init(ctx: &ReducerContext) {\n ctx.db.user().insert(User {\n id: 1,\n name: \"Alice\".to_string(),\n age: 30,\n active: true,\n });\n ctx.db.user().insert(User {\n id: 2,\n name: \"Bob\".to_string(),\n age: 22,\n active: false,\n });\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[reducer(init)]\npub fn init(ctx: &ReducerContext) {\n let user = ctx.db.user();\n user.insert(User { id: 1, name: \"Alice\".to_string(), age: 30, active: true });\n user.insert(User { id: 2, name: \"Bob\".to_string(), age: 22, active: false });\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-009-init-golden", @@ -470,7 +465,7 @@ "llm_db": "basics-t-009-init-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } @@ -486,11 +481,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:50:21.549783Z", - "finished_at": "2026-01-27T19:50:59.032183836Z" + "started_at": "2026-01-23T20:08:57.046090650Z", + "finished_at": "2026-01-23T20:09:23.724177316Z" }, "t_010_connect": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_010_connect", "lang": "rust", "golden_published": true, @@ -513,25 +508,25 @@ "llm_db": "basics-t-010-connect-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:50:19.565630879Z", - "finished_at": "2026-01-27T19:50:43.120012892Z" + "started_at": "2026-01-23T20:08:35.620982701Z", + "finished_at": "2026-01-23T20:09:12.144710803Z" }, "t_011_helper_function": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_011_helper_function", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n sum: i32,\n}\n\nfn add(a: i32, b: i32) -> i32 {\n a + b\n}\n\n#[reducer]\npub fn compute_sum(ctx: &ReducerContext, id: i32, a: i32, b: i32) {\n let sum = add(a, b);\n ctx.db.result().insert(ResultRow { id, sum });\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n sum: i32,\n}\n\nfn add(a: i32, b: i32) -> i32 {\n a + b\n}\n\n#[reducer]\npub fn compute_sum(ctx: &ReducerContext, id: i32, a: i32, b: i32) {\n ctx.db.result().insert(ResultRow { id, sum: add(a, b) });\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-011-helper-function-golden", @@ -539,6 +534,15 @@ "work_dir_golden": "target/llm-runs/basics/t_011_helper_function/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_011_helper_function/rust/server/gpt-5/llm", "scorer_details": { + "helper_func_sum_abs": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM result WHERE id=1 AND sum=5" + } + }, "helper_func_sum_parity": { "pass": true, "partial": 1.0, @@ -554,16 +558,7 @@ "llm_out": "id | sum ----+----- 1 | 5", "query": "SELECT id, sum FROM result WHERE id=1", "reducer": "compute_sum", - "server": "http://127.0.0.1:33615" - } - }, - "helper_func_sum_abs": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM result WHERE id=1 AND sum=5" + "server": "http://127.0.0.1:41115" } }, "schema_parity": { @@ -574,25 +569,25 @@ "llm_db": "basics-t-011-helper-function-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:51:00.227420335Z", - "finished_at": "2026-01-27T19:51:29.538171947Z" + "started_at": "2026-01-23T20:09:23.724208808Z", + "finished_at": "2026-01-23T20:09:51.292524674Z" }, "t_012_spacetime_product_type": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_012_spacetime_product_type", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\npub struct Score {\n left: i32,\n right: i32,\n}\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n value: Score,\n}\n\n#[reducer]\nfn set_score(ctx: &ReducerContext, id: i32, left: i32, right: i32) {\n ctx.db.result().insert(ResultRow {\n id,\n value: Score { left, right },\n });\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\npub struct Score {\n left: i32,\n right: i32,\n}\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n value: Score,\n}\n\n#[reducer]\npub fn set_score(ctx: &ReducerContext, id: i32, left: i32, right: i32) {\n ctx.db.result().insert(ResultRow {\n id,\n value: Score { left, right },\n });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-012-spacetime-product-type-golden", @@ -617,7 +612,7 @@ "llm_db": "schema-t-012-spacetime-product-type-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } @@ -637,23 +632,23 @@ "llm_out": "id | value ----+----------------------- 1 | (left = 2, right = 3)", "query": "SELECT id, value FROM result WHERE id=1", "reducer": "set_score", - "server": "http://127.0.0.1:33615" + "server": "http://127.0.0.1:41115" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:50:17.029809591Z", - "finished_at": "2026-01-27T19:50:58.838714798Z" + "started_at": "2026-01-23T20:08:32.450266496Z", + "finished_at": "2026-01-23T20:09:14.310539584Z" }, "t_013_spacetime_sum_type": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_013_spacetime_sum_type", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, - "passed_tests": 2, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\npub struct Rect {\n width: i32,\n height: i32,\n}\n\n#[derive(SpacetimeType)]\npub enum Shape {\n Circle(i32),\n Rectangle(Rect),\n}\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n value: Shape,\n}\n\n#[reducer]\npub fn set_circle(ctx: &ReducerContext, id: i32, radius: i32) {\n ctx.db.result().insert(ResultRow {\n id,\n value: Shape::Circle(radius),\n });\n}", + "passed_tests": 3, + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\nstruct Rect {\n width: i32,\n height: i32,\n}\n\n#[derive(SpacetimeType)]\nenum Shape {\n Circle(i32),\n Rectangle(Rect),\n}\n\n#[table(name = result)]\nstruct ResultRow {\n #[primary_key]\n id: i32,\n value: Shape,\n}\n\n#[reducer]\nfn set_circle(ctx: &ReducerContext, id: i32, radius: i32) {\n ctx.db.result().insert(ResultRow { id, value: Shape::Circle(radius) });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-013-spacetime-sum-type-golden", @@ -661,12 +656,13 @@ "work_dir_golden": "target/llm-runs/schema/t_013_spacetime_sum_type/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_013_spacetime_sum_type/rust/server/gpt-5/llm", "scorer_details": { - "sum_type_row_parity": { - "pass": false, - "partial": 0.0, + "sum_type_row_count": { + "pass": true, + "partial": 1.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `result`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:33615/v1/database/c200ef5026b116b67d90edbd0acaca12a273f2a7e6e888cc7265a5d4a4fe7173/sql)\n", - "phase": "sql_golden" + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM result WHERE id=1" } }, "schema_parity": { @@ -677,27 +673,35 @@ "llm_db": "schema-t-013-spacetime-sum-type-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } }, - "sum_type_row_count": { - "pass": true, - "partial": 1.0, + "sum_type_row_parity": { + "pass": false, + "partial": 0.0, "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM result WHERE id=1" + "args": [ + 1, + 10 + ], + "golden_db": "schema-t-013-spacetime-sum-type-golden", + "golden_out": "id | value ----+--------------- 1 | (Circle = 10)", + "llm_db": "schema-t-013-spacetime-sum-type-gpt-5-llm", + "llm_out": "id | value ----+--------------- 1 | (Circle = 10)", + "query": "SELECT id, value FROM result WHERE id=1", + "reducer": "set_circle", + "server": "http://127.0.0.1:41115" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:49:28.665478058Z", - "finished_at": "2026-01-27T19:50:21.549671530Z" + "started_at": "2026-01-23T20:07:57.743148689Z", + "finished_at": "2026-01-23T20:08:32.450224286Z" }, "t_014_elementary_columns": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_014_elementary_columns", "lang": "rust", "golden_published": true, @@ -712,31 +716,31 @@ "work_dir_golden": "target/llm-runs/schema/t_014_elementary_columns/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_014_elementary_columns/rust/server/gpt-5/llm", "scorer_details": { - "elementary_columns_row_parity": { + "schema_parity": { "pass": true, "partial": 1.0, "notes": { - "args": [], "golden_db": "schema-t-014-elementary-columns-golden", - "golden_out": "id | count | total | price | ratio | active | name ----+-------+------------+-------+-------+--------+--------- 1 | 2 | 3000000000 | 1.5 | 2.25 | true | \"Alice\"", "llm_db": "schema-t-014-elementary-columns-gpt-5-llm", - "llm_out": "id | count | total | price | ratio | active | name ----+-------+------------+-------+-------+--------+--------- 1 | 2 | 3000000000 | 1.5 | 2.25 | true | \"Alice\"", - "query": "SELECT id, count, total, price, ratio, active, name FROM primitive WHERE id=1", - "reducer": "seed", - "server": "http://127.0.0.1:33615" + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41115", + "tables_diff": null, + "tables_equal": true } }, - "schema_parity": { + "elementary_columns_row_parity": { "pass": true, "partial": 1.0, "notes": { + "args": [], "golden_db": "schema-t-014-elementary-columns-golden", + "golden_out": "id | count | total | price | ratio | active | name ----+-------+------------+-------+-------+--------+--------- 1 | 2 | 3000000000 | 1.5 | 2.25 | true | \"Alice\"", "llm_db": "schema-t-014-elementary-columns-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:33615", - "tables_diff": null, - "tables_equal": true + "llm_out": "id | count | total | price | ratio | active | name ----+-------+------------+-------+-------+--------+--------- 1 | 2 | 3000000000 | 1.5 | 2.25 | true | \"Alice\"", + "query": "SELECT id, count, total, price, ratio, active, name FROM primitive WHERE id=1", + "reducer": "seed", + "server": "http://127.0.0.1:41115" } }, "elementary_columns_row_count": { @@ -750,18 +754,18 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:50:12.818589409Z", - "finished_at": "2026-01-27T19:51:00.227383147Z" + "started_at": "2026-01-23T20:08:30.379293605Z", + "finished_at": "2026-01-23T20:09:14.464089675Z" }, "t_015_product_type_columns": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_015_product_type_columns", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, - "passed_tests": 2, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType, Clone)]\nstruct Address {\n street: String,\n zip: i32,\n}\n\n#[derive(SpacetimeType, Clone)]\nstruct Position {\n x: i32,\n y: i32,\n}\n\n#[table(name = profile)]\nstruct Profile {\n #[primary_key]\n id: i32,\n home: Address,\n work: Address,\n pos: Position,\n}\n\n#[reducer]\nfn seed(ctx: &ReducerContext) {\n let tbl = ctx.db.profile();\n if tbl.count() == 0 {\n let home = Address { street: \"1 Main\".to_string(), zip: 11111 };\n let work = Address { street: \"2 Broad\".to_string(), zip: 22222 };\n let pos = Position { x: 7, y: 9 };\n tbl.insert(Profile { id: 1, home, work, pos });\n }\n}", + "passed_tests": 3, + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\nstruct Address {\n street: String,\n zip: i32,\n}\n\n#[derive(SpacetimeType)]\nstruct Position {\n x: i32,\n y: i32,\n}\n\n#[table(name = profile)]\nstruct Profile {\n #[primary_key]\n id: i32,\n home: Address,\n work: Address,\n pos: Position,\n}\n\n#[reducer]\nfn seed(ctx: &ReducerContext) {\n let home = Address { street: \"1 Main\".to_string(), zip: 11111 };\n let work = Address { street: \"2 Broad\".to_string(), zip: 22222 };\n let pos = Position { x: 7, y: 9 };\n match ctx.db.profile().id().find(1) {\n Some(mut row) => {\n row.home = home;\n row.work = work;\n row.pos = pos;\n ctx.db.profile().id().update(row);\n }\n None => {\n ctx.db.profile().insert(Profile { id: 1, home, work, pos });\n }\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-015-product-type-columns-golden", @@ -769,21 +773,18 @@ "work_dir_golden": "target/llm-runs/schema/t_015_product_type_columns/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_015_product_type_columns/rust/server/gpt-5/llm", "scorer_details": { - "product_type_columns_row_count": { + "product_type_columns_row_parity": { "pass": true, "partial": 1.0, "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM profile WHERE id=1" - } - }, - "product_type_columns_row_parity": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `profile`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:33615/v1/database/c200171a9841d8ed2a9c762ac4e081fe93ed52fe5c9e32ae9bbd874bb7e1a8b5/sql)\n", - "phase": "sql_golden" + "args": [], + "golden_db": "schema-t-015-product-type-columns-golden", + "golden_out": "id | home | work | pos ----+----------------------------------+-----------------------------------+---------------- 1 | (street = \"1 Main\", zip = 11111) | (street = \"2 Broad\", zip = 22222) | (x = 7, y = 9)", + "llm_db": "schema-t-015-product-type-columns-gpt-5-llm", + "llm_out": "id | home | work | pos ----+----------------------------------+-----------------------------------+---------------- 1 | (street = \"1 Main\", zip = 11111) | (street = \"2 Broad\", zip = 22222) | (x = 7, y = 9)", + "query": "SELECT id, home, work, pos FROM profile WHERE id=1", + "reducer": "seed", + "server": "http://127.0.0.1:41115" } }, "schema_parity": { @@ -794,25 +795,34 @@ "llm_db": "schema-t-015-product-type-columns-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } + }, + "product_type_columns_row_count": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM profile WHERE id=1" + } } }, "vendor": "openai", - "started_at": "2026-01-27T19:49:28.666090278Z", - "finished_at": "2026-01-27T19:50:19.565536981Z" + "started_at": "2026-01-23T20:07:57.743649083Z", + "finished_at": "2026-01-23T20:08:57.046048716Z" }, "t_016_sum_type_columns": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_016_sum_type_columns", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 1, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\npub struct Rect {\n width: i32,\n height: i32,\n}\n\n#[derive(SpacetimeType)]\npub enum Shape {\n Circle(i32),\n Rectangle(Rect),\n}\n\n#[table(name = drawing)]\npub struct Drawing {\n #[primary_key]\n id: i32,\n a: Shape,\n b: Shape,\n}\n\n#[reducer]\npub fn seed(ctx: &ReducerContext) {\n if ctx.db.drawing().id().find(1i32).is_none() {\n ctx.db.drawing().insert(Drawing {\n id: 1,\n a: Shape::Circle(10),\n b: Shape::Rectangle(Rect { width: 4, height: 6 }),\n });\n }\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[derive(spacetimedb::SpacetimeType)]\npub struct Rect {\n width: i32,\n height: i32,\n}\n\n#[derive(spacetimedb::SpacetimeType)]\npub enum Shape {\n Circle(i32),\n Rectangle(Rect),\n}\n\n#[spacetimedb::table(name = drawing)]\npub struct Drawing {\n #[primary_key]\n id: i32,\n a: Shape,\n b: Shape,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n if ctx.db.drawing().id().find(1).is_none() {\n ctx.db.drawing().insert(Drawing {\n id: 1,\n a: Shape::Circle(10),\n b: Shape::Rectangle(Rect { width: 4, height: 6 }),\n });\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-016-sum-type-columns-golden", @@ -824,7 +834,7 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:33615/v1/database/c200881b5220df4b060ef4c2656171f2f8326cecff55db6c3c11d3ebbd2f5cec/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41115/v1/database/c200be63a5c073cb57163fbe420fbf96d0ca1c24fb78e5d67bbed19841d5eeee/sql)\n", "phase": "sql_golden" } }, @@ -836,7 +846,7 @@ "llm_db": "schema-t-016-sum-type-columns-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } @@ -845,24 +855,24 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:33615/v1/database/c20074c3ee57884fdd34989755bdcfa11644a8f79ecbbdbf8f5182f2be46b5ec/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41115/v1/database/c2001257ca4ff5c673696324b8a29b10931896a2877a4425230bec1856988aad/sql)\n", "phase": "sql" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:49:28.665270093Z", - "finished_at": "2026-01-27T19:50:17.767945290Z" + "started_at": "2026-01-23T20:07:57.742955241Z", + "finished_at": "2026-01-23T20:08:35.620943048Z" }, "t_017_scheduled_columns": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_017_scheduled_columns", "lang": "rust", "golden_published": false, "model_name": "GPT-5", "total_tests": 2, "passed_tests": 0, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, ScheduleAt};\n\n#[table(name = tick_timer, schedule(reducer = tick, column = scheduled_at))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[reducer(init)]\npub fn init(ctx: &ReducerContext) {\n if ctx.db.tick_timer().count() == 0 {\n ctx.db.tick_timer().insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::RepeatMicros(50_000),\n });\n }\n}\n\n#[reducer]\npub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, ScheduleAt};\n\n#[table(name = tick_timer, schedule(reducer = tick, column = scheduled_at))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[reducer(init)]\npub fn init(ctx: &ReducerContext) {\n if ctx.db.tick_timer().count() == 0 {\n ctx.db.tick_timer().insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::repeat_micros(50_000),\n });\n }\n}\n\n#[reducer]\npub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-017-scheduled-columns-golden", @@ -874,24 +884,24 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime publish failed (exit=1)\n--- stderr ---\n Updating crates.io index\n Locking 72 packages to latest compatible versions\n Adding generic-array v0.14.7 (available: v0.14.9)\n Adding spacetimedb v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-macro v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-sys v1.11.1 (available: v1.11.3)\n Adding spacetimedb-lib v1.11.1 (available: v1.11.3)\n Adding spacetimedb-primitives v1.11.1 (available: v1.11.3)\n Adding spacetimedb-sats v1.11.1 (available: v1.11.3)\n Compiling proc-macro2 v1.0.106\n Compiling unicode-ident v1.0.22\n Compiling quote v1.0.44\n Compiling typenum v1.19.0\n Compiling version_check v0.9.5\n Compiling autocfg v1.5.0\n Compiling heck v0.5.0\n Compiling serde_core v1.0.228\n Compiling cfg-if v1.0.4\n Compiling either v1.15.0\n Compiling serde v1.0.228\n Compiling find-msvc-tools v0.1.8\n Compiling shlex v1.3.0\n Compiling zerocopy v0.8.34\n Compiling nohash-hasher v0.2.0\n Compiling anyhow v1.0.100\n Compiling thiserror v1.0.69\n Compiling bitflags v2.10.0\n Compiling keccak v0.1.5\n Compiling convert_case v0.4.0\n Compiling zmij v1.0.17\n Compiling arrayvec v0.7.6\n Compiling humantime v2.3.0\n Compiling bytes v1.11.0\n Compiling heck v0.4.1\n Compiling second-stack v0.3.5\n Compiling hex v0.4.3\n Compiling serde_json v1.0.149\n Compiling constant_time_eq v0.4.2\n Compiling itoa v1.0.17\n Compiling arrayref v0.3.9\n Compiling getrandom v0.2.17\n Compiling spacetimedb-lib v1.11.1\n Compiling bytemuck v1.24.0\n Compiling smallvec v1.15.1\n Compiling rand_core v0.6.4\n Compiling cc v1.2.54\n Compiling log v0.4.29\n Compiling memchr v2.7.6\n Compiling scoped-tls v1.0.1\n Compiling generic-array v0.14.7\n Compiling itertools v0.12.1\n Compiling num-traits v0.2.19\n Compiling http v1.4.0\n Compiling syn v2.0.114\n Compiling approx v0.3.2\n Compiling chrono v0.4.43\n Compiling decorum v0.3.1\n Compiling blake3 v1.8.3\n Compiling crypto-common v0.1.7\n Compiling block-buffer v0.10.4\n Compiling digest v0.10.7\n Compiling sha3 v0.10.8\n Compiling ethnum v1.5.2\n Compiling ppv-lite86 v0.2.21\n Compiling rand_chacha v0.3.1\n Compiling rand v0.8.5\n Compiling enum-as-inner v0.6.1\n Compiling thiserror-impl v1.0.69\n Compiling derive_more v0.99.20\n Compiling spacetimedb-primitives v1.11.1\n Compiling spacetimedb-bindings-macro v1.11.1\n Compiling spacetimedb-bindings-sys v1.11.1\n Compiling spacetimedb-sats v1.11.1\n Compiling spacetimedb v1.11.1\n Compiling spacetime-module v0.1.0 (/__w/SpacetimeDB/SpacetimeDB/target/llm-runs/schema/t_017_scheduled_columns/rust/server/gpt-5/llm)\nerror: expected one of: `public`, `private`, `name`, `index`, `scheduled`\n --> src/lib.rs:4:28\n |\n4 | #[table(name = tick_timer, schedule(reducer = tick, column = scheduled_at))]\n | ^^^^^^^^\n\nerror[E0422]: cannot find struct, variant or union type `TickTimer` in this scope\n --> src/lib.rs:15:36\n |\n15 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^ not found in this scope\n\nerror[E0412]: cannot find type `TickTimer` in this scope\n --> src/lib.rs:23:42\n |\n23 | pub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n | ^^^^^^^^^ not found in this scope\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:14:15\n |\n14 | if ctx.db.tick_timer().count() == 0 {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:15:16\n |\n15 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no variant or associated item named `RepeatMicros` found for enum `ScheduleAt` in the current scope\n --> src/lib.rs:17:39\n |\n17 | scheduled_at: ScheduleAt::RepeatMicros(50_000),\n | ^^^^^^^^^^^^ variant or associated item not found in `ScheduleAt`\n\nerror[E0277]: invalid reducer signature\n --> src/lib.rs:23:8\n |\n 22 | #[reducer]\n | ---------- required by a bound introduced by this call\n 23 | pub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n | ^^^^ this reducer signature is not valid\n |\n = help: the trait `Reducer<'_, _>` is not implemented for fn item `for<'a> fn(&'a ReducerContext, {type error}) {tick}`\n = note: \n = note: reducer signatures must match the following pattern:\n = note: `Fn(&ReducerContext, [T1, ...]) [-> Result<(), impl Display>]`\n = note: where each `Ti` type implements `SpacetimeType`.\n = note: \nnote: required by a bound in `register_reducer`\n --> /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spacetimedb-1.11.1/src/rt.rs:746:81\n |\n746 | pub fn register_reducer<'a, A: Args<'a>, I: FnInfo>(_: impl Reducer<'a, A>) {\n | ^^^^^^^^^^^^^^ required by this bound in `register_reducer`\n\nerror[E0277]: invalid reducer signature\n --> src/lib.rs:23:8\n |\n22 | #[reducer]\n | ---------- required by a bound introduced by this call\n23 | pub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n | ^^^^ this reducer signature is not valid\n |\n = help: the trait `Reducer<'_, _>` is not implemented for fn item `for<'a> fn(&'a ReducerContext, {type error}) {tick}`\n = note: \n = note: reducer signatures must match the following pattern:\n = note: `Fn(&ReducerContext, [T1, ...]) [-> Result<(), impl Display>]`\n = note: where each `Ti` type implements `SpacetimeType`.\n = note: \nnote: required by a bound in `invoke_reducer`\n --> /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spacetimedb-1.11.1/src/rt.rs:45:19\n |\n44 | pub fn invoke_reducer<'a, A: Args<'a>>(\n | -------------- required by a bound in this function\n45 | reducer: impl Reducer<'a, A>,\n | ^^^^^^^^^^^^^^ required by this bound in `invoke_reducer`\n\nSome errors have detailed explanations: E0277, E0412, E0422, E0599.\nFor more information about an error, try `rustc --explain E0277`.\nerror: could not compile `spacetime-module` (lib) due to 8 previous errors\nError: command [\"cargo\", \"build\", \"--config=net.git-fetch-with-cli=true\", \"--target=wasm32-unknown-unknown\", \"--release\", \"--message-format=json-render-diagnostics\"] exited with code 101\n\n--- stdout ---\n", + "error": "spacetime publish failed (exit=1)\n--- stderr ---\n Updating crates.io index\n Locking 72 packages to latest compatible versions\n Adding generic-array v0.14.7 (available: v0.14.9)\n Adding spacetimedb v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-macro v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-sys v1.11.1 (available: v1.11.3)\n Adding spacetimedb-lib v1.11.1 (available: v1.11.3)\n Adding spacetimedb-primitives v1.11.1 (available: v1.11.3)\n Adding spacetimedb-sats v1.11.1 (available: v1.11.3)\n Compiling proc-macro2 v1.0.106\n Compiling quote v1.0.44\n Compiling unicode-ident v1.0.22\n Compiling typenum v1.19.0\n Compiling version_check v0.9.5\n Compiling autocfg v1.5.0\n Compiling serde_core v1.0.228\n Compiling heck v0.5.0\n Compiling cfg-if v1.0.4\n Compiling serde v1.0.228\n Compiling either v1.15.0\n Compiling shlex v1.3.0\n Compiling zerocopy v0.8.33\n Compiling find-msvc-tools v0.1.8\n Compiling nohash-hasher v0.2.0\n Compiling thiserror v1.0.69\n Compiling bitflags v2.10.0\n Compiling anyhow v1.0.100\n Compiling arrayvec v0.7.6\n Compiling zmij v1.0.16\n Compiling heck v0.4.1\n Compiling convert_case v0.4.0\n Compiling humantime v2.3.0\n Compiling bytes v1.11.0\n Compiling keccak v0.1.5\n Compiling constant_time_eq v0.4.2\n Compiling bytemuck v1.24.0\n Compiling second-stack v0.3.5\n Compiling smallvec v1.15.1\n Compiling getrandom v0.2.17\n Compiling hex v0.4.3\n Compiling spacetimedb-lib v1.11.1\n Compiling itertools v0.12.1\n Compiling cc v1.2.54\n Compiling serde_json v1.0.149\n Compiling itoa v1.0.17\n Compiling arrayref v0.3.9\n Compiling rand_core v0.6.4\n Compiling memchr v2.7.6\n Compiling log v0.4.29\n Compiling scoped-tls v1.0.1\n Compiling generic-array v0.14.7\n Compiling num-traits v0.2.19\n Compiling syn v2.0.114\n Compiling http v1.4.0\n Compiling approx v0.3.2\n Compiling chrono v0.4.43\n Compiling decorum v0.3.1\n Compiling blake3 v1.8.3\n Compiling crypto-common v0.1.7\n Compiling block-buffer v0.10.4\n Compiling digest v0.10.7\n Compiling sha3 v0.10.8\n Compiling ppv-lite86 v0.2.21\n Compiling ethnum v1.5.2\n Compiling rand_chacha v0.3.1\n Compiling rand v0.8.5\n Compiling enum-as-inner v0.6.1\n Compiling thiserror-impl v1.0.69\n Compiling derive_more v0.99.20\n Compiling spacetimedb-primitives v1.11.1\n Compiling spacetimedb-bindings-sys v1.11.1\n Compiling spacetimedb-bindings-macro v1.11.1\n Compiling spacetimedb-sats v1.11.1\n Compiling spacetimedb v1.11.1\n Compiling spacetime-module v0.1.0 (/__w/SpacetimeDB/SpacetimeDB/target/llm-runs/schema/t_017_scheduled_columns/rust/server/gpt-5/llm)\nerror: expected one of: `public`, `private`, `name`, `index`, `scheduled`\n --> src/lib.rs:4:28\n |\n4 | #[table(name = tick_timer, schedule(reducer = tick, column = scheduled_at))]\n | ^^^^^^^^\n\nerror[E0422]: cannot find struct, variant or union type `TickTimer` in this scope\n --> src/lib.rs:15:36\n |\n15 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^ not found in this scope\n\nerror[E0412]: cannot find type `TickTimer` in this scope\n --> src/lib.rs:23:42\n |\n23 | pub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n | ^^^^^^^^^ not found in this scope\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:14:15\n |\n14 | if ctx.db.tick_timer().count() == 0 {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:15:16\n |\n15 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no variant or associated item named `repeat_micros` found for enum `ScheduleAt` in the current scope\n --> src/lib.rs:17:39\n |\n17 | scheduled_at: ScheduleAt::repeat_micros(50_000),\n | ^^^^^^^^^^^^^ variant or associated item not found in `ScheduleAt`\n\nerror[E0277]: invalid reducer signature\n --> src/lib.rs:23:8\n |\n 22 | #[reducer]\n | ---------- required by a bound introduced by this call\n 23 | pub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n | ^^^^ this reducer signature is not valid\n |\n = help: the trait `Reducer<'_, _>` is not implemented for fn item `for<'a> fn(&'a ReducerContext, {type error}) {tick}`\n = note: \n = note: reducer signatures must match the following pattern:\n = note: `Fn(&ReducerContext, [T1, ...]) [-> Result<(), impl Display>]`\n = note: where each `Ti` type implements `SpacetimeType`.\n = note: \nnote: required by a bound in `register_reducer`\n --> /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spacetimedb-1.11.1/src/rt.rs:746:81\n |\n746 | pub fn register_reducer<'a, A: Args<'a>, I: FnInfo>(_: impl Reducer<'a, A>) {\n | ^^^^^^^^^^^^^^ required by this bound in `register_reducer`\n\nerror[E0277]: invalid reducer signature\n --> src/lib.rs:23:8\n |\n22 | #[reducer]\n | ---------- required by a bound introduced by this call\n23 | pub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n | ^^^^ this reducer signature is not valid\n |\n = help: the trait `Reducer<'_, _>` is not implemented for fn item `for<'a> fn(&'a ReducerContext, {type error}) {tick}`\n = note: \n = note: reducer signatures must match the following pattern:\n = note: `Fn(&ReducerContext, [T1, ...]) [-> Result<(), impl Display>]`\n = note: where each `Ti` type implements `SpacetimeType`.\n = note: \nnote: required by a bound in `invoke_reducer`\n --> /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spacetimedb-1.11.1/src/rt.rs:45:19\n |\n44 | pub fn invoke_reducer<'a, A: Args<'a>>(\n | -------------- required by a bound in this function\n45 | reducer: impl Reducer<'a, A>,\n | ^^^^^^^^^^^^^^ required by this bound in `invoke_reducer`\n\nSome errors have detailed explanations: E0277, E0412, E0422, E0599.\nFor more information about an error, try `rustc --explain E0277`.\nerror: could not compile `spacetime-module` (lib) due to 8 previous errors\nError: command [\"cargo\", \"build\", \"--config=net.git-fetch-with-cli=true\", \"--target=wasm32-unknown-unknown\", \"--release\", \"--message-format=json-render-diagnostics\"] exited with code 101\n\n--- stdout ---\n", "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:49:28.664841535Z", - "finished_at": "2026-01-27T19:50:33.923572352Z" + "started_at": "2026-01-23T20:07:57.742610502Z", + "finished_at": "2026-01-23T20:08:56.057254318Z" }, "t_018_constraints": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_018_constraints", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, - "passed_tests": 2, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = account, index(name = by_name, btree(columns = [name])))]\npub struct Account {\n #[primary_key]\n id: i32,\n #[unique]\n email: String,\n name: String,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n let accounts = ctx.db.account();\n let _ = accounts.try_insert(Account { id: 1, email: \"a@example.com\".to_string(), name: \"Alice\".to_string() });\n let _ = accounts.try_insert(Account { id: 2, email: \"b@example.com\".to_string(), name: \"Bob\".to_string() });\n}", + "passed_tests": 3, + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = account, index(name = by_name, btree(columns = [name])))]\npub struct Account {\n #[primary_key]\n id: i32,\n #[unique]\n email: String,\n name: String,\n}\n\n#[reducer]\npub fn seed(ctx: &ReducerContext) {\n ctx.db\n .account()\n .insert(Account {\n id: 1,\n email: \"a@example.com\".to_string(),\n name: \"Alice\".to_string(),\n });\n ctx.db\n .account()\n .insert(Account {\n id: 2,\n email: \"b@example.com\".to_string(),\n name: \"Bob\".to_string(),\n });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-018-constraints-golden", @@ -925,24 +935,43 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `account`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:33615/v1/database/c2002f3e10afac17bd0350f8d8feb90d1ae94d73c7c44c6824e7324679a8e5b9/sql)\n", - "phase": "sql_golden" + "args": [], + "golden_db": "schema-t-018-constraints-golden", + "golden_out": "id | email | name ----+-----------------+--------- 1 | \"a@example.com\" | \"Alice\"", + "llm_db": "schema-t-018-constraints-gpt-5-llm", + "llm_out": "id | email | name ----+-----------------+--------- 1 | \"a@example.com\" | \"Alice\"", + "query": "SELECT id, email, name FROM account WHERE id=1", + "reducer": "seed", + "server": "http://127.0.0.1:41115" + } + }, + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "schema-t-018-constraints-golden", + "llm_db": "schema-t-018-constraints-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41115", + "tables_diff": null, + "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:49:28.664543506Z", - "finished_at": "2026-01-27T19:50:17.029704757Z" + "started_at": "2026-01-23T20:07:57.742384971Z", + "finished_at": "2026-01-23T20:08:30.379256146Z" }, "t_019_many_to_many": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_019_many_to_many", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 5, "passed_tests": 5, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user)]\npub struct User {\n #[primary_key]\n user_id: i32,\n name: String,\n}\n\n#[spacetimedb::table(name = group)]\npub struct Group {\n #[primary_key]\n group_id: i32,\n title: String,\n}\n\n#[spacetimedb::table(\n name = membership,\n index(name = by_user, btree(columns = [user_id])),\n index(name = by_group, btree(columns = [group_id]))\n)]\npub struct Membership {\n #[primary_key]\n id: i32,\n user_id: i32,\n group_id: i32,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n // Clear existing rows to ensure the database contains exactly the specified rows.\n let membership_ids: Vec = ctx.db.membership().iter().map(|m| m.id).collect();\n for id in membership_ids {\n ctx.db.membership().id().delete(&id);\n }\n\n let user_ids: Vec = ctx.db.user().iter().map(|u| u.user_id).collect();\n for id in user_ids {\n ctx.db.user().user_id().delete(&id);\n }\n\n let group_ids: Vec = ctx.db.group().iter().map(|g| g.group_id).collect();\n for id in group_ids {\n ctx.db.group().group_id().delete(&id);\n }\n\n // Insert users\n ctx.db.user().insert(User { user_id: 1, name: \"Alice\".to_string() });\n ctx.db.user().insert(User { user_id: 2, name: \"Bob\".to_string() });\n\n // Insert groups\n ctx.db.group().insert(Group { group_id: 10, title: \"Admin\".to_string() });\n ctx.db.group().insert(Group { group_id: 20, title: \"Dev\".to_string() });\n\n // Insert memberships\n ctx.db.membership().insert(Membership { id: 1, user_id: 1, group_id: 10 });\n ctx.db.membership().insert(Membership { id: 2, user_id: 1, group_id: 20 });\n ctx.db.membership().insert(Membership { id: 3, user_id: 2, group_id: 20 });\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n user_id: i32,\n name: String,\n}\n\n#[table(name = group)]\npub struct Group {\n #[primary_key]\n group_id: i32,\n title: String,\n}\n\n#[table(\n name = membership,\n index(name = by_user, btree(columns = [user_id])),\n index(name = by_group, btree(columns = [group_id]))\n)]\npub struct Membership {\n #[primary_key]\n id: i32,\n user_id: i32,\n group_id: i32,\n}\n\n#[reducer]\npub fn seed(ctx: &ReducerContext) {\n // Clear existing rows to ensure exactly the requested rows exist after seeding\n let membership_ids: Vec = ctx.db.membership().iter().map(|m| m.id).collect();\n for id in membership_ids {\n ctx.db.membership().id().delete(&id);\n }\n\n let user_ids: Vec = ctx.db.user().iter().map(|u| u.user_id).collect();\n for id in user_ids {\n ctx.db.user().user_id().delete(&id);\n }\n\n let group_ids: Vec = ctx.db.group().iter().map(|g| g.group_id).collect();\n for id in group_ids {\n ctx.db.group().group_id().delete(&id);\n }\n\n // Insert users\n ctx.db.user().insert(User { user_id: 1, name: \"Alice\".to_string() });\n ctx.db.user().insert(User { user_id: 2, name: \"Bob\".to_string() });\n\n // Insert groups\n ctx.db.group().insert(Group { group_id: 10, title: \"Admin\".to_string() });\n ctx.db.group().insert(Group { group_id: 20, title: \"Dev\".to_string() });\n\n // Insert memberships\n ctx.db.membership().insert(Membership { id: 1, user_id: 1, group_id: 10 });\n ctx.db.membership().insert(Membership { id: 2, user_id: 1, group_id: 20 });\n ctx.db.membership().insert(Membership { id: 3, user_id: 2, group_id: 20 });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-019-many-to-many-golden", @@ -950,15 +979,6 @@ "work_dir_golden": "target/llm-runs/schema/t_019_many_to_many/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_019_many_to_many/rust/server/gpt-5/llm", "scorer_details": { - "m2m_has_2_20": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=2 AND group_id=20" - } - }, "schema_parity": { "pass": true, "partial": 1.0, @@ -967,7 +987,7 @@ "llm_db": "schema-t-019-many-to-many-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } @@ -981,13 +1001,13 @@ "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=1 AND group_id=20" } }, - "m2m_has_1_10": { + "m2m_has_2_20": { "pass": true, "partial": 1.0, "notes": { "actual": 1, "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=1 AND group_id=10" + "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=2 AND group_id=20" } }, "memberships_three_rows": { @@ -998,21 +1018,30 @@ "expected": 3, "sql": "SELECT COUNT(*) AS n FROM membership" } + }, + "m2m_has_1_10": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=1 AND group_id=10" + } } }, "vendor": "openai", - "started_at": "2026-01-27T19:49:28.665682949Z", - "finished_at": "2026-01-27T19:50:22.268882588Z" + "started_at": "2026-01-23T20:07:57.743323315Z", + "finished_at": "2026-01-23T20:08:57.792175612Z" }, "t_020_ecs": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_020_ecs", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 5, "passed_tests": 1, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = entity)]\npub struct Entity {\n #[primary_key]\n id: i32,\n}\n\n#[table(name = position)]\npub struct Position {\n #[primary_key]\n entity_id: i32,\n x: i32,\n y: i32,\n}\n\n#[table(name = velocity)]\npub struct Velocity {\n #[primary_key]\n entity_id: i32,\n vx: i32,\n vy: i32,\n}\n\n#[table(name = next_position)]\npub struct NextPosition {\n #[primary_key]\n entity_id: i32,\n x: i32,\n y: i32,\n}\n\n#[reducer]\npub fn seed(ctx: &ReducerContext) {\n let _ = ctx.db.entity().try_insert(Entity { id: 1 });\n let _ = ctx.db.entity().try_insert(Entity { id: 2 });\n\n let _ = ctx.db.position().try_insert(Position { entity_id: 1, x: 0, y: 0 });\n let _ = ctx.db.velocity().try_insert(Velocity { entity_id: 1, vx: 1, vy: 0 });\n\n let _ = ctx.db.position().try_insert(Position { entity_id: 2, x: 10, y: 0 });\n let _ = ctx.db.velocity().try_insert(Velocity { entity_id: 2, vx: -2, vy: 3 });\n}\n\n#[reducer]\npub fn step(ctx: &ReducerContext) {\n for pos in ctx.db.position().iter() {\n if let Some(vel) = ctx.db.velocity().entity_id().find(pos.entity_id) {\n let nx = pos.x + vel.vx;\n let ny = pos.y + vel.vy;\n\n if let Some(mut existing) = ctx.db.next_position().entity_id().find(pos.entity_id) {\n existing.x = nx;\n existing.y = ny;\n let _ = ctx.db.next_position().entity_id().update(existing);\n } else {\n let _ = ctx.db.next_position().try_insert(NextPosition {\n entity_id: pos.entity_id,\n x: nx,\n y: ny,\n });\n }\n }\n }\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = entity)]\npub struct Entity {\n #[primary_key]\n id: i32,\n}\n\n#[spacetimedb::table(name = position)]\npub struct Position {\n #[primary_key]\n entity_id: i32,\n x: i32,\n y: i32,\n}\n\n#[spacetimedb::table(name = velocity)]\npub struct Velocity {\n #[primary_key]\n entity_id: i32,\n vx: i32,\n vy: i32,\n}\n\n#[spacetimedb::table(name = next_position)]\npub struct NextPosition {\n #[primary_key]\n entity_id: i32,\n x: i32,\n y: i32,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n // Clear and insert entities\n for &id in &[1, 2] {\n if ctx.db.entity().id().find(id).is_some() {\n ctx.db.entity().id().delete(&id);\n }\n ctx.db.entity().insert(Entity { id });\n }\n\n // Clear existing positions/velocities for these entities and insert new values\n // Entity 1: pos=(0,0), vel=(1,0)\n if ctx.db.position().entity_id().find(1).is_some() {\n ctx.db.position().entity_id().delete(&1);\n }\n ctx.db.position().insert(Position { entity_id: 1, x: 0, y: 0 });\n if ctx.db.velocity().entity_id().find(1).is_some() {\n ctx.db.velocity().entity_id().delete(&1);\n }\n ctx.db.velocity().insert(Velocity { entity_id: 1, vx: 1, vy: 0 });\n\n // Entity 2: pos=(10,0), vel=(-2,3)\n if ctx.db.position().entity_id().find(2).is_some() {\n ctx.db.position().entity_id().delete(&2);\n }\n ctx.db.position().insert(Position { entity_id: 2, x: 10, y: 0 });\n if ctx.db.velocity().entity_id().find(2).is_some() {\n ctx.db.velocity().entity_id().delete(&2);\n }\n ctx.db.velocity().insert(Velocity { entity_id: 2, vx: -2, vy: 3 });\n\n // Clean any existing next_position rows for these entities\n for &id in &[1, 2] {\n if ctx.db.next_position().entity_id().find(id).is_some() {\n ctx.db.next_position().entity_id().delete(&id);\n }\n }\n}\n\n#[spacetimedb::reducer]\npub fn step(ctx: &ReducerContext) {\n for pos in ctx.db.position().iter() {\n if let Some(vel) = ctx.db.velocity().entity_id().find(pos.entity_id) {\n let nx = pos.x + vel.vx;\n let ny = pos.y + vel.vy;\n let next = NextPosition {\n entity_id: pos.entity_id,\n x: nx,\n y: ny,\n };\n\n if ctx.db.next_position().entity_id().find(pos.entity_id).is_some() {\n let _ = ctx.db.next_position().entity_id().update(next);\n } else {\n let _ = ctx.db.next_position().insert(next);\n }\n }\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-020-ecs-golden", @@ -1024,15 +1053,15 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:33615/v1/database/c200ef190fe9bac0d026751d082f663c75cb0435d300fdc35e1bc1f038529566/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41115/v1/database/c20022d8f2e2d547824e6b1c08b40372fd94143f227cebc3dd95d8debbce411d/sql)\n", "phase": "sql" } }, - "ecs_next_pos_entity2": { + "ecs_seed_positions_count": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:33615/v1/database/c200ef190fe9bac0d026751d082f663c75cb0435d300fdc35e1bc1f038529566/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41115/v1/database/c20022d8f2e2d547824e6b1c08b40372fd94143f227cebc3dd95d8debbce411d/sql)\n", "phase": "sql" } }, @@ -1044,7 +1073,7 @@ "llm_db": "schema-t-020-ecs-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } @@ -1053,25 +1082,25 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:33615/v1/database/c200ef190fe9bac0d026751d082f663c75cb0435d300fdc35e1bc1f038529566/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41115/v1/database/c20022d8f2e2d547824e6b1c08b40372fd94143f227cebc3dd95d8debbce411d/sql)\n", "phase": "sql" } }, - "ecs_seed_positions_count": { + "ecs_next_pos_entity2": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:33615/v1/database/c200ef190fe9bac0d026751d082f663c75cb0435d300fdc35e1bc1f038529566/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41115/v1/database/c20022d8f2e2d547824e6b1c08b40372fd94143f227cebc3dd95d8debbce411d/sql)\n", "phase": "sql" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:49:28.665885964Z", - "finished_at": "2026-01-27T19:50:18.814108696Z" + "started_at": "2026-01-23T20:07:57.743495455Z", + "finished_at": "2026-01-23T20:09:14.983916389Z" }, "t_021_multi_column_index": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_021_multi_column_index", "lang": "rust", "golden_published": true, @@ -1086,6 +1115,15 @@ "work_dir_golden": "target/llm-runs/schema/t_021_multi_column_index/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_021_multi_column_index/rust/server/gpt-5/llm", "scorer_details": { + "mcindex_lookup_u7_d1": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM log WHERE user_id=7 AND day=1" + } + }, "schema_parity": { "pass": true, "partial": 1.0, @@ -1094,7 +1132,7 @@ "llm_db": "schema-t-021-multi-column-index-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:33615", + "server": "http://127.0.0.1:41115", "tables_diff": null, "tables_equal": true } @@ -1108,16 +1146,7 @@ "sql": "SELECT COUNT(*) AS n FROM log" } }, - "mcindex_lookup_u7_d1": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM log WHERE user_id=7 AND day=1" - } - }, - "mcindex_lookup_u7_d2": { + "mcindex_seed_count": { "pass": true, "partial": 1.0, "notes": { @@ -1128,8 +1157,8 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:49:28.665048738Z", - "finished_at": "2026-01-27T19:50:12.818516478Z" + "started_at": "2026-01-23T20:07:57.742772776Z", + "finished_at": "2026-01-23T20:08:35.084850930Z" } } } @@ -1137,21 +1166,21 @@ }, { "mode": "docs", - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "models": [ { "name": "GPT-5", "route_api_model": "gpt-5", "tasks": { "t_000_empty_reducers": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_000_empty_reducers", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 1, "passed_tests": 0, - "llm_output": "use spacetimedb::ReducerContext;\n\n#[spacetimedb::reducer]\npub fn empty_reducer_no_args(ctx: &ReducerContext) {}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_int(ctx: &ReducerContext, count: i32) {}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_string(ctx: &ReducerContext, name: String) {}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_two_args(ctx: &ReducerContext, count: i32, name: String) {}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_three_args(ctx: &ReducerContext, active: bool, ratio: f32, label: String) {}", + "llm_output": "#[spacetimedb::reducer]\npub fn empty_reducer_no_args(_ctx: &spacetimedb::ReducerContext) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_int(_ctx: &spacetimedb::ReducerContext, _count: i32) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_string(_ctx: &spacetimedb::ReducerContext, _name: String) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_two_args(_ctx: &spacetimedb::ReducerContext, _count: i32, _name: String) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_three_args(_ctx: &spacetimedb::ReducerContext, _active: bool, _ratio: f32, _label: String) {\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-000-empty-reducers-golden", @@ -1169,11 +1198,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:53:02.635478741Z", - "finished_at": "2026-01-27T19:53:40.787269737Z" + "started_at": "2026-01-23T20:12:10.018237719Z", + "finished_at": "2026-01-23T20:12:41.638729168Z" }, "t_001_basic_tables": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_001_basic_tables", "lang": "rust", "golden_published": true, @@ -1198,18 +1227,18 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:53:04.338845678Z", - "finished_at": "2026-01-27T19:53:39.243226783Z" + "started_at": "2026-01-23T20:12:46.725514922Z", + "finished_at": "2026-01-23T20:13:51.799945305Z" }, "t_002_scheduled_table": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_002_scheduled_table", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 1, "passed_tests": 0, - "llm_output": "use spacetimedb::{ReducerContext, ScheduleAt, Table};\n\n#[spacetimedb::table(name = tick_timer, scheduled(tick))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[spacetimedb::reducer]\npub fn tick(_ctx: &ReducerContext, _timer: TickTimer) -> Result<(), String> {\n Ok(())\n}\n\n#[spacetimedb::reducer(init)]\npub fn init(ctx: &ReducerContext) -> Result<(), String> {\n if ctx.db.tick_timer().count() == 0 {\n use std::time::Duration;\n ctx.db.tick_timer().insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::Interval(Duration::from_micros(50_000).into()),\n });\n }\n Ok(())\n}", + "llm_output": "use std::time::Duration;\nuse spacetimedb::{ReducerContext, ScheduleAt, Table};\n\n#[spacetimedb::table(name = tick_timer, scheduled(tick))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[spacetimedb::reducer]\npub fn tick(_ctx: &ReducerContext, _timer: TickTimer) {\n // No-op scheduled tick.\n}\n\n#[spacetimedb::reducer(init)]\npub fn init(ctx: &ReducerContext) -> Result<(), String> {\n ctx.db.tick_timer().insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::Interval(Duration::from_micros(50_000).into()),\n });\n Ok(())\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-002-scheduled-table-golden", @@ -1227,11 +1256,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:53:38.403872273Z", - "finished_at": "2026-01-27T19:54:31.831288022Z" + "started_at": "2026-01-23T20:13:28.197750258Z", + "finished_at": "2026-01-23T20:14:26.307958881Z" }, "t_003_struct_in_table": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_003_struct_in_table", "lang": "rust", "golden_published": true, @@ -1256,11 +1285,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:53:02.638916802Z", - "finished_at": "2026-01-27T19:53:40.055864699Z" + "started_at": "2026-01-23T20:12:41.638758353Z", + "finished_at": "2026-01-23T20:13:47.479970679Z" }, "t_004_insert": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_004_insert", "lang": "rust", "golden_published": true, @@ -1275,29 +1304,29 @@ "work_dir_golden": "target/llm-runs/basics/t_004_insert/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_004_insert/rust/server/gpt-5/llm", "scorer_details": { - "schema_parity": { + "data_parity_insert_user": { "pass": false, "partial": 0.0, "notes": { - "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-004-insert-golden`.\n", - "phase": "describe_golden" + "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-004-insert-golden`.\n", + "phase": "call_reducer_golden" } }, - "data_parity_insert_user": { + "schema_parity": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-004-insert-golden`.\n", - "phase": "call_reducer_golden" + "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-004-insert-golden`.\n", + "phase": "describe_golden" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:53:33.748279444Z", - "finished_at": "2026-01-27T19:53:56.014195443Z" + "started_at": "2026-01-23T20:12:46.734575843Z", + "finished_at": "2026-01-23T20:13:46.613223334Z" }, "t_005_update": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_005_update", "lang": "rust", "golden_published": true, @@ -1328,6 +1357,14 @@ "phase": "describe_golden" } }, + "data_parity_update_user": { + "pass": false, + "partial": 0.0, + "notes": { + "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-005-update-golden`.\n", + "phase": "call_reducer_golden" + } + }, "seed_users_row": { "pass": false, "partial": 0.0, @@ -1339,11 +1376,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:53:00.578961998Z", - "finished_at": "2026-01-27T19:53:38.403844461Z" + "started_at": "2026-01-23T20:12:10.015338220Z", + "finished_at": "2026-01-23T20:13:14.713691221Z" }, "t_006_delete": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_006_delete", "lang": "rust", "golden_published": true, @@ -1366,15 +1403,6 @@ "phase": "describe_golden" } }, - "seed_users_row": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-006-delete-golden`.\n", - "phase": "sql_golden", - "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" - } - }, "delete_user_count_zero": { "pass": true, "partial": 1.0, @@ -1383,21 +1411,30 @@ "expected": 0, "sql": "SELECT COUNT(*) AS n FROM user WHERE id=1" } + }, + "seed_users_row": { + "pass": false, + "partial": 0.0, + "notes": { + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-006-delete-golden`.\n", + "phase": "sql_golden", + "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" + } } }, "vendor": "openai", - "started_at": "2026-01-27T19:52:31.910165978Z", - "finished_at": "2026-01-27T19:52:58.192517311Z" + "started_at": "2026-01-23T20:12:09.994528341Z", + "finished_at": "2026-01-23T20:12:46.205776277Z" }, "t_007_crud": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_007_crud", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 4, "passed_tests": 1, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[spacetimedb::reducer]\npub fn crud(ctx: &ReducerContext) {\n ctx.db.user().insert(User { id: 1, name: \"Alice\".into(), age: 30, active: true });\n ctx.db.user().insert(User { id: 2, name: \"Bob\".into(), age: 22, active: false });\n ctx.db.user().id().update(User { id: 1, name: \"Alice2\".into(), age: 31, active: false });\n ctx.db.user().id().delete(2);\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[spacetimedb::reducer]\npub fn crud(ctx: &ReducerContext) {\n // insert (id=1, name=\"Alice\", age=30, active=true)\n ctx.db.user().insert(User {\n id: 1,\n name: \"Alice\".to_string(),\n age: 30,\n active: true,\n });\n\n // insert (id=2, name=\"Bob\", age=22, active=false)\n ctx.db.user().insert(User {\n id: 2,\n name: \"Bob\".to_string(),\n age: 22,\n active: false,\n });\n\n // update (id=1, name=\"Alice2\", age=31, active=false)\n if let Some(mut u1) = ctx.db.user().id().find(1) {\n u1.name = \"Alice2\".to_string();\n u1.age = 31;\n u1.active = false;\n ctx.db.user().id().update(u1);\n }\n\n // delete id=2\n ctx.db.user().id().delete(2);\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-007-crud-golden", @@ -1413,6 +1450,15 @@ "phase": "call_reducer_golden" } }, + "crud_row_id2_deleted": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 0, + "expected": 0, + "sql": "SELECT COUNT(*) AS n FROM user WHERE id=2" + } + }, "crud_total_count_one": { "pass": false, "partial": 0.0, @@ -1429,30 +1475,21 @@ "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-007-crud-golden`.\n", "phase": "describe_golden" } - }, - "crud_row_id2_deleted": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 0, - "expected": 0, - "sql": "SELECT COUNT(*) AS n FROM user WHERE id=2" - } } }, "vendor": "openai", - "started_at": "2026-01-27T19:52:42.328837521Z", - "finished_at": "2026-01-27T19:53:33.740284067Z" + "started_at": "2026-01-23T20:12:10.004797508Z", + "finished_at": "2026-01-23T20:13:37.162002816Z" }, "t_008_index_lookup": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_008_index_lookup", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 0, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[spacetimedb::table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n name: String,\n}\n\n#[spacetimedb::reducer]\npub fn lookup_user_name(ctx: &ReducerContext, id: i32) {\n if let Some(user) = ctx.db.user().id().find(id) {\n let row = ResultRow { id: user.id, name: user.name.clone() };\n if ctx.db.result().id().find(user.id).is_some() {\n ctx.db.result().id().update(row);\n } else {\n ctx.db.result().insert(row);\n }\n }\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[spacetimedb::table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n name: String,\n}\n\n#[spacetimedb::reducer]\npub fn lookup_user_name(ctx: &ReducerContext, id: i32) -> Result<(), String> {\n if let Some(user) = ctx.db.user().id().find(id) {\n ctx.db\n .result()\n .try_insert(ResultRow { id: user.id, name: user.name.clone() })?;\n Ok(())\n } else {\n Err(\"User not found\".to_string())\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-008-index-lookup-golden", @@ -1487,11 +1524,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:53:17.657026192Z", - "finished_at": "2026-01-27T19:53:54.093778910Z" + "started_at": "2026-01-23T20:12:46.729438058Z", + "finished_at": "2026-01-23T20:13:54.235945228Z" }, "t_009_init": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_009_init", "lang": "rust", "golden_published": true, @@ -1543,11 +1580,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:52:58.192552680Z", - "finished_at": "2026-01-27T19:53:38.342926441Z" + "started_at": "2026-01-23T20:12:10.009828612Z", + "finished_at": "2026-01-23T20:12:45.617807272Z" }, "t_010_connect": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_010_connect", "lang": "rust", "golden_published": true, @@ -1572,18 +1609,18 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:52:35.522740907Z", - "finished_at": "2026-01-27T19:53:02.635440935Z" + "started_at": "2026-01-23T20:12:09.998960857Z", + "finished_at": "2026-01-23T20:13:28.197638116Z" }, "t_011_helper_function": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_011_helper_function", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 0, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n sum: i32,\n}\n\nfn add(a: i32, b: i32) -> i32 {\n a + b\n}\n\n#[spacetimedb::reducer]\npub fn compute_sum(ctx: &ReducerContext, id: i32, a: i32, b: i32) {\n let sum = add(a, b);\n ctx.db.result().insert(ResultRow { id, sum });\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n sum: i32,\n}\n\nfn add(a: i32, b: i32) -> i32 {\n a + b\n}\n\n#[spacetimedb::reducer]\npub fn compute_sum(ctx: &ReducerContext, id: i32, a: i32, b: i32) {\n let s = add(a, b);\n ctx.db.result().insert(ResultRow { id, sum: s });\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-011-helper-function-golden", @@ -1591,21 +1628,29 @@ "work_dir_golden": "target/llm-runs/basics/t_011_helper_function/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_011_helper_function/rust/server/gpt-5/llm", "scorer_details": { - "helper_func_sum_abs": { + "helper_func_sum_parity": { "pass": false, "partial": 0.0, "notes": { - "actual": 0, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM result WHERE id=1 AND sum=5" + "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-011-helper-function-golden`.\n", + "phase": "call_reducer_golden" } }, - "helper_func_sum_parity": { + "schema_parity": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-011-helper-function-golden`.\n", - "phase": "call_reducer_golden" + "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-011-helper-function-golden`.\n", + "phase": "describe_golden" + } + }, + "helper_func_sum_abs": { + "pass": false, + "partial": 0.0, + "notes": { + "actual": 0, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM result WHERE id=1 AND sum=5" } }, "schema_parity": { @@ -1618,18 +1663,18 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:53:37.773674958Z", - "finished_at": "2026-01-27T19:53:57.689433966Z" + "started_at": "2026-01-23T20:13:14.723917629Z", + "finished_at": "2026-01-23T20:14:00.225654958Z" }, "t_012_spacetime_product_type": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_012_spacetime_product_type", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 0, - "llm_output": "use spacetimedb::{ReducerContext, SpacetimeType, Table};\n\n#[derive(SpacetimeType)]\npub struct Score {\n left: i32,\n right: i32,\n}\n\n#[spacetimedb::table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n value: Score,\n}\n\n#[spacetimedb::reducer]\npub fn set_score(ctx: &ReducerContext, id: i32, left: i32, right: i32) {\n ctx.db.result().insert(ResultRow {\n id,\n value: Score { left, right },\n });\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[derive(spacetimedb::SpacetimeType, Clone, Debug)]\npub struct Score {\n left: i32,\n right: i32,\n}\n\n#[spacetimedb::table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n value: Score,\n}\n\n#[spacetimedb::reducer]\npub fn set_score(ctx: &ReducerContext, id: i32, left: i32, right: i32) {\n ctx.db.result().insert(ResultRow {\n id,\n value: Score { left, right },\n });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-012-spacetime-product-type-golden", @@ -1637,12 +1682,13 @@ "work_dir_golden": "target/llm-runs/schema/t_012_spacetime_product_type/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_012_spacetime_product_type/rust/server/gpt-5/llm", "scorer_details": { - "product_type_row_parity": { + "product_type_row_count": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-012-spacetime-product-type-golden`.\n", - "phase": "call_reducer_golden" + "actual": 0, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM result WHERE id=1" } }, "schema_parity": { @@ -1653,75 +1699,57 @@ "phase": "describe_golden" } }, - "product_type_row_count": { + "product_type_row_parity": { "pass": false, "partial": 0.0, "notes": { - "actual": 0, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM result WHERE id=1" + "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-012-spacetime-product-type-golden`.\n", + "phase": "call_reducer_golden" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:52:29.436388253Z", - "finished_at": "2026-01-27T19:53:04.338818518Z" + "started_at": "2026-01-23T20:12:09.991277650Z", + "finished_at": "2026-01-23T20:12:46.725468970Z" }, "t_013_spacetime_sum_type": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_013_spacetime_sum_type", "lang": "rust", - "golden_published": true, + "golden_published": false, "model_name": "GPT-5", - "total_tests": 3, + "total_tests": 1, "passed_tests": 0, - "llm_output": "use spacetimedb::Table;\n\n#[derive(spacetimedb::SpacetimeType, Clone, Debug)]\npub struct Rect {\n width: i32,\n height: i32,\n}\n\n#[derive(spacetimedb::SpacetimeType, Clone, Debug)]\npub enum Shape {\n Circle(i32),\n Rectangle(Rect),\n}\n\n#[spacetimedb::table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n value: Shape,\n}\n\n#[spacetimedb::reducer]\npub fn set_circle(ctx: &spacetimedb::ReducerContext, id: i32, radius: i32) {\n ctx.db.result().insert(ResultRow {\n id,\n value: Shape::Circle(radius),\n });\n}", + "llm_output": null, "category": "schema", "route_api_model": "gpt-5", - "golden_db": "schema-t-013-spacetime-sum-type-golden", - "llm_db": "schema-t-013-spacetime-sum-type-gpt-5-llm", - "work_dir_golden": "target/llm-runs/schema/t_013_spacetime_sum_type/rust/server/golden", - "work_dir_llm": "target/llm-runs/schema/t_013_spacetime_sum_type/rust/server/gpt-5/llm", + "golden_db": null, + "llm_db": null, + "work_dir_golden": null, + "work_dir_llm": null, "scorer_details": { - "schema_parity": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-013-spacetime-sum-type-golden`.\n", - "phase": "describe_golden" - } - }, - "sum_type_row_count": { - "pass": false, - "partial": 0.0, - "notes": { - "actual": 0, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM result WHERE id=1" - } - }, - "sum_type_row_parity": { + "publish_error": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-013-spacetime-sum-type-golden`.\n", - "phase": "call_reducer_golden" + "error": "LLM call timed out", + "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:51:47.638500741Z", - "finished_at": "2026-01-27T19:53:00.578888253Z" + "started_at": "2026-01-23T20:14:26.308049242Z", + "finished_at": "2026-01-23T20:14:26.308049242Z" }, "t_014_elementary_columns": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_014_elementary_columns", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 0, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = primitive)]\npub struct Primitive {\n #[primary_key]\n id: i32,\n count: i32,\n total: i64,\n price: f32,\n ratio: f64,\n active: bool,\n name: String,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n ctx.db.primitive().insert(Primitive {\n id: 1,\n count: 2,\n total: 3_000_000_000i64,\n price: 1.5f32,\n ratio: 2.25f64,\n active: true,\n name: \"Alice\".to_string(),\n });\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = primitive)]\npub struct Primitive {\n #[primary_key]\n id: i32,\n count: i32,\n total: i64,\n price: f32,\n ratio: f64,\n active: bool,\n name: String,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n ctx.db.primitive().insert(Primitive {\n id: 1,\n count: 2,\n total: 3_000_000_000,\n price: 1.5_f32,\n ratio: 2.25,\n active: true,\n name: \"Alice\".into(),\n });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-014-elementary-columns-golden", @@ -1729,14 +1757,6 @@ "work_dir_golden": "target/llm-runs/schema/t_014_elementary_columns/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_014_elementary_columns/rust/server/gpt-5/llm", "scorer_details": { - "elementary_columns_row_parity": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-014-elementary-columns-golden`.\n", - "phase": "call_reducer_golden" - } - }, "elementary_columns_row_count": { "pass": false, "partial": 0.0, @@ -1753,14 +1773,22 @@ "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-014-elementary-columns-golden`.\n", "phase": "describe_golden" } + }, + "elementary_columns_row_parity": { + "pass": false, + "partial": 0.0, + "notes": { + "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-014-elementary-columns-golden`.\n", + "phase": "call_reducer_golden" + } } }, "vendor": "openai", - "started_at": "2026-01-27T19:52:27.568323309Z", - "finished_at": "2026-01-27T19:53:02.605112864Z" + "started_at": "2026-01-23T20:12:09.987997099Z", + "finished_at": "2026-01-23T20:13:50.463947582Z" }, "t_015_product_type_columns": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_015_product_type_columns", "lang": "rust", "golden_published": false, @@ -1785,319 +1813,182 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:54:31.831326960Z", - "finished_at": "2026-01-27T19:54:31.831326960Z" + "started_at": "2026-01-23T20:14:26.308063959Z", + "finished_at": "2026-01-23T20:14:26.308063959Z" }, "t_016_sum_type_columns": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_016_sum_type_columns", "lang": "rust", - "golden_published": true, + "golden_published": false, "model_name": "GPT-5", - "total_tests": 3, + "total_tests": 1, "passed_tests": 0, - "llm_output": "use spacetimedb::{ReducerContext, SpacetimeType, Table};\n\n#[derive(SpacetimeType, Clone, Debug)]\npub struct Rect {\n width: i32,\n height: i32,\n}\n\n#[derive(SpacetimeType, Clone, Debug)]\npub enum Shape {\n Circle(i32),\n Rectangle(Rect),\n}\n\n#[spacetimedb::table(name = drawing)]\npub struct Drawing {\n #[primary_key]\n id: i32,\n a: Shape,\n b: Shape,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n if ctx.db.drawing().count() == 0 {\n ctx.db.drawing().insert(Drawing {\n id: 1,\n a: Shape::Circle(10),\n b: Shape::Rectangle(Rect { width: 4, height: 6 }),\n });\n }\n}", + "llm_output": null, "category": "schema", "route_api_model": "gpt-5", - "golden_db": "schema-t-016-sum-type-columns-golden", - "llm_db": "schema-t-016-sum-type-columns-gpt-5-llm", - "work_dir_golden": "target/llm-runs/schema/t_016_sum_type_columns/rust/server/golden", - "work_dir_llm": "target/llm-runs/schema/t_016_sum_type_columns/rust/server/gpt-5/llm", + "golden_db": null, + "llm_db": null, + "work_dir_golden": null, + "work_dir_llm": null, "scorer_details": { - "schema_parity": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-016-sum-type-columns-golden`.\n", - "phase": "describe_golden" - } - }, - "sum_type_columns_row_parity": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-016-sum-type-columns-golden`.\n", - "phase": "call_reducer_golden" - } - }, - "sum_type_columns_row_count": { + "publish_error": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:38927/v1/database/c200596b7e7f2350abeb00119177ef3448e7673481a61aeaa7c22e4dd952cb52/sql)\n", - "phase": "sql" + "error": "LLM call timed out", + "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:51:47.634170474Z", - "finished_at": "2026-01-27T19:52:27.568235316Z" + "started_at": "2026-01-23T20:14:26.308044663Z", + "finished_at": "2026-01-23T20:14:26.308044663Z" }, "t_017_scheduled_columns": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_017_scheduled_columns", "lang": "rust", - "golden_published": true, + "golden_published": false, "model_name": "GPT-5", - "total_tests": 2, - "passed_tests": 1, - "llm_output": "use std::time::Duration;\nuse spacetimedb::{ReducerContext, ScheduleAt, Table};\n\n#[spacetimedb::table(name = tick_timer, scheduled(tick))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[spacetimedb::reducer]\npub fn tick(_ctx: &ReducerContext, _tick_timer: TickTimer) -> Result<(), String> {\n Ok(())\n}\n\n#[spacetimedb::reducer(init)]\npub fn init(ctx: &ReducerContext) -> Result<(), String> {\n if ctx.db.tick_timer().count() == 0 {\n ctx.db.tick_timer().try_insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::Interval(Duration::from_micros(50_000).into()),\n })?;\n }\n Ok(())\n}", + "total_tests": 1, + "passed_tests": 0, + "llm_output": null, "category": "schema", "route_api_model": "gpt-5", - "golden_db": "schema-t-017-scheduled-columns-golden", - "llm_db": "schema-t-017-scheduled-columns-gpt-5-llm", - "work_dir_golden": "target/llm-runs/schema/t_017_scheduled_columns/rust/server/golden", - "work_dir_llm": "target/llm-runs/schema/t_017_scheduled_columns/rust/server/gpt-5/llm", + "golden_db": null, + "llm_db": null, + "work_dir_golden": null, + "work_dir_llm": null, "scorer_details": { - "schema_parity": { + "publish_error": { "pass": false, "partial": 0.0, "notes": { - "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-017-scheduled-columns-golden`.\n", - "phase": "describe_golden" - } - }, - "scheduled_seeded_one_row": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM tick_timer WHERE scheduled_id>=0" + "error": "LLM call timed out", + "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:51:47.625840249Z", - "finished_at": "2026-01-27T19:52:35.522695487Z" + "started_at": "2026-01-23T20:14:26.308033084Z", + "finished_at": "2026-01-23T20:14:26.308033084Z" }, "t_018_constraints": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_018_constraints", "lang": "rust", - "golden_published": true, + "golden_published": false, "model_name": "GPT-5", - "total_tests": 3, + "total_tests": 1, "passed_tests": 0, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = account, index(name = by_name, btree(columns = [name])))]\npub struct Account {\n #[primary_key]\n id: i32,\n #[unique]\n email: String,\n name: String,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n let ids: Vec = ctx.db.account().iter().map(|a| a.id).collect();\n for id in ids {\n ctx.db.account().id().delete(id);\n }\n\n ctx.db.account().insert(Account {\n id: 1,\n email: \"a@example.com\".into(),\n name: \"Alice\".into(),\n });\n ctx.db.account().insert(Account {\n id: 2,\n email: \"b@example.com\".into(),\n name: \"Bob\".into(),\n });\n}", + "llm_output": null, "category": "schema", "route_api_model": "gpt-5", - "golden_db": "schema-t-018-constraints-golden", - "llm_db": "schema-t-018-constraints-gpt-5-llm", - "work_dir_golden": "target/llm-runs/schema/t_018_constraints/rust/server/golden", - "work_dir_llm": "target/llm-runs/schema/t_018_constraints/rust/server/gpt-5/llm", + "golden_db": null, + "llm_db": null, + "work_dir_golden": null, + "work_dir_llm": null, "scorer_details": { - "constraints_row_parity_after_seed": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-018-constraints-golden`.\n", - "phase": "call_reducer_golden" - } - }, - "schema_parity": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-018-constraints-golden`.\n", - "phase": "describe_golden" - } - }, - "constraints_seed_two_rows": { + "publish_error": { "pass": false, "partial": 0.0, "notes": { - "actual": 0, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM account WHERE id=2" + "error": "LLM call timed out", + "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:51:47.622424031Z", - "finished_at": "2026-01-27T19:53:37.773579225Z" + "started_at": "2026-01-23T20:14:26.308021447Z", + "finished_at": "2026-01-23T20:14:26.308021447Z" }, "t_019_many_to_many": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_019_many_to_many", "lang": "rust", - "golden_published": true, + "golden_published": false, "model_name": "GPT-5", - "total_tests": 5, - "passed_tests": 4, - "llm_output": "use spacetimedb::Table;\n\n#[spacetimedb::table(name = user, public)]\npub struct User {\n #[primary_key]\n user_id: i32,\n name: String,\n}\n\n#[spacetimedb::table(name = group, public)]\npub struct Group {\n #[primary_key]\n group_id: i32,\n title: String,\n}\n\n#[spacetimedb::table(\n name = membership,\n public,\n index(name = by_user, btree(columns = [user_id])),\n index(name = by_group, btree(columns = [group_id]))\n)]\npub struct Membership {\n #[primary_key]\n id: i32,\n user_id: i32,\n group_id: i32,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &spacetimedb::ReducerContext) {\n ctx.db.user().insert(User { user_id: 1, name: \"Alice\".into() });\n ctx.db.user().insert(User { user_id: 2, name: \"Bob\".into() });\n\n ctx.db.group().insert(Group { group_id: 10, title: \"Admin\".into() });\n ctx.db.group().insert(Group { group_id: 20, title: \"Dev\".into() });\n\n ctx.db.membership().insert(Membership { id: 1, user_id: 1, group_id: 10 });\n ctx.db.membership().insert(Membership { id: 2, user_id: 1, group_id: 20 });\n ctx.db.membership().insert(Membership { id: 3, user_id: 2, group_id: 20 });\n}", + "total_tests": 1, + "passed_tests": 0, + "llm_output": null, "category": "schema", "route_api_model": "gpt-5", - "golden_db": "schema-t-019-many-to-many-golden", - "llm_db": "schema-t-019-many-to-many-gpt-5-llm", - "work_dir_golden": "target/llm-runs/schema/t_019_many_to_many/rust/server/golden", - "work_dir_llm": "target/llm-runs/schema/t_019_many_to_many/rust/server/gpt-5/llm", + "golden_db": null, + "llm_db": null, + "work_dir_golden": null, + "work_dir_llm": null, "scorer_details": { - "memberships_three_rows": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 3, - "expected": 3, - "sql": "SELECT COUNT(*) AS n FROM membership" - } - }, - "schema_parity": { + "publish_error": { "pass": false, "partial": 0.0, "notes": { - "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-019-many-to-many-golden`.\n", - "phase": "describe_golden" - } - }, - "m2m_has_1_20": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=1 AND group_id=20" - } - }, - "m2m_has_1_10": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=1 AND group_id=10" - } - }, - "m2m_has_2_20": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=2 AND group_id=20" + "error": "LLM call timed out", + "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:51:47.642788029Z", - "finished_at": "2026-01-27T19:52:31.910080797Z" + "started_at": "2026-01-23T20:14:26.308054994Z", + "finished_at": "2026-01-23T20:14:26.308054994Z" }, "t_020_ecs": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_020_ecs", "lang": "rust", - "golden_published": true, + "golden_published": false, "model_name": "GPT-5", - "total_tests": 5, + "total_tests": 1, "passed_tests": 0, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = entity)]\npub struct Entity {\n #[primary_key]\n id: i32,\n}\n\n#[spacetimedb::table(name = position)]\npub struct Position {\n #[primary_key]\n entity_id: i32,\n x: i32,\n y: i32,\n}\n\n#[spacetimedb::table(name = velocity)]\npub struct Velocity {\n #[primary_key]\n entity_id: i32,\n vx: i32,\n vy: i32,\n}\n\n#[spacetimedb::table(name = next_position)]\npub struct NextPosition {\n #[primary_key]\n entity_id: i32,\n x: i32,\n y: i32,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n // First entity: id=1, pos=(0,0), vel=(1,0)\n ctx.db.entity().id().delete(1);\n ctx.db.position().entity_id().delete(1);\n ctx.db.velocity().entity_id().delete(1);\n ctx.db.entity().insert(Entity { id: 1 });\n ctx.db.position().insert(Position { entity_id: 1, x: 0, y: 0 });\n ctx.db.velocity().insert(Velocity { entity_id: 1, vx: 1, vy: 0 });\n\n // Second entity: id=2, pos=(10,0), vel=(-2,3)\n ctx.db.entity().id().delete(2);\n ctx.db.position().entity_id().delete(2);\n ctx.db.velocity().entity_id().delete(2);\n ctx.db.entity().insert(Entity { id: 2 });\n ctx.db.position().insert(Position { entity_id: 2, x: 10, y: 0 });\n ctx.db.velocity().insert(Velocity { entity_id: 2, vx: -2, vy: 3 });\n}\n\n#[spacetimedb::reducer]\npub fn step(ctx: &ReducerContext) {\n for pos in ctx.db.position().iter() {\n if let Some(vel) = ctx.db.velocity().entity_id().find(pos.entity_id) {\n let nx = pos.x + vel.vx;\n let ny = pos.y + vel.vy;\n if let Some(_existing) = ctx.db.next_position().entity_id().find(pos.entity_id) {\n ctx.db\n .next_position()\n .entity_id()\n .update(NextPosition { entity_id: pos.entity_id, x: nx, y: ny });\n } else {\n ctx.db\n .next_position()\n .insert(NextPosition { entity_id: pos.entity_id, x: nx, y: ny });\n }\n }\n }\n}", + "llm_output": null, "category": "schema", "route_api_model": "gpt-5", - "golden_db": "schema-t-020-ecs-golden", - "llm_db": "schema-t-020-ecs-gpt-5-llm", - "work_dir_golden": "target/llm-runs/schema/t_020_ecs/rust/server/golden", - "work_dir_llm": "target/llm-runs/schema/t_020_ecs/rust/server/gpt-5/llm", + "golden_db": null, + "llm_db": null, + "work_dir_golden": null, + "work_dir_llm": null, "scorer_details": { - "schema_parity": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-020-ecs-golden`.\n", - "phase": "describe_golden" - } - }, - "ecs_step_next_positions_count": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:38927/v1/database/c2000dfb254023618a83b1182de85ff2f9590dae5ce1c9301d7d8cc01c8bff6e/sql)\n", - "phase": "sql" - } - }, - "ecs_next_pos_entity1": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:38927/v1/database/c2000dfb254023618a83b1182de85ff2f9590dae5ce1c9301d7d8cc01c8bff6e/sql)\n", - "phase": "sql" - } - }, - "ecs_seed_positions_count": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:38927/v1/database/c2000dfb254023618a83b1182de85ff2f9590dae5ce1c9301d7d8cc01c8bff6e/sql)\n", - "phase": "sql" - } - }, - "ecs_next_pos_entity2": { + "publish_error": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:38927/v1/database/c2000dfb254023618a83b1182de85ff2f9590dae5ce1c9301d7d8cc01c8bff6e/sql)\n", - "phase": "sql" + "error": "LLM call timed out", + "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:51:47.647113172Z", - "finished_at": "2026-01-27T19:52:42.328754582Z" + "started_at": "2026-01-23T20:14:26.308059854Z", + "finished_at": "2026-01-23T20:14:26.308059854Z" }, "t_021_multi_column_index": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "task": "t_021_multi_column_index", "lang": "rust", - "golden_published": true, + "golden_published": false, "model_name": "GPT-5", - "total_tests": 4, - "passed_tests": 3, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = log, index(name = by_user_day, btree(columns = [user_id, day])))]\npub struct Log {\n #[primary_key]\n id: i32,\n user_id: i32,\n day: i32,\n message: String,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n ctx.db.log().insert(Log { id: 1, user_id: 7, day: 1, message: \"a\".into() });\n ctx.db.log().insert(Log { id: 2, user_id: 7, day: 2, message: \"b\".into() });\n ctx.db.log().insert(Log { id: 3, user_id: 9, day: 1, message: \"c\".into() });\n}", + "total_tests": 1, + "passed_tests": 0, + "llm_output": null, "category": "schema", "route_api_model": "gpt-5", - "golden_db": "schema-t-021-multi-column-index-golden", - "llm_db": "schema-t-021-multi-column-index-gpt-5-llm", - "work_dir_golden": "target/llm-runs/schema/t_021_multi_column_index/rust/server/golden", - "work_dir_llm": "target/llm-runs/schema/t_021_multi_column_index/rust/server/gpt-5/llm", + "golden_db": null, + "llm_db": null, + "work_dir_golden": null, + "work_dir_llm": null, "scorer_details": { - "schema_parity": { + "publish_error": { "pass": false, "partial": 0.0, "notes": { - "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-021-multi-column-index-golden`.\n", - "phase": "describe_golden" - } - }, - "mcindex_seed_count": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 3, - "expected": 3, - "sql": "SELECT COUNT(*) AS n FROM log" - } - }, - "mcindex_lookup_u7_d1": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM log WHERE user_id=7 AND day=1" - } - }, - "mcindex_lookup_u7_d2": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM log WHERE user_id=7 AND day=2" + "error": "LLM call timed out", + "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:51:47.629929093Z", - "finished_at": "2026-01-27T19:52:29.436282461Z" + "started_at": "2026-01-23T20:14:26.308040547Z", + "finished_at": "2026-01-23T20:14:26.308040547Z" } } } @@ -2288,14 +2179,14 @@ "modes": [ { "mode": "docs", - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "models": [ { "name": "GPT-5", "route_api_model": "gpt-5", "tasks": { "t_000_empty_reducers": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_000_empty_reducers", "lang": "csharp", "golden_published": true, @@ -2318,18 +2209,18 @@ "llm_db": "basics-t-000-empty-reducers-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:59:45.341740044Z", - "finished_at": "2026-01-27T20:00:17.110354447Z" + "started_at": "2026-01-23T20:20:05.908071Z", + "finished_at": "2026-01-23T20:21:02.544054377Z" }, "t_001_basic_tables": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_001_basic_tables", "lang": "csharp", "golden_published": true, @@ -2352,25 +2243,25 @@ "llm_db": "basics-t-001-basic-tables-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T20:00:10.594319009Z", - "finished_at": "2026-01-27T20:00:39.454473930Z" + "started_at": "2026-01-23T20:20:17.520008030Z", + "finished_at": "2026-01-23T20:21:03.652127542Z" }, "t_002_scheduled_table": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_002_scheduled_table", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 1, "passed_tests": 1, - "llm_output": "using System;\nusing SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"TickTimer\", Scheduled = nameof(Tick), ScheduledAt = nameof(ScheduledAt))]\n public partial struct TickTimer\n {\n [SpacetimeDB.PrimaryKey]\n [SpacetimeDB.AutoInc]\n public ulong ScheduledId;\n public ScheduleAt ScheduledAt;\n }\n\n [SpacetimeDB.Reducer(ReducerKind.Init)]\n public static void Init(ReducerContext ctx)\n {\n foreach (var row in ctx.Db.TickTimer.Iter())\n {\n ctx.Db.TickTimer.ScheduledId.Delete(row.ScheduledId);\n }\n\n ctx.Db.TickTimer.Insert(new TickTimer\n {\n ScheduledId = 0,\n ScheduledAt = new ScheduleAt.Interval(TimeSpan.FromMilliseconds(50))\n });\n }\n\n [SpacetimeDB.Reducer]\n public static void Tick(ReducerContext ctx, TickTimer _timer)\n {\n // Tick scheduled reducer. Intentionally left blank.\n }\n}", + "llm_output": "using System;\nusing SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"TickTimer\", Scheduled = nameof(Tick), ScheduledAt = nameof(ScheduledAt))]\n public partial struct TickTimer\n {\n [SpacetimeDB.PrimaryKey, SpacetimeDB.AutoInc]\n public ulong ScheduledId;\n public ScheduleAt ScheduledAt;\n }\n\n [SpacetimeDB.Reducer]\n public static void Tick(ReducerContext ctx, TickTimer timer)\n {\n }\n\n [SpacetimeDB.Reducer(ReducerKind.Init)]\n public static void Init(ReducerContext ctx)\n {\n ctx.Db.TickTimer.Insert(new TickTimer\n {\n ScheduledAt = new ScheduleAt.Interval(TimeSpan.FromMilliseconds(50))\n });\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-002-scheduled-table-golden", @@ -2386,18 +2277,18 @@ "llm_db": "basics-t-002-scheduled-table-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T20:00:39.454500245Z", - "finished_at": "2026-01-27T20:01:19.695962602Z" + "started_at": "2026-01-23T20:21:05.396968262Z", + "finished_at": "2026-01-23T20:21:59.590160864Z" }, "t_003_struct_in_table": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_003_struct_in_table", "lang": "csharp", "golden_published": true, @@ -2420,18 +2311,18 @@ "llm_db": "basics-t-003-struct-in-table-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T20:00:06.267861248Z", - "finished_at": "2026-01-27T20:00:37.823969244Z" + "started_at": "2026-01-23T20:20:12.029574819Z", + "finished_at": "2026-01-23T20:20:58.944028610Z" }, "t_004_insert": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_004_insert", "lang": "csharp", "golden_published": true, @@ -2446,19 +2337,6 @@ "work_dir_golden": "target/llm-runs/basics/t_004_insert/csharp/server/golden", "work_dir_llm": "target/llm-runs/basics/t_004_insert/csharp/server/gpt-5/llm", "scorer_details": { - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "basics-t-004-insert-golden", - "llm_db": "basics-t-004-insert-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:34379", - "tables_diff": null, - "tables_equal": true - } - }, "data_parity_insert_user": { "pass": true, "partial": 1.0, @@ -2475,23 +2353,36 @@ "llm_out": "Id | Name | Age | Active ----+---------+-----+-------- 1 | \"Alice\" | 30 | true", "query": "SELECT Id, Name, Age, Active FROM User WHERE Id=1", "reducer": "InsertUser", - "server": "http://127.0.0.1:34379" + "server": "http://127.0.0.1:41045" + } + }, + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "basics-t-004-insert-golden", + "llm_db": "basics-t-004-insert-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41045", + "tables_diff": null, + "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T20:00:17.336276015Z", - "finished_at": "2026-01-27T20:00:48.236577365Z" + "started_at": "2026-01-23T20:21:02.544101204Z", + "finished_at": "2026-01-23T20:21:46.575966420Z" }, "t_005_update": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_005_update", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer]\n public static void UpdateUser(ReducerContext ctx, int id, string name, int age, bool active)\n {\n var user = ctx.Db.User.Id.Find(id) ?? throw new System.Exception(\"User not found\");\n user.Name = name;\n user.Age = age;\n user.Active = active;\n user.Id = id;\n ctx.Db.User.Id.Update(user);\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\", Public = true)]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer]\n public static void UpdateUser(ReducerContext ctx, int id, string name, int age, bool active)\n {\n ctx.Db.User.Id.Update(new User\n {\n Id = id,\n Name = name,\n Age = age,\n Active = active\n });\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-005-update-golden", @@ -2499,25 +2390,6 @@ "work_dir_golden": "target/llm-runs/basics/t_005_update/csharp/server/golden", "work_dir_llm": "target/llm-runs/basics/t_005_update/csharp/server/gpt-5/llm", "scorer_details": { - "data_parity_update_user": { - "pass": true, - "partial": 1.0, - "notes": { - "args": [ - 1, - "Alice2", - 31, - false - ], - "golden_db": "basics-t-005-update-golden", - "golden_out": "Id | Name | Age | Active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", - "llm_db": "basics-t-005-update-gpt-5-llm", - "llm_out": "Id | Name | Age | Active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", - "query": "SELECT Id, Name, Age, Active FROM User WHERE Id=1", - "reducer": "UpdateUser", - "server": "http://127.0.0.1:34379" - } - }, "seed_users_row": { "pass": true, "partial": 1.0, @@ -2533,25 +2405,44 @@ "llm_db": "basics-t-005-update-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } + }, + "data_parity_update_user": { + "pass": true, + "partial": 1.0, + "notes": { + "args": [ + 1, + "Alice2", + 31, + false + ], + "golden_db": "basics-t-005-update-golden", + "golden_out": "Id | Name | Age | Active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", + "llm_db": "basics-t-005-update-gpt-5-llm", + "llm_out": "Id | Name | Age | Active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", + "query": "SELECT Id, Name, Age, Active FROM User WHERE Id=1", + "reducer": "UpdateUser", + "server": "http://127.0.0.1:41045" + } } }, "vendor": "openai", - "started_at": "2026-01-27T19:59:43.681559749Z", - "finished_at": "2026-01-27T20:00:17.332627669Z" + "started_at": "2026-01-23T20:19:53.867992725Z", + "finished_at": "2026-01-23T20:21:05.391950708Z" }, "t_006_delete": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_006_delete", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer]\n public static void DeleteUser(ReducerContext ctx, int id)\n {\n ctx.Db.User.Id.Delete(id);\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\", Public = true)]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer]\n public static void DeleteUser(ReducerContext ctx, int id)\n {\n ctx.Db.User.Id.Delete(id);\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-006-delete-golden", @@ -2559,13 +2450,6 @@ "work_dir_golden": "target/llm-runs/basics/t_006_delete/csharp/server/golden", "work_dir_llm": "target/llm-runs/basics/t_006_delete/csharp/server/gpt-5/llm", "scorer_details": { - "seed_users_row": { - "pass": true, - "partial": 1.0, - "notes": { - "sql": "INSERT INTO User(Id, Name, Age, Active) VALUES (1, 'Alice', 30, true)" - } - }, "delete_user_count_zero": { "pass": true, "partial": 1.0, @@ -2583,25 +2467,32 @@ "llm_db": "basics-t-006-delete-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } + }, + "seed_users_row": { + "pass": true, + "partial": 1.0, + "notes": { + "sql": "INSERT INTO User(Id, Name, Age, Active) VALUES (1, 'Alice', 30, true)" + } } }, "vendor": "openai", - "started_at": "2026-01-27T19:58:58.264033858Z", - "finished_at": "2026-01-27T19:59:39.007925686Z" + "started_at": "2026-01-23T20:19:10.793697386Z", + "finished_at": "2026-01-23T20:19:53.867926470Z" }, "t_007_crud": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_007_crud", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 4, "passed_tests": 4, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer]\n public static void Crud(ReducerContext ctx)\n {\n ctx.Db.User.Insert(new User { Id = 1, Name = \"Alice\", Age = 30, Active = true });\n ctx.Db.User.Insert(new User { Id = 2, Name = \"Bob\", Age = 22, Active = false });\n\n var found = ctx.Db.User.Id.Find(1);\n if (found is User user)\n {\n user.Name = \"Alice2\";\n user.Age = 31;\n user.Active = false;\n ctx.Db.User.Id.Update(user);\n }\n\n ctx.Db.User.Id.Delete(2);\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer]\n public static void Crud(ReducerContext ctx)\n {\n ctx.Db.User.Insert(new User { Id = 1, Name = \"Alice\", Age = 30, Active = true });\n ctx.Db.User.Insert(new User { Id = 2, Name = \"Bob\", Age = 22, Active = false });\n\n var found = ctx.Db.User.Id.Find(1);\n if (found is User user1)\n {\n user1.Name = \"Alice2\";\n user1.Age = 31;\n user1.Active = false;\n ctx.Db.User.Id.Update(user1);\n }\n\n ctx.Db.User.Id.Delete(2);\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-007-crud-golden", @@ -2609,6 +2500,24 @@ "work_dir_golden": "target/llm-runs/basics/t_007_crud/csharp/server/golden", "work_dir_llm": "target/llm-runs/basics/t_007_crud/csharp/server/gpt-5/llm", "scorer_details": { + "crud_total_count_one": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM User" + } + }, + "crud_row_id2_deleted": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 0, + "expected": 0, + "sql": "SELECT COUNT(*) AS n FROM User WHERE Id=2" + } + }, "schema_parity": { "pass": true, "partial": 1.0, @@ -2617,7 +2526,7 @@ "llm_db": "basics-t-007-crud-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } @@ -2651,23 +2560,23 @@ "llm_out": "Id | Name | Age | Active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", "query": "SELECT Id, Name, Age, Active FROM User WHERE Id=1", "reducer": "Crud", - "server": "http://127.0.0.1:34379" + "server": "http://127.0.0.1:41045" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:59:29.414134061Z", - "finished_at": "2026-01-27T20:00:06.267814536Z" + "started_at": "2026-01-23T20:19:29.508011285Z", + "finished_at": "2026-01-23T20:20:17.519940667Z" }, "t_008_index_lookup": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_008_index_lookup", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial class User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Table(Name = \"Result\")]\n public partial class Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n }\n\n [SpacetimeDB.Reducer]\n public static void LookupUserName(ReducerContext ctx, int id)\n {\n var user = ctx.Db.User.Id.Find(id);\n if (user != null)\n {\n ctx.Db.Result.Insert(new Result { Id = user.Id, Name = user.Name });\n }\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial class User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name = \"\";\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Table(Name = \"Result\")]\n public partial class Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name = \"\";\n }\n\n [SpacetimeDB.Reducer]\n public static void LookupUserName(ReducerContext ctx, int id)\n {\n if (ctx.Db.User.Id.Find(id) is User u)\n {\n ctx.Db.Result.Insert(new Result { Id = u.Id, Name = u.Name });\n }\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-008-index-lookup-golden", @@ -2675,22 +2584,6 @@ "work_dir_golden": "target/llm-runs/basics/t_008_index_lookup/csharp/server/golden", "work_dir_llm": "target/llm-runs/basics/t_008_index_lookup/csharp/server/gpt-5/llm", "scorer_details": { - "index_lookup_projection_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "args": [ - 1 - ], - "golden_db": "basics-t-008-index-lookup-golden", - "golden_out": "Id | Name ----+--------- 1 | \"Alice\"", - "llm_db": "basics-t-008-index-lookup-gpt-5-llm", - "llm_out": "Id | Name ----+--------- 1 | \"Alice\"", - "query": "SELECT Id, Name FROM Result WHERE Id=1", - "reducer": "LookupUserName", - "server": "http://127.0.0.1:34379" - } - }, "schema_parity": { "pass": true, "partial": 1.0, @@ -2699,7 +2592,7 @@ "llm_db": "basics-t-008-index-lookup-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } @@ -2710,21 +2603,37 @@ "notes": { "sql": "INSERT INTO User(Id, Name, Age, Active) VALUES (1, 'Alice', 30, true)" } + }, + "index_lookup_projection_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "args": [ + 1 + ], + "golden_db": "basics-t-008-index-lookup-golden", + "golden_out": "Id | Name ----+--------- 1 | \"Alice\"", + "llm_db": "basics-t-008-index-lookup-gpt-5-llm", + "llm_out": "Id | Name ----+--------- 1 | \"Alice\"", + "query": "SELECT Id, Name FROM Result WHERE Id=1", + "reducer": "LookupUserName", + "server": "http://127.0.0.1:41045" + } } }, "vendor": "openai", - "started_at": "2026-01-27T20:00:17.332669093Z", - "finished_at": "2026-01-27T20:00:55.597420674Z" + "started_at": "2026-01-23T20:20:58.944081428Z", + "finished_at": "2026-01-23T20:21:57.704447793Z" }, "t_009_init": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_009_init", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 4, "passed_tests": 4, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer(ReducerKind.Init)]\n public static void Init(ReducerContext ctx)\n {\n ctx.Db.User.Insert(new User { Id = 1, Name = \"Alice\", Age = 30, Active = true });\n ctx.Db.User.Insert(new User { Id = 2, Name = \"Bob\", Age = 22, Active = false });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer(SpacetimeDB.ReducerKind.Init)]\n public static void Init(SpacetimeDB.ReducerContext ctx)\n {\n ctx.Db.User.Insert(new User { Id = 1, Name = \"Alice\", Age = 30, Active = true });\n ctx.Db.User.Insert(new User { Id = 2, Name = \"Bob\", Age = 22, Active = false });\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-009-init-golden", @@ -2732,17 +2641,13 @@ "work_dir_golden": "target/llm-runs/basics/t_009_init/csharp/server/golden", "work_dir_llm": "target/llm-runs/basics/t_009_init/csharp/server/gpt-5/llm", "scorer_details": { - "schema_parity": { + "init_total_two": { "pass": true, "partial": 1.0, "notes": { - "golden_db": "basics-t-009-init-golden", - "llm_db": "basics-t-009-init-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:34379", - "tables_diff": null, - "tables_equal": true + "actual": 2, + "expected": 2, + "sql": "SELECT COUNT(*) AS n FROM User" } }, "init_seed_bob": { @@ -2763,22 +2668,26 @@ "sql": "SELECT COUNT(*) AS n FROM User WHERE Id=1 AND Name='Alice' AND Age=30 AND Active=true" } }, - "init_total_two": { + "schema_parity": { "pass": true, "partial": 1.0, "notes": { - "actual": 2, - "expected": 2, - "sql": "SELECT COUNT(*) AS n FROM User" + "golden_db": "basics-t-009-init-golden", + "llm_db": "basics-t-009-init-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41045", + "tables_diff": null, + "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:59:39.007990909Z", - "finished_at": "2026-01-27T20:00:10.594272918Z" + "started_at": "2026-01-23T20:19:36.893890047Z", + "finished_at": "2026-01-23T20:20:12.029514649Z" }, "t_010_connect": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_010_connect", "lang": "csharp", "golden_published": true, @@ -2801,25 +2710,25 @@ "llm_db": "basics-t-010-connect-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:59:08.068058110Z", - "finished_at": "2026-01-27T19:59:45.341706421Z" + "started_at": "2026-01-23T20:19:23.574032624Z", + "finished_at": "2026-01-23T20:20:05.908027898Z" }, "t_011_helper_function": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_011_helper_function", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Result\")]\n public partial struct Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public int Sum;\n }\n\n public static int Add(int a, int b)\n {\n return a + b;\n }\n\n [SpacetimeDB.Reducer]\n public static void ComputeSum(ReducerContext ctx, int id, int a, int b)\n {\n ctx.Db.Result.Insert(new Result\n {\n Id = id,\n Sum = Add(a, b),\n });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Result\", Public = true)]\n public partial struct Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public int Sum;\n }\n\n public static int Add(int a, int b)\n {\n return a + b;\n }\n\n [SpacetimeDB.Reducer]\n public static void ComputeSum(ReducerContext ctx, int id, int a, int b)\n {\n ctx.Db.Result.Insert(new Result { Id = id, Sum = Add(a, b) });\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-011-helper-function-golden", @@ -2836,6 +2745,19 @@ "sql": "SELECT COUNT(*) AS n FROM Result WHERE Id=1 AND Sum=5" } }, + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "basics-t-011-helper-function-golden", + "llm_db": "basics-t-011-helper-function-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41045", + "tables_diff": null, + "tables_equal": true + } + }, "helper_func_sum_parity": { "pass": true, "partial": 1.0, @@ -2851,29 +2773,16 @@ "llm_out": "Id | Sum ----+----- 1 | 5", "query": "SELECT Id, Sum FROM Result WHERE Id=1", "reducer": "ComputeSum", - "server": "http://127.0.0.1:34379" - } - }, - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "basics-t-011-helper-function-golden", - "llm_db": "basics-t-011-helper-function-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:34379", - "tables_diff": null, - "tables_equal": true + "server": "http://127.0.0.1:41045" } } }, "vendor": "openai", - "started_at": "2026-01-27T20:00:37.824007777Z", - "finished_at": "2026-01-27T20:01:12.698364118Z" + "started_at": "2026-01-23T20:21:05.392014348Z", + "finished_at": "2026-01-23T20:21:51.189712882Z" }, "t_012_spacetime_product_type": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_012_spacetime_product_type", "lang": "csharp", "golden_published": true, @@ -2888,6 +2797,19 @@ "work_dir_golden": "target/llm-runs/schema/t_012_spacetime_product_type/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_012_spacetime_product_type/csharp/server/gpt-5/llm", "scorer_details": { + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "schema-t-012-spacetime-product-type-golden", + "llm_db": "schema-t-012-spacetime-product-type-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41045", + "tables_diff": null, + "tables_equal": true + } + }, "product_type_row_parity": { "pass": true, "partial": 1.0, @@ -2903,20 +2825,7 @@ "llm_out": "Id | Value ----+----------------------- 1 | (Left = 2, Right = 3)", "query": "SELECT Id, Value FROM Result WHERE Id=1", "reducer": "SetScore", - "server": "http://127.0.0.1:34379" - } - }, - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "schema-t-012-spacetime-product-type-golden", - "llm_db": "schema-t-012-spacetime-product-type-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:34379", - "tables_diff": null, - "tables_equal": true + "server": "http://127.0.0.1:41045" } }, "product_type_row_count": { @@ -2930,18 +2839,18 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:58:50.225754898Z", - "finished_at": "2026-01-27T19:59:29.413988946Z" + "started_at": "2026-01-23T20:18:54.161733902Z", + "finished_at": "2026-01-23T20:19:36.893826573Z" }, "t_013_spacetime_sum_type": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_013_spacetime_sum_type", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Type]\n public partial struct Circle\n {\n public int Radius;\n }\n\n [SpacetimeDB.Type]\n public partial struct Rectangle\n {\n public int Width;\n public int Height;\n }\n\n [SpacetimeDB.Type]\n public partial record Shape : TaggedEnum<(Circle Circle, Rectangle Rectangle)> { }\n\n [SpacetimeDB.Table(Name = \"Result\")]\n public partial struct Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public Shape Value;\n }\n\n [SpacetimeDB.Reducer]\n public static void SetCircle(ReducerContext ctx, int id, int radius)\n {\n ctx.Db.Result.Insert(new Result\n {\n Id = id,\n Value = new Shape.Circle(new Circle { Radius = radius })\n });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Type]\n public partial struct Circle\n {\n public int Radius;\n }\n\n [SpacetimeDB.Type]\n public partial struct Rectangle\n {\n public int Width;\n public int Height;\n }\n\n [SpacetimeDB.Type]\n public partial record Shape : TaggedEnum<(Circle Circle, Rectangle Rectangle)> { }\n\n [SpacetimeDB.Table(Name = \"Result\")]\n public partial struct Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public Shape Value;\n }\n\n [SpacetimeDB.Reducer]\n public static void SetCircle(ReducerContext ctx, int id, int radius)\n {\n var value = new Shape.Circle(new Circle { Radius = radius });\n ctx.Db.Result.Insert(new Result { Id = id, Value = value });\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-013-spacetime-sum-type-golden", @@ -2985,16 +2894,38 @@ "llm_out": "Id | Value ----+-------------------------- 1 | (Circle = (Radius = 10))", "query": "SELECT Id, Value FROM Result WHERE Id=1", "reducer": "SetCircle", - "server": "http://127.0.0.1:34379" + "server": "http://127.0.0.1:41045" + } + }, + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "schema-t-013-spacetime-sum-type-golden", + "llm_db": "schema-t-013-spacetime-sum-type-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41045", + "tables_diff": null, + "tables_equal": true + } + }, + "sum_type_row_count": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM Result WHERE Id=1" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:57:55.737450825Z", - "finished_at": "2026-01-27T19:58:46.370198569Z" + "started_at": "2026-01-23T20:17:49.057528012Z", + "finished_at": "2026-01-23T20:18:46.199910007Z" }, "t_014_elementary_columns": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_014_elementary_columns", "lang": "csharp", "golden_published": true, @@ -3017,7 +2948,7 @@ "llm_db": "schema-t-014-elementary-columns-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } @@ -3026,7 +2957,7 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `primitive`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:34379/v1/database/c2006db3efe118f9e2be4d0996245799216709f62c09af27307321501d4ca96f/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `primitive`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c200c583183a5879f79de7a06c7395893137fa8a834f830859f2ee7a4c9e10d4/sql)\n", "phase": "sql" } }, @@ -3034,17 +2965,17 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `primitive`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:34379/v1/database/c2008bda321ec5b24f06db6690e57eaa2c1b3a9bada2318accf99feb7910837d/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `primitive`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2008dfd963859de34e7ba657c3416cbcee034a702128f54b0cb0b0b03aa914f/sql)\n", "phase": "sql_golden" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:58:46.370277696Z", - "finished_at": "2026-01-27T19:59:43.681502253Z" + "started_at": "2026-01-23T20:18:46.199983893Z", + "finished_at": "2026-01-23T20:19:29.507804243Z" }, "t_015_product_type_columns": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_015_product_type_columns", "lang": "csharp", "golden_published": true, @@ -3059,17 +2990,13 @@ "work_dir_golden": "target/llm-runs/schema/t_015_product_type_columns/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_015_product_type_columns/csharp/server/gpt-5/llm", "scorer_details": { - "schema_parity": { + "product_type_columns_row_count": { "pass": true, "partial": 1.0, "notes": { - "golden_db": "schema-t-015-product-type-columns-golden", - "llm_db": "schema-t-015-product-type-columns-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:34379", - "tables_diff": null, - "tables_equal": true + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM Profile WHERE Id=1" } }, "product_type_columns_row_parity": { @@ -3083,25 +3010,29 @@ "llm_out": "Id | Home | Work | Pos ----+----------------------------------+-----------------------------------+---------------- 1 | (Street = \"1 Main\", Zip = 11111) | (Street = \"2 Broad\", Zip = 22222) | (X = 7, Y = 9)", "query": "SELECT Id, Home, Work, Pos FROM Profile WHERE Id=1", "reducer": "Seed", - "server": "http://127.0.0.1:34379" + "server": "http://127.0.0.1:41045" } }, - "product_type_columns_row_count": { + "schema_parity": { "pass": true, "partial": 1.0, "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM Profile WHERE Id=1" + "golden_db": "schema-t-015-product-type-columns-golden", + "llm_db": "schema-t-015-product-type-columns-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41045", + "tables_diff": null, + "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-27T19:58:04.285909374Z", - "finished_at": "2026-01-27T19:58:50.225511855Z" + "started_at": "2026-01-23T20:18:11.292039093Z", + "finished_at": "2026-01-23T20:18:54.161647622Z" }, "t_016_sum_type_columns": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_016_sum_type_columns", "lang": "csharp", "golden_published": true, @@ -3120,7 +3051,7 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:34379/v1/database/c200a38bd5eaec739ca1bb5f49423cf455fb484e997f330a37dbe10a2f09faac/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c200b1fbaa5b44721798298318bab63a7fcd80d50f6e47060d881bfa066b8642/sql)\n", "phase": "sql" } }, @@ -3132,7 +3063,7 @@ "llm_db": "schema-t-016-sum-type-columns-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } @@ -3141,24 +3072,24 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:34379/v1/database/c20028da21a53491f84d8895dbcf4906c6c844846426c39ae32b5fd1689a2641/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2003b0da13c17c6220fd590cdb5d23015a0e698b01b6c6ecbfd10b5aabbbf4c/sql)\n", "phase": "sql_golden" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:57:09.422528630Z", - "finished_at": "2026-01-27T19:58:04.281919840Z" + "started_at": "2026-01-23T20:16:40.802337426Z", + "finished_at": "2026-01-23T20:18:08.899029179Z" }, "t_017_scheduled_columns": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_017_scheduled_columns", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 2, "passed_tests": 1, - "llm_output": "using System;\nusing SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"TickTimer\", Scheduled = nameof(Tick), ScheduledAt = nameof(ScheduledAt))]\n public partial struct TickTimer\n {\n [SpacetimeDB.PrimaryKey]\n [SpacetimeDB.AutoInc]\n public ulong ScheduledId;\n public ScheduleAt ScheduledAt;\n }\n\n [SpacetimeDB.Reducer]\n public static void Tick(ReducerContext ctx, TickTimer _timer)\n {\n }\n\n [SpacetimeDB.Reducer(ReducerKind.Init)]\n public static void Init(ReducerContext ctx)\n {\n ctx.Db.TickTimer.Insert(new TickTimer\n {\n ScheduledAt = new ScheduleAt.Interval(TimeSpan.FromMilliseconds(50))\n });\n }\n}", + "llm_output": "using System;\nusing SpacetimeDB;\n\npublic static partial class Module\n{\n [Table(Name = \"TickTimer\", Scheduled = nameof(Tick), ScheduledAt = nameof(ScheduledAt))]\n public partial struct TickTimer\n {\n [PrimaryKey, AutoInc]\n public ulong ScheduledId;\n public ScheduleAt ScheduledAt;\n }\n\n [Reducer]\n public static void Tick(ReducerContext ctx, TickTimer timer)\n {\n // Scheduled tick handler (no-op)\n }\n\n [Reducer(ReducerKind.Init)]\n public static void Init(ReducerContext ctx)\n {\n if (ctx.Db.TickTimer.Count == 0)\n {\n ctx.Db.TickTimer.Insert(new TickTimer\n {\n ScheduledAt = new ScheduleAt.Interval(TimeSpan.FromMilliseconds(50))\n });\n }\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-017-scheduled-columns-golden", @@ -3166,14 +3097,6 @@ "work_dir_golden": "target/llm-runs/schema/t_017_scheduled_columns/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_017_scheduled_columns/csharp/server/gpt-5/llm", "scorer_details": { - "scheduled_seeded_one_row": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `tick_timer`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:34379/v1/database/c200bf2221f01a62dfa1acb5a397b4271a57cfc2f171562204bb3bcee2259214/sql)\n", - "phase": "sql" - } - }, "schema_parity": { "pass": true, "partial": 1.0, @@ -3182,18 +3105,26 @@ "llm_db": "schema-t-017-scheduled-columns-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } + }, + "scheduled_seeded_one_row": { + "pass": false, + "partial": 0.0, + "notes": { + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `tick_timer`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2000932373ef07be1f77db87f24b98a9819f6033c40da69c914e654c807ead2/sql)\n", + "phase": "sql" + } } }, "vendor": "openai", - "started_at": "2026-01-27T19:57:09.413847953Z", - "finished_at": "2026-01-27T19:57:55.737395054Z" + "started_at": "2026-01-23T20:16:40.797164170Z", + "finished_at": "2026-01-23T20:18:08.735264338Z" }, "t_018_constraints": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_018_constraints", "lang": "csharp", "golden_published": true, @@ -3208,6 +3139,19 @@ "work_dir_golden": "target/llm-runs/schema/t_018_constraints/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_018_constraints/csharp/server/gpt-5/llm", "scorer_details": { + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "schema-t-018-constraints-golden", + "llm_db": "schema-t-018-constraints-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41045", + "tables_diff": null, + "tables_equal": true + } + }, "constraints_row_parity_after_seed": { "pass": true, "partial": 1.0, @@ -3219,7 +3163,7 @@ "llm_out": "Id | Email | Name ----+-----------------+--------- 1 | \"a@example.com\" | \"Alice\"", "query": "SELECT Id, Email, Name FROM Account WHERE Id=1", "reducer": "Seed", - "server": "http://127.0.0.1:34379" + "server": "http://127.0.0.1:41045" } }, "constraints_seed_two_rows": { @@ -3246,18 +3190,18 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:57:09.410769526Z", - "finished_at": "2026-01-27T19:58:03.584746288Z" + "started_at": "2026-01-23T20:16:40.794071431Z", + "finished_at": "2026-01-23T20:18:11.291994106Z" }, "t_019_many_to_many": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_019_many_to_many", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 5, "passed_tests": 5, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int UserId;\n public string Name;\n }\n\n [SpacetimeDB.Table(Name = \"Group\")]\n public partial struct Group\n {\n [SpacetimeDB.PrimaryKey]\n public int GroupId;\n public string Title;\n }\n\n [SpacetimeDB.Table(Name = \"Membership\")]\n [SpacetimeDB.Index.BTree(Name = \"by_user\", Columns = new[] { \"UserId\" })]\n [SpacetimeDB.Index.BTree(Name = \"by_group\", Columns = new[] { \"GroupId\" })]\n public partial struct Membership\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public int UserId;\n public int GroupId;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n foreach (var m in ctx.Db.Membership.Iter())\n {\n ctx.Db.Membership.Id.Delete(m.Id);\n }\n\n foreach (var g in ctx.Db.Group.Iter())\n {\n ctx.Db.Group.GroupId.Delete(g.GroupId);\n }\n\n foreach (var u in ctx.Db.User.Iter())\n {\n ctx.Db.User.UserId.Delete(u.UserId);\n }\n\n ctx.Db.User.Insert(new User { UserId = 1, Name = \"Alice\" });\n ctx.Db.User.Insert(new User { UserId = 2, Name = \"Bob\" });\n\n ctx.Db.Group.Insert(new Group { GroupId = 10, Title = \"Admin\" });\n ctx.Db.Group.Insert(new Group { GroupId = 20, Title = \"Dev\" });\n\n ctx.Db.Membership.Insert(new Membership { Id = 1, UserId = 1, GroupId = 10 });\n ctx.Db.Membership.Insert(new Membership { Id = 2, UserId = 1, GroupId = 20 });\n ctx.Db.Membership.Insert(new Membership { Id = 3, UserId = 2, GroupId = 20 });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int UserId;\n public string Name;\n }\n\n [SpacetimeDB.Table(Name = \"Group\")]\n public partial struct Group\n {\n [SpacetimeDB.PrimaryKey]\n public int GroupId;\n public string Title;\n }\n\n [SpacetimeDB.Table(Name = \"Membership\")]\n [SpacetimeDB.Index.BTree(Name = \"by_user\", Columns = new[] { \"UserId\" })]\n [SpacetimeDB.Index.BTree(Name = \"by_group\", Columns = new[] { \"GroupId\" })]\n public partial struct Membership\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public int UserId;\n public int GroupId;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n foreach (var m in ctx.Db.Membership.Iter())\n {\n ctx.Db.Membership.Id.Delete(m.Id);\n }\n foreach (var u in ctx.Db.User.Iter())\n {\n ctx.Db.User.UserId.Delete(u.UserId);\n }\n foreach (var g in ctx.Db.Group.Iter())\n {\n ctx.Db.Group.GroupId.Delete(g.GroupId);\n }\n\n ctx.Db.User.Insert(new User { UserId = 1, Name = \"Alice\" });\n ctx.Db.User.Insert(new User { UserId = 2, Name = \"Bob\" });\n\n ctx.Db.Group.Insert(new Group { GroupId = 10, Title = \"Admin\" });\n ctx.Db.Group.Insert(new Group { GroupId = 20, Title = \"Dev\" });\n\n ctx.Db.Membership.Insert(new Membership { Id = 1, UserId = 1, GroupId = 10 });\n ctx.Db.Membership.Insert(new Membership { Id = 2, UserId = 1, GroupId = 20 });\n ctx.Db.Membership.Insert(new Membership { Id = 3, UserId = 2, GroupId = 20 });\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-019-many-to-many-golden", @@ -3265,6 +3209,19 @@ "work_dir_golden": "target/llm-runs/schema/t_019_many_to_many/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_019_many_to_many/csharp/server/gpt-5/llm", "scorer_details": { + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "schema-t-019-many-to-many-golden", + "llm_db": "schema-t-019-many-to-many-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41045", + "tables_diff": null, + "tables_equal": true + } + }, "m2m_has_2_20": { "pass": true, "partial": 1.0, @@ -3283,19 +3240,6 @@ "sql": "SELECT COUNT(*) AS n FROM Membership" } }, - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "schema-t-019-many-to-many-golden", - "llm_db": "schema-t-019-many-to-many-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:34379", - "tables_diff": null, - "tables_equal": true - } - }, "m2m_has_1_20": { "pass": true, "partial": 1.0, @@ -3316,18 +3260,18 @@ } }, "vendor": "openai", - "started_at": "2026-01-27T19:58:04.046511986Z", - "finished_at": "2026-01-27T19:58:58.263921552Z" + "started_at": "2026-01-23T20:18:08.899074821Z", + "finished_at": "2026-01-23T20:19:10.793593915Z" }, "t_020_ecs": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_020_ecs", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 5, "passed_tests": 1, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Entity\")]\n public partial struct Entity\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n }\n\n [SpacetimeDB.Table(Name = \"Position\")]\n public partial struct Position\n {\n [SpacetimeDB.PrimaryKey]\n public int EntityId;\n public int X;\n public int Y;\n }\n\n [SpacetimeDB.Table(Name = \"Velocity\")]\n public partial struct Velocity\n {\n [SpacetimeDB.PrimaryKey]\n public int EntityId;\n public int VX;\n public int VY;\n }\n\n [SpacetimeDB.Table(Name = \"NextPosition\")]\n public partial struct NextPosition\n {\n [SpacetimeDB.PrimaryKey]\n public int EntityId;\n public int X;\n public int Y;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n // Entities\n ctx.Db.Entity.Insert(new Entity { Id = 1 });\n ctx.Db.Entity.Insert(new Entity { Id = 2 });\n\n // Positions\n ctx.Db.Position.Insert(new Position { EntityId = 1, X = 0, Y = 0 });\n ctx.Db.Position.Insert(new Position { EntityId = 2, X = 10, Y = 0 });\n\n // Velocities\n ctx.Db.Velocity.Insert(new Velocity { EntityId = 1, VX = 1, VY = 0 });\n ctx.Db.Velocity.Insert(new Velocity { EntityId = 2, VX = -2, VY = 3 });\n }\n\n [SpacetimeDB.Reducer]\n public static void Step(ReducerContext ctx)\n {\n foreach (var pos in ctx.Db.Position.Iter())\n {\n var vel = ctx.Db.Velocity.EntityId.Find(pos.EntityId);\n int vx = 0, vy = 0;\n if (vel != null)\n {\n vx = vel.Value.VX;\n vy = vel.Value.VY;\n }\n\n var next = new NextPosition\n {\n EntityId = pos.EntityId,\n X = pos.X + vx,\n Y = pos.Y + vy\n };\n\n var existing = ctx.Db.NextPosition.EntityId.Find(pos.EntityId);\n if (existing != null)\n {\n ctx.Db.NextPosition.EntityId.Update(next);\n }\n else\n {\n ctx.Db.NextPosition.Insert(next);\n }\n }\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Entity\", Public = true)]\n public partial struct Entity\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n }\n\n [SpacetimeDB.Table(Name = \"Position\", Public = true)]\n public partial struct Position\n {\n [SpacetimeDB.PrimaryKey]\n public int EntityId;\n public int X;\n public int Y;\n }\n\n [SpacetimeDB.Table(Name = \"Velocity\", Public = true)]\n public partial struct Velocity\n {\n [SpacetimeDB.PrimaryKey]\n public int EntityId;\n public int VX;\n public int VY;\n }\n\n [SpacetimeDB.Table(Name = \"NextPosition\", Public = true)]\n public partial struct NextPosition\n {\n [SpacetimeDB.PrimaryKey]\n public int EntityId;\n public int X;\n public int Y;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n // Entity 1\n if (ctx.Db.Entity.Id.Find(1) is not Entity)\n {\n ctx.Db.Entity.Insert(new Entity { Id = 1 });\n }\n if (ctx.Db.Position.EntityId.Find(1) is Position p1)\n {\n p1.X = 0;\n p1.Y = 0;\n ctx.Db.Position.EntityId.Update(p1);\n }\n else\n {\n ctx.Db.Position.Insert(new Position { EntityId = 1, X = 0, Y = 0 });\n }\n if (ctx.Db.Velocity.EntityId.Find(1) is Velocity v1)\n {\n v1.VX = 1;\n v1.VY = 0;\n ctx.Db.Velocity.EntityId.Update(v1);\n }\n else\n {\n ctx.Db.Velocity.Insert(new Velocity { EntityId = 1, VX = 1, VY = 0 });\n }\n\n // Entity 2\n if (ctx.Db.Entity.Id.Find(2) is not Entity)\n {\n ctx.Db.Entity.Insert(new Entity { Id = 2 });\n }\n if (ctx.Db.Position.EntityId.Find(2) is Position p2)\n {\n p2.X = 10;\n p2.Y = 0;\n ctx.Db.Position.EntityId.Update(p2);\n }\n else\n {\n ctx.Db.Position.Insert(new Position { EntityId = 2, X = 10, Y = 0 });\n }\n if (ctx.Db.Velocity.EntityId.Find(2) is Velocity v2)\n {\n v2.VX = -2;\n v2.VY = 3;\n ctx.Db.Velocity.EntityId.Update(v2);\n }\n else\n {\n ctx.Db.Velocity.Insert(new Velocity { EntityId = 2, VX = -2, VY = 3 });\n }\n }\n\n [SpacetimeDB.Reducer]\n public static void Step(ReducerContext ctx)\n {\n foreach (var pos in ctx.Db.Position.Iter())\n {\n var vOpt = ctx.Db.Velocity.EntityId.Find(pos.EntityId);\n if (vOpt is Velocity vel)\n {\n int nx = pos.X + vel.VX;\n int ny = pos.Y + vel.VY;\n\n var npOpt = ctx.Db.NextPosition.EntityId.Find(pos.EntityId);\n if (npOpt is NextPosition np)\n {\n np.X = nx;\n np.Y = ny;\n ctx.Db.NextPosition.EntityId.Update(np);\n }\n else\n {\n ctx.Db.NextPosition.Insert(new NextPosition\n {\n EntityId = pos.EntityId,\n X = nx,\n Y = ny\n });\n }\n }\n }\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-020-ecs-golden", @@ -3335,19 +3279,19 @@ "work_dir_golden": "target/llm-runs/schema/t_020_ecs/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_020_ecs/csharp/server/gpt-5/llm", "scorer_details": { - "ecs_step_next_positions_count": { + "ecs_next_pos_entity1": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:34379/v1/database/c20015874a697116ed39e7f80d0fb9c484518ec19d2cf28ab6bbc9a525d697e0/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2005b7d5d9b2b6b33a4a581ebd8661a3b0380c077f59eee8e552ef3c67ff1b9/sql)\n", "phase": "sql" } }, - "ecs_next_pos_entity1": { + "ecs_seed_positions_count": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:34379/v1/database/c20015874a697116ed39e7f80d0fb9c484518ec19d2cf28ab6bbc9a525d697e0/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2005b7d5d9b2b6b33a4a581ebd8661a3b0380c077f59eee8e552ef3c67ff1b9/sql)\n", "phase": "sql" } }, @@ -3355,7 +3299,15 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:34379/v1/database/c20015874a697116ed39e7f80d0fb9c484518ec19d2cf28ab6bbc9a525d697e0/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2005b7d5d9b2b6b33a4a581ebd8661a3b0380c077f59eee8e552ef3c67ff1b9/sql)\n", + "phase": "sql" + } + }, + "ecs_step_next_positions_count": { + "pass": false, + "partial": 0.0, + "notes": { + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2005b7d5d9b2b6b33a4a581ebd8661a3b0380c077f59eee8e552ef3c67ff1b9/sql)\n", "phase": "sql" } }, @@ -3367,33 +3319,25 @@ "llm_db": "schema-t-020-ecs-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:34379", + "server": "http://127.0.0.1:41045", "tables_diff": null, "tables_equal": true } - }, - "ecs_seed_positions_count": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:34379/v1/database/c20015874a697116ed39e7f80d0fb9c484518ec19d2cf28ab6bbc9a525d697e0/sql)\n", - "phase": "sql" - } } }, "vendor": "openai", - "started_at": "2026-01-27T19:58:04.281975972Z", - "finished_at": "2026-01-27T19:59:08.067949434Z" + "started_at": "2026-01-23T20:18:08.902649901Z", + "finished_at": "2026-01-23T20:19:23.573927579Z" }, "t_021_multi_column_index": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "task": "t_021_multi_column_index", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 4, "passed_tests": 4, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Log\")]\n [SpacetimeDB.Index.BTree(Name = \"by_user_day\", Columns = new[] { \"UserId\", \"Day\" })]\n public partial struct Log\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public int UserId;\n public int Day;\n public string Message;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n ctx.Db.Log.Insert(new Log { Id = 1, UserId = 7, Day = 1, Message = \"a\" });\n ctx.Db.Log.Insert(new Log { Id = 2, UserId = 7, Day = 2, Message = \"b\" });\n ctx.Db.Log.Insert(new Log { Id = 3, UserId = 9, Day = 1, Message = \"c\" });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Log\")]\n [SpacetimeDB.Index.BTree(Name = \"by_user_day\", Columns = [\"UserId\", \"Day\"])]\n public partial struct Log\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public int UserId;\n public int Day;\n public string Message;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n ctx.Db.Log.Insert(new Log { Id = 1, UserId = 7, Day = 1, Message = \"a\" });\n ctx.Db.Log.Insert(new Log { Id = 2, UserId = 7, Day = 2, Message = \"b\" });\n ctx.Db.Log.Insert(new Log { Id = 3, UserId = 9, Day = 1, Message = \"c\" });\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-021-multi-column-index-golden", @@ -3401,22 +3345,26 @@ "work_dir_golden": "target/llm-runs/schema/t_021_multi_column_index/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_021_multi_column_index/csharp/server/gpt-5/llm", "scorer_details": { - "mcindex_lookup_u7_d2": { + "schema_parity": { "pass": true, "partial": 1.0, "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM Log WHERE UserId=7 AND Day=2" + "golden_db": "schema-t-021-multi-column-index-golden", + "llm_db": "schema-t-021-multi-column-index-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:41045", + "tables_diff": null, + "tables_equal": true } }, - "mcindex_seed_count": { + "mcindex_lookup_u7_d2": { "pass": true, "partial": 1.0, "notes": { - "actual": 3, - "expected": 3, - "sql": "SELECT COUNT(*) AS n FROM Log" + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM Log WHERE UserId=7 AND Day=2" } }, "mcindex_lookup_u7_d1": { @@ -3428,23 +3376,19 @@ "sql": "SELECT COUNT(*) AS n FROM Log WHERE UserId=7 AND Day=1" } }, - "schema_parity": { + "mcindex_seed_count": { "pass": true, "partial": 1.0, "notes": { - "golden_db": "schema-t-021-multi-column-index-golden", - "llm_db": "schema-t-021-multi-column-index-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:34379", - "tables_diff": null, - "tables_equal": true + "actual": 3, + "expected": 3, + "sql": "SELECT COUNT(*) AS n FROM Log" } } }, "vendor": "openai", - "started_at": "2026-01-27T19:57:09.418092225Z", - "finished_at": "2026-01-27T19:58:04.046455117Z" + "started_at": "2026-01-23T20:16:40.799865241Z", + "finished_at": "2026-01-23T20:17:49.057471707Z" } } } diff --git a/docs/llms/docs-benchmark-summary.json b/docs/llms/docs-benchmark-summary.json index bf684185512..8e7f8400b57 100644 --- a/docs/llms/docs-benchmark-summary.json +++ b/docs/llms/docs-benchmark-summary.json @@ -1,11 +1,11 @@ { "version": 1, - "generated_at": "2026-01-27T20:01:19.767Z", + "generated_at": "2026-01-23T20:21:59.670Z", "by_language": { "csharp": { "modes": { "docs": { - "hash": "e3621eaacfd5238fb514ff8c09c277ccd66170773959e5b391507110bf3ac17b", + "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", "models": { "GPT-5": { "categories": { @@ -42,7 +42,7 @@ "rust": { "modes": { "docs": { - "hash": "d1bf0b033db905c668d016082c762eb4b91edd1299f7b8d4bcc6def5398610f9", + "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", "models": { "GPT-5": { "categories": { @@ -56,53 +56,53 @@ }, "schema": { "tasks": 10, - "total_tests": 32, - "passed_tests": 8, - "pass_pct": 25.0, - "task_pass_equiv": 2.05, - "task_pass_pct": 20.5 + "total_tests": 14, + "passed_tests": 0, + "pass_pct": 0.0, + "task_pass_equiv": 0.0, + "task_pass_pct": 0.0 } }, "totals": { "tasks": 22, - "total_tests": 59, - "passed_tests": 13, - "pass_pct": 22.033897, - "task_pass_equiv": 3.3833334, - "task_pass_pct": 15.378788 + "total_tests": 41, + "passed_tests": 5, + "pass_pct": 12.195122, + "task_pass_equiv": 1.3333334, + "task_pass_pct": 6.060606 } } } }, "rustdoc_json": { - "hash": "2a0f4ec42cac03fb3da542793b311e4b399845c688bb0660a6c231c82e96c56a", + "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "models": { "GPT-5": { "categories": { "basics": { "tasks": 12, "total_tests": 27, - "passed_tests": 26, - "pass_pct": 96.296295, - "task_pass_equiv": 11.0, - "task_pass_pct": 91.66667 + "passed_tests": 25, + "pass_pct": 92.59259, + "task_pass_equiv": 10.0, + "task_pass_pct": 83.33333 }, "schema": { "tasks": 10, "total_tests": 34, - "passed_tests": 23, - "pass_pct": 67.64706, - "task_pass_equiv": 6.5333333, - "task_pass_pct": 65.33333 + "passed_tests": 26, + "pass_pct": 76.47059, + "task_pass_equiv": 7.5333333, + "task_pass_pct": 75.333336 } }, "totals": { "tasks": 22, "total_tests": 61, - "passed_tests": 49, - "pass_pct": 80.327866, - "task_pass_equiv": 17.533335, - "task_pass_pct": 79.696976 + "passed_tests": 51, + "pass_pct": 83.60656, + "task_pass_equiv": 17.533333, + "task_pass_pct": 79.69697 } } } diff --git a/modules/module-test/src/lib.rs b/modules/module-test/src/lib.rs index a5b59720cfd..433796e5b60 100644 --- a/modules/module-test/src/lib.rs +++ b/modules/module-test/src/lib.rs @@ -206,7 +206,7 @@ impl Foo<'_> { #[spacetimedb::view(name = my_player, public)] fn my_player(ctx: &ViewContext) -> Option { - ctx.db.player().identity().find(ctx.sender) + ctx.db.player().identity().find(ctx.sender()) } // ───────────────────────────────────────────────────────────────────────────── @@ -267,7 +267,7 @@ fn log_module_identity(ctx: &ReducerContext) { #[spacetimedb::reducer] pub fn test(ctx: &ReducerContext, arg: TestAlias, arg2: TestB, arg3: TestC, arg4: TestF) -> anyhow::Result<()> { log::info!("BEGIN"); - log::info!("sender: {:?}", ctx.sender); + log::info!("sender: {:?}", ctx.sender()); log::info!("timestamp: {:?}", ctx.timestamp); log::info!("bar: {:?}", arg2.foo); @@ -468,7 +468,7 @@ fn test_btree_index_args(ctx: &ReducerContext) { #[spacetimedb::reducer] fn assert_caller_identity_is_module_identity(ctx: &ReducerContext) { - let caller = ctx.sender; + let caller = ctx.sender(); let owner = ctx.identity(); if caller != owner { panic!("Caller {caller} is not the owner {owner}"); diff --git a/modules/sdk-test-connect-disconnect/src/lib.rs b/modules/sdk-test-connect-disconnect/src/lib.rs index c89b7af1f3c..4a733969c01 100644 --- a/modules/sdk-test-connect-disconnect/src/lib.rs +++ b/modules/sdk-test-connect-disconnect/src/lib.rs @@ -22,10 +22,10 @@ pub struct Disconnected { #[spacetimedb::reducer(client_connected)] pub fn identity_connected(ctx: &ReducerContext) { - ctx.db.connected().insert(Connected { identity: ctx.sender }); + ctx.db.connected().insert(Connected { identity: ctx.sender() }); } #[spacetimedb::reducer(client_disconnected)] pub fn identity_disconnected(ctx: &ReducerContext) { - ctx.db.disconnected().insert(Disconnected { identity: ctx.sender }); + ctx.db.disconnected().insert(Disconnected { identity: ctx.sender() }); } diff --git a/modules/sdk-test-view/src/lib.rs b/modules/sdk-test-view/src/lib.rs index 10b99a030e1..e00f64bdccc 100644 --- a/modules/sdk-test-view/src/lib.rs +++ b/modules/sdk-test-view/src/lib.rs @@ -52,10 +52,10 @@ fn delete_player(ctx: &ReducerContext, identity: Identity) { #[reducer] pub fn move_player(ctx: &ReducerContext, dx: i32, dy: i32) { - let my_player = ctx.db.player().identity().find(ctx.sender).unwrap_or_else(|| { + let my_player = ctx.db.player().identity().find(ctx.sender()).unwrap_or_else(|| { ctx.db.player().insert(Player { entity_id: 0, - identity: ctx.sender, + identity: ctx.sender(), }) }); match ctx.db.player_location().entity_id().find(my_player.entity_id) { @@ -82,7 +82,7 @@ pub fn move_player(ctx: &ReducerContext, dx: i32, dy: i32) { #[view(name = my_player, public)] fn my_player(ctx: &ViewContext) -> Option { - ctx.db.player().identity().find(ctx.sender) + ctx.db.player().identity().find(ctx.sender()) } #[view(name = my_player_and_level, public)] @@ -90,7 +90,7 @@ fn my_player_and_level(ctx: &ViewContext) -> Option { ctx.db .player() .identity() - .find(ctx.sender) + .find(ctx.sender()) .and_then(|Player { entity_id, identity }| { ctx.db .player_level() @@ -119,7 +119,7 @@ pub fn nearby_players(ctx: &ViewContext) -> Vec { ctx.db .player() .identity() - .find(ctx.sender) + .find(ctx.sender()) .and_then(|my_player| ctx.db.player_location().entity_id().find(my_player.entity_id)) .iter() .flat_map(|my_loc| { diff --git a/modules/sdk-test/src/lib.rs b/modules/sdk-test/src/lib.rs index 06778f733d5..0a6aed56358 100644 --- a/modules/sdk-test/src/lib.rs +++ b/modules/sdk-test/src/lib.rs @@ -637,25 +637,27 @@ fn delete_pk_u32_insert_pk_u32_two(ctx: &ReducerContext, n: u32, data: i32) -> a #[spacetimedb::reducer] fn insert_caller_one_identity(ctx: &ReducerContext) -> anyhow::Result<()> { - ctx.db.one_identity().insert(OneIdentity { i: ctx.sender }); + ctx.db.one_identity().insert(OneIdentity { i: ctx.sender() }); Ok(()) } #[spacetimedb::reducer] fn insert_caller_vec_identity(ctx: &ReducerContext) -> anyhow::Result<()> { - ctx.db.vec_identity().insert(VecIdentity { i: vec![ctx.sender] }); + ctx.db.vec_identity().insert(VecIdentity { i: vec![ctx.sender()] }); Ok(()) } #[spacetimedb::reducer] fn insert_caller_unique_identity(ctx: &ReducerContext, data: i32) -> anyhow::Result<()> { - ctx.db.unique_identity().insert(UniqueIdentity { i: ctx.sender, data }); + ctx.db + .unique_identity() + .insert(UniqueIdentity { i: ctx.sender(), data }); Ok(()) } #[spacetimedb::reducer] fn insert_caller_pk_identity(ctx: &ReducerContext, data: i32) -> anyhow::Result<()> { - ctx.db.pk_identity().insert(PkIdentity { i: ctx.sender, data }); + ctx.db.pk_identity().insert(PkIdentity { i: ctx.sender(), data }); Ok(()) } diff --git a/smoketests/tests/rls.py b/smoketests/tests/rls.py index 264f373c479..102c3378a9e 100644 --- a/smoketests/tests/rls.py +++ b/smoketests/tests/rls.py @@ -19,7 +19,7 @@ class Rls(Smoketest): #[spacetimedb::reducer] pub fn add_user(ctx: &ReducerContext, name: String) { - ctx.db.users().insert(Users { name, identity: ctx.sender }); + ctx.db.users().insert(Users { name, identity: ctx.sender() }); } """ @@ -88,7 +88,7 @@ class DisconnectRls(Smoketest): #[spacetimedb::reducer] pub fn add_user(ctx: &ReducerContext, name: String) { - ctx.db.users().insert(Users { name, identity: ctx.sender }); + ctx.db.users().insert(Users { name, identity: ctx.sender() }); } """ diff --git a/smoketests/tests/views.py b/smoketests/tests/views.py index e9d264ffbc7..23b29541789 100644 --- a/smoketests/tests/views.py +++ b/smoketests/tests/views.py @@ -609,12 +609,12 @@ class SubscribeViews(Smoketest): #[spacetimedb::view(name = my_player, public)] pub fn my_player(ctx: &ViewContext) -> Option { - ctx.db.player_state().identity().find(ctx.sender) + ctx.db.player_state().identity().find(ctx.sender()) } #[spacetimedb::reducer] pub fn insert_player(ctx: &ReducerContext, name: String) { - ctx.db.player_state().insert(PlayerState { name, identity: ctx.sender }); + ctx.db.player_state().insert(PlayerState { name, identity: ctx.sender() }); } """ diff --git a/smoketests/tests/zz_docker.py b/smoketests/tests/zz_docker.py index 86816383114..bcfdef16a73 100644 --- a/smoketests/tests/zz_docker.py +++ b/smoketests/tests/zz_docker.py @@ -112,14 +112,14 @@ class DockerRestartAutoDisconnect(Smoketest): #[spacetimedb::reducer(client_connected)] fn on_connect(ctx: &ReducerContext) { ctx.db.connected_client().insert(ConnectedClient { - identity: ctx.sender, + identity: ctx.sender(), connection_id: ctx.connection_id.expect("sender connection id unset"), }); } #[spacetimedb::reducer(client_disconnected)] fn on_disconnect(ctx: &ReducerContext) { - let sender_identity = &ctx.sender; + let sender_identity = &ctx.sender(); let sender_connection_id = ctx.connection_id.as_ref().expect("sender connection id unset"); let match_client = |row: &ConnectedClient| { &row.identity == sender_identity && &row.connection_id == sender_connection_id diff --git a/templates/chat-console-rs/spacetimedb/src/lib.rs b/templates/chat-console-rs/spacetimedb/src/lib.rs index de77f34bde2..d00949f5858 100644 --- a/templates/chat-console-rs/spacetimedb/src/lib.rs +++ b/templates/chat-console-rs/spacetimedb/src/lib.rs @@ -26,8 +26,8 @@ fn validate_name(name: String) -> Result { #[spacetimedb::reducer] pub fn set_name(ctx: &ReducerContext, name: String) -> Result<(), String> { let name = validate_name(name)?; - if let Some(user) = ctx.db.user().identity().find(ctx.sender) { - log::info!("User {} sets name to {name}", ctx.sender); + if let Some(user) = ctx.db.user().identity().find(ctx.sender()) { + log::info!("User {} sets name to {name}", ctx.sender()); ctx.db.user().identity().update(User { name: Some(name), ..user @@ -52,9 +52,9 @@ pub fn send_message(ctx: &ReducerContext, text: String) -> Result<(), String> { // - Rate-limit messages per-user. // - Reject messages from unnamed user. let text = validate_message(text)?; - log::info!("User {}: {text}", ctx.sender); + log::info!("User {}: {text}", ctx.sender()); ctx.db.message().insert(Message { - sender: ctx.sender, + sender: ctx.sender(), text, sent: ctx.timestamp, }); @@ -67,7 +67,7 @@ pub fn init(_ctx: &ReducerContext) {} #[spacetimedb::reducer(client_connected)] pub fn identity_connected(ctx: &ReducerContext) { - if let Some(user) = ctx.db.user().identity().find(ctx.sender) { + if let Some(user) = ctx.db.user().identity().find(ctx.sender()) { // If this is a returning user, i.e. we already have a `User` with this `Identity`, // set `online: true`, but leave `name` and `identity` unchanged. ctx.db.user().identity().update(User { online: true, ..user }); @@ -76,7 +76,7 @@ pub fn identity_connected(ctx: &ReducerContext) { // which is online, but hasn't set a name. ctx.db.user().insert(User { name: None, - identity: ctx.sender, + identity: ctx.sender(), online: true, }); } @@ -84,11 +84,11 @@ pub fn identity_connected(ctx: &ReducerContext) { #[spacetimedb::reducer(client_disconnected)] pub fn identity_disconnected(ctx: &ReducerContext) { - if let Some(user) = ctx.db.user().identity().find(ctx.sender) { + if let Some(user) = ctx.db.user().identity().find(ctx.sender()) { ctx.db.user().identity().update(User { online: false, ..user }); } else { // This branch should be unreachable, // as it doesn't make sense for a client to disconnect without connecting first. - log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender); + log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender()); } } From 42bdd9832e934b98953c966235e05faaa922c6d3 Mon Sep 17 00:00:00 2001 From: clockwork-labs-bot Date: Mon, 26 Jan 2026 19:42:31 +0000 Subject: [PATCH 02/18] Update LLM benchmark results --- docs/llms/docs-benchmark-analysis.md | 633 +++++------ docs/llms/docs-benchmark-comment.md | 16 +- docs/llms/docs-benchmark-details.json | 1435 ++++++++++++------------- docs/llms/docs-benchmark-summary.json | 62 +- 4 files changed, 1037 insertions(+), 1109 deletions(-) diff --git a/docs/llms/docs-benchmark-analysis.md b/docs/llms/docs-benchmark-analysis.md index fe284ef576a..f2f69378b8e 100644 --- a/docs/llms/docs-benchmark-analysis.md +++ b/docs/llms/docs-benchmark-analysis.md @@ -4,338 +4,312 @@ Generated from: `/__w/SpacetimeDB/SpacetimeDB/tools/xtask-llm-benchmark/../../do ## Summary -- **Total failures analyzed**: 31 +- **Total failures analyzed**: 33 --- # Analysis of SpacetimeDB Benchmark Test Failures -## Rust / rustdoc_json Failures - -### Compile/Publish Errors (3 Failures) - -#### 1. **t_002_scheduled_table** -- **Generated Code**: - ```rust - #[table(name = tick_timer, schedule(column = scheduled_at, reducer = tick))] - pub struct TickTimer { - #[primary_key] - #[auto_inc] - scheduled_id: u64, - scheduled_at: ScheduleAt, - } - ``` - -- **Golden Example**: - ```rust - #[table(name = tick_timer, scheduled(tick))] - pub struct TickTimer { - #[primary_key] - #[auto_inc] - pub scheduled_id: u64, - pub scheduled_at: ScheduleAt, - } - ``` +This document analyzes the SpacetimeDB benchmark test failures organized by language and mode. Each section addresses specific failures, providing insights into their causes and recommending actionable solutions. -- **Error**: `publish_error: spacetime publish failed (exit=1)` +## Rust / rustdoc_json Failures -- **Explanation**: - The LLM used incorrect syntax for the `scheduled` attribute. It should be `scheduled(tick)` instead of `schedule(column = scheduled_at, reducer = tick)`. +### Compile/Publish Errors + +#### t_002_scheduled_table & t_017_scheduled_columns + +1. **The generated code**: + ```rust + use spacetimedb::{table, reducer, ReducerContext, Table, ScheduleAt}; + + #[table(name = tick_timer, scheduled(reducer = tick, column = scheduled_at))] + pub struct TickTimer { + #[primary_key] + #[auto_inc] + scheduled_id: u64, + scheduled_at: ScheduleAt, + } + + #[reducer(init)] + pub fn init(ctx: &ReducerContext) { + ctx.db.tick_timer().insert(TickTimer { + scheduled_id: 0, + scheduled_at: ScheduleAt::repeat_micros(50_000), + }); + } + + #[reducer] + pub fn tick(_ctx: &ReducerContext, _row: TickTimer) { + } + ``` + +2. **The golden example**: + ```rust + use spacetimedb::{reducer, table, ReducerContext, ScheduleAt, Table}; + use std::time::Duration; + + #[table(name = tick_timer, scheduled(tick))] + pub struct TickTimer { + #[primary_key] + #[auto_inc] + pub scheduled_id: u64, + pub scheduled_at: ScheduleAt, + } + + #[reducer] + pub fn tick(_ctx: &ReducerContext, _schedule: TickTimer) { + } + + #[reducer(init)] + pub fn init(ctx: &ReducerContext) { + let every_50ms: ScheduleAt = Duration::from_millis(50).into(); + ctx.db.tick_timer().insert(TickTimer { + scheduled_id: 0, + scheduled_at: every_50ms, + }); + } + ``` + +3. **The error**: + - `publish_error: spacetime publish failed (exit=1)` + +4. **Explain the difference**: + - The LLM generated code uses `ScheduleAt::repeat_micros(50_000)` while the expected code uses `ScheduleAt::Interval(Duration::from_millis(50).into())`. + - The `scheduled` attribute is incorrectly set. + +5. **Root cause**: + - The documentation lacks clear guidance on using the `ScheduleAt` type effectively and the format for specifying scheduled actions. + +6. **Recommendation**: + - Update documentation to clarify how to define timing for scheduled entries, using `ScheduleAt::Interval` instead of `ScheduleAt::repeat_*` methods. -- **Root Cause**: The documentation may not clearly explain the syntax for the `scheduled` attribute. +### Compile/Publish Errors (3 Failures) -- **Recommendation**: Update documentation to emphasize that the `scheduled` attribute must be structured as `scheduled(reducer_name)`. +#### t_003_struct_in_table + +1. **The generated code**: + ```rust + use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType}; + + #[derive(SpacetimeType)] + pub struct Position { + x: i32, + y: i32, + } + + #[table(name = entity)] + pub struct Entity { + #[primary_key] + id: i32, + pos: Position, + } + + #[reducer] + pub fn add_entity(ctx: &ReducerContext, id: i32, x: i32, y: i32) { + ctx.db.entity().insert(Entity { id, pos: Position { x, y } }); + } + ``` + +2. **The golden example**: + ```rust + use spacetimedb::{table, SpacetimeType}; + + #[derive(SpacetimeType, Clone, Debug)] + pub struct Position { + pub x: i32, + pub y: i32, + } + + #[table(name = entity)] + pub struct Entity { + #[primary_key] + pub id: i32, + pub pos: Position, + } + ``` + +3. **The error**: + - `schema_parity: reducers differ - expected [], got ["add_entity()"]` + +4. **Explain the difference**: + - The expected code does not include any reducers, while the generated code has an unnecessary `add_entity` reducer. + +5. **Root cause**: + - Misrepresentation of structural requirements regarding reducers in the schema. + +6. **Recommendation**: + - Update the documentation to clarify when reducers should or should not be defined for schema parity. --- -#### 2. **t_003_struct_in_table** -- **Generated Code**: - ```rust - #[spacetimedb::table(name = entity)] - pub struct Entity { - #[primary_key] - id: i32, - pos: Position, - } - ``` - -- **Golden Example**: - ```rust - #[table(name = entity)] - pub struct Entity { - #[primary_key] - pub id: i32, - pub pos: Position, - } - ``` - -- **Error**: `publish_error: spacetime publish failed (exit=1)` - -- **Explanation**: - The LLM did not use `pub` for struct fields which is required for visibility in SpacetimeDB. - -- **Root Cause**: The visibility rules for struct fields in Rust may need clearer explanation in the documentation. - -- **Recommendation**: Include specific examples indicating that all fields in SpacetimeDB tables should be public. +#### t_018_constraints + +1. **The generated code**: + ```rust + use spacetimedb::{table, reducer, ReducerContext, Table}; + + #[table(name = account, index(name = by_name, btree(columns = [name])))] + pub struct Account { + #[primary_key] + id: i32, + #[unique] + email: String, + name: String, + } + + #[reducer] + pub fn seed(ctx: &ReducerContext) { + let t = ctx.db.account(); + t.insert(Account { id: 1, email: "a@example.com".to_string(), name: "Alice".to_string() }); + t.insert(Account { id: 2, email: "b@example.com".to_string(), name: "Bob".to_string() }); + } + ``` + +2. **The golden example**: + ```rust + use spacetimedb::{reducer, table, ReducerContext, Table}; + + #[table( + name = account, + index(name = by_name, btree(columns = [name])) + )] + pub struct Account { + #[primary_key] + pub id: i32, + #[unique] + pub email: String, + pub name: String, + } + + #[reducer] + pub fn seed(ctx: &ReducerContext) { + ctx.db.account().insert(Account { id: 1, email: "a@example.com".into(), name: "Alice".into() }); + ctx.db.account().insert(Account { id: 2, email: "b@example.com".into(), name: "Bob".into() }); + } + ``` + +3. **The error**: + - `constraints_row_parity_after_seed: spacetime sql failed: no such table: 'account'` + +4. **Explain the difference**: + - The generated code did not include the `pub` keyword in front of fields, which results in private access. + +5. **Root cause**: + - Lack of explicit guidelines on visibility modifiers for database fields and schema definition. + +6. **Recommendation**: + - Update the documentation to emphasize that struct fields in database models must be public. --- -#### 3. **t_017_scheduled_columns** -- **Generated Code**: - ```rust - #[reducer(init)] - pub fn init(ctx: &ReducerContext) { - if ctx.db.tick_timer().count() == 0 { - ctx.db.tick_timer().insert(TickTimer { - scheduled_id: 0, - scheduled_at: ScheduleAt::repeat_micros(50_000), - }); - } - } - ``` - -- **Golden Example**: - ```rust - #[reducer(init)] - pub fn init(ctx: &ReducerContext) { - let every_50ms: ScheduleAt = Duration::from_millis(50).into(); - ctx.db.tick_timer().insert(TickTimer { - scheduled_id: 0, - scheduled_at: every_50ms, - }); - } - ``` - -- **Error**: `publish_error: spacetime publish failed (exit=1)` - -- **Explanation**: The method for initializing `scheduled_at` is incorrect. Instead of using `repeat_micros()`, the code should convert a `Duration` to `ScheduleAt`. - -- **Root Cause**: Misunderstanding of the proper way to initialize scheduled columns could be reflected in lacking documentation details. - -- **Recommendation**: Clarify the documentation regarding initializing `ScheduleAt`, emphasizing conversion from `Duration`. - ---- - -### Other Failures (2 Failures) - -#### 4. **t_016_sum_type_columns** -- **Generated Code**: - ```rust - #[spacetimedb::table(name = drawing)] - pub struct Drawing { - #[primary_key] - id: i32, - a: Shape, - b: Shape, - } - ``` - -- **Golden Example**: - ```rust - #[table(name = drawing)] - pub struct Drawing { - #[primary_key] - pub id: i32, - pub a: Shape, - pub b: Shape, - } - ``` - -- **Error**: Errors regarding tables not found. - -- **Explanation**: Missing the `pub` attribute on struct fields results in failure to compile. - -- **Root Cause**: Lack of clarity on the use of visibility attributes (`pub`) in struct definitions. - -- **Recommendation**: Revise documentation to instruct that fields must be public to work within SpacetimeDB. - ---- - -#### 5. **t_020_ecs** -- **Generated Code**: - ```rust - #[spacetimedb::table(name = entity)] - pub struct Entity { - #[primary_key] - id: i32, - } - - #[spacetimedb::table(name = position)] - pub struct Position { - #[primary_key] - entity_id: i32, - x: i32, - y: i32, - } - ``` - -- **Golden Example**: - ```rust - #[table(name = entity)] - pub struct Entity { - #[primary_key] - pub id: i32, - } - - #[table(name = position)] - pub struct Position { - #[primary_key] - pub entity_id: i32, - pub x: i32, - pub y: i32, - } - ``` - -- **Error**: Errors regarding tables not found. - -- **Explanation**: Missing the `pub` attribute leads to the struct not being properly registered with SpacetimeDB. - -- **Root Cause**: Similar to previous errors, the need for public access to struct fields is unclear. - -- **Recommendation**: Ensure documentation explicitly states that public access is necessary for all fields in SpacetimeDB structs. - ---- - -## Rust / docs Failures (22 total) - -### Timeout Issues (8 Failures) - -- **Failures**: Various tasks timed out, indicating potential performance or configuration issues. - -- **Root Cause**: Specifics of timeout settings and performance optimization strategies should be more explicit in the documentation. - -- **Recommendation**: Include guidelines on optimizing performance for long-running tasks or emphasize best practices for structuring queries and data handling. - ---- - -### Other Failures (14 Failures) - -#### 6. **t_000_empty_reducers** -- **Generated Code**: - ```rust - #[spacetimedb::reducer] - pub fn empty_reducer_no_args(_ctx: &spacetimedb::ReducerContext) { - } - ``` - -- **Golden Example**: - ```rust - #[reducer] - pub fn empty_reducer_no_args(ctx: &ReducerContext) -> Result<(), String> { - Ok(()) - } - ``` - -- **Error**: Schema-related errors due to missing return type and proper handling. +### Additional Recommendations -- **Explanation**: Missing return type (`Result<(), String>`) was not implemented. +1. **Documentation Clarity**: + - Ensure clear examples defining the expected syntax for all relevant SpacetimeDB features (e.g., table structure, reducer signatures). + +2. **Example Consistency**: + - Modify the examples to guarantee consistency in field access levels (public/private) across all instances. -- **Root Cause**: The documentation may not explicitly mention that reducers should return results. - -- **Recommendation**: Adjust the documentation to specify that reducer functions must include appropriate return types. +3. **Error Handling**: + - Include a section on expected error messages and discrepancies that developers should look out for, which could help in debugging similar errors effectively. --- -#### 7. **t_001_basic_tables** -- **Generated Code**: - ```rust - #[spacetimedb::table(name = user)] - pub struct User { - #[primary_key] - id: i32, - name: String, - age: i32, - active: bool, - } - ``` +## Rust / docs Failures -- **Golden Example**: - ```rust - #[table(name = user)] - pub struct User { - #[primary_key] - pub id: i32, - pub name: String, - pub age: i32, - pub active: bool, - } - ``` - -- **Error**: Schema-related errors due to missing `pub` modifiers. - -- **Explanation**: Missing public access modifiers on struct fields prevented expected behavior. +### Timeout Issues -- **Root Cause**: Visibility rules may not have been adequately covered in the documentation. - -- **Recommendation**: Ensure the documentation includes examples with visibility modifiers. +- **Failures**: t_013_spacetime_sum_type, t_015_product_type_columns, t_016_sum_type_columns, t_018_constraints, t_019_many_to_many, t_020_ecs +- **Recommendation**: + - Review the execution time of these benchmarks and possibly optimize the code for performance or provide a timeout setting for testing. --- -### C# / docs Failures (4 total) - -#### Other Failures (4 Failures) - -#### 8. **t_014_elementary_columns** -- **Generated Code**: - ```csharp - [SpacetimeDB.Table(Name = "Primitive", Public = true)] - public partial struct Primitive - { - [SpacetimeDB.PrimaryKey] - public int Id; - public int Count; - ... - } - ``` - -- **Golden Example**: - ```csharp - [Table(Name = "Primitive")] - public partial struct Primitive - { - [PrimaryKey] public int Id; - public int Count; - ... - } - ``` - -- **Error**: Table not found during sql operations. - -- **Explanation**: The `Public` attribute's use was incorrect; it's not necessary in the struct definition. - -- **Root Cause**: Confusion over the purpose and necessity of attributes. - -- **Recommendation**: Update documentation to clarify attributes' roles in table definitions, removing unnecessary ones for struct exposure. - ---- - -#### 9. **t_016_sum_type_columns** -- **Generated Code**: - ```csharp - [SpacetimeDB.Table(Name = "Drawing", Public = true)] - public partial struct Drawing - { - [SpacetimeDB.PrimaryKey] - public int Id; - } - ``` - -- **Golden Example**: - ```csharp - [Table(Name = "Drawing")] - public partial struct Drawing - { - [PrimaryKey] public int Id; - } - ``` - -- **Error**: Table not found during sql operations. - -- **Explanation**: Similar to the previous failure, the `Public` attribute was misapplied. - -- **Root Cause**: Misalignment between understood attribute requirements and actual usage. - -- **Recommendation**: Further clarification of when and where to apply attributes in C# constructs related to SpacetimeDB. +## C# / docs Failures + +### t_014_elementary_columns + +1. **The generated code**: + ```csharp + using SpacetimeDB; + + public static partial class Module + { + [SpacetimeDB.Table(Name = "Primitive", Public = true)] + public partial struct Primitive + { + [SpacetimeDB.PrimaryKey] + public int Id; + public int Count; + public long Total; + public float Price; + public double Ratio; + public bool Active; + public string Name; + } + + [SpacetimeDB.Reducer] + public static void Seed(ReducerContext ctx) + { + ctx.Db.Primitive.Insert(new Primitive + { + Id = 1, + Count = 2, + Total = 3000000000L, + Price = 1.5f, + Ratio = 2.25, + Active = true, + Name = "Alice" + }); + } + } + ``` + +2. **The golden example**: + ```csharp + using SpacetimeDB; + + public static partial class Module + { + [Table(Name = "Primitive")] + public partial struct Primitive + { + [PrimaryKey] public int Id; + public int Count; + public long Total; + public float Price; + public double Ratio; + public bool Active; + public string Name; + } + + [Reducer] + public static void Seed(ReducerContext ctx) + { + ctx.Db.Primitive.Insert(new Primitive { + Id = 1, + Count = 2, + Total = 3000000000, + Price = 1.5f, + Ratio = 2.25, + Active = true, + Name = "Alice" + }); + } + } + ``` + +3. **The error**: + - `no such table: 'primitive'` + +4. **Explain the difference**: + - The generated code has an extra public field visibility which is redundant in this context, leading to distraction. + +5. **Root cause**: + - Inconsistent handling of public annotations for struct attributes. + +6. **Recommendation**: + - Align the documentation to show proper usage of attributes and visibility appropriately. --- @@ -351,47 +325,4 @@ Generated from: `/__w/SpacetimeDB/SpacetimeDB/tools/xtask-llm-benchmark/../../do } ``` -- **Golden Example**: - ```csharp - [Table(Name = "TickTimer", Scheduled = nameof(Tick), ScheduledAt = nameof(ScheduledAt))] - public partial struct TickTimer - { - [PrimaryKey, AutoInc] public ulong ScheduledId; - public ScheduleAt ScheduledAt; - } - ``` - -- **Error**: Table not found during sql operations. - -- **Explanation**: The field definitions and relationships were incorrectly configured. - -- **Root Cause**: Possible gaps in documentation regarding definitions of scheduled columns and expected real structures. - -- **Recommendation**: Revise documentation to ensure clear expectations about table configuration and proper struct setup. - ---- - -#### 11. **t_020_ecs** -- **Generated Code**: - ```csharp - [SpacetimeDB.Table(Name = "Entity", Public = true)] - public partial struct Entity { [SpacetimeDB.PrimaryKey] public int Id; } - ``` - -- **Golden Example**: - ```csharp - [Table(Name = "Entity")] - public partial struct Entity { [PrimaryKey] public int Id; } - ``` - -- **Error**: Errors related to missing tables. - -- **Explanation**: Public attributes were misused in creating struct definitions for the tables. - -- **Root Cause**: Attribute usage may be causing confusion in use cases. - -- **Recommendation**: Ensure documentation includes proper usage guidelines for attributes in defining entities. - ---- - -By addressing the aforementioned discrepancies and gaps in documentation, developers can improve their implementation of SpacetimeDB, leading to smoother integrations and reduced error rates during execution. +This analysis serves to highlight the discrepancies noted in the benchmark test failures across Rust and C#, with actionable steps to amend recurring issues. Essential areas of improvement focus on explicit documentation, consistent field access levels, and clearer definitions of API requirements. By implementing these recommendations, we can streamline the development process and avoid common pitfalls. diff --git a/docs/llms/docs-benchmark-comment.md b/docs/llms/docs-benchmark-comment.md index 37272389e0d..907eb0e9b50 100644 --- a/docs/llms/docs-benchmark-comment.md +++ b/docs/llms/docs-benchmark-comment.md @@ -2,16 +2,16 @@ | Language | Mode | Category | Tests Passed | Task Pass % | |----------|------|----------|--------------|-------------| -| Rust | rustdoc_json | basics | 25/27 | 83.3% ⬆️ +9.0% | -| Rust | rustdoc_json | schema | 26/34 | 75.3% ⬆️ +10.0% | -| Rust | rustdoc_json | **total** | 51/61 | **79.7%** ⬆️ +9.5% | +| Rust | rustdoc_json | basics | 25/27 | 83.3% ⬆️ +6.9% | +| Rust | rustdoc_json | schema | 24/34 | 68.7% ⬇️ -6.7% | +| Rust | rustdoc_json | **total** | 49/61 | **76.7%** ⬆️ +0.8% | | Rust | docs | basics | 5/27 | 11.1% | -| Rust | docs | schema | 0/14 | 0.0% ⬇️ -20.5% | -| Rust | docs | **total** | 5/41 | **6.1%** ⬇️ -9.3% | +| Rust | docs | schema | 4/18 | 12.5% ⬇️ -8.0% | +| Rust | docs | **total** | 9/45 | **11.7%** ⬇️ -3.6% | | C# | docs | basics | 27/27 | 100.0% | -| C# | docs | schema | 25/34 | 73.7% | -| C# | docs | **total** | 52/61 | **88.0%** | +| C# | docs | schema | 24/32 | 70.3% ⬆️ +6.7% | +| C# | docs | **total** | 51/59 | **86.5%** ⬆️ +3.0% | _Compared against master branch baseline_ -Generated at: 2026-01-23T20:21:59.670Z +Generated at: 2026-01-26T19:41:35.586Z diff --git a/docs/llms/docs-benchmark-details.json b/docs/llms/docs-benchmark-details.json index 1a8a6449ec1..fc7a2432196 100644 --- a/docs/llms/docs-benchmark-details.json +++ b/docs/llms/docs-benchmark-details.json @@ -19,7 +19,7 @@ "model_name": "GPT-5", "total_tests": 1, "passed_tests": 1, - "llm_output": "use spacetimedb::ReducerContext;\n\n#[spacetimedb::reducer]\nfn empty_reducer_no_args(_ctx: &ReducerContext) {\n}\n\n#[spacetimedb::reducer]\nfn empty_reducer_with_int(_ctx: &ReducerContext, _count: i32) {\n}\n\n#[spacetimedb::reducer]\nfn empty_reducer_with_string(_ctx: &ReducerContext, _name: String) {\n}\n\n#[spacetimedb::reducer]\nfn empty_reducer_with_two_args(_ctx: &ReducerContext, _count: i32, _name: String) {\n}\n\n#[spacetimedb::reducer]\nfn empty_reducer_with_three_args(_ctx: &ReducerContext, _active: bool, _ratio: f32, _label: String) {\n}", + "llm_output": "use spacetimedb::ReducerContext;\n\n#[spacetimedb::reducer]\npub fn empty_reducer_no_args(_ctx: &ReducerContext) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_int(_ctx: &ReducerContext, _count: i32) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_string(_ctx: &ReducerContext, _name: String) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_two_args(_ctx: &ReducerContext, _count: i32, _name: String) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_three_args(_ctx: &ReducerContext, _active: bool, _ratio: f32, _label: String) {\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-000-empty-reducers-golden", @@ -35,15 +35,15 @@ "llm_db": "basics-t-000-empty-reducers-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:09:12.144740177Z", - "finished_at": "2026-01-23T20:09:46.065291337Z" + "started_at": "2026-01-26T19:27:52.325853523Z", + "finished_at": "2026-01-26T19:28:19.691117111Z" }, "t_001_basic_tables": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -69,15 +69,15 @@ "llm_db": "basics-t-001-basic-tables-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:09:14.464369753Z", - "finished_at": "2026-01-23T20:09:44.014749235Z" + "started_at": "2026-01-26T19:27:55.244006331Z", + "finished_at": "2026-01-26T19:28:22.209162875Z" }, "t_002_scheduled_table": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -87,7 +87,7 @@ "model_name": "GPT-5", "total_tests": 1, "passed_tests": 0, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, ScheduleAt, Table};\n\n#[table(name = tick_timer, schedule(column = scheduled_at, reducer = tick))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[reducer]\npub fn tick(_ctx: &ReducerContext) {}\n\n#[reducer(init)]\npub fn init(ctx: &ReducerContext) {\n if ctx.db.tick_timer().count() == 0 {\n ctx.db.tick_timer().insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::repeat_micros(50_000),\n });\n }\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, ScheduleAt};\n\n#[table(name = tick_timer, schedule(reducer = tick, column = scheduled_at))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[reducer(init)]\npub fn init(ctx: &ReducerContext) {\n if ctx.db.tick_timer().count() == 0 {\n ctx.db.tick_timer().insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::repeat_micros(50_000),\n });\n }\n}\n\n#[reducer]\npub fn tick(_ctx: &ReducerContext, _scheduled_id: u64) {\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-002-scheduled-table-golden", @@ -99,24 +99,24 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime publish failed (exit=1)\n--- stderr ---\n Updating crates.io index\n Locking 72 packages to latest compatible versions\n Adding generic-array v0.14.7 (available: v0.14.9)\n Adding spacetimedb v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-macro v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-sys v1.11.1 (available: v1.11.3)\n Adding spacetimedb-lib v1.11.1 (available: v1.11.3)\n Adding spacetimedb-primitives v1.11.1 (available: v1.11.3)\n Adding spacetimedb-sats v1.11.1 (available: v1.11.3)\n Compiling proc-macro2 v1.0.106\n Compiling quote v1.0.44\n Compiling unicode-ident v1.0.22\n Compiling typenum v1.19.0\n Compiling version_check v0.9.5\n Compiling autocfg v1.5.0\n Compiling serde_core v1.0.228\n Compiling heck v0.5.0\n Compiling cfg-if v1.0.4\n Compiling serde v1.0.228\n Compiling zerocopy v0.8.33\n Compiling either v1.15.0\n Compiling shlex v1.3.0\n Compiling find-msvc-tools v0.1.8\n Compiling bitflags v2.10.0\n Compiling nohash-hasher v0.2.0\n Compiling anyhow v1.0.100\n Compiling thiserror v1.0.69\n Compiling zmij v1.0.16\n Compiling keccak v0.1.5\n Compiling heck v0.4.1\n Compiling arrayvec v0.7.6\n Compiling bytes v1.11.0\n Compiling humantime v2.3.0\n Compiling convert_case v0.4.0\n Compiling itoa v1.0.17\n Compiling second-stack v0.3.5\n Compiling serde_json v1.0.149\n Compiling constant_time_eq v0.4.2\n Compiling getrandom v0.2.17\n Compiling smallvec v1.15.1\n Compiling hex v0.4.3\n Compiling cc v1.2.54\n Compiling bytemuck v1.24.0\n Compiling arrayref v0.3.9\n Compiling spacetimedb-lib v1.11.1\n Compiling itertools v0.12.1\n Compiling memchr v2.7.6\n Compiling log v0.4.29\n Compiling rand_core v0.6.4\n Compiling scoped-tls v1.0.1\n Compiling generic-array v0.14.7\n Compiling num-traits v0.2.19\n Compiling http v1.4.0\n Compiling syn v2.0.114\n Compiling approx v0.3.2\n Compiling chrono v0.4.43\n Compiling blake3 v1.8.3\n Compiling decorum v0.3.1\n Compiling block-buffer v0.10.4\n Compiling crypto-common v0.1.7\n Compiling digest v0.10.7\n Compiling sha3 v0.10.8\n Compiling ppv-lite86 v0.2.21\n Compiling rand_chacha v0.3.1\n Compiling rand v0.8.5\n Compiling ethnum v1.5.2\n Compiling enum-as-inner v0.6.1\n Compiling thiserror-impl v1.0.69\n Compiling derive_more v0.99.20\n Compiling spacetimedb-primitives v1.11.1\n Compiling spacetimedb-bindings-sys v1.11.1\n Compiling spacetimedb-bindings-macro v1.11.1\n Compiling spacetimedb-sats v1.11.1\n Compiling spacetimedb v1.11.1\n Compiling spacetime-module v0.1.0 (/__w/SpacetimeDB/SpacetimeDB/target/llm-runs/basics/t_002_scheduled_table/rust/server/gpt-5/llm)\nerror: expected one of: `public`, `private`, `name`, `index`, `scheduled`\n --> src/lib.rs:4:28\n |\n4 | #[table(name = tick_timer, schedule(column = scheduled_at, reducer = tick))]\n | ^^^^^^^^\n\nerror[E0422]: cannot find struct, variant or union type `TickTimer` in this scope\n --> src/lib.rs:18:36\n |\n18 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^ not found in this scope\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:17:15\n |\n17 | if ctx.db.tick_timer().count() == 0 {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:18:16\n |\n18 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no variant or associated item named `repeat_micros` found for enum `ScheduleAt` in the current scope\n --> src/lib.rs:20:39\n |\n20 | scheduled_at: ScheduleAt::repeat_micros(50_000),\n | ^^^^^^^^^^^^^ variant or associated item not found in `ScheduleAt`\n\nSome errors have detailed explanations: E0422, E0599.\nFor more information about an error, try `rustc --explain E0422`.\nerror: could not compile `spacetime-module` (lib) due to 5 previous errors\nError: command [\"cargo\", \"build\", \"--config=net.git-fetch-with-cli=true\", \"--target=wasm32-unknown-unknown\", \"--release\", \"--message-format=json-render-diagnostics\"] exited with code 101\n\n--- stdout ---\n", + "error": "spacetime publish failed (exit=1)\n--- stderr ---\n Updating crates.io index\n Locking 72 packages to latest compatible versions\n Adding generic-array v0.14.7 (available: v0.14.9)\n Adding spacetimedb v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-macro v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-sys v1.11.1 (available: v1.11.3)\n Adding spacetimedb-lib v1.11.1 (available: v1.11.3)\n Adding spacetimedb-primitives v1.11.1 (available: v1.11.3)\n Adding spacetimedb-sats v1.11.1 (available: v1.11.3)\n Compiling proc-macro2 v1.0.106\n Compiling quote v1.0.44\n Compiling unicode-ident v1.0.22\n Compiling typenum v1.19.0\n Compiling version_check v0.9.5\n Compiling autocfg v1.5.0\n Compiling heck v0.5.0\n Compiling serde_core v1.0.228\n Compiling cfg-if v1.0.4\n Compiling find-msvc-tools v0.1.8\n Compiling either v1.15.0\n Compiling shlex v1.3.0\n Compiling serde v1.0.228\n Compiling zerocopy v0.8.34\n Compiling thiserror v1.0.69\n Compiling bitflags v2.10.0\n Compiling nohash-hasher v0.2.0\n Compiling anyhow v1.0.100\n Compiling bytes v1.11.0\n Compiling arrayvec v0.7.6\n Compiling humantime v2.3.0\n Compiling keccak v0.1.5\n Compiling zmij v1.0.17\n Compiling heck v0.4.1\n Compiling convert_case v0.4.0\n Compiling smallvec v1.15.1\n Compiling hex v0.4.3\n Compiling second-stack v0.3.5\n Compiling constant_time_eq v0.4.2\n Compiling arrayref v0.3.9\n Compiling getrandom v0.2.17\n Compiling itertools v0.12.1\n Compiling cc v1.2.54\n Compiling itoa v1.0.17\n Compiling spacetimedb-lib v1.11.1\n Compiling serde_json v1.0.149\n Compiling rand_core v0.6.4\n Compiling bytemuck v1.24.0\n Compiling log v0.4.29\n Compiling memchr v2.7.6\n Compiling scoped-tls v1.0.1\n Compiling generic-array v0.14.7\n Compiling num-traits v0.2.19\n Compiling http v1.4.0\n Compiling syn v2.0.114\n Compiling approx v0.3.2\n Compiling chrono v0.4.43\n Compiling decorum v0.3.1\n Compiling blake3 v1.8.3\n Compiling block-buffer v0.10.4\n Compiling crypto-common v0.1.7\n Compiling digest v0.10.7\n Compiling sha3 v0.10.8\n Compiling ethnum v1.5.2\n Compiling ppv-lite86 v0.2.21\n Compiling rand_chacha v0.3.1\n Compiling rand v0.8.5\n Compiling enum-as-inner v0.6.1\n Compiling thiserror-impl v1.0.69\n Compiling derive_more v0.99.20\n Compiling spacetimedb-primitives v1.11.1\n Compiling spacetimedb-bindings-sys v1.11.1\n Compiling spacetimedb-bindings-macro v1.11.1\n Compiling spacetimedb-sats v1.11.1\n Compiling spacetimedb v1.11.1\n Compiling spacetime-module v0.1.0 (/__w/SpacetimeDB/SpacetimeDB/target/llm-runs/basics/t_002_scheduled_table/rust/server/gpt-5/llm)\nerror: expected one of: `public`, `private`, `name`, `index`, `scheduled`\n --> src/lib.rs:4:28\n |\n4 | #[table(name = tick_timer, schedule(reducer = tick, column = scheduled_at))]\n | ^^^^^^^^\n\nerror[E0422]: cannot find struct, variant or union type `TickTimer` in this scope\n --> src/lib.rs:15:36\n |\n15 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^ not found in this scope\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:14:15\n |\n14 | if ctx.db.tick_timer().count() == 0 {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:15:16\n |\n15 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no variant or associated item named `repeat_micros` found for enum `ScheduleAt` in the current scope\n --> src/lib.rs:17:39\n |\n17 | scheduled_at: ScheduleAt::repeat_micros(50_000),\n | ^^^^^^^^^^^^^ variant or associated item not found in `ScheduleAt`\n\nSome errors have detailed explanations: E0422, E0599.\nFor more information about an error, try `rustc --explain E0422`.\nerror: could not compile `spacetime-module` (lib) due to 5 previous errors\nError: command [\"cargo\", \"build\", \"--config=net.git-fetch-with-cli=true\", \"--target=wasm32-unknown-unknown\", \"--release\", \"--message-format=json-render-diagnostics\"] exited with code 101\n\n--- stdout ---\n", "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:09:35.992436277Z", - "finished_at": "2026-01-23T20:10:39.770857477Z" + "started_at": "2026-01-26T19:28:10.719260484Z", + "finished_at": "2026-01-26T19:29:24.230351153Z" }, "t_003_struct_in_table": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", "task": "t_003_struct_in_table", "lang": "rust", - "golden_published": false, + "golden_published": true, "model_name": "GPT-5", "total_tests": 1, "passed_tests": 0, - "llm_output": "use spacetimedb::ReducerContext;\n\n#[derive(spacetimedb::SpacetimeType)]\npub struct Position {\n x: i32,\n y: i32,\n}\n\n#[spacetimedb::table(name = entity)]\npub struct Entity {\n #[primary_key]\n id: i32,\n pos: Position,\n}\n\n#[spacetimedb::reducer]\npub fn add_entity(ctx: &ReducerContext, id: i32, x: i32, y: i32) {\n let pos = Position { x, y };\n ctx.db.entity().insert(Entity { id, pos });\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\npub struct Position {\n x: i32,\n y: i32,\n}\n\n#[table(name = entity)]\npub struct Entity {\n #[primary_key]\n id: i32,\n pos: Position,\n}\n\n#[reducer]\npub fn add_entity(ctx: &ReducerContext, id: i32, x: i32, y: i32) {\n ctx.db.entity().insert(Entity { id, pos: Position { x, y } });\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-003-struct-in-table-golden", @@ -124,18 +124,28 @@ "work_dir_golden": "target/llm-runs/basics/t_003_struct_in_table/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_003_struct_in_table/rust/server/gpt-5/llm", "scorer_details": { - "publish_error": { + "schema_parity": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime publish failed (exit=1)\n--- stderr ---\n Updating crates.io index\n Locking 72 packages to latest compatible versions\n Adding generic-array v0.14.7 (available: v0.14.9)\n Adding spacetimedb v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-macro v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-sys v1.11.1 (available: v1.11.3)\n Adding spacetimedb-lib v1.11.1 (available: v1.11.3)\n Adding spacetimedb-primitives v1.11.1 (available: v1.11.3)\n Adding spacetimedb-sats v1.11.1 (available: v1.11.3)\n Compiling proc-macro2 v1.0.106\n Compiling unicode-ident v1.0.22\n Compiling quote v1.0.44\n Compiling version_check v0.9.5\n Compiling typenum v1.19.0\n Compiling autocfg v1.5.0\n Compiling serde_core v1.0.228\n Compiling heck v0.5.0\n Compiling cfg-if v1.0.4\n Compiling zerocopy v0.8.33\n Compiling serde v1.0.228\n Compiling shlex v1.3.0\n Compiling either v1.15.0\n Compiling find-msvc-tools v0.1.8\n Compiling anyhow v1.0.100\n Compiling nohash-hasher v0.2.0\n Compiling bitflags v2.10.0\n Compiling thiserror v1.0.69\n Compiling bytes v1.11.0\n Compiling heck v0.4.1\n Compiling humantime v2.3.0\n Compiling zmij v1.0.16\n Compiling keccak v0.1.5\n Compiling arrayvec v0.7.6\n Compiling convert_case v0.4.0\n Compiling hex v0.4.3\n Compiling bytemuck v1.24.0\n Compiling second-stack v0.3.5\n Compiling arrayref v0.3.9\n Compiling getrandom v0.2.17\n Compiling spacetimedb-lib v1.11.1\n Compiling itoa v1.0.17\n Compiling itertools v0.12.1\n Compiling constant_time_eq v0.4.2\n Compiling smallvec v1.15.1\n Compiling serde_json v1.0.149\n Compiling log v0.4.29\n Compiling memchr v2.7.6\n Compiling rand_core v0.6.4\n Compiling scoped-tls v1.0.1\n Compiling cc v1.2.54\n Compiling generic-array v0.14.7\n Compiling num-traits v0.2.19\n Compiling http v1.4.0\n Compiling syn v2.0.114\n Compiling blake3 v1.8.3\n Compiling approx v0.3.2\n Compiling chrono v0.4.43\n Compiling decorum v0.3.1\n Compiling block-buffer v0.10.4\n Compiling crypto-common v0.1.7\n Compiling digest v0.10.7\n Compiling sha3 v0.10.8\n Compiling ppv-lite86 v0.2.21\n Compiling rand_chacha v0.3.1\n Compiling rand v0.8.5\n Compiling ethnum v1.5.2\n Compiling enum-as-inner v0.6.1\n Compiling thiserror-impl v1.0.69\n Compiling derive_more v0.99.20\n Compiling spacetimedb-primitives v1.11.1\n Compiling spacetimedb-bindings-sys v1.11.1\n Compiling spacetimedb-bindings-macro v1.11.1\n Compiling spacetimedb-sats v1.11.1\n Compiling spacetimedb v1.11.1\n Compiling spacetime-module v0.1.0 (/__w/SpacetimeDB/SpacetimeDB/target/llm-runs/basics/t_003_struct_in_table/rust/server/gpt-5/llm)\nerror[E0599]: no method named `insert` found for reference `&entity__TableHandle` in the current scope\n --> src/lib.rs:20:21\n |\n20 | ctx.db.entity().insert(Entity { id, pos });\n | ^^^^^^\n |\n = help: items from traits can only be used if the trait is in scope\nhelp: trait `Table` which provides `insert` is implemented but not in scope; perhaps you want to import it\n |\n 2 + use spacetimedb::Table;\n |\nhelp: there is a method `try_insert` with a similar name\n |\n20 | ctx.db.entity().try_insert(Entity { id, pos });\n | ++++\n\nFor more information about this error, try `rustc --explain E0599`.\nerror: could not compile `spacetime-module` (lib) due to 1 previous error\nError: command [\"cargo\", \"build\", \"--config=net.git-fetch-with-cli=true\", \"--target=wasm32-unknown-unknown\", \"--release\", \"--message-format=json-render-diagnostics\"] exited with code 101\n\n--- stdout ---\n", - "phase": "build_or_publish" + "golden_db": "basics-t-003-struct-in-table-golden", + "llm_db": "basics-t-003-struct-in-table-gpt-5-llm", + "reducers_diff": { + "only_golden": [], + "only_llm": [ + "add_entity()" + ] + }, + "reducers_equal": false, + "server": "http://127.0.0.1:44233", + "tables_diff": null, + "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:09:14.464130029Z", - "finished_at": "2026-01-23T20:09:54.314351498Z" + "started_at": "2026-01-26T19:27:53.381607365Z", + "finished_at": "2026-01-26T19:28:20.526037052Z" }, "t_004_insert": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -169,7 +179,7 @@ "llm_out": "id | name | age | active ----+---------+-----+-------- 1 | \"Alice\" | 30 | true", "query": "SELECT id, name, age, active FROM user WHERE id=1", "reducer": "insert_user", - "server": "http://127.0.0.1:41115" + "server": "http://127.0.0.1:44233" } }, "schema_parity": { @@ -180,15 +190,15 @@ "llm_db": "basics-t-004-insert-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:09:14.983974693Z", - "finished_at": "2026-01-23T20:09:35.992396086Z" + "started_at": "2026-01-26T19:28:03.162962728Z", + "finished_at": "2026-01-26T19:28:30.365311126Z" }, "t_005_update": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -198,7 +208,7 @@ "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[reducer]\npub fn update_user(ctx: &ReducerContext, id: i32, name: String, age: i32, active: bool) {\n let row = User { id, name, age, active };\n ctx.db.user().id().update(row);\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, UniqueColumn};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[reducer]\npub fn update_user(ctx: &ReducerContext, id: i32, name: String, age: i32, active: bool) {\n ctx.db.user().id().update(User { id, name, age, active });\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-005-update-golden", @@ -206,6 +216,19 @@ "work_dir_golden": "target/llm-runs/basics/t_005_update/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_005_update/rust/server/gpt-5/llm", "scorer_details": { + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "basics-t-005-update-golden", + "llm_db": "basics-t-005-update-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:44233", + "tables_diff": null, + "tables_equal": true + } + }, "seed_users_row": { "pass": true, "partial": 1.0, @@ -229,26 +252,13 @@ "llm_out": "id | name | age | active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", "query": "SELECT id, name, age, active FROM user WHERE id=1", "reducer": "update_user", - "server": "http://127.0.0.1:41115" - } - }, - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "basics-t-005-update-golden", - "llm_db": "basics-t-005-update-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:41115", - "tables_diff": null, - "tables_equal": true + "server": "http://127.0.0.1:44233" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:08:57.792213429Z", - "finished_at": "2026-01-23T20:09:53.091667873Z" + "started_at": "2026-01-26T19:27:50.273973455Z", + "finished_at": "2026-01-26T19:28:39.660285285Z" }, "t_006_delete": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -266,15 +276,6 @@ "work_dir_golden": "target/llm-runs/basics/t_006_delete/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_006_delete/rust/server/gpt-5/llm", "scorer_details": { - "delete_user_count_zero": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 0, - "expected": 0, - "sql": "SELECT COUNT(*) AS n FROM user WHERE id=1" - } - }, "schema_parity": { "pass": true, "partial": 1.0, @@ -283,11 +284,20 @@ "llm_db": "basics-t-006-delete-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } }, + "delete_user_count_zero": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 0, + "expected": 0, + "sql": "SELECT COUNT(*) AS n FROM user WHERE id=1" + } + }, "seed_users_row": { "pass": true, "partial": 1.0, @@ -297,8 +307,8 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:08:35.084889228Z", - "finished_at": "2026-01-23T20:09:14.643664761Z" + "started_at": "2026-01-26T19:27:19.862018853Z", + "finished_at": "2026-01-26T19:27:52.325711770Z" }, "t_007_crud": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -308,7 +318,7 @@ "model_name": "GPT-5", "total_tests": 4, "passed_tests": 4, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, UniqueColumn};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[reducer]\npub fn crud(ctx: &ReducerContext) {\n let users = ctx.db.user();\n\n let mut u1 = users.insert(User {\n id: 1,\n name: \"Alice\".to_string(),\n age: 30,\n active: true,\n });\n\n let _u2 = users.insert(User {\n id: 2,\n name: \"Bob\".to_string(),\n age: 22,\n active: false,\n });\n\n u1.name = \"Alice2\".to_string();\n u1.age = 31;\n u1.active = false;\n let _u1_updated = users.id().update(u1);\n\n users.id().delete(&2);\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[reducer]\npub fn crud(ctx: &ReducerContext) {\n let users = ctx.db.user();\n\n users.insert(User { id: 1, name: \"Alice\".to_string(), age: 30, active: true });\n users.insert(User { id: 2, name: \"Bob\".to_string(), age: 22, active: false });\n\n let updated = User { id: 1, name: \"Alice2\".to_string(), age: 31, active: false };\n users.id().update(updated);\n\n users.id().delete(&2);\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-007-crud-golden", @@ -325,6 +335,15 @@ "sql": "SELECT COUNT(*) AS n FROM user WHERE id=2" } }, + "crud_total_count_one": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM user" + } + }, "crud_row_id1_parity": { "pass": true, "partial": 1.0, @@ -336,16 +355,7 @@ "llm_out": "id | name | age | active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", "query": "SELECT id, name, age, active FROM user WHERE id=1", "reducer": "crud", - "server": "http://127.0.0.1:41115" - } - }, - "crud_total_count_one": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM user" + "server": "http://127.0.0.1:44233" } }, "schema_parity": { @@ -356,15 +366,15 @@ "llm_db": "basics-t-007-crud-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:08:56.057273916Z", - "finished_at": "2026-01-23T20:09:48.569368820Z" + "started_at": "2026-01-26T19:27:23.893528453Z", + "finished_at": "2026-01-26T19:28:07.775124578Z" }, "t_008_index_lookup": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -374,7 +384,7 @@ "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n name: String,\n}\n\n#[reducer]\npub fn lookup_user_name(ctx: &ReducerContext, id: i32) {\n if let Some(u) = ctx.db.user().id().find(id) {\n let User { id, name, .. } = u;\n ctx.db.result().id().delete(&id);\n ctx.db.result().insert(ResultRow { id, name });\n }\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, UniqueColumn};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n name: String,\n}\n\n#[reducer]\npub fn lookup_user_name(ctx: &ReducerContext, id: i32) {\n if let Some(user) = ctx.db.user().id().find(id) {\n let _ = ctx.db.result().id().delete(&id);\n ctx.db.result().insert(ResultRow { id: user.id, name: user.name });\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-008-index-lookup-golden", @@ -382,11 +392,17 @@ "work_dir_golden": "target/llm-runs/basics/t_008_index_lookup/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_008_index_lookup/rust/server/gpt-5/llm", "scorer_details": { - "seed_user_row": { + "schema_parity": { "pass": true, "partial": 1.0, "notes": { - "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" + "golden_db": "basics-t-008-index-lookup-golden", + "llm_db": "basics-t-008-index-lookup-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:44233", + "tables_diff": null, + "tables_equal": true } }, "index_lookup_projection_parity": { @@ -402,26 +418,20 @@ "llm_out": "id | name ----+--------- 1 | \"Alice\"", "query": "SELECT id, name FROM result WHERE id=1", "reducer": "lookup_user_name", - "server": "http://127.0.0.1:41115" + "server": "http://127.0.0.1:44233" } }, - "schema_parity": { + "seed_user_row": { "pass": true, "partial": 1.0, "notes": { - "golden_db": "basics-t-008-index-lookup-golden", - "llm_db": "basics-t-008-index-lookup-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:41115", - "tables_diff": null, - "tables_equal": true + "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:09:14.643699808Z", - "finished_at": "2026-01-23T20:09:52.566672855Z" + "started_at": "2026-01-26T19:28:01.265667865Z", + "finished_at": "2026-01-26T19:28:38.153772708Z" }, "t_009_init": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -431,7 +441,7 @@ "model_name": "GPT-5", "total_tests": 4, "passed_tests": 4, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[reducer(init)]\npub fn init(ctx: &ReducerContext) {\n let user = ctx.db.user();\n user.insert(User { id: 1, name: \"Alice\".to_string(), age: 30, active: true });\n user.insert(User { id: 2, name: \"Bob\".to_string(), age: 22, active: false });\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[spacetimedb::reducer(init)]\npub fn init(ctx: &ReducerContext) {\n let user = ctx.db.user();\n user.insert(User { id: 1, name: \"Alice\".to_string(), age: 30, active: true });\n user.insert(User { id: 2, name: \"Bob\".to_string(), age: 22, active: false });\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-009-init-golden", @@ -448,15 +458,6 @@ "sql": "SELECT COUNT(*) AS n FROM user WHERE id=2 AND name='Bob' AND age=22 AND active=false" } }, - "init_seed_alice": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM user WHERE id=1 AND name='Alice' AND age=30 AND active=true" - } - }, "schema_parity": { "pass": true, "partial": 1.0, @@ -465,7 +466,7 @@ "llm_db": "basics-t-009-init-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } @@ -478,11 +479,20 @@ "expected": 2, "sql": "SELECT COUNT(*) AS n FROM user" } + }, + "init_seed_alice": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM user WHERE id=1 AND name='Alice' AND age=30 AND active=true" + } } }, "vendor": "openai", - "started_at": "2026-01-23T20:08:57.046090650Z", - "finished_at": "2026-01-23T20:09:23.724177316Z" + "started_at": "2026-01-26T19:27:35.047568301Z", + "finished_at": "2026-01-26T19:28:10.719222494Z" }, "t_010_connect": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -492,7 +502,7 @@ "model_name": "GPT-5", "total_tests": 1, "passed_tests": 1, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = event)]\npub struct Event {\n #[primary_key]\n #[auto_inc]\n id: i32,\n kind: String,\n}\n\n#[spacetimedb::reducer(client_connected)]\npub fn client_connected(ctx: &ReducerContext) {\n let _ = ctx.db.event().insert(Event { id: 0, kind: \"connected\".to_string() });\n}\n\n#[spacetimedb::reducer(client_disconnected)]\npub fn client_disconnected(ctx: &ReducerContext) {\n let _ = ctx.db.event().insert(Event { id: 0, kind: \"disconnected\".to_string() });\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = event)]\npub struct Event {\n #[primary_key]\n #[auto_inc]\n id: i32,\n kind: String,\n}\n\n#[reducer(client_connected)]\npub fn client_connected(ctx: &ReducerContext) {\n ctx.db.event().insert(Event { id: 0, kind: \"connected\".to_string() });\n}\n\n#[reducer(client_disconnected)]\npub fn client_disconnected(ctx: &ReducerContext) {\n ctx.db.event().insert(Event { id: 0, kind: \"disconnected\".to_string() });\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-010-connect-golden", @@ -508,15 +518,15 @@ "llm_db": "basics-t-010-connect-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:08:35.620982701Z", - "finished_at": "2026-01-23T20:09:12.144710803Z" + "started_at": "2026-01-26T19:27:22.864510006Z", + "finished_at": "2026-01-26T19:28:01.265636007Z" }, "t_011_helper_function": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -526,7 +536,7 @@ "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n sum: i32,\n}\n\nfn add(a: i32, b: i32) -> i32 {\n a + b\n}\n\n#[reducer]\npub fn compute_sum(ctx: &ReducerContext, id: i32, a: i32, b: i32) {\n ctx.db.result().insert(ResultRow { id, sum: add(a, b) });\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n sum: i32,\n}\n\nfn add(a: i32, b: i32) -> i32 {\n a + b\n}\n\n#[reducer]\nfn compute_sum(ctx: &ReducerContext, id: i32, a: i32, b: i32) {\n let sum = add(a, b);\n ctx.db.result().insert(ResultRow { id, sum });\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-011-helper-function-golden", @@ -534,6 +544,37 @@ "work_dir_golden": "target/llm-runs/basics/t_011_helper_function/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_011_helper_function/rust/server/gpt-5/llm", "scorer_details": { + "helper_func_sum_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "args": [ + 1, + 2, + 3 + ], + "golden_db": "basics-t-011-helper-function-golden", + "golden_out": "id | sum ----+----- 1 | 5", + "llm_db": "basics-t-011-helper-function-gpt-5-llm", + "llm_out": "id | sum ----+----- 1 | 5", + "query": "SELECT id, sum FROM result WHERE id=1", + "reducer": "compute_sum", + "server": "http://127.0.0.1:44233" + } + }, + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "basics-t-011-helper-function-golden", + "llm_db": "basics-t-011-helper-function-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:44233", + "tables_diff": null, + "tables_equal": true + } + }, "helper_func_sum_abs": { "pass": true, "partial": 1.0, @@ -576,8 +617,8 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:09:23.724208808Z", - "finished_at": "2026-01-23T20:09:51.292524674Z" + "started_at": "2026-01-26T19:28:07.775155436Z", + "finished_at": "2026-01-26T19:28:36.996978868Z" }, "t_012_spacetime_product_type": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -587,7 +628,7 @@ "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\npub struct Score {\n left: i32,\n right: i32,\n}\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n value: Score,\n}\n\n#[reducer]\npub fn set_score(ctx: &ReducerContext, id: i32, left: i32, right: i32) {\n ctx.db.result().insert(ResultRow {\n id,\n value: Score { left, right },\n });\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\npub struct Score {\n left: i32,\n right: i32,\n}\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n value: Score,\n}\n\n#[reducer]\npub fn set_score(ctx: &ReducerContext, id: i32, left: i32, right: i32) {\n ctx.db.result().insert(ResultRow { id, value: Score { left, right } });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-012-spacetime-product-type-golden", @@ -612,7 +653,7 @@ "llm_db": "schema-t-012-spacetime-product-type-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } @@ -632,13 +673,13 @@ "llm_out": "id | value ----+----------------------- 1 | (left = 2, right = 3)", "query": "SELECT id, value FROM result WHERE id=1", "reducer": "set_score", - "server": "http://127.0.0.1:41115" + "server": "http://127.0.0.1:44233" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:08:32.450266496Z", - "finished_at": "2026-01-23T20:09:14.310539584Z" + "started_at": "2026-01-26T19:27:19.861773654Z", + "finished_at": "2026-01-26T19:27:55.243933613Z" }, "t_013_spacetime_sum_type": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -647,8 +688,8 @@ "golden_published": true, "model_name": "GPT-5", "total_tests": 3, - "passed_tests": 3, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\nstruct Rect {\n width: i32,\n height: i32,\n}\n\n#[derive(SpacetimeType)]\nenum Shape {\n Circle(i32),\n Rectangle(Rect),\n}\n\n#[table(name = result)]\nstruct ResultRow {\n #[primary_key]\n id: i32,\n value: Shape,\n}\n\n#[reducer]\nfn set_circle(ctx: &ReducerContext, id: i32, radius: i32) {\n ctx.db.result().insert(ResultRow { id, value: Shape::Circle(radius) });\n}", + "passed_tests": 2, + "llm_output": "use spacetimedb::{reducer, table, ReducerContext, SpacetimeType, Table};\n\n#[derive(SpacetimeType, Clone)]\npub struct Rect {\n width: i32,\n height: i32,\n}\n\n#[derive(SpacetimeType, Clone)]\npub enum Shape {\n Circle(i32),\n Rectangle(Rect),\n}\n\n#[table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n value: Shape,\n}\n\n#[reducer]\npub fn set_circle(ctx: &ReducerContext, id: i32, radius: i32) {\n ctx.db\n .result()\n .insert(ResultRow { id, value: Shape::Circle(radius) });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-013-spacetime-sum-type-golden", @@ -656,6 +697,14 @@ "work_dir_golden": "target/llm-runs/schema/t_013_spacetime_sum_type/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_013_spacetime_sum_type/rust/server/gpt-5/llm", "scorer_details": { + "sum_type_row_parity": { + "pass": false, + "partial": 0.0, + "notes": { + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `result`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44233/v1/database/c200d2d3b6f126b42f6535fa1c89a272d1278f24e7645295553d055f0964bb68/sql)\n", + "phase": "sql_golden" + } + }, "sum_type_row_count": { "pass": true, "partial": 1.0, @@ -673,32 +722,15 @@ "llm_db": "schema-t-013-spacetime-sum-type-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } - }, - "sum_type_row_parity": { - "pass": false, - "partial": 0.0, - "notes": { - "args": [ - 1, - 10 - ], - "golden_db": "schema-t-013-spacetime-sum-type-golden", - "golden_out": "id | value ----+--------------- 1 | (Circle = 10)", - "llm_db": "schema-t-013-spacetime-sum-type-gpt-5-llm", - "llm_out": "id | value ----+--------------- 1 | (Circle = 10)", - "query": "SELECT id, value FROM result WHERE id=1", - "reducer": "set_circle", - "server": "http://127.0.0.1:41115" - } } }, "vendor": "openai", - "started_at": "2026-01-23T20:07:57.743148689Z", - "finished_at": "2026-01-23T20:08:32.450224286Z" + "started_at": "2026-01-26T19:26:39.088386414Z", + "finished_at": "2026-01-26T19:27:19.723979899Z" }, "t_014_elementary_columns": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -708,7 +740,7 @@ "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = primitive)]\npub struct Primitive {\n #[primary_key]\n id: i32,\n count: i32,\n total: i64,\n price: f32,\n ratio: f64,\n active: bool,\n name: String,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n ctx.db.primitive().insert(Primitive {\n id: 1,\n count: 2,\n total: 3_000_000_000,\n price: 1.5,\n ratio: 2.25,\n active: true,\n name: \"Alice\".to_string(),\n });\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = primitive)]\npub struct Primitive {\n #[primary_key]\n id: i32,\n count: i32,\n total: i64,\n price: f32,\n ratio: f64,\n active: bool,\n name: String,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n ctx.db.primitive().insert(Primitive {\n id: 1,\n count: 2,\n total: 3000000000,\n price: 1.5f32,\n ratio: 2.25,\n active: true,\n name: \"Alice\".to_string(),\n });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-014-elementary-columns-golden", @@ -716,17 +748,13 @@ "work_dir_golden": "target/llm-runs/schema/t_014_elementary_columns/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_014_elementary_columns/rust/server/gpt-5/llm", "scorer_details": { - "schema_parity": { + "elementary_columns_row_count": { "pass": true, "partial": 1.0, "notes": { - "golden_db": "schema-t-014-elementary-columns-golden", - "llm_db": "schema-t-014-elementary-columns-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:41115", - "tables_diff": null, - "tables_equal": true + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM primitive WHERE id=1" } }, "elementary_columns_row_parity": { @@ -740,22 +768,26 @@ "llm_out": "id | count | total | price | ratio | active | name ----+-------+------------+-------+-------+--------+--------- 1 | 2 | 3000000000 | 1.5 | 2.25 | true | \"Alice\"", "query": "SELECT id, count, total, price, ratio, active, name FROM primitive WHERE id=1", "reducer": "seed", - "server": "http://127.0.0.1:41115" + "server": "http://127.0.0.1:44233" } }, - "elementary_columns_row_count": { + "schema_parity": { "pass": true, "partial": 1.0, "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM primitive WHERE id=1" + "golden_db": "schema-t-014-elementary-columns-golden", + "llm_db": "schema-t-014-elementary-columns-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:44233", + "tables_diff": null, + "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:08:30.379293605Z", - "finished_at": "2026-01-23T20:09:14.464089675Z" + "started_at": "2026-01-26T19:27:08.469170041Z", + "finished_at": "2026-01-26T19:28:03.162920625Z" }, "t_015_product_type_columns": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -765,7 +797,7 @@ "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\nstruct Address {\n street: String,\n zip: i32,\n}\n\n#[derive(SpacetimeType)]\nstruct Position {\n x: i32,\n y: i32,\n}\n\n#[table(name = profile)]\nstruct Profile {\n #[primary_key]\n id: i32,\n home: Address,\n work: Address,\n pos: Position,\n}\n\n#[reducer]\nfn seed(ctx: &ReducerContext) {\n let home = Address { street: \"1 Main\".to_string(), zip: 11111 };\n let work = Address { street: \"2 Broad\".to_string(), zip: 22222 };\n let pos = Position { x: 7, y: 9 };\n match ctx.db.profile().id().find(1) {\n Some(mut row) => {\n row.home = home;\n row.work = work;\n row.pos = pos;\n ctx.db.profile().id().update(row);\n }\n None => {\n ctx.db.profile().insert(Profile { id: 1, home, work, pos });\n }\n }\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\npub struct Address {\n street: String,\n zip: i32,\n}\n\n#[derive(SpacetimeType)]\npub struct Position {\n x: i32,\n y: i32,\n}\n\n#[table(name = profile)]\npub struct Profile {\n #[primary_key]\n id: i32,\n home: Address,\n work: Address,\n pos: Position,\n}\n\n#[reducer]\npub fn seed(ctx: &ReducerContext) {\n ctx.db.profile().insert(Profile {\n id: 1,\n home: Address { street: \"1 Main\".to_string(), zip: 11111 },\n work: Address { street: \"2 Broad\".to_string(), zip: 22222 },\n pos: Position { x: 7, y: 9 },\n });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-015-product-type-columns-golden", @@ -773,18 +805,13 @@ "work_dir_golden": "target/llm-runs/schema/t_015_product_type_columns/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_015_product_type_columns/rust/server/gpt-5/llm", "scorer_details": { - "product_type_columns_row_parity": { + "product_type_columns_row_count": { "pass": true, "partial": 1.0, "notes": { - "args": [], - "golden_db": "schema-t-015-product-type-columns-golden", - "golden_out": "id | home | work | pos ----+----------------------------------+-----------------------------------+---------------- 1 | (street = \"1 Main\", zip = 11111) | (street = \"2 Broad\", zip = 22222) | (x = 7, y = 9)", - "llm_db": "schema-t-015-product-type-columns-gpt-5-llm", - "llm_out": "id | home | work | pos ----+----------------------------------+-----------------------------------+---------------- 1 | (street = \"1 Main\", zip = 11111) | (street = \"2 Broad\", zip = 22222) | (x = 7, y = 9)", - "query": "SELECT id, home, work, pos FROM profile WHERE id=1", - "reducer": "seed", - "server": "http://127.0.0.1:41115" + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM profile WHERE id=1" } }, "schema_parity": { @@ -795,24 +822,29 @@ "llm_db": "schema-t-015-product-type-columns-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } }, - "product_type_columns_row_count": { + "product_type_columns_row_parity": { "pass": true, "partial": 1.0, "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM profile WHERE id=1" + "args": [], + "golden_db": "schema-t-015-product-type-columns-golden", + "golden_out": "id | home | work | pos ----+----------------------------------+-----------------------------------+---------------- 1 | (street = \"1 Main\", zip = 11111) | (street = \"2 Broad\", zip = 22222) | (x = 7, y = 9)", + "llm_db": "schema-t-015-product-type-columns-gpt-5-llm", + "llm_out": "id | home | work | pos ----+----------------------------------+-----------------------------------+---------------- 1 | (street = \"1 Main\", zip = 11111) | (street = \"2 Broad\", zip = 22222) | (x = 7, y = 9)", + "query": "SELECT id, home, work, pos FROM profile WHERE id=1", + "reducer": "seed", + "server": "http://127.0.0.1:44233" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:07:57.743649083Z", - "finished_at": "2026-01-23T20:08:57.046048716Z" + "started_at": "2026-01-26T19:26:39.089258499Z", + "finished_at": "2026-01-26T19:27:08.469138831Z" }, "t_016_sum_type_columns": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -822,7 +854,7 @@ "model_name": "GPT-5", "total_tests": 3, "passed_tests": 1, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[derive(spacetimedb::SpacetimeType)]\npub struct Rect {\n width: i32,\n height: i32,\n}\n\n#[derive(spacetimedb::SpacetimeType)]\npub enum Shape {\n Circle(i32),\n Rectangle(Rect),\n}\n\n#[spacetimedb::table(name = drawing)]\npub struct Drawing {\n #[primary_key]\n id: i32,\n a: Shape,\n b: Shape,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n if ctx.db.drawing().id().find(1).is_none() {\n ctx.db.drawing().insert(Drawing {\n id: 1,\n a: Shape::Circle(10),\n b: Shape::Rectangle(Rect { width: 4, height: 6 }),\n });\n }\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, SpacetimeType};\n\n#[derive(SpacetimeType)]\npub struct Rect {\n width: i32,\n height: i32,\n}\n\n#[derive(SpacetimeType)]\npub enum Shape {\n Circle(i32),\n Rectangle(Rect),\n}\n\n#[table(name = drawing)]\npub struct Drawing {\n #[primary_key]\n id: i32,\n a: Shape,\n b: Shape,\n}\n\n#[reducer]\npub fn seed(ctx: &ReducerContext) {\n let drawings = ctx.db.drawing();\n for row in drawings.iter() {\n drawings.id().delete(&row.id);\n }\n drawings.insert(Drawing {\n id: 1,\n a: Shape::Circle(10),\n b: Shape::Rectangle(Rect { width: 4, height: 6 }),\n });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-016-sum-type-columns-golden", @@ -830,11 +862,19 @@ "work_dir_golden": "target/llm-runs/schema/t_016_sum_type_columns/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_016_sum_type_columns/rust/server/gpt-5/llm", "scorer_details": { + "sum_type_columns_row_count": { + "pass": false, + "partial": 0.0, + "notes": { + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44233/v1/database/c20072beef7cc108a057376dd8b6be7e2a74798bdfaea38dde4e2e708af5e427/sql)\n", + "phase": "sql" + } + }, "sum_type_columns_row_parity": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41115/v1/database/c200be63a5c073cb57163fbe420fbf96d0ca1c24fb78e5d67bbed19841d5eeee/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44233/v1/database/c20076700591ec6cb5396663df5e1f56128de954277e753577b8dd7756ee998c/sql)\n", "phase": "sql_golden" } }, @@ -846,7 +886,7 @@ "llm_db": "schema-t-016-sum-type-columns-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } @@ -861,8 +901,8 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:07:57.742955241Z", - "finished_at": "2026-01-23T20:08:35.620943048Z" + "started_at": "2026-01-26T19:26:39.088020973Z", + "finished_at": "2026-01-26T19:27:22.864464632Z" }, "t_017_scheduled_columns": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -872,7 +912,7 @@ "model_name": "GPT-5", "total_tests": 2, "passed_tests": 0, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, ScheduleAt};\n\n#[table(name = tick_timer, schedule(reducer = tick, column = scheduled_at))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[reducer(init)]\npub fn init(ctx: &ReducerContext) {\n if ctx.db.tick_timer().count() == 0 {\n ctx.db.tick_timer().insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::repeat_micros(50_000),\n });\n }\n}\n\n#[reducer]\npub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table, ScheduleAt};\n\n#[table(name = tick_timer, scheduled(reducer = tick, column = scheduled_at))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[reducer(init)]\npub fn init(ctx: &ReducerContext) {\n ctx.db.tick_timer().insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::repeat_micros(50_000),\n });\n}\n\n#[reducer]\npub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-017-scheduled-columns-golden", @@ -884,14 +924,14 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime publish failed (exit=1)\n--- stderr ---\n Updating crates.io index\n Locking 72 packages to latest compatible versions\n Adding generic-array v0.14.7 (available: v0.14.9)\n Adding spacetimedb v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-macro v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-sys v1.11.1 (available: v1.11.3)\n Adding spacetimedb-lib v1.11.1 (available: v1.11.3)\n Adding spacetimedb-primitives v1.11.1 (available: v1.11.3)\n Adding spacetimedb-sats v1.11.1 (available: v1.11.3)\n Compiling proc-macro2 v1.0.106\n Compiling quote v1.0.44\n Compiling unicode-ident v1.0.22\n Compiling typenum v1.19.0\n Compiling version_check v0.9.5\n Compiling autocfg v1.5.0\n Compiling serde_core v1.0.228\n Compiling heck v0.5.0\n Compiling cfg-if v1.0.4\n Compiling serde v1.0.228\n Compiling either v1.15.0\n Compiling shlex v1.3.0\n Compiling zerocopy v0.8.33\n Compiling find-msvc-tools v0.1.8\n Compiling nohash-hasher v0.2.0\n Compiling thiserror v1.0.69\n Compiling bitflags v2.10.0\n Compiling anyhow v1.0.100\n Compiling arrayvec v0.7.6\n Compiling zmij v1.0.16\n Compiling heck v0.4.1\n Compiling convert_case v0.4.0\n Compiling humantime v2.3.0\n Compiling bytes v1.11.0\n Compiling keccak v0.1.5\n Compiling constant_time_eq v0.4.2\n Compiling bytemuck v1.24.0\n Compiling second-stack v0.3.5\n Compiling smallvec v1.15.1\n Compiling getrandom v0.2.17\n Compiling hex v0.4.3\n Compiling spacetimedb-lib v1.11.1\n Compiling itertools v0.12.1\n Compiling cc v1.2.54\n Compiling serde_json v1.0.149\n Compiling itoa v1.0.17\n Compiling arrayref v0.3.9\n Compiling rand_core v0.6.4\n Compiling memchr v2.7.6\n Compiling log v0.4.29\n Compiling scoped-tls v1.0.1\n Compiling generic-array v0.14.7\n Compiling num-traits v0.2.19\n Compiling syn v2.0.114\n Compiling http v1.4.0\n Compiling approx v0.3.2\n Compiling chrono v0.4.43\n Compiling decorum v0.3.1\n Compiling blake3 v1.8.3\n Compiling crypto-common v0.1.7\n Compiling block-buffer v0.10.4\n Compiling digest v0.10.7\n Compiling sha3 v0.10.8\n Compiling ppv-lite86 v0.2.21\n Compiling ethnum v1.5.2\n Compiling rand_chacha v0.3.1\n Compiling rand v0.8.5\n Compiling enum-as-inner v0.6.1\n Compiling thiserror-impl v1.0.69\n Compiling derive_more v0.99.20\n Compiling spacetimedb-primitives v1.11.1\n Compiling spacetimedb-bindings-sys v1.11.1\n Compiling spacetimedb-bindings-macro v1.11.1\n Compiling spacetimedb-sats v1.11.1\n Compiling spacetimedb v1.11.1\n Compiling spacetime-module v0.1.0 (/__w/SpacetimeDB/SpacetimeDB/target/llm-runs/schema/t_017_scheduled_columns/rust/server/gpt-5/llm)\nerror: expected one of: `public`, `private`, `name`, `index`, `scheduled`\n --> src/lib.rs:4:28\n |\n4 | #[table(name = tick_timer, schedule(reducer = tick, column = scheduled_at))]\n | ^^^^^^^^\n\nerror[E0422]: cannot find struct, variant or union type `TickTimer` in this scope\n --> src/lib.rs:15:36\n |\n15 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^ not found in this scope\n\nerror[E0412]: cannot find type `TickTimer` in this scope\n --> src/lib.rs:23:42\n |\n23 | pub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n | ^^^^^^^^^ not found in this scope\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:14:15\n |\n14 | if ctx.db.tick_timer().count() == 0 {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:15:16\n |\n15 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no variant or associated item named `repeat_micros` found for enum `ScheduleAt` in the current scope\n --> src/lib.rs:17:39\n |\n17 | scheduled_at: ScheduleAt::repeat_micros(50_000),\n | ^^^^^^^^^^^^^ variant or associated item not found in `ScheduleAt`\n\nerror[E0277]: invalid reducer signature\n --> src/lib.rs:23:8\n |\n 22 | #[reducer]\n | ---------- required by a bound introduced by this call\n 23 | pub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n | ^^^^ this reducer signature is not valid\n |\n = help: the trait `Reducer<'_, _>` is not implemented for fn item `for<'a> fn(&'a ReducerContext, {type error}) {tick}`\n = note: \n = note: reducer signatures must match the following pattern:\n = note: `Fn(&ReducerContext, [T1, ...]) [-> Result<(), impl Display>]`\n = note: where each `Ti` type implements `SpacetimeType`.\n = note: \nnote: required by a bound in `register_reducer`\n --> /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spacetimedb-1.11.1/src/rt.rs:746:81\n |\n746 | pub fn register_reducer<'a, A: Args<'a>, I: FnInfo>(_: impl Reducer<'a, A>) {\n | ^^^^^^^^^^^^^^ required by this bound in `register_reducer`\n\nerror[E0277]: invalid reducer signature\n --> src/lib.rs:23:8\n |\n22 | #[reducer]\n | ---------- required by a bound introduced by this call\n23 | pub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n | ^^^^ this reducer signature is not valid\n |\n = help: the trait `Reducer<'_, _>` is not implemented for fn item `for<'a> fn(&'a ReducerContext, {type error}) {tick}`\n = note: \n = note: reducer signatures must match the following pattern:\n = note: `Fn(&ReducerContext, [T1, ...]) [-> Result<(), impl Display>]`\n = note: where each `Ti` type implements `SpacetimeType`.\n = note: \nnote: required by a bound in `invoke_reducer`\n --> /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spacetimedb-1.11.1/src/rt.rs:45:19\n |\n44 | pub fn invoke_reducer<'a, A: Args<'a>>(\n | -------------- required by a bound in this function\n45 | reducer: impl Reducer<'a, A>,\n | ^^^^^^^^^^^^^^ required by this bound in `invoke_reducer`\n\nSome errors have detailed explanations: E0277, E0412, E0422, E0599.\nFor more information about an error, try `rustc --explain E0277`.\nerror: could not compile `spacetime-module` (lib) due to 8 previous errors\nError: command [\"cargo\", \"build\", \"--config=net.git-fetch-with-cli=true\", \"--target=wasm32-unknown-unknown\", \"--release\", \"--message-format=json-render-diagnostics\"] exited with code 101\n\n--- stdout ---\n", + "error": "spacetime publish failed (exit=1)\n--- stderr ---\n Updating crates.io index\n Blocking waiting for file lock on package cache\n Locking 72 packages to latest compatible versions\n Adding generic-array v0.14.7 (available: v0.14.9)\n Adding spacetimedb v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-macro v1.11.1 (available: v1.11.3)\n Adding spacetimedb-bindings-sys v1.11.1 (available: v1.11.3)\n Adding spacetimedb-lib v1.11.1 (available: v1.11.3)\n Adding spacetimedb-primitives v1.11.1 (available: v1.11.3)\n Adding spacetimedb-sats v1.11.1 (available: v1.11.3)\n Blocking waiting for file lock on package cache\n Blocking waiting for file lock on package cache\n Compiling proc-macro2 v1.0.106\n Compiling unicode-ident v1.0.22\n Compiling quote v1.0.44\n Compiling version_check v0.9.5\n Compiling typenum v1.19.0\n Compiling autocfg v1.5.0\n Compiling heck v0.5.0\n Compiling serde_core v1.0.228\n Compiling cfg-if v1.0.4\n Compiling find-msvc-tools v0.1.8\n Compiling serde v1.0.228\n Compiling either v1.15.0\n Compiling zerocopy v0.8.34\n Compiling shlex v1.3.0\n Compiling anyhow v1.0.100\n Compiling bitflags v2.10.0\n Compiling thiserror v1.0.69\n Compiling nohash-hasher v0.2.0\n Compiling heck v0.4.1\n Compiling arrayvec v0.7.6\n Compiling zmij v1.0.17\n Compiling convert_case v0.4.0\n Compiling keccak v0.1.5\n Compiling humantime v2.3.0\n Compiling bytes v1.11.0\n Compiling itoa v1.0.17\n Compiling arrayref v0.3.9\n Compiling second-stack v0.3.5\n Compiling smallvec v1.15.1\n Compiling getrandom v0.2.17\n Compiling constant_time_eq v0.4.2\n Compiling cc v1.2.54\n Compiling itertools v0.12.1\n Compiling serde_json v1.0.149\n Compiling hex v0.4.3\n Compiling spacetimedb-lib v1.11.1\n Compiling bytemuck v1.24.0\n Compiling memchr v2.7.6\n Compiling generic-array v0.14.7\n Compiling log v0.4.29\n Compiling scoped-tls v1.0.1\n Compiling rand_core v0.6.4\n Compiling num-traits v0.2.19\n Compiling http v1.4.0\n Compiling syn v2.0.114\n Compiling blake3 v1.8.3\n Compiling approx v0.3.2\n Compiling chrono v0.4.43\n Compiling crypto-common v0.1.7\n Compiling block-buffer v0.10.4\n Compiling decorum v0.3.1\n Compiling digest v0.10.7\n Compiling sha3 v0.10.8\n Compiling ppv-lite86 v0.2.21\n Compiling ethnum v1.5.2\n Compiling rand_chacha v0.3.1\n Compiling rand v0.8.5\n Compiling enum-as-inner v0.6.1\n Compiling thiserror-impl v1.0.69\n Compiling derive_more v0.99.20\n Compiling spacetimedb-primitives v1.11.1\n Compiling spacetimedb-bindings-sys v1.11.1\n Compiling spacetimedb-bindings-macro v1.11.1\n Compiling spacetimedb-sats v1.11.1\n Compiling spacetimedb v1.11.1\n Compiling spacetime-module v0.1.0 (/__w/SpacetimeDB/SpacetimeDB/target/llm-runs/schema/t_017_scheduled_columns/rust/server/gpt-5/llm)\nerror: expected `at`\n --> src/lib.rs:4:38\n |\n4 | #[table(name = tick_timer, scheduled(reducer = tick, column = scheduled_at))]\n | ^^^^^^^\n\nerror[E0422]: cannot find struct, variant or union type `TickTimer` in this scope\n --> src/lib.rs:14:32\n |\n14 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^ not found in this scope\n\nerror[E0412]: cannot find type `TickTimer` in this scope\n --> src/lib.rs:21:42\n |\n21 | pub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n | ^^^^^^^^^ not found in this scope\n\nerror[E0599]: no method named `tick_timer` found for struct `Local` in the current scope\n --> src/lib.rs:14:12\n |\n14 | ctx.db.tick_timer().insert(TickTimer {\n | ^^^^^^^^^^ method not found in `Local`\n\nerror[E0599]: no variant or associated item named `repeat_micros` found for enum `ScheduleAt` in the current scope\n --> src/lib.rs:16:35\n |\n16 | scheduled_at: ScheduleAt::repeat_micros(50_000),\n | ^^^^^^^^^^^^^ variant or associated item not found in `ScheduleAt`\n\nerror[E0277]: invalid reducer signature\n --> src/lib.rs:21:8\n |\n 20 | #[reducer]\n | ---------- required by a bound introduced by this call\n 21 | pub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n | ^^^^ this reducer signature is not valid\n |\n = help: the trait `Reducer<'_, _>` is not implemented for fn item `for<'a> fn(&'a ReducerContext, {type error}) {tick}`\n = note: \n = note: reducer signatures must match the following pattern:\n = note: `Fn(&ReducerContext, [T1, ...]) [-> Result<(), impl Display>]`\n = note: where each `Ti` type implements `SpacetimeType`.\n = note: \nnote: required by a bound in `register_reducer`\n --> /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spacetimedb-1.11.1/src/rt.rs:746:81\n |\n746 | pub fn register_reducer<'a, A: Args<'a>, I: FnInfo>(_: impl Reducer<'a, A>) {\n | ^^^^^^^^^^^^^^ required by this bound in `register_reducer`\n\nerror[E0277]: invalid reducer signature\n --> src/lib.rs:21:8\n |\n20 | #[reducer]\n | ---------- required by a bound introduced by this call\n21 | pub fn tick(_ctx: &ReducerContext, _row: TickTimer) {\n | ^^^^ this reducer signature is not valid\n |\n = help: the trait `Reducer<'_, _>` is not implemented for fn item `for<'a> fn(&'a ReducerContext, {type error}) {tick}`\n = note: \n = note: reducer signatures must match the following pattern:\n = note: `Fn(&ReducerContext, [T1, ...]) [-> Result<(), impl Display>]`\n = note: where each `Ti` type implements `SpacetimeType`.\n = note: \nnote: required by a bound in `invoke_reducer`\n --> /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spacetimedb-1.11.1/src/rt.rs:45:19\n |\n44 | pub fn invoke_reducer<'a, A: Args<'a>>(\n | -------------- required by a bound in this function\n45 | reducer: impl Reducer<'a, A>,\n | ^^^^^^^^^^^^^^ required by this bound in `invoke_reducer`\n\nSome errors have detailed explanations: E0277, E0412, E0422, E0599.\nFor more information about an error, try `rustc --explain E0277`.\nerror: could not compile `spacetime-module` (lib) due to 7 previous errors\nError: command [\"cargo\", \"build\", \"--config=net.git-fetch-with-cli=true\", \"--target=wasm32-unknown-unknown\", \"--release\", \"--message-format=json-render-diagnostics\"] exited with code 101\n\n--- stdout ---\n", "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:07:57.742610502Z", - "finished_at": "2026-01-23T20:08:56.057254318Z" + "started_at": "2026-01-26T19:26:39.087192758Z", + "finished_at": "2026-01-26T19:27:53.381568310Z" }, "t_018_constraints": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -900,8 +940,8 @@ "golden_published": true, "model_name": "GPT-5", "total_tests": 3, - "passed_tests": 3, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = account, index(name = by_name, btree(columns = [name])))]\npub struct Account {\n #[primary_key]\n id: i32,\n #[unique]\n email: String,\n name: String,\n}\n\n#[reducer]\npub fn seed(ctx: &ReducerContext) {\n ctx.db\n .account()\n .insert(Account {\n id: 1,\n email: \"a@example.com\".to_string(),\n name: \"Alice\".to_string(),\n });\n ctx.db\n .account()\n .insert(Account {\n id: 2,\n email: \"b@example.com\".to_string(),\n name: \"Bob\".to_string(),\n });\n}", + "passed_tests": 2, + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = account, index(name = by_name, btree(columns = [name])))]\npub struct Account {\n #[primary_key]\n id: i32,\n #[unique]\n email: String,\n name: String,\n}\n\n#[reducer]\npub fn seed(ctx: &ReducerContext) {\n let t = ctx.db.account();\n t.insert(Account { id: 1, email: \"a@example.com\".to_string(), name: \"Alice\".to_string() });\n t.insert(Account { id: 2, email: \"b@example.com\".to_string(), name: \"Bob\".to_string() });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-018-constraints-golden", @@ -909,17 +949,12 @@ "work_dir_golden": "target/llm-runs/schema/t_018_constraints/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_018_constraints/rust/server/gpt-5/llm", "scorer_details": { - "schema_parity": { - "pass": true, - "partial": 1.0, + "constraints_row_parity_after_seed": { + "pass": false, + "partial": 0.0, "notes": { - "golden_db": "schema-t-018-constraints-golden", - "llm_db": "schema-t-018-constraints-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:33615", - "tables_diff": null, - "tables_equal": true + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `account`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44233/v1/database/c200ce532d202b333f35de1400d0f2b40c51bd06fe40198129dd9b2a5b0d196e/sql)\n", + "phase": "sql_golden" } }, "constraints_seed_two_rows": { @@ -953,15 +988,15 @@ "llm_db": "schema-t-018-constraints-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:07:57.742384971Z", - "finished_at": "2026-01-23T20:08:30.379256146Z" + "started_at": "2026-01-26T19:26:39.086684099Z", + "finished_at": "2026-01-26T19:27:19.861734913Z" }, "t_019_many_to_many": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -971,7 +1006,7 @@ "model_name": "GPT-5", "total_tests": 5, "passed_tests": 5, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n user_id: i32,\n name: String,\n}\n\n#[table(name = group)]\npub struct Group {\n #[primary_key]\n group_id: i32,\n title: String,\n}\n\n#[table(\n name = membership,\n index(name = by_user, btree(columns = [user_id])),\n index(name = by_group, btree(columns = [group_id]))\n)]\npub struct Membership {\n #[primary_key]\n id: i32,\n user_id: i32,\n group_id: i32,\n}\n\n#[reducer]\npub fn seed(ctx: &ReducerContext) {\n // Clear existing rows to ensure exactly the requested rows exist after seeding\n let membership_ids: Vec = ctx.db.membership().iter().map(|m| m.id).collect();\n for id in membership_ids {\n ctx.db.membership().id().delete(&id);\n }\n\n let user_ids: Vec = ctx.db.user().iter().map(|u| u.user_id).collect();\n for id in user_ids {\n ctx.db.user().user_id().delete(&id);\n }\n\n let group_ids: Vec = ctx.db.group().iter().map(|g| g.group_id).collect();\n for id in group_ids {\n ctx.db.group().group_id().delete(&id);\n }\n\n // Insert users\n ctx.db.user().insert(User { user_id: 1, name: \"Alice\".to_string() });\n ctx.db.user().insert(User { user_id: 2, name: \"Bob\".to_string() });\n\n // Insert groups\n ctx.db.group().insert(Group { group_id: 10, title: \"Admin\".to_string() });\n ctx.db.group().insert(Group { group_id: 20, title: \"Dev\".to_string() });\n\n // Insert memberships\n ctx.db.membership().insert(Membership { id: 1, user_id: 1, group_id: 10 });\n ctx.db.membership().insert(Membership { id: 2, user_id: 1, group_id: 20 });\n ctx.db.membership().insert(Membership { id: 3, user_id: 2, group_id: 20 });\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = user)]\npub struct User {\n #[primary_key]\n user_id: i32,\n name: String,\n}\n\n#[table(name = group)]\npub struct Group {\n #[primary_key]\n group_id: i32,\n title: String,\n}\n\n#[table(\n name = membership,\n index(name = by_user, btree(columns = [user_id])),\n index(name = by_group, btree(columns = [group_id]))\n)]\npub struct Membership {\n #[primary_key]\n id: i32,\n user_id: i32,\n group_id: i32,\n}\n\n#[reducer]\npub fn seed(ctx: &ReducerContext) {\n {\n let tbl = ctx.db.membership();\n let ids: Vec = tbl.iter().map(|r| r.id).collect();\n for id in ids {\n tbl.id().delete(&id);\n }\n }\n {\n let tbl = ctx.db.user();\n let ids: Vec = tbl.iter().map(|r| r.user_id).collect();\n for id in ids {\n tbl.user_id().delete(&id);\n }\n }\n {\n let tbl = ctx.db.group();\n let ids: Vec = tbl.iter().map(|r| r.group_id).collect();\n for id in ids {\n tbl.group_id().delete(&id);\n }\n }\n\n ctx.db.user().insert(User { user_id: 1, name: \"Alice\".to_string() });\n ctx.db.user().insert(User { user_id: 2, name: \"Bob\".to_string() });\n\n ctx.db.group().insert(Group { group_id: 10, title: \"Admin\".to_string() });\n ctx.db.group().insert(Group { group_id: 20, title: \"Dev\".to_string() });\n\n ctx.db.membership().insert(Membership { id: 1, user_id: 1, group_id: 10 });\n ctx.db.membership().insert(Membership { id: 2, user_id: 1, group_id: 20 });\n ctx.db.membership().insert(Membership { id: 3, user_id: 2, group_id: 20 });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-019-many-to-many-golden", @@ -979,20 +1014,7 @@ "work_dir_golden": "target/llm-runs/schema/t_019_many_to_many/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_019_many_to_many/rust/server/gpt-5/llm", "scorer_details": { - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "schema-t-019-many-to-many-golden", - "llm_db": "schema-t-019-many-to-many-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:41115", - "tables_diff": null, - "tables_equal": true - } - }, - "m2m_has_1_20": { + "m2m_has_1_10": { "pass": true, "partial": 1.0, "notes": { @@ -1001,13 +1023,13 @@ "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=1 AND group_id=20" } }, - "m2m_has_2_20": { + "m2m_has_1_20": { "pass": true, "partial": 1.0, "notes": { "actual": 1, "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=2 AND group_id=20" + "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=1 AND group_id=20" } }, "memberships_three_rows": { @@ -1019,19 +1041,32 @@ "sql": "SELECT COUNT(*) AS n FROM membership" } }, - "m2m_has_1_10": { + "m2m_has_2_20": { "pass": true, "partial": 1.0, "notes": { "actual": 1, "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=1 AND group_id=10" + "sql": "SELECT COUNT(*) AS n FROM membership WHERE user_id=2 AND group_id=20" + } + }, + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "schema-t-019-many-to-many-golden", + "llm_db": "schema-t-019-many-to-many-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:44233", + "tables_diff": null, + "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:07:57.743323315Z", - "finished_at": "2026-01-23T20:08:57.792175612Z" + "started_at": "2026-01-26T19:26:39.088752482Z", + "finished_at": "2026-01-26T19:27:50.273815091Z" }, "t_020_ecs": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -1041,7 +1076,7 @@ "model_name": "GPT-5", "total_tests": 5, "passed_tests": 1, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = entity)]\npub struct Entity {\n #[primary_key]\n id: i32,\n}\n\n#[spacetimedb::table(name = position)]\npub struct Position {\n #[primary_key]\n entity_id: i32,\n x: i32,\n y: i32,\n}\n\n#[spacetimedb::table(name = velocity)]\npub struct Velocity {\n #[primary_key]\n entity_id: i32,\n vx: i32,\n vy: i32,\n}\n\n#[spacetimedb::table(name = next_position)]\npub struct NextPosition {\n #[primary_key]\n entity_id: i32,\n x: i32,\n y: i32,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n // Clear and insert entities\n for &id in &[1, 2] {\n if ctx.db.entity().id().find(id).is_some() {\n ctx.db.entity().id().delete(&id);\n }\n ctx.db.entity().insert(Entity { id });\n }\n\n // Clear existing positions/velocities for these entities and insert new values\n // Entity 1: pos=(0,0), vel=(1,0)\n if ctx.db.position().entity_id().find(1).is_some() {\n ctx.db.position().entity_id().delete(&1);\n }\n ctx.db.position().insert(Position { entity_id: 1, x: 0, y: 0 });\n if ctx.db.velocity().entity_id().find(1).is_some() {\n ctx.db.velocity().entity_id().delete(&1);\n }\n ctx.db.velocity().insert(Velocity { entity_id: 1, vx: 1, vy: 0 });\n\n // Entity 2: pos=(10,0), vel=(-2,3)\n if ctx.db.position().entity_id().find(2).is_some() {\n ctx.db.position().entity_id().delete(&2);\n }\n ctx.db.position().insert(Position { entity_id: 2, x: 10, y: 0 });\n if ctx.db.velocity().entity_id().find(2).is_some() {\n ctx.db.velocity().entity_id().delete(&2);\n }\n ctx.db.velocity().insert(Velocity { entity_id: 2, vx: -2, vy: 3 });\n\n // Clean any existing next_position rows for these entities\n for &id in &[1, 2] {\n if ctx.db.next_position().entity_id().find(id).is_some() {\n ctx.db.next_position().entity_id().delete(&id);\n }\n }\n}\n\n#[spacetimedb::reducer]\npub fn step(ctx: &ReducerContext) {\n for pos in ctx.db.position().iter() {\n if let Some(vel) = ctx.db.velocity().entity_id().find(pos.entity_id) {\n let nx = pos.x + vel.vx;\n let ny = pos.y + vel.vy;\n let next = NextPosition {\n entity_id: pos.entity_id,\n x: nx,\n y: ny,\n };\n\n if ctx.db.next_position().entity_id().find(pos.entity_id).is_some() {\n let _ = ctx.db.next_position().entity_id().update(next);\n } else {\n let _ = ctx.db.next_position().insert(next);\n }\n }\n }\n}", + "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = entity)]\npub struct Entity {\n #[primary_key]\n id: i32,\n}\n\n#[table(name = position)]\npub struct Position {\n #[primary_key]\n entity_id: i32,\n x: i32,\n y: i32,\n}\n\n#[table(name = velocity)]\npub struct Velocity {\n #[primary_key]\n entity_id: i32,\n vx: i32,\n vy: i32,\n}\n\n#[table(name = next_position)]\npub struct NextPosition {\n #[primary_key]\n entity_id: i32,\n x: i32,\n y: i32,\n}\n\n#[reducer]\npub fn seed(ctx: &ReducerContext) {\n ctx.db.entity().insert(Entity { id: 1 });\n ctx.db.position().insert(Position { entity_id: 1, x: 0, y: 0 });\n ctx.db.velocity().insert(Velocity { entity_id: 1, vx: 1, vy: 0 });\n\n ctx.db.entity().insert(Entity { id: 2 });\n ctx.db.position().insert(Position { entity_id: 2, x: 10, y: 0 });\n ctx.db.velocity().insert(Velocity { entity_id: 2, vx: -2, vy: 3 });\n}\n\n#[reducer]\npub fn step(ctx: &ReducerContext) {\n for pos in ctx.db.position().iter() {\n if let Some(vel) = ctx.db.velocity().entity_id().find(pos.entity_id) {\n let next = NextPosition {\n entity_id: pos.entity_id,\n x: pos.x + vel.vx,\n y: pos.y + vel.vy,\n };\n\n if ctx.db.next_position().entity_id().find(pos.entity_id).is_some() {\n ctx.db.next_position().entity_id().update(next);\n } else {\n ctx.db.next_position().insert(next);\n }\n }\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-020-ecs-golden", @@ -1053,7 +1088,15 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41115/v1/database/c20022d8f2e2d547824e6b1c08b40372fd94143f227cebc3dd95d8debbce411d/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44233/v1/database/c200adf8fd49d0e7e167ec3aa9141c1b249dc335dfa97e666a41345612d7362a/sql)\n", + "phase": "sql" + } + }, + "ecs_next_pos_entity2": { + "pass": false, + "partial": 0.0, + "notes": { + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44233/v1/database/c200adf8fd49d0e7e167ec3aa9141c1b249dc335dfa97e666a41345612d7362a/sql)\n", "phase": "sql" } }, @@ -1061,7 +1104,7 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41115/v1/database/c20022d8f2e2d547824e6b1c08b40372fd94143f227cebc3dd95d8debbce411d/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44233/v1/database/c200adf8fd49d0e7e167ec3aa9141c1b249dc335dfa97e666a41345612d7362a/sql)\n", "phase": "sql" } }, @@ -1073,7 +1116,7 @@ "llm_db": "schema-t-020-ecs-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } @@ -1082,22 +1125,14 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41115/v1/database/c20022d8f2e2d547824e6b1c08b40372fd94143f227cebc3dd95d8debbce411d/sql)\n", - "phase": "sql" - } - }, - "ecs_next_pos_entity2": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41115/v1/database/c20022d8f2e2d547824e6b1c08b40372fd94143f227cebc3dd95d8debbce411d/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44233/v1/database/c200adf8fd49d0e7e167ec3aa9141c1b249dc335dfa97e666a41345612d7362a/sql)\n", "phase": "sql" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:07:57.743495455Z", - "finished_at": "2026-01-23T20:09:14.983916389Z" + "started_at": "2026-01-26T19:26:39.089004480Z", + "finished_at": "2026-01-26T19:27:35.047523671Z" }, "t_021_multi_column_index": { "hash": "da32ac1e4a22e29f27c1c75b3ce526f5ba909c184b9057d83384313a5e7b881a", @@ -1107,7 +1142,7 @@ "model_name": "GPT-5", "total_tests": 4, "passed_tests": 4, - "llm_output": "use spacetimedb::{table, reducer, ReducerContext, Table};\n\n#[table(name = log, index(name = by_user_day, btree(columns = [user_id, day])))]\npub struct Log {\n #[primary_key]\n id: i32,\n user_id: i32,\n day: i32,\n message: String,\n}\n\n#[reducer]\npub fn seed(ctx: &ReducerContext) {\n let table = ctx.db.log();\n table.insert(Log { id: 1, user_id: 7, day: 1, message: \"a\".to_string() });\n table.insert(Log { id: 2, user_id: 7, day: 2, message: \"b\".to_string() });\n table.insert(Log { id: 3, user_id: 9, day: 1, message: \"c\".to_string() });\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = log, index(name = by_user_day, btree(columns = [user_id, day])))]\npub struct Log {\n #[primary_key]\n id: i32,\n user_id: i32,\n day: i32,\n message: String,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n let ids: Vec = ctx.db.log().iter().map(|r| r.id).collect();\n for id in ids {\n ctx.db.log().id().delete(&id);\n }\n\n ctx.db.log().insert(Log { id: 1, user_id: 7, day: 1, message: \"a\".to_string() });\n ctx.db.log().insert(Log { id: 2, user_id: 7, day: 2, message: \"b\".to_string() });\n ctx.db.log().insert(Log { id: 3, user_id: 9, day: 1, message: \"c\".to_string() });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-021-multi-column-index-golden", @@ -1115,15 +1150,6 @@ "work_dir_golden": "target/llm-runs/schema/t_021_multi_column_index/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_021_multi_column_index/rust/server/gpt-5/llm", "scorer_details": { - "mcindex_lookup_u7_d1": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM log WHERE user_id=7 AND day=1" - } - }, "schema_parity": { "pass": true, "partial": 1.0, @@ -1132,7 +1158,7 @@ "llm_db": "schema-t-021-multi-column-index-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41115", + "server": "http://127.0.0.1:44233", "tables_diff": null, "tables_equal": true } @@ -1146,7 +1172,16 @@ "sql": "SELECT COUNT(*) AS n FROM log" } }, - "mcindex_seed_count": { + "mcindex_lookup_u7_d2": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM log WHERE user_id=7 AND day=2" + } + }, + "mcindex_lookup_u7_d1": { "pass": true, "partial": 1.0, "notes": { @@ -1157,8 +1192,8 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:07:57.742772776Z", - "finished_at": "2026-01-23T20:08:35.084850930Z" + "started_at": "2026-01-26T19:26:39.087595992Z", + "finished_at": "2026-01-26T19:27:23.893472645Z" } } } @@ -1166,21 +1201,21 @@ }, { "mode": "docs", - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "models": [ { "name": "GPT-5", "route_api_model": "gpt-5", "tasks": { "t_000_empty_reducers": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_000_empty_reducers", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 1, "passed_tests": 0, - "llm_output": "#[spacetimedb::reducer]\npub fn empty_reducer_no_args(_ctx: &spacetimedb::ReducerContext) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_int(_ctx: &spacetimedb::ReducerContext, _count: i32) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_string(_ctx: &spacetimedb::ReducerContext, _name: String) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_two_args(_ctx: &spacetimedb::ReducerContext, _count: i32, _name: String) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_three_args(_ctx: &spacetimedb::ReducerContext, _active: bool, _ratio: f32, _label: String) {\n}", + "llm_output": "use spacetimedb::ReducerContext;\n\n#[spacetimedb::reducer]\npub fn empty_reducer_no_args(_ctx: &ReducerContext) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_int(_ctx: &ReducerContext, count: i32) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_string(_ctx: &ReducerContext, name: String) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_two_args(_ctx: &ReducerContext, count: i32, name: String) {\n}\n\n#[spacetimedb::reducer]\npub fn empty_reducer_with_three_args(_ctx: &ReducerContext, active: bool, ratio: f32, label: String) {\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-000-empty-reducers-golden", @@ -1198,11 +1233,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:12:10.018237719Z", - "finished_at": "2026-01-23T20:12:41.638729168Z" + "started_at": "2026-01-26T19:30:54.611008723Z", + "finished_at": "2026-01-26T19:31:59.326178772Z" }, "t_001_basic_tables": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_001_basic_tables", "lang": "rust", "golden_published": true, @@ -1227,18 +1262,18 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:12:46.725514922Z", - "finished_at": "2026-01-23T20:13:51.799945305Z" + "started_at": "2026-01-26T19:31:23.564110648Z", + "finished_at": "2026-01-26T19:32:09.696102989Z" }, "t_002_scheduled_table": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_002_scheduled_table", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 1, "passed_tests": 0, - "llm_output": "use std::time::Duration;\nuse spacetimedb::{ReducerContext, ScheduleAt, Table};\n\n#[spacetimedb::table(name = tick_timer, scheduled(tick))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[spacetimedb::reducer]\npub fn tick(_ctx: &ReducerContext, _timer: TickTimer) {\n // No-op scheduled tick.\n}\n\n#[spacetimedb::reducer(init)]\npub fn init(ctx: &ReducerContext) -> Result<(), String> {\n ctx.db.tick_timer().insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::Interval(Duration::from_micros(50_000).into()),\n });\n Ok(())\n}", + "llm_output": "use std::time::Duration;\nuse spacetimedb::{ReducerContext, ScheduleAt, Table};\n\n#[spacetimedb::table(name = tick_timer, scheduled(tick))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[spacetimedb::reducer]\npub fn tick(_ctx: &ReducerContext, _timer: TickTimer) {}\n\n#[spacetimedb::reducer(init)]\npub fn init(ctx: &ReducerContext) -> Result<(), String> {\n if ctx.db.tick_timer().count() == 0 {\n ctx.db.tick_timer().try_insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::Interval(Duration::from_micros(50_000).into()),\n })?;\n }\n Ok(())\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-002-scheduled-table-golden", @@ -1256,11 +1291,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:13:28.197750258Z", - "finished_at": "2026-01-23T20:14:26.307958881Z" + "started_at": "2026-01-26T19:32:03.232154280Z", + "finished_at": "2026-01-26T19:32:55.980604615Z" }, "t_003_struct_in_table": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_003_struct_in_table", "lang": "rust", "golden_published": true, @@ -1285,11 +1320,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:12:41.638758353Z", - "finished_at": "2026-01-23T20:13:47.479970679Z" + "started_at": "2026-01-26T19:31:11.581070012Z", + "finished_at": "2026-01-26T19:32:09.839951728Z" }, "t_004_insert": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_004_insert", "lang": "rust", "golden_published": true, @@ -1322,11 +1357,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:12:46.734575843Z", - "finished_at": "2026-01-23T20:13:46.613223334Z" + "started_at": "2026-01-26T19:31:53.617759187Z", + "finished_at": "2026-01-26T19:32:28.129265268Z" }, "t_005_update": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_005_update", "lang": "rust", "golden_published": true, @@ -1341,12 +1376,13 @@ "work_dir_golden": "target/llm-runs/basics/t_005_update/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_005_update/rust/server/gpt-5/llm", "scorer_details": { - "data_parity_update_user": { + "seed_users_row": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-005-update-golden`.\n", - "phase": "call_reducer_golden" + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-005-update-golden`.\n", + "phase": "sql_golden", + "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" } }, "schema_parity": { @@ -1364,23 +1400,14 @@ "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-005-update-golden`.\n", "phase": "call_reducer_golden" } - }, - "seed_users_row": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-005-update-golden`.\n", - "phase": "sql_golden", - "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" - } } }, "vendor": "openai", - "started_at": "2026-01-23T20:12:10.015338220Z", - "finished_at": "2026-01-23T20:13:14.713691221Z" + "started_at": "2026-01-26T19:30:54.604964500Z", + "finished_at": "2026-01-26T19:31:53.617639721Z" }, "t_006_delete": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_006_delete", "lang": "rust", "golden_published": true, @@ -1412,29 +1439,28 @@ "sql": "SELECT COUNT(*) AS n FROM user WHERE id=1" } }, - "seed_users_row": { + "schema_parity": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-006-delete-golden`.\n", - "phase": "sql_golden", - "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" + "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-006-delete-golden`.\n", + "phase": "describe_golden" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:12:09.994528341Z", - "finished_at": "2026-01-23T20:12:46.205776277Z" + "started_at": "2026-01-26T19:30:54.580009457Z", + "finished_at": "2026-01-26T19:32:03.232098066Z" }, "t_007_crud": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_007_crud", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 4, "passed_tests": 1, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[spacetimedb::reducer]\npub fn crud(ctx: &ReducerContext) {\n // insert (id=1, name=\"Alice\", age=30, active=true)\n ctx.db.user().insert(User {\n id: 1,\n name: \"Alice\".to_string(),\n age: 30,\n active: true,\n });\n\n // insert (id=2, name=\"Bob\", age=22, active=false)\n ctx.db.user().insert(User {\n id: 2,\n name: \"Bob\".to_string(),\n age: 22,\n active: false,\n });\n\n // update (id=1, name=\"Alice2\", age=31, active=false)\n if let Some(mut u1) = ctx.db.user().id().find(1) {\n u1.name = \"Alice2\".to_string();\n u1.age = 31;\n u1.active = false;\n ctx.db.user().id().update(u1);\n }\n\n // delete id=2\n ctx.db.user().id().delete(2);\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[spacetimedb::reducer]\npub fn crud(ctx: &ReducerContext) {\n ctx.db.user().insert(User { id: 1, name: \"Alice\".to_string(), age: 30, active: true });\n ctx.db.user().insert(User { id: 2, name: \"Bob\".to_string(), age: 22, active: false });\n\n if ctx.db.user().id().find(1).is_some() {\n ctx.db.user().id().update(User { id: 1, name: \"Alice2\".to_string(), age: 31, active: false });\n }\n\n ctx.db.user().id().delete(2);\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-007-crud-golden", @@ -1442,21 +1468,12 @@ "work_dir_golden": "target/llm-runs/basics/t_007_crud/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_007_crud/rust/server/gpt-5/llm", "scorer_details": { - "crud_row_id1_parity": { + "schema_parity": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-007-crud-golden`.\n", - "phase": "call_reducer_golden" - } - }, - "crud_row_id2_deleted": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 0, - "expected": 0, - "sql": "SELECT COUNT(*) AS n FROM user WHERE id=2" + "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-007-crud-golden`.\n", + "phase": "describe_golden" } }, "crud_total_count_one": { @@ -1468,28 +1485,37 @@ "sql": "SELECT COUNT(*) AS n FROM user" } }, - "schema_parity": { + "crud_row_id1_parity": { "pass": false, "partial": 0.0, "notes": { - "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-007-crud-golden`.\n", - "phase": "describe_golden" + "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-007-crud-golden`.\n", + "phase": "call_reducer_golden" + } + }, + "crud_row_id2_deleted": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 0, + "expected": 0, + "sql": "SELECT COUNT(*) AS n FROM user WHERE id=2" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:12:10.004797508Z", - "finished_at": "2026-01-23T20:13:37.162002816Z" + "started_at": "2026-01-26T19:30:54.591258099Z", + "finished_at": "2026-01-26T19:32:19.735936055Z" }, "t_008_index_lookup": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_008_index_lookup", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 0, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[spacetimedb::table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n name: String,\n}\n\n#[spacetimedb::reducer]\npub fn lookup_user_name(ctx: &ReducerContext, id: i32) -> Result<(), String> {\n if let Some(user) = ctx.db.user().id().find(id) {\n ctx.db\n .result()\n .try_insert(ResultRow { id: user.id, name: user.name.clone() })?;\n Ok(())\n } else {\n Err(\"User not found\".to_string())\n }\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user, public)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[spacetimedb::table(name = result, public)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n name: String,\n}\n\n#[spacetimedb::reducer]\npub fn lookup_user_name(ctx: &ReducerContext, id: i32) {\n if let Some(u) = ctx.db.user().id().find(id) {\n ctx.db.result().id().delete(&id);\n ctx.db.result().insert(ResultRow { id: u.id, name: u.name });\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-008-index-lookup-golden", @@ -1497,6 +1523,15 @@ "work_dir_golden": "target/llm-runs/basics/t_008_index_lookup/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_008_index_lookup/rust/server/gpt-5/llm", "scorer_details": { + "seed_user_row": { + "pass": false, + "partial": 0.0, + "notes": { + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-008-index-lookup-golden`.\n", + "phase": "sql_golden", + "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" + } + }, "schema_parity": { "pass": false, "partial": 0.0, @@ -1512,30 +1547,21 @@ "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-008-index-lookup-golden`.\n", "phase": "call_reducer_golden" } - }, - "seed_user_row": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `basics-t-008-index-lookup-golden`.\n", - "phase": "sql_golden", - "sql": "INSERT INTO user(id, name, age, active) VALUES (1, 'Alice', 30, true)" - } } }, "vendor": "openai", - "started_at": "2026-01-23T20:12:46.729438058Z", - "finished_at": "2026-01-23T20:13:54.235945228Z" + "started_at": "2026-01-26T19:31:52.996077836Z", + "finished_at": "2026-01-26T19:32:44.567947473Z" }, "t_009_init": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_009_init", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 4, "passed_tests": 3, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[spacetimedb::reducer(init)]\npub fn init(ctx: &ReducerContext) -> Result<(), String> {\n ctx.db.user().insert(User { id: 1, name: \"Alice\".to_string(), age: 30, active: true });\n ctx.db.user().insert(User { id: 2, name: \"Bob\".to_string(), age: 22, active: false });\n Ok(())\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = user)]\npub struct User {\n #[primary_key]\n id: i32,\n name: String,\n age: i32,\n active: bool,\n}\n\n#[spacetimedb::reducer(init)]\npub fn init(ctx: &ReducerContext) -> Result<(), String> {\n ctx.db.user().insert(User {\n id: 1,\n name: \"Alice\".to_string(),\n age: 30,\n active: true,\n });\n ctx.db.user().insert(User {\n id: 2,\n name: \"Bob\".to_string(),\n age: 22,\n active: false,\n });\n Ok(())\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-009-init-golden", @@ -1543,13 +1569,13 @@ "work_dir_golden": "target/llm-runs/basics/t_009_init/rust/server/golden", "work_dir_llm": "target/llm-runs/basics/t_009_init/rust/server/gpt-5/llm", "scorer_details": { - "init_seed_bob": { + "init_seed_alice": { "pass": true, "partial": 1.0, "notes": { "actual": 1, "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM user WHERE id=2 AND name='Bob' AND age=22 AND active=false" + "sql": "SELECT COUNT(*) AS n FROM user WHERE id=1 AND name='Alice' AND age=30 AND active=true" } }, "schema_parity": { @@ -1569,22 +1595,22 @@ "sql": "SELECT COUNT(*) AS n FROM user" } }, - "init_seed_alice": { + "init_seed_bob": { "pass": true, "partial": 1.0, "notes": { "actual": 1, "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM user WHERE id=1 AND name='Alice' AND age=30 AND active=true" + "sql": "SELECT COUNT(*) AS n FROM user WHERE id=2 AND name='Bob' AND age=22 AND active=false" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:12:10.009828612Z", - "finished_at": "2026-01-23T20:12:45.617807272Z" + "started_at": "2026-01-26T19:30:54.597845517Z", + "finished_at": "2026-01-26T19:32:17.483969682Z" }, "t_010_connect": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_010_connect", "lang": "rust", "golden_published": true, @@ -1609,18 +1635,18 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:12:09.998960857Z", - "finished_at": "2026-01-23T20:13:28.197638116Z" + "started_at": "2026-01-26T19:30:54.585220084Z", + "finished_at": "2026-01-26T19:31:52.995965049Z" }, "t_011_helper_function": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_011_helper_function", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 0, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n sum: i32,\n}\n\nfn add(a: i32, b: i32) -> i32 {\n a + b\n}\n\n#[spacetimedb::reducer]\npub fn compute_sum(ctx: &ReducerContext, id: i32, a: i32, b: i32) {\n let s = add(a, b);\n ctx.db.result().insert(ResultRow { id, sum: s });\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n sum: i32,\n}\n\nfn add(a: i32, b: i32) -> i32 {\n a + b\n}\n\n#[spacetimedb::reducer]\npub fn compute_sum(ctx: &ReducerContext, id: i32, a: i32, b: i32) {\n let sum = add(a, b);\n ctx.db.result().insert(ResultRow { id, sum });\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-011-helper-function-golden", @@ -1663,18 +1689,18 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:13:14.723917629Z", - "finished_at": "2026-01-23T20:14:00.225654958Z" + "started_at": "2026-01-26T19:31:59.326285562Z", + "finished_at": "2026-01-26T19:32:34.857458085Z" }, "t_012_spacetime_product_type": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_012_spacetime_product_type", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 0, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[derive(spacetimedb::SpacetimeType, Clone, Debug)]\npub struct Score {\n left: i32,\n right: i32,\n}\n\n#[spacetimedb::table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n value: Score,\n}\n\n#[spacetimedb::reducer]\npub fn set_score(ctx: &ReducerContext, id: i32, left: i32, right: i32) {\n ctx.db.result().insert(ResultRow {\n id,\n value: Score { left, right },\n });\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[derive(spacetimedb::SpacetimeType, Clone)]\npub struct Score {\n left: i32,\n right: i32,\n}\n\n#[spacetimedb::table(name = result)]\npub struct ResultRow {\n #[primary_key]\n id: i32,\n value: Score,\n}\n\n#[spacetimedb::reducer]\npub fn set_score(ctx: &ReducerContext, id: i32, left: i32, right: i32) {\n ctx.db\n .result()\n .insert(ResultRow { id, value: Score { left, right } });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-012-spacetime-product-type-golden", @@ -1709,11 +1735,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:12:09.991277650Z", - "finished_at": "2026-01-23T20:12:46.725468970Z" + "started_at": "2026-01-26T19:30:31.399995435Z", + "finished_at": "2026-01-26T19:31:11.581019739Z" }, "t_013_spacetime_sum_type": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_013_spacetime_sum_type", "lang": "rust", "golden_published": false, @@ -1738,18 +1764,18 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:14:26.308049242Z", - "finished_at": "2026-01-23T20:14:26.308049242Z" + "started_at": "2026-01-26T19:32:55.980673255Z", + "finished_at": "2026-01-26T19:32:55.980673255Z" }, "t_014_elementary_columns": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_014_elementary_columns", "lang": "rust", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 0, - "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = primitive)]\npub struct Primitive {\n #[primary_key]\n id: i32,\n count: i32,\n total: i64,\n price: f32,\n ratio: f64,\n active: bool,\n name: String,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n ctx.db.primitive().insert(Primitive {\n id: 1,\n count: 2,\n total: 3_000_000_000,\n price: 1.5_f32,\n ratio: 2.25,\n active: true,\n name: \"Alice\".into(),\n });\n}", + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(name = primitive, public)]\npub struct Primitive {\n #[primary_key]\n id: i32,\n count: i32,\n total: i64,\n price: f32,\n ratio: f64,\n active: bool,\n name: String,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n ctx.db.primitive().insert(Primitive {\n id: 1,\n count: 2,\n total: 3_000_000_000,\n price: 1.5f32,\n ratio: 2.25,\n active: true,\n name: \"Alice\".to_string(),\n });\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-014-elementary-columns-golden", @@ -1757,13 +1783,12 @@ "work_dir_golden": "target/llm-runs/schema/t_014_elementary_columns/rust/server/golden", "work_dir_llm": "target/llm-runs/schema/t_014_elementary_columns/rust/server/gpt-5/llm", "scorer_details": { - "elementary_columns_row_count": { + "elementary_columns_row_parity": { "pass": false, "partial": 0.0, "notes": { - "actual": 0, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM primitive WHERE id=1" + "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-014-elementary-columns-golden`.\n", + "phase": "call_reducer_golden" } }, "schema_parity": { @@ -1774,21 +1799,22 @@ "phase": "describe_golden" } }, - "elementary_columns_row_parity": { + "elementary_columns_row_count": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime call failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-014-elementary-columns-golden`.\n", - "phase": "call_reducer_golden" + "actual": 0, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM primitive WHERE id=1" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:12:09.987997099Z", - "finished_at": "2026-01-23T20:13:50.463947582Z" + "started_at": "2026-01-26T19:30:30.882003264Z", + "finished_at": "2026-01-26T19:31:23.563975616Z" }, "t_015_product_type_columns": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_015_product_type_columns", "lang": "rust", "golden_published": false, @@ -1813,11 +1839,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:14:26.308063959Z", - "finished_at": "2026-01-23T20:14:26.308063959Z" + "started_at": "2026-01-26T19:32:55.980689378Z", + "finished_at": "2026-01-26T19:32:55.980689378Z" }, "t_016_sum_type_columns": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_016_sum_type_columns", "lang": "rust", "golden_published": false, @@ -1842,40 +1868,49 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:14:26.308044663Z", - "finished_at": "2026-01-23T20:14:26.308044663Z" + "started_at": "2026-01-26T19:32:55.980668485Z", + "finished_at": "2026-01-26T19:32:55.980668485Z" }, "t_017_scheduled_columns": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_017_scheduled_columns", "lang": "rust", - "golden_published": false, + "golden_published": true, "model_name": "GPT-5", - "total_tests": 1, - "passed_tests": 0, - "llm_output": null, + "total_tests": 2, + "passed_tests": 1, + "llm_output": "use std::time::Duration;\nuse spacetimedb::{ReducerContext, ScheduleAt, Table};\n\n#[spacetimedb::table(name = tick_timer, scheduled(tick))]\npub struct TickTimer {\n #[primary_key]\n #[auto_inc]\n scheduled_id: u64,\n scheduled_at: ScheduleAt,\n}\n\n#[spacetimedb::reducer]\npub fn tick(_ctx: &ReducerContext, _timer: TickTimer) {}\n\n#[spacetimedb::reducer(init)]\npub fn init(ctx: &ReducerContext) -> Result<(), String> {\n ctx.db.tick_timer().try_insert(TickTimer {\n scheduled_id: 0,\n scheduled_at: ScheduleAt::Interval(Duration::from_micros(50_000).into()),\n })?;\n Ok(())\n}", "category": "schema", "route_api_model": "gpt-5", - "golden_db": null, - "llm_db": null, - "work_dir_golden": null, - "work_dir_llm": null, + "golden_db": "schema-t-017-scheduled-columns-golden", + "llm_db": "schema-t-017-scheduled-columns-gpt-5-llm", + "work_dir_golden": "target/llm-runs/schema/t_017_scheduled_columns/rust/server/golden", + "work_dir_llm": "target/llm-runs/schema/t_017_scheduled_columns/rust/server/gpt-5/llm", "scorer_details": { - "publish_error": { + "schema_parity": { "pass": false, "partial": 0.0, "notes": { - "error": "LLM call timed out", - "phase": "build_or_publish" + "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-017-scheduled-columns-golden`.\n", + "phase": "describe_golden" + } + }, + "scheduled_seeded_one_row": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM tick_timer WHERE scheduled_id>=0" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:14:26.308033084Z", - "finished_at": "2026-01-23T20:14:26.308033084Z" + "started_at": "2026-01-26T19:29:24.576470966Z", + "finished_at": "2026-01-26T19:30:31.399943290Z" }, "t_018_constraints": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_018_constraints", "lang": "rust", "golden_published": false, @@ -1900,11 +1935,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:14:26.308021447Z", - "finished_at": "2026-01-23T20:14:26.308021447Z" + "started_at": "2026-01-26T19:32:55.980661308Z", + "finished_at": "2026-01-26T19:32:55.980661308Z" }, "t_019_many_to_many": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_019_many_to_many", "lang": "rust", "golden_published": false, @@ -1929,11 +1964,11 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:14:26.308054994Z", - "finished_at": "2026-01-23T20:14:26.308054994Z" + "started_at": "2026-01-26T19:32:55.980679692Z", + "finished_at": "2026-01-26T19:32:55.980679692Z" }, "t_020_ecs": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_020_ecs", "lang": "rust", "golden_published": false, @@ -1958,37 +1993,64 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:14:26.308059854Z", - "finished_at": "2026-01-23T20:14:26.308059854Z" + "started_at": "2026-01-26T19:32:55.980684633Z", + "finished_at": "2026-01-26T19:32:55.980684633Z" }, "t_021_multi_column_index": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "task": "t_021_multi_column_index", "lang": "rust", - "golden_published": false, + "golden_published": true, "model_name": "GPT-5", - "total_tests": 1, - "passed_tests": 0, - "llm_output": null, + "total_tests": 4, + "passed_tests": 3, + "llm_output": "use spacetimedb::{ReducerContext, Table};\n\n#[spacetimedb::table(\n name = log,\n index(name = by_user_day, btree(columns = [user_id, day]))\n)]\npub struct Log {\n #[primary_key]\n id: i32,\n user_id: i32,\n day: i32,\n message: String,\n}\n\n#[spacetimedb::reducer]\npub fn seed(ctx: &ReducerContext) {\n let _ = ctx.db.log().try_insert(Log { id: 1, user_id: 7, day: 1, message: \"a\".to_string() });\n let _ = ctx.db.log().try_insert(Log { id: 2, user_id: 7, day: 2, message: \"b\".to_string() });\n let _ = ctx.db.log().try_insert(Log { id: 3, user_id: 9, day: 1, message: \"c\".to_string() });\n}", "category": "schema", "route_api_model": "gpt-5", - "golden_db": null, - "llm_db": null, - "work_dir_golden": null, - "work_dir_llm": null, + "golden_db": "schema-t-021-multi-column-index-golden", + "llm_db": "schema-t-021-multi-column-index-gpt-5-llm", + "work_dir_golden": "target/llm-runs/schema/t_021_multi_column_index/rust/server/golden", + "work_dir_llm": "target/llm-runs/schema/t_021_multi_column_index/rust/server/gpt-5/llm", "scorer_details": { - "publish_error": { + "mcindex_lookup_u7_d2": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM log WHERE user_id=7 AND day=2" + } + }, + "schema_parity": { "pass": false, "partial": 0.0, "notes": { - "error": "LLM call timed out", - "phase": "build_or_publish" + "error": "describe failed: WARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: failed to find database `schema-t-021-multi-column-index-golden`.\n", + "phase": "describe_golden" + } + }, + "mcindex_lookup_u7_d1": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM log WHERE user_id=7 AND day=1" + } + }, + "mcindex_seed_count": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 3, + "expected": 3, + "sql": "SELECT COUNT(*) AS n FROM log" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:14:26.308040547Z", - "finished_at": "2026-01-23T20:14:26.308040547Z" + "started_at": "2026-01-26T19:29:24.579594233Z", + "finished_at": "2026-01-26T19:30:30.881922637Z" } } } @@ -2179,14 +2241,14 @@ "modes": [ { "mode": "docs", - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "models": [ { "name": "GPT-5", "route_api_model": "gpt-5", "tasks": { "t_000_empty_reducers": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_000_empty_reducers", "lang": "csharp", "golden_published": true, @@ -2209,25 +2271,25 @@ "llm_db": "basics-t-000-empty-reducers-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:20:05.908071Z", - "finished_at": "2026-01-23T20:21:02.544054377Z" + "started_at": "2026-01-26T19:38:54.385915075Z", + "finished_at": "2026-01-26T19:40:03.912043999Z" }, "t_001_basic_tables": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_001_basic_tables", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 1, "passed_tests": 1, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Table(Name = \"Product\")]\n public partial struct Product\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Title;\n public float Price;\n public bool InStock;\n }\n\n [SpacetimeDB.Table(Name = \"Note\")]\n public partial struct Note\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Body;\n public long Rating;\n public bool Pinned;\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\", Public = true)]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Table(Name = \"Product\", Public = true)]\n public partial struct Product\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Title;\n public float Price;\n public bool InStock;\n }\n\n [SpacetimeDB.Table(Name = \"Note\", Public = true)]\n public partial struct Note\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Body;\n public long Rating;\n public bool Pinned;\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-001-basic-tables-golden", @@ -2243,25 +2305,25 @@ "llm_db": "basics-t-001-basic-tables-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:20:17.520008030Z", - "finished_at": "2026-01-23T20:21:03.652127542Z" + "started_at": "2026-01-26T19:39:06.588178775Z", + "finished_at": "2026-01-26T19:40:26.686164444Z" }, "t_002_scheduled_table": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_002_scheduled_table", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 1, "passed_tests": 1, - "llm_output": "using System;\nusing SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"TickTimer\", Scheduled = nameof(Tick), ScheduledAt = nameof(ScheduledAt))]\n public partial struct TickTimer\n {\n [SpacetimeDB.PrimaryKey, SpacetimeDB.AutoInc]\n public ulong ScheduledId;\n public ScheduleAt ScheduledAt;\n }\n\n [SpacetimeDB.Reducer]\n public static void Tick(ReducerContext ctx, TickTimer timer)\n {\n }\n\n [SpacetimeDB.Reducer(ReducerKind.Init)]\n public static void Init(ReducerContext ctx)\n {\n ctx.Db.TickTimer.Insert(new TickTimer\n {\n ScheduledAt = new ScheduleAt.Interval(TimeSpan.FromMilliseconds(50))\n });\n }\n}", + "llm_output": "using System;\nusing SpacetimeDB;\n\npublic static partial class Module\n{\n [Table(Name = \"TickTimer\", Scheduled = nameof(Tick), ScheduledAt = nameof(ScheduledAt))]\n public partial struct TickTimer\n {\n [PrimaryKey, AutoInc]\n public ulong ScheduledId;\n public ScheduleAt ScheduledAt;\n }\n\n [Reducer]\n public static void Tick(ReducerContext ctx, TickTimer _timer)\n {\n }\n\n [Reducer(ReducerKind.Init)]\n public static void Init(ReducerContext ctx)\n {\n ctx.Db.TickTimer.Insert(new TickTimer\n {\n ScheduledId = 0,\n ScheduledAt = new ScheduleAt.Interval(TimeSpan.FromMilliseconds(50))\n });\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-002-scheduled-table-golden", @@ -2277,25 +2339,25 @@ "llm_db": "basics-t-002-scheduled-table-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:21:05.396968262Z", - "finished_at": "2026-01-23T20:21:59.590160864Z" + "started_at": "2026-01-26T19:40:26.686215935Z", + "finished_at": "2026-01-26T19:41:35.359471807Z" }, "t_003_struct_in_table": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_003_struct_in_table", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 1, "passed_tests": 1, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Type]\n public partial struct Position\n {\n public int X;\n public int Y;\n }\n\n [SpacetimeDB.Table(Name = \"Entity\")]\n public partial struct Entity\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public Position Pos;\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Type]\n public partial struct Position\n {\n public int X;\n public int Y;\n }\n\n [SpacetimeDB.Table(Name = \"Entity\", Public = true)]\n public partial struct Entity\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public Position Pos;\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-003-struct-in-table-golden", @@ -2311,18 +2373,18 @@ "llm_db": "basics-t-003-struct-in-table-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:20:12.029574819Z", - "finished_at": "2026-01-23T20:20:58.944028610Z" + "started_at": "2026-01-26T19:39:03.248071954Z", + "finished_at": "2026-01-26T19:40:22.292027026Z" }, "t_004_insert": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_004_insert", "lang": "csharp", "golden_published": true, @@ -2337,6 +2399,19 @@ "work_dir_golden": "target/llm-runs/basics/t_004_insert/csharp/server/golden", "work_dir_llm": "target/llm-runs/basics/t_004_insert/csharp/server/gpt-5/llm", "scorer_details": { + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "basics-t-004-insert-golden", + "llm_db": "basics-t-004-insert-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:44935", + "tables_diff": null, + "tables_equal": true + } + }, "data_parity_insert_user": { "pass": true, "partial": 1.0, @@ -2353,36 +2428,23 @@ "llm_out": "Id | Name | Age | Active ----+---------+-----+-------- 1 | \"Alice\" | 30 | true", "query": "SELECT Id, Name, Age, Active FROM User WHERE Id=1", "reducer": "InsertUser", - "server": "http://127.0.0.1:41045" - } - }, - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "basics-t-004-insert-golden", - "llm_db": "basics-t-004-insert-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:41045", - "tables_diff": null, - "tables_equal": true + "server": "http://127.0.0.1:44935" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:21:02.544101204Z", - "finished_at": "2026-01-23T20:21:46.575966420Z" + "started_at": "2026-01-26T19:40:05.942682308Z", + "finished_at": "2026-01-26T19:41:00.825583459Z" }, "t_005_update": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_005_update", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\", Public = true)]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer]\n public static void UpdateUser(ReducerContext ctx, int id, string name, int age, bool active)\n {\n ctx.Db.User.Id.Update(new User\n {\n Id = id,\n Name = name,\n Age = age,\n Active = active\n });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer]\n public static void UpdateUser(ReducerContext ctx, int id, string name, int age, bool active)\n {\n var user = ctx.Db.User.Id.Find(id) ?? throw new System.Exception(\"User not found\");\n user.Name = name;\n user.Age = age;\n user.Active = active;\n ctx.Db.User.Id.Update(user);\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-005-update-golden", @@ -2397,20 +2459,7 @@ "sql": "INSERT INTO User(Id, Name, Age, Active) VALUES (1, 'Alice', 30, true)" } }, - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "basics-t-005-update-golden", - "llm_db": "basics-t-005-update-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:41045", - "tables_diff": null, - "tables_equal": true - } - }, - "data_parity_update_user": { + "data_parity_update_user": { "pass": true, "partial": 1.0, "notes": { @@ -2426,23 +2475,36 @@ "llm_out": "Id | Name | Age | Active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", "query": "SELECT Id, Name, Age, Active FROM User WHERE Id=1", "reducer": "UpdateUser", - "server": "http://127.0.0.1:41045" + "server": "http://127.0.0.1:44935" + } + }, + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "basics-t-005-update-golden", + "llm_db": "basics-t-005-update-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:44935", + "tables_diff": null, + "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:19:53.867992725Z", - "finished_at": "2026-01-23T20:21:05.391950708Z" + "started_at": "2026-01-26T19:38:38.720018388Z", + "finished_at": "2026-01-26T19:40:05.937381701Z" }, "t_006_delete": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_006_delete", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\", Public = true)]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer]\n public static void DeleteUser(ReducerContext ctx, int id)\n {\n ctx.Db.User.Id.Delete(id);\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer]\n public static void DeleteUser(ReducerContext ctx, int id)\n {\n ctx.Db.User.Id.Delete(id);\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-006-delete-golden", @@ -2450,15 +2512,6 @@ "work_dir_golden": "target/llm-runs/basics/t_006_delete/csharp/server/golden", "work_dir_llm": "target/llm-runs/basics/t_006_delete/csharp/server/gpt-5/llm", "scorer_details": { - "delete_user_count_zero": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 0, - "expected": 0, - "sql": "SELECT COUNT(*) AS n FROM User WHERE Id=1" - } - }, "schema_parity": { "pass": true, "partial": 1.0, @@ -2467,7 +2520,7 @@ "llm_db": "basics-t-006-delete-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } @@ -2478,21 +2531,30 @@ "notes": { "sql": "INSERT INTO User(Id, Name, Age, Active) VALUES (1, 'Alice', 30, true)" } + }, + "delete_user_count_zero": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 0, + "expected": 0, + "sql": "SELECT COUNT(*) AS n FROM User WHERE Id=1" + } } }, "vendor": "openai", - "started_at": "2026-01-23T20:19:10.793697386Z", - "finished_at": "2026-01-23T20:19:53.867926470Z" + "started_at": "2026-01-26T19:37:37.167869929Z", + "finished_at": "2026-01-26T19:38:38.719937430Z" }, "t_007_crud": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_007_crud", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 4, "passed_tests": 4, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer]\n public static void Crud(ReducerContext ctx)\n {\n ctx.Db.User.Insert(new User { Id = 1, Name = \"Alice\", Age = 30, Active = true });\n ctx.Db.User.Insert(new User { Id = 2, Name = \"Bob\", Age = 22, Active = false });\n\n var found = ctx.Db.User.Id.Find(1);\n if (found is User user1)\n {\n user1.Name = \"Alice2\";\n user1.Age = 31;\n user1.Active = false;\n ctx.Db.User.Id.Update(user1);\n }\n\n ctx.Db.User.Id.Delete(2);\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer]\n public static void Crud(ReducerContext ctx)\n {\n ctx.Db.User.Insert(new User { Id = 1, Name = \"Alice\", Age = 30, Active = true });\n ctx.Db.User.Insert(new User { Id = 2, Name = \"Bob\", Age = 22, Active = false });\n\n if (ctx.Db.User.Id.Find(1) is User user1)\n {\n user1.Name = \"Alice2\";\n user1.Age = 31;\n user1.Active = false;\n ctx.Db.User.Id.Update(user1);\n }\n\n ctx.Db.User.Id.Delete(2);\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-007-crud-golden", @@ -2509,15 +2571,6 @@ "sql": "SELECT COUNT(*) AS n FROM User" } }, - "crud_row_id2_deleted": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 0, - "expected": 0, - "sql": "SELECT COUNT(*) AS n FROM User WHERE Id=2" - } - }, "schema_parity": { "pass": true, "partial": 1.0, @@ -2526,18 +2579,18 @@ "llm_db": "basics-t-007-crud-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } }, - "crud_total_count_one": { + "crud_row_id2_deleted": { "pass": true, "partial": 1.0, "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM User" + "actual": 0, + "expected": 0, + "sql": "SELECT COUNT(*) AS n FROM User WHERE Id=2" } }, "crud_row_id2_deleted": { @@ -2560,23 +2613,23 @@ "llm_out": "Id | Name | Age | Active ----+----------+-----+-------- 1 | \"Alice2\" | 31 | false", "query": "SELECT Id, Name, Age, Active FROM User WHERE Id=1", "reducer": "Crud", - "server": "http://127.0.0.1:41045" + "server": "http://127.0.0.1:44935" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:19:29.508011285Z", - "finished_at": "2026-01-23T20:20:17.519940667Z" + "started_at": "2026-01-26T19:37:59.027103288Z", + "finished_at": "2026-01-26T19:38:54.385590993Z" }, "t_008_index_lookup": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_008_index_lookup", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial class User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name = \"\";\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Table(Name = \"Result\")]\n public partial class Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name = \"\";\n }\n\n [SpacetimeDB.Reducer]\n public static void LookupUserName(ReducerContext ctx, int id)\n {\n if (ctx.Db.User.Id.Find(id) is User u)\n {\n ctx.Db.Result.Insert(new Result { Id = u.Id, Name = u.Name });\n }\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Table(Name = \"Result\")]\n public partial struct Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n }\n\n [SpacetimeDB.Reducer]\n public static void LookupUserName(ReducerContext ctx, int id)\n {\n if (ctx.Db.User.Id.Find(id) is User user)\n {\n ctx.Db.Result.Insert(new Result\n {\n Id = user.Id,\n Name = user.Name\n });\n }\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-008-index-lookup-golden", @@ -2592,7 +2645,7 @@ "llm_db": "basics-t-008-index-lookup-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } @@ -2617,23 +2670,23 @@ "llm_out": "Id | Name ----+--------- 1 | \"Alice\"", "query": "SELECT Id, Name FROM Result WHERE Id=1", "reducer": "LookupUserName", - "server": "http://127.0.0.1:41045" + "server": "http://127.0.0.1:44935" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:20:58.944081428Z", - "finished_at": "2026-01-23T20:21:57.704447793Z" + "started_at": "2026-01-26T19:40:05.937447735Z", + "finished_at": "2026-01-26T19:41:10.697769188Z" }, "t_009_init": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_009_init", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 4, "passed_tests": 4, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer(SpacetimeDB.ReducerKind.Init)]\n public static void Init(SpacetimeDB.ReducerContext ctx)\n {\n ctx.Db.User.Insert(new User { Id = 1, Name = \"Alice\", Age = 30, Active = true });\n ctx.Db.User.Insert(new User { Id = 2, Name = \"Bob\", Age = 22, Active = false });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public string Name;\n public int Age;\n public bool Active;\n }\n\n [SpacetimeDB.Reducer(ReducerKind.Init)]\n public static void Init(ReducerContext ctx)\n {\n ctx.Db.User.Insert(new User { Id = 1, Name = \"Alice\", Age = 30, Active = true });\n ctx.Db.User.Insert(new User { Id = 2, Name = \"Bob\", Age = 22, Active = false });\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-009-init-golden", @@ -2641,60 +2694,60 @@ "work_dir_golden": "target/llm-runs/basics/t_009_init/csharp/server/golden", "work_dir_llm": "target/llm-runs/basics/t_009_init/csharp/server/gpt-5/llm", "scorer_details": { - "init_total_two": { + "schema_parity": { "pass": true, "partial": 1.0, "notes": { - "actual": 2, - "expected": 2, - "sql": "SELECT COUNT(*) AS n FROM User" + "golden_db": "basics-t-009-init-golden", + "llm_db": "basics-t-009-init-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:44935", + "tables_diff": null, + "tables_equal": true } }, - "init_seed_bob": { + "init_seed_alice": { "pass": true, "partial": 1.0, "notes": { "actual": 1, "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM User WHERE Id=2 AND Name='Bob' AND Age=22 AND Active=false" + "sql": "SELECT COUNT(*) AS n FROM User WHERE Id=1 AND Name='Alice' AND Age=30 AND Active=true" } }, - "init_seed_alice": { + "init_seed_bob": { "pass": true, "partial": 1.0, "notes": { "actual": 1, "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM User WHERE Id=1 AND Name='Alice' AND Age=30 AND Active=true" + "sql": "SELECT COUNT(*) AS n FROM User WHERE Id=2 AND Name='Bob' AND Age=22 AND Active=false" } }, - "schema_parity": { + "init_total_two": { "pass": true, "partial": 1.0, "notes": { - "golden_db": "basics-t-009-init-golden", - "llm_db": "basics-t-009-init-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:41045", - "tables_diff": null, - "tables_equal": true + "actual": 2, + "expected": 2, + "sql": "SELECT COUNT(*) AS n FROM User" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:19:36.893890047Z", - "finished_at": "2026-01-23T20:20:12.029514649Z" + "started_at": "2026-01-26T19:38:16.753424300Z", + "finished_at": "2026-01-26T19:39:06.588120002Z" }, "t_010_connect": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_010_connect", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 1, "passed_tests": 1, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Event\")]\n public partial struct Event\n {\n [SpacetimeDB.PrimaryKey]\n [SpacetimeDB.AutoInc]\n public int Id;\n public string Kind;\n }\n\n [SpacetimeDB.Reducer(ReducerKind.ClientConnected)]\n public static void ClientConnected(ReducerContext ctx)\n {\n ctx.Db.Event.Insert(new Event { Id = 0, Kind = \"connected\" });\n }\n\n [SpacetimeDB.Reducer(ReducerKind.ClientDisconnected)]\n public static void ClientDisconnected(ReducerContext ctx)\n {\n ctx.Db.Event.Insert(new Event { Id = 0, Kind = \"disconnected\" });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Event\", Public = true)]\n public partial struct Event\n {\n [SpacetimeDB.PrimaryKey]\n [SpacetimeDB.AutoInc]\n public int Id;\n public string Kind;\n }\n\n [SpacetimeDB.Reducer(ReducerKind.ClientConnected)]\n public static void ClientConnected(ReducerContext ctx)\n {\n ctx.Db.Event.Insert(new Event { Id = 0, Kind = \"connected\" });\n }\n\n [SpacetimeDB.Reducer(ReducerKind.ClientDisconnected)]\n public static void ClientDisconnected(ReducerContext ctx)\n {\n ctx.Db.Event.Insert(new Event { Id = 0, Kind = \"disconnected\" });\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-010-connect-golden", @@ -2710,25 +2763,25 @@ "llm_db": "basics-t-010-connect-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } } }, "vendor": "openai", - "started_at": "2026-01-23T20:19:23.574032624Z", - "finished_at": "2026-01-23T20:20:05.908027898Z" + "started_at": "2026-01-26T19:37:47.380111761Z", + "finished_at": "2026-01-26T19:39:03.248030401Z" }, "t_011_helper_function": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_011_helper_function", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Result\", Public = true)]\n public partial struct Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public int Sum;\n }\n\n public static int Add(int a, int b)\n {\n return a + b;\n }\n\n [SpacetimeDB.Reducer]\n public static void ComputeSum(ReducerContext ctx, int id, int a, int b)\n {\n ctx.Db.Result.Insert(new Result { Id = id, Sum = Add(a, b) });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Result\")]\n public partial struct Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public int Sum;\n }\n\n private static int Add(int a, int b)\n {\n return a + b;\n }\n\n [SpacetimeDB.Reducer]\n public static void ComputeSum(ReducerContext ctx, int id, int a, int b)\n {\n ctx.Db.Result.Insert(new Result\n {\n Id = id,\n Sum = Add(a, b)\n });\n }\n}", "category": "basics", "route_api_model": "gpt-5", "golden_db": "basics-t-011-helper-function-golden", @@ -2753,7 +2806,7 @@ "llm_db": "basics-t-011-helper-function-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } @@ -2773,23 +2826,23 @@ "llm_out": "Id | Sum ----+----- 1 | 5", "query": "SELECT Id, Sum FROM Result WHERE Id=1", "reducer": "ComputeSum", - "server": "http://127.0.0.1:41045" + "server": "http://127.0.0.1:44935" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:21:05.392014348Z", - "finished_at": "2026-01-23T20:21:51.189712882Z" + "started_at": "2026-01-26T19:40:22.292081947Z", + "finished_at": "2026-01-26T19:41:08.915943296Z" }, "t_012_spacetime_product_type": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_012_spacetime_product_type", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Type]\n public partial struct Score\n {\n public int Left;\n public int Right;\n }\n\n [SpacetimeDB.Table(Name = \"Result\", Public = true)]\n public partial struct Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public Score Value;\n }\n\n [SpacetimeDB.Reducer]\n public static void SetScore(ReducerContext ctx, int id, int left, int right)\n {\n ctx.Db.Result.Insert(new Result\n {\n Id = id,\n Value = new Score { Left = left, Right = right }\n });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Type]\n public partial struct Score\n {\n public int Left;\n public int Right;\n }\n\n [SpacetimeDB.Table(Name = \"Result\", Public = true)]\n public partial struct Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public Score Value;\n }\n\n [SpacetimeDB.Reducer]\n public static void SetScore(ReducerContext ctx, int id, int left, int right)\n {\n ctx.Db.Result.Insert(new Result\n {\n Id = id,\n Value = new Score\n {\n Left = left,\n Right = right\n }\n });\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-012-spacetime-product-type-golden", @@ -2797,19 +2850,6 @@ "work_dir_golden": "target/llm-runs/schema/t_012_spacetime_product_type/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_012_spacetime_product_type/csharp/server/gpt-5/llm", "scorer_details": { - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "schema-t-012-spacetime-product-type-golden", - "llm_db": "schema-t-012-spacetime-product-type-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:41045", - "tables_diff": null, - "tables_equal": true - } - }, "product_type_row_parity": { "pass": true, "partial": 1.0, @@ -2825,7 +2865,7 @@ "llm_out": "Id | Value ----+----------------------- 1 | (Left = 2, Right = 3)", "query": "SELECT Id, Value FROM Result WHERE Id=1", "reducer": "SetScore", - "server": "http://127.0.0.1:41045" + "server": "http://127.0.0.1:44935" } }, "product_type_row_count": { @@ -2836,21 +2876,34 @@ "expected": 1, "sql": "SELECT COUNT(*) AS n FROM Result WHERE Id=1" } + }, + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "schema-t-012-spacetime-product-type-golden", + "llm_db": "schema-t-012-spacetime-product-type-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:44935", + "tables_diff": null, + "tables_equal": true + } } }, "vendor": "openai", - "started_at": "2026-01-23T20:18:54.161733902Z", - "finished_at": "2026-01-23T20:19:36.893826573Z" + "started_at": "2026-01-26T19:37:30.236090594Z", + "finished_at": "2026-01-26T19:38:16.753346626Z" }, "t_013_spacetime_sum_type": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_013_spacetime_sum_type", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Type]\n public partial struct Circle\n {\n public int Radius;\n }\n\n [SpacetimeDB.Type]\n public partial struct Rectangle\n {\n public int Width;\n public int Height;\n }\n\n [SpacetimeDB.Type]\n public partial record Shape : TaggedEnum<(Circle Circle, Rectangle Rectangle)> { }\n\n [SpacetimeDB.Table(Name = \"Result\")]\n public partial struct Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public Shape Value;\n }\n\n [SpacetimeDB.Reducer]\n public static void SetCircle(ReducerContext ctx, int id, int radius)\n {\n var value = new Shape.Circle(new Circle { Radius = radius });\n ctx.Db.Result.Insert(new Result { Id = id, Value = value });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Type]\n public partial struct Circle\n {\n public int Radius;\n }\n\n [SpacetimeDB.Type]\n public partial struct Rectangle\n {\n public int Width;\n public int Height;\n }\n\n [SpacetimeDB.Type]\n public partial record Shape : TaggedEnum<(Circle Circle, Rectangle Rectangle)> { }\n\n [SpacetimeDB.Table(Name = \"Result\", Public = true)]\n public partial struct Result\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public Shape Value;\n }\n\n [SpacetimeDB.Reducer]\n public static void SetCircle(ReducerContext ctx, int id, int radius)\n {\n var shape = new Shape.Circle(new Circle { Radius = radius });\n ctx.Db.Result.Insert(new Result\n {\n Id = id,\n Value = shape\n });\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-013-spacetime-sum-type-golden", @@ -2858,28 +2911,6 @@ "work_dir_golden": "target/llm-runs/schema/t_013_spacetime_sum_type/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_013_spacetime_sum_type/csharp/server/gpt-5/llm", "scorer_details": { - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "schema-t-013-spacetime-sum-type-golden", - "llm_db": "schema-t-013-spacetime-sum-type-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:34379", - "tables_diff": null, - "tables_equal": true - } - }, - "sum_type_row_count": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM Result WHERE Id=1" - } - }, "sum_type_row_parity": { "pass": true, "partial": 1.0, @@ -2894,7 +2925,16 @@ "llm_out": "Id | Value ----+-------------------------- 1 | (Circle = (Radius = 10))", "query": "SELECT Id, Value FROM Result WHERE Id=1", "reducer": "SetCircle", - "server": "http://127.0.0.1:41045" + "server": "http://127.0.0.1:44935" + } + }, + "sum_type_row_count": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM Result WHERE Id=1" } }, "schema_parity": { @@ -2905,27 +2945,18 @@ "llm_db": "schema-t-013-spacetime-sum-type-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } - }, - "sum_type_row_count": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM Result WHERE Id=1" - } } }, "vendor": "openai", - "started_at": "2026-01-23T20:17:49.057528012Z", - "finished_at": "2026-01-23T20:18:46.199910007Z" + "started_at": "2026-01-26T19:35:59.196578278Z", + "finished_at": "2026-01-26T19:37:03.535790946Z" }, "t_014_elementary_columns": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_014_elementary_columns", "lang": "csharp", "golden_published": true, @@ -2940,6 +2971,14 @@ "work_dir_golden": "target/llm-runs/schema/t_014_elementary_columns/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_014_elementary_columns/csharp/server/gpt-5/llm", "scorer_details": { + "elementary_columns_row_parity": { + "pass": false, + "partial": 0.0, + "notes": { + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `primitive`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44935/v1/database/c2000e37e733499f47b57d9f488477b94fccf2e4c5c6c32182171721cbaba64a/sql)\n", + "phase": "sql_golden" + } + }, "schema_parity": { "pass": true, "partial": 1.0, @@ -2948,7 +2987,7 @@ "llm_db": "schema-t-014-elementary-columns-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } @@ -2957,32 +2996,24 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `primitive`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c200c583183a5879f79de7a06c7395893137fa8a834f830859f2ee7a4c9e10d4/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `primitive`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44935/v1/database/c200e70d6c47b9f5b97a9584014efb7008b4c312687bfdbfe1b0ee1891420453/sql)\n", "phase": "sql" } - }, - "elementary_columns_row_parity": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `primitive`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2008dfd963859de34e7ba657c3416cbcee034a702128f54b0cb0b0b03aa914f/sql)\n", - "phase": "sql_golden" - } } }, "vendor": "openai", - "started_at": "2026-01-23T20:18:46.199983893Z", - "finished_at": "2026-01-23T20:19:29.507804243Z" + "started_at": "2026-01-26T19:37:03.535862900Z", + "finished_at": "2026-01-26T19:37:59.026960569Z" }, "t_015_product_type_columns": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_015_product_type_columns", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Type]\n public partial struct Address\n {\n public string Street;\n public int Zip;\n }\n\n [SpacetimeDB.Type]\n public partial struct Position\n {\n public int X;\n public int Y;\n }\n\n [SpacetimeDB.Table(Name = \"Profile\", Public = true)]\n public partial struct Profile\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public Address Home;\n public Address Work;\n public Position Pos;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n if (ctx.Db.Profile.Id.Find(1) == null)\n {\n ctx.Db.Profile.Insert(new Profile\n {\n Id = 1,\n Home = new Address { Street = \"1 Main\", Zip = 11111 },\n Work = new Address { Street = \"2 Broad\", Zip = 22222 },\n Pos = new Position { X = 7, Y = 9 },\n });\n }\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Type]\n public partial struct Address\n {\n public string Street;\n public int Zip;\n }\n\n [SpacetimeDB.Type]\n public partial struct Position\n {\n public int X;\n public int Y;\n }\n\n [SpacetimeDB.Table(Name = \"Profile\", Public = true)]\n public partial struct Profile\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public Address Home;\n public Address Work;\n public Position Pos;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n ctx.Db.Profile.Insert(new Profile\n {\n Id = 1,\n Home = new Address { Street = \"1 Main\", Zip = 11111 },\n Work = new Address { Street = \"2 Broad\", Zip = 22222 },\n Pos = new Position { X = 7, Y = 9 }\n });\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-015-product-type-columns-golden", @@ -2990,6 +3021,19 @@ "work_dir_golden": "target/llm-runs/schema/t_015_product_type_columns/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_015_product_type_columns/csharp/server/gpt-5/llm", "scorer_details": { + "schema_parity": { + "pass": true, + "partial": 1.0, + "notes": { + "golden_db": "schema-t-015-product-type-columns-golden", + "llm_db": "schema-t-015-product-type-columns-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:44935", + "tables_diff": null, + "tables_equal": true + } + }, "product_type_columns_row_count": { "pass": true, "partial": 1.0, @@ -3010,86 +3054,52 @@ "llm_out": "Id | Home | Work | Pos ----+----------------------------------+-----------------------------------+---------------- 1 | (Street = \"1 Main\", Zip = 11111) | (Street = \"2 Broad\", Zip = 22222) | (X = 7, Y = 9)", "query": "SELECT Id, Home, Work, Pos FROM Profile WHERE Id=1", "reducer": "Seed", - "server": "http://127.0.0.1:41045" - } - }, - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "schema-t-015-product-type-columns-golden", - "llm_db": "schema-t-015-product-type-columns-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:41045", - "tables_diff": null, - "tables_equal": true + "server": "http://127.0.0.1:44935" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:18:11.292039093Z", - "finished_at": "2026-01-23T20:18:54.161647622Z" + "started_at": "2026-01-26T19:36:38.953458698Z", + "finished_at": "2026-01-26T19:37:30.236009816Z" }, "t_016_sum_type_columns": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_016_sum_type_columns", "lang": "csharp", - "golden_published": true, + "golden_published": false, "model_name": "GPT-5", - "total_tests": 3, - "passed_tests": 1, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Type]\n public partial struct Circle\n {\n public int Radius;\n }\n\n [SpacetimeDB.Type]\n public partial struct Rectangle\n {\n public int Width;\n public int Height;\n }\n\n [SpacetimeDB.Type]\n public partial record Shape : TaggedEnum<(Circle Circle, Rectangle Rectangle)> { }\n\n [SpacetimeDB.Table(Name = \"Drawing\")]\n public partial struct Drawing\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public Shape A;\n public Shape B;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n ctx.Db.Drawing.Insert(new Drawing\n {\n Id = 1,\n A = new Shape.Circle(new Circle { Radius = 10 }),\n B = new Shape.Rectangle(new Rectangle { Width = 4, Height = 6 })\n });\n }\n}", + "total_tests": 1, + "passed_tests": 0, + "llm_output": null, "category": "schema", "route_api_model": "gpt-5", - "golden_db": "schema-t-016-sum-type-columns-golden", - "llm_db": "schema-t-016-sum-type-columns-gpt-5-llm", - "work_dir_golden": "target/llm-runs/schema/t_016_sum_type_columns/csharp/server/golden", - "work_dir_llm": "target/llm-runs/schema/t_016_sum_type_columns/csharp/server/gpt-5/llm", + "golden_db": null, + "llm_db": null, + "work_dir_golden": null, + "work_dir_llm": null, "scorer_details": { - "sum_type_columns_row_count": { - "pass": false, - "partial": 0.0, - "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c200b1fbaa5b44721798298318bab63a7fcd80d50f6e47060d881bfa066b8642/sql)\n", - "phase": "sql" - } - }, - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "schema-t-016-sum-type-columns-golden", - "llm_db": "schema-t-016-sum-type-columns-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:41045", - "tables_diff": null, - "tables_equal": true - } - }, - "sum_type_columns_row_parity": { + "publish_error": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `drawings`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2003b0da13c17c6220fd590cdb5d23015a0e698b01b6c6ecbfd10b5aabbbf4c/sql)\n", - "phase": "sql_golden" + "error": "LLM call timed out", + "phase": "build_or_publish" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:16:40.802337426Z", - "finished_at": "2026-01-23T20:18:08.899029179Z" + "started_at": "2026-01-26T19:41:35.359543125Z", + "finished_at": "2026-01-26T19:41:35.359543125Z" }, "t_017_scheduled_columns": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_017_scheduled_columns", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 2, "passed_tests": 1, - "llm_output": "using System;\nusing SpacetimeDB;\n\npublic static partial class Module\n{\n [Table(Name = \"TickTimer\", Scheduled = nameof(Tick), ScheduledAt = nameof(ScheduledAt))]\n public partial struct TickTimer\n {\n [PrimaryKey, AutoInc]\n public ulong ScheduledId;\n public ScheduleAt ScheduledAt;\n }\n\n [Reducer]\n public static void Tick(ReducerContext ctx, TickTimer timer)\n {\n // Scheduled tick handler (no-op)\n }\n\n [Reducer(ReducerKind.Init)]\n public static void Init(ReducerContext ctx)\n {\n if (ctx.Db.TickTimer.Count == 0)\n {\n ctx.Db.TickTimer.Insert(new TickTimer\n {\n ScheduledAt = new ScheduleAt.Interval(TimeSpan.FromMilliseconds(50))\n });\n }\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"TickTimer\", Scheduled = nameof(Tick), ScheduledAt = nameof(ScheduledAt))]\n public partial struct TickTimer\n {\n [SpacetimeDB.PrimaryKey]\n [SpacetimeDB.AutoInc]\n public ulong ScheduledId;\n public ScheduleAt ScheduledAt;\n }\n\n [SpacetimeDB.Reducer]\n public static void Tick(ReducerContext ctx, TickTimer _timer)\n {\n }\n\n [SpacetimeDB.Reducer(ReducerKind.Init)]\n public static void Init(ReducerContext ctx)\n {\n ctx.Db.TickTimer.Insert(new TickTimer\n {\n ScheduledAt = new ScheduleAt.Interval(TimeSpan.FromMicroseconds(50_000))\n });\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-017-scheduled-columns-golden", @@ -3105,7 +3115,7 @@ "llm_db": "schema-t-017-scheduled-columns-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } @@ -3114,24 +3124,24 @@ "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `tick_timer`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2000932373ef07be1f77db87f24b98a9819f6033c40da69c914e654c807ead2/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `tick_timer`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44935/v1/database/c2004563b2a3af718eb5a6d78c0e16523a6ad57949ac9dd820dbc2c2e11c8842/sql)\n", "phase": "sql" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:16:40.797164170Z", - "finished_at": "2026-01-23T20:18:08.735264338Z" + "started_at": "2026-01-26T19:35:08.495907944Z", + "finished_at": "2026-01-26T19:36:38.949408263Z" }, "t_018_constraints": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_018_constraints", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 3, "passed_tests": 3, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Account\", Public = true)]\n public partial struct Account\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n\n [SpacetimeDB.Unique]\n public string Email;\n\n [SpacetimeDB.Index.BTree(Name = \"by_name\")]\n public string Name;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n ctx.Db.Account.Insert(new Account { Id = 1, Email = \"a@example.com\", Name = \"Alice\" });\n ctx.Db.Account.Insert(new Account { Id = 2, Email = \"b@example.com\", Name = \"Bob\" });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Account\", Public = true)]\n [SpacetimeDB.Index.BTree(Name = \"by_name\", Columns = new[] { \"Name\" })]\n public partial struct Account\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n [SpacetimeDB.Unique]\n public string Email;\n public string Name;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n ctx.Db.Account.Insert(new Account { Id = 1, Email = \"a@example.com\", Name = \"Alice\" });\n ctx.Db.Account.Insert(new Account { Id = 2, Email = \"b@example.com\", Name = \"Bob\" });\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-018-constraints-golden", @@ -3139,6 +3149,15 @@ "work_dir_golden": "target/llm-runs/schema/t_018_constraints/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_018_constraints/csharp/server/gpt-5/llm", "scorer_details": { + "constraints_seed_two_rows": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM Account WHERE Id=2" + } + }, "schema_parity": { "pass": true, "partial": 1.0, @@ -3147,7 +3166,7 @@ "llm_db": "schema-t-018-constraints-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } @@ -3163,45 +3182,23 @@ "llm_out": "Id | Email | Name ----+-----------------+--------- 1 | \"a@example.com\" | \"Alice\"", "query": "SELECT Id, Email, Name FROM Account WHERE Id=1", "reducer": "Seed", - "server": "http://127.0.0.1:41045" - } - }, - "constraints_seed_two_rows": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM Account WHERE Id=2" - } - }, - "schema_parity": { - "pass": true, - "partial": 1.0, - "notes": { - "golden_db": "schema-t-018-constraints-golden", - "llm_db": "schema-t-018-constraints-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:34379", - "tables_diff": null, - "tables_equal": true + "server": "http://127.0.0.1:44935" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:16:40.794071431Z", - "finished_at": "2026-01-23T20:18:11.291994106Z" + "started_at": "2026-01-26T19:35:08.491947971Z", + "finished_at": "2026-01-26T19:35:59.196533076Z" }, "t_019_many_to_many": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_019_many_to_many", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 5, "passed_tests": 5, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\")]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int UserId;\n public string Name;\n }\n\n [SpacetimeDB.Table(Name = \"Group\")]\n public partial struct Group\n {\n [SpacetimeDB.PrimaryKey]\n public int GroupId;\n public string Title;\n }\n\n [SpacetimeDB.Table(Name = \"Membership\")]\n [SpacetimeDB.Index.BTree(Name = \"by_user\", Columns = new[] { \"UserId\" })]\n [SpacetimeDB.Index.BTree(Name = \"by_group\", Columns = new[] { \"GroupId\" })]\n public partial struct Membership\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public int UserId;\n public int GroupId;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n foreach (var m in ctx.Db.Membership.Iter())\n {\n ctx.Db.Membership.Id.Delete(m.Id);\n }\n foreach (var u in ctx.Db.User.Iter())\n {\n ctx.Db.User.UserId.Delete(u.UserId);\n }\n foreach (var g in ctx.Db.Group.Iter())\n {\n ctx.Db.Group.GroupId.Delete(g.GroupId);\n }\n\n ctx.Db.User.Insert(new User { UserId = 1, Name = \"Alice\" });\n ctx.Db.User.Insert(new User { UserId = 2, Name = \"Bob\" });\n\n ctx.Db.Group.Insert(new Group { GroupId = 10, Title = \"Admin\" });\n ctx.Db.Group.Insert(new Group { GroupId = 20, Title = \"Dev\" });\n\n ctx.Db.Membership.Insert(new Membership { Id = 1, UserId = 1, GroupId = 10 });\n ctx.Db.Membership.Insert(new Membership { Id = 2, UserId = 1, GroupId = 20 });\n ctx.Db.Membership.Insert(new Membership { Id = 3, UserId = 2, GroupId = 20 });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"User\", Public = true)]\n public partial struct User\n {\n [SpacetimeDB.PrimaryKey]\n public int UserId;\n public string Name;\n }\n\n [SpacetimeDB.Table(Name = \"Group\", Public = true)]\n public partial struct Group\n {\n [SpacetimeDB.PrimaryKey]\n public int GroupId;\n public string Title;\n }\n\n [SpacetimeDB.Table(Name = \"Membership\", Public = true)]\n [SpacetimeDB.Index.BTree(Name = \"by_user\", Columns = new[] { \"UserId\" })]\n [SpacetimeDB.Index.BTree(Name = \"by_group\", Columns = new[] { \"GroupId\" })]\n public partial struct Membership\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public int UserId;\n public int GroupId;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n // Ensure exactly these rows by clearing existing data first\n foreach (var m in ctx.Db.Membership.Iter())\n {\n ctx.Db.Membership.Id.Delete(m.Id);\n }\n foreach (var u in ctx.Db.User.Iter())\n {\n ctx.Db.User.UserId.Delete(u.UserId);\n }\n foreach (var g in ctx.Db.Group.Iter())\n {\n ctx.Db.Group.GroupId.Delete(g.GroupId);\n }\n\n // Users\n ctx.Db.User.Insert(new User { UserId = 1, Name = \"Alice\" });\n ctx.Db.User.Insert(new User { UserId = 2, Name = \"Bob\" });\n\n // Groups\n ctx.Db.Group.Insert(new Group { GroupId = 10, Title = \"Admin\" });\n ctx.Db.Group.Insert(new Group { GroupId = 20, Title = \"Dev\" });\n\n // Memberships\n ctx.Db.Membership.Insert(new Membership { Id = 1, UserId = 1, GroupId = 10 });\n ctx.Db.Membership.Insert(new Membership { Id = 2, UserId = 1, GroupId = 20 });\n ctx.Db.Membership.Insert(new Membership { Id = 3, UserId = 2, GroupId = 20 });\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-019-many-to-many-golden", @@ -3209,6 +3206,15 @@ "work_dir_golden": "target/llm-runs/schema/t_019_many_to_many/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_019_many_to_many/csharp/server/gpt-5/llm", "scorer_details": { + "memberships_three_rows": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 3, + "expected": 3, + "sql": "SELECT COUNT(*) AS n FROM Membership" + } + }, "schema_parity": { "pass": true, "partial": 1.0, @@ -3217,7 +3223,7 @@ "llm_db": "schema-t-019-many-to-many-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } @@ -3231,22 +3237,13 @@ "sql": "SELECT COUNT(*) AS n FROM Membership WHERE UserId=2 AND GroupId=20" } }, - "memberships_three_rows": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 3, - "expected": 3, - "sql": "SELECT COUNT(*) AS n FROM Membership" - } - }, "m2m_has_1_20": { "pass": true, "partial": 1.0, "notes": { "actual": 1, "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM Membership WHERE UserId=1 AND GroupId=20" + "sql": "SELECT COUNT(*) AS n FROM Membership WHERE UserId=2 AND GroupId=20" } }, "m2m_has_1_10": { @@ -3260,18 +3257,18 @@ } }, "vendor": "openai", - "started_at": "2026-01-23T20:18:08.899074821Z", - "finished_at": "2026-01-23T20:19:10.793593915Z" + "started_at": "2026-01-26T19:36:32.689581659Z", + "finished_at": "2026-01-26T19:37:37.167783708Z" }, "t_020_ecs": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_020_ecs", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 5, "passed_tests": 1, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Entity\", Public = true)]\n public partial struct Entity\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n }\n\n [SpacetimeDB.Table(Name = \"Position\", Public = true)]\n public partial struct Position\n {\n [SpacetimeDB.PrimaryKey]\n public int EntityId;\n public int X;\n public int Y;\n }\n\n [SpacetimeDB.Table(Name = \"Velocity\", Public = true)]\n public partial struct Velocity\n {\n [SpacetimeDB.PrimaryKey]\n public int EntityId;\n public int VX;\n public int VY;\n }\n\n [SpacetimeDB.Table(Name = \"NextPosition\", Public = true)]\n public partial struct NextPosition\n {\n [SpacetimeDB.PrimaryKey]\n public int EntityId;\n public int X;\n public int Y;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n // Entity 1\n if (ctx.Db.Entity.Id.Find(1) is not Entity)\n {\n ctx.Db.Entity.Insert(new Entity { Id = 1 });\n }\n if (ctx.Db.Position.EntityId.Find(1) is Position p1)\n {\n p1.X = 0;\n p1.Y = 0;\n ctx.Db.Position.EntityId.Update(p1);\n }\n else\n {\n ctx.Db.Position.Insert(new Position { EntityId = 1, X = 0, Y = 0 });\n }\n if (ctx.Db.Velocity.EntityId.Find(1) is Velocity v1)\n {\n v1.VX = 1;\n v1.VY = 0;\n ctx.Db.Velocity.EntityId.Update(v1);\n }\n else\n {\n ctx.Db.Velocity.Insert(new Velocity { EntityId = 1, VX = 1, VY = 0 });\n }\n\n // Entity 2\n if (ctx.Db.Entity.Id.Find(2) is not Entity)\n {\n ctx.Db.Entity.Insert(new Entity { Id = 2 });\n }\n if (ctx.Db.Position.EntityId.Find(2) is Position p2)\n {\n p2.X = 10;\n p2.Y = 0;\n ctx.Db.Position.EntityId.Update(p2);\n }\n else\n {\n ctx.Db.Position.Insert(new Position { EntityId = 2, X = 10, Y = 0 });\n }\n if (ctx.Db.Velocity.EntityId.Find(2) is Velocity v2)\n {\n v2.VX = -2;\n v2.VY = 3;\n ctx.Db.Velocity.EntityId.Update(v2);\n }\n else\n {\n ctx.Db.Velocity.Insert(new Velocity { EntityId = 2, VX = -2, VY = 3 });\n }\n }\n\n [SpacetimeDB.Reducer]\n public static void Step(ReducerContext ctx)\n {\n foreach (var pos in ctx.Db.Position.Iter())\n {\n var vOpt = ctx.Db.Velocity.EntityId.Find(pos.EntityId);\n if (vOpt is Velocity vel)\n {\n int nx = pos.X + vel.VX;\n int ny = pos.Y + vel.VY;\n\n var npOpt = ctx.Db.NextPosition.EntityId.Find(pos.EntityId);\n if (npOpt is NextPosition np)\n {\n np.X = nx;\n np.Y = ny;\n ctx.Db.NextPosition.EntityId.Update(np);\n }\n else\n {\n ctx.Db.NextPosition.Insert(new NextPosition\n {\n EntityId = pos.EntityId,\n X = nx,\n Y = ny\n });\n }\n }\n }\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Entity\", Public = true)]\n public partial struct Entity\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n }\n\n [SpacetimeDB.Table(Name = \"Position\", Public = true)]\n public partial struct Position\n {\n [SpacetimeDB.PrimaryKey]\n public int EntityId;\n public int X;\n public int Y;\n }\n\n [SpacetimeDB.Table(Name = \"Velocity\", Public = true)]\n public partial struct Velocity\n {\n [SpacetimeDB.PrimaryKey]\n public int EntityId;\n public int VX;\n public int VY;\n }\n\n [SpacetimeDB.Table(Name = \"NextPosition\", Public = true)]\n public partial struct NextPosition\n {\n [SpacetimeDB.PrimaryKey]\n public int EntityId;\n public int X;\n public int Y;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n ctx.Db.Entity.Insert(new Entity { Id = 1 });\n ctx.Db.Position.Insert(new Position { EntityId = 1, X = 0, Y = 0 });\n ctx.Db.Velocity.Insert(new Velocity { EntityId = 1, VX = 1, VY = 0 });\n\n ctx.Db.Entity.Insert(new Entity { Id = 2 });\n ctx.Db.Position.Insert(new Position { EntityId = 2, X = 10, Y = 0 });\n ctx.Db.Velocity.Insert(new Velocity { EntityId = 2, VX = -2, VY = 3 });\n }\n\n [SpacetimeDB.Reducer]\n public static void Step(ReducerContext ctx)\n {\n foreach (var pos in ctx.Db.Position.Iter())\n {\n if (ctx.Db.Velocity.EntityId.Find(pos.EntityId) is Velocity vel)\n {\n int nx = pos.X + vel.VX;\n int ny = pos.Y + vel.VY;\n\n if (ctx.Db.NextPosition.EntityId.Find(pos.EntityId) is NextPosition np)\n {\n np.X = nx;\n np.Y = ny;\n ctx.Db.NextPosition.EntityId.Update(np);\n }\n else\n {\n ctx.Db.NextPosition.Insert(new NextPosition { EntityId = pos.EntityId, X = nx, Y = ny });\n }\n }\n }\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-020-ecs-golden", @@ -3279,65 +3276,65 @@ "work_dir_golden": "target/llm-runs/schema/t_020_ecs/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_020_ecs/csharp/server/gpt-5/llm", "scorer_details": { - "ecs_next_pos_entity1": { - "pass": false, - "partial": 0.0, + "schema_parity": { + "pass": true, + "partial": 1.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2005b7d5d9b2b6b33a4a581ebd8661a3b0380c077f59eee8e552ef3c67ff1b9/sql)\n", - "phase": "sql" + "golden_db": "schema-t-020-ecs-golden", + "llm_db": "schema-t-020-ecs-gpt-5-llm", + "reducers_diff": null, + "reducers_equal": true, + "server": "http://127.0.0.1:44935", + "tables_diff": null, + "tables_equal": true } }, "ecs_seed_positions_count": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2005b7d5d9b2b6b33a4a581ebd8661a3b0380c077f59eee8e552ef3c67ff1b9/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44935/v1/database/c2003766705eb1f0e9f55468e9bf8d13f967d7125178a2028f2dd6ca5f43756d/sql)\n", "phase": "sql" } }, - "ecs_next_pos_entity2": { + "ecs_step_next_positions_count": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2005b7d5d9b2b6b33a4a581ebd8661a3b0380c077f59eee8e552ef3c67ff1b9/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44935/v1/database/c2003766705eb1f0e9f55468e9bf8d13f967d7125178a2028f2dd6ca5f43756d/sql)\n", "phase": "sql" } }, - "ecs_step_next_positions_count": { + "ecs_next_pos_entity2": { "pass": false, "partial": 0.0, "notes": { - "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:41045/v1/database/c2005b7d5d9b2b6b33a4a581ebd8661a3b0380c077f59eee8e552ef3c67ff1b9/sql)\n", + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44935/v1/database/c2003766705eb1f0e9f55468e9bf8d13f967d7125178a2028f2dd6ca5f43756d/sql)\n", "phase": "sql" } }, - "schema_parity": { - "pass": true, - "partial": 1.0, + "ecs_next_pos_entity1": { + "pass": false, + "partial": 0.0, "notes": { - "golden_db": "schema-t-020-ecs-golden", - "llm_db": "schema-t-020-ecs-gpt-5-llm", - "reducers_diff": null, - "reducers_equal": true, - "server": "http://127.0.0.1:41045", - "tables_diff": null, - "tables_equal": true + "error": "spacetime sql failed:\nWARNING: This command is UNSTABLE and subject to breaking changes.\n\nError: no such table: `next_positions`. If the table exists, it may be marked private.\n\nCaused by:\n HTTP status client error (400 Bad Request) for url (http://127.0.0.1:44935/v1/database/c2003766705eb1f0e9f55468e9bf8d13f967d7125178a2028f2dd6ca5f43756d/sql)\n", + "phase": "sql" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:18:08.902649901Z", - "finished_at": "2026-01-23T20:19:23.573927579Z" + "started_at": "2026-01-26T19:36:38.949546269Z", + "finished_at": "2026-01-26T19:37:47.379943704Z" }, "t_021_multi_column_index": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "task": "t_021_multi_column_index", "lang": "csharp", "golden_published": true, "model_name": "GPT-5", "total_tests": 4, "passed_tests": 4, - "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Log\")]\n [SpacetimeDB.Index.BTree(Name = \"by_user_day\", Columns = [\"UserId\", \"Day\"])]\n public partial struct Log\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public int UserId;\n public int Day;\n public string Message;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n ctx.Db.Log.Insert(new Log { Id = 1, UserId = 7, Day = 1, Message = \"a\" });\n ctx.Db.Log.Insert(new Log { Id = 2, UserId = 7, Day = 2, Message = \"b\" });\n ctx.Db.Log.Insert(new Log { Id = 3, UserId = 9, Day = 1, Message = \"c\" });\n }\n}", + "llm_output": "using SpacetimeDB;\n\npublic static partial class Module\n{\n [SpacetimeDB.Table(Name = \"Log\", Public = true)]\n [SpacetimeDB.Index.BTree(Name = \"by_user_day\", Columns = new[] { \"UserId\", \"Day\" })]\n public partial struct Log\n {\n [SpacetimeDB.PrimaryKey]\n public int Id;\n public int UserId;\n public int Day;\n public string Message;\n }\n\n [SpacetimeDB.Reducer]\n public static void Seed(ReducerContext ctx)\n {\n ctx.Db.Log.Insert(new Log { Id = 1, UserId = 7, Day = 1, Message = \"a\" });\n ctx.Db.Log.Insert(new Log { Id = 2, UserId = 7, Day = 2, Message = \"b\" });\n ctx.Db.Log.Insert(new Log { Id = 3, UserId = 9, Day = 1, Message = \"c\" });\n }\n}", "category": "schema", "route_api_model": "gpt-5", "golden_db": "schema-t-021-multi-column-index-golden", @@ -3345,6 +3342,15 @@ "work_dir_golden": "target/llm-runs/schema/t_021_multi_column_index/csharp/server/golden", "work_dir_llm": "target/llm-runs/schema/t_021_multi_column_index/csharp/server/gpt-5/llm", "scorer_details": { + "mcindex_seed_count": { + "pass": true, + "partial": 1.0, + "notes": { + "actual": 3, + "expected": 3, + "sql": "SELECT COUNT(*) AS n FROM Log" + } + }, "schema_parity": { "pass": true, "partial": 1.0, @@ -3353,20 +3359,11 @@ "llm_db": "schema-t-021-multi-column-index-gpt-5-llm", "reducers_diff": null, "reducers_equal": true, - "server": "http://127.0.0.1:41045", + "server": "http://127.0.0.1:44935", "tables_diff": null, "tables_equal": true } }, - "mcindex_lookup_u7_d2": { - "pass": true, - "partial": 1.0, - "notes": { - "actual": 1, - "expected": 1, - "sql": "SELECT COUNT(*) AS n FROM Log WHERE UserId=7 AND Day=2" - } - }, "mcindex_lookup_u7_d1": { "pass": true, "partial": 1.0, @@ -3376,19 +3373,19 @@ "sql": "SELECT COUNT(*) AS n FROM Log WHERE UserId=7 AND Day=1" } }, - "mcindex_seed_count": { + "mcindex_lookup_u7_d2": { "pass": true, "partial": 1.0, "notes": { - "actual": 3, - "expected": 3, - "sql": "SELECT COUNT(*) AS n FROM Log" + "actual": 1, + "expected": 1, + "sql": "SELECT COUNT(*) AS n FROM Log WHERE UserId=7 AND Day=2" } } }, "vendor": "openai", - "started_at": "2026-01-23T20:16:40.799865241Z", - "finished_at": "2026-01-23T20:17:49.057471707Z" + "started_at": "2026-01-26T19:35:08.500770472Z", + "finished_at": "2026-01-26T19:36:32.689520614Z" } } } diff --git a/docs/llms/docs-benchmark-summary.json b/docs/llms/docs-benchmark-summary.json index 8e7f8400b57..fa057f8e85f 100644 --- a/docs/llms/docs-benchmark-summary.json +++ b/docs/llms/docs-benchmark-summary.json @@ -1,11 +1,11 @@ { "version": 1, - "generated_at": "2026-01-23T20:21:59.670Z", + "generated_at": "2026-01-26T19:41:35.586Z", "by_language": { "csharp": { "modes": { "docs": { - "hash": "0bdd5572150f1bebf8032e2007d3a7644df903777de6c1ad070cab80e77b3ed2", + "hash": "2f6071a69fd778167c45e20453bc018eebc468cc87681c455f819adfa10148a0", "models": { "GPT-5": { "categories": { @@ -19,20 +19,20 @@ }, "schema": { "tasks": 10, - "total_tests": 34, - "passed_tests": 25, - "pass_pct": 73.52941, - "task_pass_equiv": 7.3666663, - "task_pass_pct": 73.666664 + "total_tests": 32, + "passed_tests": 24, + "pass_pct": 75.0, + "task_pass_equiv": 7.033333, + "task_pass_pct": 70.33333 } }, "totals": { "tasks": 22, - "total_tests": 61, - "passed_tests": 52, - "pass_pct": 85.2459, - "task_pass_equiv": 19.366667, - "task_pass_pct": 88.030304 + "total_tests": 59, + "passed_tests": 51, + "pass_pct": 86.44068, + "task_pass_equiv": 19.033333, + "task_pass_pct": 86.515144 } } } @@ -42,7 +42,7 @@ "rust": { "modes": { "docs": { - "hash": "315390340d7551db2791f061b9bff7602dc13350b7a4caee6aca61ef97867ec9", + "hash": "a9b7f59b2c00330aa9e00220d45b9d8f7d257f9b10dc9f37b56a1e954c2b5117", "models": { "GPT-5": { "categories": { @@ -56,20 +56,20 @@ }, "schema": { "tasks": 10, - "total_tests": 14, - "passed_tests": 0, - "pass_pct": 0.0, - "task_pass_equiv": 0.0, - "task_pass_pct": 0.0 + "total_tests": 18, + "passed_tests": 4, + "pass_pct": 22.222221, + "task_pass_equiv": 1.25, + "task_pass_pct": 12.5 } }, "totals": { "tasks": 22, - "total_tests": 41, - "passed_tests": 5, - "pass_pct": 12.195122, - "task_pass_equiv": 1.3333334, - "task_pass_pct": 6.060606 + "total_tests": 45, + "passed_tests": 9, + "pass_pct": 20.0, + "task_pass_equiv": 2.5833335, + "task_pass_pct": 11.742425 } } } @@ -90,19 +90,19 @@ "schema": { "tasks": 10, "total_tests": 34, - "passed_tests": 26, - "pass_pct": 76.47059, - "task_pass_equiv": 7.5333333, - "task_pass_pct": 75.333336 + "passed_tests": 24, + "pass_pct": 70.588234, + "task_pass_equiv": 6.8666663, + "task_pass_pct": 68.666664 } }, "totals": { "tasks": 22, "total_tests": 61, - "passed_tests": 51, - "pass_pct": 83.60656, - "task_pass_equiv": 17.533333, - "task_pass_pct": 79.69697 + "passed_tests": 49, + "pass_pct": 80.327866, + "task_pass_equiv": 16.866667, + "task_pass_pct": 76.666664 } } } From 85dc1dc4fb5494269211e30092198460826b1f7d Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Wed, 28 Jan 2026 09:53:35 -0800 Subject: [PATCH 03/18] [2.0 Breaking] `Sender` changes for C# modules (#4143) # Description of Changes Make `Sender` a method on [Reducer|View|Procedure|Tx]Context in C#. Equivalent changes to https://github.com/clockworklabs/SpacetimeDB/pull/4101. # API and ABI breaking changes API breaking # Expected complexity level and risk 1 # Testing Pure refactor, no additional testing. --- .../diag/snapshots/Module#FFI.verified.cs | 21 +++++++++--- .../server/snapshots/Module#FFI.verified.cs | 21 +++++++++--- crates/bindings-csharp/Codegen/Module.cs | 20 +++++++++--- .../Runtime/Internal/TxContext.cs | 7 ++-- .../Runtime/ProcedureContext.cs | 10 ++++-- demo/Blackholio/server-csharp/Lib.cs | 16 +++++----- .../00400-key-architecture.md | 2 +- .../00300-tutorials/00100-chat-app.md | 12 +++---- .../00300-unity-tutorial/00300-part-2.md | 4 +-- .../00300-unity-tutorial/00400-part-3.md | 10 +++--- .../00300-unity-tutorial/00500-part-4.md | 4 +-- .../00400-unreal-tutorial/00300-part-2.md | 4 +-- .../00400-unreal-tutorial/00400-part-3.md | 10 +++--- .../00400-unreal-tutorial/00500-part-4.md | 4 +-- .../00100-databases/00500-cheat-sheet.md | 4 +-- .../00300-reducers/00400-reducer-context.md | 4 +-- .../00300-reducers/00500-lifecycle.md | 6 ++-- .../00300-reducers/00600-error-handling.md | 2 +- .../00200-functions/00500-views.md | 6 ++-- docs/docs/00200-core-concepts/00300-tables.md | 2 +- .../00300-tables/00210-file-storage.md | 2 +- .../00300-tables/00400-access-permissions.md | 8 ++--- .../00100-how-to/00300-logging.md | 4 +-- docs/static/llms.md | 32 +++++++++---------- modules/module-test-cs/Lib.cs | 6 ++-- modules/sdk-test-connect-disconnect-cs/Lib.cs | 4 +-- modules/sdk-test-cs/Lib.cs | 8 ++--- .../examples~/regression-tests/server/Lib.cs | 24 +++++++------- templates/chat-console-cs/spacetimedb/Lib.cs | 12 +++---- 29 files changed, 155 insertions(+), 114 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs index 90eb00d3eaf..0731b890923 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs @@ -1,4 +1,4 @@ -//HintName: FFI.cs +//HintName: FFI.cs // #nullable enable // The runtime already defines SpacetimeDB.Internal.LocalReadOnly in Runtime\Internal\Module.cs as an empty partial type. @@ -17,7 +17,6 @@ namespace SpacetimeDB { public sealed record ReducerContext : DbContext, Internal.IReducerContext { - public readonly Identity Sender; public readonly ConnectionId? ConnectionId; public readonly Random Rng; public readonly Timestamp Timestamp; @@ -29,6 +28,8 @@ public sealed record ReducerContext : DbContext, Internal.IReducerContext // We need this property to be non-static for parity with client SDK. public Identity Identity => Internal.IReducerContext.GetIdentity(); + private readonly Identity _sender; + internal ReducerContext( Identity identity, ConnectionId? connectionId, @@ -37,7 +38,7 @@ internal ReducerContext( AuthCtx? senderAuth = null ) { - Sender = identity; + _sender = identity; ConnectionId = connectionId; Rng = random; Timestamp = time; @@ -45,6 +46,11 @@ internal ReducerContext( CounterUuid = 0; } + /// + /// The identity of the client that invoked the reducer. + /// + public Identity Sender() => _sender; + /// /// Create a new random `v4` using the built-in RNG. /// @@ -209,13 +215,18 @@ public sealed class Local : global::SpacetimeDB.LocalBase public sealed record ViewContext : DbContext, Internal.IViewContext { - public Identity Sender { get; } + private readonly Identity _sender; internal ViewContext(Identity sender, Internal.LocalReadOnly db) : base(db) { - Sender = sender; + _sender = sender; } + + /// + /// The identity of the client that invoked the view. + /// + public Identity Sender() => _sender; } public sealed record AnonymousViewContext diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs index f4d86c2ddbc..86a559890c1 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs @@ -1,4 +1,4 @@ -//HintName: FFI.cs +//HintName: FFI.cs // #nullable enable // The runtime already defines SpacetimeDB.Internal.LocalReadOnly in Runtime\Internal\Module.cs as an empty partial type. @@ -17,7 +17,6 @@ namespace SpacetimeDB { public sealed record ReducerContext : DbContext, Internal.IReducerContext { - public readonly Identity Sender; public readonly ConnectionId? ConnectionId; public readonly Random Rng; public readonly Timestamp Timestamp; @@ -29,6 +28,8 @@ public sealed record ReducerContext : DbContext, Internal.IReducerContext // We need this property to be non-static for parity with client SDK. public Identity Identity => Internal.IReducerContext.GetIdentity(); + private readonly Identity _sender; + internal ReducerContext( Identity identity, ConnectionId? connectionId, @@ -37,7 +38,7 @@ internal ReducerContext( AuthCtx? senderAuth = null ) { - Sender = identity; + _sender = identity; ConnectionId = connectionId; Rng = random; Timestamp = time; @@ -45,6 +46,11 @@ internal ReducerContext( CounterUuid = 0; } + /// + /// The identity of the client that invoked the reducer. + /// + public Identity Sender() => _sender; + /// /// Create a new random `v4` using the built-in RNG. /// @@ -199,13 +205,18 @@ public sealed class Local : global::SpacetimeDB.LocalBase public sealed record ViewContext : DbContext, Internal.IViewContext { - public Identity Sender { get; } + private readonly Identity _sender; internal ViewContext(Identity sender, Internal.LocalReadOnly db) : base(db) { - Sender = sender; + _sender = sender; } + + /// + /// The identity of the client that invoked the view. + /// + public Identity Sender() => _sender; } public sealed record AnonymousViewContext diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 63331bba5b6..e927f8832a4 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -1737,7 +1737,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context) namespace SpacetimeDB { public sealed record ReducerContext : DbContext, Internal.IReducerContext { - public readonly Identity Sender; public readonly ConnectionId? ConnectionId; public readonly Random Rng; public readonly Timestamp Timestamp; @@ -1747,16 +1746,24 @@ public sealed record ReducerContext : DbContext, Internal.IReducerContext // We need this property to be non-static for parity with client SDK. public Identity Identity => Internal.IReducerContext.GetIdentity(); + private readonly Identity _sender; + internal ReducerContext(Identity identity, ConnectionId? connectionId, Random random, Timestamp time, AuthCtx? senderAuth = null) { - Sender = identity; + _sender = identity; ConnectionId = connectionId; Rng = random; Timestamp = time; SenderAuth = senderAuth ?? AuthCtx.BuildFromSystemTables(connectionId, identity); CounterUuid = 0; } + + /// + /// The identity of the client that invoked the reducer. + /// + public Identity Sender() => _sender; + /// /// Create a new random `v4` using the built-in RNG. /// @@ -1891,13 +1898,18 @@ public sealed class Local : global::SpacetimeDB.LocalBase { public sealed record ViewContext : DbContext, Internal.IViewContext { - public Identity Sender { get; } + private readonly Identity _sender; internal ViewContext(Identity sender, Internal.LocalReadOnly db) : base(db) { - Sender = sender; + _sender = sender; } + + /// + /// The identity of the client that invoked the view. + /// + public Identity Sender() => _sender; } public sealed record AnonymousViewContext : DbContext, Internal.IAnonymousViewContext diff --git a/crates/bindings-csharp/Runtime/Internal/TxContext.cs b/crates/bindings-csharp/Runtime/Internal/TxContext.cs index d5bea2febd9..f8465e78d56 100644 --- a/crates/bindings-csharp/Runtime/Internal/TxContext.cs +++ b/crates/bindings-csharp/Runtime/Internal/TxContext.cs @@ -9,13 +9,16 @@ public sealed class TxContext( Random rng ) { + private readonly Identity _sender = sender; + public Local Db { get; } = db; - public Identity Sender { get; } = sender; public ConnectionId? ConnectionId { get; } = connectionId; public Timestamp Timestamp { get; } = timestamp; public AuthCtx SenderAuth { get; } = senderAuth; public Random Rng { get; } = rng; + public Identity Sender() => _sender; + public TxContext WithTimestamp(Timestamp ts) => - new(Db, Sender, ConnectionId, ts, SenderAuth, Rng); + new(Db, _sender, ConnectionId, ts, SenderAuth, Rng); } diff --git a/crates/bindings-csharp/Runtime/ProcedureContext.cs b/crates/bindings-csharp/Runtime/ProcedureContext.cs index 4eb8583b7d5..1b878b8e549 100644 --- a/crates/bindings-csharp/Runtime/ProcedureContext.cs +++ b/crates/bindings-csharp/Runtime/ProcedureContext.cs @@ -10,8 +10,11 @@ public abstract class ProcedureContextBase( Timestamp time ) : Internal.IInternalProcedureContext { + private readonly Identity _sender = sender; + + public Identity Sender() => _sender; + public static Identity Identity => Internal.IProcedureContext.GetIdentity(); - public Identity Sender { get; } = sender; public ConnectionId? ConnectionId { get; } = connectionId; public Random Rng { get; } = random; public Timestamp Timestamp { get; private set; } = time; @@ -47,7 +50,7 @@ public Internal.TxContext EnterTxContext(long timestampMicros) txContext?.WithTimestamp(timestamp) ?? new Internal.TxContext( CreateLocal(), - Sender, + _sender, ConnectionId, timestamp, SenderAuth, @@ -229,8 +232,9 @@ public abstract class ProcedureTxContextBase(Internal.TxContext inner) internal void Refresh(Internal.TxContext inner) => Inner = inner; + public Identity Sender() => Inner.Sender(); + public LocalBase Db => (LocalBase)Inner.Db; - public Identity Sender => Inner.Sender; public ConnectionId? ConnectionId => Inner.ConnectionId; public Timestamp Timestamp => Inner.Timestamp; public AuthCtx SenderAuth => Inner.SenderAuth; diff --git a/demo/Blackholio/server-csharp/Lib.cs b/demo/Blackholio/server-csharp/Lib.cs index 20e26cf99e6..542a7040037 100644 --- a/demo/Blackholio/server-csharp/Lib.cs +++ b/demo/Blackholio/server-csharp/Lib.cs @@ -138,7 +138,7 @@ public static void Init(ReducerContext ctx) [Reducer(ReducerKind.ClientConnected)] public static void Connect(ReducerContext ctx) { - var player = ctx.Db.logged_out_player.identity.Find(ctx.Sender); + var player = ctx.Db.logged_out_player.identity.Find(ctx.Sender()); if (player != null) { ctx.Db.player.Insert(player.Value); @@ -157,7 +157,7 @@ public static void Connect(ReducerContext ctx) { ctx.Db.player.Insert(new Player { - identity = ctx.Sender, + identity = ctx.Sender(), name = "", }); } @@ -166,7 +166,7 @@ public static void Connect(ReducerContext ctx) [Reducer(ReducerKind.ClientDisconnected)] public static void Disconnect(ReducerContext ctx) { - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("Player not found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("Player not found"); foreach (var circle in ctx.Db.circle.player_id.Filter(player.player_id)) { var entity = ctx.Db.entity.entity_id.Find(circle.entity_id) ?? throw new Exception("Could not find circle"); @@ -183,7 +183,7 @@ public static void Disconnect(ReducerContext ctx) public static void EnterGame(ReducerContext ctx, string name) { Log.Info($"Creating player with name {name}"); - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("Player not found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("Player not found"); player.name = name; ctx.Db.player.identity.Update(player); SpawnPlayerInitialCircle(ctx, player.player_id); @@ -192,7 +192,7 @@ public static void EnterGame(ReducerContext ctx, string name) [Reducer] public static void Respawn(ReducerContext ctx) { - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("No such player found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("No such player found"); SpawnPlayerInitialCircle(ctx, player.player_id); } @@ -200,7 +200,7 @@ public static void Respawn(ReducerContext ctx) [Reducer] public static void Suicide(ReducerContext ctx) { - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("No such player found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("No such player found"); foreach (var circle in ctx.Db.circle.player_id.Filter(player.player_id)) { @@ -246,7 +246,7 @@ public static Entity SpawnCircleAt(ReducerContext ctx, int player_id, int mass, [Reducer] public static void UpdatePlayerInput(ReducerContext ctx, DbVector2 direction) { - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("Player not found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("Player not found"); foreach (var c in ctx.Db.circle.player_id.Filter(player.player_id)) { var circle = c; @@ -449,7 +449,7 @@ public static void DestroyEntity(ReducerContext ctx, int entityId) [Reducer] public static void PlayerSplit(ReducerContext ctx) { - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("Sender has no player"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("Sender has no player"); List circles = ctx.Db.circle.player_id.Filter(player.player_id).ToList(); var circle_count = circles.Count; if (circle_count >= MAX_CIRCLES_PER_PLAYER) diff --git a/docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md b/docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md index 63eff91f7b0..59ba40c581f 100644 --- a/docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md +++ b/docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md @@ -439,7 +439,7 @@ A view can be written in C# like so: [SpacetimeDB.View(Name = "MyPlayer", Public = true)] public static Player? MyPlayer(ViewContext ctx) { - return ctx.Db.Player.Identity.Find(ctx.Sender) as Player; + return ctx.Db.Player.Identity.Find(ctx.Sender()) as Player; } ``` diff --git a/docs/docs/00100-intro/00300-tutorials/00100-chat-app.md b/docs/docs/00100-intro/00300-tutorials/00100-chat-app.md index 06ef0c039ce..f8dc277f38c 100644 --- a/docs/docs/00100-intro/00300-tutorials/00100-chat-app.md +++ b/docs/docs/00100-intro/00300-tutorials/00100-chat-app.md @@ -322,7 +322,7 @@ public static void SetName(ReducerContext ctx, string name) { name = ValidateName(name); - if (ctx.Db.User.Identity.Find(ctx.Sender) is User user) + if (ctx.Db.User.Identity.Find(ctx.Sender()) is User user) { user.Name = name; ctx.Db.User.Identity.Update(user); @@ -411,7 +411,7 @@ public static void SendMessage(ReducerContext ctx, string text) ctx.Db.Message.Insert( new Message { - Sender = ctx.Sender, + Sender = ctx.Sender(), Text = text, Sent = ctx.Timestamp, } @@ -504,9 +504,9 @@ In `spacetimedb/Lib.cs`, add to the `Module` class: [Reducer(ReducerKind.ClientConnected)] public static void ClientConnected(ReducerContext ctx) { - Log.Info($"Connect {ctx.Sender}"); + Log.Info($"Connect {ctx.Sender()}"); - if (ctx.Db.User.Identity.Find(ctx.Sender) is User user) + if (ctx.Db.User.Identity.Find(ctx.Sender()) is User user) { user.Online = true; ctx.Db.User.Identity.Update(user); @@ -517,7 +517,7 @@ public static void ClientConnected(ReducerContext ctx) new User { Name = null, - Identity = ctx.Sender, + Identity = ctx.Sender(), Online = true, } ); @@ -527,7 +527,7 @@ public static void ClientConnected(ReducerContext ctx) [Reducer(ReducerKind.ClientDisconnected)] public static void ClientDisconnected(ReducerContext ctx) { - if (ctx.Db.User.Identity.Find(ctx.Sender) is User user) + if (ctx.Db.User.Identity.Find(ctx.Sender()) is User user) { user.Online = false; ctx.Db.User.Identity.Update(user); diff --git a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md index b6766e12672..26f278f5051 100644 --- a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md +++ b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md @@ -335,7 +335,7 @@ Add this function to the `Module` class in `Lib.cs`: [Reducer] public static void Debug(ReducerContext ctx) { - Log.Info($"This reducer was called by {ctx.Sender}"); + Log.Info($"This reducer was called by {ctx.Sender()}"); } ``` @@ -444,7 +444,7 @@ Next let's connect our client to our database. Let's start by modifying our `Deb [Reducer(ReducerKind.ClientConnected)] public static void Connect(ReducerContext ctx) { - Log.Info($"{ctx.Sender} just connected."); + Log.Info($"{ctx.Sender()} just connected."); } ``` diff --git a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md index ab95e71294d..f1a0c99aa0d 100644 --- a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md +++ b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md @@ -359,7 +359,7 @@ Next, modify your `Connect` reducer and add a new `Disconnect` reducer below it: [Reducer(ReducerKind.ClientConnected)] public static void Connect(ReducerContext ctx) { - var player = ctx.Db.logged_out_player.identity.Find(ctx.Sender); + var player = ctx.Db.logged_out_player.identity.Find(ctx.Sender()); if (player != null) { ctx.Db.player.Insert(player.Value); @@ -369,7 +369,7 @@ public static void Connect(ReducerContext ctx) { ctx.Db.player.Insert(new Player { - identity = ctx.Sender, + identity = ctx.Sender(), name = "", }); } @@ -378,7 +378,7 @@ public static void Connect(ReducerContext ctx) [Reducer(ReducerKind.ClientDisconnected)] public static void Disconnect(ReducerContext ctx) { - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("Player not found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("Player not found"); ctx.Db.logged_out_player.Insert(player); ctx.Db.player.identity.Delete(player.identity); } @@ -457,7 +457,7 @@ const int START_PLAYER_MASS = 15; public static void EnterGame(ReducerContext ctx, string name) { Log.Info($"Creating player with name {name}"); - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("Player not found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("Player not found"); player.name = name; ctx.Db.player.identity.Update(player); SpawnPlayerInitialCircle(ctx, player.player_id); @@ -579,7 +579,7 @@ Let's also modify our `disconnect` reducer to remove the circles from the arena [Reducer(ReducerKind.ClientDisconnected)] public static void Disconnect(ReducerContext ctx) { - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("Player not found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("Player not found"); // Remove any circles from the arena foreach (var circle in ctx.Db.circle.player_id.Filter(player.player_id)) { diff --git a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00500-part-4.md b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00500-part-4.md index 647efe78bcb..cdf062fd8d0 100644 --- a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00500-part-4.md +++ b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00500-part-4.md @@ -49,7 +49,7 @@ Next, add the following reducer to the `Module` class of your `Lib.cs` file. [Reducer] public static void UpdatePlayerInput(ReducerContext ctx, DbVector2 direction) { - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("Player not found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("Player not found"); foreach (var c in ctx.Db.circle.player_id.Filter(player.player_id)) { var circle = c; @@ -60,7 +60,7 @@ public static void UpdatePlayerInput(ReducerContext ctx, DbVector2 direction) } ``` -This is a simple reducer that takes the movement input from the client and applies them to all circles that that player controls. Note that it is not possible for a player to move another player's circles using this reducer, because the `ctx.Sender` value is not set by the client. Instead `ctx.Sender` is set by SpacetimeDB after it has authenticated that sender. You can rest assured that the caller has been authenticated as that player by the time this reducer is called. +This is a simple reducer that takes the movement input from the client and applies them to all circles that that player controls. Note that it is not possible for a player to move another player's circles using this reducer, because the `ctx.Sender()` value is not set by the client. Instead `ctx.Sender()` is set by SpacetimeDB after it has authenticated that sender. You can rest assured that the caller has been authenticated as that player by the time this reducer is called. diff --git a/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00300-part-2.md b/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00300-part-2.md index bde4659ba26..a97a65abec8 100644 --- a/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00300-part-2.md +++ b/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00300-part-2.md @@ -333,7 +333,7 @@ Add this function to the `Module` class in `Lib.cs`: [Reducer] public static void Debug(ReducerContext ctx) { - Log.Info($"This reducer was called by {ctx.Sender}"); + Log.Info($"This reducer was called by {ctx.Sender()}"); } ``` @@ -440,7 +440,7 @@ Next let's connect our client to our database. Let's start by modifying our `Deb [Reducer(ReducerKind.ClientConnected)] public static void Connect(ReducerContext ctx) { - Log.Info($"{ctx.Sender} just connected."); + Log.Info($"{ctx.Sender()} just connected."); } ``` diff --git a/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00400-part-3.md b/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00400-part-3.md index 192c7d3ebc8..d3543050874 100644 --- a/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00400-part-3.md +++ b/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00400-part-3.md @@ -352,7 +352,7 @@ Next, modify your `Connect` reducer and add a new `Disconnect` reducer below it: [Reducer(ReducerKind.ClientConnected)] public static void Connect(ReducerContext ctx) { - var player = ctx.Db.logged_out_player.identity.Find(ctx.Sender); + var player = ctx.Db.logged_out_player.identity.Find(ctx.Sender()); if (player != null) { ctx.Db.player.Insert(player.Value); @@ -362,7 +362,7 @@ public static void Connect(ReducerContext ctx) { ctx.Db.player.Insert(new Player { - identity = ctx.Sender, + identity = ctx.Sender(), name = "", }); } @@ -371,7 +371,7 @@ public static void Connect(ReducerContext ctx) [Reducer(ReducerKind.ClientDisconnected)] public static void Disconnect(ReducerContext ctx) { - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("Player not found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("Player not found"); ctx.Db.logged_out_player.Insert(player); ctx.Db.player.identity.Delete(player.identity); } @@ -446,7 +446,7 @@ const int START_PLAYER_MASS = 15; public static void EnterGame(ReducerContext ctx, string name) { Log.Info($"Creating player with name {name}"); - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("Player not found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("Player not found"); player.name = name; ctx.Db.player.identity.Update(player); SpawnPlayerInitialCircle(ctx, player.player_id); @@ -566,7 +566,7 @@ Let's also modify our `disconnect` reducer to remove the circles from the arena [Reducer(ReducerKind.ClientDisconnected)] public static void Disconnect(ReducerContext ctx) { - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("Player not found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("Player not found"); // Remove any circles from the arena foreach (var circle in ctx.Db.circle.player_id.Filter(player.player_id)) { diff --git a/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00500-part-4.md b/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00500-part-4.md index ae8eb620633..2acda18aac8 100644 --- a/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00500-part-4.md +++ b/docs/docs/00100-intro/00300-tutorials/00400-unreal-tutorial/00500-part-4.md @@ -50,7 +50,7 @@ Next, add the following reducer to the `Module` class of your `Lib.cs` file. [Reducer] public static void UpdatePlayerInput(ReducerContext ctx, DbVector2 direction) { - var player = ctx.Db.player.identity.Find(ctx.Sender) ?? throw new Exception("Player not found"); + var player = ctx.Db.player.identity.Find(ctx.Sender()) ?? throw new Exception("Player not found"); foreach (var c in ctx.Db.circle.player_id.Filter(player.player_id)) { var circle = c; @@ -61,7 +61,7 @@ public static void UpdatePlayerInput(ReducerContext ctx, DbVector2 direction) } ``` -This is a simple reducer that takes the movement input from the client and applies them to all circles that that player controls. Note that it is not possible for a player to move another player's circles using this reducer, because the `ctx.Sender` value is not set by the client. Instead `ctx.Sender` is set by SpacetimeDB after it has authenticated that sender. You can rest assured that the caller has been authenticated as that player by the time this reducer is called. +This is a simple reducer that takes the movement input from the client and applies them to all circles that that player controls. Note that it is not possible for a player to move another player's circles using this reducer, because the `ctx.Sender()` value is not set by the client. Instead `ctx.Sender()` is set by SpacetimeDB after it has authenticated that sender. You can rest assured that the caller has been authenticated as that player by the time this reducer is called. Let's start by building out a simple math library to help us do collision calculations. Create a new `math.rs` file in the `blackholio/spacetimedb/src` directory and add the following contents. Let's also move the `DbVector2` type from `lib.rs` into this file. diff --git a/docs/docs/00200-core-concepts/00100-databases/00500-cheat-sheet.md b/docs/docs/00200-core-concepts/00100-databases/00500-cheat-sheet.md index e4754aca0e8..c7c8eafee96 100644 --- a/docs/docs/00200-core-concepts/00100-databases/00500-cheat-sheet.md +++ b/docs/docs/00200-core-concepts/00100-databases/00500-cheat-sheet.md @@ -457,7 +457,7 @@ using SpacetimeDB; [SpacetimeDB.View(Public = true)] public static Player? MyPlayer(ViewContext ctx) { - return ctx.Db.Player.Identity.Find(ctx.Sender); + return ctx.Db.Player.Identity.Find(ctx.Sender()); } // Return multiple rows @@ -510,7 +510,7 @@ ctx.identity // Module's identity ```csharp ctx.Db // Database access -ctx.Sender // Identity of caller +ctx.Sender() // Identity of caller ctx.ConnectionId // ConnectionId? ctx.Timestamp // Timestamp ctx.Identity // Module's identity diff --git a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00400-reducer-context.md b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00400-reducer-context.md index 38f447125d4..d789845ab29 100644 --- a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00400-reducer-context.md +++ b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00400-reducer-context.md @@ -145,7 +145,7 @@ public static partial class Module public static void UpdateScore(ReducerContext ctx, uint newScore) { // Get the caller's identity - Identity caller = ctx.Sender; + Identity caller = ctx.Sender(); // Find and update their player record if (ctx.Db.Player.Identity.Find(caller) is Player player) @@ -262,7 +262,7 @@ public static partial class Module public static void SendReminder(ReducerContext ctx, ScheduledTask task) { // Only allow the scheduler (module identity) to call this - if (ctx.Sender != ctx.Identity) + if (ctx.Sender() != ctx.Identity) { throw new Exception("This reducer can only be called by the scheduler"); } diff --git a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00500-lifecycle.md b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00500-lifecycle.md index 20f43bc8394..605ad09dd09 100644 --- a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00500-lifecycle.md +++ b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00500-lifecycle.md @@ -110,7 +110,7 @@ spacetimedb.clientConnected((ctx) => { [SpacetimeDB.Reducer(ReducerKind.ClientConnected)] public static void OnConnect(ReducerContext ctx) { - Log.Info($"Client connected: {ctx.Sender}"); + Log.Info($"Client connected: {ctx.Sender()}"); // ctx.ConnectionId is guaranteed to be non-null var connId = ctx.ConnectionId!.Value; @@ -119,7 +119,7 @@ public static void OnConnect(ReducerContext ctx) ctx.Db.Session.Insert(new Session { ConnectionId = connId, - Identity = ctx.Sender, + Identity = ctx.Sender(), ConnectedAt = ctx.Timestamp }); } @@ -182,7 +182,7 @@ spacetimedb.clientDisconnected((ctx) => { [SpacetimeDB.Reducer(ReducerKind.ClientDisconnected)] public static void OnDisconnect(ReducerContext ctx) { - Log.Info($"Client disconnected: {ctx.Sender}"); + Log.Info($"Client disconnected: {ctx.Sender()}"); // ctx.ConnectionId is guaranteed to be non-null var connId = ctx.ConnectionId!.Value; diff --git a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00600-error-handling.md b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00600-error-handling.md index 714f68d1110..661e5870853 100644 --- a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00600-error-handling.md +++ b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00600-error-handling.md @@ -61,7 +61,7 @@ Throw an exception: [SpacetimeDB.Reducer] public static void TransferCredits(ReducerContext ctx, ulong toUser, uint amount) { - var fromUser = ctx.Db.User.Id.Find(ctx.Sender); + var fromUser = ctx.Db.User.Id.Find(ctx.Sender()); if (fromUser == null) { throw new InvalidOperationException("User not found"); diff --git a/docs/docs/00200-core-concepts/00200-functions/00500-views.md b/docs/docs/00200-core-concepts/00200-functions/00500-views.md index 0603fa97dad..7b8c43ea1b7 100644 --- a/docs/docs/00200-core-concepts/00200-functions/00500-views.md +++ b/docs/docs/00200-core-concepts/00200-functions/00500-views.md @@ -130,7 +130,7 @@ public static partial class Module [SpacetimeDB.View(Name = "MyPlayer", Public = true)] public static Player? MyPlayer(ViewContext ctx) { - return ctx.Db.Player.Identity.Find(ctx.Sender) as Player; + return ctx.Db.Player.Identity.Find(ctx.Sender()) as Player; } // Multiple rows: return a list @@ -283,7 +283,7 @@ spacetimedb.view( [SpacetimeDB.View(Name = "MyPlayer", Public = true)] public static Player? MyPlayer(ViewContext ctx) { - return ctx.Db.Player.Identity.Find(ctx.Sender); + return ctx.Db.Player.Identity.Find(ctx.Sender()); } ``` @@ -485,7 +485,7 @@ public partial class Module [SpacetimeDB.View(Name = "EntitiesInMyChunk", Public = true)] public static List EntitiesInMyChunk(ViewContext ctx) { - if (ctx.Db.Player.Identity.Find(ctx.Sender) is not Player player) + if (ctx.Db.Player.Identity.Find(ctx.Sender()) is not Player player) { return new List(); } diff --git a/docs/docs/00200-core-concepts/00300-tables.md b/docs/docs/00200-core-concepts/00300-tables.md index cf3727b18d8..c09cf9b832c 100644 --- a/docs/docs/00200-core-concepts/00300-tables.md +++ b/docs/docs/00200-core-concepts/00300-tables.md @@ -348,7 +348,7 @@ ctx.Db.Player.Insert(new Player { /* ... */ }); ctx.Db.LoggedOutPlayer.Insert(new Player { /* ... */ }); // Move a row between tables -var player = ctx.Db.LoggedOutPlayer.Identity.Find(ctx.Sender); +var player = ctx.Db.LoggedOutPlayer.Identity.Find(ctx.Sender()); if (player != null) { ctx.Db.Player.Insert(player.Value); diff --git a/docs/docs/00200-core-concepts/00300-tables/00210-file-storage.md b/docs/docs/00200-core-concepts/00300-tables/00210-file-storage.md index 33e617c542a..239737330c8 100644 --- a/docs/docs/00200-core-concepts/00300-tables/00210-file-storage.md +++ b/docs/docs/00200-core-concepts/00300-tables/00210-file-storage.md @@ -221,7 +221,7 @@ public static partial class Module ctx.Db.Document.Insert(new Document { Id = 0, // auto-increment - OwnerId = ctx.Sender, + OwnerId = ctx.Sender(), Filename = filename, MimeType = mimeType, SizeBytes = sizeBytes, diff --git a/docs/docs/00200-core-concepts/00300-tables/00400-access-permissions.md b/docs/docs/00200-core-concepts/00300-tables/00400-access-permissions.md index 0f3c83978ed..6fe4e6d9833 100644 --- a/docs/docs/00200-core-concepts/00300-tables/00400-access-permissions.md +++ b/docs/docs/00200-core-concepts/00300-tables/00400-access-permissions.md @@ -393,8 +393,8 @@ public partial class Module public static List MyMessages(ViewContext ctx) { // Look up messages by index where caller is sender or recipient - var sent = ctx.Db.Message.Sender.Filter(ctx.Sender).ToList(); - var received = ctx.Db.Message.Recipient.Filter(ctx.Sender).ToList(); + var sent = ctx.Db.Message.Sender.Filter(ctx.Sender()).ToList(); + var received = ctx.Db.Message.Recipient.Filter(ctx.Sender()).ToList(); sent.AddRange(received); return sent; } @@ -526,7 +526,7 @@ public partial class Module public static PublicUserProfile? MyProfile(ViewContext ctx) { // Look up the caller's account by their identity (unique index) - if (ctx.Db.UserAccount.Identity.Find(ctx.Sender) is not UserAccount user) + if (ctx.Db.UserAccount.Identity.Find(ctx.Sender()) is not UserAccount user) { return null; } @@ -676,7 +676,7 @@ public partial class Module public static List MyColleagues(ViewContext ctx) { // Find the caller's employee record by identity (unique index) - if (ctx.Db.Employee.Identity.Find(ctx.Sender) is not Employee me) + if (ctx.Db.Employee.Identity.Find(ctx.Sender()) is not Employee me) { return new List(); } diff --git a/docs/docs/00300-resources/00100-how-to/00300-logging.md b/docs/docs/00300-resources/00100-how-to/00300-logging.md index 1958b01634e..1b77fd7bcc7 100644 --- a/docs/docs/00300-resources/00100-how-to/00300-logging.md +++ b/docs/docs/00300-resources/00100-how-to/00300-logging.md @@ -69,7 +69,7 @@ public static partial class Module throw new ArgumentException("Value cannot be zero"); } - Log.Debug($"Debug information: ctx.Sender = {ctx.Sender}"); + Log.Debug($"Debug information: ctx.Sender() = {ctx.Sender()}"); } } ``` @@ -202,7 +202,7 @@ Include relevant context in your log messages: [SpacetimeDB.Reducer] public static void TransferCredits(ReducerContext ctx, ulong toUser, uint amount) { - Log.Info($"Credit transfer: from={ctx.Sender}, to={toUser}, amount={amount}"); + Log.Info($"Credit transfer: from={ctx.Sender()}, to={toUser}, amount={amount}"); // ... transfer logic } diff --git a/docs/static/llms.md b/docs/static/llms.md index 876a91b31ad..f35907bf85d 100644 --- a/docs/static/llms.md +++ b/docs/static/llms.md @@ -1449,7 +1449,7 @@ Reducers are the functions within your server module responsible for atomically - **Return Type:** Reducers should typically return `void`. Errors are signaled by throwing exceptions. - **Reducer Context:** The `ReducerContext` (`ctx`) provides access to: - `ctx.Db`: Handles for interacting with database tables. - - `ctx.Sender`: The `Identity` of the caller. + - `ctx.Sender()`: The `Identity` of the caller. - `ctx.Identity`: The `Identity` of the module itself. - `ctx.Timestamp`: The `Timestamp` of the invocation. - `ctx.ConnectionId`: The nullable `ConnectionId` of the caller. @@ -1478,7 +1478,7 @@ public static partial class Module [Reducer] public static void UpdatePlayerData(ReducerContext ctx, string? newName) { - var playerId = ctx.Sender; + var playerId = ctx.Sender(); // Find player by primary key var player = ctx.Db.player_state.PlayerId.Find(playerId); @@ -1521,10 +1521,10 @@ public static partial class Module if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("Name cannot be empty."); } - Log.Info($"Attempting to register player: {name} ({ctx.Sender})"); + Log.Info($"Attempting to register player: {name} ({ctx.Sender()})"); // Check if player identity or name already exists - if (ctx.Db.player_state.PlayerId.Find(ctx.Sender) != null || ctx.Db.player_state.Name.Find(name) != null) + if (ctx.Db.player_state.PlayerId.Find(ctx.Sender()) != null || ctx.Db.player_state.Name.Find(name) != null) { throw new Exception("Player already registered or name taken."); } @@ -1532,7 +1532,7 @@ public static partial class Module // Create new player instance var newPlayer = new PlayerState { - PlayerId = ctx.Sender, + PlayerId = ctx.Sender(), Name = name, Health = 100, Level = 1, @@ -1541,14 +1541,14 @@ public static partial class Module // Insert the new player. This will throw on constraint violation. ctx.Db.player_state.Insert(newPlayer); - Log.Info($"Player registered successfully: {ctx.Sender}"); + Log.Info($"Player registered successfully: {ctx.Sender()}"); } // Example: Basic reducer showing deletion [Reducer] public static void DeleteMyItems(ReducerContext ctx) { - var ownerId = ctx.Sender; + var ownerId = ctx.Sender(); int deletedCount = 0; // Find items by owner (Requires an index on OwnerId for efficiency) @@ -1632,13 +1632,13 @@ These reducers cannot take arguments beyond `&ReducerContext`. // Example init reducer is shown in Scheduled Reducers section [Reducer(ReducerKind.ClientConnected)] public static void HandleConnect(ReducerContext ctx) { - Log.Info($"Client connected: {ctx.Sender}"); + Log.Info($"Client connected: {ctx.Sender()}"); // ... setup initial state for ctx.sender ... } [Reducer(ReducerKind.ClientDisconnected)] public static void HandleDisconnect(ReducerContext ctx) { - Log.Info($"Client disconnected: {ctx.Sender}"); + Log.Info($"Client disconnected: {ctx.Sender()}"); // ... cleanup state for ctx.sender ... } ``` @@ -1692,7 +1692,7 @@ public static partial class Module public static void SendMessage(ReducerContext ctx, SendMessageSchedule scheduleArgs) { // Security check is important! - if (!ctx.Sender.Equals(ctx.Identity)) + if (!ctx.Sender().Equals(ctx.Identity)) { throw new Exception("Reducer SendMessage may not be invoked by clients, only via scheduling."); } @@ -1740,12 +1740,12 @@ public static partial class Module - **Best-Effort Scheduling:** Scheduled reducers are called on a best-effort basis and may be slightly delayed in their execution when a database is under heavy load. -- **Restricting Access (Security):** Scheduled reducers are normal reducers and _can_ still be called directly by clients. If a scheduled reducer should _only_ be called by the scheduler, it is crucial to begin the reducer with a check comparing the caller's identity (`ctx.Sender`) to the module's own identity (`ctx.Identity`). +- **Restricting Access (Security):** Scheduled reducers are normal reducers and _can_ still be called directly by clients. If a scheduled reducer should _only_ be called by the scheduler, it is crucial to begin the reducer with a check comparing the caller's identity (`ctx.Sender()`) to the module's own identity (`ctx.Identity`). ```csharp [Reducer] // Assuming linked via [Table(Scheduled=...)] public static void MyScheduledTask(ReducerContext ctx, MyScheduleArgs args) { - if (!ctx.Sender.Equals(ctx.Identity)) + if (!ctx.Sender().Equals(ctx.Identity)) { throw new Exception("Reducer MyScheduledTask may not be invoked by clients, only via scheduling."); } @@ -1757,7 +1757,7 @@ public static partial class Module ``` :::info Scheduled Reducers and Connections -Scheduled reducer calls originate from the SpacetimeDB scheduler itself, not from an external client connection. Therefore, within a scheduled reducer, `ctx.Sender` will be the module's own identity, and `ctx.ConnectionId` will be `null`. +Scheduled reducer calls originate from the SpacetimeDB scheduler itself, not from an external client connection. Therefore, within a scheduled reducer, `ctx.Sender()` will be the module's own identity, and `ctx.ConnectionId` will be `null`. ::: ##### Error Handling: Exceptions @@ -1827,7 +1827,7 @@ public static partial class Module [SpacetimeDB.View(Name = "MyPlayer", Public = true)] public static Player? MyPlayer(ViewContext ctx) { - return ctx.Db.Player.Identity.Find(ctx.Sender); + return ctx.Db.Player.Identity.Find(ctx.Sender()); } // View that returns all players at a specific level (same for all callers) @@ -1858,7 +1858,7 @@ public static partial class Module Views use one of two context types: -- **`ViewContext`**: Provides access to the caller's `Identity` through `ctx.Sender`. Use this when the view depends on who is querying it (e.g., "get my player"). +- **`ViewContext`**: Provides access to the caller's `Identity` through `ctx.Sender()`. Use this when the view depends on who is querying it (e.g., "get my player"). - **`AnonymousViewContext`**: Does not provide caller information. Use this when the view produces the same results regardless of who queries it (e.g., "get top 10 players"). Both contexts provide read-only access to tables and indexes through `ctx.Db`. @@ -1887,7 +1887,7 @@ The query builder provides a fluent API for constructing type-safe SQL queries: public static Query MyMessages(ViewContext ctx) { return ctx.Db.Message - .Filter(msg => msg.Sender == ctx.Sender) + .Filter(msg => msg.Sender == ctx.Sender()) .Build(); } diff --git a/modules/module-test-cs/Lib.cs b/modules/module-test-cs/Lib.cs index a8d7d7a05ba..72b69649960 100644 --- a/modules/module-test-cs/Lib.cs +++ b/modules/module-test-cs/Lib.cs @@ -219,7 +219,7 @@ static partial class Module [View(Name = "my_player", Public = true)] public static Player? my_player(ViewContext ctx) { - return (Player?)ctx.Db.player.identity.Find(ctx.Sender); + return (Player?)ctx.Db.player.identity.Find(ctx.Sender()); } // This reducer is run at module initialization. @@ -278,7 +278,7 @@ public static void log_module_identity(ReducerContext ctx) public static void test(ReducerContext ctx, TestAlias arg, TestB arg2, TestC arg3, TestF arg4) { Log.Info("BEGIN"); - Log.Info($"sender: {ctx.Sender}"); + Log.Info($"sender: {ctx.Sender()}"); Log.Info($"timestamp: {ctx.Timestamp}"); Log.Info($"bar: {arg2.foo}"); @@ -462,7 +462,7 @@ public static void test_btree_index_args(ReducerContext ctx) [Reducer] public static void assert_caller_identity_is_module_identity(ReducerContext ctx) { - var caller = ctx.Sender; + var caller = ctx.Sender(); var owner = ctx.Identity; if (!caller.Equals(owner)) { diff --git a/modules/sdk-test-connect-disconnect-cs/Lib.cs b/modules/sdk-test-connect-disconnect-cs/Lib.cs index 79af81d8cc4..200457fa616 100644 --- a/modules/sdk-test-connect-disconnect-cs/Lib.cs +++ b/modules/sdk-test-connect-disconnect-cs/Lib.cs @@ -19,12 +19,12 @@ static partial class Module [SpacetimeDB.Reducer(ReducerKind.ClientConnected)] public static void identity_connected(ReducerContext ctx) { - ctx.Db.connected.Insert(new Connected { identity = ctx.Sender}); + ctx.Db.connected.Insert(new Connected { identity = ctx.Sender()}); } [SpacetimeDB.Reducer(ReducerKind.ClientDisconnected)] public static void identity_disconnected(ReducerContext ctx) { - ctx.Db.disconnected.Insert(new Disconnected { identity = ctx.Sender}); + ctx.Db.disconnected.Insert(new Disconnected { identity = ctx.Sender()}); } } diff --git a/modules/sdk-test-cs/Lib.cs b/modules/sdk-test-cs/Lib.cs index 06ddacbb631..0387d77abae 100644 --- a/modules/sdk-test-cs/Lib.cs +++ b/modules/sdk-test-cs/Lib.cs @@ -1887,25 +1887,25 @@ public static void update_pk_simple_enum(ReducerContext ctx, SimpleEnum a, int d [SpacetimeDB.Reducer] public static void insert_caller_one_identity(ReducerContext ctx) { - ctx.Db.one_identity.Insert(new OneIdentity { i = ctx.Sender }); + ctx.Db.one_identity.Insert(new OneIdentity { i = ctx.Sender() }); } [SpacetimeDB.Reducer] public static void insert_caller_vec_identity(ReducerContext ctx) { - ctx.Db.vec_identity.Insert(new VecIdentity { i = new List { ctx.Sender } }); + ctx.Db.vec_identity.Insert(new VecIdentity { i = new List { ctx.Sender() } }); } [SpacetimeDB.Reducer] public static void insert_caller_unique_identity(ReducerContext ctx, int data) { - ctx.Db.unique_identity.Insert(new UniqueIdentity { i = ctx.Sender, data = data }); + ctx.Db.unique_identity.Insert(new UniqueIdentity { i = ctx.Sender(), data = data }); } [SpacetimeDB.Reducer] public static void insert_caller_pk_identity(ReducerContext ctx, int data) { - ctx.Db.pk_identity.Insert(new PkIdentity { i = ctx.Sender, data = data }); + ctx.Db.pk_identity.Insert(new PkIdentity { i = ctx.Sender(), data = data }); } [SpacetimeDB.Reducer] diff --git a/sdks/csharp/examples~/regression-tests/server/Lib.cs b/sdks/csharp/examples~/regression-tests/server/Lib.cs index bb63e977af4..7137e8cb468 100644 --- a/sdks/csharp/examples~/regression-tests/server/Lib.cs +++ b/sdks/csharp/examples~/regression-tests/server/Lib.cs @@ -163,13 +163,13 @@ public partial struct NullStringNullable [SpacetimeDB.View(Name = "my_player", Public = true)] public static Player? MyPlayer(ViewContext ctx) { - return ctx.Db.player.Identity.Find(ctx.Sender); + return ctx.Db.player.Identity.Find(ctx.Sender()); } [SpacetimeDB.View(Name = "my_account", Public = true)] public static Account? MyAccount(ViewContext ctx) { - return ctx.Db.account.Identity.Find(ctx.Sender) as Account; + return ctx.Db.account.Identity.Find(ctx.Sender()) as Account; } [SpacetimeDB.View(Name = "my_account_missing", Public = true)] @@ -299,23 +299,23 @@ public static void InsertWhereTest(ReducerContext ctx, uint id, uint value, stri [Reducer(ReducerKind.ClientConnected)] public static void ClientConnected(ReducerContext ctx) { - Log.Info($"Connect {ctx.Sender}"); + Log.Info($"Connect {ctx.Sender()}"); - if (ctx.Db.player.Identity.Find(ctx.Sender) is Player player) + if (ctx.Db.player.Identity.Find(ctx.Sender()) is Player player) { // We are not logging player login status, so do nothing } else { // Lets setup a new player with a level of 1 - ctx.Db.player.Insert(new Player { Identity = ctx.Sender, Name = "NewPlayer" }); - var playerId = (ctx.Db.player.Identity.Find(ctx.Sender)!).Value.Id; + ctx.Db.player.Insert(new Player { Identity = ctx.Sender(), Name = "NewPlayer" }); + var playerId = (ctx.Db.player.Identity.Find(ctx.Sender())!).Value.Id; ctx.Db.player_level.Insert(new PlayerLevel { PlayerId = playerId, Level = 1 }); } - if (ctx.Db.account.Identity.Find(ctx.Sender) is null) + if (ctx.Db.account.Identity.Find(ctx.Sender()) is null) { - ctx.Db.account.Insert(new Account { Identity = ctx.Sender, Name = "Account" }); + ctx.Db.account.Insert(new Account { Identity = ctx.Sender(), Name = "Account" }); } if (ctx.Db.nullable_vec.Id.Find(1) is null) @@ -646,10 +646,10 @@ public static ReturnStruct TxContextCapabilities(ProcedureContext ctx) } // Test 3: Verify transaction context properties are accessible - var txSender = tx.Sender; + var txSender = tx.Sender(); var txTimestamp = tx.Timestamp; - if (txSender.Equals(ctx.Sender) == false) + if (txSender.Equals(ctx.Sender()) == false) { throw new InvalidOperationException("Transaction sender should match procedure sender"); } @@ -686,14 +686,14 @@ public static ReturnStruct AuthenticationCapabilities(ProcedureContext ctx) { // Test 1: Verify authentication context is accessible from procedure context var procAuth = ctx.SenderAuth; - var procSender = ctx.Sender; + var procSender = ctx.Sender(); var procConnectionId = ctx.ConnectionId; var result = ctx.WithTx(tx => { // Test 2: Verify authentication context is accessible from transaction context var txAuth = tx.SenderAuth; - var txSender = tx.Sender; + var txSender = tx.Sender(); var txConnectionId = tx.ConnectionId; // Test 3: Authentication contexts should be consistent diff --git a/templates/chat-console-cs/spacetimedb/Lib.cs b/templates/chat-console-cs/spacetimedb/Lib.cs index 3d82175859a..020bf6c072b 100644 --- a/templates/chat-console-cs/spacetimedb/Lib.cs +++ b/templates/chat-console-cs/spacetimedb/Lib.cs @@ -24,7 +24,7 @@ public static void SetName(ReducerContext ctx, string name) { name = ValidateName(name); - if (ctx.Db.User.Identity.Find(ctx.Sender) is User user) + if (ctx.Db.User.Identity.Find(ctx.Sender()) is User user) { user.Name = name; ctx.Db.User.Identity.Update(user); @@ -49,7 +49,7 @@ public static void SendMessage(ReducerContext ctx, string text) ctx.Db.Message.Insert( new Message { - Sender = ctx.Sender, + Sender = ctx.Sender(), Text = text, Sent = ctx.Timestamp, } @@ -69,9 +69,9 @@ private static string ValidateMessage(string text) [Reducer(ReducerKind.ClientConnected)] public static void ClientConnected(ReducerContext ctx) { - Log.Info($"Connect {ctx.Sender}"); + Log.Info($"Connect {ctx.Sender()}"); - if (ctx.Db.User.Identity.Find(ctx.Sender) is User user) + if (ctx.Db.User.Identity.Find(ctx.Sender()) is User user) { // If this is a returning user, i.e., we already have a `User` with this `Identity`, // set `Online: true`, but leave `Name` and `Identity` unchanged. @@ -86,7 +86,7 @@ public static void ClientConnected(ReducerContext ctx) new User { Name = null, - Identity = ctx.Sender, + Identity = ctx.Sender(), Online = true, } ); @@ -96,7 +96,7 @@ public static void ClientConnected(ReducerContext ctx) [Reducer(ReducerKind.ClientDisconnected)] public static void ClientDisconnected(ReducerContext ctx) { - if (ctx.Db.User.Identity.Find(ctx.Sender) is User user) + if (ctx.Db.User.Identity.Find(ctx.Sender()) is User user) { // This user should exist, so set `Online: false`. user.Online = false; From 865b4952b7c2b836298b48d46467ca7308b342c9 Mon Sep 17 00:00:00 2001 From: Shubham Mishra Date: Tue, 3 Feb 2026 11:03:04 +0530 Subject: [PATCH 04/18] [WASM] Expose `RawModuleDefV10` from modules (#4153) # Description of Changes Switch Wasm module to `__describe_module_v10__` from `__describe_module__` to expose `RawModuleDefV10` # API and ABI breaking changes 2.0 breaking change. # Expected complexity level and risk 1 # Testing Exising smoketests should be enough. --- crates/bindings-sys/src/lib.rs | 2 +- crates/bindings/src/rt.rs | 28 ++++++++++++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/crates/bindings-sys/src/lib.rs b/crates/bindings-sys/src/lib.rs index dfbef0c6c55..50c0ccf13d0 100644 --- a/crates/bindings-sys/src/lib.rs +++ b/crates/bindings-sys/src/lib.rs @@ -924,7 +924,7 @@ pub mod raw { /// would be where you would initialize the interepreter and load the user module into it. fn __setup__() -> Result; /// Required. Runs after `__setup__`; returns all the exports for the module. - fn __describe_module__() -> Encoded; + fn __describe_module_v10__() -> Encoded; /// Required. id is an index into the `ModuleDef.reducers` returned from `__describe_module__`. /// args is a bsatn-encoded product value defined by the schema at `reducers[id]`. fn __call_reducer__( diff --git a/crates/bindings/src/rt.rs b/crates/bindings/src/rt.rs index 09f2e5e40eb..5bb4067df9f 100644 --- a/crates/bindings/src/rt.rs +++ b/crates/bindings/src/rt.rs @@ -4,8 +4,9 @@ use crate::query_builder::Query; use crate::table::IndexAlgo; use crate::{sys, AnonymousViewContext, IterBuf, ReducerContext, ReducerResult, SpacetimeType, Table, ViewContext}; use spacetimedb_lib::bsatn::EncodeError; +use spacetimedb_lib::db::raw_def::v10::RawModuleDefV10Builder; pub use spacetimedb_lib::db::raw_def::v9::Lifecycle as LifecycleReducer; -use spacetimedb_lib::db::raw_def::v9::{RawIndexAlgorithm, RawModuleDefV9Builder, TableType, ViewResultHeader}; +use spacetimedb_lib::db::raw_def::v9::{RawIndexAlgorithm, TableType, ViewResultHeader}; use spacetimedb_lib::de::{self, Deserialize, DeserializeOwned, Error as _, SeqProductAccess}; use spacetimedb_lib::sats::typespace::TypespaceBuilder; use spacetimedb_lib::sats::{impl_deserialize, impl_serialize, ProductTypeElement}; @@ -674,7 +675,7 @@ pub trait RowLevelSecurityInfo { } /// A function which will be registered by [`register_describer`] into [`DESCRIBERS`], -/// which will be called by [`__describe_module__`] to construct a module definition. +/// which will be called by [`__describe_module_v10__`] to construct a module definition. /// /// May be a closure over static data, so that e.g. /// [`register_row_level_security`] doesn't need to take a type parameter. @@ -700,6 +701,13 @@ pub fn register_reftype() { pub fn register_table() { register_describer(|module| { let product_type_ref = *T::Row::make_type(&mut module.inner).as_ref().unwrap(); + if let Some(schedule) = T::SCHEDULE { + module.inner.add_schedule( + T::TABLE_NAME, + schedule.scheduled_at_column, + schedule.reducer_or_procedure_name, + ); + } let mut table = module .inner @@ -719,10 +727,6 @@ pub fn register_table() { for &col in T::SEQUENCES { table = table.with_column_sequence(col); } - if let Some(schedule) = T::SCHEDULE { - table = table.with_schedule(schedule.reducer_or_procedure_name, schedule.scheduled_at_column); - } - for col in T::get_default_col_values().iter_mut() { table = table.with_default_column_value(col.col_id, col.value.clone()) } @@ -749,7 +753,11 @@ impl From> for RawIndexAlgorithm { pub fn register_reducer<'a, A: Args<'a>, I: FnInfo>(_: impl Reducer<'a, A>) { register_describer(|module| { let params = A::schema::(&mut module.inner); - module.inner.add_reducer(I::NAME, params, I::LIFECYCLE); + if let Some(lifecycle) = I::LIFECYCLE { + module.inner.add_lifecycle_reducer(lifecycle, I::NAME, params); + } else { + module.inner.add_reducer(I::NAME, params); + } module.reducers.push(I::INVOKE); }) } @@ -814,7 +822,7 @@ pub fn register_row_level_security(sql: &'static str) { #[derive(Default)] pub struct ModuleBuilder { /// The module definition. - inner: RawModuleDefV9Builder, + inner: RawModuleDefV10Builder, /// The reducers of the module. reducers: Vec, /// The procedures of the module. @@ -863,7 +871,7 @@ static ANONYMOUS_VIEWS: OnceLock> = OnceLock::new(); /// including when modules are updated (re-publishing). /// After initialization, the module cannot alter the schema. #[no_mangle] -extern "C" fn __describe_module__(description: BytesSink) { +extern "C" fn __describe_module_v10__(description: BytesSink) { // Collect the `module`. let mut module = ModuleBuilder::default(); for describer in &mut *DESCRIBERS.lock().unwrap() { @@ -872,7 +880,7 @@ extern "C" fn __describe_module__(description: BytesSink) { // Serialize the module to bsatn. let module_def = module.inner.finish(); - let module_def = RawModuleDef::V9(module_def); + let module_def = RawModuleDef::V10(module_def); let bytes = bsatn::to_vec(&module_def).expect("unable to serialize typespace"); // Write the sets of reducers, procedures and views. From 5de40c307a8114b0f9bcc3aa7e60c64cbc11b038 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Tue, 3 Feb 2026 14:55:28 -0800 Subject: [PATCH 05/18] Update codegen to not provide private tables by default with a future option to enable --- crates/codegen/src/csharp.rs | 4 ++-- crates/codegen/src/lib.rs | 2 +- crates/codegen/src/rust.rs | 16 ++++++++-------- crates/codegen/src/typescript.rs | 4 ++-- crates/codegen/src/unrealcpp.rs | 18 +++++++++--------- crates/codegen/src/util.rs | 14 +++++++++++--- 6 files changed, 33 insertions(+), 25 deletions(-) diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs index f004d8e8a3d..3f6013813dd 100644 --- a/crates/codegen/src/csharp.rs +++ b/crates/codegen/src/csharp.rs @@ -1048,7 +1048,7 @@ impl Lang for Csharp<'_> { indented_block(&mut output, |output| { writeln!(output, "public RemoteTables(DbConnection conn)"); indented_block(output, |output| { - for (table_name, _) in iter_table_names_and_types(module) { + for (table_name, _) in iter_table_names_and_types(module, false) { writeln!( output, "AddTable({} = new(conn));", @@ -1071,7 +1071,7 @@ impl Lang for Csharp<'_> { writeln!(output, "public sealed class From"); indented_block(&mut output, |output| { - for (table_name, product_type_ref) in iter_table_names_and_types(module) { + for (table_name, product_type_ref) in iter_table_names_and_types(module, false) { let method_name = table_name.deref().to_case(Case::Pascal); let row_type = type_ref_name(module, product_type_ref); let table_name_lit = format!("{:?}", table_name.deref()); diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 6dbaeeea910..20ce59d83ae 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -15,7 +15,7 @@ pub use util::AUTO_GENERATED_PREFIX; pub fn generate(module: &ModuleDef, lang: &dyn Lang) -> Vec { itertools::chain!( - module.tables().map(|tbl| lang.generate_table_file(module, tbl)), + util::iter_tables(module, false).map(|tbl| lang.generate_table_file(module, tbl)), module.views().map(|view| lang.generate_view_file(module, view)), module.types().flat_map(|typ| lang.generate_type_files(module, typ)), util::iter_reducers(module).map(|reducer| lang.generate_reducer_file(module, reducer)), diff --git a/crates/codegen/src/rust.rs b/crates/codegen/src/rust.rs index 47c8097aa37..9048019a797 100644 --- a/crates/codegen/src/rust.rs +++ b/crates/codegen/src/rust.rs @@ -1131,7 +1131,7 @@ fn iter_module_names(module: &ModuleDef) -> impl Iterator + '_ { itertools::chain!( iter_types(module).map(|ty| type_module_name(&ty.name)), iter_reducers(module).map(|r| reducer_module_name(&r.name)), - iter_tables(module).map(|tbl| table_module_name(&tbl.name)), + iter_tables(module, false).map(|tbl| table_module_name(&tbl.name)), iter_views(module).map(|view| table_module_name(&view.name)), iter_procedures(module).map(|proc| procedure_module_name(&proc.name)), ) @@ -1151,7 +1151,7 @@ fn print_module_reexports(module: &ModuleDef, out: &mut Indenter) { let type_name = collect_case(Case::Pascal, ty.name.name_segments()); writeln!(out, "pub use {mod_name}::{type_name};") } - for (table_name, _) in iter_table_names_and_types(module) { + for (table_name, _) in iter_table_names_and_types(module, false) { let mod_name = table_module_name(table_name); // TODO: More precise reexport: we want: // - The trait name. @@ -1310,7 +1310,7 @@ fn print_db_update_defn(module: &ModuleDef, out: &mut Indenter) { out.delimited_block( "pub struct DbUpdate {", |out| { - for (table_name, product_type_ref) in iter_table_names_and_types(module) { + for (table_name, product_type_ref) in iter_table_names_and_types(module, false) { writeln!( out, "{}: __sdk::TableUpdate<{}>,", @@ -1334,7 +1334,7 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { match &table_update.table_name[..] { ", |out| { - for (table_name, _) in iter_table_names_and_types(module) { + for (table_name, _) in iter_table_names_and_types(module, false) { writeln!( out, "{:?} => db_update.{}.append({}::parse_table_update(table_update)?),", @@ -1378,7 +1378,7 @@ impl __sdk::InModule for DbUpdate {{ let mut diff = AppliedDiff::default(); ", |out| { - for table in iter_tables(module) { + for table in iter_tables(module, false) { let with_updates = table .primary_key .map(|col| { @@ -1421,7 +1421,7 @@ fn print_applied_diff_defn(module: &ModuleDef, out: &mut Indenter) { out.delimited_block( "pub struct AppliedDiff<'r> {", |out| { - for (table_name, product_type_ref) in iter_table_names_and_types(module) { + for (table_name, product_type_ref) in iter_table_names_and_types(module, false) { writeln!( out, "{}: __sdk::TableAppliedDiff<'r, {}>,", @@ -1454,7 +1454,7 @@ impl __sdk::InModule for AppliedDiff<'_> {{ out.delimited_block( "fn invoke_row_callbacks(&self, event: &EventContext, callbacks: &mut __sdk::DbCallbacks) {", |out| { - for (table_name, product_type_ref) in iter_table_names_and_types(module) { + for (table_name, product_type_ref) in iter_table_names_and_types(module, false) { writeln!( out, "callbacks.invoke_table_row_callbacks::<{}>({:?}, &self.{}, event);", @@ -1497,7 +1497,7 @@ type QueryBuilder = __sdk::QueryBuilder; out.delimited_block( "fn register_tables(client_cache: &mut __sdk::ClientCache) {", |out| { - for (table_name, _) in iter_table_names_and_types(module) { + for (table_name, _) in iter_table_names_and_types(module, false) { writeln!(out, "{}::register_table(client_cache);", table_module_name(table_name)); } }, diff --git a/crates/codegen/src/typescript.rs b/crates/codegen/src/typescript.rs index e153d756996..858618b77cc 100644 --- a/crates/codegen/src/typescript.rs +++ b/crates/codegen/src/typescript.rs @@ -231,7 +231,7 @@ impl Lang for TypeScript { writeln!(out); writeln!(out, "// Import and reexport all table handle types"); - for (table_name, _) in iter_table_names_and_types(module) { + for (table_name, _) in iter_table_names_and_types(module, false) { let table_module_name = table_module_name(table_name); let table_name_pascalcase = table_name.deref().to_case(Case::Pascal); // TODO: This really shouldn't be necessary. We could also have `table()` accept @@ -253,7 +253,7 @@ impl Lang for TypeScript { writeln!(out, "/** 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. */"); writeln!(out, "const tablesSchema = __schema("); out.indent(1); - for table in iter_tables(module) { + for table in iter_tables(module, false) { let type_ref = table.product_type_ref; let table_name_pascalcase = table.name.deref().to_case(Case::Pascal); writeln!(out, "__table({{"); diff --git a/crates/codegen/src/unrealcpp.rs b/crates/codegen/src/unrealcpp.rs index 0baa6adbc81..e2fa0c30838 100644 --- a/crates/codegen/src/unrealcpp.rs +++ b/crates/codegen/src/unrealcpp.rs @@ -1,7 +1,7 @@ //! Autogenerated Unreal‑C++ code‑gen backend for SpacetimeDB CLI use crate::code_indenter::CodeIndenter; use crate::util::{ - collect_case, fmt_fn, iter_table_names_and_types, print_auto_generated_file_comment, + collect_case, fmt_fn, iter_table_names_and_types, iter_tables, print_auto_generated_file_comment, print_auto_generated_version_comment, }; use crate::util::{iter_indexes, iter_procedures, iter_reducers}; @@ -865,7 +865,7 @@ impl Lang for UnrealCpp<'_> { writeln!(client_h); writeln!(client_h, "/** Forward declaration for tables */"); - for (table_name, _) in iter_table_names_and_types(module) { + for (table_name, _) in iter_table_names_and_types(module, false) { writeln!(client_h, "class U{}Table;", table_name.deref().to_case(Case::Pascal)); } writeln!(client_h, "/***/"); @@ -958,7 +958,7 @@ impl Lang for UnrealCpp<'_> { }); // Build table includes - let table_includes: Vec = iter_table_names_and_types(module) + let table_includes: Vec = iter_table_names_and_types(module, false) .map(|(table_name, _)| { format!( "ModuleBindings/Tables/{}Table.g.h", @@ -987,7 +987,7 @@ impl Lang for UnrealCpp<'_> { }); // Generate .cpp implementation files for each table - for table in module.tables() { + for table in iter_tables(module, false) { let schema = TableSchema::from_module_def(module, table, (), 0.into()) .validated() .expect("table schema should validate"); @@ -2349,7 +2349,7 @@ fn generate_remote_tables_class(output: &mut UnrealCppAutogen, module: &ModuleDe writeln!(output); // Generate table handle properties - for (table_name, _) in iter_table_names_and_types(module) { + for (table_name, _) in iter_table_names_and_types(module, false) { writeln!(output, " UPROPERTY(BlueprintReadOnly, Category=\"SpacetimeDB\")"); writeln!( output, @@ -3023,7 +3023,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "\tProcedures->Conn = this;"); writeln!(output); - for (table_name, product_type_ref) in iter_table_names_and_types(module) { + for (table_name, product_type_ref) in iter_table_names_and_types(module, false) { let struct_name = type_ref_name(module, product_type_ref); let table_name = table_name.deref(); writeln!( @@ -3079,7 +3079,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "{{"); writeln!(output); writeln!(output, "\t/** Creating tables */"); - for (table_name, _) in iter_table_names_and_types(module) { + for (table_name, _) in iter_table_names_and_types(module, false) { writeln!( output, "\t{} = NewObject(this);", @@ -3090,7 +3090,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "\t/**/"); writeln!(output); writeln!(output, "\t/** Initialization */"); - for (table_name, _) in iter_table_names_and_types(module) { + for (table_name, _) in iter_table_names_and_types(module, false) { writeln!( output, "\t{}->PostInitialize();", @@ -3980,7 +3980,7 @@ fn collect_wrapper_types(module: &ModuleDef) -> (HashSet, HashSet<(Strin } // Collect from all tables - for (_, product_type_ref) in iter_table_names_and_types(module) { + for (_, product_type_ref) in iter_table_names_and_types(module, false) { let product_type = module.typespace_for_generate()[product_type_ref].as_product().unwrap(); for (_, field_ty) in &product_type.elements { collect_from_type(module, field_ty, &mut optional_types, &mut result_types); diff --git a/crates/codegen/src/util.rs b/crates/codegen/src/util.rs index 6ff3d11b408..54e35d15fec 100644 --- a/crates/codegen/src/util.rs +++ b/crates/codegen/src/util.rs @@ -8,6 +8,7 @@ use std::{ use super::code_indenter::Indenter; use convert_case::{Case, Casing}; use itertools::Itertools; +use spacetimedb_lib::db::raw_def::v9::TableAccess; use spacetimedb_lib::sats::layout::PrimitiveType; use spacetimedb_lib::version; use spacetimedb_lib::{db::raw_def::v9::Lifecycle, sats::AlgebraicTypeRef}; @@ -111,8 +112,11 @@ pub(super) fn iter_procedures(module: &ModuleDef) -> impl Iterator impl Iterator { - module.tables().sorted_by_key(|table| &table.name) +pub(super) fn iter_tables(module: &ModuleDef, allow_private: bool) -> impl Iterator { + module + .tables() + .filter(move |table| allow_private || table.table_access == TableAccess::Public) + .sorted_by_key(|table| &table.name) } /// Iterate over all the [`ViewDef`]s defined by the module, in alphabetical order by name. @@ -125,9 +129,13 @@ pub(super) fn iter_views(module: &ModuleDef) -> impl Iterator { /// Iterate over the names of all the tables and views defined by the module, in alphabetical order. /// /// Sorting is necessary to have deterministic reproducible codegen. -pub(super) fn iter_table_names_and_types(module: &ModuleDef) -> impl Iterator { +pub(super) fn iter_table_names_and_types( + module: &ModuleDef, + allow_private: bool, +) -> impl Iterator { module .tables() + .filter(move |table| allow_private || table.table_access == TableAccess::Public) .map(|def| (&def.name, def.product_type_ref)) .chain(module.views().map(|def| (&def.name, def.product_type_ref))) .sorted_by_key(|(name, _)| *name) From 9f9c9f539e854fbe1e82bf114a008764cfac0151 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Tue, 3 Feb 2026 15:04:21 -0800 Subject: [PATCH 06/18] Rename allow_private to include_private to match the future argument --- crates/codegen/src/util.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/codegen/src/util.rs b/crates/codegen/src/util.rs index 54e35d15fec..8607b4c92e0 100644 --- a/crates/codegen/src/util.rs +++ b/crates/codegen/src/util.rs @@ -112,10 +112,10 @@ pub(super) fn iter_procedures(module: &ModuleDef) -> impl Iterator impl Iterator { +pub(super) fn iter_tables(module: &ModuleDef, include_private: bool) -> impl Iterator { module .tables() - .filter(move |table| allow_private || table.table_access == TableAccess::Public) + .filter(move |table| include_private || table.table_access == TableAccess::Public) .sorted_by_key(|table| &table.name) } @@ -131,11 +131,11 @@ pub(super) fn iter_views(module: &ModuleDef) -> impl Iterator { /// Sorting is necessary to have deterministic reproducible codegen. pub(super) fn iter_table_names_and_types( module: &ModuleDef, - allow_private: bool, + include_private: bool, ) -> impl Iterator { module .tables() - .filter(move |table| allow_private || table.table_access == TableAccess::Public) + .filter(move |table| include_private || table.table_access == TableAccess::Public) .map(|def| (&def.name, def.product_type_ref)) .chain(module.views().map(|def| (&def.name, def.product_type_ref))) .sorted_by_key(|(name, _)| *name) From 5a6fdc05ae2c3754959d83882d7cf1ba8a887019 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Tue, 3 Feb 2026 15:18:03 -0800 Subject: [PATCH 07/18] Updated codegen snap files --- .../snapshots/codegen__codegen_csharp.snap | 501 ------ .../snapshots/codegen__codegen_rust.snap | 1396 ++--------------- .../codegen__codegen_typescript.snap | 242 --- 3 files changed, 110 insertions(+), 2029 deletions(-) diff --git a/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap b/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap index 426cc4093bf..023a7eb3cef 100644 --- a/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap +++ b/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap @@ -1,6 +1,5 @@ --- source: crates/codegen/tests/codegen.rs -assertion_line: 37 expression: outfiles --- "Procedures/GetMySchemaViaHttp.g.cs" = ''' @@ -1287,19 +1286,11 @@ namespace SpacetimeDB { public RemoteTables(DbConnection conn) { - AddTable(HasSpecialStuff = new(conn)); AddTable(LoggedOutPlayer = new(conn)); AddTable(MyPlayer = new(conn)); AddTable(Person = new(conn)); - AddTable(PkMultiIdentity = new(conn)); AddTable(Player = new(conn)); - AddTable(Points = new(conn)); - AddTable(PrivateTable = new(conn)); - AddTable(RepeatingTestArg = new(conn)); - AddTable(TableToRemove = new(conn)); - AddTable(TestA = new(conn)); AddTable(TestD = new(conn)); - AddTable(TestE = new(conn)); AddTable(TestF = new(conn)); } } @@ -1839,19 +1830,11 @@ namespace SpacetimeDB public sealed class From { - public global::SpacetimeDB.Table HasSpecialStuff() => new("has_special_stuff", new HasSpecialStuffCols("has_special_stuff"), new HasSpecialStuffIxCols("has_special_stuff")); public global::SpacetimeDB.Table LoggedOutPlayer() => new("logged_out_player", new LoggedOutPlayerCols("logged_out_player"), new LoggedOutPlayerIxCols("logged_out_player")); public global::SpacetimeDB.Table MyPlayer() => new("my_player", new MyPlayerCols("my_player"), new MyPlayerIxCols("my_player")); public global::SpacetimeDB.Table Person() => new("person", new PersonCols("person"), new PersonIxCols("person")); - public global::SpacetimeDB.Table PkMultiIdentity() => new("pk_multi_identity", new PkMultiIdentityCols("pk_multi_identity"), new PkMultiIdentityIxCols("pk_multi_identity")); public global::SpacetimeDB.Table Player() => new("player", new PlayerCols("player"), new PlayerIxCols("player")); - public global::SpacetimeDB.Table Points() => new("points", new PointsCols("points"), new PointsIxCols("points")); - public global::SpacetimeDB.Table PrivateTable() => new("private_table", new PrivateTableCols("private_table"), new PrivateTableIxCols("private_table")); - public global::SpacetimeDB.Table RepeatingTestArg() => new("repeating_test_arg", new RepeatingTestArgCols("repeating_test_arg"), new RepeatingTestArgIxCols("repeating_test_arg")); - public global::SpacetimeDB.Table TableToRemove() => new("table_to_remove", new TableToRemoveCols("table_to_remove"), new TableToRemoveIxCols("table_to_remove")); - public global::SpacetimeDB.Table TestA() => new("test_a", new TestACols("test_a"), new TestAIxCols("test_a")); public global::SpacetimeDB.Table TestD() => new("test_d", new TestDCols("test_d"), new TestDIxCols("test_d")); - public global::SpacetimeDB.Table TestE() => new("test_e", new TestECols("test_e"), new TestEIxCols("test_e")); public global::SpacetimeDB.Table TestF() => new("test_f", new TestFCols("test_f"), new TestFIxCols("test_f")); } @@ -1984,55 +1967,6 @@ namespace SpacetimeDB } } ''' -"Tables/HasSpecialStuff.g.cs" = ''' -// 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 -{ - public sealed partial class RemoteTables - { - public sealed class HasSpecialStuffHandle : RemoteTableHandle - { - protected override string RemoteTableName => "has_special_stuff"; - - internal HasSpecialStuffHandle(DbConnection conn) : base(conn) - { - } - } - - public readonly HasSpecialStuffHandle HasSpecialStuff; - } - - public sealed class HasSpecialStuffCols - { - public global::SpacetimeDB.Col Identity { get; } - public global::SpacetimeDB.Col ConnectionId { get; } - - public HasSpecialStuffCols(string tableName) - { - Identity = new global::SpacetimeDB.Col(tableName, "identity"); - ConnectionId = new global::SpacetimeDB.Col(tableName, "connection_id"); - } - } - - public sealed class HasSpecialStuffIxCols - { - - public HasSpecialStuffIxCols(string tableName) - { - } - } -} -''' "Tables/LoggedOutPlayer.g.cs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. @@ -2250,81 +2184,6 @@ namespace SpacetimeDB } } ''' -"Tables/PkMultiIdentity.g.cs" = ''' -// 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 -{ - public sealed partial class RemoteTables - { - public sealed class PkMultiIdentityHandle : RemoteTableHandle - { - protected override string RemoteTableName => "pk_multi_identity"; - - public sealed class IdUniqueIndex : UniqueIndexBase - { - protected override uint GetKey(PkMultiIdentity row) => row.Id; - - public IdUniqueIndex(PkMultiIdentityHandle table) : base(table) { } - } - - public readonly IdUniqueIndex Id; - - public sealed class OtherUniqueIndex : UniqueIndexBase - { - protected override uint GetKey(PkMultiIdentity row) => row.Other; - - public OtherUniqueIndex(PkMultiIdentityHandle table) : base(table) { } - } - - public readonly OtherUniqueIndex Other; - - internal PkMultiIdentityHandle(DbConnection conn) : base(conn) - { - Id = new(this); - Other = new(this); - } - - protected override object GetPrimaryKey(PkMultiIdentity row) => row.Id; - } - - public readonly PkMultiIdentityHandle PkMultiIdentity; - } - - public sealed class PkMultiIdentityCols - { - public global::SpacetimeDB.Col Id { get; } - public global::SpacetimeDB.Col Other { get; } - - public PkMultiIdentityCols(string tableName) - { - Id = new global::SpacetimeDB.Col(tableName, "id"); - Other = new global::SpacetimeDB.Col(tableName, "other"); - } - } - - public sealed class PkMultiIdentityIxCols - { - public global::SpacetimeDB.IxCol Id { get; } - public global::SpacetimeDB.IxCol Other { get; } - - public PkMultiIdentityIxCols(string tableName) - { - Id = new global::SpacetimeDB.IxCol(tableName, "id"); - Other = new global::SpacetimeDB.IxCol(tableName, "other"); - } - } -} -''' "Tables/Player.g.cs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. @@ -2414,291 +2273,6 @@ namespace SpacetimeDB } } ''' -"Tables/Points.g.cs" = ''' -// 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 -{ - public sealed partial class RemoteTables - { - public sealed class PointsHandle : RemoteTableHandle - { - protected override string RemoteTableName => "points"; - - public sealed class MultiColumnIndexIndex : BTreeIndexBase<(long X, long Y)> - { - protected override (long X, long Y) GetKey(Point row) => (row.X, row.Y); - - public MultiColumnIndexIndex(PointsHandle table) : base(table) { } - } - - public readonly MultiColumnIndexIndex MultiColumnIndex; - - internal PointsHandle(DbConnection conn) : base(conn) - { - MultiColumnIndex = new(this); - } - } - - public readonly PointsHandle Points; - } - - public sealed class PointsCols - { - public global::SpacetimeDB.Col X { get; } - public global::SpacetimeDB.Col Y { get; } - - public PointsCols(string tableName) - { - X = new global::SpacetimeDB.Col(tableName, "x"); - Y = new global::SpacetimeDB.Col(tableName, "y"); - } - } - - public sealed class PointsIxCols - { - public global::SpacetimeDB.IxCol X { get; } - public global::SpacetimeDB.IxCol Y { get; } - - public PointsIxCols(string tableName) - { - X = new global::SpacetimeDB.IxCol(tableName, "x"); - Y = new global::SpacetimeDB.IxCol(tableName, "y"); - } - } -} -''' -"Tables/PrivateTable.g.cs" = ''' -// 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 -{ - public sealed partial class RemoteTables - { - public sealed class PrivateTableHandle : RemoteTableHandle - { - protected override string RemoteTableName => "private_table"; - - internal PrivateTableHandle(DbConnection conn) : base(conn) - { - } - } - - public readonly PrivateTableHandle PrivateTable; - } - - public sealed class PrivateTableCols - { - public global::SpacetimeDB.Col Name { get; } - - public PrivateTableCols(string tableName) - { - Name = new global::SpacetimeDB.Col(tableName, "name"); - } - } - - public sealed class PrivateTableIxCols - { - - public PrivateTableIxCols(string tableName) - { - } - } -} -''' -"Tables/RepeatingTestArg.g.cs" = ''' -// 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 -{ - public sealed partial class RemoteTables - { - public sealed class RepeatingTestArgHandle : RemoteTableHandle - { - protected override string RemoteTableName => "repeating_test_arg"; - - public sealed class ScheduledIdUniqueIndex : UniqueIndexBase - { - protected override ulong GetKey(RepeatingTestArg row) => row.ScheduledId; - - public ScheduledIdUniqueIndex(RepeatingTestArgHandle table) : base(table) { } - } - - public readonly ScheduledIdUniqueIndex ScheduledId; - - internal RepeatingTestArgHandle(DbConnection conn) : base(conn) - { - ScheduledId = new(this); - } - - protected override object GetPrimaryKey(RepeatingTestArg row) => row.ScheduledId; - } - - public readonly RepeatingTestArgHandle RepeatingTestArg; - } - - public sealed class RepeatingTestArgCols - { - public global::SpacetimeDB.Col ScheduledId { get; } - public global::SpacetimeDB.Col ScheduledAt { get; } - public global::SpacetimeDB.Col PrevTime { get; } - - public RepeatingTestArgCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.Col(tableName, "scheduled_id"); - ScheduledAt = new global::SpacetimeDB.Col(tableName, "scheduled_at"); - PrevTime = new global::SpacetimeDB.Col(tableName, "prev_time"); - } - } - - public sealed class RepeatingTestArgIxCols - { - public global::SpacetimeDB.IxCol ScheduledId { get; } - - public RepeatingTestArgIxCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.IxCol(tableName, "scheduled_id"); - } - } -} -''' -"Tables/TableToRemove.g.cs" = ''' -// 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 -{ - public sealed partial class RemoteTables - { - public sealed class TableToRemoveHandle : RemoteTableHandle - { - protected override string RemoteTableName => "table_to_remove"; - - internal TableToRemoveHandle(DbConnection conn) : base(conn) - { - } - } - - public readonly TableToRemoveHandle TableToRemove; - } - - public sealed class TableToRemoveCols - { - public global::SpacetimeDB.Col Id { get; } - - public TableToRemoveCols(string tableName) - { - Id = new global::SpacetimeDB.Col(tableName, "id"); - } - } - - public sealed class TableToRemoveIxCols - { - - public TableToRemoveIxCols(string tableName) - { - } - } -} -''' -"Tables/TestA.g.cs" = ''' -// 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 -{ - public sealed partial class RemoteTables - { - public sealed class TestAHandle : RemoteTableHandle - { - protected override string RemoteTableName => "test_a"; - - public sealed class FooIndex : BTreeIndexBase - { - protected override uint GetKey(TestA row) => row.X; - - public FooIndex(TestAHandle table) : base(table) { } - } - - public readonly FooIndex Foo; - - internal TestAHandle(DbConnection conn) : base(conn) - { - Foo = new(this); - } - } - - public readonly TestAHandle TestA; - } - - public sealed class TestACols - { - public global::SpacetimeDB.Col X { get; } - public global::SpacetimeDB.Col Y { get; } - public global::SpacetimeDB.Col Z { get; } - - public TestACols(string tableName) - { - X = new global::SpacetimeDB.Col(tableName, "x"); - Y = new global::SpacetimeDB.Col(tableName, "y"); - Z = new global::SpacetimeDB.Col(tableName, "z"); - } - } - - public sealed class TestAIxCols - { - public global::SpacetimeDB.IxCol X { get; } - - public TestAIxCols(string tableName) - { - X = new global::SpacetimeDB.IxCol(tableName, "x"); - } - } -} -''' "Tables/TestD.g.cs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. @@ -2746,81 +2320,6 @@ namespace SpacetimeDB } } ''' -"Tables/TestE.g.cs" = ''' -// 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 -{ - public sealed partial class RemoteTables - { - public sealed class TestEHandle : RemoteTableHandle - { - protected override string RemoteTableName => "test_e"; - - public sealed class IdUniqueIndex : UniqueIndexBase - { - protected override ulong GetKey(TestE row) => row.Id; - - public IdUniqueIndex(TestEHandle table) : base(table) { } - } - - public readonly IdUniqueIndex Id; - - public sealed class NameIndex : BTreeIndexBase - { - protected override string GetKey(TestE row) => row.Name; - - public NameIndex(TestEHandle table) : base(table) { } - } - - public readonly NameIndex Name; - - internal TestEHandle(DbConnection conn) : base(conn) - { - Id = new(this); - Name = new(this); - } - - protected override object GetPrimaryKey(TestE row) => row.Id; - } - - public readonly TestEHandle TestE; - } - - public sealed class TestECols - { - public global::SpacetimeDB.Col Id { get; } - public global::SpacetimeDB.Col Name { get; } - - public TestECols(string tableName) - { - Id = new global::SpacetimeDB.Col(tableName, "id"); - Name = new global::SpacetimeDB.Col(tableName, "name"); - } - } - - public sealed class TestEIxCols - { - public global::SpacetimeDB.IxCol Id { get; } - public global::SpacetimeDB.IxCol Name { get; } - - public TestEIxCols(string tableName) - { - Id = new global::SpacetimeDB.IxCol(tableName, "id"); - Name = new global::SpacetimeDB.IxCol(tableName, "name"); - } - } -} -''' "Tables/TestF.g.cs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. diff --git a/crates/codegen/tests/snapshots/codegen__codegen_rust.snap b/crates/codegen/tests/snapshots/codegen__codegen_rust.snap index c53d06879eb..c54e2ee3066 100644 --- a/crates/codegen/tests/snapshots/codegen__codegen_rust.snap +++ b/crates/codegen/tests/snapshots/codegen__codegen_rust.snap @@ -1,6 +1,5 @@ --- source: crates/codegen/tests/codegen.rs -assertion_line: 37 expression: outfiles --- "add_player_reducer.rs" = ''' @@ -877,123 +876,6 @@ impl get_my_schema_via_http for super::RemoteProcedures { } } -''' -"has_special_stuff_table.rs" = ''' -// 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, -}; -use super::has_special_stuff_type::HasSpecialStuff; - -/// Table handle for the table `has_special_stuff`. -/// -/// Obtain a handle from the [`HasSpecialStuffTableAccess::has_special_stuff`] method on [`super::RemoteTables`], -/// like `ctx.db.has_special_stuff()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.has_special_stuff().on_insert(...)`. -pub struct HasSpecialStuffTableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `has_special_stuff`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait HasSpecialStuffTableAccess { - #[allow(non_snake_case)] - /// Obtain a [`HasSpecialStuffTableHandle`], which mediates access to the table `has_special_stuff`. - fn has_special_stuff(&self) -> HasSpecialStuffTableHandle<'_>; -} - -impl HasSpecialStuffTableAccess for super::RemoteTables { - fn has_special_stuff(&self) -> HasSpecialStuffTableHandle<'_> { - HasSpecialStuffTableHandle { - imp: self.imp.get_table::("has_special_stuff"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct HasSpecialStuffInsertCallbackId(__sdk::CallbackId); -pub struct HasSpecialStuffDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for HasSpecialStuffTableHandle<'ctx> { - type Row = HasSpecialStuff; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { self.imp.count() } - fn iter(&self) -> impl Iterator + '_ { self.imp.iter() } - - type InsertCallbackId = HasSpecialStuffInsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> HasSpecialStuffInsertCallbackId { - HasSpecialStuffInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: HasSpecialStuffInsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = HasSpecialStuffDeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> HasSpecialStuffDeleteCallbackId { - HasSpecialStuffDeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: HasSpecialStuffDeleteCallbackId) { - self.imp.remove_on_delete(callback.0) - } -} - -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - - let _table = client_cache.get_or_make_table::("has_special_stuff"); -} - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __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 `HasSpecialStuff`. - /// - /// Implemented for [`__sdk::QueryTableAccessor`]. - pub trait has_special_stuffQueryTableAccess { - #[allow(non_snake_case)] - /// Get a query builder for the table `HasSpecialStuff`. - fn has_special_stuff(&self) -> __sdk::__query_builder::Table; - } - - impl has_special_stuffQueryTableAccess for __sdk::QueryTableAccessor { - fn has_special_stuff(&self) -> __sdk::__query_builder::Table { - __sdk::__query_builder::Table::new("has_special_stuff") - } - } - ''' "has_special_stuff_type.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -1543,18 +1425,10 @@ pub mod repeating_test_reducer; pub mod say_hello_reducer; pub mod test_reducer; pub mod test_btree_index_args_reducer; -pub mod has_special_stuff_table; pub mod logged_out_player_table; pub mod person_table; -pub mod pk_multi_identity_table; pub mod player_table; -pub mod points_table; -pub mod private_table_table; -pub mod repeating_test_arg_table; -pub mod table_to_remove_table; -pub mod test_a_table; pub mod test_d_table; -pub mod test_e_table; pub mod test_f_table; pub mod my_player_table; pub mod get_my_schema_via_http_procedure; @@ -1579,19 +1453,11 @@ pub use test_e_type::TestE; pub use test_foobar_type::TestFoobar; pub use namespace_test_c_type::NamespaceTestC; pub use namespace_test_f_type::NamespaceTestF; -pub use has_special_stuff_table::*; pub use logged_out_player_table::*; pub use my_player_table::*; pub use person_table::*; -pub use pk_multi_identity_table::*; pub use player_table::*; -pub use points_table::*; -pub use private_table_table::*; -pub use repeating_test_arg_table::*; -pub use table_to_remove_table::*; -pub use test_a_table::*; pub use test_d_table::*; -pub use test_e_table::*; pub use test_f_table::*; pub use add_reducer::{add, set_flags_for_add, AddCallbackId}; pub use add_player_reducer::{add_player, set_flags_for_add_player, AddPlayerCallbackId}; @@ -1709,19 +1575,11 @@ fn try_from(value: __ws::ReducerCallInfo<__ws::BsatnFormat>) -> __sdk::Result, - logged_out_player: __sdk::TableUpdate, + logged_out_player: __sdk::TableUpdate, my_player: __sdk::TableUpdate, person: __sdk::TableUpdate, - pk_multi_identity: __sdk::TableUpdate, player: __sdk::TableUpdate, - points: __sdk::TableUpdate, - private_table: __sdk::TableUpdate, - repeating_test_arg: __sdk::TableUpdate, - table_to_remove: __sdk::TableUpdate, - test_a: __sdk::TableUpdate, test_d: __sdk::TableUpdate, - test_e: __sdk::TableUpdate, test_f: __sdk::TableUpdate, } @@ -1733,19 +1591,11 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { for table_update in raw.tables { match &table_update.table_name[..] { - "has_special_stuff" => db_update.has_special_stuff.append(has_special_stuff_table::parse_table_update(table_update)?), - "logged_out_player" => db_update.logged_out_player.append(logged_out_player_table::parse_table_update(table_update)?), + "logged_out_player" => db_update.logged_out_player.append(logged_out_player_table::parse_table_update(table_update)?), "my_player" => db_update.my_player.append(my_player_table::parse_table_update(table_update)?), "person" => db_update.person.append(person_table::parse_table_update(table_update)?), - "pk_multi_identity" => db_update.pk_multi_identity.append(pk_multi_identity_table::parse_table_update(table_update)?), "player" => db_update.player.append(player_table::parse_table_update(table_update)?), - "points" => db_update.points.append(points_table::parse_table_update(table_update)?), - "private_table" => db_update.private_table.append(private_table_table::parse_table_update(table_update)?), - "repeating_test_arg" => db_update.repeating_test_arg.append(repeating_test_arg_table::parse_table_update(table_update)?), - "table_to_remove" => db_update.table_to_remove.append(table_to_remove_table::parse_table_update(table_update)?), - "test_a" => db_update.test_a.append(test_a_table::parse_table_update(table_update)?), "test_d" => db_update.test_d.append(test_d_table::parse_table_update(table_update)?), - "test_e" => db_update.test_e.append(test_e_table::parse_table_update(table_update)?), "test_f" => db_update.test_f.append(test_f_table::parse_table_update(table_update)?), unknown => { @@ -1769,18 +1619,10 @@ impl __sdk::DbUpdate for DbUpdate { fn apply_to_client_cache(&self, cache: &mut __sdk::ClientCache) -> AppliedDiff<'_> { let mut diff = AppliedDiff::default(); - diff.has_special_stuff = cache.apply_diff_to_table::("has_special_stuff", &self.has_special_stuff); - diff.logged_out_player = cache.apply_diff_to_table::("logged_out_player", &self.logged_out_player).with_updates_by_pk(|row| &row.identity); + diff.logged_out_player = cache.apply_diff_to_table::("logged_out_player", &self.logged_out_player).with_updates_by_pk(|row| &row.identity); diff.person = cache.apply_diff_to_table::("person", &self.person).with_updates_by_pk(|row| &row.id); - diff.pk_multi_identity = cache.apply_diff_to_table::("pk_multi_identity", &self.pk_multi_identity).with_updates_by_pk(|row| &row.id); diff.player = cache.apply_diff_to_table::("player", &self.player).with_updates_by_pk(|row| &row.identity); - diff.points = cache.apply_diff_to_table::("points", &self.points); - diff.private_table = cache.apply_diff_to_table::("private_table", &self.private_table); - diff.repeating_test_arg = cache.apply_diff_to_table::("repeating_test_arg", &self.repeating_test_arg).with_updates_by_pk(|row| &row.scheduled_id); - diff.table_to_remove = cache.apply_diff_to_table::("table_to_remove", &self.table_to_remove); - diff.test_a = cache.apply_diff_to_table::("test_a", &self.test_a); diff.test_d = cache.apply_diff_to_table::("test_d", &self.test_d); - diff.test_e = cache.apply_diff_to_table::("test_e", &self.test_e).with_updates_by_pk(|row| &row.id); diff.test_f = cache.apply_diff_to_table::("test_f", &self.test_f); diff.my_player = cache.apply_diff_to_table::("my_player", &self.my_player); @@ -1792,19 +1634,11 @@ impl __sdk::DbUpdate for DbUpdate { #[allow(non_snake_case)] #[doc(hidden)] pub struct AppliedDiff<'r> { - has_special_stuff: __sdk::TableAppliedDiff<'r, HasSpecialStuff>, - logged_out_player: __sdk::TableAppliedDiff<'r, Player>, + logged_out_player: __sdk::TableAppliedDiff<'r, Player>, my_player: __sdk::TableAppliedDiff<'r, Player>, person: __sdk::TableAppliedDiff<'r, Person>, - pk_multi_identity: __sdk::TableAppliedDiff<'r, PkMultiIdentity>, player: __sdk::TableAppliedDiff<'r, Player>, - points: __sdk::TableAppliedDiff<'r, Point>, - private_table: __sdk::TableAppliedDiff<'r, PrivateTable>, - repeating_test_arg: __sdk::TableAppliedDiff<'r, RepeatingTestArg>, - table_to_remove: __sdk::TableAppliedDiff<'r, RemoveTable>, - test_a: __sdk::TableAppliedDiff<'r, TestA>, test_d: __sdk::TableAppliedDiff<'r, TestD>, - test_e: __sdk::TableAppliedDiff<'r, TestE>, test_f: __sdk::TableAppliedDiff<'r, TestFoobar>, __unused: std::marker::PhantomData<&'r ()>, } @@ -1816,19 +1650,11 @@ impl __sdk::InModule for AppliedDiff<'_> { impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> { fn invoke_row_callbacks(&self, event: &EventContext, callbacks: &mut __sdk::DbCallbacks) { - callbacks.invoke_table_row_callbacks::("has_special_stuff", &self.has_special_stuff, event); - callbacks.invoke_table_row_callbacks::("logged_out_player", &self.logged_out_player, event); + callbacks.invoke_table_row_callbacks::("logged_out_player", &self.logged_out_player, event); callbacks.invoke_table_row_callbacks::("my_player", &self.my_player, event); callbacks.invoke_table_row_callbacks::("person", &self.person, event); - callbacks.invoke_table_row_callbacks::("pk_multi_identity", &self.pk_multi_identity, event); callbacks.invoke_table_row_callbacks::("player", &self.player, event); - callbacks.invoke_table_row_callbacks::("points", &self.points, event); - callbacks.invoke_table_row_callbacks::("private_table", &self.private_table, event); - callbacks.invoke_table_row_callbacks::("repeating_test_arg", &self.repeating_test_arg, event); - callbacks.invoke_table_row_callbacks::("table_to_remove", &self.table_to_remove, event); - callbacks.invoke_table_row_callbacks::("test_a", &self.test_a, event); callbacks.invoke_table_row_callbacks::("test_d", &self.test_d, event); - callbacks.invoke_table_row_callbacks::("test_e", &self.test_e, event); callbacks.invoke_table_row_callbacks::("test_f", &self.test_f, event); } } @@ -2547,19 +2373,11 @@ impl __sdk::SpacetimeModule for RemoteModule { type QueryBuilder = __sdk::QueryBuilder; fn register_tables(client_cache: &mut __sdk::ClientCache) { - has_special_stuff_table::register_table(client_cache); - logged_out_player_table::register_table(client_cache); + logged_out_player_table::register_table(client_cache); my_player_table::register_table(client_cache); person_table::register_table(client_cache); - pk_multi_identity_table::register_table(client_cache); player_table::register_table(client_cache); - points_table::register_table(client_cache); - private_table_table::register_table(client_cache); - repeating_test_arg_table::register_table(client_cache); - table_to_remove_table::register_table(client_cache); - test_a_table::register_table(client_cache); test_d_table::register_table(client_cache); - test_e_table::register_table(client_cache); test_f_table::register_table(client_cache); } } @@ -2973,202 +2791,6 @@ impl __sdk::__query_builder::HasIxCols for Person { } } -''' -"pk_multi_identity_table.rs" = ''' -// 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, -}; -use super::pk_multi_identity_type::PkMultiIdentity; - -/// Table handle for the table `pk_multi_identity`. -/// -/// Obtain a handle from the [`PkMultiIdentityTableAccess::pk_multi_identity`] method on [`super::RemoteTables`], -/// like `ctx.db.pk_multi_identity()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.pk_multi_identity().on_insert(...)`. -pub struct PkMultiIdentityTableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `pk_multi_identity`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait PkMultiIdentityTableAccess { - #[allow(non_snake_case)] - /// Obtain a [`PkMultiIdentityTableHandle`], which mediates access to the table `pk_multi_identity`. - fn pk_multi_identity(&self) -> PkMultiIdentityTableHandle<'_>; -} - -impl PkMultiIdentityTableAccess for super::RemoteTables { - fn pk_multi_identity(&self) -> PkMultiIdentityTableHandle<'_> { - PkMultiIdentityTableHandle { - imp: self.imp.get_table::("pk_multi_identity"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct PkMultiIdentityInsertCallbackId(__sdk::CallbackId); -pub struct PkMultiIdentityDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for PkMultiIdentityTableHandle<'ctx> { - type Row = PkMultiIdentity; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { self.imp.count() } - fn iter(&self) -> impl Iterator + '_ { self.imp.iter() } - - type InsertCallbackId = PkMultiIdentityInsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> PkMultiIdentityInsertCallbackId { - PkMultiIdentityInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: PkMultiIdentityInsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = PkMultiIdentityDeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> PkMultiIdentityDeleteCallbackId { - PkMultiIdentityDeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: PkMultiIdentityDeleteCallbackId) { - self.imp.remove_on_delete(callback.0) - } -} - -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - - let _table = client_cache.get_or_make_table::("pk_multi_identity"); - _table.add_unique_constraint::("id", |row| &row.id); - _table.add_unique_constraint::("other", |row| &row.other); -} -pub struct PkMultiIdentityUpdateCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::TableWithPrimaryKey for PkMultiIdentityTableHandle<'ctx> { - type UpdateCallbackId = PkMultiIdentityUpdateCallbackId; - - fn on_update( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, - ) -> PkMultiIdentityUpdateCallbackId { - PkMultiIdentityUpdateCallbackId(self.imp.on_update(Box::new(callback))) - } - - fn remove_on_update(&self, callback: PkMultiIdentityUpdateCallbackId) { - self.imp.remove_on_update(callback.0) - } -} - - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __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 `pk_multi_identity`, - /// which allows point queries on the field of the same name - /// via the [`PkMultiIdentityIdUnique::find`] method. - /// - /// Users are encouraged not to explicitly reference this type, - /// but to directly chain method calls, - /// like `ctx.db.pk_multi_identity().id().find(...)`. - pub struct PkMultiIdentityIdUnique<'ctx> { - imp: __sdk::UniqueConstraintHandle, - phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, - } - - impl<'ctx> PkMultiIdentityTableHandle<'ctx> { - /// Get a handle on the `id` unique index on the table `pk_multi_identity`. - pub fn id(&self) -> PkMultiIdentityIdUnique<'ctx> { - PkMultiIdentityIdUnique { - imp: self.imp.get_unique_constraint::("id"), - phantom: std::marker::PhantomData, - } - } - } - - impl<'ctx> PkMultiIdentityIdUnique<'ctx> { - /// Find the subscribed row whose `id` column value is equal to `col_val`, - /// if such a row is present in the client cache. - pub fn find(&self, col_val: &u32) -> Option { - self.imp.find(col_val) - } - } - - /// Access to the `other` unique index on the table `pk_multi_identity`, - /// which allows point queries on the field of the same name - /// via the [`PkMultiIdentityOtherUnique::find`] method. - /// - /// Users are encouraged not to explicitly reference this type, - /// but to directly chain method calls, - /// like `ctx.db.pk_multi_identity().other().find(...)`. - pub struct PkMultiIdentityOtherUnique<'ctx> { - imp: __sdk::UniqueConstraintHandle, - phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, - } - - impl<'ctx> PkMultiIdentityTableHandle<'ctx> { - /// Get a handle on the `other` unique index on the table `pk_multi_identity`. - pub fn other(&self) -> PkMultiIdentityOtherUnique<'ctx> { - PkMultiIdentityOtherUnique { - imp: self.imp.get_unique_constraint::("other"), - phantom: std::marker::PhantomData, - } - } - } - - impl<'ctx> PkMultiIdentityOtherUnique<'ctx> { - /// Find the subscribed row whose `other` column value is equal to `col_val`, - /// if such a row is present in the client cache. - pub fn find(&self, col_val: &u32) -> Option { - self.imp.find(col_val) - } - } - - #[allow(non_camel_case_types)] - /// Extension trait for query builder access to the table `PkMultiIdentity`. - /// - /// Implemented for [`__sdk::QueryTableAccessor`]. - pub trait pk_multi_identityQueryTableAccess { - #[allow(non_snake_case)] - /// Get a query builder for the table `PkMultiIdentity`. - fn pk_multi_identity(&self) -> __sdk::__query_builder::Table; - } - - impl pk_multi_identityQueryTableAccess for __sdk::QueryTableAccessor { - fn pk_multi_identity(&self) -> __sdk::__query_builder::Table { - __sdk::__query_builder::Table::new("pk_multi_identity") - } - } - ''' "pk_multi_identity_type.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -3593,7 +3215,7 @@ impl __sdk::__query_builder::HasIxCols for Point { } ''' -"points_table.rs" = ''' +"private_table_type.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. @@ -3604,285 +3226,51 @@ use spacetimedb_sdk::__codegen::{ __sats, __ws, }; -use super::point_type::Point; -/// Table handle for the table `points`. -/// -/// Obtain a handle from the [`PointsTableAccess::points`] method on [`super::RemoteTables`], -/// like `ctx.db.points()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.points().on_insert(...)`. -pub struct PointsTableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct PrivateTable { + pub name: String, } -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `points`. + +impl __sdk::InModule for PrivateTable { + type Module = super::RemoteModule; +} + + +/// Column accessor struct for the table `PrivateTable`. /// -/// Implemented for [`super::RemoteTables`]. -pub trait PointsTableAccess { - #[allow(non_snake_case)] - /// Obtain a [`PointsTableHandle`], which mediates access to the table `points`. - fn points(&self) -> PointsTableHandle<'_>; +/// Provides typed access to columns for query building. +pub struct PrivateTableCols { + pub name: __sdk::__query_builder::Col, } -impl PointsTableAccess for super::RemoteTables { - fn points(&self) -> PointsTableHandle<'_> { - PointsTableHandle { - imp: self.imp.get_table::("points"), - ctx: std::marker::PhantomData, +impl __sdk::__query_builder::HasCols for PrivateTable { + type Cols = PrivateTableCols; + fn cols(table_name: &'static str) -> Self::Cols { + PrivateTableCols { + name: __sdk::__query_builder::Col::new(table_name, "name"), + } } } -pub struct PointsInsertCallbackId(__sdk::CallbackId); -pub struct PointsDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for PointsTableHandle<'ctx> { - type Row = Point; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { self.imp.count() } - fn iter(&self) -> impl Iterator + '_ { self.imp.iter() } - - type InsertCallbackId = PointsInsertCallbackId; +/// Indexed column accessor struct for the table `PrivateTable`. +/// +/// Provides typed access to indexed columns for query building. +pub struct PrivateTableIxCols { +} - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> PointsInsertCallbackId { - PointsInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } +impl __sdk::__query_builder::HasIxCols for PrivateTable { + type IxCols = PrivateTableIxCols; + fn ix_cols(table_name: &'static str) -> Self::IxCols { + PrivateTableIxCols { - fn remove_on_insert(&self, callback: PointsInsertCallbackId) { - self.imp.remove_on_insert(callback.0) + } } - - type DeleteCallbackId = PointsDeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> PointsDeleteCallbackId { - PointsDeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: PointsDeleteCallbackId) { - self.imp.remove_on_delete(callback.0) - } -} - -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - - let _table = client_cache.get_or_make_table::("points"); -} - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __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 `Point`. - /// - /// Implemented for [`__sdk::QueryTableAccessor`]. - pub trait pointsQueryTableAccess { - #[allow(non_snake_case)] - /// Get a query builder for the table `Point`. - fn points(&self) -> __sdk::__query_builder::Table; - } - - impl pointsQueryTableAccess for __sdk::QueryTableAccessor { - fn points(&self) -> __sdk::__query_builder::Table { - __sdk::__query_builder::Table::new("points") - } - } - -''' -"private_table_table.rs" = ''' -// 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, -}; -use super::private_table_type::PrivateTable; - -/// Table handle for the table `private_table`. -/// -/// Obtain a handle from the [`PrivateTableTableAccess::private_table`] method on [`super::RemoteTables`], -/// like `ctx.db.private_table()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.private_table().on_insert(...)`. -pub struct PrivateTableTableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `private_table`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait PrivateTableTableAccess { - #[allow(non_snake_case)] - /// Obtain a [`PrivateTableTableHandle`], which mediates access to the table `private_table`. - fn private_table(&self) -> PrivateTableTableHandle<'_>; -} - -impl PrivateTableTableAccess for super::RemoteTables { - fn private_table(&self) -> PrivateTableTableHandle<'_> { - PrivateTableTableHandle { - imp: self.imp.get_table::("private_table"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct PrivateTableInsertCallbackId(__sdk::CallbackId); -pub struct PrivateTableDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for PrivateTableTableHandle<'ctx> { - type Row = PrivateTable; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { self.imp.count() } - fn iter(&self) -> impl Iterator + '_ { self.imp.iter() } - - type InsertCallbackId = PrivateTableInsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> PrivateTableInsertCallbackId { - PrivateTableInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: PrivateTableInsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = PrivateTableDeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> PrivateTableDeleteCallbackId { - PrivateTableDeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: PrivateTableDeleteCallbackId) { - self.imp.remove_on_delete(callback.0) - } -} - -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - - let _table = client_cache.get_or_make_table::("private_table"); -} - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __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 `PrivateTable`. - /// - /// Implemented for [`__sdk::QueryTableAccessor`]. - pub trait private_tableQueryTableAccess { - #[allow(non_snake_case)] - /// Get a query builder for the table `PrivateTable`. - fn private_table(&self) -> __sdk::__query_builder::Table; - } - - impl private_tableQueryTableAccess for __sdk::QueryTableAccessor { - fn private_table(&self) -> __sdk::__query_builder::Table { - __sdk::__query_builder::Table::new("private_table") - } - } - -''' -"private_table_type.rs" = ''' -// 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 PrivateTable { - pub name: String, -} - - -impl __sdk::InModule for PrivateTable { - type Module = super::RemoteModule; -} - - -/// Column accessor struct for the table `PrivateTable`. -/// -/// Provides typed access to columns for query building. -pub struct PrivateTableCols { - pub name: __sdk::__query_builder::Col, -} - -impl __sdk::__query_builder::HasCols for PrivateTable { - type Cols = PrivateTableCols; - fn cols(table_name: &'static str) -> Self::Cols { - PrivateTableCols { - name: __sdk::__query_builder::Col::new(table_name, "name"), - - } - } -} - -/// Indexed column accessor struct for the table `PrivateTable`. -/// -/// Provides typed access to indexed columns for query building. -pub struct PrivateTableIxCols { -} - -impl __sdk::__query_builder::HasIxCols for PrivateTable { - type IxCols = PrivateTableIxCols; - fn ix_cols(table_name: &'static str) -> Self::IxCols { - PrivateTableIxCols { - - } - } -} +} ''' "query_private_reducer.rs" = ''' @@ -4047,171 +3435,6 @@ impl __sdk::__query_builder::HasIxCols for RemoveTable { } } -''' -"repeating_test_arg_table.rs" = ''' -// 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, -}; -use super::repeating_test_arg_type::RepeatingTestArg; - -/// Table handle for the table `repeating_test_arg`. -/// -/// Obtain a handle from the [`RepeatingTestArgTableAccess::repeating_test_arg`] method on [`super::RemoteTables`], -/// like `ctx.db.repeating_test_arg()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.repeating_test_arg().on_insert(...)`. -pub struct RepeatingTestArgTableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `repeating_test_arg`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait RepeatingTestArgTableAccess { - #[allow(non_snake_case)] - /// Obtain a [`RepeatingTestArgTableHandle`], which mediates access to the table `repeating_test_arg`. - fn repeating_test_arg(&self) -> RepeatingTestArgTableHandle<'_>; -} - -impl RepeatingTestArgTableAccess for super::RemoteTables { - fn repeating_test_arg(&self) -> RepeatingTestArgTableHandle<'_> { - RepeatingTestArgTableHandle { - imp: self.imp.get_table::("repeating_test_arg"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct RepeatingTestArgInsertCallbackId(__sdk::CallbackId); -pub struct RepeatingTestArgDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for RepeatingTestArgTableHandle<'ctx> { - type Row = RepeatingTestArg; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { self.imp.count() } - fn iter(&self) -> impl Iterator + '_ { self.imp.iter() } - - type InsertCallbackId = RepeatingTestArgInsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> RepeatingTestArgInsertCallbackId { - RepeatingTestArgInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: RepeatingTestArgInsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = RepeatingTestArgDeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> RepeatingTestArgDeleteCallbackId { - RepeatingTestArgDeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: RepeatingTestArgDeleteCallbackId) { - self.imp.remove_on_delete(callback.0) - } -} - -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - - let _table = client_cache.get_or_make_table::("repeating_test_arg"); - _table.add_unique_constraint::("scheduled_id", |row| &row.scheduled_id); -} -pub struct RepeatingTestArgUpdateCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::TableWithPrimaryKey for RepeatingTestArgTableHandle<'ctx> { - type UpdateCallbackId = RepeatingTestArgUpdateCallbackId; - - fn on_update( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, - ) -> RepeatingTestArgUpdateCallbackId { - RepeatingTestArgUpdateCallbackId(self.imp.on_update(Box::new(callback))) - } - - fn remove_on_update(&self, callback: RepeatingTestArgUpdateCallbackId) { - self.imp.remove_on_update(callback.0) - } -} - - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __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 `repeating_test_arg`, - /// which allows point queries on the field of the same name - /// via the [`RepeatingTestArgScheduledIdUnique::find`] method. - /// - /// Users are encouraged not to explicitly reference this type, - /// but to directly chain method calls, - /// like `ctx.db.repeating_test_arg().scheduled_id().find(...)`. - pub struct RepeatingTestArgScheduledIdUnique<'ctx> { - imp: __sdk::UniqueConstraintHandle, - phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, - } - - impl<'ctx> RepeatingTestArgTableHandle<'ctx> { - /// Get a handle on the `scheduled_id` unique index on the table `repeating_test_arg`. - pub fn scheduled_id(&self) -> RepeatingTestArgScheduledIdUnique<'ctx> { - RepeatingTestArgScheduledIdUnique { - imp: self.imp.get_unique_constraint::("scheduled_id"), - phantom: std::marker::PhantomData, - } - } - } - - impl<'ctx> RepeatingTestArgScheduledIdUnique<'ctx> { - /// Find the subscribed row whose `scheduled_id` column value is equal to `col_val`, - /// if such a row is present in the client cache. - pub fn find(&self, col_val: &u64) -> Option { - self.imp.find(col_val) - } - } - - #[allow(non_camel_case_types)] - /// Extension trait for query builder access to the table `RepeatingTestArg`. - /// - /// Implemented for [`__sdk::QueryTableAccessor`]. - pub trait repeating_test_argQueryTableAccess { - #[allow(non_snake_case)] - /// Get a query builder for the table `RepeatingTestArg`. - fn repeating_test_arg(&self) -> __sdk::__query_builder::Table; - } - - impl repeating_test_argQueryTableAccess for __sdk::QueryTableAccessor { - fn repeating_test_arg(&self) -> __sdk::__query_builder::Table { - __sdk::__query_builder::Table::new("repeating_test_arg") - } - } - ''' "repeating_test_arg_type.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -4501,231 +3724,60 @@ pub trait say_hello { /// Cancel a callback previously registered by [`Self::on_say_hello`], /// causing it not to run in the future. fn remove_on_say_hello(&self, callback: SayHelloCallbackId); -} - -impl say_hello for super::RemoteReducers { - fn say_hello(&self, ) -> __sdk::Result<()> { - self.imp.call_reducer("say_hello", SayHelloArgs { }) - } - fn on_say_hello( - &self, - mut callback: impl FnMut(&super::ReducerEventContext, ) + Send + 'static, - ) -> SayHelloCallbackId { - SayHelloCallbackId(self.imp.on_reducer( - "say_hello", - Box::new(move |ctx: &super::ReducerEventContext| { - #[allow(irrefutable_let_patterns)] - let super::ReducerEventContext { - event: __sdk::ReducerEvent { - reducer: super::Reducer::SayHello { - - }, - .. - }, - .. - } = ctx else { unreachable!() }; - callback(ctx, ) - }), - )) - } - fn remove_on_say_hello(&self, callback: SayHelloCallbackId) { - self.imp.remove_on_reducer("say_hello", callback.0) - } -} - -#[allow(non_camel_case_types)] -#[doc(hidden)] -/// Extension trait for setting the call-flags for the reducer `say_hello`. -/// -/// Implemented for [`super::SetReducerFlags`]. -/// -/// This type is currently unstable and may be removed without a major version bump. -pub trait set_flags_for_say_hello { - /// Set the call-reducer flags for the reducer `say_hello` to `flags`. - /// - /// This type is currently unstable and may be removed without a major version bump. - fn say_hello(&self, flags: __ws::CallReducerFlags); -} - -impl set_flags_for_say_hello for super::SetReducerFlags { - fn say_hello(&self, flags: __ws::CallReducerFlags) { - self.imp.set_call_reducer_flags("say_hello", flags); - } -} - -''' -"sleep_one_second_procedure.rs" = ''' -// 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)] - struct SleepOneSecondArgs { - } - - -impl __sdk::InModule for SleepOneSecondArgs { - type Module = super::RemoteModule; -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the procedure `sleep_one_second`. -/// -/// Implemented for [`super::RemoteProcedures`]. -pub trait sleep_one_second { - fn sleep_one_second(&self, ) { - self.sleep_one_second_then( |_, _| {}); - } - - fn sleep_one_second_then( - &self, - - __callback: impl FnOnce(&super::ProcedureEventContext, Result<(), __sdk::InternalError>) + Send + 'static, - ); -} - -impl sleep_one_second for super::RemoteProcedures { - fn sleep_one_second_then( - &self, - - __callback: impl FnOnce(&super::ProcedureEventContext, Result<(), __sdk::InternalError>) + Send + 'static, - ) { - self.imp.invoke_procedure_with_callback::<_, ()>( - "sleep_one_second", - SleepOneSecondArgs { }, - __callback, - ); - } -} - -''' -"table_to_remove_table.rs" = ''' -// 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, -}; -use super::remove_table_type::RemoveTable; - -/// Table handle for the table `table_to_remove`. -/// -/// Obtain a handle from the [`TableToRemoveTableAccess::table_to_remove`] method on [`super::RemoteTables`], -/// like `ctx.db.table_to_remove()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.table_to_remove().on_insert(...)`. -pub struct TableToRemoveTableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `table_to_remove`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait TableToRemoveTableAccess { - #[allow(non_snake_case)] - /// Obtain a [`TableToRemoveTableHandle`], which mediates access to the table `table_to_remove`. - fn table_to_remove(&self) -> TableToRemoveTableHandle<'_>; -} - -impl TableToRemoveTableAccess for super::RemoteTables { - fn table_to_remove(&self) -> TableToRemoveTableHandle<'_> { - TableToRemoveTableHandle { - imp: self.imp.get_table::("table_to_remove"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct TableToRemoveInsertCallbackId(__sdk::CallbackId); -pub struct TableToRemoveDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for TableToRemoveTableHandle<'ctx> { - type Row = RemoveTable; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { self.imp.count() } - fn iter(&self) -> impl Iterator + '_ { self.imp.iter() } - - type InsertCallbackId = TableToRemoveInsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> TableToRemoveInsertCallbackId { - TableToRemoveInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: TableToRemoveInsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = TableToRemoveDeleteCallbackId; +} - fn on_delete( +impl say_hello for super::RemoteReducers { + fn say_hello(&self, ) -> __sdk::Result<()> { + self.imp.call_reducer("say_hello", SayHelloArgs { }) + } + fn on_say_hello( &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> TableToRemoveDeleteCallbackId { - TableToRemoveDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + mut callback: impl FnMut(&super::ReducerEventContext, ) + Send + 'static, + ) -> SayHelloCallbackId { + SayHelloCallbackId(self.imp.on_reducer( + "say_hello", + Box::new(move |ctx: &super::ReducerEventContext| { + #[allow(irrefutable_let_patterns)] + let super::ReducerEventContext { + event: __sdk::ReducerEvent { + reducer: super::Reducer::SayHello { + + }, + .. + }, + .. + } = ctx else { unreachable!() }; + callback(ctx, ) + }), + )) } - - fn remove_on_delete(&self, callback: TableToRemoveDeleteCallbackId) { - self.imp.remove_on_delete(callback.0) + fn remove_on_say_hello(&self, callback: SayHelloCallbackId) { + self.imp.remove_on_reducer("say_hello", callback.0) } } +#[allow(non_camel_case_types)] #[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - - let _table = client_cache.get_or_make_table::("table_to_remove"); +/// Extension trait for setting the call-flags for the reducer `say_hello`. +/// +/// Implemented for [`super::SetReducerFlags`]. +/// +/// This type is currently unstable and may be removed without a major version bump. +pub trait set_flags_for_say_hello { + /// Set the call-reducer flags for the reducer `say_hello` to `flags`. + /// + /// This type is currently unstable and may be removed without a major version bump. + fn say_hello(&self, flags: __ws::CallReducerFlags); } -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse( - "TableUpdate", - "TableUpdate", - ).with_cause(e).into() - }) +impl set_flags_for_say_hello for super::SetReducerFlags { + fn say_hello(&self, flags: __ws::CallReducerFlags) { + self.imp.set_call_reducer_flags("say_hello", flags); + } } - #[allow(non_camel_case_types)] - /// Extension trait for query builder access to the table `RemoveTable`. - /// - /// Implemented for [`__sdk::QueryTableAccessor`]. - pub trait table_to_removeQueryTableAccess { - #[allow(non_snake_case)] - /// Get a query builder for the table `RemoveTable`. - fn table_to_remove(&self) -> __sdk::__query_builder::Table; - } - - impl table_to_removeQueryTableAccess for __sdk::QueryTableAccessor { - fn table_to_remove(&self) -> __sdk::__query_builder::Table { - __sdk::__query_builder::Table::new("table_to_remove") - } - } - ''' -"test_a_table.rs" = ''' +"sleep_one_second_procedure.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. @@ -4736,111 +3788,48 @@ use spacetimedb_sdk::__codegen::{ __sats, __ws, }; -use super::test_a_type::TestA; - -/// Table handle for the table `test_a`. -/// -/// Obtain a handle from the [`TestATableAccess::test_a`] method on [`super::RemoteTables`], -/// like `ctx.db.test_a()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.test_a().on_insert(...)`. -pub struct TestATableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `test_a`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait TestATableAccess { - #[allow(non_snake_case)] - /// Obtain a [`TestATableHandle`], which mediates access to the table `test_a`. - fn test_a(&self) -> TestATableHandle<'_>; -} -impl TestATableAccess for super::RemoteTables { - fn test_a(&self) -> TestATableHandle<'_> { - TestATableHandle { - imp: self.imp.get_table::("test_a"), - ctx: std::marker::PhantomData, - } +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] + struct SleepOneSecondArgs { } -} - -pub struct TestAInsertCallbackId(__sdk::CallbackId); -pub struct TestADeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for TestATableHandle<'ctx> { - type Row = TestA; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { self.imp.count() } - fn iter(&self) -> impl Iterator + '_ { self.imp.iter() } - type InsertCallbackId = TestAInsertCallbackId; - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> TestAInsertCallbackId { - TestAInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } +impl __sdk::InModule for SleepOneSecondArgs { + type Module = super::RemoteModule; +} - fn remove_on_insert(&self, callback: TestAInsertCallbackId) { - self.imp.remove_on_insert(callback.0) +#[allow(non_camel_case_types)] +/// Extension trait for access to the procedure `sleep_one_second`. +/// +/// Implemented for [`super::RemoteProcedures`]. +pub trait sleep_one_second { + fn sleep_one_second(&self, ) { + self.sleep_one_second_then( |_, _| {}); } - type DeleteCallbackId = TestADeleteCallbackId; - - fn on_delete( + fn sleep_one_second_then( &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> TestADeleteCallbackId { - TestADeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: TestADeleteCallbackId) { - self.imp.remove_on_delete(callback.0) - } -} - -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - - let _table = client_cache.get_or_make_table::("test_a"); + + __callback: impl FnOnce(&super::ProcedureEventContext, Result<(), __sdk::InternalError>) + Send + 'static, + ); } -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __sdk::Result<__sdk::TableUpdate> { - __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { - __sdk::InternalError::failed_parse( - "TableUpdate", - "TableUpdate", - ).with_cause(e).into() - }) +impl sleep_one_second for super::RemoteProcedures { + fn sleep_one_second_then( + &self, + + __callback: impl FnOnce(&super::ProcedureEventContext, Result<(), __sdk::InternalError>) + Send + 'static, + ) { + self.imp.invoke_procedure_with_callback::<_, ()>( + "sleep_one_second", + SleepOneSecondArgs { }, + __callback, + ); + } } - #[allow(non_camel_case_types)] - /// Extension trait for query builder access to the table `TestA`. - /// - /// Implemented for [`__sdk::QueryTableAccessor`]. - pub trait test_aQueryTableAccess { - #[allow(non_snake_case)] - /// Get a query builder for the table `TestA`. - fn test_a(&self) -> __sdk::__query_builder::Table; - } - - impl test_aQueryTableAccess for __sdk::QueryTableAccessor { - fn test_a(&self) -> __sdk::__query_builder::Table { - __sdk::__query_builder::Table::new("test_a") - } - } - ''' "test_a_type.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -5214,171 +4203,6 @@ impl __sdk::__query_builder::HasIxCols for TestD { } } -''' -"test_e_table.rs" = ''' -// 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, -}; -use super::test_e_type::TestE; - -/// Table handle for the table `test_e`. -/// -/// Obtain a handle from the [`TestETableAccess::test_e`] method on [`super::RemoteTables`], -/// like `ctx.db.test_e()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.test_e().on_insert(...)`. -pub struct TestETableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `test_e`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait TestETableAccess { - #[allow(non_snake_case)] - /// Obtain a [`TestETableHandle`], which mediates access to the table `test_e`. - fn test_e(&self) -> TestETableHandle<'_>; -} - -impl TestETableAccess for super::RemoteTables { - fn test_e(&self) -> TestETableHandle<'_> { - TestETableHandle { - imp: self.imp.get_table::("test_e"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct TestEInsertCallbackId(__sdk::CallbackId); -pub struct TestEDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for TestETableHandle<'ctx> { - type Row = TestE; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { self.imp.count() } - fn iter(&self) -> impl Iterator + '_ { self.imp.iter() } - - type InsertCallbackId = TestEInsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> TestEInsertCallbackId { - TestEInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: TestEInsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = TestEDeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> TestEDeleteCallbackId { - TestEDeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: TestEDeleteCallbackId) { - self.imp.remove_on_delete(callback.0) - } -} - -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - - let _table = client_cache.get_or_make_table::("test_e"); - _table.add_unique_constraint::("id", |row| &row.id); -} -pub struct TestEUpdateCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::TableWithPrimaryKey for TestETableHandle<'ctx> { - type UpdateCallbackId = TestEUpdateCallbackId; - - fn on_update( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, - ) -> TestEUpdateCallbackId { - TestEUpdateCallbackId(self.imp.on_update(Box::new(callback))) - } - - fn remove_on_update(&self, callback: TestEUpdateCallbackId) { - self.imp.remove_on_update(callback.0) - } -} - - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __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 `test_e`, - /// which allows point queries on the field of the same name - /// via the [`TestEIdUnique::find`] method. - /// - /// Users are encouraged not to explicitly reference this type, - /// but to directly chain method calls, - /// like `ctx.db.test_e().id().find(...)`. - pub struct TestEIdUnique<'ctx> { - imp: __sdk::UniqueConstraintHandle, - phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, - } - - impl<'ctx> TestETableHandle<'ctx> { - /// Get a handle on the `id` unique index on the table `test_e`. - pub fn id(&self) -> TestEIdUnique<'ctx> { - TestEIdUnique { - imp: self.imp.get_unique_constraint::("id"), - phantom: std::marker::PhantomData, - } - } - } - - impl<'ctx> TestEIdUnique<'ctx> { - /// Find the subscribed row whose `id` column value is equal to `col_val`, - /// if such a row is present in the client cache. - pub fn find(&self, col_val: &u64) -> Option { - self.imp.find(col_val) - } - } - - #[allow(non_camel_case_types)] - /// Extension trait for query builder access to the table `TestE`. - /// - /// Implemented for [`__sdk::QueryTableAccessor`]. - pub trait test_eQueryTableAccess { - #[allow(non_snake_case)] - /// Get a query builder for the table `TestE`. - fn test_e(&self) -> __sdk::__query_builder::Table; - } - - impl test_eQueryTableAccess for __sdk::QueryTableAccessor { - fn test_e(&self) -> __sdk::__query_builder::Table { - __sdk::__query_builder::Table::new("test_e") - } - } - ''' "test_e_type.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE diff --git a/crates/codegen/tests/snapshots/codegen__codegen_typescript.snap b/crates/codegen/tests/snapshots/codegen__codegen_typescript.snap index c2dee2a19b0..1bef42e38e6 100644 --- a/crates/codegen/tests/snapshots/codegen__codegen_typescript.snap +++ b/crates/codegen/tests/snapshots/codegen__codegen_typescript.snap @@ -180,24 +180,6 @@ import { export const params = { }; export const returnType = __t.string()''' -"has_special_stuff_table.ts" = ''' -// 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 { - TypeBuilder as __TypeBuilder, - t as __t, - type AlgebraicTypeType as __AlgebraicTypeType, - type Infer as __Infer, -} from "spacetimedb"; - -export default __t.row({ - identity: __t.identity(), - connectionId: __t.connectionId().name("connection_id"), -}); -''' "has_special_stuff_type.ts" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. @@ -295,32 +277,16 @@ import * as WithTxProcedure from "./with_tx_procedure"; export { WithTxProcedure }; // Import and reexport all table handle types -import HasSpecialStuffRow from "./has_special_stuff_table"; -export { HasSpecialStuffRow }; import LoggedOutPlayerRow from "./logged_out_player_table"; export { LoggedOutPlayerRow }; import MyPlayerRow from "./my_player_table"; export { MyPlayerRow }; import PersonRow from "./person_table"; export { PersonRow }; -import PkMultiIdentityRow from "./pk_multi_identity_table"; -export { PkMultiIdentityRow }; import PlayerRow from "./player_table"; export { PlayerRow }; -import PointsRow from "./points_table"; -export { PointsRow }; -import PrivateTableRow from "./private_table_table"; -export { PrivateTableRow }; -import RepeatingTestArgRow from "./repeating_test_arg_table"; -export { RepeatingTestArgRow }; -import TableToRemoveRow from "./table_to_remove_table"; -export { TableToRemoveRow }; -import TestARow from "./test_a_table"; -export { TestARow }; import TestDRow from "./test_d_table"; export { TestDRow }; -import TestERow from "./test_e_table"; -export { TestERow }; import TestFRow from "./test_f_table"; export { TestFRow }; @@ -362,13 +328,6 @@ export { NamespaceTestF }; /** 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({ - name: 'has_special_stuff', - indexes: [ - ], - constraints: [ - ], - }, HasSpecialStuffRow), __table({ name: 'logged_out_player', indexes: [ @@ -402,21 +361,6 @@ const tablesSchema = __schema( { name: 'person_id_key', constraint: 'unique', columns: ['id'] }, ], }, PersonRow), - __table({ - name: 'pk_multi_identity', - indexes: [ - { name: 'id', algorithm: 'btree', columns: [ - 'id', - ] }, - { name: 'other', algorithm: 'btree', columns: [ - 'other', - ] }, - ], - constraints: [ - { name: 'pk_multi_identity_id_key', constraint: 'unique', columns: ['id'] }, - { name: 'pk_multi_identity_other_key', constraint: 'unique', columns: ['other'] }, - ], - }, PkMultiIdentityRow), __table({ name: 'player', indexes: [ @@ -436,52 +380,6 @@ const tablesSchema = __schema( { name: 'player_player_id_key', constraint: 'unique', columns: ['playerId'] }, ], }, PlayerRow), - __table({ - name: 'points', - indexes: [ - { name: 'multi_column_index', algorithm: 'btree', columns: [ - 'x', - 'y', - ] }, - ], - constraints: [ - ], - }, PointsRow), - __table({ - name: 'private_table', - indexes: [ - ], - constraints: [ - ], - }, PrivateTableRow), - __table({ - name: 'repeating_test_arg', - indexes: [ - { name: 'scheduled_id', algorithm: 'btree', columns: [ - 'scheduledId', - ] }, - ], - constraints: [ - { name: 'repeating_test_arg_scheduled_id_key', constraint: 'unique', columns: ['scheduledId'] }, - ], - }, RepeatingTestArgRow), - __table({ - name: 'table_to_remove', - indexes: [ - ], - constraints: [ - ], - }, TableToRemoveRow), - __table({ - name: 'test_a', - indexes: [ - { name: 'foo', algorithm: 'btree', columns: [ - 'x', - ] }, - ], - constraints: [ - ], - }, TestARow), __table({ name: 'test_d', indexes: [ @@ -489,20 +387,6 @@ const tablesSchema = __schema( constraints: [ ], }, TestDRow), - __table({ - name: 'test_e', - indexes: [ - { name: 'id', algorithm: 'btree', columns: [ - 'id', - ] }, - { name: 'name', algorithm: 'btree', columns: [ - 'name', - ] }, - ], - constraints: [ - { name: 'test_e_id_key', constraint: 'unique', columns: ['id'] }, - ], - }, TestERow), __table({ name: 'test_f', indexes: [ @@ -752,24 +636,6 @@ export default __t.object("Person", { }); -''' -"pk_multi_identity_table.ts" = ''' -// 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 { - TypeBuilder as __TypeBuilder, - t as __t, - type AlgebraicTypeType as __AlgebraicTypeType, - type Infer as __Infer, -} from "spacetimedb"; - -export default __t.row({ - id: __t.u32().primaryKey(), - other: __t.u32(), -}); ''' "pk_multi_identity_type.ts" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -850,41 +716,6 @@ export default __t.object("Point", { }); -''' -"points_table.ts" = ''' -// 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 { - TypeBuilder as __TypeBuilder, - t as __t, - type AlgebraicTypeType as __AlgebraicTypeType, - type Infer as __Infer, -} from "spacetimedb"; - -export default __t.row({ - x: __t.i64(), - y: __t.i64(), -}); -''' -"private_table_table.ts" = ''' -// 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 { - TypeBuilder as __TypeBuilder, - t as __t, - type AlgebraicTypeType as __AlgebraicTypeType, - type Infer as __Infer, -} from "spacetimedb"; - -export default __t.row({ - name: __t.string(), -}); ''' "private_table_type.ts" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -938,25 +769,6 @@ export default __t.object("RemoveTable", { }); -''' -"repeating_test_arg_table.ts" = ''' -// 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 { - TypeBuilder as __TypeBuilder, - t as __t, - type AlgebraicTypeType as __AlgebraicTypeType, - type Infer as __Infer, -} from "spacetimedb"; - -export default __t.row({ - scheduledId: __t.u64().primaryKey().name("scheduled_id"), - scheduledAt: __t.scheduleAt().name("scheduled_at"), - prevTime: __t.timestamp().name("prev_time"), -}); ''' "repeating_test_arg_type.ts" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -1050,42 +862,6 @@ import { export const params = { }; export const returnType = __t.unit()''' -"table_to_remove_table.ts" = ''' -// 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 { - TypeBuilder as __TypeBuilder, - t as __t, - type AlgebraicTypeType as __AlgebraicTypeType, - type Infer as __Infer, -} from "spacetimedb"; - -export default __t.row({ - id: __t.u32(), -}); -''' -"test_a_table.ts" = ''' -// 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 { - TypeBuilder as __TypeBuilder, - t as __t, - type AlgebraicTypeType as __AlgebraicTypeType, - type Infer as __Infer, -} from "spacetimedb"; - -export default __t.row({ - x: __t.u32(), - y: __t.u32(), - z: __t.string(), -}); -''' "test_a_type.ts" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. @@ -1184,24 +960,6 @@ export default __t.object("TestD", { }); -''' -"test_e_table.ts" = ''' -// 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 { - TypeBuilder as __TypeBuilder, - t as __t, - type AlgebraicTypeType as __AlgebraicTypeType, - type Infer as __Infer, -} from "spacetimedb"; - -export default __t.row({ - id: __t.u64().primaryKey(), - name: __t.string(), -}); ''' "test_e_type.ts" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE From e472665998688b1227bea6600d8103ffd3ad172d Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Tue, 3 Feb 2026 18:07:25 -0800 Subject: [PATCH 08/18] Updated Blackholio bindings for Unreal, but rolled back Unity as it broke and I'm not certain why yet --- .../ModuleBindings/SpacetimeDBClient.g.cpp | 304 ++++++++++++++---- .../Tables/CircleDecayTimerTable.g.cpp | 47 --- .../Tables/CircleRecombineTimerTable.g.cpp | 47 --- .../Tables/ConsumeEntityTimerTable.g.cpp | 47 --- .../Tables/MoveAllPlayersTimerTable.g.cpp | 47 --- .../Tables/SpawnFoodTimerTable.g.cpp | 47 --- .../ModuleBindings/SpacetimeDBClient.g.h | 145 ++++++--- .../Tables/CircleDecayTimerTable.g.h | 104 ------ .../Tables/CircleRecombineTimerTable.g.h | 104 ------ .../ModuleBindings/Tables/CircleTable.g.h | 4 +- .../Tables/ConsumeEntityTimerTable.g.h | 104 ------ .../Tables/MoveAllPlayersTimerTable.g.h | 104 ------ .../ModuleBindings/Tables/PlayerTable.g.h | 4 +- .../Tables/SpawnFoodTimerTable.g.h | 104 ------ 14 files changed, 345 insertions(+), 867 deletions(-) delete mode 100644 demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleDecayTimerTable.g.cpp delete mode 100644 demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleRecombineTimerTable.g.cpp delete mode 100644 demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/ConsumeEntityTimerTable.g.cpp delete mode 100644 demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.cpp delete mode 100644 demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/SpawnFoodTimerTable.g.cpp delete mode 100644 demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleDecayTimerTable.g.h delete mode 100644 demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleRecombineTimerTable.g.h delete mode 100644 demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/ConsumeEntityTimerTable.g.h delete mode 100644 demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.h delete mode 100644 demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/SpawnFoodTimerTable.g.h 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 33552184eed..c3f5355ed41 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 @@ -4,19 +4,11 @@ #include "ModuleBindings/SpacetimeDBClient.g.h" #include "DBCache/WithBsatn.h" #include "BSATN/UEBSATNHelpers.h" -#include "ModuleBindings/Tables/ConsumeEntityTimerTable.g.h" #include "ModuleBindings/Tables/CircleTable.g.h" -#include "ModuleBindings/Tables/FoodTable.g.h" -#include "ModuleBindings/Tables/CircleTable.g.h" -#include "ModuleBindings/Tables/SpawnFoodTimerTable.g.h" #include "ModuleBindings/Tables/ConfigTable.g.h" -#include "ModuleBindings/Tables/PlayerTable.g.h" #include "ModuleBindings/Tables/EntityTable.g.h" +#include "ModuleBindings/Tables/FoodTable.g.h" #include "ModuleBindings/Tables/PlayerTable.g.h" -#include "ModuleBindings/Tables/CircleDecayTimerTable.g.h" -#include "ModuleBindings/Tables/CircleRecombineTimerTable.g.h" -#include "ModuleBindings/Tables/EntityTable.g.h" -#include "ModuleBindings/Tables/MoveAllPlayersTimerTable.g.h" static FReducer DecodeReducer(const FReducerEvent& Event) { @@ -108,19 +100,14 @@ UDbConnection::UDbConnection(const FObjectInitializer& ObjectInitializer) : Supe Reducers->SetCallReducerFlags = SetReducerFlags; Reducers->Conn = this; - RegisterTable(TEXT("consume_entity_timer"), Db->ConsumeEntityTimer); + Procedures = ObjectInitializer.CreateDefaultSubobject(this, TEXT("RemoteProcedures")); + Procedures->Conn = this; + RegisterTable(TEXT("circle"), Db->Circle); - RegisterTable(TEXT("food"), Db->Food); - RegisterTable(TEXT("logged_out_circle"), Db->LoggedOutCircle); - RegisterTable(TEXT("spawn_food_timer"), Db->SpawnFoodTimer); RegisterTable(TEXT("config"), Db->Config); - RegisterTable(TEXT("player"), Db->Player); - RegisterTable(TEXT("logged_out_entity"), Db->LoggedOutEntity); - RegisterTable(TEXT("logged_out_player"), Db->LoggedOutPlayer); - RegisterTable(TEXT("circle_decay_timer"), Db->CircleDecayTimer); - RegisterTable(TEXT("circle_recombine_timer"), Db->CircleRecombineTimer); RegisterTable(TEXT("entity"), Db->Entity); - RegisterTable(TEXT("move_all_players_timer"), Db->MoveAllPlayersTimer); + RegisterTable(TEXT("food"), Db->Food); + RegisterTable(TEXT("player"), Db->Player); } FContextBase::FContextBase(UDbConnection* InConn) @@ -128,6 +115,7 @@ FContextBase::FContextBase(UDbConnection* InConn) Db = InConn->Db; Reducers = InConn->Reducers; SetReducerFlags = InConn->SetReducerFlags; + Procedures = InConn->Procedures; Conn = InConn; } bool FContextBase::IsActive() const @@ -155,35 +143,19 @@ void URemoteTables::Initialize() { /** Creating tables */ - ConsumeEntityTimer = NewObject(this); Circle = NewObject(this); - Food = NewObject(this); - LoggedOutCircle = NewObject(this); - SpawnFoodTimer = NewObject(this); Config = NewObject(this); - Player = NewObject(this); - LoggedOutEntity = NewObject(this); - LoggedOutPlayer = NewObject(this); - CircleDecayTimer = NewObject(this); - CircleRecombineTimer = NewObject(this); Entity = NewObject(this); - MoveAllPlayersTimer = NewObject(this); + Food = NewObject(this); + Player = NewObject(this); /**/ /** Initialization */ - ConsumeEntityTimer->PostInitialize(); Circle->PostInitialize(); - Food->PostInitialize(); - LoggedOutCircle->PostInitialize(); - SpawnFoodTimer->PostInitialize(); Config->PostInitialize(); - Player->PostInitialize(); - LoggedOutEntity->PostInitialize(); - LoggedOutPlayer->PostInitialize(); - CircleDecayTimer->PostInitialize(); - CircleRecombineTimer->PostInitialize(); Entity->PostInitialize(); - MoveAllPlayersTimer->PostInitialize(); + Food->PostInitialize(); + Player->PostInitialize(); /**/ } @@ -265,6 +237,21 @@ bool URemoteReducers::InvokeCircleDecay(const FReducerEventContext& Context, con 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) @@ -294,6 +281,21 @@ bool URemoteReducers::InvokeCircleRecombine(const FReducerEventContext& Context, 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) @@ -323,6 +325,21 @@ bool URemoteReducers::InvokeConnect(const FReducerEventContext& Context, const U 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) @@ -352,6 +369,21 @@ bool URemoteReducers::InvokeConsumeEntity(const FReducerEventContext& Context, c 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) @@ -381,6 +413,21 @@ bool URemoteReducers::InvokeDisconnect(const FReducerEventContext& Context, cons 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) @@ -410,6 +457,21 @@ bool URemoteReducers::InvokeEnterGame(const FReducerEventContext& Context, const return true; } +bool URemoteReducers::InvokeEnterGameWithArgs(const FReducerEventContext& Context, const FEnterGameArgs& Args) +{ + if (!OnEnterGame.IsBound()) + { + if (InternalOnUnhandledReducerError.IsBound()) + { + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for EnterGame")); + } + return false; + } + + OnEnterGame.Broadcast(Context, Args.Name); + return true; +} + void URemoteReducers::MoveAllPlayers(const FMoveAllPlayersTimerType& Timer) { if (!Conn) @@ -439,6 +501,21 @@ bool URemoteReducers::InvokeMoveAllPlayers(const FReducerEventContext& Context, 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) @@ -468,6 +545,21 @@ bool URemoteReducers::InvokePlayerSplit(const FReducerEventContext& Context, con return true; } +bool URemoteReducers::InvokePlayerSplitWithArgs(const FReducerEventContext& Context, const FPlayerSplitArgs& Args) +{ + if (!OnPlayerSplit.IsBound()) + { + if (InternalOnUnhandledReducerError.IsBound()) + { + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for PlayerSplit")); + } + return false; + } + + OnPlayerSplit.Broadcast(Context); + return true; +} + void URemoteReducers::Respawn() { if (!Conn) @@ -497,6 +589,21 @@ bool URemoteReducers::InvokeRespawn(const FReducerEventContext& Context, const U return true; } +bool URemoteReducers::InvokeRespawnWithArgs(const FReducerEventContext& Context, const FRespawnArgs& Args) +{ + if (!OnRespawn.IsBound()) + { + if (InternalOnUnhandledReducerError.IsBound()) + { + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for Respawn")); + } + return false; + } + + OnRespawn.Broadcast(Context); + return true; +} + void URemoteReducers::SpawnFood(const FSpawnFoodTimerType& Timer) { if (!Conn) @@ -526,6 +633,21 @@ bool URemoteReducers::InvokeSpawnFood(const FReducerEventContext& Context, const 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) @@ -555,6 +677,21 @@ bool URemoteReducers::InvokeSuicide(const FReducerEventContext& Context, const U return true; } +bool URemoteReducers::InvokeSuicideWithArgs(const FReducerEventContext& Context, const FSuicideArgs& Args) +{ + if (!OnSuicide.IsBound()) + { + if (InternalOnUnhandledReducerError.IsBound()) + { + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for Suicide")); + } + return false; + } + + OnSuicide.Broadcast(Context); + return true; +} + void URemoteReducers::UpdatePlayerInput(const FDbVector2Type& Direction) { if (!Conn) @@ -584,6 +721,21 @@ bool URemoteReducers::InvokeUpdatePlayerInput(const FReducerEventContext& Contex return true; } +bool URemoteReducers::InvokeUpdatePlayerInputWithArgs(const FReducerEventContext& Context, const FUpdatePlayerInputArgs& Args) +{ + if (!OnUpdatePlayerInput.IsBound()) + { + if (InternalOnUnhandledReducerError.IsBound()) + { + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for UpdatePlayerInput")); + } + return false; + } + + OnUpdatePlayerInput.Broadcast(Context, Args.Direction); + return true; +} + void UDbConnection::PostInitProperties() { Super::PostInitProperties(); @@ -593,6 +745,12 @@ void UDbConnection::PostInitProperties() { Reducers->InternalOnUnhandledReducerError.AddDynamic(this, &UDbConnection::OnUnhandledReducerErrorHandler); } + + // Connect OnUnhandledProcedureError to Procedures.InternalOnUnhandledProcedureError + if (Procedures) + { + Procedures->InternalOnUnhandledProcedureError.AddDynamic(this, &UDbConnection::OnUnhandledProcedureErrorHandler); + } } UFUNCTION() @@ -604,6 +762,15 @@ void UDbConnection::OnUnhandledReducerErrorHandler(const FReducerEventContext& C } } +UFUNCTION() +void UDbConnection::OnUnhandledProcedureErrorHandler(const FProcedureEventContext& Context, const FString& Error) +{ + if (OnUnhandledProcedureError.IsBound()) + { + OnUnhandledProcedureError.Broadcast(Context, Error); + } +} + void UDbConnection::ReducerEvent(const FReducerEvent& Event) { if (!Reducers) { return; } @@ -626,92 +793,73 @@ void UDbConnection::ReducerEvent(const FReducerEvent& Event) if (ReducerName == TEXT("circle_decay")) { FCircleDecayArgs Args = ReducerEvent.Reducer.GetAsCircleDecay(); - UCircleDecayReducer* Reducer = NewObject(); - Reducer->Timer = Args.Timer; - Reducers->InvokeCircleDecay(Context, Reducer); + Reducers->InvokeCircleDecayWithArgs(Context, Args); return; } if (ReducerName == TEXT("circle_recombine")) { FCircleRecombineArgs Args = ReducerEvent.Reducer.GetAsCircleRecombine(); - UCircleRecombineReducer* Reducer = NewObject(); - Reducer->Timer = Args.Timer; - Reducers->InvokeCircleRecombine(Context, Reducer); + Reducers->InvokeCircleRecombineWithArgs(Context, Args); return; } if (ReducerName == TEXT("connect")) { FConnectArgs Args = ReducerEvent.Reducer.GetAsConnect(); - UConnectReducer* Reducer = NewObject(); - Reducers->InvokeConnect(Context, Reducer); + Reducers->InvokeConnectWithArgs(Context, Args); return; } if (ReducerName == TEXT("consume_entity")) { FConsumeEntityArgs Args = ReducerEvent.Reducer.GetAsConsumeEntity(); - UConsumeEntityReducer* Reducer = NewObject(); - Reducer->Request = Args.Request; - Reducers->InvokeConsumeEntity(Context, Reducer); + Reducers->InvokeConsumeEntityWithArgs(Context, Args); return; } if (ReducerName == TEXT("disconnect")) { FDisconnectArgs Args = ReducerEvent.Reducer.GetAsDisconnect(); - UDisconnectReducer* Reducer = NewObject(); - Reducers->InvokeDisconnect(Context, Reducer); + Reducers->InvokeDisconnectWithArgs(Context, Args); return; } if (ReducerName == TEXT("enter_game")) { FEnterGameArgs Args = ReducerEvent.Reducer.GetAsEnterGame(); - UEnterGameReducer* Reducer = NewObject(); - Reducer->Name = Args.Name; - Reducers->InvokeEnterGame(Context, Reducer); + Reducers->InvokeEnterGameWithArgs(Context, Args); return; } if (ReducerName == TEXT("move_all_players")) { FMoveAllPlayersArgs Args = ReducerEvent.Reducer.GetAsMoveAllPlayers(); - UMoveAllPlayersReducer* Reducer = NewObject(); - Reducer->Timer = Args.Timer; - Reducers->InvokeMoveAllPlayers(Context, Reducer); + Reducers->InvokeMoveAllPlayersWithArgs(Context, Args); return; } if (ReducerName == TEXT("player_split")) { FPlayerSplitArgs Args = ReducerEvent.Reducer.GetAsPlayerSplit(); - UPlayerSplitReducer* Reducer = NewObject(); - Reducers->InvokePlayerSplit(Context, Reducer); + Reducers->InvokePlayerSplitWithArgs(Context, Args); return; } if (ReducerName == TEXT("respawn")) { FRespawnArgs Args = ReducerEvent.Reducer.GetAsRespawn(); - URespawnReducer* Reducer = NewObject(); - Reducers->InvokeRespawn(Context, Reducer); + Reducers->InvokeRespawnWithArgs(Context, Args); return; } if (ReducerName == TEXT("spawn_food")) { FSpawnFoodArgs Args = ReducerEvent.Reducer.GetAsSpawnFood(); - USpawnFoodReducer* Reducer = NewObject(); - Reducer->Timer = Args.Timer; - Reducers->InvokeSpawnFood(Context, Reducer); + Reducers->InvokeSpawnFoodWithArgs(Context, Args); return; } if (ReducerName == TEXT("suicide")) { FSuicideArgs Args = ReducerEvent.Reducer.GetAsSuicide(); - USuicideReducer* Reducer = NewObject(); - Reducers->InvokeSuicide(Context, Reducer); + Reducers->InvokeSuicideWithArgs(Context, Args); return; } if (ReducerName == TEXT("update_player_input")) { FUpdatePlayerInputArgs Args = ReducerEvent.Reducer.GetAsUpdatePlayerInput(); - UUpdatePlayerInputReducer* Reducer = NewObject(); - Reducer->Direction = Args.Direction; - Reducers->InvokeUpdatePlayerInput(Context, Reducer); + Reducers->InvokeUpdatePlayerInputWithArgs(Context, Args); return; } @@ -737,6 +885,22 @@ void UDbConnection::ReducerEventFailed(const FReducerEvent& Event, const FString } } +void UDbConnection::ProcedureEventFailed(const FProcedureEvent& Event, const FString ErrorMessage) +{ + if (!Procedures) { return; } + + FClientUnrealProcedureEvent ProcedureEvent; + ProcedureEvent.Status = FSpacetimeDBProcedureStatus::FromStatus(Event.Status); + ProcedureEvent.Timestamp = Event.Timestamp; + + FProcedureEventContext Context(this, ProcedureEvent); + + if (Procedures->InternalOnUnhandledProcedureError.IsBound()) + { + Procedures->InternalOnUnhandledProcedureError.Broadcast(Context, ErrorMessage); + } +} + UDbConnectionBuilder* UDbConnection::Builder() { return NewObject(); diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleDecayTimerTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleDecayTimerTable.g.cpp deleted file mode 100644 index 3f843a1028e..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleDecayTimerTable.g.cpp +++ /dev/null @@ -1,47 +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. - -#include "ModuleBindings/Tables/CircleDecayTimerTable.g.h" -#include "DBCache/UniqueIndex.h" -#include "DBCache/BTreeUniqueIndex.h" -#include "DBCache/ClientCache.h" -#include "DBCache/TableCache.h" - -void UCircleDecayTimerTable::PostInitialize() -{ - /** Client cache init and setting up indexes*/ - Data = MakeShared>(); - - TSharedPtr> CircleDecayTimerTable = Data->GetOrAdd(TableName); - CircleDecayTimerTable->AddUniqueConstraint("scheduled_id", [](const FCircleDecayTimerType& Row) -> const uint64& { - return Row.ScheduledId; }); - - ScheduledId = NewObject(this); - ScheduledId->SetCache(CircleDecayTimerTable); - - /***/ -} - -FTableAppliedDiff UCircleDecayTimerTable::Update(TArray> InsertsRef, TArray> DeletesRef) -{ - FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); - - Diff.DeriveUpdatesByPrimaryKey( - [](const FCircleDecayTimerType& Row) - { - return Row.ScheduledId; - } - ); - - return Diff; -} - -int32 UCircleDecayTimerTable::Count() const -{ - return GetRowCountFromTable(Data, TableName); -} - -TArray UCircleDecayTimerTable::Iter() const -{ - return GetAllRowsFromTable(Data, TableName); -} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleRecombineTimerTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleRecombineTimerTable.g.cpp deleted file mode 100644 index c79d81391bd..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleRecombineTimerTable.g.cpp +++ /dev/null @@ -1,47 +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. - -#include "ModuleBindings/Tables/CircleRecombineTimerTable.g.h" -#include "DBCache/UniqueIndex.h" -#include "DBCache/BTreeUniqueIndex.h" -#include "DBCache/ClientCache.h" -#include "DBCache/TableCache.h" - -void UCircleRecombineTimerTable::PostInitialize() -{ - /** Client cache init and setting up indexes*/ - Data = MakeShared>(); - - TSharedPtr> CircleRecombineTimerTable = Data->GetOrAdd(TableName); - CircleRecombineTimerTable->AddUniqueConstraint("scheduled_id", [](const FCircleRecombineTimerType& Row) -> const uint64& { - return Row.ScheduledId; }); - - ScheduledId = NewObject(this); - ScheduledId->SetCache(CircleRecombineTimerTable); - - /***/ -} - -FTableAppliedDiff UCircleRecombineTimerTable::Update(TArray> InsertsRef, TArray> DeletesRef) -{ - FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); - - Diff.DeriveUpdatesByPrimaryKey( - [](const FCircleRecombineTimerType& Row) - { - return Row.ScheduledId; - } - ); - - return Diff; -} - -int32 UCircleRecombineTimerTable::Count() const -{ - return GetRowCountFromTable(Data, TableName); -} - -TArray UCircleRecombineTimerTable::Iter() const -{ - return GetAllRowsFromTable(Data, TableName); -} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/ConsumeEntityTimerTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/ConsumeEntityTimerTable.g.cpp deleted file mode 100644 index 398c24bdbde..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/ConsumeEntityTimerTable.g.cpp +++ /dev/null @@ -1,47 +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. - -#include "ModuleBindings/Tables/ConsumeEntityTimerTable.g.h" -#include "DBCache/UniqueIndex.h" -#include "DBCache/BTreeUniqueIndex.h" -#include "DBCache/ClientCache.h" -#include "DBCache/TableCache.h" - -void UConsumeEntityTimerTable::PostInitialize() -{ - /** Client cache init and setting up indexes*/ - Data = MakeShared>(); - - TSharedPtr> ConsumeEntityTimerTable = Data->GetOrAdd(TableName); - ConsumeEntityTimerTable->AddUniqueConstraint("scheduled_id", [](const FConsumeEntityTimerType& Row) -> const uint64& { - return Row.ScheduledId; }); - - ScheduledId = NewObject(this); - ScheduledId->SetCache(ConsumeEntityTimerTable); - - /***/ -} - -FTableAppliedDiff UConsumeEntityTimerTable::Update(TArray> InsertsRef, TArray> DeletesRef) -{ - FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); - - Diff.DeriveUpdatesByPrimaryKey( - [](const FConsumeEntityTimerType& Row) - { - return Row.ScheduledId; - } - ); - - return Diff; -} - -int32 UConsumeEntityTimerTable::Count() const -{ - return GetRowCountFromTable(Data, TableName); -} - -TArray UConsumeEntityTimerTable::Iter() const -{ - return GetAllRowsFromTable(Data, TableName); -} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.cpp deleted file mode 100644 index ed8b6a847f2..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.cpp +++ /dev/null @@ -1,47 +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. - -#include "ModuleBindings/Tables/MoveAllPlayersTimerTable.g.h" -#include "DBCache/UniqueIndex.h" -#include "DBCache/BTreeUniqueIndex.h" -#include "DBCache/ClientCache.h" -#include "DBCache/TableCache.h" - -void UMoveAllPlayersTimerTable::PostInitialize() -{ - /** Client cache init and setting up indexes*/ - Data = MakeShared>(); - - TSharedPtr> MoveAllPlayersTimerTable = Data->GetOrAdd(TableName); - MoveAllPlayersTimerTable->AddUniqueConstraint("scheduled_id", [](const FMoveAllPlayersTimerType& Row) -> const uint64& { - return Row.ScheduledId; }); - - ScheduledId = NewObject(this); - ScheduledId->SetCache(MoveAllPlayersTimerTable); - - /***/ -} - -FTableAppliedDiff UMoveAllPlayersTimerTable::Update(TArray> InsertsRef, TArray> DeletesRef) -{ - FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); - - Diff.DeriveUpdatesByPrimaryKey( - [](const FMoveAllPlayersTimerType& Row) - { - return Row.ScheduledId; - } - ); - - return Diff; -} - -int32 UMoveAllPlayersTimerTable::Count() const -{ - return GetRowCountFromTable(Data, TableName); -} - -TArray UMoveAllPlayersTimerTable::Iter() const -{ - return GetAllRowsFromTable(Data, TableName); -} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/SpawnFoodTimerTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/SpawnFoodTimerTable.g.cpp deleted file mode 100644 index f7a36cff76b..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/SpawnFoodTimerTable.g.cpp +++ /dev/null @@ -1,47 +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. - -#include "ModuleBindings/Tables/SpawnFoodTimerTable.g.h" -#include "DBCache/UniqueIndex.h" -#include "DBCache/BTreeUniqueIndex.h" -#include "DBCache/ClientCache.h" -#include "DBCache/TableCache.h" - -void USpawnFoodTimerTable::PostInitialize() -{ - /** Client cache init and setting up indexes*/ - Data = MakeShared>(); - - TSharedPtr> SpawnFoodTimerTable = Data->GetOrAdd(TableName); - SpawnFoodTimerTable->AddUniqueConstraint("scheduled_id", [](const FSpawnFoodTimerType& Row) -> const uint64& { - return Row.ScheduledId; }); - - ScheduledId = NewObject(this); - ScheduledId->SetCache(SpawnFoodTimerTable); - - /***/ -} - -FTableAppliedDiff USpawnFoodTimerTable::Update(TArray> InsertsRef, TArray> DeletesRef) -{ - FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); - - Diff.DeriveUpdatesByPrimaryKey( - [](const FSpawnFoodTimerType& Row) - { - return Row.ScheduledId; - } - ); - - return Diff; -} - -int32 USpawnFoodTimerTable::Count() const -{ - return GetRowCountFromTable(Data, TableName); -} - -TArray USpawnFoodTimerTable::Iter() const -{ - return GetAllRowsFromTable(Data, TableName); -} 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 d44f9a01029..34baad8fa2d 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.6.0 (commit fa943010b614e8ec11eb04f8c56f12b466a1b814). +// This was generated using spacetimedb cli version 1.12.0 (commit 819069447d9034135872ce2bdc28722c4e5e46b6). #pragma once #include "CoreMinimal.h" @@ -38,23 +38,16 @@ class UDbConnection; class URemoteTables; class URemoteReducers; +class URemoteProcedures; class USubscriptionBuilder; class USubscriptionHandle; /** Forward declaration for tables */ class UCircleTable; -class UCircleDecayTimerTable; -class UCircleRecombineTimerTable; class UConfigTable; -class UConsumeEntityTimerTable; class UEntityTable; class UFoodTable; -class UCircleTable; -class UEntityTable; -class UPlayerTable; -class UMoveAllPlayersTimerTable; class UPlayerTable; -class USpawnFoodTimerTable; /***/ // Delegates using the generated connection type. These wrap the base @@ -79,7 +72,7 @@ struct CLIENT_UNREAL_API FContextBase { GENERATED_BODY() - FContextBase() : Db(nullptr), Reducers(nullptr), SetReducerFlags(nullptr), Conn(nullptr) {}; + FContextBase() : Db(nullptr), Reducers(nullptr), SetReducerFlags(nullptr), Procedures(nullptr), Conn(nullptr) {}; FContextBase(UDbConnection* InConn); UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") @@ -91,6 +84,9 @@ struct CLIENT_UNREAL_API FContextBase UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") USetReducerFlags* SetReducerFlags; + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + URemoteProcedures* Procedures; + bool IsActive() const; void Disconnect(); bool TryGetIdentity(FSpacetimeDBIdentity& OutIdentity) const; @@ -118,6 +114,8 @@ class CLIENT_UNREAL_API UContextBaseBpLib : public UBlueprintFunctionLibrary UFUNCTION(BlueprintPure, Category="SpacetimeDB") static USetReducerFlags* GetSetReducerFlags(const FContextBase& Ctx) { return Ctx.SetReducerFlags; } + static URemoteProcedures* GetProcedures(const FContextBase& Ctx) { return Ctx.Procedures; } + UFUNCTION(BlueprintPure, Category="SpacetimeDB") static bool IsActive(const FContextBase& Ctx) { return Ctx.IsActive(); } }; @@ -590,6 +588,44 @@ struct CLIENT_UNREAL_API FClientUnrealReducerEvent } }; +// No procedures defined in this module. +/** Metadata describing a procedure run. */ +USTRUCT(BlueprintType) +struct CLIENT_UNREAL_API FClientUnrealProcedureEvent +{ + GENERATED_BODY() + + /** Timestamp for when the procedure executed */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBTimestamp Timestamp; + + /** Result status of the procedure */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBProcedureStatus Status; + + /** Identity that initiated the call */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBTimeDuration TotalHostExecutionDuration; + + FClientUnrealProcedureEvent() { + } + FClientUnrealProcedureEvent(FProcedureEvent Event) { + Timestamp = Event.Timestamp; + Status = FSpacetimeDBProcedureStatus::FromStatus(Event.Status); + TotalHostExecutionDuration = Event.TotalHostExecutionDuration; + } + FORCEINLINE bool operator==(const FClientUnrealProcedureEvent& Other) const + { + return Status == Other.Status && Timestamp == Other.Timestamp && + TotalHostExecutionDuration == Other.TotalHostExecutionDuration; + } + + FORCEINLINE bool operator!=(const FClientUnrealProcedureEvent& Other) const + { + return !(*this == Other); + } +}; + /** Represents event with variant message data. */ USTRUCT(BlueprintType) struct CLIENT_UNREAL_API FClientUnrealEvent @@ -838,6 +874,18 @@ struct CLIENT_UNREAL_API FReducerEventContext : public FContextBase FClientUnrealReducerEvent Event; }; +USTRUCT(BlueprintType) +struct CLIENT_UNREAL_API FProcedureEventContext : public FContextBase +{ + GENERATED_BODY() + + FProcedureEventContext() = default; + FProcedureEventContext(UDbConnection* InConn, FClientUnrealProcedureEvent InEvent) : FContextBase(InConn), Event(InEvent) {} + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FClientUnrealProcedureEvent Event; +}; + USTRUCT(BlueprintType) struct CLIENT_UNREAL_API FErrorContext : public FContextBase { @@ -911,44 +959,20 @@ class CLIENT_UNREAL_API URemoteTables : public UObject public: void Initialize(); - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UConsumeEntityTimerTable* ConsumeEntityTimer; - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") UCircleTable* Circle; - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UFoodTable* Food; - - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UCircleTable* LoggedOutCircle; - - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - USpawnFoodTimerTable* SpawnFoodTimer; - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") UConfigTable* Config; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPlayerTable* Player; - - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UEntityTable* LoggedOutEntity; - - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPlayerTable* LoggedOutPlayer; - - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UCircleDecayTimerTable* CircleDecayTimer; - - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UCircleRecombineTimerTable* CircleRecombineTimer; + UEntityTable* Entity; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UEntityTable* Entity; + UFoodTable* Food; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UMoveAllPlayersTimerTable* MoveAllPlayersTimer; + UPlayerTable* Player; }; @@ -972,6 +996,7 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject 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, @@ -985,6 +1010,7 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject 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, @@ -997,6 +1023,7 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject void Connect(); bool InvokeConnect(const FReducerEventContext& Context, const UConnectReducer* Args); + bool InvokeConnectWithArgs(const FReducerEventContext& Context, const FConnectArgs& Args); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( FConsumeEntityHandler, @@ -1010,6 +1037,7 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject 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, @@ -1022,6 +1050,7 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject void Disconnect(); bool InvokeDisconnect(const FReducerEventContext& Context, const UDisconnectReducer* Args); + bool InvokeDisconnectWithArgs(const FReducerEventContext& Context, const FDisconnectArgs& Args); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( FEnterGameHandler, @@ -1035,6 +1064,7 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject void EnterGame(const FString& Name); bool InvokeEnterGame(const FReducerEventContext& Context, const UEnterGameReducer* Args); + bool InvokeEnterGameWithArgs(const FReducerEventContext& Context, const FEnterGameArgs& Args); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( FMoveAllPlayersHandler, @@ -1048,6 +1078,7 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject 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, @@ -1060,6 +1091,7 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject void PlayerSplit(); bool InvokePlayerSplit(const FReducerEventContext& Context, const UPlayerSplitReducer* Args); + bool InvokePlayerSplitWithArgs(const FReducerEventContext& Context, const FPlayerSplitArgs& Args); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( FRespawnHandler, @@ -1072,6 +1104,7 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject void Respawn(); bool InvokeRespawn(const FReducerEventContext& Context, const URespawnReducer* Args); + bool InvokeRespawnWithArgs(const FReducerEventContext& Context, const FRespawnArgs& Args); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( FSpawnFoodHandler, @@ -1085,6 +1118,7 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject 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, @@ -1097,6 +1131,7 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject void Suicide(); bool InvokeSuicide(const FReducerEventContext& Context, const USuicideReducer* Args); + bool InvokeSuicideWithArgs(const FReducerEventContext& Context, const FSuicideArgs& Args); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( FUpdatePlayerInputHandler, @@ -1110,6 +1145,7 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject void UpdatePlayerInput(const FDbVector2Type& Direction); bool InvokeUpdatePlayerInput(const FReducerEventContext& Context, const UUpdatePlayerInputReducer* Args); + bool InvokeUpdatePlayerInputWithArgs(const FReducerEventContext& Context, const FUpdatePlayerInputArgs& Args); // Internal error handling DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FInternalOnUnhandledReducerError, const FReducerEventContext&, Context, const FString&, Error); @@ -1126,6 +1162,26 @@ class CLIENT_UNREAL_API URemoteReducers : public UObject USetReducerFlags* SetCallReducerFlags; }; +// RemoteProcedures class +UCLASS(BlueprintType) +class CLIENT_UNREAL_API URemoteProcedures : public UObject +{ + GENERATED_BODY() + +public: + + // Internal error handling + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FInternalOnUnhandledProcedureError, const FProcedureEventContext&, Context, const FString&, Error); + FInternalOnUnhandledProcedureError InternalOnUnhandledProcedureError; + +private: + + friend UDbConnection; + + UPROPERTY() + class UDbConnection* Conn; +}; + // SubscriptionBuilder class UCLASS(BlueprintType) class CLIENT_UNREAL_API USubscriptionBuilder : public USubscriptionBuilderBase @@ -1241,6 +1297,9 @@ class CLIENT_UNREAL_API UDbConnection : public UDbConnectionBase UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") USetReducerFlags* SetReducerFlags; + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + URemoteProcedures* Procedures; + // Delegates that allow users to bind with the concrete connection type. FOnConnectDelegate OnConnectDelegate; FOnDisconnectDelegate OnDisconnectDelegate; @@ -1257,10 +1316,15 @@ class CLIENT_UNREAL_API UDbConnection : public UDbConnectionBase UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") FOnUnhandledReducerError OnUnhandledReducerError; + // Error handling + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnUnhandledProcedureError, const FProcedureEventContext&, Context, const FString&, Error); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FOnUnhandledProcedureError OnUnhandledProcedureError; + protected: - // Hook up error handling to reducers + // Hook up error handling to reducers and procedures virtual void PostInitProperties() override; UFUNCTION() @@ -1271,6 +1335,9 @@ class CLIENT_UNREAL_API UDbConnection : public UDbConnectionBase UFUNCTION() void OnUnhandledReducerErrorHandler(const FReducerEventContext& Context, const FString& Error); + UFUNCTION() + void OnUnhandledProcedureErrorHandler(const FProcedureEventContext& Context, const FString& Error); + // Override the DbConnectionBase methods to handle updates and events virtual void DbUpdate(const FDatabaseUpdateType& Update, const FSpacetimeDBEvent& Event) override; @@ -1279,5 +1346,7 @@ class CLIENT_UNREAL_API UDbConnection : public UDbConnectionBase // Override the reducer event failed handler virtual void ReducerEventFailed(const FReducerEvent& Event, const FString ErrorMessage) override; + // Override the procedure event failed handler + virtual void ProcedureEventFailed(const FProcedureEvent& Event, const FString ErrorMessage) override; }; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleDecayTimerTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleDecayTimerTable.g.h deleted file mode 100644 index 67734c5a801..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleDecayTimerTable.g.h +++ /dev/null @@ -1,104 +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 "Types/Builtins.h" -#include "ModuleBindings/Types/CircleDecayTimerType.g.h" -#include "Tables/RemoteTable.h" -#include "DBCache/WithBsatn.h" -#include "DBCache/TableHandle.h" -#include "DBCache/TableCache.h" -#include "CircleDecayTimerTable.g.generated.h" - -UCLASS(Blueprintable) -class CLIENT_UNREAL_API UCircleDecayTimerScheduledIdUniqueIndex : public UObject -{ - GENERATED_BODY() - -private: - // Declare an instance of your templated helper. - // It's private because the UObject wrapper will expose its functionality. - FUniqueIndexHelper> ScheduledIdIndexHelper; - -public: - UCircleDecayTimerScheduledIdUniqueIndex() - // Initialize the helper with the specific unique index name - : ScheduledIdIndexHelper("scheduled_id") { - } - - /** - * Finds a CircleDecayTimer by their unique scheduledid. - * @param Key The scheduledid to search for. - * @return The found FCircleDecayTimerType, or a default-constructed FCircleDecayTimerType if not found. - */ - // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible - FCircleDecayTimerType Find(uint64 Key) - { - // Simply delegate the call to the internal helper - return ScheduledIdIndexHelper.FindUniqueIndex(Key); - } - - // A public setter to provide the cache to the helper after construction - // This is a common pattern when the cache might be created or provided by another system. - void SetCache(TSharedPtr> InCircleDecayTimerCache) - { - ScheduledIdIndexHelper.Cache = InCircleDecayTimerCache; - } -}; -/***/ - -UCLASS(BlueprintType) -class CLIENT_UNREAL_API UCircleDecayTimerTable : public URemoteTable -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly) - UCircleDecayTimerScheduledIdUniqueIndex* ScheduledId; - - void PostInitialize(); - - /** Update function for circle_decay_timer table*/ - FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); - - /** Number of subscribed rows currently in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - int32 Count() const; - - /** Return all subscribed rows in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - TArray Iter() const; - - // Table Events - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnCircleDecayTimerInsert, - const FEventContext&, Context, - const FCircleDecayTimerType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( - FOnCircleDecayTimerUpdate, - const FEventContext&, Context, - const FCircleDecayTimerType&, OldRow, - const FCircleDecayTimerType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnCircleDecayTimerDelete, - const FEventContext&, Context, - const FCircleDecayTimerType&, DeletedRow); - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnCircleDecayTimerInsert OnInsert; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnCircleDecayTimerUpdate OnUpdate; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnCircleDecayTimerDelete OnDelete; - -private: - const FString TableName = TEXT("circle_decay_timer"); - - TSharedPtr> Data; -}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleRecombineTimerTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleRecombineTimerTable.g.h deleted file mode 100644 index fa2584ed493..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleRecombineTimerTable.g.h +++ /dev/null @@ -1,104 +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 "Types/Builtins.h" -#include "ModuleBindings/Types/CircleRecombineTimerType.g.h" -#include "Tables/RemoteTable.h" -#include "DBCache/WithBsatn.h" -#include "DBCache/TableHandle.h" -#include "DBCache/TableCache.h" -#include "CircleRecombineTimerTable.g.generated.h" - -UCLASS(Blueprintable) -class CLIENT_UNREAL_API UCircleRecombineTimerScheduledIdUniqueIndex : public UObject -{ - GENERATED_BODY() - -private: - // Declare an instance of your templated helper. - // It's private because the UObject wrapper will expose its functionality. - FUniqueIndexHelper> ScheduledIdIndexHelper; - -public: - UCircleRecombineTimerScheduledIdUniqueIndex() - // Initialize the helper with the specific unique index name - : ScheduledIdIndexHelper("scheduled_id") { - } - - /** - * Finds a CircleRecombineTimer by their unique scheduledid. - * @param Key The scheduledid to search for. - * @return The found FCircleRecombineTimerType, or a default-constructed FCircleRecombineTimerType if not found. - */ - // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible - FCircleRecombineTimerType Find(uint64 Key) - { - // Simply delegate the call to the internal helper - return ScheduledIdIndexHelper.FindUniqueIndex(Key); - } - - // A public setter to provide the cache to the helper after construction - // This is a common pattern when the cache might be created or provided by another system. - void SetCache(TSharedPtr> InCircleRecombineTimerCache) - { - ScheduledIdIndexHelper.Cache = InCircleRecombineTimerCache; - } -}; -/***/ - -UCLASS(BlueprintType) -class CLIENT_UNREAL_API UCircleRecombineTimerTable : public URemoteTable -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly) - UCircleRecombineTimerScheduledIdUniqueIndex* ScheduledId; - - void PostInitialize(); - - /** Update function for circle_recombine_timer table*/ - FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); - - /** Number of subscribed rows currently in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - int32 Count() const; - - /** Return all subscribed rows in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - TArray Iter() const; - - // Table Events - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnCircleRecombineTimerInsert, - const FEventContext&, Context, - const FCircleRecombineTimerType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( - FOnCircleRecombineTimerUpdate, - const FEventContext&, Context, - const FCircleRecombineTimerType&, OldRow, - const FCircleRecombineTimerType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnCircleRecombineTimerDelete, - const FEventContext&, Context, - const FCircleRecombineTimerType&, DeletedRow); - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnCircleRecombineTimerInsert OnInsert; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnCircleRecombineTimerUpdate OnUpdate; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnCircleRecombineTimerDelete OnDelete; - -private: - const FString TableName = TEXT("circle_recombine_timer"); - - TSharedPtr> Data; -}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleTable.g.h index 3bb3f394a9b..e92587259a2 100644 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleTable.g.h +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleTable.g.h @@ -97,7 +97,7 @@ class CLIENT_UNREAL_API UCircleTable : public URemoteTable void PostInitialize(); - /** Update function for logged_out_circle table*/ + /** Update function for circle table*/ FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); /** Number of subscribed rows currently in the cache */ @@ -135,7 +135,7 @@ class CLIENT_UNREAL_API UCircleTable : public URemoteTable FOnCircleDelete OnDelete; private: - const FString TableName = TEXT("logged_out_circle"); + const FString TableName = TEXT("circle"); TSharedPtr> Data; }; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/ConsumeEntityTimerTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/ConsumeEntityTimerTable.g.h deleted file mode 100644 index f07cca059d6..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/ConsumeEntityTimerTable.g.h +++ /dev/null @@ -1,104 +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 "Types/Builtins.h" -#include "ModuleBindings/Types/ConsumeEntityTimerType.g.h" -#include "Tables/RemoteTable.h" -#include "DBCache/WithBsatn.h" -#include "DBCache/TableHandle.h" -#include "DBCache/TableCache.h" -#include "ConsumeEntityTimerTable.g.generated.h" - -UCLASS(Blueprintable) -class CLIENT_UNREAL_API UConsumeEntityTimerScheduledIdUniqueIndex : public UObject -{ - GENERATED_BODY() - -private: - // Declare an instance of your templated helper. - // It's private because the UObject wrapper will expose its functionality. - FUniqueIndexHelper> ScheduledIdIndexHelper; - -public: - UConsumeEntityTimerScheduledIdUniqueIndex() - // Initialize the helper with the specific unique index name - : ScheduledIdIndexHelper("scheduled_id") { - } - - /** - * Finds a ConsumeEntityTimer by their unique scheduledid. - * @param Key The scheduledid to search for. - * @return The found FConsumeEntityTimerType, or a default-constructed FConsumeEntityTimerType if not found. - */ - // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible - FConsumeEntityTimerType Find(uint64 Key) - { - // Simply delegate the call to the internal helper - return ScheduledIdIndexHelper.FindUniqueIndex(Key); - } - - // A public setter to provide the cache to the helper after construction - // This is a common pattern when the cache might be created or provided by another system. - void SetCache(TSharedPtr> InConsumeEntityTimerCache) - { - ScheduledIdIndexHelper.Cache = InConsumeEntityTimerCache; - } -}; -/***/ - -UCLASS(BlueprintType) -class CLIENT_UNREAL_API UConsumeEntityTimerTable : public URemoteTable -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly) - UConsumeEntityTimerScheduledIdUniqueIndex* ScheduledId; - - void PostInitialize(); - - /** Update function for consume_entity_timer table*/ - FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); - - /** Number of subscribed rows currently in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - int32 Count() const; - - /** Return all subscribed rows in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - TArray Iter() const; - - // Table Events - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnConsumeEntityTimerInsert, - const FEventContext&, Context, - const FConsumeEntityTimerType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( - FOnConsumeEntityTimerUpdate, - const FEventContext&, Context, - const FConsumeEntityTimerType&, OldRow, - const FConsumeEntityTimerType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnConsumeEntityTimerDelete, - const FEventContext&, Context, - const FConsumeEntityTimerType&, DeletedRow); - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnConsumeEntityTimerInsert OnInsert; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnConsumeEntityTimerUpdate OnUpdate; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnConsumeEntityTimerDelete OnDelete; - -private: - const FString TableName = TEXT("consume_entity_timer"); - - TSharedPtr> Data; -}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.h deleted file mode 100644 index 5e81ed977ff..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.h +++ /dev/null @@ -1,104 +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 "Types/Builtins.h" -#include "ModuleBindings/Types/MoveAllPlayersTimerType.g.h" -#include "Tables/RemoteTable.h" -#include "DBCache/WithBsatn.h" -#include "DBCache/TableHandle.h" -#include "DBCache/TableCache.h" -#include "MoveAllPlayersTimerTable.g.generated.h" - -UCLASS(Blueprintable) -class CLIENT_UNREAL_API UMoveAllPlayersTimerScheduledIdUniqueIndex : public UObject -{ - GENERATED_BODY() - -private: - // Declare an instance of your templated helper. - // It's private because the UObject wrapper will expose its functionality. - FUniqueIndexHelper> ScheduledIdIndexHelper; - -public: - UMoveAllPlayersTimerScheduledIdUniqueIndex() - // Initialize the helper with the specific unique index name - : ScheduledIdIndexHelper("scheduled_id") { - } - - /** - * Finds a MoveAllPlayersTimer by their unique scheduledid. - * @param Key The scheduledid to search for. - * @return The found FMoveAllPlayersTimerType, or a default-constructed FMoveAllPlayersTimerType if not found. - */ - // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible - FMoveAllPlayersTimerType Find(uint64 Key) - { - // Simply delegate the call to the internal helper - return ScheduledIdIndexHelper.FindUniqueIndex(Key); - } - - // A public setter to provide the cache to the helper after construction - // This is a common pattern when the cache might be created or provided by another system. - void SetCache(TSharedPtr> InMoveAllPlayersTimerCache) - { - ScheduledIdIndexHelper.Cache = InMoveAllPlayersTimerCache; - } -}; -/***/ - -UCLASS(BlueprintType) -class CLIENT_UNREAL_API UMoveAllPlayersTimerTable : public URemoteTable -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly) - UMoveAllPlayersTimerScheduledIdUniqueIndex* ScheduledId; - - void PostInitialize(); - - /** Update function for move_all_players_timer table*/ - FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); - - /** Number of subscribed rows currently in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - int32 Count() const; - - /** Return all subscribed rows in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - TArray Iter() const; - - // Table Events - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnMoveAllPlayersTimerInsert, - const FEventContext&, Context, - const FMoveAllPlayersTimerType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( - FOnMoveAllPlayersTimerUpdate, - const FEventContext&, Context, - const FMoveAllPlayersTimerType&, OldRow, - const FMoveAllPlayersTimerType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnMoveAllPlayersTimerDelete, - const FEventContext&, Context, - const FMoveAllPlayersTimerType&, DeletedRow); - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnMoveAllPlayersTimerInsert OnInsert; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnMoveAllPlayersTimerUpdate OnUpdate; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnMoveAllPlayersTimerDelete OnDelete; - -private: - const FString TableName = TEXT("move_all_players_timer"); - - TSharedPtr> Data; -}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/PlayerTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/PlayerTable.g.h index 9e8734b5c6e..fd13ef2a07a 100644 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/PlayerTable.g.h +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/PlayerTable.g.h @@ -100,7 +100,7 @@ class CLIENT_UNREAL_API UPlayerTable : public URemoteTable void PostInitialize(); - /** Update function for logged_out_player table*/ + /** Update function for player table*/ FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); /** Number of subscribed rows currently in the cache */ @@ -138,7 +138,7 @@ class CLIENT_UNREAL_API UPlayerTable : public URemoteTable FOnPlayerDelete OnDelete; private: - const FString TableName = TEXT("logged_out_player"); + const FString TableName = TEXT("player"); TSharedPtr> Data; }; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/SpawnFoodTimerTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/SpawnFoodTimerTable.g.h deleted file mode 100644 index 362243f28fa..00000000000 --- a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/SpawnFoodTimerTable.g.h +++ /dev/null @@ -1,104 +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 "Types/Builtins.h" -#include "ModuleBindings/Types/SpawnFoodTimerType.g.h" -#include "Tables/RemoteTable.h" -#include "DBCache/WithBsatn.h" -#include "DBCache/TableHandle.h" -#include "DBCache/TableCache.h" -#include "SpawnFoodTimerTable.g.generated.h" - -UCLASS(Blueprintable) -class CLIENT_UNREAL_API USpawnFoodTimerScheduledIdUniqueIndex : public UObject -{ - GENERATED_BODY() - -private: - // Declare an instance of your templated helper. - // It's private because the UObject wrapper will expose its functionality. - FUniqueIndexHelper> ScheduledIdIndexHelper; - -public: - USpawnFoodTimerScheduledIdUniqueIndex() - // Initialize the helper with the specific unique index name - : ScheduledIdIndexHelper("scheduled_id") { - } - - /** - * Finds a SpawnFoodTimer by their unique scheduledid. - * @param Key The scheduledid to search for. - * @return The found FSpawnFoodTimerType, or a default-constructed FSpawnFoodTimerType if not found. - */ - // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible - FSpawnFoodTimerType Find(uint64 Key) - { - // Simply delegate the call to the internal helper - return ScheduledIdIndexHelper.FindUniqueIndex(Key); - } - - // A public setter to provide the cache to the helper after construction - // This is a common pattern when the cache might be created or provided by another system. - void SetCache(TSharedPtr> InSpawnFoodTimerCache) - { - ScheduledIdIndexHelper.Cache = InSpawnFoodTimerCache; - } -}; -/***/ - -UCLASS(BlueprintType) -class CLIENT_UNREAL_API USpawnFoodTimerTable : public URemoteTable -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly) - USpawnFoodTimerScheduledIdUniqueIndex* ScheduledId; - - void PostInitialize(); - - /** Update function for spawn_food_timer table*/ - FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); - - /** Number of subscribed rows currently in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - int32 Count() const; - - /** Return all subscribed rows in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - TArray Iter() const; - - // Table Events - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnSpawnFoodTimerInsert, - const FEventContext&, Context, - const FSpawnFoodTimerType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( - FOnSpawnFoodTimerUpdate, - const FEventContext&, Context, - const FSpawnFoodTimerType&, OldRow, - const FSpawnFoodTimerType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnSpawnFoodTimerDelete, - const FEventContext&, Context, - const FSpawnFoodTimerType&, DeletedRow); - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnSpawnFoodTimerInsert OnInsert; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnSpawnFoodTimerUpdate OnUpdate; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnSpawnFoodTimerDelete OnDelete; - -private: - const FString TableName = TEXT("spawn_food_timer"); - - TSharedPtr> Data; -}; From 165fd71779c1de99c33a6e4710b2544e7c4e3417 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Tue, 3 Feb 2026 20:29:37 -0800 Subject: [PATCH 09/18] Regenerated module bindings for Unity Blackholio --- .../Scripts/autogen/SpacetimeDBClient.g.cs | 18 +---- .../autogen/Tables/CircleDecayTimer.g.cs | 61 -------------- .../autogen/Tables/CircleDecayTimer.g.cs.meta | 11 --- .../autogen/Tables/CircleRecombineTimer.g.cs | 63 --------------- .../Tables/CircleRecombineTimer.g.cs.meta | 11 --- .../autogen/Tables/ConsumeEntityTimer.g.cs | 65 --------------- .../Tables/ConsumeEntityTimer.g.cs.meta | 11 --- .../autogen/Tables/LoggedOutCircle.g.cs | 79 ------------------- .../autogen/Tables/LoggedOutCircle.g.cs.meta | 11 --- .../autogen/Tables/LoggedOutEntity.g.cs | 63 --------------- .../autogen/Tables/LoggedOutEntity.g.cs.meta | 11 --- .../autogen/Tables/LoggedOutPlayer.g.cs | 75 ------------------ .../autogen/Tables/LoggedOutPlayer.g.cs.meta | 11 --- .../autogen/Tables/MoveAllPlayersTimer.g.cs | 61 -------------- .../Tables/MoveAllPlayersTimer.g.cs.meta | 11 --- .../autogen/Tables/SpawnFoodTimer.g.cs | 61 -------------- .../autogen/Tables/SpawnFoodTimer.g.cs.meta | 11 --- 17 files changed, 1 insertion(+), 633 deletions(-) delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleDecayTimer.g.cs delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleDecayTimer.g.cs.meta delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleRecombineTimer.g.cs delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleRecombineTimer.g.cs.meta delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityTimer.g.cs delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityTimer.g.cs.meta delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutCircle.g.cs delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutCircle.g.cs.meta delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutEntity.g.cs delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutEntity.g.cs.meta delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutPlayer.g.cs delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutPlayer.g.cs.meta delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/MoveAllPlayersTimer.g.cs delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/MoveAllPlayersTimer.g.cs.meta delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/SpawnFoodTimer.g.cs delete mode 100644 demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/SpawnFoodTimer.g.cs.meta 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 1e684b35787..287eb2f65d2 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 1.11.2 (commit 97aa69de8942102a6ea0b50dfadea3cd15e44f50). +// This was generated using spacetimedb cli version 1.12.0 (commit 819069447d9034135872ce2bdc28722c4e5e46b6). #nullable enable @@ -29,18 +29,10 @@ public sealed partial class RemoteTables : RemoteTablesBase public RemoteTables(DbConnection conn) { AddTable(Circle = new(conn)); - AddTable(CircleDecayTimer = new(conn)); - AddTable(CircleRecombineTimer = new(conn)); AddTable(Config = new(conn)); - AddTable(ConsumeEntityTimer = new(conn)); AddTable(Entity = new(conn)); AddTable(Food = new(conn)); - AddTable(LoggedOutCircle = new(conn)); - AddTable(LoggedOutEntity = new(conn)); - AddTable(LoggedOutPlayer = new(conn)); - AddTable(MoveAllPlayersTimer = new(conn)); AddTable(Player = new(conn)); - AddTable(SpawnFoodTimer = new(conn)); } } @@ -594,18 +586,10 @@ public sealed class QueryBuilder public sealed class From { public global::SpacetimeDB.Table Circle() => new("circle", new CircleCols("circle"), new CircleIxCols("circle")); - public global::SpacetimeDB.Table CircleDecayTimer() => new("circle_decay_timer", new CircleDecayTimerCols("circle_decay_timer"), new CircleDecayTimerIxCols("circle_decay_timer")); - public global::SpacetimeDB.Table CircleRecombineTimer() => new("circle_recombine_timer", new CircleRecombineTimerCols("circle_recombine_timer"), new CircleRecombineTimerIxCols("circle_recombine_timer")); public global::SpacetimeDB.Table Config() => new("config", new ConfigCols("config"), new ConfigIxCols("config")); - public global::SpacetimeDB.Table ConsumeEntityTimer() => new("consume_entity_timer", new ConsumeEntityTimerCols("consume_entity_timer"), new ConsumeEntityTimerIxCols("consume_entity_timer")); 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 LoggedOutCircle() => new("logged_out_circle", new LoggedOutCircleCols("logged_out_circle"), new LoggedOutCircleIxCols("logged_out_circle")); - public global::SpacetimeDB.Table LoggedOutEntity() => new("logged_out_entity", new LoggedOutEntityCols("logged_out_entity"), new LoggedOutEntityIxCols("logged_out_entity")); - public global::SpacetimeDB.Table LoggedOutPlayer() => new("logged_out_player", new LoggedOutPlayerCols("logged_out_player"), new LoggedOutPlayerIxCols("logged_out_player")); - public global::SpacetimeDB.Table MoveAllPlayersTimer() => new("move_all_players_timer", new MoveAllPlayersTimerCols("move_all_players_timer"), new MoveAllPlayersTimerIxCols("move_all_players_timer")); public global::SpacetimeDB.Table Player() => new("player", new PlayerCols("player"), new PlayerIxCols("player")); - public global::SpacetimeDB.Table SpawnFoodTimer() => new("spawn_food_timer", new SpawnFoodTimerCols("spawn_food_timer"), new SpawnFoodTimerIxCols("spawn_food_timer")); } public sealed class TypedSubscriptionBuilder diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleDecayTimer.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleDecayTimer.g.cs deleted file mode 100644 index 09cd0b1053b..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleDecayTimer.g.cs +++ /dev/null @@ -1,61 +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.BSATN; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteTables - { - public sealed class CircleDecayTimerHandle : RemoteTableHandle - { - protected override string RemoteTableName => "circle_decay_timer"; - - public sealed class ScheduledIdUniqueIndex : UniqueIndexBase - { - protected override ulong GetKey(CircleDecayTimer row) => row.ScheduledId; - - public ScheduledIdUniqueIndex(CircleDecayTimerHandle table) : base(table) { } - } - - public readonly ScheduledIdUniqueIndex ScheduledId; - - internal CircleDecayTimerHandle(DbConnection conn) : base(conn) - { - ScheduledId = new(this); - } - - protected override object GetPrimaryKey(CircleDecayTimer row) => row.ScheduledId; - } - - public readonly CircleDecayTimerHandle CircleDecayTimer; - } - - public sealed class CircleDecayTimerCols - { - public global::SpacetimeDB.Col ScheduledId { get; } - public global::SpacetimeDB.Col ScheduledAt { get; } - - public CircleDecayTimerCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.Col(tableName, "scheduled_id"); - ScheduledAt = new global::SpacetimeDB.Col(tableName, "scheduled_at"); - } - } - - public sealed class CircleDecayTimerIxCols - { - public global::SpacetimeDB.IxCol ScheduledId { get; } - - public CircleDecayTimerIxCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.IxCol(tableName, "scheduled_id"); - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleDecayTimer.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleDecayTimer.g.cs.meta deleted file mode 100644 index 883147192bc..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleDecayTimer.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 57d3843cee8f7d94b9d02c442f4aaf0e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleRecombineTimer.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleRecombineTimer.g.cs deleted file mode 100644 index 5bb48e1918b..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleRecombineTimer.g.cs +++ /dev/null @@ -1,63 +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.BSATN; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteTables - { - public sealed class CircleRecombineTimerHandle : RemoteTableHandle - { - protected override string RemoteTableName => "circle_recombine_timer"; - - public sealed class ScheduledIdUniqueIndex : UniqueIndexBase - { - protected override ulong GetKey(CircleRecombineTimer row) => row.ScheduledId; - - public ScheduledIdUniqueIndex(CircleRecombineTimerHandle table) : base(table) { } - } - - public readonly ScheduledIdUniqueIndex ScheduledId; - - internal CircleRecombineTimerHandle(DbConnection conn) : base(conn) - { - ScheduledId = new(this); - } - - protected override object GetPrimaryKey(CircleRecombineTimer row) => row.ScheduledId; - } - - public readonly CircleRecombineTimerHandle CircleRecombineTimer; - } - - public sealed class CircleRecombineTimerCols - { - public global::SpacetimeDB.Col ScheduledId { get; } - public global::SpacetimeDB.Col ScheduledAt { get; } - public global::SpacetimeDB.Col PlayerId { get; } - - public CircleRecombineTimerCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.Col(tableName, "scheduled_id"); - ScheduledAt = new global::SpacetimeDB.Col(tableName, "scheduled_at"); - PlayerId = new global::SpacetimeDB.Col(tableName, "player_id"); - } - } - - public sealed class CircleRecombineTimerIxCols - { - public global::SpacetimeDB.IxCol ScheduledId { get; } - - public CircleRecombineTimerIxCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.IxCol(tableName, "scheduled_id"); - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleRecombineTimer.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleRecombineTimer.g.cs.meta deleted file mode 100644 index 937e29e9fa3..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleRecombineTimer.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 90a420ed2322bf140be4f3111ab47ea7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityTimer.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityTimer.g.cs deleted file mode 100644 index 991112b45b6..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityTimer.g.cs +++ /dev/null @@ -1,65 +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.BSATN; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteTables - { - public sealed class ConsumeEntityTimerHandle : RemoteTableHandle - { - protected override string RemoteTableName => "consume_entity_timer"; - - public sealed class ScheduledIdUniqueIndex : UniqueIndexBase - { - protected override ulong GetKey(ConsumeEntityTimer row) => row.ScheduledId; - - public ScheduledIdUniqueIndex(ConsumeEntityTimerHandle table) : base(table) { } - } - - public readonly ScheduledIdUniqueIndex ScheduledId; - - internal ConsumeEntityTimerHandle(DbConnection conn) : base(conn) - { - ScheduledId = new(this); - } - - protected override object GetPrimaryKey(ConsumeEntityTimer row) => row.ScheduledId; - } - - public readonly ConsumeEntityTimerHandle ConsumeEntityTimer; - } - - public sealed class ConsumeEntityTimerCols - { - public global::SpacetimeDB.Col ScheduledId { get; } - public global::SpacetimeDB.Col ScheduledAt { get; } - public global::SpacetimeDB.Col ConsumedEntityId { get; } - public global::SpacetimeDB.Col ConsumerEntityId { get; } - - public ConsumeEntityTimerCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.Col(tableName, "scheduled_id"); - ScheduledAt = new global::SpacetimeDB.Col(tableName, "scheduled_at"); - ConsumedEntityId = new global::SpacetimeDB.Col(tableName, "consumed_entity_id"); - ConsumerEntityId = new global::SpacetimeDB.Col(tableName, "consumer_entity_id"); - } - } - - public sealed class ConsumeEntityTimerIxCols - { - public global::SpacetimeDB.IxCol ScheduledId { get; } - - public ConsumeEntityTimerIxCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.IxCol(tableName, "scheduled_id"); - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityTimer.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityTimer.g.cs.meta deleted file mode 100644 index def7a8b8eb1..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityTimer.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 78647a76650941c468cc02c4fda86386 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutCircle.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutCircle.g.cs deleted file mode 100644 index 4c56218c271..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutCircle.g.cs +++ /dev/null @@ -1,79 +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.BSATN; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteTables - { - public sealed class LoggedOutCircleHandle : RemoteTableHandle - { - protected override string RemoteTableName => "logged_out_circle"; - - public sealed class EntityIdUniqueIndex : UniqueIndexBase - { - protected override int GetKey(Circle row) => row.EntityId; - - public EntityIdUniqueIndex(LoggedOutCircleHandle table) : base(table) { } - } - - public readonly EntityIdUniqueIndex EntityId; - - public sealed class PlayerIdIndex : BTreeIndexBase - { - protected override int GetKey(Circle row) => row.PlayerId; - - public PlayerIdIndex(LoggedOutCircleHandle table) : base(table) { } - } - - public readonly PlayerIdIndex PlayerId; - - internal LoggedOutCircleHandle(DbConnection conn) : base(conn) - { - EntityId = new(this); - PlayerId = new(this); - } - - protected override object GetPrimaryKey(Circle row) => row.EntityId; - } - - public readonly LoggedOutCircleHandle LoggedOutCircle; - } - - public sealed class LoggedOutCircleCols - { - public global::SpacetimeDB.Col EntityId { get; } - public global::SpacetimeDB.Col PlayerId { get; } - public global::SpacetimeDB.Col Direction { get; } - public global::SpacetimeDB.Col Speed { get; } - public global::SpacetimeDB.Col LastSplitTime { get; } - - public LoggedOutCircleCols(string tableName) - { - EntityId = new global::SpacetimeDB.Col(tableName, "entity_id"); - PlayerId = new global::SpacetimeDB.Col(tableName, "player_id"); - Direction = new global::SpacetimeDB.Col(tableName, "direction"); - Speed = new global::SpacetimeDB.Col(tableName, "speed"); - LastSplitTime = new global::SpacetimeDB.Col(tableName, "last_split_time"); - } - } - - public sealed class LoggedOutCircleIxCols - { - public global::SpacetimeDB.IxCol EntityId { get; } - public global::SpacetimeDB.IxCol PlayerId { get; } - - public LoggedOutCircleIxCols(string tableName) - { - EntityId = new global::SpacetimeDB.IxCol(tableName, "entity_id"); - PlayerId = new global::SpacetimeDB.IxCol(tableName, "player_id"); - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutCircle.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutCircle.g.cs.meta deleted file mode 100644 index dd99a0a9956..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutCircle.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4c19f6af775194970b23ef28055872de -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutEntity.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutEntity.g.cs deleted file mode 100644 index 00eec8e2b12..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutEntity.g.cs +++ /dev/null @@ -1,63 +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.BSATN; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteTables - { - public sealed class LoggedOutEntityHandle : RemoteTableHandle - { - protected override string RemoteTableName => "logged_out_entity"; - - public sealed class EntityIdUniqueIndex : UniqueIndexBase - { - protected override int GetKey(Entity row) => row.EntityId; - - public EntityIdUniqueIndex(LoggedOutEntityHandle table) : base(table) { } - } - - public readonly EntityIdUniqueIndex EntityId; - - internal LoggedOutEntityHandle(DbConnection conn) : base(conn) - { - EntityId = new(this); - } - - protected override object GetPrimaryKey(Entity row) => row.EntityId; - } - - public readonly LoggedOutEntityHandle LoggedOutEntity; - } - - public sealed class LoggedOutEntityCols - { - public global::SpacetimeDB.Col EntityId { get; } - public global::SpacetimeDB.Col Position { get; } - public global::SpacetimeDB.Col Mass { get; } - - public LoggedOutEntityCols(string tableName) - { - EntityId = new global::SpacetimeDB.Col(tableName, "entity_id"); - Position = new global::SpacetimeDB.Col(tableName, "position"); - Mass = new global::SpacetimeDB.Col(tableName, "mass"); - } - } - - public sealed class LoggedOutEntityIxCols - { - public global::SpacetimeDB.IxCol EntityId { get; } - - public LoggedOutEntityIxCols(string tableName) - { - EntityId = new global::SpacetimeDB.IxCol(tableName, "entity_id"); - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutEntity.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutEntity.g.cs.meta deleted file mode 100644 index 29ed5cea05c..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutEntity.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5571e411f0f7244f09db138c87ad7fa6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutPlayer.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutPlayer.g.cs deleted file mode 100644 index 035f671053e..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutPlayer.g.cs +++ /dev/null @@ -1,75 +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.BSATN; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteTables - { - public sealed class LoggedOutPlayerHandle : RemoteTableHandle - { - protected override string RemoteTableName => "logged_out_player"; - - public sealed class IdentityUniqueIndex : UniqueIndexBase - { - protected override SpacetimeDB.Identity GetKey(Player row) => row.Identity; - - public IdentityUniqueIndex(LoggedOutPlayerHandle table) : base(table) { } - } - - public readonly IdentityUniqueIndex Identity; - - public sealed class PlayerIdUniqueIndex : UniqueIndexBase - { - protected override int GetKey(Player row) => row.PlayerId; - - public PlayerIdUniqueIndex(LoggedOutPlayerHandle table) : base(table) { } - } - - public readonly PlayerIdUniqueIndex PlayerId; - - internal LoggedOutPlayerHandle(DbConnection conn) : base(conn) - { - Identity = new(this); - PlayerId = new(this); - } - - protected override object GetPrimaryKey(Player row) => row.Identity; - } - - public readonly LoggedOutPlayerHandle LoggedOutPlayer; - } - - public sealed class LoggedOutPlayerCols - { - public global::SpacetimeDB.Col Identity { get; } - public global::SpacetimeDB.Col PlayerId { get; } - public global::SpacetimeDB.Col Name { get; } - - public LoggedOutPlayerCols(string tableName) - { - Identity = new global::SpacetimeDB.Col(tableName, "identity"); - PlayerId = new global::SpacetimeDB.Col(tableName, "player_id"); - Name = new global::SpacetimeDB.Col(tableName, "name"); - } - } - - public sealed class LoggedOutPlayerIxCols - { - public global::SpacetimeDB.IxCol Identity { get; } - public global::SpacetimeDB.IxCol PlayerId { get; } - - public LoggedOutPlayerIxCols(string tableName) - { - Identity = new global::SpacetimeDB.IxCol(tableName, "identity"); - PlayerId = new global::SpacetimeDB.IxCol(tableName, "player_id"); - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutPlayer.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutPlayer.g.cs.meta deleted file mode 100644 index 076508dbb7e..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutPlayer.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fec3f4e4213dc304dadb74b8fee558da -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/MoveAllPlayersTimer.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/MoveAllPlayersTimer.g.cs deleted file mode 100644 index b84ba4c72ef..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/MoveAllPlayersTimer.g.cs +++ /dev/null @@ -1,61 +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.BSATN; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteTables - { - public sealed class MoveAllPlayersTimerHandle : RemoteTableHandle - { - protected override string RemoteTableName => "move_all_players_timer"; - - public sealed class ScheduledIdUniqueIndex : UniqueIndexBase - { - protected override ulong GetKey(MoveAllPlayersTimer row) => row.ScheduledId; - - public ScheduledIdUniqueIndex(MoveAllPlayersTimerHandle table) : base(table) { } - } - - public readonly ScheduledIdUniqueIndex ScheduledId; - - internal MoveAllPlayersTimerHandle(DbConnection conn) : base(conn) - { - ScheduledId = new(this); - } - - protected override object GetPrimaryKey(MoveAllPlayersTimer row) => row.ScheduledId; - } - - public readonly MoveAllPlayersTimerHandle MoveAllPlayersTimer; - } - - public sealed class MoveAllPlayersTimerCols - { - public global::SpacetimeDB.Col ScheduledId { get; } - public global::SpacetimeDB.Col ScheduledAt { get; } - - public MoveAllPlayersTimerCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.Col(tableName, "scheduled_id"); - ScheduledAt = new global::SpacetimeDB.Col(tableName, "scheduled_at"); - } - } - - public sealed class MoveAllPlayersTimerIxCols - { - public global::SpacetimeDB.IxCol ScheduledId { get; } - - public MoveAllPlayersTimerIxCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.IxCol(tableName, "scheduled_id"); - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/MoveAllPlayersTimer.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/MoveAllPlayersTimer.g.cs.meta deleted file mode 100644 index b88d73cef22..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/MoveAllPlayersTimer.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 037804098ca85634abc83a5cfe85292d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/SpawnFoodTimer.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/SpawnFoodTimer.g.cs deleted file mode 100644 index 5a8c134a48b..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/SpawnFoodTimer.g.cs +++ /dev/null @@ -1,61 +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.BSATN; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteTables - { - public sealed class SpawnFoodTimerHandle : RemoteTableHandle - { - protected override string RemoteTableName => "spawn_food_timer"; - - public sealed class ScheduledIdUniqueIndex : UniqueIndexBase - { - protected override ulong GetKey(SpawnFoodTimer row) => row.ScheduledId; - - public ScheduledIdUniqueIndex(SpawnFoodTimerHandle table) : base(table) { } - } - - public readonly ScheduledIdUniqueIndex ScheduledId; - - internal SpawnFoodTimerHandle(DbConnection conn) : base(conn) - { - ScheduledId = new(this); - } - - protected override object GetPrimaryKey(SpawnFoodTimer row) => row.ScheduledId; - } - - public readonly SpawnFoodTimerHandle SpawnFoodTimer; - } - - public sealed class SpawnFoodTimerCols - { - public global::SpacetimeDB.Col ScheduledId { get; } - public global::SpacetimeDB.Col ScheduledAt { get; } - - public SpawnFoodTimerCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.Col(tableName, "scheduled_id"); - ScheduledAt = new global::SpacetimeDB.Col(tableName, "scheduled_at"); - } - } - - public sealed class SpawnFoodTimerIxCols - { - public global::SpacetimeDB.IxCol ScheduledId { get; } - - public SpawnFoodTimerIxCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.IxCol(tableName, "scheduled_id"); - } - } -} diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/SpawnFoodTimer.g.cs.meta b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/SpawnFoodTimer.g.cs.meta deleted file mode 100644 index 478b3ff8e68..00000000000 --- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/SpawnFoodTimer.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 954d9d0ae83400248b5aec8d7b407bbc -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: From f65c6734b093c56adcbc0c5e2e68f2c9874babc3 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Wed, 4 Feb 2026 07:05:29 -0800 Subject: [PATCH 10/18] Update for regression-tests module_bindings --- .../module_bindings/SpacetimeDBClient.g.cs | 2 +- .../module_bindings/SpacetimeDBClient.g.cs | 4 +- .../Tables/ScheduledProcTable.g.cs | 67 ------------------- .../module_bindings/SpacetimeDBClient.g.cs | 2 +- 4 files changed, 3 insertions(+), 72 deletions(-) delete mode 100644 sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/Tables/ScheduledProcTable.g.cs 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 b8c7b3a9224..40d76ad4f84 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 1.11.3 (commit 7cd565f410fd6ad504b4397c4a970300b92a1c1c). +// This was generated using spacetimedb cli version 1.12.0 (commit 819069447d9034135872ce2bdc28722c4e5e46b6). #nullable enable 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 8eab9eb3391..79c87218fb4 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 1.11.3 (commit 214a46c8fac0d98c96d03017993ba757b7962124). +// This was generated using spacetimedb cli version 1.12.0 (commit 819069447d9034135872ce2bdc28722c4e5e46b6). #nullable enable @@ -31,7 +31,6 @@ public RemoteTables(DbConnection conn) AddTable(MyTable = new(conn)); AddTable(PkUuid = new(conn)); AddTable(ProcInsertsInto = new(conn)); - AddTable(ScheduledProcTable = new(conn)); } } @@ -587,7 +586,6 @@ public sealed class From public global::SpacetimeDB.Table MyTable() => new("my_table", new MyTableCols("my_table"), new MyTableIxCols("my_table")); public global::SpacetimeDB.Table PkUuid() => new("pk_uuid", new PkUuidCols("pk_uuid"), new PkUuidIxCols("pk_uuid")); public global::SpacetimeDB.Table ProcInsertsInto() => new("proc_inserts_into", new ProcInsertsIntoCols("proc_inserts_into"), new ProcInsertsIntoIxCols("proc_inserts_into")); - public global::SpacetimeDB.Table ScheduledProcTable() => new("scheduled_proc_table", new ScheduledProcTableCols("scheduled_proc_table"), new ScheduledProcTableIxCols("scheduled_proc_table")); } public sealed class TypedSubscriptionBuilder diff --git a/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/Tables/ScheduledProcTable.g.cs b/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/Tables/ScheduledProcTable.g.cs deleted file mode 100644 index 67f120a2902..00000000000 --- a/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/Tables/ScheduledProcTable.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.BSATN; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteTables - { - public sealed class ScheduledProcTableHandle : RemoteTableHandle - { - protected override string RemoteTableName => "scheduled_proc_table"; - - public sealed class ScheduledIdUniqueIndex : UniqueIndexBase - { - protected override ulong GetKey(ScheduledProcTable row) => row.ScheduledId; - - public ScheduledIdUniqueIndex(ScheduledProcTableHandle table) : base(table) { } - } - - public readonly ScheduledIdUniqueIndex ScheduledId; - - internal ScheduledProcTableHandle(DbConnection conn) : base(conn) - { - ScheduledId = new(this); - } - - protected override object GetPrimaryKey(ScheduledProcTable row) => row.ScheduledId; - } - - public readonly ScheduledProcTableHandle ScheduledProcTable; - } - - public sealed class ScheduledProcTableCols - { - public global::SpacetimeDB.Col ScheduledId { get; } - public global::SpacetimeDB.Col ScheduledAt { get; } - public global::SpacetimeDB.Col ReducerTs { get; } - public global::SpacetimeDB.Col X { get; } - public global::SpacetimeDB.Col Y { get; } - - public ScheduledProcTableCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.Col(tableName, "scheduled_id"); - ScheduledAt = new global::SpacetimeDB.Col(tableName, "scheduled_at"); - ReducerTs = new global::SpacetimeDB.Col(tableName, "reducer_ts"); - X = new global::SpacetimeDB.Col(tableName, "x"); - Y = new global::SpacetimeDB.Col(tableName, "y"); - } - } - - public sealed class ScheduledProcTableIxCols - { - public global::SpacetimeDB.IxCol ScheduledId { get; } - - public ScheduledProcTableIxCols(string tableName) - { - ScheduledId = new global::SpacetimeDB.IxCol(tableName, "scheduled_id"); - } - } -} 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 d5eb058bf81..e8015a356d0 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 1.11.3 (commit 214a46c8fac0d98c96d03017993ba757b7962124). +// This was generated using spacetimedb cli version 1.12.0 (commit 819069447d9034135872ce2bdc28722c4e5e46b6). #nullable enable From 32216019bd243f58c7844ffdd7682591f8566865 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Wed, 4 Feb 2026 07:39:29 -0800 Subject: [PATCH 11/18] Update Rust test module_bindings --- .../src/module_bindings/mod.rs | 2 +- .../src/module_bindings/mod.rs | 18 +- .../scheduled_proc_table_table.rs | 158 ------------------ .../module_bindings/indexed_table_2_table.rs | 111 ------------ .../module_bindings/indexed_table_table.rs | 111 ------------ .../view-client/src/module_bindings/mod.rs | 12 +- .../module_bindings/player_location_table.rs | 142 ---------------- 7 files changed, 3 insertions(+), 551 deletions(-) delete mode 100644 sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_table_table.rs delete mode 100644 sdks/rust/tests/test-client/src/module_bindings/indexed_table_2_table.rs delete mode 100644 sdks/rust/tests/test-client/src/module_bindings/indexed_table_table.rs delete mode 100644 sdks/rust/tests/view-client/src/module_bindings/player_location_table.rs 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 5a54035abec..9fd4e75ac17 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.11.2 (commit 13a0172567170d9b8c87d2aa71de3246c21acb8c). +// This was generated using spacetimedb cli version 1.12.0 (commit 819069447d9034135872ce2bdc28722c4e5e46b6). #![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/mod.rs b/sdks/rust/tests/procedure-client/src/module_bindings/mod.rs index 892f78d2899..a6637c87664 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.11.2 (commit 13a0172567170d9b8c87d2aa71de3246c21acb8c). +// This was generated using spacetimedb cli version 1.12.0 (commit 819069447d9034135872ce2bdc28722c4e5e46b6). #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; @@ -24,7 +24,6 @@ pub mod return_struct_procedure; pub mod return_struct_type; pub mod schedule_proc_reducer; pub mod scheduled_proc_procedure; -pub mod scheduled_proc_table_table; pub mod scheduled_proc_table_type; pub mod sorted_uuids_insert_procedure; pub mod will_panic_procedure; @@ -47,7 +46,6 @@ pub use return_struct_procedure::return_struct; pub use return_struct_type::ReturnStruct; pub use schedule_proc_reducer::{schedule_proc, set_flags_for_schedule_proc, ScheduleProcCallbackId}; pub use scheduled_proc_procedure::scheduled_proc; -pub use scheduled_proc_table_table::*; pub use scheduled_proc_table_type::ScheduledProcTable; pub use sorted_uuids_insert_procedure::sorted_uuids_insert; pub use will_panic_procedure::will_panic; @@ -96,7 +94,6 @@ pub struct DbUpdate { my_table: __sdk::TableUpdate, pk_uuid: __sdk::TableUpdate, proc_inserts_into: __sdk::TableUpdate, - scheduled_proc_table: __sdk::TableUpdate, } impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { @@ -114,9 +111,6 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { "proc_inserts_into" => db_update .proc_inserts_into .append(proc_inserts_into_table::parse_table_update(table_update)?), - "scheduled_proc_table" => db_update - .scheduled_proc_table - .append(scheduled_proc_table_table::parse_table_update(table_update)?), unknown => { return Err(__sdk::InternalError::unknown_name("table", unknown, "DatabaseUpdate").into()); @@ -139,9 +133,6 @@ impl __sdk::DbUpdate for DbUpdate { diff.pk_uuid = cache.apply_diff_to_table::("pk_uuid", &self.pk_uuid); diff.proc_inserts_into = cache.apply_diff_to_table::("proc_inserts_into", &self.proc_inserts_into); - diff.scheduled_proc_table = cache - .apply_diff_to_table::("scheduled_proc_table", &self.scheduled_proc_table) - .with_updates_by_pk(|row| &row.scheduled_id); diff } @@ -154,7 +145,6 @@ pub struct AppliedDiff<'r> { my_table: __sdk::TableAppliedDiff<'r, MyTable>, pk_uuid: __sdk::TableAppliedDiff<'r, PkUuid>, proc_inserts_into: __sdk::TableAppliedDiff<'r, ProcInsertsInto>, - scheduled_proc_table: __sdk::TableAppliedDiff<'r, ScheduledProcTable>, __unused: std::marker::PhantomData<&'r ()>, } @@ -167,11 +157,6 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> { callbacks.invoke_table_row_callbacks::("my_table", &self.my_table, event); callbacks.invoke_table_row_callbacks::("pk_uuid", &self.pk_uuid, event); callbacks.invoke_table_row_callbacks::("proc_inserts_into", &self.proc_inserts_into, event); - callbacks.invoke_table_row_callbacks::( - "scheduled_proc_table", - &self.scheduled_proc_table, - event, - ); } } @@ -895,6 +880,5 @@ impl __sdk::SpacetimeModule for RemoteModule { my_table_table::register_table(client_cache); pk_uuid_table::register_table(client_cache); proc_inserts_into_table::register_table(client_cache); - scheduled_proc_table_table::register_table(client_cache); } } 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 deleted file mode 100644 index afea2c721a1..00000000000 --- a/sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_table_table.rs +++ /dev/null @@ -1,158 +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. - -#![allow(unused, clippy::all)] -use super::scheduled_proc_table_type::ScheduledProcTable; -use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; - -/// Table handle for the table `scheduled_proc_table`. -/// -/// Obtain a handle from the [`ScheduledProcTableTableAccess::scheduled_proc_table`] method on [`super::RemoteTables`], -/// like `ctx.db.scheduled_proc_table()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.scheduled_proc_table().on_insert(...)`. -pub struct ScheduledProcTableTableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `scheduled_proc_table`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait ScheduledProcTableTableAccess { - #[allow(non_snake_case)] - /// Obtain a [`ScheduledProcTableTableHandle`], which mediates access to the table `scheduled_proc_table`. - fn scheduled_proc_table(&self) -> ScheduledProcTableTableHandle<'_>; -} - -impl ScheduledProcTableTableAccess for super::RemoteTables { - fn scheduled_proc_table(&self) -> ScheduledProcTableTableHandle<'_> { - ScheduledProcTableTableHandle { - imp: self.imp.get_table::("scheduled_proc_table"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct ScheduledProcTableInsertCallbackId(__sdk::CallbackId); -pub struct ScheduledProcTableDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for ScheduledProcTableTableHandle<'ctx> { - type Row = ScheduledProcTable; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { - self.imp.count() - } - fn iter(&self) -> impl Iterator + '_ { - self.imp.iter() - } - - type InsertCallbackId = ScheduledProcTableInsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> ScheduledProcTableInsertCallbackId { - ScheduledProcTableInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: ScheduledProcTableInsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = ScheduledProcTableDeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> ScheduledProcTableDeleteCallbackId { - ScheduledProcTableDeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: ScheduledProcTableDeleteCallbackId) { - self.imp.remove_on_delete(callback.0) - } -} - -#[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> { - type UpdateCallbackId = ScheduledProcTableUpdateCallbackId; - - fn on_update( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, - ) -> ScheduledProcTableUpdateCallbackId { - ScheduledProcTableUpdateCallbackId(self.imp.on_update(Box::new(callback))) - } - - fn remove_on_update(&self, callback: ScheduledProcTableUpdateCallbackId) { - self.imp.remove_on_update(callback.0) - } -} - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __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. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.scheduled_proc_table().scheduled_id().find(...)`. -pub struct ScheduledProcTableScheduledIdUnique<'ctx> { - imp: __sdk::UniqueConstraintHandle, - phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -impl<'ctx> ScheduledProcTableTableHandle<'ctx> { - /// Get a handle on the `scheduled_id` unique index on the table `scheduled_proc_table`. - pub fn scheduled_id(&self) -> ScheduledProcTableScheduledIdUnique<'ctx> { - ScheduledProcTableScheduledIdUnique { - imp: self.imp.get_unique_constraint::("scheduled_id"), - phantom: std::marker::PhantomData, - } - } -} - -impl<'ctx> ScheduledProcTableScheduledIdUnique<'ctx> { - /// Find the subscribed row whose `scheduled_id` column value is equal to `col_val`, - /// if such a row is present in the client cache. - pub fn find(&self, col_val: &u64) -> Option { - self.imp.find(col_val) - } -} - -#[allow(non_camel_case_types)] -/// Extension trait for query builder access to the table `ScheduledProcTable`. -/// -/// Implemented for [`__sdk::QueryTableAccessor`]. -pub trait scheduled_proc_tableQueryTableAccess { - #[allow(non_snake_case)] - /// Get a query builder for the table `ScheduledProcTable`. - fn scheduled_proc_table(&self) -> __sdk::__query_builder::Table; -} - -impl scheduled_proc_tableQueryTableAccess for __sdk::QueryTableAccessor { - fn scheduled_proc_table(&self) -> __sdk::__query_builder::Table { - __sdk::__query_builder::Table::new("scheduled_proc_table") - } -} diff --git a/sdks/rust/tests/test-client/src/module_bindings/indexed_table_2_table.rs b/sdks/rust/tests/test-client/src/module_bindings/indexed_table_2_table.rs deleted file mode 100644 index 727d167e592..00000000000 --- a/sdks/rust/tests/test-client/src/module_bindings/indexed_table_2_table.rs +++ /dev/null @@ -1,111 +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. - -#![allow(unused, clippy::all)] -use super::indexed_table_2_type::IndexedTable2; -use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; - -/// Table handle for the table `indexed_table_2`. -/// -/// Obtain a handle from the [`IndexedTable2TableAccess::indexed_table_2`] method on [`super::RemoteTables`], -/// like `ctx.db.indexed_table_2()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.indexed_table_2().on_insert(...)`. -pub struct IndexedTable2TableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `indexed_table_2`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait IndexedTable2TableAccess { - #[allow(non_snake_case)] - /// Obtain a [`IndexedTable2TableHandle`], which mediates access to the table `indexed_table_2`. - fn indexed_table_2(&self) -> IndexedTable2TableHandle<'_>; -} - -impl IndexedTable2TableAccess for super::RemoteTables { - fn indexed_table_2(&self) -> IndexedTable2TableHandle<'_> { - IndexedTable2TableHandle { - imp: self.imp.get_table::("indexed_table_2"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct IndexedTable2InsertCallbackId(__sdk::CallbackId); -pub struct IndexedTable2DeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for IndexedTable2TableHandle<'ctx> { - type Row = IndexedTable2; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { - self.imp.count() - } - fn iter(&self) -> impl Iterator + '_ { - self.imp.iter() - } - - type InsertCallbackId = IndexedTable2InsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> IndexedTable2InsertCallbackId { - IndexedTable2InsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: IndexedTable2InsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = IndexedTable2DeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> IndexedTable2DeleteCallbackId { - IndexedTable2DeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: IndexedTable2DeleteCallbackId) { - self.imp.remove_on_delete(callback.0) - } -} - -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("indexed_table_2"); -} - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __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 `IndexedTable2`. -/// -/// Implemented for [`__sdk::QueryTableAccessor`]. -pub trait indexed_table_2QueryTableAccess { - #[allow(non_snake_case)] - /// Get a query builder for the table `IndexedTable2`. - fn indexed_table_2(&self) -> __sdk::__query_builder::Table; -} - -impl indexed_table_2QueryTableAccess for __sdk::QueryTableAccessor { - fn indexed_table_2(&self) -> __sdk::__query_builder::Table { - __sdk::__query_builder::Table::new("indexed_table_2") - } -} diff --git a/sdks/rust/tests/test-client/src/module_bindings/indexed_table_table.rs b/sdks/rust/tests/test-client/src/module_bindings/indexed_table_table.rs deleted file mode 100644 index ab01d94a663..00000000000 --- a/sdks/rust/tests/test-client/src/module_bindings/indexed_table_table.rs +++ /dev/null @@ -1,111 +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. - -#![allow(unused, clippy::all)] -use super::indexed_table_type::IndexedTable; -use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; - -/// Table handle for the table `indexed_table`. -/// -/// Obtain a handle from the [`IndexedTableTableAccess::indexed_table`] method on [`super::RemoteTables`], -/// like `ctx.db.indexed_table()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.indexed_table().on_insert(...)`. -pub struct IndexedTableTableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `indexed_table`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait IndexedTableTableAccess { - #[allow(non_snake_case)] - /// Obtain a [`IndexedTableTableHandle`], which mediates access to the table `indexed_table`. - fn indexed_table(&self) -> IndexedTableTableHandle<'_>; -} - -impl IndexedTableTableAccess for super::RemoteTables { - fn indexed_table(&self) -> IndexedTableTableHandle<'_> { - IndexedTableTableHandle { - imp: self.imp.get_table::("indexed_table"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct IndexedTableInsertCallbackId(__sdk::CallbackId); -pub struct IndexedTableDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for IndexedTableTableHandle<'ctx> { - type Row = IndexedTable; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { - self.imp.count() - } - fn iter(&self) -> impl Iterator + '_ { - self.imp.iter() - } - - type InsertCallbackId = IndexedTableInsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> IndexedTableInsertCallbackId { - IndexedTableInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: IndexedTableInsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = IndexedTableDeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> IndexedTableDeleteCallbackId { - IndexedTableDeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: IndexedTableDeleteCallbackId) { - self.imp.remove_on_delete(callback.0) - } -} - -#[doc(hidden)] -pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { - let _table = client_cache.get_or_make_table::("indexed_table"); -} - -#[doc(hidden)] -pub(super) fn parse_table_update( - raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, -) -> __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 `IndexedTable`. -/// -/// Implemented for [`__sdk::QueryTableAccessor`]. -pub trait indexed_tableQueryTableAccess { - #[allow(non_snake_case)] - /// Get a query builder for the table `IndexedTable`. - fn indexed_table(&self) -> __sdk::__query_builder::Table; -} - -impl indexed_tableQueryTableAccess for __sdk::QueryTableAccessor { - fn indexed_table(&self) -> __sdk::__query_builder::Table { - __sdk::__query_builder::Table::new("indexed_table") - } -} 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 40ff3f092bf..a5bb61a598c 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.11.2 (commit 13a0172567170d9b8c87d2aa71de3246c21acb8c). +// This was generated using spacetimedb cli version 1.12.0 (commit 819069447d9034135872ce2bdc28722c4e5e46b6). #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; @@ -15,7 +15,6 @@ pub mod nearby_players_table; pub mod player_and_level_type; pub mod player_level_table; pub mod player_level_type; -pub mod player_location_table; pub mod player_location_type; pub mod player_table; pub mod player_type; @@ -30,7 +29,6 @@ pub use nearby_players_table::*; pub use player_and_level_type::PlayerAndLevel; pub use player_level_table::*; pub use player_level_type::PlayerLevel; -pub use player_location_table::*; pub use player_location_type::PlayerLocation; pub use player_table::*; pub use player_type::Player; @@ -96,7 +94,6 @@ pub struct DbUpdate { nearby_players: __sdk::TableUpdate, player: __sdk::TableUpdate, player_level: __sdk::TableUpdate, - player_location: __sdk::TableUpdate, players_at_level_0: __sdk::TableUpdate, } @@ -119,9 +116,6 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { "player_level" => db_update .player_level .append(player_level_table::parse_table_update(table_update)?), - "player_location" => db_update - .player_location - .append(player_location_table::parse_table_update(table_update)?), "players_at_level_0" => db_update .players_at_level_0 .append(players_at_level_0_table::parse_table_update(table_update)?), @@ -147,7 +141,6 @@ impl __sdk::DbUpdate for DbUpdate { .apply_diff_to_table::("player", &self.player) .with_updates_by_pk(|row| &row.entity_id); diff.player_level = cache.apply_diff_to_table::("player_level", &self.player_level); - diff.player_location = cache.apply_diff_to_table::("player_location", &self.player_location); diff.my_player = cache.apply_diff_to_table::("my_player", &self.my_player); diff.my_player_and_level = cache.apply_diff_to_table::("my_player_and_level", &self.my_player_and_level); @@ -167,7 +160,6 @@ pub struct AppliedDiff<'r> { nearby_players: __sdk::TableAppliedDiff<'r, PlayerLocation>, player: __sdk::TableAppliedDiff<'r, Player>, player_level: __sdk::TableAppliedDiff<'r, PlayerLevel>, - player_location: __sdk::TableAppliedDiff<'r, PlayerLocation>, players_at_level_0: __sdk::TableAppliedDiff<'r, Player>, __unused: std::marker::PhantomData<&'r ()>, } @@ -183,7 +175,6 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> { callbacks.invoke_table_row_callbacks::("nearby_players", &self.nearby_players, event); callbacks.invoke_table_row_callbacks::("player", &self.player, event); callbacks.invoke_table_row_callbacks::("player_level", &self.player_level, event); - callbacks.invoke_table_row_callbacks::("player_location", &self.player_location, event); callbacks.invoke_table_row_callbacks::("players_at_level_0", &self.players_at_level_0, event); } } @@ -910,7 +901,6 @@ impl __sdk::SpacetimeModule for RemoteModule { nearby_players_table::register_table(client_cache); player_table::register_table(client_cache); player_level_table::register_table(client_cache); - player_location_table::register_table(client_cache); players_at_level_0_table::register_table(client_cache); } } 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 deleted file mode 100644 index 97034b47576..00000000000 --- a/sdks/rust/tests/view-client/src/module_bindings/player_location_table.rs +++ /dev/null @@ -1,142 +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. - -#![allow(unused, clippy::all)] -use super::player_location_type::PlayerLocation; -use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; - -/// Table handle for the table `player_location`. -/// -/// Obtain a handle from the [`PlayerLocationTableAccess::player_location`] method on [`super::RemoteTables`], -/// like `ctx.db.player_location()`. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.player_location().on_insert(...)`. -pub struct PlayerLocationTableHandle<'ctx> { - imp: __sdk::TableHandle, - ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the table `player_location`. -/// -/// Implemented for [`super::RemoteTables`]. -pub trait PlayerLocationTableAccess { - #[allow(non_snake_case)] - /// Obtain a [`PlayerLocationTableHandle`], which mediates access to the table `player_location`. - fn player_location(&self) -> PlayerLocationTableHandle<'_>; -} - -impl PlayerLocationTableAccess for super::RemoteTables { - fn player_location(&self) -> PlayerLocationTableHandle<'_> { - PlayerLocationTableHandle { - imp: self.imp.get_table::("player_location"), - ctx: std::marker::PhantomData, - } - } -} - -pub struct PlayerLocationInsertCallbackId(__sdk::CallbackId); -pub struct PlayerLocationDeleteCallbackId(__sdk::CallbackId); - -impl<'ctx> __sdk::Table for PlayerLocationTableHandle<'ctx> { - type Row = PlayerLocation; - type EventContext = super::EventContext; - - fn count(&self) -> u64 { - self.imp.count() - } - fn iter(&self) -> impl Iterator + '_ { - self.imp.iter() - } - - type InsertCallbackId = PlayerLocationInsertCallbackId; - - fn on_insert( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> PlayerLocationInsertCallbackId { - PlayerLocationInsertCallbackId(self.imp.on_insert(Box::new(callback))) - } - - fn remove_on_insert(&self, callback: PlayerLocationInsertCallbackId) { - self.imp.remove_on_insert(callback.0) - } - - type DeleteCallbackId = PlayerLocationDeleteCallbackId; - - fn on_delete( - &self, - callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, - ) -> PlayerLocationDeleteCallbackId { - PlayerLocationDeleteCallbackId(self.imp.on_delete(Box::new(callback))) - } - - fn remove_on_delete(&self, callback: PlayerLocationDeleteCallbackId) { - self.imp.remove_on_delete(callback.0) - } -} - -#[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::TableUpdate<__ws::BsatnFormat>, -) -> __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. -/// -/// Users are encouraged not to explicitly reference this type, -/// but to directly chain method calls, -/// like `ctx.db.player_location().entity_id().find(...)`. -pub struct PlayerLocationEntityIdUnique<'ctx> { - imp: __sdk::UniqueConstraintHandle, - phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, -} - -impl<'ctx> PlayerLocationTableHandle<'ctx> { - /// Get a handle on the `entity_id` unique index on the table `player_location`. - pub fn entity_id(&self) -> PlayerLocationEntityIdUnique<'ctx> { - PlayerLocationEntityIdUnique { - imp: self.imp.get_unique_constraint::("entity_id"), - phantom: std::marker::PhantomData, - } - } -} - -impl<'ctx> PlayerLocationEntityIdUnique<'ctx> { - /// Find the subscribed row whose `entity_id` column value is equal to `col_val`, - /// if such a row is present in the client cache. - pub fn find(&self, col_val: &u64) -> Option { - self.imp.find(col_val) - } -} - -#[allow(non_camel_case_types)] -/// Extension trait for query builder access to the table `PlayerLocation`. -/// -/// Implemented for [`__sdk::QueryTableAccessor`]. -pub trait player_locationQueryTableAccess { - #[allow(non_snake_case)] - /// Get a query builder for the table `PlayerLocation`. - fn player_location(&self) -> __sdk::__query_builder::Table; -} - -impl player_locationQueryTableAccess for __sdk::QueryTableAccessor { - fn player_location(&self) -> __sdk::__query_builder::Table { - __sdk::__query_builder::Table::new("player_location") - } -} From 56a0c783ccfee81e4aa912093cdca6057dce0d95 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Wed, 4 Feb 2026 08:42:18 -0800 Subject: [PATCH 12/18] Regenerated rust test-client again as it seemed to miss something, and fixed up the Unreal tests --- .../test-client/src/module_bindings/mod.rs | 22 +--- .../ModuleBindings/SpacetimeDBClient.g.cpp | 8 -- .../Tables/IndexedTable2Table.g.cpp | 48 -------- .../Tables/IndexedTableTable.g.cpp | 48 -------- .../ModuleBindings/SpacetimeDBClient.g.h | 10 +- .../Tables/IndexedTable2Table.g.h | 101 ----------------- .../Tables/IndexedTableTable.g.h | 101 ----------------- .../Types/EnumWithPayloadType.g.h | 4 +- .../Public/Tests/UmbreallaHeaderaTables.h | 2 - .../ModuleBindings/SpacetimeDBClient.g.cpp | 4 - .../Tables/ScheduledProcTableTable.g.cpp | 47 -------- .../ModuleBindings/SpacetimeDBClient.g.h | 6 +- .../Tables/ScheduledProcTableTable.g.h | 104 ------------------ 13 files changed, 5 insertions(+), 500 deletions(-) delete mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/IndexedTable2Table.g.cpp delete mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/IndexedTableTable.g.cpp delete mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/IndexedTable2Table.g.h delete mode 100644 sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/IndexedTableTable.g.h delete mode 100644 sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/Tables/ScheduledProcTableTable.g.cpp delete mode 100644 sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Tables/ScheduledProcTableTable.g.h 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 88c57803d23..9f081f441fe 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.11.2 (commit 13a0172567170d9b8c87d2aa71de3246c21acb8c). +// This was generated using spacetimedb cli version 1.12.0 (commit 819069447d9034135872ce2bdc28722c4e5e46b6). #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; @@ -52,9 +52,7 @@ pub mod every_primitive_struct_type; pub mod every_vec_struct_type; pub mod indexed_simple_enum_table; pub mod indexed_simple_enum_type; -pub mod indexed_table_2_table; pub mod indexed_table_2_type; -pub mod indexed_table_table; pub mod indexed_table_type; pub mod insert_call_timestamp_reducer; pub mod insert_call_uuid_v_4_reducer; @@ -504,9 +502,7 @@ pub use every_primitive_struct_type::EveryPrimitiveStruct; pub use every_vec_struct_type::EveryVecStruct; pub use indexed_simple_enum_table::*; pub use indexed_simple_enum_type::IndexedSimpleEnum; -pub use indexed_table_2_table::*; pub use indexed_table_2_type::IndexedTable2; -pub use indexed_table_table::*; pub use indexed_table_type::IndexedTable; pub use insert_call_timestamp_reducer::{ insert_call_timestamp, set_flags_for_insert_call_timestamp, InsertCallTimestampCallbackId, @@ -3047,8 +3043,6 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer { pub struct DbUpdate { btree_u_32: __sdk::TableUpdate, indexed_simple_enum: __sdk::TableUpdate, - indexed_table: __sdk::TableUpdate, - indexed_table_2: __sdk::TableUpdate, large_table: __sdk::TableUpdate, one_bool: __sdk::TableUpdate, one_byte_struct: __sdk::TableUpdate, @@ -3168,12 +3162,6 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { "indexed_simple_enum" => db_update .indexed_simple_enum .append(indexed_simple_enum_table::parse_table_update(table_update)?), - "indexed_table" => db_update - .indexed_table - .append(indexed_table_table::parse_table_update(table_update)?), - "indexed_table_2" => db_update - .indexed_table_2 - .append(indexed_table_2_table::parse_table_update(table_update)?), "large_table" => db_update .large_table .append(large_table_table::parse_table_update(table_update)?), @@ -3504,8 +3492,6 @@ impl __sdk::DbUpdate for DbUpdate { diff.btree_u_32 = cache.apply_diff_to_table::("btree_u32", &self.btree_u_32); diff.indexed_simple_enum = cache.apply_diff_to_table::("indexed_simple_enum", &self.indexed_simple_enum); - diff.indexed_table = cache.apply_diff_to_table::("indexed_table", &self.indexed_table); - diff.indexed_table_2 = cache.apply_diff_to_table::("indexed_table_2", &self.indexed_table_2); diff.large_table = cache.apply_diff_to_table::("large_table", &self.large_table); diff.one_bool = cache.apply_diff_to_table::("one_bool", &self.one_bool); diff.one_byte_struct = cache.apply_diff_to_table::("one_byte_struct", &self.one_byte_struct); @@ -3691,8 +3677,6 @@ impl __sdk::DbUpdate for DbUpdate { pub struct AppliedDiff<'r> { btree_u_32: __sdk::TableAppliedDiff<'r, BTreeU32>, indexed_simple_enum: __sdk::TableAppliedDiff<'r, IndexedSimpleEnum>, - indexed_table: __sdk::TableAppliedDiff<'r, IndexedTable>, - indexed_table_2: __sdk::TableAppliedDiff<'r, IndexedTable2>, large_table: __sdk::TableAppliedDiff<'r, LargeTable>, one_bool: __sdk::TableAppliedDiff<'r, OneBool>, one_byte_struct: __sdk::TableAppliedDiff<'r, OneByteStruct>, @@ -3813,8 +3797,6 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> { &self.indexed_simple_enum, event, ); - callbacks.invoke_table_row_callbacks::("indexed_table", &self.indexed_table, event); - callbacks.invoke_table_row_callbacks::("indexed_table_2", &self.indexed_table_2, event); callbacks.invoke_table_row_callbacks::("large_table", &self.large_table, event); callbacks.invoke_table_row_callbacks::("one_bool", &self.one_bool, event); callbacks.invoke_table_row_callbacks::("one_byte_struct", &self.one_byte_struct, event); @@ -4694,8 +4676,6 @@ impl __sdk::SpacetimeModule for RemoteModule { fn register_tables(client_cache: &mut __sdk::ClientCache) { btree_u_32_table::register_table(client_cache); indexed_simple_enum_table::register_table(client_cache); - indexed_table_table::register_table(client_cache); - indexed_table_2_table::register_table(client_cache); large_table_table::register_table(client_cache); one_bool_table::register_table(client_cache); one_byte_struct_table::register_table(client_cache); diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp index 7a640870a2f..119e8f76194 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -6,8 +6,6 @@ #include "BSATN/UEBSATNHelpers.h" #include "ModuleBindings/Tables/BtreeU32Table.g.h" #include "ModuleBindings/Tables/IndexedSimpleEnumTable.g.h" -#include "ModuleBindings/Tables/IndexedTableTable.g.h" -#include "ModuleBindings/Tables/IndexedTable2Table.g.h" #include "ModuleBindings/Tables/LargeTableTable.g.h" #include "ModuleBindings/Tables/OneBoolTable.g.h" #include "ModuleBindings/Tables/OneByteStructTable.g.h" @@ -1325,8 +1323,6 @@ UDbConnection::UDbConnection(const FObjectInitializer& ObjectInitializer) : Supe RegisterTable(TEXT("btree_u32"), Db->BtreeU32); RegisterTable(TEXT("indexed_simple_enum"), Db->IndexedSimpleEnum); - RegisterTable(TEXT("indexed_table"), Db->IndexedTable); - RegisterTable(TEXT("indexed_table_2"), Db->IndexedTable2); RegisterTable(TEXT("large_table"), Db->LargeTable); RegisterTable(TEXT("one_bool"), Db->OneBool); RegisterTable(TEXT("one_byte_struct"), Db->OneByteStruct); @@ -1469,8 +1465,6 @@ void URemoteTables::Initialize() /** Creating tables */ BtreeU32 = NewObject(this); IndexedSimpleEnum = NewObject(this); - IndexedTable = NewObject(this); - IndexedTable2 = NewObject(this); LargeTable = NewObject(this); OneBool = NewObject(this); OneByteStruct = NewObject(this); @@ -1581,8 +1575,6 @@ void URemoteTables::Initialize() /** Initialization */ BtreeU32->PostInitialize(); IndexedSimpleEnum->PostInitialize(); - IndexedTable->PostInitialize(); - IndexedTable2->PostInitialize(); LargeTable->PostInitialize(); OneBool->PostInitialize(); OneByteStruct->PostInitialize(); diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/IndexedTable2Table.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/IndexedTable2Table.g.cpp deleted file mode 100644 index 2f850e9a500..00000000000 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/IndexedTable2Table.g.cpp +++ /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. - -#include "ModuleBindings/Tables/IndexedTable2Table.g.h" -#include "DBCache/UniqueIndex.h" -#include "DBCache/BTreeUniqueIndex.h" -#include "DBCache/ClientCache.h" -#include "DBCache/TableCache.h" - -void UIndexedTable2Table::PostInitialize() -{ - /** Client cache init and setting up indexes*/ - Data = MakeShared>(); - - TSharedPtr> IndexedTable2Table = Data->GetOrAdd(TableName); - - // Register a new multi-key B-Tree index named "player_id_snazz_index" on the IndexedTable2Table. - IndexedTable2Table->AddMultiKeyBTreeIndex>( - TEXT("player_id_snazz_index"), - [](const FIndexedTable2Type& Row) - { - // This tuple is stored in the B-Tree index for fast composite key lookups. - return MakeTuple(Row.PlayerId, Row.PlayerSnazz); - } - ); - - PlayerIdSnazzIndex = NewObject(this); - PlayerIdSnazzIndex->SetCache(IndexedTable2Table); - - /***/ -} - -FTableAppliedDiff UIndexedTable2Table::Update(TArray> InsertsRef, TArray> DeletesRef) -{ - FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); - - return Diff; -} - -int32 UIndexedTable2Table::Count() const -{ - return GetRowCountFromTable(Data, TableName); -} - -TArray UIndexedTable2Table::Iter() const -{ - return GetAllRowsFromTable(Data, TableName); -} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/IndexedTableTable.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/IndexedTableTable.g.cpp deleted file mode 100644 index 5f4755f7b1b..00000000000 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/Tables/IndexedTableTable.g.cpp +++ /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. - -#include "ModuleBindings/Tables/IndexedTableTable.g.h" -#include "DBCache/UniqueIndex.h" -#include "DBCache/BTreeUniqueIndex.h" -#include "DBCache/ClientCache.h" -#include "DBCache/TableCache.h" - -void UIndexedTableTable::PostInitialize() -{ - /** Client cache init and setting up indexes*/ - Data = MakeShared>(); - - TSharedPtr> IndexedTableTable = Data->GetOrAdd(TableName); - - // Register a new multi-key B-Tree index named "player_id" on the IndexedTableTable. - IndexedTableTable->AddMultiKeyBTreeIndex>( - TEXT("player_id"), - [](const FIndexedTableType& Row) - { - // This tuple is stored in the B-Tree index for fast composite key lookups. - return MakeTuple(Row.PlayerId); - } - ); - - PlayerId = NewObject(this); - PlayerId->SetCache(IndexedTableTable); - - /***/ -} - -FTableAppliedDiff UIndexedTableTable::Update(TArray> InsertsRef, TArray> DeletesRef) -{ - FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); - - return Diff; -} - -int32 UIndexedTableTable::Count() const -{ - return GetRowCountFromTable(Data, TableName); -} - -TArray UIndexedTableTable::Iter() const -{ - return GetAllRowsFromTable(Data, TableName); -} diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h index d87a51e16d1..ef4c228a95b 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/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.11.2 (commit e090367c50e718fe19fbf827206a7516502288a9). +// This was generated using spacetimedb cli version 1.12.0 (commit 819069447d9034135872ce2bdc28722c4e5e46b6). #pragma once #include "CoreMinimal.h" @@ -249,8 +249,6 @@ class USubscriptionHandle; /** Forward declaration for tables */ class UBtreeU32Table; class UIndexedSimpleEnumTable; -class UIndexedTableTable; -class UIndexedTable2Table; class ULargeTableTable; class UOneBoolTable; class UOneByteStructTable; @@ -7597,12 +7595,6 @@ class TESTCLIENT_API URemoteTables : public UObject UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") UIndexedSimpleEnumTable* IndexedSimpleEnum; - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UIndexedTableTable* IndexedTable; - - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UIndexedTable2Table* IndexedTable2; - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") ULargeTableTable* LargeTable; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/IndexedTable2Table.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/IndexedTable2Table.g.h deleted file mode 100644 index c943ba5e3bd..00000000000 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/IndexedTable2Table.g.h +++ /dev/null @@ -1,101 +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 "Types/Builtins.h" -#include "ModuleBindings/Types/IndexedTable2Type.g.h" -#include "Tables/RemoteTable.h" -#include "DBCache/WithBsatn.h" -#include "DBCache/TableHandle.h" -#include "DBCache/TableCache.h" -#include "IndexedTable2Table.g.generated.h" - -UCLASS(Blueprintable) -class UIndexedTable2PlayerIdSnazzIndexIndex : public UObject -{ - GENERATED_BODY() - -public: - TArray Filter(const uint32& PlayerId, const float& PlayerSnazz) const - { - TArray OutResults; - - LocalCache->FindByMultiKeyBTreeIndex>( - OutResults, - TEXT("player_id_snazz_index"), - MakeTuple(PlayerId, PlayerSnazz) - ); - - return OutResults; - } - - void SetCache(TSharedPtr> InCache) - { - LocalCache = InCache; - } - -private: - // NOTE: Not exposed to Blueprint because some parameter types are not Blueprint-compatible - void FilterPlayerIdPlayerSnazz(TArray& OutResults, const uint32& PlayerId, const float& PlayerSnazz) - { - OutResults = Filter(PlayerId, PlayerSnazz); - } - - TSharedPtr> LocalCache; -}; - -UCLASS(BlueprintType) -class TESTCLIENT_API UIndexedTable2Table : public URemoteTable -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly) - UIndexedTable2PlayerIdSnazzIndexIndex* PlayerIdSnazzIndex; - - void PostInitialize(); - - /** Update function for indexed_table_2 table*/ - FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); - - /** Number of subscribed rows currently in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - int32 Count() const; - - /** Return all subscribed rows in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - TArray Iter() const; - - // Table Events - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnIndexedTable2Insert, - const FEventContext&, Context, - const FIndexedTable2Type&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( - FOnIndexedTable2Update, - const FEventContext&, Context, - const FIndexedTable2Type&, OldRow, - const FIndexedTable2Type&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnIndexedTable2Delete, - const FEventContext&, Context, - const FIndexedTable2Type&, DeletedRow); - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnIndexedTable2Insert OnInsert; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnIndexedTable2Update OnUpdate; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnIndexedTable2Delete OnDelete; - -private: - const FString TableName = TEXT("indexed_table_2"); - - TSharedPtr> Data; -}; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/IndexedTableTable.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/IndexedTableTable.g.h deleted file mode 100644 index 0280e19a2c1..00000000000 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Tables/IndexedTableTable.g.h +++ /dev/null @@ -1,101 +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 "Types/Builtins.h" -#include "ModuleBindings/Types/IndexedTableType.g.h" -#include "Tables/RemoteTable.h" -#include "DBCache/WithBsatn.h" -#include "DBCache/TableHandle.h" -#include "DBCache/TableCache.h" -#include "IndexedTableTable.g.generated.h" - -UCLASS(Blueprintable) -class UIndexedTablePlayerIdIndex : public UObject -{ - GENERATED_BODY() - -public: - TArray Filter(const uint32& PlayerId) const - { - TArray OutResults; - - LocalCache->FindByMultiKeyBTreeIndex>( - OutResults, - TEXT("player_id"), - MakeTuple(PlayerId) - ); - - return OutResults; - } - - void SetCache(TSharedPtr> InCache) - { - LocalCache = InCache; - } - -private: - // NOTE: Not exposed to Blueprint because some parameter types are not Blueprint-compatible - void FilterPlayerId(TArray& OutResults, const uint32& PlayerId) - { - OutResults = Filter(PlayerId); - } - - TSharedPtr> LocalCache; -}; - -UCLASS(BlueprintType) -class TESTCLIENT_API UIndexedTableTable : public URemoteTable -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly) - UIndexedTablePlayerIdIndex* PlayerId; - - void PostInitialize(); - - /** Update function for indexed_table table*/ - FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); - - /** Number of subscribed rows currently in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - int32 Count() const; - - /** Return all subscribed rows in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - TArray Iter() const; - - // Table Events - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnIndexedTableInsert, - const FEventContext&, Context, - const FIndexedTableType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( - FOnIndexedTableUpdate, - const FEventContext&, Context, - const FIndexedTableType&, OldRow, - const FIndexedTableType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnIndexedTableDelete, - const FEventContext&, Context, - const FIndexedTableType&, DeletedRow); - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnIndexedTableInsert OnInsert; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnIndexedTableUpdate OnUpdate; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnIndexedTableDelete OnDelete; - -private: - const FString TableName = TEXT("indexed_table"); - - TSharedPtr> Data; -}; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h index 4557262a45c..ecd68f0d197 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h @@ -4,9 +4,9 @@ #pragma once #include "CoreMinimal.h" #include "BSATN/UESpacetimeDB.h" -#include "Kismet/BlueprintFunctionLibrary.h" #include "Types/Builtins.h" #include "ModuleBindings/Types/SimpleEnumType.g.h" +#include "Kismet/BlueprintFunctionLibrary.h" #include "EnumWithPayloadType.g.generated.h" UENUM(BlueprintType) @@ -46,7 +46,7 @@ struct TESTCLIENT_API FEnumWithPayloadType public: FEnumWithPayloadType() = default; - TVariant, FSpacetimeDBTimestamp, FSpacetimeDBUInt256, TArray, uint8, int64, int16, uint32, uint64, FSpacetimeDBInt256, int32, uint16, FSpacetimeDBIdentity, TArray, int8, float, FSpacetimeDBConnectionId, TArray, FSpacetimeDBInt128, bool> MessageData; + TVariant, FSpacetimeDBUuid, FSpacetimeDBInt128, FString, int32, TArray, TArray, uint16, uint64, int64, float, bool, FSpacetimeDBUInt256, FSpacetimeDBUInt128, FSpacetimeDBConnectionId, uint8, FSpacetimeDBIdentity, uint32, double, FSpacetimeDBTimestamp, int8, FSpacetimeDBInt256, int16, TArray> MessageData; UPROPERTY(BlueprintReadOnly) EEnumWithPayloadTag Tag = static_cast(0); diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/UmbreallaHeaderaTables.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/UmbreallaHeaderaTables.h index f79650429f5..331e301a2da 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/UmbreallaHeaderaTables.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/UmbreallaHeaderaTables.h @@ -1,8 +1,6 @@ //Include Tables #include "ModuleBindings/Tables/BtreeU32Table.g.h" #include "ModuleBindings/Tables/IndexedSimpleEnumTable.g.h" -#include "ModuleBindings/Tables/IndexedTable2Table.g.h" -#include "ModuleBindings/Tables/IndexedTableTable.g.h" #include "ModuleBindings/Tables/LargeTableTable.g.h" #include "ModuleBindings/Tables/OneBoolTable.g.h" #include "ModuleBindings/Tables/OneByteStructTable.g.h" diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp index 10d056bf5da..ee361b58397 100644 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp +++ b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -7,7 +7,6 @@ #include "ModuleBindings/Tables/MyTableTable.g.h" #include "ModuleBindings/Tables/PkUuidTable.g.h" #include "ModuleBindings/Tables/ProcInsertsIntoTable.g.h" -#include "ModuleBindings/Tables/ScheduledProcTableTable.g.h" static FReducer DecodeReducer(const FReducerEvent& Event) { @@ -39,7 +38,6 @@ UDbConnection::UDbConnection(const FObjectInitializer& ObjectInitializer) : Supe RegisterTable(TEXT("my_table"), Db->MyTable); RegisterTable(TEXT("pk_uuid"), Db->PkUuid); RegisterTable(TEXT("proc_inserts_into"), Db->ProcInsertsInto); - RegisterTable(TEXT("scheduled_proc_table"), Db->ScheduledProcTable); } FContextBase::FContextBase(UDbConnection* InConn) @@ -78,14 +76,12 @@ void URemoteTables::Initialize() MyTable = NewObject(this); PkUuid = NewObject(this); ProcInsertsInto = NewObject(this); - ScheduledProcTable = NewObject(this); /**/ /** Initialization */ MyTable->PostInitialize(); PkUuid->PostInitialize(); ProcInsertsInto->PostInitialize(); - ScheduledProcTable->PostInitialize(); /**/ } diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/Tables/ScheduledProcTableTable.g.cpp b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/Tables/ScheduledProcTableTable.g.cpp deleted file mode 100644 index e6f6502d7a7..00000000000 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/Tables/ScheduledProcTableTable.g.cpp +++ /dev/null @@ -1,47 +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. - -#include "ModuleBindings/Tables/ScheduledProcTableTable.g.h" -#include "DBCache/UniqueIndex.h" -#include "DBCache/BTreeUniqueIndex.h" -#include "DBCache/ClientCache.h" -#include "DBCache/TableCache.h" - -void UScheduledProcTableTable::PostInitialize() -{ - /** Client cache init and setting up indexes*/ - Data = MakeShared>(); - - TSharedPtr> ScheduledProcTableTable = Data->GetOrAdd(TableName); - ScheduledProcTableTable->AddUniqueConstraint("scheduled_id", [](const FScheduledProcTableType& Row) -> const uint64& { - return Row.ScheduledId; }); - - ScheduledId = NewObject(this); - ScheduledId->SetCache(ScheduledProcTableTable); - - /***/ -} - -FTableAppliedDiff UScheduledProcTableTable::Update(TArray> InsertsRef, TArray> DeletesRef) -{ - FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); - - Diff.DeriveUpdatesByPrimaryKey( - [](const FScheduledProcTableType& Row) - { - return Row.ScheduledId; - } - ); - - return Diff; -} - -int32 UScheduledProcTableTable::Count() const -{ - return GetRowCountFromTable(Data, TableName); -} - -TArray UScheduledProcTableTable::Iter() const -{ - return GetAllRowsFromTable(Data, TableName); -} diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h index c37059835d5..700fdb983f8 100644 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/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.11.2 (commit e090367c50e718fe19fbf827206a7516502288a9). +// This was generated using spacetimedb cli version 1.12.0 (commit 819069447d9034135872ce2bdc28722c4e5e46b6). #pragma once #include "CoreMinimal.h" @@ -44,7 +44,6 @@ class USubscriptionHandle; class UMyTableTable; class UPkUuidTable; class UProcInsertsIntoTable; -class UScheduledProcTableTable; /***/ // Delegates using the generated connection type. These wrap the base @@ -983,9 +982,6 @@ class TESTPROCCLIENT_API URemoteTables : public UObject UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") UProcInsertsIntoTable* ProcInsertsInto; - UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UScheduledProcTableTable* ScheduledProcTable; - }; // RemoteReducers class diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Tables/ScheduledProcTableTable.g.h b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Tables/ScheduledProcTableTable.g.h deleted file mode 100644 index b3838b0c979..00000000000 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Tables/ScheduledProcTableTable.g.h +++ /dev/null @@ -1,104 +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 "Types/Builtins.h" -#include "ModuleBindings/Types/ScheduledProcTableType.g.h" -#include "Tables/RemoteTable.h" -#include "DBCache/WithBsatn.h" -#include "DBCache/TableHandle.h" -#include "DBCache/TableCache.h" -#include "ScheduledProcTableTable.g.generated.h" - -UCLASS(Blueprintable) -class TESTPROCCLIENT_API UScheduledProcTableScheduledIdUniqueIndex : public UObject -{ - GENERATED_BODY() - -private: - // Declare an instance of your templated helper. - // It's private because the UObject wrapper will expose its functionality. - FUniqueIndexHelper> ScheduledIdIndexHelper; - -public: - UScheduledProcTableScheduledIdUniqueIndex() - // Initialize the helper with the specific unique index name - : ScheduledIdIndexHelper("scheduled_id") { - } - - /** - * Finds a ScheduledProcTable by their unique scheduledid. - * @param Key The scheduledid to search for. - * @return The found FScheduledProcTableType, or a default-constructed FScheduledProcTableType if not found. - */ - // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible - FScheduledProcTableType Find(uint64 Key) - { - // Simply delegate the call to the internal helper - return ScheduledIdIndexHelper.FindUniqueIndex(Key); - } - - // A public setter to provide the cache to the helper after construction - // This is a common pattern when the cache might be created or provided by another system. - void SetCache(TSharedPtr> InScheduledProcTableCache) - { - ScheduledIdIndexHelper.Cache = InScheduledProcTableCache; - } -}; -/***/ - -UCLASS(BlueprintType) -class TESTPROCCLIENT_API UScheduledProcTableTable : public URemoteTable -{ - GENERATED_BODY() - -public: - UPROPERTY(BlueprintReadOnly) - UScheduledProcTableScheduledIdUniqueIndex* ScheduledId; - - void PostInitialize(); - - /** Update function for scheduled_proc_table table*/ - FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); - - /** Number of subscribed rows currently in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - int32 Count() const; - - /** Return all subscribed rows in the cache */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") - TArray Iter() const; - - // Table Events - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnScheduledProcTableInsert, - const FEventContext&, Context, - const FScheduledProcTableType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( - FOnScheduledProcTableUpdate, - const FEventContext&, Context, - const FScheduledProcTableType&, OldRow, - const FScheduledProcTableType&, NewRow); - - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( - FOnScheduledProcTableDelete, - const FEventContext&, Context, - const FScheduledProcTableType&, DeletedRow); - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnScheduledProcTableInsert OnInsert; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnScheduledProcTableUpdate OnUpdate; - - UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") - FOnScheduledProcTableDelete OnDelete; - -private: - const FString TableName = TEXT("scheduled_proc_table"); - - TSharedPtr> Data; -}; From 750ae7d43e2a125f0a36b184dba0a3915ca32fba Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Wed, 4 Feb 2026 17:42:52 -0800 Subject: [PATCH 13/18] [2.0 Breaking] Make `connection_id` a method on `ReducerContext` (#4200) # Description of Changes Same changes as https://github.com/clockworklabs/SpacetimeDB/pull/4101 but for `connection_id`. # API and ABI breaking changes API Breaking # Expected complexity level and risk 1 # Testing Pure refactor. Tests and docs have been updated, but no new tests added. --- crates/bindings/src/lib.rs | 19 +++++++++-- .../00100-databases/00500-cheat-sheet.md | 2 +- .../00300-reducers/00500-lifecycle.md | 14 ++++---- docs/static/llms.md | 34 +++++++++---------- modules/sdk-test/src/lib.rs | 8 ++--- smoketests/tests/zz_docker.py | 5 +-- 6 files changed, 49 insertions(+), 33 deletions(-) diff --git a/crates/bindings/src/lib.rs b/crates/bindings/src/lib.rs index ebe5f7075b3..ab8da2c663c 100644 --- a/crates/bindings/src/lib.rs +++ b/crates/bindings/src/lib.rs @@ -938,7 +938,7 @@ pub struct ReducerContext { /// /// Will be `None` for certain reducers invoked automatically by the host, /// including `init` and scheduled reducers. - pub connection_id: Option, + connection_id: Option, sender_auth: AuthCtx, @@ -1024,6 +1024,14 @@ impl ReducerContext { self.sender } + /// The `ConnectionId` of the client that invoked the reducer. + /// + /// Will be `None` for certain reducers invoked automatically by the host, + /// including `init` and scheduled reducers. + pub fn connection_id(&self) -> Option { + self.connection_id + } + /// Returns the authorization information for the caller of this reducer. pub fn sender_auth(&self) -> &AuthCtx { &self.sender_auth @@ -1142,7 +1150,7 @@ pub struct ProcedureContext { /// The `ConnectionId` of the client that invoked the procedure. /// /// Will be `None` for certain scheduled procedures. - pub connection_id: Option, + connection_id: Option, /// Methods for performing HTTP requests. pub http: crate::http::HttpClient, @@ -1178,6 +1186,13 @@ impl ProcedureContext { self.sender } + /// The `ConnectionId` of the client that invoked the procedure. + /// + /// Will be `None` for certain scheduled procedures. + pub fn connection_id(&self) -> Option { + self.connection_id + } + /// Read the current module's [`Identity`]. pub fn identity(&self) -> Identity { // Hypothetically, we *could* read the module identity out of the system tables. diff --git a/docs/docs/00200-core-concepts/00100-databases/00500-cheat-sheet.md b/docs/docs/00200-core-concepts/00100-databases/00500-cheat-sheet.md index c7c8eafee96..d1e2624b343 100644 --- a/docs/docs/00200-core-concepts/00100-databases/00500-cheat-sheet.md +++ b/docs/docs/00200-core-concepts/00100-databases/00500-cheat-sheet.md @@ -523,7 +523,7 @@ ctx.Rng // Random number generator ```rust ctx.db // Database access ctx.sender() // Identity of caller -ctx.connection_id // Option +ctx.connection_id() // Option ctx.timestamp // Timestamp ctx.identity() // Module's identity ctx.rng() // Random number generator diff --git a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00500-lifecycle.md b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00500-lifecycle.md index 605ad09dd09..e9c6b1cff61 100644 --- a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00500-lifecycle.md +++ b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00500-lifecycle.md @@ -133,8 +133,8 @@ public static void OnConnect(ReducerContext ctx) pub fn on_connect(ctx: &ReducerContext) -> Result<(), String> { log::info!("Client connected: {}", ctx.sender()); - // ctx.connection_id is guaranteed to be Some(...) - let conn_id = ctx.connection_id.unwrap(); + // ctx.connection_id() is guaranteed to be Some(...) + let conn_id = ctx.connection_id().unwrap(); // Initialize client session ctx.db.sessions().try_insert(Session { @@ -152,7 +152,7 @@ pub fn on_connect(ctx: &ReducerContext) -> Result<(), String> { The `client_connected` reducer: - Cannot take arguments beyond `ReducerContext` -- `ctx.connection_id` is guaranteed to be present +- `ctx.connection_id()` is guaranteed to be present - Failure disconnects the client - Runs for each distinct connection (WebSocket, HTTP call) @@ -200,8 +200,8 @@ public static void OnDisconnect(ReducerContext ctx) pub fn on_disconnect(ctx: &ReducerContext) -> Result<(), String> { log::info!("Client disconnected: {}", ctx.sender()); - // ctx.connection_id is guaranteed to be Some(...) - let conn_id = ctx.connection_id.unwrap(); + // ctx.connection_id() is guaranteed to be Some(...) + let conn_id = ctx.connection_id().unwrap(); // Clean up client session ctx.db.sessions().connection_id().delete(&conn_id); @@ -215,7 +215,7 @@ pub fn on_disconnect(ctx: &ReducerContext) -> Result<(), String> { The `client_disconnected` reducer: - Cannot take arguments beyond `ReducerContext` -- `ctx.connection_id` is guaranteed to be present +- `ctx.connection_id()` is guaranteed to be present - Failure is logged but doesn't prevent disconnection - Runs when connection ends (close, timeout, error) @@ -231,5 +231,5 @@ Reducers can be triggered at specific times using schedule tables. See [Schedule :::info Scheduled Reducer Context Scheduled reducer calls originate from SpacetimeDB itself, not from a client. Therefore: - `ctx.sender()` will be the module's own identity -- `ctx.connection_id` will be `None`/`null`/`undefined` +- `ctx.connection_id()` will be `None`/`null`/`undefined` ::: diff --git a/docs/static/llms.md b/docs/static/llms.md index f35907bf85d..c7144f9f20f 100644 --- a/docs/static/llms.md +++ b/docs/static/llms.md @@ -434,7 +434,7 @@ pub struct PlayerSessionData { fn example_reducer(ctx: &spacetimedb::ReducerContext) { // Reducers interact with the specific table handles: let session = PlayerSessionData { - player_id: ctx.sender, // Example: Use sender identity + player_id: ctx.sender(), // Example: Use sender identity session_id: 0, // Assuming auto_inc last_activity: ctx.timestamp, }; @@ -446,12 +446,12 @@ fn example_reducer(ctx: &spacetimedb::ReducerContext) { } // Find a player in the 'players_in_lobby' table by primary key - if let Some(lobby_player) = ctx.db.players_in_lobby().player_id().find(&ctx.sender) { + if let Some(lobby_player) = ctx.db.players_in_lobby().player_id().find(&ctx.sender()) { spacetimedb::log::info!("Player {} found in lobby.", lobby_player.player_id); } // Delete from the 'logged_in_players' table using the PK index - ctx.db.logged_in_players().player_id().delete(&ctx.sender); + ctx.db.logged_in_players().player_id().delete(&ctx.sender()); } ``` @@ -499,7 +499,7 @@ use spacetimedb::{reducer, ReducerContext, Table, Identity, Timestamp, log}; // Example: Basic reducer to set a user's name #[reducer] pub fn set_name(ctx: &ReducerContext, name: String) -> Result<(), String> { - let sender_id = ctx.sender; + let sender_id = ctx.sender(); let name = validate_name(name)?; // Use helper for validation // Find the user row by primary key @@ -519,13 +519,13 @@ pub fn set_name(ctx: &ReducerContext, name: String) -> Result<(), String> { #[reducer] pub fn send_message(ctx: &ReducerContext, text: String) -> Result<(), String> { let text = validate_message(text)?; // Use helper for validation - log::info!("User {} sent message: {}", ctx.sender, text); + log::info!("User {} sent message: {}", ctx.sender(), text); // Insert a new row into the Message table // Note: id is auto_inc, so we provide 0. insert() panics on constraint violation. let new_message = Message { id: 0, - sender: ctx.sender, + sender: ctx.sender(), text, sent: ctx.timestamp, }; @@ -567,8 +567,8 @@ Reducers can indicate failure either by returning `Err` from a function with a ` Special reducers handle specific events: - `#[reducer(init)]`: Runs once when the module is first published **and** any time the database is manually cleared (e.g., via `spacetime publish -c` or `spacetime server clear`). Failure prevents publishing or clearing. Often used for initial data setup. -- `#[reducer(client_connected)]`: Runs when any distinct client connection (e.g., WebSocket, HTTP call) is established. Failure disconnects the client. `ctx.connection_id` is guaranteed to be `Some(...)` within this reducer. -- `#[reducer(client_disconnected)]`: Runs when any distinct client connection terminates. Failure is logged but does not prevent disconnection. `ctx.connection_id` is guaranteed to be `Some(...)` within this reducer. +- `#[reducer(client_connected)]`: Runs when any distinct client connection (e.g., WebSocket, HTTP call) is established. Failure disconnects the client. `ctx.connection_id()` is guaranteed to be `Some(...)` within this reducer. +- `#[reducer(client_disconnected)]`: Runs when any distinct client connection terminates. Failure is logged but does not prevent disconnection. `ctx.connection_id()` is guaranteed to be `Some(...)` within this reducer. These reducers cannot take arguments beyond `&ReducerContext`. @@ -611,14 +611,14 @@ pub fn initialize_database(ctx: &ReducerContext) { // Example client_connected reducer #[reducer(client_connected)] pub fn handle_connect(ctx: &ReducerContext) { - log::info!("Client connected: {}, Connection ID: {:?}", ctx.sender, ctx.connection_id); + log::info!("Client connected: {}, Connection ID: {:?}", ctx.sender(), ctx.connection_id()); // ... setup initial state for ctx.sender ... } // Example client_disconnected reducer #[reducer(client_disconnected)] pub fn handle_disconnect(ctx: &ReducerContext) { - log::info!("Client disconnected: {}, Connection ID: {:?}", ctx.sender, ctx.connection_id); + log::info!("Client disconnected: {}, Connection ID: {:?}", ctx.sender(), ctx.connection_id()); // ... cleanup state for ctx.sender ... } ``` @@ -800,7 +800,7 @@ struct SendMessageSchedule { #[reducer] fn send_message(ctx: &ReducerContext, args: SendMessageSchedule) -> Result<(), String> { // Security check is important! - if ctx.sender != ctx.identity() { + if ctx.sender() != ctx.identity() { return Err("Reducer `send_message` may not be invoked by clients, only via scheduling.".into()); } @@ -851,7 +851,7 @@ Refer to the [official Rust Module SDK documentation on docs.rs](https://docs.rs - **Best-Effort Scheduling:** Scheduled reducers are called on a best-effort basis and may be slightly delayed in their execution when a database is under heavy load. -- **Restricting Access (Security):** Scheduled reducers are normal reducers and _can_ still be called directly by clients. If a scheduled reducer should _only_ be called by the scheduler, it is crucial to begin the reducer with a check comparing the caller's identity (`ctx.sender`) to the module's own identity (`ctx.identity()`). +- **Restricting Access (Security):** Scheduled reducers are normal reducers and _can_ still be called directly by clients. If a scheduled reducer should _only_ be called by the scheduler, it is crucial to begin the reducer with a check comparing the caller's identity (`ctx.sender()`) to the module's own identity (`ctx.identity()`). ```rust use spacetimedb::{reducer, ReducerContext}; @@ -860,7 +860,7 @@ Refer to the [official Rust Module SDK documentation on docs.rs](https://docs.rs #[reducer] fn my_scheduled_reducer(ctx: &ReducerContext, args: MyScheduleArgs) -> Result<(), String> { - if ctx.sender != ctx.identity() { + if ctx.sender() != ctx.identity() { return Err("Reducer `my_scheduled_reducer` may not be invoked by clients, only via scheduling.".into()); } // ... Reducer body proceeds only if called by scheduler ... @@ -869,7 +869,7 @@ Refer to the [official Rust Module SDK documentation on docs.rs](https://docs.rs ``` :::info Scheduled Reducers and Connections -Scheduled reducer calls originate from the SpacetimeDB scheduler itself, not from an external client connection. Therefore, within a scheduled reducer, `ctx.sender` will be the module's own identity, and `ctx.connection_id` will be `None`. +Scheduled reducer calls originate from the SpacetimeDB scheduler itself, not from an external client connection. Therefore, within a scheduled reducer, `ctx.sender()` will be the module's own identity, and `ctx.connection_id()` will be `None`. ::: #### View Functions @@ -922,7 +922,7 @@ pub struct PlayerAndLevel { // Returns Option for at-most-one row #[view(name = my_player, public)] fn my_player(ctx: &ViewContext) -> Option { - ctx.db.player().identity().find(ctx.sender) + ctx.db.player().identity().find(ctx.sender()) } // View that returns all players at a specific level (same for all callers) @@ -953,7 +953,7 @@ fn players_for_level(ctx: &AnonymousViewContext) -> Vec { Views use one of two context types: -- **`ViewContext`**: Provides access to the caller's `Identity` through `ctx.sender`. Use this when the view depends on who is querying it (e.g., "get my player"). +- **`ViewContext`**: Provides access to the caller's `Identity` through `ctx.sender()`. Use this when the view depends on who is querying it (e.g., "get my player"). - **`AnonymousViewContext`**: Does not provide caller information. Use this when the view produces the same results regardless of who queries it (e.g., "get top 10 players"). Both contexts provide read-only access to tables and indexes through `ctx.db`. @@ -984,7 +984,7 @@ use spacetimedb::{view, ViewContext, Query}; fn my_messages(ctx: &ViewContext) -> Query { // Build a typed query using the query builder ctx.db.message() - .filter(|cols| cols.sender.eq(ctx.sender)) + .filter(|cols| cols.sender.eq(ctx.sender())) .build() } diff --git a/modules/sdk-test/src/lib.rs b/modules/sdk-test/src/lib.rs index 0a6aed56358..26c19064d3f 100644 --- a/modules/sdk-test/src/lib.rs +++ b/modules/sdk-test/src/lib.rs @@ -664,7 +664,7 @@ fn insert_caller_pk_identity(ctx: &ReducerContext, data: i32) -> anyhow::Result< #[spacetimedb::reducer] fn insert_caller_one_connection_id(ctx: &ReducerContext) -> anyhow::Result<()> { ctx.db.one_connection_id().insert(OneConnectionId { - a: ctx.connection_id.context("No connection id in reducer context")?, + a: ctx.connection_id().context("No connection id in reducer context")?, }); Ok(()) } @@ -672,7 +672,7 @@ fn insert_caller_one_connection_id(ctx: &ReducerContext) -> anyhow::Result<()> { #[spacetimedb::reducer] fn insert_caller_vec_connection_id(ctx: &ReducerContext) -> anyhow::Result<()> { ctx.db.vec_connection_id().insert(VecConnectionId { - a: vec![ctx.connection_id.context("No connection id in reducer context")?], + a: vec![ctx.connection_id().context("No connection id in reducer context")?], }); Ok(()) } @@ -680,7 +680,7 @@ fn insert_caller_vec_connection_id(ctx: &ReducerContext) -> anyhow::Result<()> { #[spacetimedb::reducer] fn insert_caller_unique_connection_id(ctx: &ReducerContext, data: i32) -> anyhow::Result<()> { ctx.db.unique_connection_id().insert(UniqueConnectionId { - a: ctx.connection_id.context("No connection id in reducer context")?, + a: ctx.connection_id().context("No connection id in reducer context")?, data, }); Ok(()) @@ -689,7 +689,7 @@ fn insert_caller_unique_connection_id(ctx: &ReducerContext, data: i32) -> anyhow #[spacetimedb::reducer] fn insert_caller_pk_connection_id(ctx: &ReducerContext, data: i32) -> anyhow::Result<()> { ctx.db.pk_connection_id().insert(PkConnectionId { - a: ctx.connection_id.context("No connection id in reducer context")?, + a: ctx.connection_id().context("No connection id in reducer context")?, data, }); Ok(()) diff --git a/smoketests/tests/zz_docker.py b/smoketests/tests/zz_docker.py index bcfdef16a73..71ddf173093 100644 --- a/smoketests/tests/zz_docker.py +++ b/smoketests/tests/zz_docker.py @@ -113,14 +113,15 @@ class DockerRestartAutoDisconnect(Smoketest): fn on_connect(ctx: &ReducerContext) { ctx.db.connected_client().insert(ConnectedClient { identity: ctx.sender(), - connection_id: ctx.connection_id.expect("sender connection id unset"), + connection_id: ctx.connection_id().expect("sender connection id unset"), }); } #[spacetimedb::reducer(client_disconnected)] fn on_disconnect(ctx: &ReducerContext) { let sender_identity = &ctx.sender(); - let sender_connection_id = ctx.connection_id.as_ref().expect("sender connection id unset"); + let connection_id = ctx.connection_id(); + let sender_connection_id = connection_id.as_ref().expect("sender connection id unset"); let match_client = |row: &ConnectedClient| { &row.identity == sender_identity && &row.connection_id == sender_connection_id }; From 76eeda315a81d76c8c4e7dd593ef4b1325d63c85 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Thu, 5 Feb 2026 19:15:44 -0800 Subject: [PATCH 14/18] Added output to list private tables not included during the generate command --- crates/cli/src/subcommands/generate.rs | 10 +++++++++- crates/codegen/src/lib.rs | 1 + crates/codegen/src/util.rs | 10 ++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/cli/src/subcommands/generate.rs b/crates/cli/src/subcommands/generate.rs index 4e6fb5ec124..2cd26885dc0 100644 --- a/crates/cli/src/subcommands/generate.rs +++ b/crates/cli/src/subcommands/generate.rs @@ -5,7 +5,9 @@ use clap::parser::ValueSource; use clap::Arg; use clap::ArgAction::Set; use fs_err as fs; -use spacetimedb_codegen::{generate, Csharp, Lang, OutputFile, Rust, TypeScript, UnrealCpp, AUTO_GENERATED_PREFIX}; +use spacetimedb_codegen::{ + generate, private_table_names, Csharp, Lang, OutputFile, Rust, TypeScript, UnrealCpp, AUTO_GENERATED_PREFIX, +}; use spacetimedb_lib::de::serde::DeserializeWrapper; use spacetimedb_lib::{sats, RawModuleDef}; use spacetimedb_schema; @@ -171,6 +173,12 @@ pub async fn exec_ex( extract_descriptions(&path).context("could not extract schema")? }; + // TODO: Update this to work with --include-private once that flag exists. + let private_tables = private_table_names(&module); + if !private_tables.is_empty() { + println!("Skipping private tables during codegen: {}.", private_tables.join(", ")); + } + fs::create_dir_all(out_dir)?; let mut paths = BTreeSet::new(); diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 20ce59d83ae..eea3a51a727 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -11,6 +11,7 @@ pub use self::csharp::Csharp; pub use self::rust::Rust; pub use self::typescript::TypeScript; pub use self::unrealcpp::UnrealCpp; +pub use util::private_table_names; pub use util::AUTO_GENERATED_PREFIX; pub fn generate(module: &ModuleDef, lang: &dyn Lang) -> Vec { diff --git a/crates/codegen/src/util.rs b/crates/codegen/src/util.rs index 8607b4c92e0..fbde0db5e27 100644 --- a/crates/codegen/src/util.rs +++ b/crates/codegen/src/util.rs @@ -119,6 +119,16 @@ pub(super) fn iter_tables(module: &ModuleDef, include_private: bool) -> impl Ite .sorted_by_key(|table| &table.name) } +/// Return the names of all private tables, in alphabetical order. +pub fn private_table_names(module: &ModuleDef) -> Vec { + module + .tables() + .filter(|table| table.table_access == TableAccess::Private) + .sorted_by_key(|table| &table.name) + .map(|table| table.name.to_string()) + .collect() +} + /// Iterate over all the [`ViewDef`]s defined by the module, in alphabetical order by name. /// /// Sorting is necessary to have deterministic reproducible codegen. From b549a7a220771f0a8ffd71305c74bcffdb0ed7df Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Fri, 6 Feb 2026 10:11:43 -0800 Subject: [PATCH 15/18] Updated snaps from merge --- .../snapshots/codegen__codegen_csharp.snap | 130 +--------- .../snapshots/codegen__codegen_rust.snap | 229 +----------------- .../codegen__codegen_typescript.snap | 42 +--- 3 files changed, 3 insertions(+), 398 deletions(-) diff --git a/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap b/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap index 023a7eb3cef..ea9e3ca4a8f 100644 --- a/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap +++ b/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap @@ -1,5 +1,6 @@ --- source: crates/codegen/tests/codegen.rs +assertion_line: 37 expression: outfiles --- "Procedures/GetMySchemaViaHttp.g.cs" = ''' @@ -569,56 +570,6 @@ namespace SpacetimeDB } } ''' -"Reducers/ClientConnected.g.cs" = ''' -// 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 -{ - 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 => "client_connected"; - } - } -} -''' "Reducers/DeletePlayer.g.cs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. @@ -964,81 +915,6 @@ namespace SpacetimeDB } } ''' -"Reducers/RepeatingTest.g.cs" = ''' -// 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 -{ - public sealed partial class RemoteReducers : RemoteBase - { - public delegate void RepeatingTestHandler(ReducerEventContext ctx, SpacetimeDB.RepeatingTestArg arg); - public event RepeatingTestHandler? OnRepeatingTest; - - public void RepeatingTest(SpacetimeDB.RepeatingTestArg arg) - { - conn.InternalCallReducer(new Reducer.RepeatingTest(arg), this.SetCallReducerFlags.RepeatingTestFlags); - } - - public bool InvokeRepeatingTest(ReducerEventContext ctx, Reducer.RepeatingTest args) - { - if (OnRepeatingTest == 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; - } - OnRepeatingTest( - ctx, - args.Arg - ); - return true; - } - } - - public abstract partial class Reducer - { - [SpacetimeDB.Type] - [DataContract] - public sealed partial class RepeatingTest : Reducer, IReducerArgs - { - [DataMember(Name = "arg")] - public RepeatingTestArg Arg; - - public RepeatingTest(RepeatingTestArg Arg) - { - this.Arg = Arg; - } - - public RepeatingTest() - { - this.Arg = new(); - } - - string IReducerArgs.ReducerName => "repeating_test"; - } - } - - public sealed partial class SetReducerFlags - { - internal CallReducerFlags RepeatingTestFlags; - public void RepeatingTest(CallReducerFlags flags) => RepeatingTestFlags = flags; - } -} -''' "Reducers/SayHello.g.cs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. @@ -1906,13 +1782,11 @@ namespace SpacetimeDB "add_player" => BSATNHelpers.Decode(encodedArgs), "add_private" => BSATNHelpers.Decode(encodedArgs), "assert_caller_identity_is_module_identity" => BSATNHelpers.Decode(encodedArgs), - "client_connected" => BSATNHelpers.Decode(encodedArgs), "delete_player" => BSATNHelpers.Decode(encodedArgs), "delete_players_by_name" => BSATNHelpers.Decode(encodedArgs), "list_over_age" => BSATNHelpers.Decode(encodedArgs), "log_module_identity" => BSATNHelpers.Decode(encodedArgs), "query_private" => BSATNHelpers.Decode(encodedArgs), - "repeating_test" => BSATNHelpers.Decode(encodedArgs), "say_hello" => BSATNHelpers.Decode(encodedArgs), "test" => BSATNHelpers.Decode(encodedArgs), "test_btree_index_args" => BSATNHelpers.Decode(encodedArgs), @@ -1944,13 +1818,11 @@ namespace SpacetimeDB Reducer.AddPlayer args => Reducers.InvokeAddPlayer(eventContext, args), Reducer.AddPrivate args => Reducers.InvokeAddPrivate(eventContext, args), Reducer.AssertCallerIdentityIsModuleIdentity args => Reducers.InvokeAssertCallerIdentityIsModuleIdentity(eventContext, args), - Reducer.ClientConnected args => Reducers.InvokeClientConnected(eventContext, args), Reducer.DeletePlayer args => Reducers.InvokeDeletePlayer(eventContext, args), Reducer.DeletePlayersByName args => Reducers.InvokeDeletePlayersByName(eventContext, args), Reducer.ListOverAge args => Reducers.InvokeListOverAge(eventContext, args), Reducer.LogModuleIdentity args => Reducers.InvokeLogModuleIdentity(eventContext, args), Reducer.QueryPrivate args => Reducers.InvokeQueryPrivate(eventContext, args), - Reducer.RepeatingTest args => Reducers.InvokeRepeatingTest(eventContext, args), Reducer.SayHello args => Reducers.InvokeSayHello(eventContext, args), Reducer.Test args => Reducers.InvokeTest(eventContext, args), Reducer.TestBtreeIndexArgs args => Reducers.InvokeTestBtreeIndexArgs(eventContext, args), diff --git a/crates/codegen/tests/snapshots/codegen__codegen_rust.snap b/crates/codegen/tests/snapshots/codegen__codegen_rust.snap index c54e2ee3066..49e3aaea161 100644 --- a/crates/codegen/tests/snapshots/codegen__codegen_rust.snap +++ b/crates/codegen/tests/snapshots/codegen__codegen_rust.snap @@ -1,5 +1,6 @@ --- source: crates/codegen/tests/codegen.rs +assertion_line: 37 expression: outfiles --- "add_player_reducer.rs" = ''' @@ -465,111 +466,6 @@ impl __sdk::InModule for Baz { type Module = super::RemoteModule; } -''' -"client_connected_reducer.rs" = ''' -// 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 ClientConnectedArgs { - } - -impl From for super::Reducer { - fn from(args: ClientConnectedArgs) -> Self { - Self::ClientConnected -} -} - -impl __sdk::InModule for ClientConnectedArgs { - type Module = super::RemoteModule; -} - -pub struct ClientConnectedCallbackId(__sdk::CallbackId); - -#[allow(non_camel_case_types)] -/// Extension trait for access to the reducer `client_connected`. -/// -/// Implemented for [`super::RemoteReducers`]. -pub trait client_connected { - /// Request that the remote module invoke the reducer `client_connected` 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 its status can be observed by listening for [`Self::on_client_connected`] callbacks. - fn client_connected(&self, ) -> __sdk::Result<()>; - /// Register a callback to run whenever we are notified of an invocation of the reducer `client_connected`. - /// - /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] - /// to determine the reducer's status. - /// - /// The returned [`ClientConnectedCallbackId`] can be passed to [`Self::remove_on_client_connected`] - /// to cancel the callback. - fn on_client_connected(&self, callback: impl FnMut(&super::ReducerEventContext, ) + Send + 'static) -> ClientConnectedCallbackId; - /// Cancel a callback previously registered by [`Self::on_client_connected`], - /// causing it not to run in the future. - fn remove_on_client_connected(&self, callback: ClientConnectedCallbackId); -} - -impl client_connected for super::RemoteReducers { - fn client_connected(&self, ) -> __sdk::Result<()> { - self.imp.call_reducer("client_connected", ClientConnectedArgs { }) - } - fn on_client_connected( - &self, - mut callback: impl FnMut(&super::ReducerEventContext, ) + Send + 'static, - ) -> ClientConnectedCallbackId { - ClientConnectedCallbackId(self.imp.on_reducer( - "client_connected", - Box::new(move |ctx: &super::ReducerEventContext| { - #[allow(irrefutable_let_patterns)] - let super::ReducerEventContext { - event: __sdk::ReducerEvent { - reducer: super::Reducer::ClientConnected { - - }, - .. - }, - .. - } = ctx else { unreachable!() }; - callback(ctx, ) - }), - )) - } - fn remove_on_client_connected(&self, callback: ClientConnectedCallbackId) { - self.imp.remove_on_reducer("client_connected", callback.0) - } -} - -#[allow(non_camel_case_types)] -#[doc(hidden)] -/// Extension trait for setting the call-flags for the reducer `client_connected`. -/// -/// Implemented for [`super::SetReducerFlags`]. -/// -/// This type is currently unstable and may be removed without a major version bump. -pub trait set_flags_for_client_connected { - /// Set the call-reducer flags for the reducer `client_connected` to `flags`. - /// - /// This type is currently unstable and may be removed without a major version bump. - fn client_connected(&self, flags: __ws::CallReducerFlags); -} - -impl set_flags_for_client_connected for super::SetReducerFlags { - fn client_connected(&self, flags: __ws::CallReducerFlags) { - self.imp.set_call_reducer_flags("client_connected", flags); - } -} - ''' "delete_player_reducer.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -1415,13 +1311,11 @@ pub mod add_reducer; pub mod add_player_reducer; pub mod add_private_reducer; pub mod assert_caller_identity_is_module_identity_reducer; -pub mod client_connected_reducer; pub mod delete_player_reducer; pub mod delete_players_by_name_reducer; pub mod list_over_age_reducer; pub mod log_module_identity_reducer; pub mod query_private_reducer; -pub mod repeating_test_reducer; pub mod say_hello_reducer; pub mod test_reducer; pub mod test_btree_index_args_reducer; @@ -1463,13 +1357,11 @@ pub use add_reducer::{add, set_flags_for_add, AddCallbackId}; pub use add_player_reducer::{add_player, set_flags_for_add_player, AddPlayerCallbackId}; pub use add_private_reducer::{add_private, set_flags_for_add_private, AddPrivateCallbackId}; pub use assert_caller_identity_is_module_identity_reducer::{assert_caller_identity_is_module_identity, set_flags_for_assert_caller_identity_is_module_identity, AssertCallerIdentityIsModuleIdentityCallbackId}; -pub use client_connected_reducer::{client_connected, set_flags_for_client_connected, ClientConnectedCallbackId}; pub use delete_player_reducer::{delete_player, set_flags_for_delete_player, DeletePlayerCallbackId}; pub use delete_players_by_name_reducer::{delete_players_by_name, set_flags_for_delete_players_by_name, DeletePlayersByNameCallbackId}; pub use list_over_age_reducer::{list_over_age, set_flags_for_list_over_age, ListOverAgeCallbackId}; pub use log_module_identity_reducer::{log_module_identity, set_flags_for_log_module_identity, LogModuleIdentityCallbackId}; pub use query_private_reducer::{query_private, set_flags_for_query_private, QueryPrivateCallbackId}; -pub use repeating_test_reducer::{repeating_test, set_flags_for_repeating_test, RepeatingTestCallbackId}; pub use say_hello_reducer::{say_hello, set_flags_for_say_hello, SayHelloCallbackId}; pub use test_reducer::{test, set_flags_for_test, TestCallbackId}; pub use test_btree_index_args_reducer::{test_btree_index_args, set_flags_for_test_btree_index_args, TestBtreeIndexArgsCallbackId}; @@ -1497,7 +1389,6 @@ pub enum Reducer { name: String, } , AssertCallerIdentityIsModuleIdentity , - ClientConnected , DeletePlayer { id: u64, } , @@ -1509,9 +1400,6 @@ pub enum Reducer { } , LogModuleIdentity , QueryPrivate , - RepeatingTest { - arg: RepeatingTestArg, -} , SayHello , Test { arg: TestA, @@ -1534,13 +1422,11 @@ impl __sdk::Reducer for Reducer { Reducer::AddPlayer { .. } => "add_player", Reducer::AddPrivate { .. } => "add_private", Reducer::AssertCallerIdentityIsModuleIdentity => "assert_caller_identity_is_module_identity", - Reducer::ClientConnected => "client_connected", Reducer::DeletePlayer { .. } => "delete_player", Reducer::DeletePlayersByName { .. } => "delete_players_by_name", Reducer::ListOverAge { .. } => "list_over_age", Reducer::LogModuleIdentity => "log_module_identity", Reducer::QueryPrivate => "query_private", - Reducer::RepeatingTest { .. } => "repeating_test", Reducer::SayHello => "say_hello", Reducer::Test { .. } => "test", Reducer::TestBtreeIndexArgs => "test_btree_index_args", @@ -1556,13 +1442,11 @@ fn try_from(value: __ws::ReducerCallInfo<__ws::BsatnFormat>) -> __sdk::Result Ok(__sdk::parse_reducer_args::("add_player", &value.args)?.into()), "add_private" => Ok(__sdk::parse_reducer_args::("add_private", &value.args)?.into()), "assert_caller_identity_is_module_identity" => Ok(__sdk::parse_reducer_args::("assert_caller_identity_is_module_identity", &value.args)?.into()), - "client_connected" => Ok(__sdk::parse_reducer_args::("client_connected", &value.args)?.into()), "delete_player" => Ok(__sdk::parse_reducer_args::("delete_player", &value.args)?.into()), "delete_players_by_name" => Ok(__sdk::parse_reducer_args::("delete_players_by_name", &value.args)?.into()), "list_over_age" => Ok(__sdk::parse_reducer_args::("list_over_age", &value.args)?.into()), "log_module_identity" => Ok(__sdk::parse_reducer_args::("log_module_identity", &value.args)?.into()), "query_private" => Ok(__sdk::parse_reducer_args::("query_private", &value.args)?.into()), - "repeating_test" => Ok(__sdk::parse_reducer_args::("repeating_test", &value.args)?.into()), "say_hello" => Ok(__sdk::parse_reducer_args::("say_hello", &value.args)?.into()), "test" => Ok(__sdk::parse_reducer_args::("test", &value.args)?.into()), "test_btree_index_args" => Ok(__sdk::parse_reducer_args::("test_btree_index_args", &value.args)?.into()), @@ -3501,117 +3385,6 @@ impl __sdk::__query_builder::HasIxCols for RepeatingTestArg { } } -''' -"repeating_test_reducer.rs" = ''' -// 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, -}; - -use super::repeating_test_arg_type::RepeatingTestArg; - -#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] -#[sats(crate = __lib)] -pub(super) struct RepeatingTestArgs { - pub arg: RepeatingTestArg, -} - -impl From for super::Reducer { - fn from(args: RepeatingTestArgs) -> Self { - Self::RepeatingTest { - arg: args.arg, -} -} -} - -impl __sdk::InModule for RepeatingTestArgs { - type Module = super::RemoteModule; -} - -pub struct RepeatingTestCallbackId(__sdk::CallbackId); - -#[allow(non_camel_case_types)] -/// Extension trait for access to the reducer `repeating_test`. -/// -/// Implemented for [`super::RemoteReducers`]. -pub trait repeating_test { - /// Request that the remote module invoke the reducer `repeating_test` 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 its status can be observed by listening for [`Self::on_repeating_test`] callbacks. - fn repeating_test(&self, arg: RepeatingTestArg, -) -> __sdk::Result<()>; - /// Register a callback to run whenever we are notified of an invocation of the reducer `repeating_test`. - /// - /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::ReducerEventContext`] - /// to determine the reducer's status. - /// - /// The returned [`RepeatingTestCallbackId`] can be passed to [`Self::remove_on_repeating_test`] - /// to cancel the callback. - fn on_repeating_test(&self, callback: impl FnMut(&super::ReducerEventContext, &RepeatingTestArg, ) + Send + 'static) -> RepeatingTestCallbackId; - /// Cancel a callback previously registered by [`Self::on_repeating_test`], - /// causing it not to run in the future. - fn remove_on_repeating_test(&self, callback: RepeatingTestCallbackId); -} - -impl repeating_test for super::RemoteReducers { - fn repeating_test(&self, arg: RepeatingTestArg, -) -> __sdk::Result<()> { - self.imp.call_reducer("repeating_test", RepeatingTestArgs { arg, }) - } - fn on_repeating_test( - &self, - mut callback: impl FnMut(&super::ReducerEventContext, &RepeatingTestArg, ) + Send + 'static, - ) -> RepeatingTestCallbackId { - RepeatingTestCallbackId(self.imp.on_reducer( - "repeating_test", - Box::new(move |ctx: &super::ReducerEventContext| { - #[allow(irrefutable_let_patterns)] - let super::ReducerEventContext { - event: __sdk::ReducerEvent { - reducer: super::Reducer::RepeatingTest { - arg, - }, - .. - }, - .. - } = ctx else { unreachable!() }; - callback(ctx, arg, ) - }), - )) - } - fn remove_on_repeating_test(&self, callback: RepeatingTestCallbackId) { - self.imp.remove_on_reducer("repeating_test", callback.0) - } -} - -#[allow(non_camel_case_types)] -#[doc(hidden)] -/// Extension trait for setting the call-flags for the reducer `repeating_test`. -/// -/// Implemented for [`super::SetReducerFlags`]. -/// -/// This type is currently unstable and may be removed without a major version bump. -pub trait set_flags_for_repeating_test { - /// Set the call-reducer flags for the reducer `repeating_test` to `flags`. - /// - /// This type is currently unstable and may be removed without a major version bump. - fn repeating_test(&self, flags: __ws::CallReducerFlags); -} - -impl set_flags_for_repeating_test for super::SetReducerFlags { - fn repeating_test(&self, flags: __ws::CallReducerFlags) { - self.imp.set_call_reducer_flags("repeating_test", flags); - } -} - ''' "return_value_procedure.rs" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE diff --git a/crates/codegen/tests/snapshots/codegen__codegen_typescript.snap b/crates/codegen/tests/snapshots/codegen__codegen_typescript.snap index 1bef42e38e6..f5ae325d55c 100644 --- a/crates/codegen/tests/snapshots/codegen__codegen_typescript.snap +++ b/crates/codegen/tests/snapshots/codegen__codegen_typescript.snap @@ -1,5 +1,6 @@ --- source: crates/codegen/tests/codegen.rs +assertion_line: 37 expression: outfiles --- "add_player_reducer.ts" = ''' @@ -87,21 +88,6 @@ export default __t.object("Baz", { }); -''' -"client_connected_reducer.ts" = ''' -// 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 { - TypeBuilder as __TypeBuilder, - t as __t, - type AlgebraicTypeType as __AlgebraicTypeType, - type Infer as __Infer, -} from "spacetimedb"; - -export default {}; ''' "delete_player_reducer.ts" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE @@ -245,8 +231,6 @@ import AddPrivateReducer from "./add_private_reducer"; export { AddPrivateReducer }; import AssertCallerIdentityIsModuleIdentityReducer from "./assert_caller_identity_is_module_identity_reducer"; export { AssertCallerIdentityIsModuleIdentityReducer }; -import ClientConnectedReducer from "./client_connected_reducer"; -export { ClientConnectedReducer }; import DeletePlayerReducer from "./delete_player_reducer"; export { DeletePlayerReducer }; import DeletePlayersByNameReducer from "./delete_players_by_name_reducer"; @@ -257,8 +241,6 @@ import LogModuleIdentityReducer from "./log_module_identity_reducer"; export { LogModuleIdentityReducer }; import QueryPrivateReducer from "./query_private_reducer"; export { QueryPrivateReducer }; -import RepeatingTestReducer from "./repeating_test_reducer"; -export { RepeatingTestReducer }; import SayHelloReducer from "./say_hello_reducer"; export { SayHelloReducer }; import TestReducer from "./test_reducer"; @@ -414,7 +396,6 @@ const reducersSchema = __reducers( __reducerSchema("list_over_age", ListOverAgeReducer), __reducerSchema("log_module_identity", LogModuleIdentityReducer), __reducerSchema("query_private", QueryPrivateReducer), - __reducerSchema("repeating_test", RepeatingTestReducer), __reducerSchema("say_hello", SayHelloReducer), __reducerSchema("test", TestReducer), __reducerSchema("test_btree_index_args", TestBtreeIndexArgsReducer), @@ -790,27 +771,6 @@ export default __t.object("RepeatingTestArg", { }); -''' -"repeating_test_reducer.ts" = ''' -// 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 { - TypeBuilder as __TypeBuilder, - t as __t, - type AlgebraicTypeType as __AlgebraicTypeType, - type Infer as __Infer, -} from "spacetimedb"; - -import RepeatingTestArg from "./repeating_test_arg_type"; - -export default { - get arg() { - return RepeatingTestArg; - }, -}; ''' "return_value_procedure.ts" = ''' // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE From fc3af2cc9f5646505684f7ffdacb77ede7b93f50 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Fri, 6 Feb 2026 14:24:16 -0800 Subject: [PATCH 16/18] Clean up procedure test for CI --- .../src/module_bindings/mod.rs | 4 +- .../scheduled_proc_procedure.rs | 46 ------------------- 2 files changed, 1 insertion(+), 49 deletions(-) delete mode 100644 sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_procedure.rs 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 a6637c87664..59454ef8ed1 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 819069447d9034135872ce2bdc28722c4e5e46b6). +// This was generated using spacetimedb cli version 1.12.0 (commit 27fc5ac8802947bdafba1c58cd5b6406159dedd2). #![allow(unused, clippy::all)] use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; @@ -23,7 +23,6 @@ pub mod return_primitive_procedure; pub mod return_struct_procedure; pub mod return_struct_type; pub mod schedule_proc_reducer; -pub mod scheduled_proc_procedure; pub mod scheduled_proc_table_type; pub mod sorted_uuids_insert_procedure; pub mod will_panic_procedure; @@ -45,7 +44,6 @@ pub use return_primitive_procedure::return_primitive; pub use return_struct_procedure::return_struct; pub use return_struct_type::ReturnStruct; pub use schedule_proc_reducer::{schedule_proc, set_flags_for_schedule_proc, ScheduleProcCallbackId}; -pub use scheduled_proc_procedure::scheduled_proc; pub use scheduled_proc_table_type::ScheduledProcTable; pub use sorted_uuids_insert_procedure::sorted_uuids_insert; pub use will_panic_procedure::will_panic; diff --git a/sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_procedure.rs b/sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_procedure.rs deleted file mode 100644 index 124f51162f0..00000000000 --- a/sdks/rust/tests/procedure-client/src/module_bindings/scheduled_proc_procedure.rs +++ /dev/null @@ -1,46 +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. - -#![allow(unused, clippy::all)] -use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; - -use super::scheduled_proc_table_type::ScheduledProcTable; - -#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] -#[sats(crate = __lib)] -struct ScheduledProcArgs { - pub data: ScheduledProcTable, -} - -impl __sdk::InModule for ScheduledProcArgs { - type Module = super::RemoteModule; -} - -#[allow(non_camel_case_types)] -/// Extension trait for access to the procedure `scheduled_proc`. -/// -/// Implemented for [`super::RemoteProcedures`]. -pub trait scheduled_proc { - fn scheduled_proc(&self, data: ScheduledProcTable) { - self.scheduled_proc_then(data, |_, _| {}); - } - - fn scheduled_proc_then( - &self, - data: ScheduledProcTable, - - __callback: impl FnOnce(&super::ProcedureEventContext, Result<(), __sdk::InternalError>) + Send + 'static, - ); -} - -impl scheduled_proc for super::RemoteProcedures { - fn scheduled_proc_then( - &self, - data: ScheduledProcTable, - - __callback: impl FnOnce(&super::ProcedureEventContext, Result<(), __sdk::InternalError>) + Send + 'static, - ) { - self.imp - .invoke_procedure_with_callback::<_, ()>("scheduled_proc", ScheduledProcArgs { data }, __callback); - } -} From 0c237a5065172c805d6618914b1dab3d3000747d Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Fri, 6 Feb 2026 20:07:34 -0800 Subject: [PATCH 17/18] Switched to enum for the private visibility check --- crates/codegen/src/csharp.rs | 6 +++--- crates/codegen/src/lib.rs | 2 +- crates/codegen/src/rust.rs | 18 +++++++++--------- crates/codegen/src/typescript.rs | 8 ++++---- crates/codegen/src/unrealcpp.rs | 20 ++++++++++---------- crates/codegen/src/util.rs | 21 +++++++++++++++++---- 6 files changed, 44 insertions(+), 31 deletions(-) diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs index 3f6013813dd..fbec1ab85a8 100644 --- a/crates/codegen/src/csharp.rs +++ b/crates/codegen/src/csharp.rs @@ -8,7 +8,7 @@ use std::ops::Deref; use super::code_indenter::CodeIndenter; use super::Lang; use crate::util::{ - collect_case, is_reducer_invokable, iter_indexes, iter_reducers, iter_table_names_and_types, + CodegenVisibility, collect_case, is_reducer_invokable, iter_indexes, iter_reducers, iter_table_names_and_types, print_auto_generated_file_comment, print_auto_generated_version_comment, type_ref_name, }; use crate::{indent_scope, OutputFile}; @@ -1048,7 +1048,7 @@ impl Lang for Csharp<'_> { indented_block(&mut output, |output| { writeln!(output, "public RemoteTables(DbConnection conn)"); indented_block(output, |output| { - for (table_name, _) in iter_table_names_and_types(module, false) { + for (table_name, _) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { writeln!( output, "AddTable({} = new(conn));", @@ -1071,7 +1071,7 @@ impl Lang for Csharp<'_> { writeln!(output, "public sealed class From"); indented_block(&mut output, |output| { - for (table_name, product_type_ref) in iter_table_names_and_types(module, false) { + for (table_name, product_type_ref) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { let method_name = table_name.deref().to_case(Case::Pascal); let row_type = type_ref_name(module, product_type_ref); let table_name_lit = format!("{:?}", table_name.deref()); diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index eea3a51a727..1697fbd9c91 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -16,7 +16,7 @@ pub use util::AUTO_GENERATED_PREFIX; pub fn generate(module: &ModuleDef, lang: &dyn Lang) -> Vec { itertools::chain!( - util::iter_tables(module, false).map(|tbl| lang.generate_table_file(module, tbl)), + util::iter_tables(module, util::CodegenVisibility::OnlyPublic).map(|tbl| lang.generate_table_file(module, tbl)), module.views().map(|view| lang.generate_view_file(module, view)), module.types().flat_map(|typ| lang.generate_type_files(module, typ)), util::iter_reducers(module).map(|reducer| lang.generate_reducer_file(module, reducer)), diff --git a/crates/codegen/src/rust.rs b/crates/codegen/src/rust.rs index 9048019a797..a831cd0d7dd 100644 --- a/crates/codegen/src/rust.rs +++ b/crates/codegen/src/rust.rs @@ -3,7 +3,7 @@ use super::util::{collect_case, iter_reducers, print_lines, type_ref_name}; use super::Lang; use crate::util::{ iter_indexes, iter_procedures, iter_table_names_and_types, iter_tables, iter_types, iter_unique_cols, iter_views, - print_auto_generated_file_comment, print_auto_generated_version_comment, + print_auto_generated_file_comment, print_auto_generated_version_comment, CodegenVisibility, }; use crate::OutputFile; use convert_case::{Case, Casing}; @@ -1131,7 +1131,7 @@ fn iter_module_names(module: &ModuleDef) -> impl Iterator + '_ { itertools::chain!( iter_types(module).map(|ty| type_module_name(&ty.name)), iter_reducers(module).map(|r| reducer_module_name(&r.name)), - iter_tables(module, false).map(|tbl| table_module_name(&tbl.name)), + iter_tables(module, CodegenVisibility::OnlyPublic).map(|tbl| table_module_name(&tbl.name)), iter_views(module).map(|view| table_module_name(&view.name)), iter_procedures(module).map(|proc| procedure_module_name(&proc.name)), ) @@ -1151,7 +1151,7 @@ fn print_module_reexports(module: &ModuleDef, out: &mut Indenter) { let type_name = collect_case(Case::Pascal, ty.name.name_segments()); writeln!(out, "pub use {mod_name}::{type_name};") } - for (table_name, _) in iter_table_names_and_types(module, false) { + for (table_name, _) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { let mod_name = table_module_name(table_name); // TODO: More precise reexport: we want: // - The trait name. @@ -1310,7 +1310,7 @@ fn print_db_update_defn(module: &ModuleDef, out: &mut Indenter) { out.delimited_block( "pub struct DbUpdate {", |out| { - for (table_name, product_type_ref) in iter_table_names_and_types(module, false) { + for (table_name, product_type_ref) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { writeln!( out, "{}: __sdk::TableUpdate<{}>,", @@ -1334,7 +1334,7 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { match &table_update.table_name[..] { ", |out| { - for (table_name, _) in iter_table_names_and_types(module, false) { + for (table_name, _) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { writeln!( out, "{:?} => db_update.{}.append({}::parse_table_update(table_update)?),", @@ -1378,7 +1378,7 @@ impl __sdk::InModule for DbUpdate {{ let mut diff = AppliedDiff::default(); ", |out| { - for table in iter_tables(module, false) { + for table in iter_tables(module, CodegenVisibility::OnlyPublic) { let with_updates = table .primary_key .map(|col| { @@ -1421,7 +1421,7 @@ fn print_applied_diff_defn(module: &ModuleDef, out: &mut Indenter) { out.delimited_block( "pub struct AppliedDiff<'r> {", |out| { - for (table_name, product_type_ref) in iter_table_names_and_types(module, false) { + for (table_name, product_type_ref) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { writeln!( out, "{}: __sdk::TableAppliedDiff<'r, {}>,", @@ -1454,7 +1454,7 @@ impl __sdk::InModule for AppliedDiff<'_> {{ out.delimited_block( "fn invoke_row_callbacks(&self, event: &EventContext, callbacks: &mut __sdk::DbCallbacks) {", |out| { - for (table_name, product_type_ref) in iter_table_names_and_types(module, false) { + for (table_name, product_type_ref) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { writeln!( out, "callbacks.invoke_table_row_callbacks::<{}>({:?}, &self.{}, event);", @@ -1497,7 +1497,7 @@ type QueryBuilder = __sdk::QueryBuilder; out.delimited_block( "fn register_tables(client_cache: &mut __sdk::ClientCache) {", |out| { - for (table_name, _) in iter_table_names_and_types(module, false) { + for (table_name, _) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { writeln!(out, "{}::register_table(client_cache);", table_module_name(table_name)); } }, diff --git a/crates/codegen/src/typescript.rs b/crates/codegen/src/typescript.rs index 858618b77cc..c89ef1a5b79 100644 --- a/crates/codegen/src/typescript.rs +++ b/crates/codegen/src/typescript.rs @@ -1,6 +1,6 @@ use crate::util::{ - is_reducer_invokable, iter_constraints, iter_indexes, iter_procedures, iter_reducers, iter_table_names_and_types, - iter_tables, iter_types, iter_views, print_auto_generated_version_comment, + CodegenVisibility, is_reducer_invokable, iter_constraints, iter_indexes, iter_procedures, iter_reducers, + iter_table_names_and_types, iter_tables, iter_types, iter_views, print_auto_generated_version_comment, }; use crate::OutputFile; @@ -231,7 +231,7 @@ impl Lang for TypeScript { writeln!(out); writeln!(out, "// Import and reexport all table handle types"); - for (table_name, _) in iter_table_names_and_types(module, false) { + for (table_name, _) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { let table_module_name = table_module_name(table_name); let table_name_pascalcase = table_name.deref().to_case(Case::Pascal); // TODO: This really shouldn't be necessary. We could also have `table()` accept @@ -253,7 +253,7 @@ impl Lang for TypeScript { writeln!(out, "/** 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. */"); writeln!(out, "const tablesSchema = __schema("); out.indent(1); - for table in iter_tables(module, false) { + for table in iter_tables(module, CodegenVisibility::OnlyPublic) { let type_ref = table.product_type_ref; let table_name_pascalcase = table.name.deref().to_case(Case::Pascal); writeln!(out, "__table({{"); diff --git a/crates/codegen/src/unrealcpp.rs b/crates/codegen/src/unrealcpp.rs index e2fa0c30838..c0743a43318 100644 --- a/crates/codegen/src/unrealcpp.rs +++ b/crates/codegen/src/unrealcpp.rs @@ -1,8 +1,8 @@ //! Autogenerated Unreal‑C++ code‑gen backend for SpacetimeDB CLI use crate::code_indenter::CodeIndenter; use crate::util::{ - collect_case, fmt_fn, iter_table_names_and_types, iter_tables, print_auto_generated_file_comment, - print_auto_generated_version_comment, + CodegenVisibility, collect_case, fmt_fn, iter_table_names_and_types, iter_tables, + print_auto_generated_file_comment, print_auto_generated_version_comment, }; use crate::util::{iter_indexes, iter_procedures, iter_reducers}; use crate::Lang; @@ -865,7 +865,7 @@ impl Lang for UnrealCpp<'_> { writeln!(client_h); writeln!(client_h, "/** Forward declaration for tables */"); - for (table_name, _) in iter_table_names_and_types(module, false) { + for (table_name, _) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { writeln!(client_h, "class U{}Table;", table_name.deref().to_case(Case::Pascal)); } writeln!(client_h, "/***/"); @@ -958,7 +958,7 @@ impl Lang for UnrealCpp<'_> { }); // Build table includes - let table_includes: Vec = iter_table_names_and_types(module, false) + let table_includes: Vec = iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) .map(|(table_name, _)| { format!( "ModuleBindings/Tables/{}Table.g.h", @@ -987,7 +987,7 @@ impl Lang for UnrealCpp<'_> { }); // Generate .cpp implementation files for each table - for table in iter_tables(module, false) { + for table in iter_tables(module, CodegenVisibility::OnlyPublic) { let schema = TableSchema::from_module_def(module, table, (), 0.into()) .validated() .expect("table schema should validate"); @@ -2349,7 +2349,7 @@ fn generate_remote_tables_class(output: &mut UnrealCppAutogen, module: &ModuleDe writeln!(output); // Generate table handle properties - for (table_name, _) in iter_table_names_and_types(module, false) { + for (table_name, _) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { writeln!(output, " UPROPERTY(BlueprintReadOnly, Category=\"SpacetimeDB\")"); writeln!( output, @@ -3023,7 +3023,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "\tProcedures->Conn = this;"); writeln!(output); - for (table_name, product_type_ref) in iter_table_names_and_types(module, false) { + for (table_name, product_type_ref) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { let struct_name = type_ref_name(module, product_type_ref); let table_name = table_name.deref(); writeln!( @@ -3079,7 +3079,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "{{"); writeln!(output); writeln!(output, "\t/** Creating tables */"); - for (table_name, _) in iter_table_names_and_types(module, false) { + for (table_name, _) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { writeln!( output, "\t{} = NewObject(this);", @@ -3090,7 +3090,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "\t/**/"); writeln!(output); writeln!(output, "\t/** Initialization */"); - for (table_name, _) in iter_table_names_and_types(module, false) { + for (table_name, _) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { writeln!( output, "\t{}->PostInitialize();", @@ -3980,7 +3980,7 @@ fn collect_wrapper_types(module: &ModuleDef) -> (HashSet, HashSet<(Strin } // Collect from all tables - for (_, product_type_ref) in iter_table_names_and_types(module, false) { + for (_, product_type_ref) in iter_table_names_and_types(module, CodegenVisibility::OnlyPublic) { let product_type = module.typespace_for_generate()[product_type_ref].as_product().unwrap(); for (_, field_ty) in &product_type.elements { collect_from_type(module, field_ty, &mut optional_types, &mut result_types); diff --git a/crates/codegen/src/util.rs b/crates/codegen/src/util.rs index d0478e5675a..76fd995925f 100644 --- a/crates/codegen/src/util.rs +++ b/crates/codegen/src/util.rs @@ -28,6 +28,13 @@ use spacetimedb_schema::{ type_for_generate::AlgebraicTypeUse, }; +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub(super) enum CodegenVisibility { + #[allow(unused)] // reserved for upcoming change for --include-private option + IncludePrivate, + OnlyPublic, +} + /// Turns a closure `f: Fn(&mut Formatter) -> Result` into `fmt::Display`. pub(super) fn fmt_fn(f: impl Fn(&mut Formatter) -> Result) -> impl Display { struct FDisplay(F); @@ -124,10 +131,13 @@ pub(super) fn iter_procedures(module: &ModuleDef) -> impl Iterator impl Iterator { +pub(super) fn iter_tables(module: &ModuleDef, visibility: CodegenVisibility) -> impl Iterator { module .tables() - .filter(move |table| include_private || table.table_access == TableAccess::Public) + .filter(move |table| match visibility { + CodegenVisibility::IncludePrivate => true, + CodegenVisibility::OnlyPublic => table.table_access == TableAccess::Public, + }) .sorted_by_key(|table| &table.name) } @@ -153,11 +163,14 @@ pub(super) fn iter_views(module: &ModuleDef) -> impl Iterator { /// Sorting is necessary to have deterministic reproducible codegen. pub(super) fn iter_table_names_and_types( module: &ModuleDef, - include_private: bool, + visibility: CodegenVisibility, ) -> impl Iterator { module .tables() - .filter(move |table| include_private || table.table_access == TableAccess::Public) + .filter(move |table| match visibility { + CodegenVisibility::IncludePrivate => true, + CodegenVisibility::OnlyPublic => table.table_access == TableAccess::Public, + }) .map(|def| (&def.name, def.product_type_ref)) .chain(module.views().map(|def| (&def.name, def.product_type_ref))) .sorted_by_key(|(name, _)| *name) From 77b5995f884a61cf6e9a7a501416c025595c1c39 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Sat, 7 Feb 2026 13:19:45 -0800 Subject: [PATCH 18/18] Fix for formatting --- crates/codegen/src/csharp.rs | 4 ++-- crates/codegen/src/typescript.rs | 4 ++-- crates/codegen/src/unrealcpp.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs index fbec1ab85a8..0be88f55ba3 100644 --- a/crates/codegen/src/csharp.rs +++ b/crates/codegen/src/csharp.rs @@ -8,8 +8,8 @@ use std::ops::Deref; use super::code_indenter::CodeIndenter; use super::Lang; use crate::util::{ - CodegenVisibility, collect_case, is_reducer_invokable, iter_indexes, iter_reducers, iter_table_names_and_types, - print_auto_generated_file_comment, print_auto_generated_version_comment, type_ref_name, + collect_case, is_reducer_invokable, iter_indexes, iter_reducers, iter_table_names_and_types, + print_auto_generated_file_comment, print_auto_generated_version_comment, type_ref_name, CodegenVisibility, }; use crate::{indent_scope, OutputFile}; use convert_case::{Case, Casing}; diff --git a/crates/codegen/src/typescript.rs b/crates/codegen/src/typescript.rs index c89ef1a5b79..1fe1900c3a3 100644 --- a/crates/codegen/src/typescript.rs +++ b/crates/codegen/src/typescript.rs @@ -1,6 +1,6 @@ use crate::util::{ - CodegenVisibility, is_reducer_invokable, iter_constraints, iter_indexes, iter_procedures, iter_reducers, - iter_table_names_and_types, iter_tables, iter_types, iter_views, print_auto_generated_version_comment, + is_reducer_invokable, iter_constraints, iter_indexes, iter_procedures, iter_reducers, iter_table_names_and_types, + iter_tables, iter_types, iter_views, print_auto_generated_version_comment, CodegenVisibility, }; use crate::OutputFile; diff --git a/crates/codegen/src/unrealcpp.rs b/crates/codegen/src/unrealcpp.rs index c0743a43318..22187ecc26a 100644 --- a/crates/codegen/src/unrealcpp.rs +++ b/crates/codegen/src/unrealcpp.rs @@ -1,8 +1,8 @@ //! Autogenerated Unreal‑C++ code‑gen backend for SpacetimeDB CLI use crate::code_indenter::CodeIndenter; use crate::util::{ - CodegenVisibility, collect_case, fmt_fn, iter_table_names_and_types, iter_tables, - print_auto_generated_file_comment, print_auto_generated_version_comment, + collect_case, fmt_fn, iter_table_names_and_types, iter_tables, print_auto_generated_file_comment, + print_auto_generated_version_comment, CodegenVisibility, }; use crate::util::{iter_indexes, iter_procedures, iter_reducers}; use crate::Lang;