Skip to content

Commit 0188ee2

Browse files
authored
Merge branch 'jlarabie/csharp-view-ns' into rekhoff/csharp_replication_test_with_views
2 parents 594c4d1 + a6ebefd commit 0188ee2

24 files changed

Lines changed: 401 additions & 129 deletions

File tree

crates/cli/src/config.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,10 +1114,12 @@ protocol =1
11141114
let config_path = CliTomlPath::from_path_unchecked(tmp.path().join("config.toml"));
11151115

11161116
let mut local = Config::load(config_path.clone()).unwrap();
1117-
let mut testnet = Config::load(config_path.clone()).unwrap();
1117+
let mut testnet = local.clone();
1118+
let mut maincloud = local.clone();
11181119

11191120
local.home.default_server = Some("local".to_string());
11201121
testnet.home.default_server = Some("testnet".to_string());
1122+
maincloud.home.default_server = Some("maincloud".to_string());
11211123

11221124
let mut handles = vec![];
11231125
let total_threads: usize = 8;
@@ -1154,11 +1156,12 @@ protocol =1
11541156
}
11551157
let local = local.doc().to_string();
11561158
let testnet = testnet.doc().to_string();
1159+
let maincloud = maincloud.doc().to_string();
11571160

11581161
// As long the results are any valid config, we're good.
11591162
assert!(results
11601163
.iter()
1161-
.all(|r| r.trim() == local.trim() || r.trim() == testnet.trim()));
1164+
.all(|r| r.trim() == local.trim() || r.trim() == testnet.trim() || r.trim() == maincloud.trim()));
11621165
Ok(())
11631166
}
11641167
}

crates/cli/src/subcommands/generate.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ pub async fn exec_ex(
252252
}
253253
}
254254

255-
if let Err(err) = lang.format_files(paths) {
255+
if let Err(err) = lang.format_files(out_dir, paths) {
256256
// If we couldn't format the files, print a warning but don't fail the entire
257257
// task as the output should still be usable, just less pretty.
258258
eprintln!("Could not format generated files: {err}");
@@ -285,10 +285,10 @@ impl clap::ValueEnum for Language {
285285
}
286286

287287
impl Language {
288-
fn format_files(&self, generated_files: BTreeSet<PathBuf>) -> anyhow::Result<()> {
288+
fn format_files(&self, project_dir: &PathBuf, generated_files: BTreeSet<PathBuf>) -> anyhow::Result<()> {
289289
match self {
290290
Language::Rust => rustfmt(generated_files)?,
291-
Language::Csharp => dotnet_format(generated_files)?,
291+
Language::Csharp => dotnet_format(project_dir, generated_files)?,
292292
Language::TypeScript => {
293293
// TODO: implement formatting.
294294
}

crates/cli/src/tasks/csharp.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ pub(crate) fn build_csharp(project_path: &Path, build_debug: bool) -> anyhow::Re
108108
anyhow::bail!("Built project successfully but couldn't find the output file.");
109109
}
110110

111-
pub(crate) fn dotnet_format(files: impl IntoIterator<Item = PathBuf>) -> anyhow::Result<()> {
111+
pub(crate) fn dotnet_format(project_dir: &PathBuf, files: impl IntoIterator<Item = PathBuf>) -> anyhow::Result<()> {
112112
duct::cmd(
113113
"dotnet",
114114
itertools::chain(
@@ -128,6 +128,8 @@ pub(crate) fn dotnet_format(files: impl IntoIterator<Item = PathBuf>) -> anyhow:
128128
files.into_iter().map_into(),
129129
),
130130
)
131+
// This is important because we're running with `--folder`. We want to format the right folder!
132+
.dir(project_dir)
131133
.run()?;
132134
Ok(())
133135
}
Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
mod module_bindings;
22
use module_bindings::*;
33
use std::env;
4+
use std::io::{self, Read};
45

5-
use spacetimedb_sdk::{DbConnection, Table};
6+
use spacetimedb_sdk::{DbContext, Table};
67

78
fn main() {
89
// The URI of the SpacetimeDB instance hosting our chat module.
@@ -14,28 +15,31 @@ fn main() {
1415
// Connect to the database
1516
let conn = DbConnection::builder()
1617
.with_module_name(db_name)
17-
.with_host(host)
18+
.with_uri(host)
1819
.on_connect(|_, _, _| {
1920
println!("Connected to SpacetimeDB");
2021
})
21-
.on_connect_error(|e| {
22+
.on_connect_error(|_ctx, e| {
2223
eprintln!("Connection error: {:?}", e);
2324
std::process::exit(1);
2425
})
2526
.build()
2627
.expect("Failed to connect");
2728

29+
conn.run_threaded();
30+
2831
// Subscribe to the person table
29-
conn.subscribe(&[
30-
"SELECT * FROM person"
31-
]);
32+
conn.subscription_builder()
33+
.on_applied(|_ctx| println!("Subscripted to the person table"))
34+
.on_error(|_ctx, e| eprintln!("There was an error when subscring to the person table: {e}"))
35+
.subscribe(["SELECT * FROM person"]);
3236

3337
// Register a callback for when rows are inserted into the person table
34-
Person::on_insert(|_ctx, person| {
38+
conn.db().person().on_insert(|_ctx, person| {
3539
println!("New person: {}", person.name);
3640
});
3741

38-
// Run the connection on the current thread
39-
// This will block and handle all database events
40-
conn.run();
42+
println!("Press any key to exit...");
43+
44+
let _ = io::stdin().read(&mut [0u8]).unwrap();
4145
}

crates/cli/templates/basic-rust/server/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use spacetimedb::{ReducerContext, Table};
22

3-
#[spacetimedb::table(name = person)]
3+
#[spacetimedb::table(name = person, public)]
44
pub struct Person {
55
name: String,
66
}

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| {

0 commit comments

Comments
 (0)