Skip to content

Commit 9a10dc1

Browse files
fix client codegen for views
1 parent f7ef92b commit 9a10dc1

File tree

8 files changed

+136
-76
lines changed

8 files changed

+136
-76
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: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::util::{
2-
is_reducer_invokable, iter_reducers, iter_tables, iter_types, iter_unique_cols,
3-
print_auto_generated_version_comment,
2+
is_reducer_invokable, iter_reducers, iter_table_names_and_types, iter_tables, iter_types, iter_unique_cols,
3+
iter_views, print_auto_generated_version_comment,
44
};
55
use crate::{indent_scope, OutputFile};
66

@@ -341,10 +341,9 @@ removeOnUpdate = (cb: (ctx: EventContext, onRow: {row_type}, newRow: {row_type})
341341

342342
writeln!(out);
343343
writeln!(out, "// Import and reexport all table handle types");
344-
for table in iter_tables(module) {
345-
let table_name = &table.name;
344+
for (table_name, _) in iter_table_names_and_types(module) {
346345
let table_module_name = table_module_name(table_name) + ".ts";
347-
let table_name_pascalcase = table.name.deref().to_case(Case::Pascal);
346+
let table_name_pascalcase = table_name.deref().to_case(Case::Pascal);
348347
let table_handle = table_name_pascalcase.clone() + "TableHandle";
349348
writeln!(out, "import {{ {table_handle} }} from \"./{table_module_name}\";");
350349
writeln!(out, "export {{ {table_handle} }};");
@@ -366,15 +365,31 @@ removeOnUpdate = (cb: (ctx: EventContext, onRow: {row_type}, newRow: {row_type})
366365
out.indent(1);
367366
writeln!(out, "tables: {{");
368367
out.indent(1);
369-
for table in iter_tables(module) {
370-
let type_ref = table.product_type_ref;
368+
for (table_name, product_type_ref, schema) in itertools::chain!(
369+
iter_tables(module).map(|def| {
370+
(
371+
&def.name,
372+
def.product_type_ref,
373+
TableSchema::from_module_def(module, def, (), 0.into()),
374+
)
375+
}),
376+
iter_views(module).map(|def| {
377+
(
378+
&def.name,
379+
def.product_type_ref,
380+
TableSchema::from_view_def_for_codegen(module, def),
381+
)
382+
})
383+
) {
384+
let table_name = table_name.deref();
385+
let type_ref = product_type_ref;
371386
let row_type = type_ref_name(module, type_ref);
372-
let schema = TableSchema::from_module_def(module, table, (), 0.into())
387+
let schema = schema
373388
.validated()
374389
.expect("Failed to generate table due to validation errors");
375-
writeln!(out, "{}: {{", table.name);
390+
writeln!(out, "{}: {{", table_name);
376391
out.indent(1);
377-
writeln!(out, "tableName: \"{}\" as const,", table.name);
392+
writeln!(out, "tableName: \"{}\" as const,", table_name);
378393
writeln!(out, "rowType: {row_type}.getTypeScriptAlgebraicType(),");
379394
if let Some(pk) = schema.pk() {
380395
// This is left here so we can release the codegen change before releasing a new
@@ -612,13 +627,13 @@ fn print_remote_tables(module: &ModuleDef, out: &mut Indenter) {
612627
out.indent(1);
613628
writeln!(out, "constructor(private connection: __DbConnectionImpl) {{}}");
614629

615-
for table in iter_tables(module) {
630+
for (table_name, product_type_ref) in iter_table_names_and_types(module) {
616631
writeln!(out);
617-
let table_name = table.name.deref();
618-
let table_name_pascalcase = table.name.deref().to_case(Case::Pascal);
619-
let table_name_camelcase = table.name.deref().to_case(Case::Camel);
632+
let table_name = table_name.deref();
633+
let table_name_pascalcase = table_name.to_case(Case::Pascal);
634+
let table_name_camelcase = table_name.to_case(Case::Camel);
620635
let table_handle = table_name_pascalcase.clone() + "TableHandle";
621-
let type_ref = table.product_type_ref;
636+
let type_ref = product_type_ref;
622637
let row_type = type_ref_name(module, type_ref);
623638
writeln!(out, "get {table_name_camelcase}(): {table_handle}<'{table_name}'> {{");
624639
out.with_indent(|out| {

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
}

0 commit comments

Comments
 (0)