Skip to content

Commit f5fb729

Browse files
fix client codegen for views
1 parent ce54385 commit f5fb729

File tree

6 files changed

+87
-60
lines changed

6 files changed

+87
-60
lines changed

crates/codegen/src/csharp.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use std::ops::Deref;
77
use super::code_indenter::CodeIndenter;
88
use super::Lang;
99
use crate::util::{
10-
collect_case, is_reducer_invokable, iter_indexes, iter_reducers, iter_tables, print_auto_generated_file_comment,
11-
print_auto_generated_version_comment, type_ref_name,
10+
collect_case, is_reducer_invokable, iter_indexes, iter_reducers, iter_table_names_and_types,
11+
print_auto_generated_file_comment, print_auto_generated_version_comment, type_ref_name,
1212
};
1313
use crate::{indent_scope, OutputFile};
1414
use convert_case::{Case, Casing};
@@ -745,11 +745,11 @@ impl Lang for Csharp<'_> {
745745
indented_block(&mut output, |output| {
746746
writeln!(output, "public RemoteTables(DbConnection conn)");
747747
indented_block(output, |output| {
748-
for table in iter_tables(module) {
748+
for (table_name, _) in iter_table_names_and_types(module) {
749749
writeln!(
750750
output,
751751
"AddTable({} = new(conn));",
752-
table.name.deref().to_case(Case::Pascal)
752+
table_name.deref().to_case(Case::Pascal)
753753
);
754754
}
755755
});

crates/codegen/src/rust.rs

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use super::code_indenter::{CodeIndenter, Indenter};
22
use super::util::{collect_case, iter_reducers, print_lines, type_ref_name};
33
use super::Lang;
44
use crate::util::{
5-
iter_procedures, iter_tables, iter_types, iter_unique_cols, print_auto_generated_file_comment,
6-
print_auto_generated_version_comment,
5+
iter_procedures, iter_table_names_and_types, iter_tables, iter_types, iter_unique_cols, iter_views,
6+
print_auto_generated_file_comment, print_auto_generated_version_comment,
77
};
88
use crate::OutputFile;
99
use convert_case::{Case, Casing};
@@ -930,12 +930,13 @@ fn reducer_flags_trait_name(reducer: &ReducerDef) -> String {
930930
format!("set_flags_for_{}", reducer_function_name(reducer))
931931
}
932932

933-
/// Iterate over all of the Rust `mod`s for types, reducers and tables in the `module`.
933+
/// Iterate over all of the Rust `mod`s for types, reducers, views, and tables in the `module`.
934934
fn iter_module_names(module: &ModuleDef) -> impl Iterator<Item = String> + '_ {
935935
itertools::chain!(
936936
iter_types(module).map(|ty| type_module_name(&ty.name)),
937937
iter_reducers(module).map(|r| reducer_module_name(&r.name)),
938938
iter_tables(module).map(|tbl| table_module_name(&tbl.name)),
939+
iter_views(module).map(|view| table_module_name(&view.name)),
939940
iter_procedures(module).map(|proc| procedure_module_name(&proc.name)),
940941
)
941942
}
@@ -954,8 +955,8 @@ fn print_module_reexports(module: &ModuleDef, out: &mut Indenter) {
954955
let type_name = collect_case(Case::Pascal, ty.name.name_segments());
955956
writeln!(out, "pub use {mod_name}::{type_name};")
956957
}
957-
for table in iter_tables(module) {
958-
let mod_name = table_module_name(&table.name);
958+
for (table_name, _) in iter_table_names_and_types(module) {
959+
let mod_name = table_module_name(table_name);
959960
// TODO: More precise reexport: we want:
960961
// - The trait name.
961962
// - The insert, delete and possibly update callback ids.
@@ -1113,12 +1114,12 @@ fn print_db_update_defn(module: &ModuleDef, out: &mut Indenter) {
11131114
out.delimited_block(
11141115
"pub struct DbUpdate {",
11151116
|out| {
1116-
for table in iter_tables(module) {
1117+
for (table_name, product_type_ref) in iter_table_names_and_types(module) {
11171118
writeln!(
11181119
out,
11191120
"{}: __sdk::TableUpdate<{}>,",
1120-
table_method_name(&table.name),
1121-
type_ref_name(module, table.product_type_ref),
1121+
table_method_name(table_name),
1122+
type_ref_name(module, product_type_ref),
11221123
);
11231124
}
11241125
},
@@ -1137,13 +1138,13 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate {
11371138
match &table_update.table_name[..] {
11381139
",
11391140
|out| {
1140-
for table in iter_tables(module) {
1141+
for (table_name, _) in iter_table_names_and_types(module) {
11411142
writeln!(
11421143
out,
11431144
"{:?} => db_update.{}.append({}::parse_table_update(table_update)?),",
1144-
table.name.deref(),
1145-
table_method_name(&table.name),
1146-
table_module_name(&table.name),
1145+
table_name.deref(),
1146+
table_method_name(table_name),
1147+
table_module_name(table_name),
11471148
);
11481149
}
11491150
},
@@ -1181,21 +1182,28 @@ impl __sdk::InModule for DbUpdate {{
11811182
let mut diff = AppliedDiff::default();
11821183
",
11831184
|out| {
1184-
for table in iter_tables(module) {
1185-
let with_updates = table
1186-
.primary_key
1187-
.map(|col| {
1188-
let pk_field = table.get_column(col).unwrap().name.deref().to_case(Case::Snake);
1189-
format!(".with_updates_by_pk(|row| &row.{pk_field})")
1190-
})
1191-
.unwrap_or_default();
1192-
1193-
let field_name = table_method_name(&table.name);
1185+
for (table_name, product_type_ref, with_updates) in itertools::chain!(
1186+
iter_tables(module).map(|table| {
1187+
(
1188+
&table.name,
1189+
table.product_type_ref,
1190+
table
1191+
.primary_key
1192+
.map(|col| {
1193+
let pk_field = table.get_column(col).unwrap().name.deref().to_case(Case::Snake);
1194+
format!(".with_updates_by_pk(|row| &row.{pk_field})")
1195+
})
1196+
.unwrap_or_default(),
1197+
)
1198+
}),
1199+
iter_views(module).map(|view| (&view.name, view.product_type_ref, "".into()))
1200+
) {
1201+
let field_name = table_method_name(table_name);
11941202
writeln!(
11951203
out,
11961204
"diff.{field_name} = cache.apply_diff_to_table::<{}>({:?}, &self.{field_name}){with_updates};",
1197-
type_ref_name(module, table.product_type_ref),
1198-
table.name.deref(),
1205+
type_ref_name(module, product_type_ref),
1206+
table_name.deref(),
11991207
);
12001208
}
12011209
},
@@ -1215,12 +1223,12 @@ fn print_applied_diff_defn(module: &ModuleDef, out: &mut Indenter) {
12151223
out.delimited_block(
12161224
"pub struct AppliedDiff<'r> {",
12171225
|out| {
1218-
for table in iter_tables(module) {
1226+
for (table_name, product_type_ref) in iter_table_names_and_types(module) {
12191227
writeln!(
12201228
out,
12211229
"{}: __sdk::TableAppliedDiff<'r, {}>,",
1222-
table_method_name(&table.name),
1223-
type_ref_name(module, table.product_type_ref),
1230+
table_method_name(table_name),
1231+
type_ref_name(module, product_type_ref),
12241232
);
12251233
}
12261234
// Also write a `PhantomData` field which uses the lifetime `r`,
@@ -1248,13 +1256,13 @@ impl __sdk::InModule for AppliedDiff<'_> {{
12481256
out.delimited_block(
12491257
"fn invoke_row_callbacks(&self, event: &EventContext, callbacks: &mut __sdk::DbCallbacks<RemoteModule>) {",
12501258
|out| {
1251-
for table in iter_tables(module) {
1259+
for (table_name, product_type_ref) in iter_table_names_and_types(module) {
12521260
writeln!(
12531261
out,
12541262
"callbacks.invoke_table_row_callbacks::<{}>({:?}, &self.{}, event);",
1255-
type_ref_name(module, table.product_type_ref),
1256-
table.name.deref(),
1257-
table_method_name(&table.name),
1263+
type_ref_name(module, product_type_ref),
1264+
table_name.deref(),
1265+
table_method_name(table_name),
12581266
);
12591267
}
12601268
},
@@ -1290,8 +1298,8 @@ type SubscriptionHandle = SubscriptionHandle;
12901298
out.delimited_block(
12911299
"fn register_tables(client_cache: &mut __sdk::ClientCache<Self>) {",
12921300
|out| {
1293-
for table in iter_tables(module) {
1294-
writeln!(out, "{}::register_table(client_cache);", table_module_name(&table.name));
1301+
for (table_name, _) in iter_table_names_and_types(module) {
1302+
writeln!(out, "{}::register_table(client_cache);", table_module_name(table_name));
12951303
}
12961304
},
12971305
"}\n",

crates/codegen/src/unrealcpp.rs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//! Autogenerated Unreal‑C++ code‑gen backend for SpacetimeDB CLI
22
use crate::code_indenter::CodeIndenter;
33
use crate::util::{
4-
collect_case, fmt_fn, iter_tables, print_auto_generated_file_comment, print_auto_generated_version_comment,
4+
collect_case, fmt_fn, iter_table_names_and_types, print_auto_generated_file_comment,
5+
print_auto_generated_version_comment,
56
};
67
use crate::util::{iter_indexes, iter_reducers};
78
use crate::Lang;
@@ -683,8 +684,8 @@ impl Lang for UnrealCpp<'_> {
683684
writeln!(client_h);
684685

685686
writeln!(client_h, "/** Forward declaration for tables */");
686-
for table in iter_tables(module) {
687-
let table_pascal = type_ref_name(module, table.product_type_ref);
687+
for (_, product_type_ref) in iter_table_names_and_types(module) {
688+
let table_pascal = type_ref_name(module, product_type_ref);
688689
writeln!(client_h, "class U{table_pascal}Table;");
689690
}
690691
writeln!(client_h, "/***/");
@@ -774,12 +775,11 @@ impl Lang for UnrealCpp<'_> {
774775
});
775776

776777
// Build table includes
777-
let table_includes: Vec<String> = module
778-
.tables()
779-
.map(|table| {
778+
let table_includes: Vec<String> = iter_table_names_and_types(module)
779+
.map(|(_, product_type_ref)| {
780780
format!(
781781
"ModuleBindings/Tables/{}Table.g.h",
782-
type_ref_name(module, table.product_type_ref)
782+
type_ref_name(module, product_type_ref)
783783
)
784784
})
785785
.collect();
@@ -1856,14 +1856,14 @@ fn generate_remote_tables_class(output: &mut UnrealCppAutogen, module: &ModuleDe
18561856
writeln!(output);
18571857

18581858
// Generate table handle properties
1859-
for table in module.tables() {
1860-
let table_pascal = type_ref_name(module, table.product_type_ref);
1859+
for (table_name, product_type_ref) in iter_table_names_and_types(module) {
1860+
let table_pascal = type_ref_name(module, product_type_ref);
18611861

18621862
writeln!(output, " UPROPERTY(BlueprintReadOnly, Category=\"SpacetimeDB\")");
18631863
writeln!(
18641864
output,
18651865
" U{table_pascal}Table* {};",
1866-
table.name.deref().to_case(Case::Pascal)
1866+
table_name.deref().to_case(Case::Pascal)
18671867
);
18681868
writeln!(output);
18691869
}
@@ -2357,16 +2357,16 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module
23572357
writeln!(output, "\tReducers->SetCallReducerFlags = SetReducerFlags;");
23582358
writeln!(output, "\tReducers->Conn = this;");
23592359
writeln!(output);
2360-
for table in module.tables() {
2361-
let table_pascal = type_ref_name(module, table.product_type_ref);
2362-
let table_name = table.name.deref();
2360+
for (table_name, product_type_ref) in iter_table_names_and_types(module) {
2361+
let table_pascal = type_ref_name(module, product_type_ref);
2362+
let table_name = table_name.deref();
23632363
writeln!(
23642364
output,
23652365
"\tRegisterTable<F{}Type, U{}Table, FEventContext>(TEXT(\"{}\"), Db->{});",
23662366
table_pascal,
23672367
table_pascal,
23682368
table_name,
2369-
table.name.deref().to_case(Case::Pascal)
2369+
table_name.to_case(Case::Pascal)
23702370
);
23712371
}
23722372
writeln!(output, "}}");
@@ -2412,23 +2412,23 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module
24122412
writeln!(output, "{{");
24132413
writeln!(output);
24142414
writeln!(output, "\t/** Creating tables */");
2415-
for table in module.tables() {
2416-
let table_pascal = type_ref_name(module, table.product_type_ref);
2415+
for (table_name, product_type_ref) in iter_table_names_and_types(module) {
2416+
let table_pascal = type_ref_name(module, product_type_ref);
24172417
writeln!(
24182418
output,
24192419
"\t{} = NewObject<U{}Table>(this);",
2420-
table.name.deref().to_case(Case::Pascal),
2420+
table_name.deref().to_case(Case::Pascal),
24212421
table_pascal
24222422
);
24232423
}
24242424
writeln!(output, "\t/**/");
24252425
writeln!(output);
24262426
writeln!(output, "\t/** Initialization */");
2427-
for table in module.tables() {
2427+
for (table_name, _) in iter_table_names_and_types(module) {
24282428
writeln!(
24292429
output,
24302430
"\t{}->PostInitialize();",
2431-
table.name.deref().to_case(Case::Pascal)
2431+
table_name.deref().to_case(Case::Pascal)
24322432
);
24332433
}
24342434
writeln!(output, "\t/**/");
@@ -3095,10 +3095,8 @@ fn collect_optional_types(module: &ModuleDef) -> HashSet<String> {
30953095
}
30963096

30973097
// Collect from all tables
3098-
for table in module.tables() {
3099-
let product_type = module.typespace_for_generate()[table.product_type_ref]
3100-
.as_product()
3101-
.unwrap();
3098+
for (_, product_type_ref) in iter_table_names_and_types(module) {
3099+
let product_type = module.typespace_for_generate()[product_type_ref].as_product().unwrap();
31023100
for (_, field_ty) in &product_type.elements {
31033101
collect_from_type(module, field_ty, &mut optional_types);
31043102
}

crates/codegen/src/util.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,18 @@ pub(super) fn iter_tables(module: &ModuleDef) -> impl Iterator<Item = &TableDef>
115115
module.tables().sorted_by_key(|table| &table.name)
116116
}
117117

118+
/// Iterate over all the table names defined by the module (in alphabetical order) and their product types.
119+
/// Note, this also includes view names because from the perspective of codegen, views are tables.
120+
///
121+
/// Sorting is necessary to have deterministic reproducible codegen.
122+
pub(super) fn iter_table_names_and_types(module: &ModuleDef) -> impl Iterator<Item = (&Identifier, AlgebraicTypeRef)> {
123+
module
124+
.tables()
125+
.map(|def| (&def.name, def.product_type_ref))
126+
.chain(module.views().map(|def| (&def.name, def.product_type_ref)))
127+
.sorted_by_key(|(name, _)| *name)
128+
}
129+
118130
/// Iterate over all the [`ViewDef`]s defined by the module, in alphabetical order by name.
119131
///
120132
/// Sorting is necessary to have deterministic reproducible codegen.

crates/codegen/tests/snapshots/codegen__codegen_csharp.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,7 @@ namespace SpacetimeDB
10111011
{
10121012
AddTable(HasSpecialStuff = new(conn));
10131013
AddTable(LoggedOutPlayer = new(conn));
1014+
AddTable(MyPlayer = new(conn));
10141015
AddTable(Person = new(conn));
10151016
AddTable(PkMultiIdentity = new(conn));
10161017
AddTable(Player = new(conn));

crates/codegen/tests/snapshots/codegen__codegen_rust.snap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,7 @@ pub mod test_a_table;
14211421
pub mod test_d_table;
14221422
pub mod test_e_table;
14231423
pub mod test_f_table;
1424+
pub mod my_player_table;
14241425
pub mod return_value_procedure;
14251426
pub mod sleep_one_second_procedure;
14261427

@@ -1442,6 +1443,7 @@ pub use namespace_test_c_type::NamespaceTestC;
14421443
pub use namespace_test_f_type::NamespaceTestF;
14431444
pub use has_special_stuff_table::*;
14441445
pub use logged_out_player_table::*;
1446+
pub use my_player_table::*;
14451447
pub use person_table::*;
14461448
pub use pk_multi_identity_table::*;
14471449
pub use player_table::*;
@@ -1568,6 +1570,7 @@ fn try_from(value: __ws::ReducerCallInfo<__ws::BsatnFormat>) -> __sdk::Result<Se
15681570
pub struct DbUpdate {
15691571
has_special_stuff: __sdk::TableUpdate<HasSpecialStuff>,
15701572
logged_out_player: __sdk::TableUpdate<Player>,
1573+
my_player: __sdk::TableUpdate<Player>,
15711574
person: __sdk::TableUpdate<Person>,
15721575
pk_multi_identity: __sdk::TableUpdate<PkMultiIdentity>,
15731576
player: __sdk::TableUpdate<Player>,
@@ -1590,6 +1593,7 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate {
15901593

15911594
"has_special_stuff" => db_update.has_special_stuff.append(has_special_stuff_table::parse_table_update(table_update)?),
15921595
"logged_out_player" => db_update.logged_out_player.append(logged_out_player_table::parse_table_update(table_update)?),
1596+
"my_player" => db_update.my_player.append(my_player_table::parse_table_update(table_update)?),
15931597
"person" => db_update.person.append(person_table::parse_table_update(table_update)?),
15941598
"pk_multi_identity" => db_update.pk_multi_identity.append(pk_multi_identity_table::parse_table_update(table_update)?),
15951599
"player" => db_update.player.append(player_table::parse_table_update(table_update)?),
@@ -1634,6 +1638,7 @@ impl __sdk::DbUpdate for DbUpdate {
16341638
diff.test_d = cache.apply_diff_to_table::<TestD>("test_d", &self.test_d);
16351639
diff.test_e = cache.apply_diff_to_table::<TestE>("test_e", &self.test_e).with_updates_by_pk(|row| &row.id);
16361640
diff.test_f = cache.apply_diff_to_table::<TestFoobar>("test_f", &self.test_f);
1641+
diff.my_player = cache.apply_diff_to_table::<Player>("my_player", &self.my_player);
16371642

16381643
diff
16391644
}
@@ -1645,6 +1650,7 @@ impl __sdk::DbUpdate for DbUpdate {
16451650
pub struct AppliedDiff<'r> {
16461651
has_special_stuff: __sdk::TableAppliedDiff<'r, HasSpecialStuff>,
16471652
logged_out_player: __sdk::TableAppliedDiff<'r, Player>,
1653+
my_player: __sdk::TableAppliedDiff<'r, Player>,
16481654
person: __sdk::TableAppliedDiff<'r, Person>,
16491655
pk_multi_identity: __sdk::TableAppliedDiff<'r, PkMultiIdentity>,
16501656
player: __sdk::TableAppliedDiff<'r, Player>,
@@ -1667,6 +1673,7 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> {
16671673
fn invoke_row_callbacks(&self, event: &EventContext, callbacks: &mut __sdk::DbCallbacks<RemoteModule>) {
16681674
callbacks.invoke_table_row_callbacks::<HasSpecialStuff>("has_special_stuff", &self.has_special_stuff, event);
16691675
callbacks.invoke_table_row_callbacks::<Player>("logged_out_player", &self.logged_out_player, event);
1676+
callbacks.invoke_table_row_callbacks::<Player>("my_player", &self.my_player, event);
16701677
callbacks.invoke_table_row_callbacks::<Person>("person", &self.person, event);
16711678
callbacks.invoke_table_row_callbacks::<PkMultiIdentity>("pk_multi_identity", &self.pk_multi_identity, event);
16721679
callbacks.invoke_table_row_callbacks::<Player>("player", &self.player, event);
@@ -2395,6 +2402,7 @@ impl __sdk::SpacetimeModule for RemoteModule {
23952402
fn register_tables(client_cache: &mut __sdk::ClientCache<Self>) {
23962403
has_special_stuff_table::register_table(client_cache);
23972404
logged_out_player_table::register_table(client_cache);
2405+
my_player_table::register_table(client_cache);
23982406
person_table::register_table(client_cache);
23992407
pk_multi_identity_table::register_table(client_cache);
24002408
player_table::register_table(client_cache);

0 commit comments

Comments
 (0)