diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs
index e08d53deb5f..e6f09ceb225 100644
--- a/crates/codegen/src/csharp.rs
+++ b/crates/codegen/src/csharp.rs
@@ -1,6 +1,7 @@
// Note: the generated code depends on APIs and interfaces from crates/bindings-csharp/BSATN.Runtime.
use super::util::fmt_fn;
+use std::collections::BTreeSet;
use std::fmt::{self, Write};
use std::ops::Deref;
@@ -14,7 +15,7 @@ use crate::{indent_scope, OutputFile};
use convert_case::{Case, Casing};
use spacetimedb_lib::sats::layout::PrimitiveType;
use spacetimedb_primitives::ColId;
-use spacetimedb_schema::def::{ModuleDef, TableDef, TypeDef};
+use spacetimedb_schema::def::{BTreeAlgorithm, IndexAlgorithm, ModuleDef, TableDef, TypeDef};
use spacetimedb_schema::identifier::Identifier;
use spacetimedb_schema::schema::TableSchema;
use spacetimedb_schema::type_for_generate::{
@@ -473,6 +474,20 @@ const REDUCER_EVENTS: &str = r#"
Error += callback;
return this;
}
+
+ ///
+ /// Add a typed query to this subscription.
+ ///
+ /// This is the entry point for building subscriptions without writing SQL by hand.
+ /// Once a typed query is added, only typed queries may follow (SQL and typed queries cannot be mixed).
+ ///
+ public TypedSubscriptionBuilder AddQuery(
+ Func> build
+ )
+ {
+ var typed = new TypedSubscriptionBuilder(conn, Applied, Error);
+ return typed.AddQuery(build);
+ }
///
/// Subscribe to the following SQL queries.
@@ -670,6 +685,81 @@ impl Lang for Csharp<'_> {
writeln!(output, "public readonly {csharp_table_class_name} {csharp_table_name};");
});
+ // Emit top-level Cols/IxCols helpers for the typed query builder.
+ writeln!(output);
+
+ let cols_owner_name = table.name.deref().to_case(Case::Pascal);
+ let row_type = type_ref_name(module, table.product_type_ref);
+ let product_type = module.typespace_for_generate()[table.product_type_ref]
+ .as_product()
+ .unwrap();
+
+ let mut ix_col_positions: BTreeSet = BTreeSet::new();
+ for idx in iter_indexes(table) {
+ if let IndexAlgorithm::BTree(BTreeAlgorithm { columns }) = &idx.algorithm {
+ for col_pos in columns.iter() {
+ ix_col_positions.insert(col_pos.idx());
+ }
+ }
+ }
+
+ writeln!(output, "public sealed class {cols_owner_name}Cols");
+ indented_block(&mut output, |output| {
+ for (field_name, field_type) in &product_type.elements {
+ let prop = field_name.deref().to_case(Case::Pascal);
+ let ty = ty_fmt(module, field_type);
+ writeln!(
+ output,
+ "public global::SpacetimeDB.Col<{row_type}, {ty}> {prop} {{ get; }}"
+ );
+ }
+ writeln!(output);
+ writeln!(output, "public {cols_owner_name}Cols(string tableName)");
+ indented_block(output, |output| {
+ for (field_name, field_type) in &product_type.elements {
+ let prop = field_name.deref().to_case(Case::Pascal);
+ let ty = ty_fmt(module, field_type);
+ let col_name = field_name.deref();
+ writeln!(
+ output,
+ "{prop} = new global::SpacetimeDB.Col<{row_type}, {ty}>(tableName, \"{col_name}\");"
+ );
+ }
+ });
+ });
+ writeln!(output);
+
+ writeln!(output, "public sealed class {cols_owner_name}IxCols");
+ indented_block(&mut output, |output| {
+ for (i, (field_name, field_type)) in product_type.elements.iter().enumerate() {
+ if !ix_col_positions.contains(&i) {
+ continue;
+ }
+ let prop = field_name.deref().to_case(Case::Pascal);
+ let ty = ty_fmt(module, field_type);
+ writeln!(
+ output,
+ "public global::SpacetimeDB.IxCol<{row_type}, {ty}> {prop} {{ get; }}"
+ );
+ }
+ writeln!(output);
+ writeln!(output, "public {cols_owner_name}IxCols(string tableName)");
+ indented_block(output, |output| {
+ for (i, (field_name, field_type)) in product_type.elements.iter().enumerate() {
+ if !ix_col_positions.contains(&i) {
+ continue;
+ }
+ let prop = field_name.deref().to_case(Case::Pascal);
+ let ty = ty_fmt(module, field_type);
+ let col_name = field_name.deref();
+ writeln!(
+ output,
+ "{prop} = new global::SpacetimeDB.IxCol<{row_type}, {ty}>(tableName, \"{col_name}\");"
+ );
+ }
+ });
+ });
+
OutputFile {
filename: format!("Tables/{}.g.cs", table.name.deref().to_case(Case::Pascal)),
code: output.into_inner(),
@@ -961,6 +1051,80 @@ impl Lang for Csharp<'_> {
writeln!(output, "{REDUCER_EVENTS}");
+ writeln!(output, "public sealed class QueryBuilder");
+ indented_block(&mut output, |output| {
+ writeln!(output, "public From From {{ get; }} = new();");
+ });
+ writeln!(output);
+
+ writeln!(output, "public sealed class From");
+ indented_block(&mut output, |output| {
+ for (table_name, product_type_ref) in iter_table_names_and_types(module) {
+ 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());
+ writeln!(
+ output,
+ "public global::SpacetimeDB.Table<{row_type}, {method_name}Cols, {method_name}IxCols> {method_name}() => new({table_name_lit}, new {method_name}Cols({table_name_lit}), new {method_name}IxCols({table_name_lit}));"
+ );
+ }
+ });
+ writeln!(output);
+
+ writeln!(output, "public sealed class TypedSubscriptionBuilder");
+ indented_block(&mut output, |output| {
+ writeln!(output, "private readonly IDbConnection conn;");
+ writeln!(output, "private Action? Applied;");
+ writeln!(output, "private Action? Error;");
+ writeln!(output, "private readonly List querySqls = new();");
+ writeln!(output);
+
+ writeln!(
+ output,
+ "internal TypedSubscriptionBuilder(IDbConnection conn, Action? applied, Action? error)"
+ );
+ indented_block(output, |output| {
+ writeln!(output, "this.conn = conn;");
+ writeln!(output, "Applied = applied;");
+ writeln!(output, "Error = error;");
+ });
+ writeln!(output);
+
+ writeln!(
+ output,
+ "public TypedSubscriptionBuilder OnApplied(Action callback)"
+ );
+ indented_block(output, |output| {
+ writeln!(output, "Applied += callback;");
+ writeln!(output, "return this;");
+ });
+ writeln!(output);
+
+ writeln!(
+ output,
+ "public TypedSubscriptionBuilder OnError(Action callback)"
+ );
+ indented_block(output, |output| {
+ writeln!(output, "Error += callback;");
+ writeln!(output, "return this;");
+ });
+ writeln!(output);
+
+ writeln!(output, "public TypedSubscriptionBuilder AddQuery(Func> build)");
+ indented_block(output, |output| {
+ writeln!(output, "var qb = new QueryBuilder();");
+ writeln!(output, "querySqls.Add(build(qb).ToSql());");
+ writeln!(output, "return this;");
+ });
+ writeln!(output);
+
+ writeln!(
+ output,
+ "public SubscriptionHandle Subscribe() => new(conn, Applied, Error, querySqls.ToArray());"
+ );
+ });
+ writeln!(output);
+
writeln!(output, "public abstract partial class Reducer");
indented_block(&mut output, |output| {
// Prevent instantiation of this class from outside.
diff --git a/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap b/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap
index f5c0f73934a..67e2f096be1 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" = '''
@@ -1754,6 +1755,20 @@ namespace SpacetimeDB
Error += callback;
return this;
}
+
+ ///
+ /// Add a typed query to this subscription.
+ ///
+ /// This is the entry point for building subscriptions without writing SQL by hand.
+ /// Once a typed query is added, only typed queries may follow (SQL and typed queries cannot be mixed).
+ ///
+ public TypedSubscriptionBuilder AddQuery(
+ Func> build
+ )
+ {
+ var typed = new TypedSubscriptionBuilder(conn, Applied, Error);
+ return typed.AddQuery(build);
+ }
///
/// Subscribe to the following SQL queries.
@@ -1817,6 +1832,65 @@ namespace SpacetimeDB
{ }
}
+ public sealed class QueryBuilder
+ {
+ public From From { get; } = new();
+ }
+
+ 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"));
+ }
+
+ public sealed class TypedSubscriptionBuilder
+ {
+ private readonly IDbConnection conn;
+ private Action? Applied;
+ private Action? Error;
+ private readonly List querySqls = new();
+
+ internal TypedSubscriptionBuilder(IDbConnection conn, Action? applied, Action? error)
+ {
+ this.conn = conn;
+ Applied = applied;
+ Error = error;
+ }
+
+ public TypedSubscriptionBuilder OnApplied(Action callback)
+ {
+ Applied += callback;
+ return this;
+ }
+
+ public TypedSubscriptionBuilder OnError(Action callback)
+ {
+ Error += callback;
+ return this;
+ }
+
+ public TypedSubscriptionBuilder AddQuery(Func> build)
+ {
+ var qb = new QueryBuilder();
+ querySqls.Add(build(qb).Sql);
+ return this;
+ }
+
+ public SubscriptionHandle Subscribe() => new(conn, Applied, Error, querySqls.ToArray());
+ }
+
public abstract partial class Reducer
{
private Reducer() { }
@@ -1937,6 +2011,26 @@ namespace SpacetimeDB
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" = '''
@@ -1998,6 +2092,34 @@ namespace SpacetimeDB
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 global::SpacetimeDB.IxCol Name { get; }
+
+ public LoggedOutPlayerIxCols(string tableName)
+ {
+ Identity = new global::SpacetimeDB.IxCol(tableName, "identity");
+ PlayerId = new global::SpacetimeDB.IxCol(tableName, "player_id");
+ Name = new global::SpacetimeDB.IxCol(tableName, "name");
+ }
+ }
}
'''
"Tables/MyPlayer.g.cs" = '''
@@ -2027,6 +2149,28 @@ namespace SpacetimeDB
public readonly MyPlayerHandle MyPlayer;
}
+
+ public sealed class MyPlayerCols
+ {
+ public global::SpacetimeDB.Col Identity { get; }
+ public global::SpacetimeDB.Col PlayerId { get; }
+ public global::SpacetimeDB.Col Name { get; }
+
+ public MyPlayerCols(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 MyPlayerIxCols
+ {
+
+ public MyPlayerIxCols(string tableName)
+ {
+ }
+ }
}
'''
"Tables/Person.g.cs" = '''
@@ -2078,6 +2222,32 @@ namespace SpacetimeDB
public readonly PersonHandle Person;
}
+
+ public sealed class PersonCols
+ {
+ public global::SpacetimeDB.Col Id { get; }
+ public global::SpacetimeDB.Col Name { get; }
+ public global::SpacetimeDB.Col Age { get; }
+
+ public PersonCols(string tableName)
+ {
+ Id = new global::SpacetimeDB.Col(tableName, "id");
+ Name = new global::SpacetimeDB.Col(tableName, "name");
+ Age = new global::SpacetimeDB.Col(tableName, "age");
+ }
+ }
+
+ public sealed class PersonIxCols
+ {
+ public global::SpacetimeDB.IxCol Id { get; }
+ public global::SpacetimeDB.IxCol Age { get; }
+
+ public PersonIxCols(string tableName)
+ {
+ Id = new global::SpacetimeDB.IxCol(tableName, "id");
+ Age = new global::SpacetimeDB.IxCol(tableName, "age");
+ }
+ }
}
'''
"Tables/PkMultiIdentity.g.cs" = '''
@@ -2129,6 +2299,30 @@ namespace SpacetimeDB
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" = '''
@@ -2190,6 +2384,34 @@ namespace SpacetimeDB
public readonly PlayerHandle Player;
}
+
+ public sealed class PlayerCols
+ {
+ public global::SpacetimeDB.Col Identity { get; }
+ public global::SpacetimeDB.Col PlayerId { get; }
+ public global::SpacetimeDB.Col Name { get; }
+
+ public PlayerCols(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 PlayerIxCols
+ {
+ public global::SpacetimeDB.IxCol Identity { get; }
+ public global::SpacetimeDB.IxCol PlayerId { get; }
+ public global::SpacetimeDB.IxCol Name { get; }
+
+ public PlayerIxCols(string tableName)
+ {
+ Identity = new global::SpacetimeDB.IxCol(tableName, "identity");
+ PlayerId = new global::SpacetimeDB.IxCol(tableName, "player_id");
+ Name = new global::SpacetimeDB.IxCol(tableName, "name");
+ }
+ }
}
'''
"Tables/Points.g.cs" = '''
@@ -2229,6 +2451,30 @@ namespace SpacetimeDB
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" = '''
@@ -2258,6 +2504,24 @@ namespace SpacetimeDB
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" = '''
@@ -2299,6 +2563,30 @@ namespace SpacetimeDB
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" = '''
@@ -2328,6 +2616,24 @@ namespace SpacetimeDB
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" = '''
@@ -2367,6 +2673,30 @@ namespace SpacetimeDB
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" = '''
@@ -2396,6 +2726,24 @@ namespace SpacetimeDB
public readonly TestDHandle TestD;
}
+
+ public sealed class TestDCols
+ {
+ public global::SpacetimeDB.Col TestC { get; }
+
+ public TestDCols(string tableName)
+ {
+ TestC = new global::SpacetimeDB.Col(tableName, "test_c");
+ }
+ }
+
+ public sealed class TestDIxCols
+ {
+
+ public TestDIxCols(string tableName)
+ {
+ }
+ }
}
'''
"Tables/TestE.g.cs" = '''
@@ -2447,6 +2795,30 @@ namespace SpacetimeDB
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" = '''
@@ -2476,6 +2848,24 @@ namespace SpacetimeDB
public readonly TestFHandle TestF;
}
+
+ public sealed class TestFCols
+ {
+ public global::SpacetimeDB.Col Field { get; }
+
+ public TestFCols(string tableName)
+ {
+ Field = new global::SpacetimeDB.Col(tableName, "field");
+ }
+ }
+
+ public sealed class TestFIxCols
+ {
+
+ public TestFIxCols(string tableName)
+ {
+ }
+ }
}
'''
"Types/Baz.g.cs" = '''
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 f8210f1cfb5..b51e7eee1d9 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.8.0 (commit a64e8764427700df864f347417437ee0881c1226).
+// This was generated using spacetimedb cli version 1.11.2 (commit 97aa69de8942102a6ea0b50dfadea3cd15e44f50).
#nullable enable
@@ -509,6 +509,20 @@ Action callback
return this;
}
+ ///
+ /// Add a typed query to this subscription.
+ ///
+ /// This is the entry point for building subscriptions without writing SQL by hand.
+ /// Once a typed query is added, only typed queries may follow (SQL and typed queries cannot be mixed).
+ ///
+ public TypedSubscriptionBuilder AddQuery(
+ Func> build
+ )
+ {
+ var typed = new TypedSubscriptionBuilder(conn, Applied, Error);
+ return typed.AddQuery(build);
+ }
+
///
/// Subscribe to the following SQL queries.
///
@@ -572,6 +586,64 @@ string[] querySqls
{ }
}
+ public sealed class QueryBuilder
+ {
+ public From From { get; } = new();
+ }
+
+ 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
+ {
+ private readonly IDbConnection conn;
+ private Action? Applied;
+ private Action? Error;
+ private readonly List querySqls = new();
+
+ internal TypedSubscriptionBuilder(IDbConnection conn, Action? applied, Action? error)
+ {
+ this.conn = conn;
+ Applied = applied;
+ Error = error;
+ }
+
+ public TypedSubscriptionBuilder OnApplied(Action callback)
+ {
+ Applied += callback;
+ return this;
+ }
+
+ public TypedSubscriptionBuilder OnError(Action callback)
+ {
+ Error += callback;
+ return this;
+ }
+
+ public TypedSubscriptionBuilder AddQuery(Func> build)
+ {
+ var qb = new QueryBuilder();
+ querySqls.Add(build(qb).Sql);
+ return this;
+ }
+
+ public SubscriptionHandle Subscribe() => new(conn, Applied, Error, querySqls.ToArray());
+ }
+
public abstract partial class Reducer
{
private Reducer() { }
diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Circle.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Circle.g.cs
index bc664fb15fc..8ae958b6c7a 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Circle.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Circle.g.cs
@@ -46,4 +46,34 @@ internal CircleHandle(DbConnection conn) : base(conn)
public readonly CircleHandle Circle;
}
+
+ public sealed class CircleCols
+ {
+ 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 CircleCols(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 CircleIxCols
+ {
+ public global::SpacetimeDB.IxCol EntityId { get; }
+ public global::SpacetimeDB.IxCol PlayerId { get; }
+
+ public CircleIxCols(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/CircleDecayTimer.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleDecayTimer.g.cs
index db8fe6a8373..09cd0b1053b 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleDecayTimer.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleDecayTimer.g.cs
@@ -36,4 +36,26 @@ internal CircleDecayTimerHandle(DbConnection conn) : base(conn)
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/CircleRecombineTimer.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleRecombineTimer.g.cs
index aa64283f0fd..5bb48e1918b 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleRecombineTimer.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/CircleRecombineTimer.g.cs
@@ -36,4 +36,28 @@ internal CircleRecombineTimerHandle(DbConnection conn) : base(conn)
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/Config.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Config.g.cs
index 9c24535cf38..d6340962dee 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Config.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Config.g.cs
@@ -36,4 +36,26 @@ internal ConfigHandle(DbConnection conn) : base(conn)
public readonly ConfigHandle Config;
}
+
+ public sealed class ConfigCols
+ {
+ public global::SpacetimeDB.Col Id { get; }
+ public global::SpacetimeDB.Col WorldSize { get; }
+
+ public ConfigCols(string tableName)
+ {
+ Id = new global::SpacetimeDB.Col(tableName, "id");
+ WorldSize = new global::SpacetimeDB.Col(tableName, "world_size");
+ }
+ }
+
+ public sealed class ConfigIxCols
+ {
+ public global::SpacetimeDB.IxCol Id { get; }
+
+ public ConfigIxCols(string tableName)
+ {
+ Id = new global::SpacetimeDB.IxCol(tableName, "id");
+ }
+ }
}
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
index 335a6674868..991112b45b6 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityTimer.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/ConsumeEntityTimer.g.cs
@@ -36,4 +36,30 @@ internal ConsumeEntityTimerHandle(DbConnection conn) : base(conn)
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/Entity.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Entity.g.cs
index c2ca1e53672..e15bec6af06 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Entity.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Entity.g.cs
@@ -36,4 +36,28 @@ internal EntityHandle(DbConnection conn) : base(conn)
public readonly EntityHandle Entity;
}
+
+ public sealed class EntityCols
+ {
+ public global::SpacetimeDB.Col EntityId { get; }
+ public global::SpacetimeDB.Col Position { get; }
+ public global::SpacetimeDB.Col Mass { get; }
+
+ public EntityCols(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 EntityIxCols
+ {
+ public global::SpacetimeDB.IxCol EntityId { get; }
+
+ public EntityIxCols(string tableName)
+ {
+ EntityId = new global::SpacetimeDB.IxCol(tableName, "entity_id");
+ }
+ }
}
diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Food.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Food.g.cs
index d36b66ed744..7b62f84d523 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Food.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Food.g.cs
@@ -36,4 +36,24 @@ internal FoodHandle(DbConnection conn) : base(conn)
public readonly FoodHandle Food;
}
+
+ public sealed class FoodCols
+ {
+ public global::SpacetimeDB.Col EntityId { get; }
+
+ public FoodCols(string tableName)
+ {
+ EntityId = new global::SpacetimeDB.Col(tableName, "entity_id");
+ }
+ }
+
+ public sealed class FoodIxCols
+ {
+ public global::SpacetimeDB.IxCol EntityId { get; }
+
+ public FoodIxCols(string tableName)
+ {
+ EntityId = new global::SpacetimeDB.IxCol(tableName, "entity_id");
+ }
+ }
}
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
index 5d3d6fa6f60..4c56218c271 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutCircle.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutCircle.g.cs
@@ -46,4 +46,34 @@ internal LoggedOutCircleHandle(DbConnection conn) : base(conn)
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/LoggedOutEntity.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutEntity.g.cs
index fe22ef0eea3..00eec8e2b12 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutEntity.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutEntity.g.cs
@@ -36,4 +36,28 @@ internal LoggedOutEntityHandle(DbConnection conn) : base(conn)
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/LoggedOutPlayer.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutPlayer.g.cs
index eb4590f2264..035f671053e 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutPlayer.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/LoggedOutPlayer.g.cs
@@ -46,4 +46,30 @@ internal LoggedOutPlayerHandle(DbConnection conn) : base(conn)
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/MoveAllPlayersTimer.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/MoveAllPlayersTimer.g.cs
index 105dd8e2a14..b84ba4c72ef 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/MoveAllPlayersTimer.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/MoveAllPlayersTimer.g.cs
@@ -36,4 +36,26 @@ internal MoveAllPlayersTimerHandle(DbConnection conn) : base(conn)
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/Player.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Player.g.cs
index e4db13e2ad9..9250cf376e0 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Player.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/Tables/Player.g.cs
@@ -46,4 +46,30 @@ internal PlayerHandle(DbConnection conn) : base(conn)
public readonly PlayerHandle Player;
}
+
+ public sealed class PlayerCols
+ {
+ public global::SpacetimeDB.Col Identity { get; }
+ public global::SpacetimeDB.Col PlayerId { get; }
+ public global::SpacetimeDB.Col Name { get; }
+
+ public PlayerCols(string tableName)
+ {
+ Identity = new global::SpacetimeDB.Col