Skip to content

Commit 65e12df

Browse files
fix client codegen for views
1 parent ce54385 commit 65e12df

File tree

7 files changed

+83
-68
lines changed

7 files changed

+83
-68
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/typescript.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::util::{
2-
is_reducer_invokable, iter_constraints, iter_indexes, iter_reducers, iter_table_and_view_names, iter_tables,
2+
is_reducer_invokable, iter_constraints, iter_indexes, iter_reducers, iter_table_names_and_types, iter_tables,
33
iter_types, iter_views, print_auto_generated_version_comment,
44
};
55
use crate::OutputFile;
@@ -195,7 +195,7 @@ impl Lang for TypeScript {
195195

196196
writeln!(out);
197197
writeln!(out, "// Import and reexport all table handle types");
198-
for table_name in iter_table_and_view_names(module) {
198+
for (table_name, _) in iter_table_names_and_types(module) {
199199
let table_module_name = table_module_name(table_name);
200200
let table_name_pascalcase = table_name.deref().to_case(Case::Pascal);
201201
// TODO: This really shouldn't be necessary. We could also have `table()` accept

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: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,12 @@ pub(super) fn iter_views(module: &ModuleDef) -> impl Iterator<Item = &ViewDef> {
125125
/// Iterate over the names of all the tables and views defined by the module, in alphabetical order.
126126
///
127127
/// Sorting is necessary to have deterministic reproducible codegen.
128-
pub(super) fn iter_table_and_view_names(module: &ModuleDef) -> impl Iterator<Item = &Identifier> {
129-
itertools::chain(
130-
module.tables().map(|table| &table.name),
131-
module.views().map(|view| &view.name),
132-
)
133-
.sorted()
128+
pub(super) fn iter_table_names_and_types(module: &ModuleDef) -> impl Iterator<Item = (&Identifier, AlgebraicTypeRef)> {
129+
module
130+
.tables()
131+
.map(|def| (&def.name, def.product_type_ref))
132+
.chain(module.views().map(|def| (&def.name, def.product_type_ref)))
133+
.sorted_by_key(|(name, _)| *name)
134134
}
135135

136136
pub(super) fn iter_unique_cols<'a>(

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));

0 commit comments

Comments
 (0)