From 276e455012f537b8cb8d6a023627c6ba358d4ec1 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Mon, 23 Mar 2026 10:10:28 -0700 Subject: [PATCH 1/4] Working first pass before refactoring --- .gitattributes | 1 + crates/codegen/src/unrealcpp.rs | 351 +- .../Public/Connection/DbConnectionBase.h | 2 +- .../SpacetimeDbSdk/Public/QueryBuilder/expr.h | 376 ++ .../SpacetimeDbSdk/Public/QueryBuilder/join.h | 415 ++ .../Public/QueryBuilder/query_builder.h | 99 + .../Public/QueryBuilder/table.h | 307 ++ .../ModuleBindings/SpacetimeDBClient.g.cpp | 23 +- .../Tests/SpacetimeFullClientTests.cpp | 40 + .../ModuleBindings/SpacetimeDBClient.g.h | 4154 ++++++++++++++++- .../Types/EnumWithPayloadType.g.h | 4 +- .../ModuleBindings/SpacetimeDBClient.g.cpp | 23 +- .../ModuleBindings/SpacetimeDBClient.g.h | 172 +- sdks/unreal/tests/TestViewClient/.vsconfig | 17 + .../TestViewClient/Config/DefaultEditor.ini | 0 .../DefaultEditorPerProjectUserSettings.ini | 5 + .../TestViewClient/Config/DefaultEngine.ini | 57 + .../TestViewClient/Config/DefaultGame.ini | 5 + .../TestViewClient/Config/DefaultInput.ini | 85 + .../Source/TestViewClient.Target.cs | 15 + .../ModuleBindings/SpacetimeDBClient.g.cpp | 584 +++ .../Tables/MyPlayerAndLevelTable.g.cpp | 35 + .../ModuleBindings/Tables/MyPlayerTable.g.cpp | 35 + .../Tables/NearbyPlayersTable.g.cpp | 35 + .../Tables/PlayerLevelTable.g.cpp | 53 + .../ModuleBindings/Tables/PlayerTable.g.cpp | 52 + .../Tables/PlayersAtLevel0Table.g.cpp | 35 + .../Private/Tests/CommonTestFunctions.cpp | 1 + .../Tests/SpacetimeFullClientTests.cpp | 65 + .../Private/Tests/TestCounter.cpp | 87 + .../Private/Tests/TestHandler.cpp | 1 + .../Public/ModuleBindings/ReducerBase.g.h | 18 + .../ModuleBindings/Reducers/DeletePlayer.g.h | 54 + .../ModuleBindings/Reducers/InsertPlayer.g.h | 59 + .../ModuleBindings/Reducers/MovePlayer.g.h | 58 + .../ModuleBindings/SpacetimeDBClient.g.h | 1153 +++++ .../Tables/MyPlayerAndLevelTable.g.h | 64 + .../ModuleBindings/Tables/MyPlayerTable.g.h | 64 + .../Tables/NearbyPlayersTable.g.h | 64 + .../Tables/PlayerLevelTable.g.h | 141 + .../ModuleBindings/Tables/PlayerTable.g.h | 144 + .../Tables/PlayersAtLevel0Table.g.h | 64 + .../Types/PlayerAndLevelType.g.h | 54 + .../ModuleBindings/Types/PlayerLevelType.g.h | 49 + .../Types/PlayerLocationType.g.h | 57 + .../ModuleBindings/Types/PlayerType.g.h | 50 + .../Public/Tests/CommonTestFunctions.h | 1 + .../Public/Tests/PrimitiveHandlerList.def | 1 + .../Public/Tests/SpacetimeFullClientTests.h | 16 + .../TestViewClient/Public/Tests/TestCounter.h | 35 + .../TestViewClient/Public/Tests/TestHandler.h | 3 + .../Public/Tests/UmbreallaHeaderReducers.h | 1 + .../Public/Tests/UmbreallaHeaderTypes.h | 1 + .../Public/Tests/UmbreallaHeaderaTables.h | 1 + .../TestViewClient/TestViewClient.Build.cs | 25 + .../Source/TestViewClient/TestViewClient.cpp | 6 + .../Source/TestViewClient/TestViewClient.h | 6 + .../TestViewClientGameModeBase.cpp | 5 + .../TestViewClientGameModeBase.h | 17 + .../Source/TestViewClientEditor.Target.cs | 15 + .../TestViewClient/TestViewClient.uproject | 25 + sdks/unreal/tests/TestViewPkClient/.vsconfig | 17 + .../TestViewPkClient/Config/DefaultEditor.ini | 0 .../DefaultEditorPerProjectUserSettings.ini | 5 + .../TestViewPkClient/Config/DefaultEngine.ini | 57 + .../TestViewPkClient/Config/DefaultGame.ini | 5 + .../TestViewPkClient/Config/DefaultInput.ini | 85 + .../Source/TestViewPkClient.Target.cs | 15 + .../ModuleBindings/SpacetimeDBClient.g.cpp | 636 +++ .../Tables/AllViewPkPlayersTable.g.cpp | 42 + .../Tables/SenderViewPkPlayersATable.g.cpp | 42 + .../Tables/SenderViewPkPlayersBTable.g.cpp | 42 + .../ViewPkMembershipSecondaryTable.g.cpp | 60 + .../Tables/ViewPkMembershipTable.g.cpp | 60 + .../Tables/ViewPkPlayerTable.g.cpp | 47 + .../Private/Tests/CommonTestFunctions.cpp | 171 + .../Tests/SpacetimeFullClientTests.cpp | 220 + .../Private/Tests/TestCounter.cpp | 87 + .../Private/Tests/TestHandler.cpp | 88 + .../Public/ModuleBindings/ReducerBase.g.h | 18 + .../Reducers/InsertViewPkMembership.g.h | 58 + .../InsertViewPkMembershipSecondary.g.h | 58 + .../Reducers/InsertViewPkPlayer.g.h | 58 + .../Reducers/UpdateViewPkPlayer.g.h | 58 + .../ModuleBindings/SpacetimeDBClient.g.h | 1165 +++++ .../Tables/AllViewPkPlayersTable.g.h | 64 + .../Tables/SenderViewPkPlayersATable.g.h | 64 + .../Tables/SenderViewPkPlayersBTable.g.h | 64 + .../Tables/ViewPkMembershipSecondaryTable.g.h | 141 + .../Tables/ViewPkMembershipTable.g.h | 141 + .../Tables/ViewPkPlayerTable.g.h | 104 + .../Types/ViewPkMembershipSecondaryType.g.h | 49 + .../Types/ViewPkMembershipType.g.h | 49 + .../ModuleBindings/Types/ViewPkPlayerType.g.h | 49 + .../Public/Tests/CommonTestFunctions.h | 74 + .../Public/Tests/PrimitiveHandlerList.def | 1 + .../Public/Tests/SpacetimeFullClientTests.h | 29 + .../Public/Tests/TestCounter.h | 35 + .../Public/Tests/TestHandler.h | 47 + .../Public/Tests/UmbreallaHeaderReducers.h | 1 + .../Public/Tests/UmbreallaHeaderTypes.h | 1 + .../Public/Tests/UmbreallaHeaderaTables.h | 1 + .../TestViewPkClient.Build.cs | 25 + .../TestViewPkClient/TestViewPkClient.cpp | 6 + .../TestViewPkClient/TestViewPkClient.h | 6 + .../TestViewPkClientGameModeBase.cpp | 5 + .../TestViewPkClientGameModeBase.h | 17 + .../Source/TestViewPkClientEditor.Target.cs | 15 + .../TestViewPkClient.uproject | 25 + sdks/unreal/tests/test_view.rs | 28 + sdks/unreal/tests/test_view_pk.rs | 40 + 111 files changed, 13551 insertions(+), 9 deletions(-) create mode 100644 sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr.h create mode 100644 sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/join.h create mode 100644 sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/query_builder.h create mode 100644 sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/table.h create mode 100644 sdks/unreal/tests/TestViewClient/.vsconfig create mode 100644 sdks/unreal/tests/TestViewClient/Config/DefaultEditor.ini create mode 100644 sdks/unreal/tests/TestViewClient/Config/DefaultEditorPerProjectUserSettings.ini create mode 100644 sdks/unreal/tests/TestViewClient/Config/DefaultEngine.ini create mode 100644 sdks/unreal/tests/TestViewClient/Config/DefaultGame.ini create mode 100644 sdks/unreal/tests/TestViewClient/Config/DefaultInput.ini create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient.Target.cs create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/MyPlayerAndLevelTable.g.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/MyPlayerTable.g.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/NearbyPlayersTable.g.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/PlayerLevelTable.g.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/PlayerTable.g.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/PlayersAtLevel0Table.g.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/CommonTestFunctions.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/SpacetimeFullClientTests.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/TestCounter.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/TestHandler.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/ReducerBase.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Reducers/DeletePlayer.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Reducers/InsertPlayer.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Reducers/MovePlayer.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/SpacetimeDBClient.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/MyPlayerAndLevelTable.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/MyPlayerTable.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/NearbyPlayersTable.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/PlayerLevelTable.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/PlayerTable.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/PlayersAtLevel0Table.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerAndLevelType.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerLevelType.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerLocationType.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerType.g.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/CommonTestFunctions.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/PrimitiveHandlerList.def create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/SpacetimeFullClientTests.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/TestCounter.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/TestHandler.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/UmbreallaHeaderReducers.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/UmbreallaHeaderTypes.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/UmbreallaHeaderaTables.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClient.Build.cs create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClient.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClient.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClientGameModeBase.cpp create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClientGameModeBase.h create mode 100644 sdks/unreal/tests/TestViewClient/Source/TestViewClientEditor.Target.cs create mode 100644 sdks/unreal/tests/TestViewClient/TestViewClient.uproject create mode 100644 sdks/unreal/tests/TestViewPkClient/.vsconfig create mode 100644 sdks/unreal/tests/TestViewPkClient/Config/DefaultEditor.ini create mode 100644 sdks/unreal/tests/TestViewPkClient/Config/DefaultEditorPerProjectUserSettings.ini create mode 100644 sdks/unreal/tests/TestViewPkClient/Config/DefaultEngine.ini create mode 100644 sdks/unreal/tests/TestViewPkClient/Config/DefaultGame.ini create mode 100644 sdks/unreal/tests/TestViewPkClient/Config/DefaultInput.ini create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient.Target.cs create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/AllViewPkPlayersTable.g.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/SenderViewPkPlayersATable.g.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/SenderViewPkPlayersBTable.g.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/ViewPkMembershipSecondaryTable.g.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/ViewPkMembershipTable.g.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/ViewPkPlayerTable.g.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/CommonTestFunctions.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/SpacetimeFullClientTests.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/TestCounter.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/TestHandler.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/ReducerBase.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/InsertViewPkMembership.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/InsertViewPkMembershipSecondary.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/InsertViewPkPlayer.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/UpdateViewPkPlayer.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/SpacetimeDBClient.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/AllViewPkPlayersTable.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/SenderViewPkPlayersATable.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/SenderViewPkPlayersBTable.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/ViewPkMembershipSecondaryTable.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/ViewPkMembershipTable.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/ViewPkPlayerTable.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Types/ViewPkMembershipSecondaryType.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Types/ViewPkMembershipType.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Types/ViewPkPlayerType.g.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/CommonTestFunctions.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/PrimitiveHandlerList.def create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/SpacetimeFullClientTests.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/TestCounter.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/TestHandler.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/UmbreallaHeaderReducers.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/UmbreallaHeaderTypes.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/UmbreallaHeaderaTables.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClient.Build.cs create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClient.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClient.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClientGameModeBase.cpp create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClientGameModeBase.h create mode 100644 sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClientEditor.Target.cs create mode 100644 sdks/unreal/tests/TestViewPkClient/TestViewPkClient.uproject create mode 100644 sdks/unreal/tests/test_view.rs create mode 100644 sdks/unreal/tests/test_view_pk.rs diff --git a/.gitattributes b/.gitattributes index 8059f23d196..05b1a132398 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ **/module_bindings/** linguist-generated=true eol=lf +**/ModuleBindings/** linguist-generated=true eol=lf /docs/llms/** linguist-generated=true /docs/llms/*-details.json linguist-generated=false diff --git a/crates/codegen/src/unrealcpp.rs b/crates/codegen/src/unrealcpp.rs index bab5d0bfed5..ec17b383ad8 100644 --- a/crates/codegen/src/unrealcpp.rs +++ b/crates/codegen/src/unrealcpp.rs @@ -916,6 +916,14 @@ impl Lang for UnrealCpp<'_> { ); } + for (_, _, product_type_ref) in iter_table_names_and_types(module, options.visibility) { + includes.insert(format!( + "ModuleBindings/Types/{}Type.g.h", + type_ref_name(self.module_prefix, module, product_type_ref) + )); + } + includes.insert("QueryBuilder/query_builder.h".to_string()); + // Convert to sorted vector let mut include_vec: Vec = includes.into_iter().collect(); include_vec.sort(); @@ -989,6 +997,16 @@ impl Lang for UnrealCpp<'_> { self.module_name, ); + // QueryBuilder types + generate_query_builder_types( + &mut client_h, + module, + options.visibility, + self.module_prefix, + &self.get_api_macro(), + self.module_name, + ); + // SubscriptionBuilder class generate_subscription_builder_class(&mut client_h, self.module_prefix, &self.get_api_macro()); @@ -2948,6 +2966,289 @@ fn generate_remote_procedures_class( writeln!(output); } +fn generate_query_builder_types( + output: &mut UnrealCppAutogen, + module: &ModuleDef, + visibility: CodegenVisibility, + module_prefix: &str, + api_macro: &str, + module_name: &str, +) { + struct QueryBuilderRowMeta { + row_struct: String, + cols_struct: String, + ix_cols_struct: String, + fields: Vec<(String, String, String)>, + singleton_indexed_fields: Vec, + can_be_lookup: bool, + } + + writeln!(output, "// QueryBuilder types"); + + let mut row_metas = Vec::::new(); + + for (table_name, _accessor_name, product_type_ref) in iter_table_names_and_types(module, visibility) { + let product_type = module.typespace_for_generate()[product_type_ref] + .as_product() + .expect("query builder source should be a product type"); + let row_struct = format!("F{}Type", type_ref_name(module_prefix, module, product_type_ref)); + let row_type_name = row_struct + .strip_suffix("Type") + .expect("row struct should end with Type") + .to_string(); + + let is_event = iter_tables(module, visibility) + .find(|table| table.name == *table_name) + .map(|table| table.is_event) + .unwrap_or(false); + + let singleton_indexed_fields: Vec = iter_tables(module, visibility) + .find(|table| table.name == *table_name) + .map(|table| { + let table_product_type = module.typespace_for_generate()[table.product_type_ref] + .as_product() + .expect("table schema should be a product type"); + iter_indexes(table) + .filter_map(|idx| { + let col = idx.algorithm.columns().as_singleton()?; + let (field_name, _) = &table_product_type.elements[col.idx()]; + Some(field_name.deref().to_case(Case::Pascal)) + }) + .collect() + }) + .unwrap_or_default(); + + let row_fields = product_type + .elements + .iter() + .map(|(field_name, field_ty)| { + ( + field_name.deref().to_string(), + field_name.deref().to_case(Case::Pascal), + cpp_ty_fmt_with_module(module_prefix, module, field_ty, module_name).to_string(), + ) + }) + .collect::>(); + + if let Some(existing) = row_metas.iter_mut().find(|meta| meta.row_struct == row_struct) { + for field_name in singleton_indexed_fields { + if !existing.singleton_indexed_fields.contains(&field_name) { + existing.singleton_indexed_fields.push(field_name); + } + } + if !is_event { + existing.can_be_lookup = true; + } + continue; + } + + row_metas.push(QueryBuilderRowMeta { + row_struct, + cols_struct: format!("{row_type_name}Cols"), + ix_cols_struct: format!("{row_type_name}IxCols"), + fields: row_fields, + singleton_indexed_fields, + can_be_lookup: !is_event, + }); + } + + for row_meta in &row_metas { + let row_struct = &row_meta.row_struct; + let cols_struct = &row_meta.cols_struct; + let ix_cols_struct = &row_meta.ix_cols_struct; + let singleton_indexed_fields = &row_meta.singleton_indexed_fields; + + writeln!(output, "struct {api_macro} {cols_struct}"); + writeln!(output, "{{"); + writeln!(output, " explicit {cols_struct}(const char* TableName)"); + write!(output, " : "); + for (idx, (field_name_raw, field_name_pascal, _field_type)) in row_meta.fields.iter().enumerate() { + if idx > 0 { + write!(output, ", "); + } + write!( + output, + "{}(TableName, \"{}\")", + field_name_pascal, + field_name_raw + ); + } + writeln!(output, " {{}}"); + writeln!(output); + for (_field_name_raw, field_name_pascal, field_type) in &row_meta.fields { + writeln!( + output, + " ::SpacetimeDB::query_builder::Col<{row_struct}, {field_type}> {field_name_pascal};" + ); + } + writeln!(output, "}};"); + writeln!(output); + + writeln!(output, "struct {api_macro} {ix_cols_struct}"); + writeln!(output, "{{"); + writeln!(output, " explicit {ix_cols_struct}(const char* TableName)"); + if !singleton_indexed_fields.is_empty() { + write!(output, " : "); + for (idx, (field_name_raw, field_name_pascal, _field_type)) in row_meta + .fields + .iter() + .filter(|(_field_name_raw, field_name_pascal, _)| singleton_indexed_fields.contains(field_name_pascal)) + .enumerate() + { + if idx > 0 { + write!(output, ", "); + } + write!( + output, + "{}(TableName, \"{}\")", + field_name_pascal, + field_name_raw + ); + } + } + writeln!(output, " {{}}"); + writeln!(output); + for (_field_name_raw, field_name_pascal, field_type) in row_meta + .fields + .iter() + .filter(|(_field_name_raw, field_name_pascal, _)| singleton_indexed_fields.contains(field_name_pascal)) + { + writeln!( + output, + " ::SpacetimeDB::query_builder::detail::ix_col_member_t<{row_struct}, {field_type}, &{row_struct}::{field_name_pascal}> {field_name_pascal};" + ); + } + writeln!(output, "}};"); + writeln!(output); + + writeln!(output, "namespace SpacetimeDB::query_builder"); + writeln!(output, "{{"); + for field_name_pascal in singleton_indexed_fields { + writeln!( + output, + " inline std::true_type indexed_member_lookup(member_tag<{row_struct}, &{row_struct}::{field_name_pascal}>);" + ); + } + writeln!(output); + writeln!(output, " template<>"); + writeln!(output, " struct HasCols<{row_struct}>"); + writeln!(output, " {{"); + writeln!( + output, + " static {cols_struct} get(const char* table_name) {{ return {cols_struct}(table_name); }}" + ); + writeln!(output, " }};"); + writeln!(output); + writeln!(output, " template<>"); + writeln!(output, " struct HasIxCols<{row_struct}>"); + writeln!(output, " {{"); + writeln!( + output, + " static {ix_cols_struct} get(const char* table_name) {{ return {ix_cols_struct}(table_name); }}" + ); + writeln!(output, " }};"); + if row_meta.can_be_lookup { + writeln!(output); + writeln!(output, " template<>"); + writeln!( + output, + " struct CanBeLookupTable<{row_struct}> : std::true_type {{}};" + ); + } + writeln!(output, "}}"); + writeln!(output); + } + + writeln!(output, "struct {api_macro} F{module_prefix}From"); + writeln!(output, "{{"); + for (table_name, accessor_name, product_type_ref) in iter_table_names_and_types(module, visibility) { + let row_struct = format!("F{}Type", type_ref_name(module_prefix, module, product_type_ref)); + let source_pascal = accessor_name.deref().to_case(Case::Pascal); + writeln!( + output, + " [[nodiscard]] ::SpacetimeDB::query_builder::Table<{row_struct}> {source_pascal}() const {{ return ::SpacetimeDB::query_builder::Table<{row_struct}>(\"{}\"); }}", + table_name.deref() + ); + } + writeln!(output, "}};"); + writeln!(output); + + writeln!(output, "struct {api_macro} F{module_prefix}QueryBuilder"); + writeln!(output, "{{"); + writeln!(output, " F{module_prefix}From From;"); + writeln!(output); + writeln!(output, " static TArray AllTablesSqlQueries()"); + writeln!(output, " {{"); + writeln!(output, " TArray Sql;"); + for (_table_name, accessor_name, _product_type_ref) in iter_table_names_and_types(module, visibility) { + let source_pascal = accessor_name.deref().to_case(Case::Pascal); + writeln!( + output, + " Sql.Add(FString(UTF8_TO_TCHAR(F{module_prefix}QueryBuilder().From.{source_pascal}().into_sql().c_str())));" + ); + } + writeln!(output, " return Sql;"); + writeln!(output, " }}"); + writeln!(output, "}};"); + writeln!(output); + + writeln!(output, "struct {api_macro} F{module_prefix}TypedSubscriptionBuilder"); + writeln!(output, "{{"); + writeln!( + output, + " explicit F{module_prefix}TypedSubscriptionBuilder(U{module_prefix}DbConnection* InConn)" + ); + writeln!(output, " : Conn(InConn) {{}}"); + writeln!(output); + writeln!( + output, + " F{module_prefix}TypedSubscriptionBuilder& OnApplied(F{module_prefix}OnSubscriptionApplied Callback);" + ); + writeln!( + output, + " F{module_prefix}TypedSubscriptionBuilder& OnError(F{module_prefix}OnSubscriptionError Callback);" + ); + writeln!(output); + writeln!(output, " template"); + writeln!( + output, + " F{module_prefix}TypedSubscriptionBuilder& AddQuery(TFn&& Build)" + ); + writeln!(output, " {{"); + writeln!(output, " F{module_prefix}QueryBuilder Q;"); + writeln!(output, " auto Query = std::forward(Build)(Q);"); + writeln!( + output, + " static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn," + ); + writeln!( + output, + " \"Typed subscription queries must return a query_builder table/query expression.\");" + ); + writeln!( + output, + " Sql.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str())));" + ); + writeln!(output, " return *this;"); + writeln!(output, " }}"); + writeln!(output); + writeln!(output, " U{module_prefix}SubscriptionHandle* Subscribe();"); + writeln!(output); + writeln!(output, "private:"); + writeln!(output, " U{module_prefix}DbConnection* Conn = nullptr;"); + writeln!(output, " TArray Sql;"); + writeln!( + output, + " F{module_prefix}OnSubscriptionApplied OnAppliedDelegateInternal;" + ); + writeln!( + output, + " F{module_prefix}OnSubscriptionError OnErrorDelegateInternal;" + ); + writeln!(output, "}};"); + writeln!(output); +} + fn generate_subscription_builder_class(output: &mut UnrealCppAutogen, module_prefix: &str, api_macro: &str) { writeln!(output, "// SubscriptionBuilder class"); writeln!(output, "UCLASS(BlueprintType)"); @@ -2978,6 +3279,19 @@ fn generate_subscription_builder_class(output: &mut UnrealCppAutogen, module_pre " U{module_prefix}SubscriptionHandle* Subscribe(const TArray& SQL);" ); writeln!(output); + writeln!(output, " template"); + writeln!( + output, + " [[nodiscard]] F{module_prefix}TypedSubscriptionBuilder AddQuery(TFn&& Build)" + ); + writeln!(output, " {{"); + writeln!(output, " F{module_prefix}TypedSubscriptionBuilder Typed(Conn);"); + writeln!(output, " Typed.OnApplied(OnAppliedDelegateInternal);"); + writeln!(output, " Typed.OnError(OnErrorDelegateInternal);"); + writeln!(output, " Typed.AddQuery(std::forward(Build));"); + writeln!(output, " return Typed;"); + writeln!(output, " }}"); + writeln!(output); writeln!( output, " /** Convenience for subscribing to all rows from all tables */" @@ -3666,6 +3980,39 @@ fn generate_client_implementation( writeln!(output, "\tBuilder->Conn = this;"); writeln!(output, "\treturn Builder;"); writeln!(output, "}}"); + writeln!( + output, + "F{module_prefix}TypedSubscriptionBuilder& F{module_prefix}TypedSubscriptionBuilder::OnApplied(F{module_prefix}OnSubscriptionApplied Callback)" + ); + writeln!(output, "{{"); + writeln!(output, "\tOnAppliedDelegateInternal = Callback;"); + writeln!(output, "\treturn *this;"); + writeln!(output, "}}"); + writeln!( + output, + "F{module_prefix}TypedSubscriptionBuilder& F{module_prefix}TypedSubscriptionBuilder::OnError(F{module_prefix}OnSubscriptionError Callback)" + ); + writeln!(output, "{{"); + writeln!(output, "\tOnErrorDelegateInternal = Callback;"); + writeln!(output, "\treturn *this;"); + writeln!(output, "}}"); + writeln!( + output, + "U{module_prefix}SubscriptionHandle* F{module_prefix}TypedSubscriptionBuilder::Subscribe()" + ); + writeln!(output, "{{"); + writeln!(output, "\tif (!Conn)"); + writeln!(output, "\t{{"); + writeln!(output, "\t\treturn nullptr;"); + writeln!(output, "\t}}"); + writeln!( + output, + "\tU{module_prefix}SubscriptionBuilder* Builder = Conn->SubscriptionBuilder();" + ); + writeln!(output, "\tBuilder->OnApplied(OnAppliedDelegateInternal);"); + writeln!(output, "\tBuilder->OnError(OnErrorDelegateInternal);"); + writeln!(output, "\treturn Builder->Subscribe(Sql);"); + writeln!(output, "}}"); writeln!( output, "U{module_prefix}SubscriptionBuilder* U{module_prefix}SubscriptionBuilder::OnApplied(F{module_prefix}OnSubscriptionApplied Callback)" @@ -3721,7 +4068,7 @@ fn generate_client_implementation( "U{module_prefix}SubscriptionHandle* U{module_prefix}SubscriptionBuilder::SubscribeToAllTables()" ); writeln!(output, "{{"); - writeln!(output, "\treturn Subscribe({{ \"SELECT * FROM * \" }});"); + writeln!(output, "\treturn Subscribe(F{module_prefix}QueryBuilder::AllTablesSqlQueries());"); writeln!(output, "}}"); writeln!(output); writeln!( @@ -5574,7 +5921,7 @@ fn autogen_cpp_sum( writeln!(output, " case E{name}Tag::{pas}:"); writeln!( output, - " return GetAs{variant_name}() == Other.GetAs{variant_name}();" + " return GetAs{pas}() == Other.GetAs{pas}();" ); } diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/Connection/DbConnectionBase.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/Connection/DbConnectionBase.h index e8c26b3a988..4510dfa1da7 100644 --- a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/Connection/DbConnectionBase.h +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/Connection/DbConnectionBase.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr.h new file mode 100644 index 00000000000..b20bd641bad --- /dev/null +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr.h @@ -0,0 +1,376 @@ +#pragma once + +#include "CoreMinimal.h" +#include "BSATN/Core/timestamp.h" +#include "BSATN/Core/types.h" +#include "Types/Builtins.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace SpacetimeDB::query_builder { + +template +class Col; + +template +class ColumnRef { +public: + constexpr ColumnRef() + : table_name_(""), column_name_("") {} + + constexpr ColumnRef(const char* table_name, const char* column_name) + : table_name_(table_name), column_name_(column_name) {} + + [[nodiscard]] std::string format() const { + return "\"" + std::string(table_name_) + "\".\"" + std::string(column_name_) + "\""; + } + + [[nodiscard]] constexpr const char* table_name() const { return table_name_; } + [[nodiscard]] constexpr const char* column_name() const { return column_name_; } + +private: + const char* table_name_; + const char* column_name_; +}; + +namespace detail { + +inline std::string quote_string(std::string_view value) { + std::string escaped; + escaped.reserve(value.size() + 2); + escaped.push_back('\''); + for (char ch : value) { + escaped.push_back(ch); + if (ch == '\'') { + escaped.push_back('\''); + } + } + escaped.push_back('\''); + return escaped; +} + +inline std::string trim_timestamp_fraction(std::string value) { + // Keep this in sync with the current Timestamp::to_string() UTC form. + // If that representation changes away from a +00:00 / Z suffix, revisit this trimming logic. + const std::size_t plus = value.rfind("+00:00"); + const std::size_t z = value.rfind('Z'); + const std::size_t dot = value.find('.'); + const std::size_t suffix = plus != std::string::npos ? plus : z; + if (suffix == std::string::npos || dot == std::string::npos || dot > suffix) { + return value; + } + + std::size_t trim = suffix; + while (trim > dot + 1 && value[trim - 1] == '0') { + --trim; + } + if (trim == dot + 1) { + value.erase(dot, suffix - dot); + } else { + value.erase(trim, suffix - trim); + } + return value; +} + +inline std::string literal_sql(const std::string& value) { return quote_string(value); } +inline std::string literal_sql(std::string_view value) { return quote_string(value); } +inline std::string literal_sql(const char* value) { return quote_string(value == nullptr ? "" : value); } +inline std::string literal_sql(const TCHAR* value) { + return quote_string(value == nullptr ? "" : TCHAR_TO_UTF8(value)); +} +inline std::string literal_sql(const FString& value) { + return quote_string(TCHAR_TO_UTF8(*value)); +} +inline std::string literal_sql(bool value) { return value ? "TRUE" : "FALSE"; } +inline std::string literal_sql(const ::SpacetimeDb::Identity& value) { return "0x" + value.to_hex_string(); } +inline std::string literal_sql(const ::SpacetimeDb::ConnectionId& value) { return "0x" + value.to_string(); } +inline std::string literal_sql(const ::SpacetimeDb::Timestamp& value) { return quote_string(trim_timestamp_fraction(value.to_string())); } +inline std::string literal_sql(const FSpacetimeDBIdentity& value) { return std::string(TCHAR_TO_UTF8(*value.ToHex())); } +inline std::string literal_sql(const FSpacetimeDBConnectionId& value) { return std::string(TCHAR_TO_UTF8(*value.ToHex())); } +inline std::string literal_sql(const FSpacetimeDBTimestamp& value) { + return quote_string(trim_timestamp_fraction(TCHAR_TO_UTF8(*value.ToString()))); +} +inline std::string literal_sql(const std::vector& value) { + std::ostringstream out; + out << "0x" << std::hex << std::setfill('0'); + for (uint8_t byte : value) { + out << std::setw(2) << static_cast(byte); + } + return out.str(); +} +inline std::string literal_sql(const TArray& value) { + std::ostringstream out; + out << "0x" << std::hex << std::setfill('0'); + for (uint8 byte : value) { + out << std::setw(2) << static_cast(byte); + } + return out.str(); +} +inline std::string literal_sql(const ::SpacetimeDb::u128& value) { return value.to_string(); } +inline std::string literal_sql(const ::SpacetimeDb::i128& value) { return value.to_string(); } +inline std::string literal_sql(const ::SpacetimeDb::u256& value) { return value.to_string(); } +inline std::string literal_sql(const ::SpacetimeDb::i256& value) { return value.to_string(); } +inline std::string literal_sql(const FSpacetimeDBUInt128& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } +inline std::string literal_sql(const FSpacetimeDBInt128& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } +inline std::string literal_sql(const FSpacetimeDBUInt256& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } +inline std::string literal_sql(const FSpacetimeDBInt256& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } + +inline std::string format_floating_point(double value) { + std::ostringstream out; + out.imbue(std::locale::classic()); + out << value; + return out.str(); +} + +inline std::string literal_sql(float value) { + return format_floating_point(static_cast(value)); +} + +inline std::string literal_sql(double value) { + return format_floating_point(value); +} + +template +std::string literal_sql(const TValue& value) +requires(std::is_integral_v && !std::is_same_v, bool>) +{ + return std::to_string(value); +} + +template +class Operand { +public: + static Operand column(ColumnRef column) { return Operand(std::move(column)); } + static Operand literal(std::string sql) { return Operand(std::move(sql)); } + + [[nodiscard]] std::string format() const { + return std::holds_alternative>(value_) + ? std::get>(value_).format() + : std::get(value_); + } + +private: + explicit Operand(ColumnRef column) : value_(std::move(column)) {} + explicit Operand(std::string sql) : value_(std::move(sql)) {} + + std::variant, std::string> value_; +}; + +template +Operand to_operand(const Col& column); + +template +Operand to_operand(const TValue& value) { + return Operand::literal(literal_sql(value)); +} + +} // namespace detail + +template +class BoolExpr { +public: + enum class Kind { + Eq, + Ne, + Gt, + Lt, + Gte, + Lte, + And, + Or, + Not, + }; + + static BoolExpr compare(Kind kind, detail::Operand lhs, detail::Operand rhs) { + return BoolExpr(std::make_shared(kind, std::move(lhs), std::move(rhs))); + } + + static BoolExpr always(bool value) { + return compare( + Kind::Eq, + detail::Operand::literal(value ? "TRUE" : "FALSE"), + detail::Operand::literal("TRUE")); + } + + [[nodiscard]] std::string format() const { + return format_node(root_); + } + + [[nodiscard]] BoolExpr and_(const BoolExpr& other) const { + return BoolExpr(std::make_shared(Kind::And, root_, other.root_)); + } + [[nodiscard]] BoolExpr And(const BoolExpr& other) const { return and_(other); } + + [[nodiscard]] BoolExpr or_(const BoolExpr& other) const { + return BoolExpr(std::make_shared(Kind::Or, root_, other.root_)); + } + [[nodiscard]] BoolExpr Or(const BoolExpr& other) const { return or_(other); } + + [[nodiscard]] BoolExpr not_() const { + return BoolExpr(std::make_shared(Kind::Not, root_, nullptr)); + } + [[nodiscard]] BoolExpr Not() const { return not_(); } + +private: + struct Node; + + struct CompareData { + detail::Operand lhs; + detail::Operand rhs; + }; + + struct LogicData { + std::shared_ptr left; + std::shared_ptr right; + }; + + struct NotData { + std::shared_ptr child; + }; + + struct Node { + Node(Kind kind_in, detail::Operand lhs_in, detail::Operand rhs_in) + : kind(kind_in), data(CompareData{std::move(lhs_in), std::move(rhs_in)}) {} + + Node(Kind kind_in, std::shared_ptr left_in, std::shared_ptr right_in) + : kind(kind_in), + data(kind_in == Kind::Not + ? NodeData(NotData{std::move(left_in)}) + : NodeData(LogicData{std::move(left_in), std::move(right_in)})) {} + + Kind kind; + using NodeData = std::variant; + NodeData data; + }; + + explicit BoolExpr(std::shared_ptr root) + : root_(std::move(root)) {} + + static std::string format_node(const std::shared_ptr& node) { + switch (node->kind) { + case Kind::Eq: { + const auto& compare = std::get(node->data); + return "(" + compare.lhs.format() + " = " + compare.rhs.format() + ")"; + } + case Kind::Ne: { + const auto& compare = std::get(node->data); + return "(" + compare.lhs.format() + " <> " + compare.rhs.format() + ")"; + } + case Kind::Gt: { + const auto& compare = std::get(node->data); + return "(" + compare.lhs.format() + " > " + compare.rhs.format() + ")"; + } + case Kind::Lt: { + const auto& compare = std::get(node->data); + return "(" + compare.lhs.format() + " < " + compare.rhs.format() + ")"; + } + case Kind::Gte: { + const auto& compare = std::get(node->data); + return "(" + compare.lhs.format() + " >= " + compare.rhs.format() + ")"; + } + case Kind::Lte: { + const auto& compare = std::get(node->data); + return "(" + compare.lhs.format() + " <= " + compare.rhs.format() + ")"; + } + case Kind::And: { + const auto& logic = std::get(node->data); + return "(" + format_node(logic.left) + " AND " + format_node(logic.right) + ")"; + } + case Kind::Or: { + const auto& logic = std::get(node->data); + return "(" + format_node(logic.left) + " OR " + format_node(logic.right) + ")"; + } + case Kind::Not: { + const auto& not_data = std::get(node->data); + return "(NOT " + format_node(not_data.child) + ")"; + } + } + return {}; + } + + std::shared_ptr root_; +}; + +namespace detail { + +template +BoolExpr make_bool_expr(BoolExpr expr) { + return expr; +} + +template +BoolExpr make_bool_expr(bool value) { + return BoolExpr::always(value); +} + +template +BoolExpr make_bool_expr(const Col& column) { + return column.eq(true); +} + +} // namespace detail + +template +class Col { +public: + constexpr Col() = default; + + constexpr Col(const char* table_name, const char* column_name) + : column_(table_name, column_name) {} + + template + [[nodiscard]] BoolExpr eq(const TRhs& rhs) const { return compare(BoolExpr::Kind::Eq, rhs); } + template + [[nodiscard]] BoolExpr Eq(const TRhs& rhs) const { return eq(rhs); } + template + [[nodiscard]] BoolExpr ne(const TRhs& rhs) const { return compare(BoolExpr::Kind::Ne, rhs); } + template + [[nodiscard]] BoolExpr Neq(const TRhs& rhs) const { return ne(rhs); } + template + [[nodiscard]] BoolExpr gt(const TRhs& rhs) const { return compare(BoolExpr::Kind::Gt, rhs); } + template + [[nodiscard]] BoolExpr Gt(const TRhs& rhs) const { return gt(rhs); } + template + [[nodiscard]] BoolExpr lt(const TRhs& rhs) const { return compare(BoolExpr::Kind::Lt, rhs); } + template + [[nodiscard]] BoolExpr Lt(const TRhs& rhs) const { return lt(rhs); } + template + [[nodiscard]] BoolExpr gte(const TRhs& rhs) const { return compare(BoolExpr::Kind::Gte, rhs); } + template + [[nodiscard]] BoolExpr Gte(const TRhs& rhs) const { return gte(rhs); } + template + [[nodiscard]] BoolExpr lte(const TRhs& rhs) const { return compare(BoolExpr::Kind::Lte, rhs); } + template + [[nodiscard]] BoolExpr Lte(const TRhs& rhs) const { return lte(rhs); } + + [[nodiscard]] constexpr const ColumnRef& column_ref() const { return column_; } + +private: + template + [[nodiscard]] BoolExpr compare(typename BoolExpr::Kind kind, const TRhs& rhs) const { + return BoolExpr::compare(kind, detail::to_operand(*this), detail::to_operand(rhs)); + } + + ColumnRef column_; +}; + +namespace detail { + +template +Operand to_operand(const Col& column) { + return Operand::column(column.column_ref()); +} + +} // namespace detail + +} // namespace SpacetimeDB::query_builder diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/join.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/join.h new file mode 100644 index 00000000000..dfc95c02736 --- /dev/null +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/join.h @@ -0,0 +1,415 @@ +#pragma once + +#include "QueryBuilder/table.h" + +#include +#include +#include + +namespace SpacetimeDB::query_builder { + +template +struct IxJoinEq; + +template +struct member_tag {}; + +inline std::false_type indexed_member_lookup(...); + +template +inline constexpr bool is_indexed_member_v = decltype(indexed_member_lookup(member_tag{}))::value; + +template +class IxCol { +public: + constexpr IxCol() = default; + + constexpr IxCol(const char* table_name, const char* column_name) + : column_(table_name, column_name) {} + + template + [[nodiscard]] auto eq(const IxCol& rhs) const { + return IxJoinEq{column_, rhs.column_}; + } + template + [[nodiscard]] auto Eq(const IxCol& rhs) const { + return eq(rhs); + } + + template + [[nodiscard]] BoolExpr eq(const TRhs& rhs) const { + return compare(BoolExpr::Kind::Eq, rhs); + } + template + [[nodiscard]] BoolExpr Eq(const TRhs& rhs) const { return eq(rhs); } + template + [[nodiscard]] BoolExpr ne(const TRhs& rhs) const { + return compare(BoolExpr::Kind::Ne, rhs); + } + template + [[nodiscard]] BoolExpr Neq(const TRhs& rhs) const { return ne(rhs); } + template + [[nodiscard]] BoolExpr gt(const TRhs& rhs) const { + return compare(BoolExpr::Kind::Gt, rhs); + } + template + [[nodiscard]] BoolExpr Gt(const TRhs& rhs) const { return gt(rhs); } + template + [[nodiscard]] BoolExpr lt(const TRhs& rhs) const { + return compare(BoolExpr::Kind::Lt, rhs); + } + template + [[nodiscard]] BoolExpr Lt(const TRhs& rhs) const { return lt(rhs); } + template + [[nodiscard]] BoolExpr gte(const TRhs& rhs) const { + return compare(BoolExpr::Kind::Gte, rhs); + } + template + [[nodiscard]] BoolExpr Gte(const TRhs& rhs) const { return gte(rhs); } + template + [[nodiscard]] BoolExpr lte(const TRhs& rhs) const { + return compare(BoolExpr::Kind::Lte, rhs); + } + template + [[nodiscard]] BoolExpr Lte(const TRhs& rhs) const { return lte(rhs); } + + [[nodiscard]] constexpr const ColumnRef& column_ref() const { return column_; } + +private: + template + [[nodiscard]] BoolExpr compare(typename BoolExpr::Kind kind, const TRhs& rhs) const { + return BoolExpr::compare(kind, detail::Operand::column(column_), detail::to_operand(rhs)); + } + + ColumnRef column_; + + template + friend class IxCol; +}; + +namespace detail { + +template +inline constexpr bool delayed_is_indexed_member_v = is_indexed_member_v; + +template +class MaybeIxCol { +public: + constexpr MaybeIxCol() = default; + constexpr MaybeIxCol(const char* table_name, const char* column_name) + : column_(table_name, column_name) {} + + template + [[nodiscard]] auto eq(const MaybeIxCol& rhs) const { + static_assert( + is_indexed_member_v && is_indexed_member_v, + "Semijoin predicates may only use single-column indexed fields."); + return IxJoinEq{column_, rhs.column_}; + } + template + [[nodiscard]] auto Eq(const MaybeIxCol& rhs) const { + return eq(rhs); + } + + template + [[nodiscard]] BoolExpr eq(const TRhs& rhs) const { + return compare(BoolExpr::Kind::Eq, rhs); + } + template + [[nodiscard]] BoolExpr Eq(const TRhs& rhs) const { return eq(rhs); } + template + [[nodiscard]] BoolExpr ne(const TRhs& rhs) const { + return compare(BoolExpr::Kind::Ne, rhs); + } + template + [[nodiscard]] BoolExpr Neq(const TRhs& rhs) const { return ne(rhs); } + template + [[nodiscard]] BoolExpr gt(const TRhs& rhs) const { + return compare(BoolExpr::Kind::Gt, rhs); + } + template + [[nodiscard]] BoolExpr Gt(const TRhs& rhs) const { return gt(rhs); } + template + [[nodiscard]] BoolExpr lt(const TRhs& rhs) const { + return compare(BoolExpr::Kind::Lt, rhs); + } + template + [[nodiscard]] BoolExpr Lt(const TRhs& rhs) const { return lt(rhs); } + template + [[nodiscard]] BoolExpr gte(const TRhs& rhs) const { + return compare(BoolExpr::Kind::Gte, rhs); + } + template + [[nodiscard]] BoolExpr Gte(const TRhs& rhs) const { return gte(rhs); } + template + [[nodiscard]] BoolExpr lte(const TRhs& rhs) const { + return compare(BoolExpr::Kind::Lte, rhs); + } + template + [[nodiscard]] BoolExpr Lte(const TRhs& rhs) const { return lte(rhs); } + + [[nodiscard]] constexpr const ColumnRef& column_ref() const { return column_; } + +private: + template + [[nodiscard]] BoolExpr compare(typename BoolExpr::Kind kind, const TRhs& rhs) const { + return BoolExpr::compare(kind, detail::Operand::column(column_), detail::to_operand(rhs)); + } + + ColumnRef column_{}; + + template + friend class MaybeIxCol; +}; + +template +using ix_col_member_t = MaybeIxCol; +// HasIxCols currently exposes all fields through MaybeIxCol so table/view macros can stay uniform. +// Non-indexed fields are rejected when .eq() is used in a semijoin predicate. + +} // namespace detail + +template +struct IxJoinEq { + ColumnRef lhs; + ColumnRef rhs; +}; + +template +class LeftSemiJoin { +public: + using row_type = TRow; + + LeftSemiJoin(ColumnRef lhs, const char* right_table, const char* right_column, std::optional> where_expr = std::nullopt) + : lhs_(lhs), right_table_(right_table), right_column_(right_column), where_expr_(std::move(where_expr)) {} + + template + [[nodiscard]] LeftSemiJoin where(TFn&& predicate) const { + auto extra = detail::make_bool_expr(std::forward(predicate)(HasCols::get(lhs_.table_name()))); + return LeftSemiJoin(lhs_, right_table_, right_column_, where_expr_ ? where_expr_->and_(extra) : std::optional>(std::move(extra))); + } + template + [[nodiscard]] LeftSemiJoin where_ix(TFn&& predicate) const { + auto extra = detail::make_bool_expr(std::forward(predicate)(HasCols::get(lhs_.table_name()), HasIxCols::get(lhs_.table_name()))); + return LeftSemiJoin(lhs_, right_table_, right_column_, where_expr_ ? where_expr_->and_(extra) : std::optional>(std::move(extra))); + } + template + [[nodiscard]] LeftSemiJoin Where(TFn&& predicate) const { + if constexpr (std::is_invocable_v::get(lhs_.table_name())), decltype(HasIxCols::get(lhs_.table_name()))>) { + return where_ix(std::forward(predicate)); + } else { + return where(std::forward(predicate)); + } + } + + template + [[nodiscard]] LeftSemiJoin filter(TFn&& predicate) const { + return where(std::forward(predicate)); + } + template + [[nodiscard]] LeftSemiJoin Filter(TFn&& predicate) const { + return Where(std::forward(predicate)); + } + + [[nodiscard]] RawQuery build() const { + std::string sql; + sql.reserve( + 48 + + (std::char_traits::length(lhs_.table_name()) * 3) + + std::char_traits::length(right_table_) * 2 + + std::char_traits::length(lhs_.column_name()) + + std::char_traits::length(right_column_)); + sql += "SELECT \""; + sql += lhs_.table_name(); + sql += "\".* FROM \""; + sql += lhs_.table_name(); + sql += "\" JOIN \""; + sql += right_table_; + sql += "\" ON \""; + sql += lhs_.table_name(); + sql += "\".\""; + sql += lhs_.column_name(); + sql += "\" = \""; + sql += right_table_; + sql += "\".\""; + sql += right_column_; + sql += "\""; + if (where_expr_) { + sql += " WHERE " + where_expr_->format(); + } + return RawQuery(std::move(sql)); + } + + [[nodiscard]] std::string into_sql() const { return build().into_sql(); } + +private: + ColumnRef lhs_; + const char* right_table_; + const char* right_column_; + std::optional> where_expr_; +}; + +template +class RightSemiJoin { +public: + using row_type = TRightRow; + + RightSemiJoin( + ColumnRef lhs, + ColumnRef rhs, + std::optional> left_where_expr = std::nullopt, + std::optional> right_where_expr = std::nullopt) + : lhs_(lhs), rhs_(rhs), left_where_expr_(std::move(left_where_expr)), right_where_expr_(std::move(right_where_expr)) {} + + template + [[nodiscard]] RightSemiJoin where(TFn&& predicate) const { + auto extra = detail::make_bool_expr(std::forward(predicate)(HasCols::get(rhs_.table_name()))); + return RightSemiJoin(lhs_, rhs_, left_where_expr_, right_where_expr_ ? right_where_expr_->and_(extra) : std::optional>(std::move(extra))); + } + template + [[nodiscard]] RightSemiJoin where_ix(TFn&& predicate) const { + auto extra = detail::make_bool_expr(std::forward(predicate)(HasCols::get(rhs_.table_name()), HasIxCols::get(rhs_.table_name()))); + return RightSemiJoin(lhs_, rhs_, left_where_expr_, right_where_expr_ ? right_where_expr_->and_(extra) : std::optional>(std::move(extra))); + } + template + [[nodiscard]] RightSemiJoin Where(TFn&& predicate) const { + if constexpr (std::is_invocable_v::get(rhs_.table_name())), decltype(HasIxCols::get(rhs_.table_name()))>) { + return where_ix(std::forward(predicate)); + } else { + return where(std::forward(predicate)); + } + } + + template + [[nodiscard]] RightSemiJoin filter(TFn&& predicate) const { + return where(std::forward(predicate)); + } + template + [[nodiscard]] RightSemiJoin Filter(TFn&& predicate) const { + return Where(std::forward(predicate)); + } + + [[nodiscard]] RawQuery build() const { + std::string sql; + sql.reserve( + 48 + + (std::char_traits::length(lhs_.table_name()) * 2) + + (std::char_traits::length(rhs_.table_name()) * 3) + + std::char_traits::length(lhs_.column_name()) + + std::char_traits::length(rhs_.column_name())); + sql += "SELECT \""; + sql += rhs_.table_name(); + sql += "\".* FROM \""; + sql += lhs_.table_name(); + sql += "\" JOIN \""; + sql += rhs_.table_name(); + sql += "\" ON \""; + sql += lhs_.table_name(); + sql += "\".\""; + sql += lhs_.column_name(); + sql += "\" = \""; + sql += rhs_.table_name(); + sql += "\".\""; + sql += rhs_.column_name(); + sql += "\""; + + if (left_where_expr_ && right_where_expr_) { + sql += " WHERE "; + sql += left_where_expr_->format(); + sql += " AND "; + sql += right_where_expr_->format(); + } else if (left_where_expr_) { + sql += " WHERE "; + sql += left_where_expr_->format(); + } else if (right_where_expr_) { + sql += " WHERE "; + sql += right_where_expr_->format(); + } + + return RawQuery(std::move(sql)); + } + + [[nodiscard]] std::string into_sql() const { return build().into_sql(); } + +private: + ColumnRef lhs_; + ColumnRef rhs_; + std::optional> left_where_expr_; + std::optional> right_where_expr_; +}; + +namespace detail { + +template +[[nodiscard]] LeftSemiJoin left_semijoin_impl(const Table& left, const Table& right, TFn&& predicate) { + static_assert(can_be_lookup_table_v, "Lookup side of a semijoin must opt in via CanBeLookupTable."); + static_assert(requires { HasIxCols::get(left.name()); }, "Left side of a semijoin must provide HasIxCols."); + static_assert(requires { HasIxCols::get(right.name()); }, "Lookup side of a semijoin must provide HasIxCols."); + const auto join = std::forward(predicate)(HasIxCols::get(left.name()), HasIxCols::get(right.name())); + return LeftSemiJoin(join.lhs, right.name(), join.rhs.column_name()); +} + +template +[[nodiscard]] LeftSemiJoin left_semijoin_impl(const FromWhere& left, const Table& right, TFn&& predicate) { + static_assert(can_be_lookup_table_v, "Lookup side of a semijoin must opt in via CanBeLookupTable."); + static_assert(requires { HasIxCols::get(left.table_name()); }, "Left side of a semijoin must provide HasIxCols."); + static_assert(requires { HasIxCols::get(right.name()); }, "Lookup side of a semijoin must provide HasIxCols."); + const auto join = std::forward(predicate)(HasIxCols::get(left.table_name()), HasIxCols::get(right.name())); + return LeftSemiJoin(join.lhs, right.name(), join.rhs.column_name(), left.expr()); +} + +template +[[nodiscard]] RightSemiJoin right_semijoin_impl(const Table& left, const Table& right, TFn&& predicate) { + static_assert(can_be_lookup_table_v, "Lookup side of a semijoin must opt in via CanBeLookupTable."); + static_assert(requires { HasIxCols::get(left.name()); }, "Left side of a semijoin must provide HasIxCols."); + static_assert(requires { HasIxCols::get(right.name()); }, "Lookup side of a semijoin must provide HasIxCols."); + const auto join = std::forward(predicate)(HasIxCols::get(left.name()), HasIxCols::get(right.name())); + return RightSemiJoin(join.lhs, join.rhs); +} + +template +[[nodiscard]] RightSemiJoin right_semijoin_impl(const FromWhere& left, const Table& right, TFn&& predicate) { + static_assert(can_be_lookup_table_v, "Lookup side of a semijoin must opt in via CanBeLookupTable."); + static_assert(requires { HasIxCols::get(left.table_name()); }, "Left side of a semijoin must provide HasIxCols."); + static_assert(requires { HasIxCols::get(right.name()); }, "Lookup side of a semijoin must provide HasIxCols."); + const auto join = std::forward(predicate)(HasIxCols::get(left.table_name()), HasIxCols::get(right.name())); + return RightSemiJoin(join.lhs, join.rhs, left.expr()); +} + +} // namespace detail + +template +template +[[nodiscard]] LeftSemiJoin Table::left_semijoin(const Table& right, TFn&& predicate) const { + return detail::left_semijoin_impl(*this, right, std::forward(predicate)); +} + +template +template +[[nodiscard]] RightSemiJoin Table::right_semijoin(const Table& right, TFn&& predicate) const { + return detail::right_semijoin_impl(*this, right, std::forward(predicate)); +} + +template +template +[[nodiscard]] LeftSemiJoin FromWhere::left_semijoin(const Table& right, TFn&& predicate) const { + return detail::left_semijoin_impl(*this, right, std::forward(predicate)); +} + +template +template +[[nodiscard]] RightSemiJoin FromWhere::right_semijoin(const Table& right, TFn&& predicate) const { + return detail::right_semijoin_impl(*this, right, std::forward(predicate)); +} + +template +struct query_row_type> { + using type = TRow; +}; + +template +struct query_row_type> { + using type = TRightRow; +}; + +} // namespace SpacetimeDB::query_builder diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/query_builder.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/query_builder.h new file mode 100644 index 00000000000..c8386a19f0f --- /dev/null +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/query_builder.h @@ -0,0 +1,99 @@ +#pragma once + +#include "QueryBuilder/expr.h" +#include "QueryBuilder/join.h" +#include "QueryBuilder/table.h" + +#include +#include +#include + +namespace SpacetimeDB { + +template +using Query = query_builder::RawQuery; + +namespace detail { + +template +struct NamedQuerySourceTag { + using type = TRow; + const char* __table_name_internal; +}; + +struct NotAQuerySourceTag {}; + +template +struct query_source_row_type {}; + +template +concept HasQuerySourceRowType = requires { + typename query_source_row_type>::type; +}; + +template +using query_source_row_type_t = typename query_source_row_type>::type; + +template + requires query_builder::QueryBuilderReturn +struct query_source_row_type { + using type = query_builder::query_row_type_t; +}; + +template +struct query_source_row_type> { + using type = TRow; +}; + +template +struct query_source_row_type> { + using type = TRow; +}; + +template +constexpr auto MakeQuerySourceTag(const char* source_name) { + if constexpr (HasQuerySourceRowType) { + return NamedQuerySourceTag>{source_name}; + } else { + return NotAQuerySourceTag{}; + } +} + +template +constexpr const char* GetQuerySourceName(const TSourceTag& tag) { + return tag.__table_name_internal; +} + +} // namespace detail + +class QueryBuilder { +public: + template + [[nodiscard]] constexpr query_builder::Table table(const char* table_name) const { + return query_builder::Table(table_name); + } + + template + [[nodiscard]] constexpr auto table(TTableTag tag) const + -> query_builder::Table::type> { + using Tag = std::remove_cvref_t; + using TRow = typename Tag::type; + // Tags may refer to either base tables or published view relations. + return query_builder::Table(detail::GetQuerySourceName(tag)); + } + + template + [[nodiscard]] constexpr auto operator()(TTableTag tag) const + -> query_builder::Table::type> { + return table(tag); + } + + template + [[nodiscard]] constexpr auto operator[](TTableTag tag) const + -> query_builder::Table::type> { + return table(tag); + } + +}; + +} // namespace SpacetimeDB diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/table.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/table.h new file mode 100644 index 00000000000..d86e60ec63d --- /dev/null +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/table.h @@ -0,0 +1,307 @@ +#pragma once + +#if 0 +// bindings-cpp source include kept here for traceability: +// #include "spacetimedb/bsatn/traits.h" +#include "BSATN/Core/traits.h" +#endif +#include "QueryBuilder/expr.h" + +#include +#include +#include +#include +#include + +namespace SpacetimeDB::query_builder { + +template +struct query_row_type; + +template +class Table; + +template +class FromWhere; + +template +class LeftSemiJoin; + +template +class RightSemiJoin; + +template +using query_row_type_t = typename query_row_type>::type; + +template +class RawQuery { +public: + using row_type = TRow; + + explicit RawQuery(std::string sql) + : sql_(std::move(sql)) {} + + template + requires(!std::same_as, RawQuery> && + requires { typename query_row_type_t; } && + std::same_as, TRow> && + requires(TQuery&& query) { { std::forward(query).into_sql() } -> std::convertible_to; }) + RawQuery(TQuery&& query) + : sql_(std::forward(query).into_sql()) {} + + [[nodiscard]] const std::string& sql() const { return sql_; } + [[nodiscard]] std::string into_sql() const { return sql_; } + +private: + std::string sql_; +}; + +template +concept QueryLike = requires(const TRow& query) { + { query.into_sql() } -> std::convertible_to; +}; + +template +concept QueryBuilderReturn = requires { + typename query_row_type_t; +} && QueryLike>; + +template +struct HasCols; + +template +struct HasIxCols; + +template +struct CanBeLookupTable : std::false_type {}; + +namespace detail { + +template +struct row_tag {}; + +inline std::false_type lookup_table_allowed(...); + +template +auto adl_lookup_table_allowed(int) -> decltype(lookup_table_allowed(row_tag{})); + +template +std::false_type adl_lookup_table_allowed(...); + +} // namespace detail + +template +inline constexpr bool can_be_lookup_table_v = + CanBeLookupTable::value || decltype(detail::adl_lookup_table_allowed(0))::value; + +template +class Table { +public: + using row_type = TRow; + + explicit constexpr Table(const char* table_name) + : table_name_(table_name) {} + + [[nodiscard]] constexpr const char* name() const { return table_name_; } + + [[nodiscard]] RawQuery build() const { + std::string sql; + sql.reserve(16 + std::char_traits::length(table_name_)); + sql += "SELECT * FROM \""; + sql += table_name_; + sql += "\""; + return RawQuery(std::move(sql)); + } + + [[nodiscard]] std::string into_sql() const { + return build().into_sql(); + } + + template + [[nodiscard]] auto where(TFn&& predicate) const; + template + [[nodiscard]] auto where_ix(TFn&& predicate) const; + template + [[nodiscard]] auto Where(TFn&& predicate) const; + + template + [[nodiscard]] auto filter(TFn&& predicate) const { + return where(std::forward(predicate)); + } + template + [[nodiscard]] auto Filter(TFn&& predicate) const { + return Where(std::forward(predicate)); + } + + template + [[nodiscard]] LeftSemiJoin left_semijoin(const Table& right, TFn&& predicate) const; + template + [[nodiscard]] LeftSemiJoin LeftSemijoin(const Table& right, TFn&& predicate) const { + return left_semijoin(right, std::forward(predicate)); + } + + template + [[nodiscard]] RightSemiJoin right_semijoin(const Table& right, TFn&& predicate) const; + template + [[nodiscard]] RightSemiJoin RightSemijoin(const Table& right, TFn&& predicate) const { + return right_semijoin(right, std::forward(predicate)); + } + +private: + const char* table_name_; +}; + +template +class FromWhere { +public: + using row_type = TRow; + + constexpr FromWhere(const char* table_name, BoolExpr expr) + : table_name_(table_name), expr_(std::move(expr)) {} + + [[nodiscard]] constexpr const char* table_name() const { return table_name_; } + [[nodiscard]] const BoolExpr& expr() const { return expr_; } + + [[nodiscard]] RawQuery build() const { + std::string predicate = expr_.format(); + std::string sql; + sql.reserve(24 + std::char_traits::length(table_name_) + predicate.size()); + sql += "SELECT * FROM \""; + sql += table_name_; + sql += "\" WHERE "; + sql += predicate; + return RawQuery(std::move(sql)); + } + + [[nodiscard]] std::string into_sql() const { + return build().into_sql(); + } + + template + [[nodiscard]] FromWhere where(TFn&& predicate) const { + auto extra = detail::make_bool_expr(std::forward(predicate)(HasCols::get(table_name_))); + return FromWhere(table_name_, expr_.and_(extra)); + } + template + [[nodiscard]] FromWhere where_ix(TFn&& predicate) const { + auto extra = detail::make_bool_expr(std::forward(predicate)(HasCols::get(table_name_), HasIxCols::get(table_name_))); + return FromWhere(table_name_, expr_.and_(extra)); + } + template + [[nodiscard]] FromWhere Where(TFn&& predicate) const { + if constexpr (std::is_invocable_v::get(table_name_)), decltype(HasIxCols::get(table_name_))>) { + return where_ix(std::forward(predicate)); + } else { + return where(std::forward(predicate)); + } + } + + template + [[nodiscard]] FromWhere filter(TFn&& predicate) const { + return where(std::forward(predicate)); + } + template + [[nodiscard]] FromWhere Filter(TFn&& predicate) const { + return Where(std::forward(predicate)); + } + + template + [[nodiscard]] LeftSemiJoin left_semijoin(const Table& right, TFn&& predicate) const; + template + [[nodiscard]] LeftSemiJoin LeftSemijoin(const Table& right, TFn&& predicate) const { + return left_semijoin(right, std::forward(predicate)); + } + + template + [[nodiscard]] RightSemiJoin right_semijoin(const Table& right, TFn&& predicate) const; + template + [[nodiscard]] RightSemiJoin RightSemijoin(const Table& right, TFn&& predicate) const { + return right_semijoin(right, std::forward(predicate)); + } + +private: + const char* table_name_; + BoolExpr expr_; +}; + +template +template +[[nodiscard]] auto Table::where(TFn&& predicate) const { + auto expr = detail::make_bool_expr(std::forward(predicate)(HasCols::get(table_name_))); + return FromWhere(table_name_, std::move(expr)); +} + +template +template +[[nodiscard]] auto Table::where_ix(TFn&& predicate) const { + auto expr = detail::make_bool_expr(std::forward(predicate)(HasCols::get(table_name_), HasIxCols::get(table_name_))); + return FromWhere(table_name_, std::move(expr)); +} + +template +template +[[nodiscard]] auto Table::Where(TFn&& predicate) const { + if constexpr (std::is_invocable_v::get(table_name_)), decltype(HasIxCols::get(table_name_))>) { + return where_ix(std::forward(predicate)); + } else { + return where(std::forward(predicate)); + } +} + +template +struct query_row_type> { + using type = TRow; +}; + +template +struct query_row_type> { + using type = TRow; +}; + +template +struct query_row_type> { + using type = TRow; +}; + +} // namespace SpacetimeDB::query_builder + +#if 0 +// Intentionally disabled in Unreal v1. +// These bindings-cpp-only bsatn/algebraic_type hooks support module-side query-view +// metadata handling for RawQuery. The Unreal client query builder reuses the SQL +// generation core but does not participate in bindings-cpp module view registration. +// +// Source of truth: jlarabie/cpp-query-builder +// crates/bindings-cpp/include/spacetimedb/query_builder/table.h +namespace SpacetimeDB::bsatn { +template +struct algebraic_type_of<::SpacetimeDB::query_builder::RawQuery> { + static AlgebraicType get() { + std::vector elements; + elements.emplace_back(std::string("__query__"), algebraic_type_of::get()); + return AlgebraicType::make_product(std::make_unique(std::move(elements))); + } +}; + +template +struct bsatn_traits<::SpacetimeDB::query_builder::RawQuery> { + static void serialize(Writer&, const ::SpacetimeDB::query_builder::RawQuery&) { + std::fputs("SpacetimeDB bindings-cpp internal error: attempted to BSATN-serialize query_builder::RawQuery. " + "RawQuery is only valid as a view return type and should not be serialized directly.\n", + stderr); + std::abort(); + } + + static ::SpacetimeDB::query_builder::RawQuery deserialize(Reader&) { + std::fputs("SpacetimeDB bindings-cpp internal error: attempted to BSATN-deserialize query_builder::RawQuery. " + "RawQuery should only appear in query-view metadata handling.\n", + stderr); + std::abort(); + } + + static AlgebraicType algebraic_type() { + return algebraic_type_of<::SpacetimeDB::query_builder::RawQuery>::get(); + } +}; +} +#endif diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp index 22169073be0..b9655b02486 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -10911,6 +10911,27 @@ USubscriptionBuilder* UDbConnection::SubscriptionBuilder() Builder->Conn = this; return Builder; } +FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) +{ + OnAppliedDelegateInternal = Callback; + return *this; +} +FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnError(FOnSubscriptionError Callback) +{ + OnErrorDelegateInternal = Callback; + return *this; +} +USubscriptionHandle* FTypedSubscriptionBuilder::Subscribe() +{ + if (!Conn) + { + return nullptr; + } + USubscriptionBuilder* Builder = Conn->SubscriptionBuilder(); + Builder->OnApplied(OnAppliedDelegateInternal); + Builder->OnError(OnErrorDelegateInternal); + return Builder->Subscribe(Sql); +} USubscriptionBuilder* USubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) { OnAppliedDelegateInternal = Callback; @@ -10948,7 +10969,7 @@ USubscriptionHandle* USubscriptionBuilder::Subscribe(const TArray& SQL) } USubscriptionHandle* USubscriptionBuilder::SubscribeToAllTables() { - return Subscribe({ "SELECT * FROM * " }); + return Subscribe(FQueryBuilder::AllTablesSqlQueries()); } USubscriptionHandle::USubscriptionHandle(UDbConnection* InConn) diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/SpacetimeFullClientTests.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/SpacetimeFullClientTests.cpp index 4d201baeee3..18a9ae8635d 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/SpacetimeFullClientTests.cpp +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/SpacetimeFullClientTests.cpp @@ -102,6 +102,46 @@ static FString NormalizeDuration(const FSpacetimeDBTimeDuration &Dur) const double Seconds = static_cast(Dur.GetMicroseconds()) / 1'000'000.0; return TrimFloat(Seconds); } + +static void CompileTypedQueryBuilderSmoke(UDbConnection* Conn) +{ + Conn->SubscriptionBuilder() + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.OneU8().Where([](const FOneU8Cols& Cols) + { + return Cols.N.Eq(static_cast(1)); + }); + }) + .AddQuery([](const FQueryBuilder& Q) + { + return Q.From.OneString().Where([](const FOneStringCols& Cols) + { + return Cols.S.Eq(TEXT("typed-query-builder")); + }); + }) + .AddQuery([](const FQueryBuilder& Q) + { + return Q.From.OneTimestamp().Where([](const FOneTimestampCols& Cols) + { + return Cols.T.Gte(FSpacetimeDBTimestamp(1)); + }); + }) + .AddQuery([](const FQueryBuilder& Q) + { + return Q.From.PkU32().LeftSemijoin(Q.From.UniqueU32(), [](const FPkU32IxCols& Left, const FUniqueU32IxCols& Right) + { + return Left.N.Eq(Right.N); + }); + }) + .AddQuery([](const FQueryBuilder& Q) + { + return Q.From.UniqueU32().Where([](const FUniqueU32Cols&, const FUniqueU32IxCols& Ix) + { + return Ix.N.Eq(static_cast(7)); + }); + }); +} // bool FInsertPrimitiveTest::RunTest(const FString &Parameters) diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h index 1fb7d093579..793a2328dc9 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -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 2.0.3 (commit b6045fcc908d2846f8fb26570c2f300f5d685996). +// This was generated using spacetimedb cli version 2.0.5 (commit 047dac974526f5c5aff873026e90177270b10f38). #pragma once #include "CoreMinimal.h" @@ -227,11 +227,115 @@ #include "ModuleBindings/Types/EnumWithPayloadType.g.h" #include "ModuleBindings/Types/EveryPrimitiveStructType.g.h" #include "ModuleBindings/Types/EveryVecStructType.g.h" +#include "ModuleBindings/Types/IndexedSimpleEnumType.g.h" +#include "ModuleBindings/Types/LargeTableType.g.h" +#include "ModuleBindings/Types/OneBoolType.g.h" +#include "ModuleBindings/Types/OneByteStructType.g.h" +#include "ModuleBindings/Types/OneConnectionIdType.g.h" +#include "ModuleBindings/Types/OneEnumWithPayloadType.g.h" +#include "ModuleBindings/Types/OneEveryPrimitiveStructType.g.h" +#include "ModuleBindings/Types/OneEveryVecStructType.g.h" +#include "ModuleBindings/Types/OneF32Type.g.h" +#include "ModuleBindings/Types/OneF64Type.g.h" +#include "ModuleBindings/Types/OneI128Type.g.h" +#include "ModuleBindings/Types/OneI16Type.g.h" +#include "ModuleBindings/Types/OneI256Type.g.h" +#include "ModuleBindings/Types/OneI32Type.g.h" +#include "ModuleBindings/Types/OneI64Type.g.h" +#include "ModuleBindings/Types/OneI8Type.g.h" +#include "ModuleBindings/Types/OneIdentityType.g.h" +#include "ModuleBindings/Types/OneSimpleEnumType.g.h" +#include "ModuleBindings/Types/OneStringType.g.h" +#include "ModuleBindings/Types/OneTimestampType.g.h" +#include "ModuleBindings/Types/OneU128Type.g.h" +#include "ModuleBindings/Types/OneU16Type.g.h" +#include "ModuleBindings/Types/OneU256Type.g.h" +#include "ModuleBindings/Types/OneU32Type.g.h" +#include "ModuleBindings/Types/OneU64Type.g.h" #include "ModuleBindings/Types/OneU8Type.g.h" +#include "ModuleBindings/Types/OneUnitStructType.g.h" +#include "ModuleBindings/Types/OneUuidType.g.h" +#include "ModuleBindings/Types/OptionEveryPrimitiveStructType.g.h" +#include "ModuleBindings/Types/OptionI32Type.g.h" +#include "ModuleBindings/Types/OptionIdentityType.g.h" +#include "ModuleBindings/Types/OptionSimpleEnumType.g.h" +#include "ModuleBindings/Types/OptionStringType.g.h" +#include "ModuleBindings/Types/OptionUuidType.g.h" +#include "ModuleBindings/Types/OptionVecOptionI32Type.g.h" +#include "ModuleBindings/Types/PkBoolType.g.h" +#include "ModuleBindings/Types/PkConnectionIdType.g.h" +#include "ModuleBindings/Types/PkI128Type.g.h" +#include "ModuleBindings/Types/PkI16Type.g.h" +#include "ModuleBindings/Types/PkI256Type.g.h" +#include "ModuleBindings/Types/PkI32Type.g.h" +#include "ModuleBindings/Types/PkI64Type.g.h" +#include "ModuleBindings/Types/PkI8Type.g.h" +#include "ModuleBindings/Types/PkIdentityType.g.h" +#include "ModuleBindings/Types/PkSimpleEnumType.g.h" +#include "ModuleBindings/Types/PkStringType.g.h" +#include "ModuleBindings/Types/PkU128Type.g.h" +#include "ModuleBindings/Types/PkU16Type.g.h" +#include "ModuleBindings/Types/PkU256Type.g.h" +#include "ModuleBindings/Types/PkU32TwoType.g.h" #include "ModuleBindings/Types/PkU32Type.g.h" +#include "ModuleBindings/Types/PkU64Type.g.h" +#include "ModuleBindings/Types/PkU8Type.g.h" +#include "ModuleBindings/Types/PkUuidType.g.h" +#include "ModuleBindings/Types/ResultEveryPrimitiveStructStringType.g.h" +#include "ModuleBindings/Types/ResultI32StringType.g.h" +#include "ModuleBindings/Types/ResultIdentityStringType.g.h" +#include "ModuleBindings/Types/ResultSimpleEnumI32Type.g.h" +#include "ModuleBindings/Types/ResultStringI32Type.g.h" +#include "ModuleBindings/Types/ResultVecI32StringType.g.h" +#include "ModuleBindings/Types/ScheduledTableType.g.h" #include "ModuleBindings/Types/SimpleEnumType.g.h" +#include "ModuleBindings/Types/TableHoldsTableType.g.h" +#include "ModuleBindings/Types/UniqueBoolType.g.h" +#include "ModuleBindings/Types/UniqueConnectionIdType.g.h" +#include "ModuleBindings/Types/UniqueI128Type.g.h" +#include "ModuleBindings/Types/UniqueI16Type.g.h" +#include "ModuleBindings/Types/UniqueI256Type.g.h" +#include "ModuleBindings/Types/UniqueI32Type.g.h" +#include "ModuleBindings/Types/UniqueI64Type.g.h" +#include "ModuleBindings/Types/UniqueI8Type.g.h" +#include "ModuleBindings/Types/UniqueIdentityType.g.h" +#include "ModuleBindings/Types/UniqueStringType.g.h" +#include "ModuleBindings/Types/UniqueU128Type.g.h" +#include "ModuleBindings/Types/UniqueU16Type.g.h" +#include "ModuleBindings/Types/UniqueU256Type.g.h" +#include "ModuleBindings/Types/UniqueU32Type.g.h" +#include "ModuleBindings/Types/UniqueU64Type.g.h" +#include "ModuleBindings/Types/UniqueU8Type.g.h" +#include "ModuleBindings/Types/UniqueUuidType.g.h" #include "ModuleBindings/Types/UnitStructType.g.h" +#include "ModuleBindings/Types/UsersType.g.h" +#include "ModuleBindings/Types/VecBoolType.g.h" +#include "ModuleBindings/Types/VecByteStructType.g.h" +#include "ModuleBindings/Types/VecConnectionIdType.g.h" +#include "ModuleBindings/Types/VecEnumWithPayloadType.g.h" +#include "ModuleBindings/Types/VecEveryPrimitiveStructType.g.h" +#include "ModuleBindings/Types/VecEveryVecStructType.g.h" +#include "ModuleBindings/Types/VecF32Type.g.h" +#include "ModuleBindings/Types/VecF64Type.g.h" +#include "ModuleBindings/Types/VecI128Type.g.h" +#include "ModuleBindings/Types/VecI16Type.g.h" +#include "ModuleBindings/Types/VecI256Type.g.h" +#include "ModuleBindings/Types/VecI32Type.g.h" +#include "ModuleBindings/Types/VecI64Type.g.h" +#include "ModuleBindings/Types/VecI8Type.g.h" +#include "ModuleBindings/Types/VecIdentityType.g.h" +#include "ModuleBindings/Types/VecSimpleEnumType.g.h" +#include "ModuleBindings/Types/VecStringType.g.h" +#include "ModuleBindings/Types/VecTimestampType.g.h" +#include "ModuleBindings/Types/VecU128Type.g.h" +#include "ModuleBindings/Types/VecU16Type.g.h" +#include "ModuleBindings/Types/VecU256Type.g.h" +#include "ModuleBindings/Types/VecU32Type.g.h" +#include "ModuleBindings/Types/VecU64Type.g.h" #include "ModuleBindings/Types/VecU8Type.g.h" +#include "ModuleBindings/Types/VecUnitStructType.g.h" +#include "ModuleBindings/Types/VecUuidType.g.h" +#include "QueryBuilder/query_builder.h" #include "Types/Builtins.h" #include "SpacetimeDBClient.g.generated.h" @@ -10365,6 +10469,4044 @@ class TESTCLIENT_API URemoteProcedures : public UObject class UDbConnection* Conn; }; +// QueryBuilder types +struct TESTCLIENT_API FBTreeU32Cols +{ + explicit FBTreeU32Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FBTreeU32IxCols +{ + explicit FBTreeU32IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FBTreeU32Cols get(const char* table_name) { return FBTreeU32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FBTreeU32IxCols get(const char* table_name) { return FBTreeU32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FIndexedSimpleEnumCols +{ + explicit FIndexedSimpleEnumCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FIndexedSimpleEnumIxCols +{ + explicit FIndexedSimpleEnumIxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FIndexedSimpleEnumCols get(const char* table_name) { return FIndexedSimpleEnumCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FIndexedSimpleEnumIxCols get(const char* table_name) { return FIndexedSimpleEnumIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FLargeTableCols +{ + explicit FLargeTableCols(const char* TableName) + : A(TableName, "a"), B(TableName, "b"), C(TableName, "c"), D(TableName, "d"), E(TableName, "e"), F(TableName, "f"), G(TableName, "g"), H(TableName, "h"), I(TableName, "i"), J(TableName, "j"), K(TableName, "k"), L(TableName, "l"), M(TableName, "m"), N(TableName, "n"), O(TableName, "o"), P(TableName, "p"), Q(TableName, "q"), R(TableName, "r"), S(TableName, "s"), T(TableName, "t"), U(TableName, "u"), V(TableName, "v") {} + + ::SpacetimeDB::query_builder::Col A; + ::SpacetimeDB::query_builder::Col B; + ::SpacetimeDB::query_builder::Col C; + ::SpacetimeDB::query_builder::Col D; + ::SpacetimeDB::query_builder::Col E; + ::SpacetimeDB::query_builder::Col F; + ::SpacetimeDB::query_builder::Col G; + ::SpacetimeDB::query_builder::Col H; + ::SpacetimeDB::query_builder::Col I; + ::SpacetimeDB::query_builder::Col J; + ::SpacetimeDB::query_builder::Col K; + ::SpacetimeDB::query_builder::Col L; + ::SpacetimeDB::query_builder::Col M; + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col O; + ::SpacetimeDB::query_builder::Col P; + ::SpacetimeDB::query_builder::Col Q; + ::SpacetimeDB::query_builder::Col R; + ::SpacetimeDB::query_builder::Col S; + ::SpacetimeDB::query_builder::Col T; + ::SpacetimeDB::query_builder::Col U; + ::SpacetimeDB::query_builder::Col V; +}; + +struct TESTCLIENT_API FLargeTableIxCols +{ + explicit FLargeTableIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FLargeTableCols get(const char* table_name) { return FLargeTableCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FLargeTableIxCols get(const char* table_name) { return FLargeTableIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneBoolCols +{ + explicit FOneBoolCols(const char* TableName) + : B(TableName, "b") {} + + ::SpacetimeDB::query_builder::Col B; +}; + +struct TESTCLIENT_API FOneBoolIxCols +{ + explicit FOneBoolIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneBoolCols get(const char* table_name) { return FOneBoolCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneBoolIxCols get(const char* table_name) { return FOneBoolIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneByteStructCols +{ + explicit FOneByteStructCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::Col S; +}; + +struct TESTCLIENT_API FOneByteStructIxCols +{ + explicit FOneByteStructIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneByteStructCols get(const char* table_name) { return FOneByteStructCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneByteStructIxCols get(const char* table_name) { return FOneByteStructIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneConnectionIdCols +{ + explicit FOneConnectionIdCols(const char* TableName) + : A(TableName, "a") {} + + ::SpacetimeDB::query_builder::Col A; +}; + +struct TESTCLIENT_API FOneConnectionIdIxCols +{ + explicit FOneConnectionIdIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneConnectionIdCols get(const char* table_name) { return FOneConnectionIdCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneConnectionIdIxCols get(const char* table_name) { return FOneConnectionIdIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneEnumWithPayloadCols +{ + explicit FOneEnumWithPayloadCols(const char* TableName) + : E(TableName, "e") {} + + ::SpacetimeDB::query_builder::Col E; +}; + +struct TESTCLIENT_API FOneEnumWithPayloadIxCols +{ + explicit FOneEnumWithPayloadIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneEnumWithPayloadCols get(const char* table_name) { return FOneEnumWithPayloadCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneEnumWithPayloadIxCols get(const char* table_name) { return FOneEnumWithPayloadIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneEveryPrimitiveStructCols +{ + explicit FOneEveryPrimitiveStructCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::Col S; +}; + +struct TESTCLIENT_API FOneEveryPrimitiveStructIxCols +{ + explicit FOneEveryPrimitiveStructIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneEveryPrimitiveStructCols get(const char* table_name) { return FOneEveryPrimitiveStructCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneEveryPrimitiveStructIxCols get(const char* table_name) { return FOneEveryPrimitiveStructIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneEveryVecStructCols +{ + explicit FOneEveryVecStructCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::Col S; +}; + +struct TESTCLIENT_API FOneEveryVecStructIxCols +{ + explicit FOneEveryVecStructIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneEveryVecStructCols get(const char* table_name) { return FOneEveryVecStructCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneEveryVecStructIxCols get(const char* table_name) { return FOneEveryVecStructIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneF32Cols +{ + explicit FOneF32Cols(const char* TableName) + : F(TableName, "f") {} + + ::SpacetimeDB::query_builder::Col F; +}; + +struct TESTCLIENT_API FOneF32IxCols +{ + explicit FOneF32IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneF32Cols get(const char* table_name) { return FOneF32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneF32IxCols get(const char* table_name) { return FOneF32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneF64Cols +{ + explicit FOneF64Cols(const char* TableName) + : F(TableName, "f") {} + + ::SpacetimeDB::query_builder::Col F; +}; + +struct TESTCLIENT_API FOneF64IxCols +{ + explicit FOneF64IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneF64Cols get(const char* table_name) { return FOneF64Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneF64IxCols get(const char* table_name) { return FOneF64IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneI128Cols +{ + explicit FOneI128Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOneI128IxCols +{ + explicit FOneI128IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneI128Cols get(const char* table_name) { return FOneI128Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneI128IxCols get(const char* table_name) { return FOneI128IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneI16Cols +{ + explicit FOneI16Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOneI16IxCols +{ + explicit FOneI16IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneI16Cols get(const char* table_name) { return FOneI16Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneI16IxCols get(const char* table_name) { return FOneI16IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneI256Cols +{ + explicit FOneI256Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOneI256IxCols +{ + explicit FOneI256IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneI256Cols get(const char* table_name) { return FOneI256Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneI256IxCols get(const char* table_name) { return FOneI256IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneI32Cols +{ + explicit FOneI32Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOneI32IxCols +{ + explicit FOneI32IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneI32Cols get(const char* table_name) { return FOneI32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneI32IxCols get(const char* table_name) { return FOneI32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneI64Cols +{ + explicit FOneI64Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOneI64IxCols +{ + explicit FOneI64IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneI64Cols get(const char* table_name) { return FOneI64Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneI64IxCols get(const char* table_name) { return FOneI64IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneI8Cols +{ + explicit FOneI8Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOneI8IxCols +{ + explicit FOneI8IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneI8Cols get(const char* table_name) { return FOneI8Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneI8IxCols get(const char* table_name) { return FOneI8IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneIdentityCols +{ + explicit FOneIdentityCols(const char* TableName) + : I(TableName, "i") {} + + ::SpacetimeDB::query_builder::Col I; +}; + +struct TESTCLIENT_API FOneIdentityIxCols +{ + explicit FOneIdentityIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneIdentityCols get(const char* table_name) { return FOneIdentityCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneIdentityIxCols get(const char* table_name) { return FOneIdentityIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneSimpleEnumCols +{ + explicit FOneSimpleEnumCols(const char* TableName) + : E(TableName, "e") {} + + ::SpacetimeDB::query_builder::Col E; +}; + +struct TESTCLIENT_API FOneSimpleEnumIxCols +{ + explicit FOneSimpleEnumIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneSimpleEnumCols get(const char* table_name) { return FOneSimpleEnumCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneSimpleEnumIxCols get(const char* table_name) { return FOneSimpleEnumIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneStringCols +{ + explicit FOneStringCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::Col S; +}; + +struct TESTCLIENT_API FOneStringIxCols +{ + explicit FOneStringIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneStringCols get(const char* table_name) { return FOneStringCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneStringIxCols get(const char* table_name) { return FOneStringIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneTimestampCols +{ + explicit FOneTimestampCols(const char* TableName) + : T(TableName, "t") {} + + ::SpacetimeDB::query_builder::Col T; +}; + +struct TESTCLIENT_API FOneTimestampIxCols +{ + explicit FOneTimestampIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneTimestampCols get(const char* table_name) { return FOneTimestampCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneTimestampIxCols get(const char* table_name) { return FOneTimestampIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneU128Cols +{ + explicit FOneU128Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOneU128IxCols +{ + explicit FOneU128IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneU128Cols get(const char* table_name) { return FOneU128Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneU128IxCols get(const char* table_name) { return FOneU128IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneU16Cols +{ + explicit FOneU16Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOneU16IxCols +{ + explicit FOneU16IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneU16Cols get(const char* table_name) { return FOneU16Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneU16IxCols get(const char* table_name) { return FOneU16IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneU256Cols +{ + explicit FOneU256Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOneU256IxCols +{ + explicit FOneU256IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneU256Cols get(const char* table_name) { return FOneU256Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneU256IxCols get(const char* table_name) { return FOneU256IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneU32Cols +{ + explicit FOneU32Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOneU32IxCols +{ + explicit FOneU32IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneU32Cols get(const char* table_name) { return FOneU32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneU32IxCols get(const char* table_name) { return FOneU32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneU64Cols +{ + explicit FOneU64Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOneU64IxCols +{ + explicit FOneU64IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneU64Cols get(const char* table_name) { return FOneU64Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneU64IxCols get(const char* table_name) { return FOneU64IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneU8Cols +{ + explicit FOneU8Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOneU8IxCols +{ + explicit FOneU8IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneU8Cols get(const char* table_name) { return FOneU8Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneU8IxCols get(const char* table_name) { return FOneU8IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneUnitStructCols +{ + explicit FOneUnitStructCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::Col S; +}; + +struct TESTCLIENT_API FOneUnitStructIxCols +{ + explicit FOneUnitStructIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneUnitStructCols get(const char* table_name) { return FOneUnitStructCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneUnitStructIxCols get(const char* table_name) { return FOneUnitStructIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOneUuidCols +{ + explicit FOneUuidCols(const char* TableName) + : U(TableName, "u") {} + + ::SpacetimeDB::query_builder::Col U; +}; + +struct TESTCLIENT_API FOneUuidIxCols +{ + explicit FOneUuidIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOneUuidCols get(const char* table_name) { return FOneUuidCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOneUuidIxCols get(const char* table_name) { return FOneUuidIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOptionEveryPrimitiveStructCols +{ + explicit FOptionEveryPrimitiveStructCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::Col S; +}; + +struct TESTCLIENT_API FOptionEveryPrimitiveStructIxCols +{ + explicit FOptionEveryPrimitiveStructIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOptionEveryPrimitiveStructCols get(const char* table_name) { return FOptionEveryPrimitiveStructCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOptionEveryPrimitiveStructIxCols get(const char* table_name) { return FOptionEveryPrimitiveStructIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOptionI32Cols +{ + explicit FOptionI32Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col N; +}; + +struct TESTCLIENT_API FOptionI32IxCols +{ + explicit FOptionI32IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOptionI32Cols get(const char* table_name) { return FOptionI32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOptionI32IxCols get(const char* table_name) { return FOptionI32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOptionIdentityCols +{ + explicit FOptionIdentityCols(const char* TableName) + : I(TableName, "i") {} + + ::SpacetimeDB::query_builder::Col I; +}; + +struct TESTCLIENT_API FOptionIdentityIxCols +{ + explicit FOptionIdentityIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOptionIdentityCols get(const char* table_name) { return FOptionIdentityCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOptionIdentityIxCols get(const char* table_name) { return FOptionIdentityIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOptionSimpleEnumCols +{ + explicit FOptionSimpleEnumCols(const char* TableName) + : E(TableName, "e") {} + + ::SpacetimeDB::query_builder::Col E; +}; + +struct TESTCLIENT_API FOptionSimpleEnumIxCols +{ + explicit FOptionSimpleEnumIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOptionSimpleEnumCols get(const char* table_name) { return FOptionSimpleEnumCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOptionSimpleEnumIxCols get(const char* table_name) { return FOptionSimpleEnumIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOptionStringCols +{ + explicit FOptionStringCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::Col S; +}; + +struct TESTCLIENT_API FOptionStringIxCols +{ + explicit FOptionStringIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOptionStringCols get(const char* table_name) { return FOptionStringCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOptionStringIxCols get(const char* table_name) { return FOptionStringIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOptionUuidCols +{ + explicit FOptionUuidCols(const char* TableName) + : U(TableName, "u") {} + + ::SpacetimeDB::query_builder::Col U; +}; + +struct TESTCLIENT_API FOptionUuidIxCols +{ + explicit FOptionUuidIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOptionUuidCols get(const char* table_name) { return FOptionUuidCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOptionUuidIxCols get(const char* table_name) { return FOptionUuidIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FOptionVecOptionI32Cols +{ + explicit FOptionVecOptionI32Cols(const char* TableName) + : V(TableName, "v") {} + + ::SpacetimeDB::query_builder::Col V; +}; + +struct TESTCLIENT_API FOptionVecOptionI32IxCols +{ + explicit FOptionVecOptionI32IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FOptionVecOptionI32Cols get(const char* table_name) { return FOptionVecOptionI32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FOptionVecOptionI32IxCols get(const char* table_name) { return FOptionVecOptionI32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkBoolCols +{ + explicit FPkBoolCols(const char* TableName) + : B(TableName, "b"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col B; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkBoolIxCols +{ + explicit FPkBoolIxCols(const char* TableName) + : B(TableName, "b") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t B; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkBoolCols get(const char* table_name) { return FPkBoolCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkBoolIxCols get(const char* table_name) { return FPkBoolIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkConnectionIdCols +{ + explicit FPkConnectionIdCols(const char* TableName) + : A(TableName, "a"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col A; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkConnectionIdIxCols +{ + explicit FPkConnectionIdIxCols(const char* TableName) + : A(TableName, "a") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t A; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkConnectionIdCols get(const char* table_name) { return FPkConnectionIdCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkConnectionIdIxCols get(const char* table_name) { return FPkConnectionIdIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkI128Cols +{ + explicit FPkI128Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkI128IxCols +{ + explicit FPkI128IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkI128Cols get(const char* table_name) { return FPkI128Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkI128IxCols get(const char* table_name) { return FPkI128IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkI16Cols +{ + explicit FPkI16Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkI16IxCols +{ + explicit FPkI16IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkI16Cols get(const char* table_name) { return FPkI16Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkI16IxCols get(const char* table_name) { return FPkI16IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkI256Cols +{ + explicit FPkI256Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkI256IxCols +{ + explicit FPkI256IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkI256Cols get(const char* table_name) { return FPkI256Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkI256IxCols get(const char* table_name) { return FPkI256IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkI32Cols +{ + explicit FPkI32Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkI32IxCols +{ + explicit FPkI32IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkI32Cols get(const char* table_name) { return FPkI32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkI32IxCols get(const char* table_name) { return FPkI32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkI64Cols +{ + explicit FPkI64Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkI64IxCols +{ + explicit FPkI64IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkI64Cols get(const char* table_name) { return FPkI64Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkI64IxCols get(const char* table_name) { return FPkI64IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkI8Cols +{ + explicit FPkI8Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkI8IxCols +{ + explicit FPkI8IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkI8Cols get(const char* table_name) { return FPkI8Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkI8IxCols get(const char* table_name) { return FPkI8IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkIdentityCols +{ + explicit FPkIdentityCols(const char* TableName) + : I(TableName, "i"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col I; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkIdentityIxCols +{ + explicit FPkIdentityIxCols(const char* TableName) + : I(TableName, "i") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t I; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkIdentityCols get(const char* table_name) { return FPkIdentityCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkIdentityIxCols get(const char* table_name) { return FPkIdentityIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkSimpleEnumCols +{ + explicit FPkSimpleEnumCols(const char* TableName) + : A(TableName, "a"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col A; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkSimpleEnumIxCols +{ + explicit FPkSimpleEnumIxCols(const char* TableName) + : A(TableName, "a") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t A; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkSimpleEnumCols get(const char* table_name) { return FPkSimpleEnumCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkSimpleEnumIxCols get(const char* table_name) { return FPkSimpleEnumIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkStringCols +{ + explicit FPkStringCols(const char* TableName) + : S(TableName, "s"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col S; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkStringIxCols +{ + explicit FPkStringIxCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t S; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkStringCols get(const char* table_name) { return FPkStringCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkStringIxCols get(const char* table_name) { return FPkStringIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkU128Cols +{ + explicit FPkU128Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkU128IxCols +{ + explicit FPkU128IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkU128Cols get(const char* table_name) { return FPkU128Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkU128IxCols get(const char* table_name) { return FPkU128IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkU16Cols +{ + explicit FPkU16Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkU16IxCols +{ + explicit FPkU16IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkU16Cols get(const char* table_name) { return FPkU16Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkU16IxCols get(const char* table_name) { return FPkU16IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkU256Cols +{ + explicit FPkU256Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkU256IxCols +{ + explicit FPkU256IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkU256Cols get(const char* table_name) { return FPkU256Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkU256IxCols get(const char* table_name) { return FPkU256IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkU32Cols +{ + explicit FPkU32Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkU32IxCols +{ + explicit FPkU32IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkU32Cols get(const char* table_name) { return FPkU32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkU32IxCols get(const char* table_name) { return FPkU32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkU32TwoCols +{ + explicit FPkU32TwoCols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkU32TwoIxCols +{ + explicit FPkU32TwoIxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkU32TwoCols get(const char* table_name) { return FPkU32TwoCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkU32TwoIxCols get(const char* table_name) { return FPkU32TwoIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkU64Cols +{ + explicit FPkU64Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkU64IxCols +{ + explicit FPkU64IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkU64Cols get(const char* table_name) { return FPkU64Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkU64IxCols get(const char* table_name) { return FPkU64IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkU8Cols +{ + explicit FPkU8Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkU8IxCols +{ + explicit FPkU8IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkU8Cols get(const char* table_name) { return FPkU8Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkU8IxCols get(const char* table_name) { return FPkU8IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FPkUuidCols +{ + explicit FPkUuidCols(const char* TableName) + : U(TableName, "u"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col U; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FPkUuidIxCols +{ + explicit FPkUuidIxCols(const char* TableName) + : U(TableName, "u") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t U; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPkUuidCols get(const char* table_name) { return FPkUuidCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkUuidIxCols get(const char* table_name) { return FPkUuidIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FResultEveryPrimitiveStructStringCols +{ + explicit FResultEveryPrimitiveStructStringCols(const char* TableName) + : R(TableName, "r") {} + + ::SpacetimeDB::query_builder::Col R; +}; + +struct TESTCLIENT_API FResultEveryPrimitiveStructStringIxCols +{ + explicit FResultEveryPrimitiveStructStringIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FResultEveryPrimitiveStructStringCols get(const char* table_name) { return FResultEveryPrimitiveStructStringCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FResultEveryPrimitiveStructStringIxCols get(const char* table_name) { return FResultEveryPrimitiveStructStringIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FResultI32StringCols +{ + explicit FResultI32StringCols(const char* TableName) + : R(TableName, "r") {} + + ::SpacetimeDB::query_builder::Col R; +}; + +struct TESTCLIENT_API FResultI32StringIxCols +{ + explicit FResultI32StringIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FResultI32StringCols get(const char* table_name) { return FResultI32StringCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FResultI32StringIxCols get(const char* table_name) { return FResultI32StringIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FResultIdentityStringCols +{ + explicit FResultIdentityStringCols(const char* TableName) + : R(TableName, "r") {} + + ::SpacetimeDB::query_builder::Col R; +}; + +struct TESTCLIENT_API FResultIdentityStringIxCols +{ + explicit FResultIdentityStringIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FResultIdentityStringCols get(const char* table_name) { return FResultIdentityStringCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FResultIdentityStringIxCols get(const char* table_name) { return FResultIdentityStringIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FResultSimpleEnumI32Cols +{ + explicit FResultSimpleEnumI32Cols(const char* TableName) + : R(TableName, "r") {} + + ::SpacetimeDB::query_builder::Col R; +}; + +struct TESTCLIENT_API FResultSimpleEnumI32IxCols +{ + explicit FResultSimpleEnumI32IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FResultSimpleEnumI32Cols get(const char* table_name) { return FResultSimpleEnumI32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FResultSimpleEnumI32IxCols get(const char* table_name) { return FResultSimpleEnumI32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FResultStringI32Cols +{ + explicit FResultStringI32Cols(const char* TableName) + : R(TableName, "r") {} + + ::SpacetimeDB::query_builder::Col R; +}; + +struct TESTCLIENT_API FResultStringI32IxCols +{ + explicit FResultStringI32IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FResultStringI32Cols get(const char* table_name) { return FResultStringI32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FResultStringI32IxCols get(const char* table_name) { return FResultStringI32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FResultVecI32StringCols +{ + explicit FResultVecI32StringCols(const char* TableName) + : R(TableName, "r") {} + + ::SpacetimeDB::query_builder::Col R; +}; + +struct TESTCLIENT_API FResultVecI32StringIxCols +{ + explicit FResultVecI32StringIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FResultVecI32StringCols get(const char* table_name) { return FResultVecI32StringCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FResultVecI32StringIxCols get(const char* table_name) { return FResultVecI32StringIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FScheduledTableCols +{ + explicit FScheduledTableCols(const char* TableName) + : ScheduledId(TableName, "scheduled_id"), ScheduledAt(TableName, "scheduled_at"), Text(TableName, "text") {} + + ::SpacetimeDB::query_builder::Col ScheduledId; + ::SpacetimeDB::query_builder::Col ScheduledAt; + ::SpacetimeDB::query_builder::Col Text; +}; + +struct TESTCLIENT_API FScheduledTableIxCols +{ + explicit FScheduledTableIxCols(const char* TableName) + : ScheduledId(TableName, "scheduled_id") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t ScheduledId; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FScheduledTableCols get(const char* table_name) { return FScheduledTableCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FScheduledTableIxCols get(const char* table_name) { return FScheduledTableIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FTableHoldsTableCols +{ + explicit FTableHoldsTableCols(const char* TableName) + : A(TableName, "a"), B(TableName, "b") {} + + ::SpacetimeDB::query_builder::Col A; + ::SpacetimeDB::query_builder::Col B; +}; + +struct TESTCLIENT_API FTableHoldsTableIxCols +{ + explicit FTableHoldsTableIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FTableHoldsTableCols get(const char* table_name) { return FTableHoldsTableCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FTableHoldsTableIxCols get(const char* table_name) { return FTableHoldsTableIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueBoolCols +{ + explicit FUniqueBoolCols(const char* TableName) + : B(TableName, "b"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col B; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueBoolIxCols +{ + explicit FUniqueBoolIxCols(const char* TableName) + : B(TableName, "b") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t B; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueBoolCols get(const char* table_name) { return FUniqueBoolCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueBoolIxCols get(const char* table_name) { return FUniqueBoolIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueConnectionIdCols +{ + explicit FUniqueConnectionIdCols(const char* TableName) + : A(TableName, "a"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col A; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueConnectionIdIxCols +{ + explicit FUniqueConnectionIdIxCols(const char* TableName) + : A(TableName, "a") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t A; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueConnectionIdCols get(const char* table_name) { return FUniqueConnectionIdCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueConnectionIdIxCols get(const char* table_name) { return FUniqueConnectionIdIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueI128Cols +{ + explicit FUniqueI128Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueI128IxCols +{ + explicit FUniqueI128IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueI128Cols get(const char* table_name) { return FUniqueI128Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueI128IxCols get(const char* table_name) { return FUniqueI128IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueI16Cols +{ + explicit FUniqueI16Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueI16IxCols +{ + explicit FUniqueI16IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueI16Cols get(const char* table_name) { return FUniqueI16Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueI16IxCols get(const char* table_name) { return FUniqueI16IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueI256Cols +{ + explicit FUniqueI256Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueI256IxCols +{ + explicit FUniqueI256IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueI256Cols get(const char* table_name) { return FUniqueI256Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueI256IxCols get(const char* table_name) { return FUniqueI256IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueI32Cols +{ + explicit FUniqueI32Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueI32IxCols +{ + explicit FUniqueI32IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueI32Cols get(const char* table_name) { return FUniqueI32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueI32IxCols get(const char* table_name) { return FUniqueI32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueI64Cols +{ + explicit FUniqueI64Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueI64IxCols +{ + explicit FUniqueI64IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueI64Cols get(const char* table_name) { return FUniqueI64Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueI64IxCols get(const char* table_name) { return FUniqueI64IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueI8Cols +{ + explicit FUniqueI8Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueI8IxCols +{ + explicit FUniqueI8IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueI8Cols get(const char* table_name) { return FUniqueI8Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueI8IxCols get(const char* table_name) { return FUniqueI8IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueIdentityCols +{ + explicit FUniqueIdentityCols(const char* TableName) + : I(TableName, "i"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col I; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueIdentityIxCols +{ + explicit FUniqueIdentityIxCols(const char* TableName) + : I(TableName, "i") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t I; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueIdentityCols get(const char* table_name) { return FUniqueIdentityCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueIdentityIxCols get(const char* table_name) { return FUniqueIdentityIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueStringCols +{ + explicit FUniqueStringCols(const char* TableName) + : S(TableName, "s"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col S; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueStringIxCols +{ + explicit FUniqueStringIxCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t S; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueStringCols get(const char* table_name) { return FUniqueStringCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueStringIxCols get(const char* table_name) { return FUniqueStringIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueU128Cols +{ + explicit FUniqueU128Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueU128IxCols +{ + explicit FUniqueU128IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueU128Cols get(const char* table_name) { return FUniqueU128Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueU128IxCols get(const char* table_name) { return FUniqueU128IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueU16Cols +{ + explicit FUniqueU16Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueU16IxCols +{ + explicit FUniqueU16IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueU16Cols get(const char* table_name) { return FUniqueU16Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueU16IxCols get(const char* table_name) { return FUniqueU16IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueU256Cols +{ + explicit FUniqueU256Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueU256IxCols +{ + explicit FUniqueU256IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueU256Cols get(const char* table_name) { return FUniqueU256Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueU256IxCols get(const char* table_name) { return FUniqueU256IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueU32Cols +{ + explicit FUniqueU32Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueU32IxCols +{ + explicit FUniqueU32IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueU32Cols get(const char* table_name) { return FUniqueU32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueU32IxCols get(const char* table_name) { return FUniqueU32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueU64Cols +{ + explicit FUniqueU64Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueU64IxCols +{ + explicit FUniqueU64IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueU64Cols get(const char* table_name) { return FUniqueU64Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueU64IxCols get(const char* table_name) { return FUniqueU64IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueU8Cols +{ + explicit FUniqueU8Cols(const char* TableName) + : N(TableName, "n"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col N; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueU8IxCols +{ + explicit FUniqueU8IxCols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t N; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueU8Cols get(const char* table_name) { return FUniqueU8Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueU8IxCols get(const char* table_name) { return FUniqueU8IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUniqueUuidCols +{ + explicit FUniqueUuidCols(const char* TableName) + : U(TableName, "u"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col U; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTCLIENT_API FUniqueUuidIxCols +{ + explicit FUniqueUuidIxCols(const char* TableName) + : U(TableName, "u") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t U; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUniqueUuidCols get(const char* table_name) { return FUniqueUuidCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUniqueUuidIxCols get(const char* table_name) { return FUniqueUuidIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FUsersCols +{ + explicit FUsersCols(const char* TableName) + : Identity(TableName, "identity"), Name(TableName, "name") {} + + ::SpacetimeDB::query_builder::Col Identity; + ::SpacetimeDB::query_builder::Col Name; +}; + +struct TESTCLIENT_API FUsersIxCols +{ + explicit FUsersIxCols(const char* TableName) + : Identity(TableName, "identity") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t Identity; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FUsersCols get(const char* table_name) { return FUsersCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FUsersIxCols get(const char* table_name) { return FUsersIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecBoolCols +{ + explicit FVecBoolCols(const char* TableName) + : B(TableName, "b") {} + + ::SpacetimeDB::query_builder::Col> B; +}; + +struct TESTCLIENT_API FVecBoolIxCols +{ + explicit FVecBoolIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecBoolCols get(const char* table_name) { return FVecBoolCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecBoolIxCols get(const char* table_name) { return FVecBoolIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecByteStructCols +{ + explicit FVecByteStructCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::Col> S; +}; + +struct TESTCLIENT_API FVecByteStructIxCols +{ + explicit FVecByteStructIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecByteStructCols get(const char* table_name) { return FVecByteStructCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecByteStructIxCols get(const char* table_name) { return FVecByteStructIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecConnectionIdCols +{ + explicit FVecConnectionIdCols(const char* TableName) + : A(TableName, "a") {} + + ::SpacetimeDB::query_builder::Col> A; +}; + +struct TESTCLIENT_API FVecConnectionIdIxCols +{ + explicit FVecConnectionIdIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecConnectionIdCols get(const char* table_name) { return FVecConnectionIdCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecConnectionIdIxCols get(const char* table_name) { return FVecConnectionIdIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecEnumWithPayloadCols +{ + explicit FVecEnumWithPayloadCols(const char* TableName) + : E(TableName, "e") {} + + ::SpacetimeDB::query_builder::Col> E; +}; + +struct TESTCLIENT_API FVecEnumWithPayloadIxCols +{ + explicit FVecEnumWithPayloadIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecEnumWithPayloadCols get(const char* table_name) { return FVecEnumWithPayloadCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecEnumWithPayloadIxCols get(const char* table_name) { return FVecEnumWithPayloadIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecEveryPrimitiveStructCols +{ + explicit FVecEveryPrimitiveStructCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::Col> S; +}; + +struct TESTCLIENT_API FVecEveryPrimitiveStructIxCols +{ + explicit FVecEveryPrimitiveStructIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecEveryPrimitiveStructCols get(const char* table_name) { return FVecEveryPrimitiveStructCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecEveryPrimitiveStructIxCols get(const char* table_name) { return FVecEveryPrimitiveStructIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecEveryVecStructCols +{ + explicit FVecEveryVecStructCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::Col> S; +}; + +struct TESTCLIENT_API FVecEveryVecStructIxCols +{ + explicit FVecEveryVecStructIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecEveryVecStructCols get(const char* table_name) { return FVecEveryVecStructCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecEveryVecStructIxCols get(const char* table_name) { return FVecEveryVecStructIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecF32Cols +{ + explicit FVecF32Cols(const char* TableName) + : F(TableName, "f") {} + + ::SpacetimeDB::query_builder::Col> F; +}; + +struct TESTCLIENT_API FVecF32IxCols +{ + explicit FVecF32IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecF32Cols get(const char* table_name) { return FVecF32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecF32IxCols get(const char* table_name) { return FVecF32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecF64Cols +{ + explicit FVecF64Cols(const char* TableName) + : F(TableName, "f") {} + + ::SpacetimeDB::query_builder::Col> F; +}; + +struct TESTCLIENT_API FVecF64IxCols +{ + explicit FVecF64IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecF64Cols get(const char* table_name) { return FVecF64Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecF64IxCols get(const char* table_name) { return FVecF64IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecI128Cols +{ + explicit FVecI128Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col> N; +}; + +struct TESTCLIENT_API FVecI128IxCols +{ + explicit FVecI128IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecI128Cols get(const char* table_name) { return FVecI128Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecI128IxCols get(const char* table_name) { return FVecI128IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecI16Cols +{ + explicit FVecI16Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col> N; +}; + +struct TESTCLIENT_API FVecI16IxCols +{ + explicit FVecI16IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecI16Cols get(const char* table_name) { return FVecI16Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecI16IxCols get(const char* table_name) { return FVecI16IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecI256Cols +{ + explicit FVecI256Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col> N; +}; + +struct TESTCLIENT_API FVecI256IxCols +{ + explicit FVecI256IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecI256Cols get(const char* table_name) { return FVecI256Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecI256IxCols get(const char* table_name) { return FVecI256IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecI32Cols +{ + explicit FVecI32Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col> N; +}; + +struct TESTCLIENT_API FVecI32IxCols +{ + explicit FVecI32IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecI32Cols get(const char* table_name) { return FVecI32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecI32IxCols get(const char* table_name) { return FVecI32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecI64Cols +{ + explicit FVecI64Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col> N; +}; + +struct TESTCLIENT_API FVecI64IxCols +{ + explicit FVecI64IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecI64Cols get(const char* table_name) { return FVecI64Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecI64IxCols get(const char* table_name) { return FVecI64IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecI8Cols +{ + explicit FVecI8Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col> N; +}; + +struct TESTCLIENT_API FVecI8IxCols +{ + explicit FVecI8IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecI8Cols get(const char* table_name) { return FVecI8Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecI8IxCols get(const char* table_name) { return FVecI8IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecIdentityCols +{ + explicit FVecIdentityCols(const char* TableName) + : I(TableName, "i") {} + + ::SpacetimeDB::query_builder::Col> I; +}; + +struct TESTCLIENT_API FVecIdentityIxCols +{ + explicit FVecIdentityIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecIdentityCols get(const char* table_name) { return FVecIdentityCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecIdentityIxCols get(const char* table_name) { return FVecIdentityIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecSimpleEnumCols +{ + explicit FVecSimpleEnumCols(const char* TableName) + : E(TableName, "e") {} + + ::SpacetimeDB::query_builder::Col> E; +}; + +struct TESTCLIENT_API FVecSimpleEnumIxCols +{ + explicit FVecSimpleEnumIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecSimpleEnumCols get(const char* table_name) { return FVecSimpleEnumCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecSimpleEnumIxCols get(const char* table_name) { return FVecSimpleEnumIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecStringCols +{ + explicit FVecStringCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::Col> S; +}; + +struct TESTCLIENT_API FVecStringIxCols +{ + explicit FVecStringIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecStringCols get(const char* table_name) { return FVecStringCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecStringIxCols get(const char* table_name) { return FVecStringIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecTimestampCols +{ + explicit FVecTimestampCols(const char* TableName) + : T(TableName, "t") {} + + ::SpacetimeDB::query_builder::Col> T; +}; + +struct TESTCLIENT_API FVecTimestampIxCols +{ + explicit FVecTimestampIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecTimestampCols get(const char* table_name) { return FVecTimestampCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecTimestampIxCols get(const char* table_name) { return FVecTimestampIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecU128Cols +{ + explicit FVecU128Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col> N; +}; + +struct TESTCLIENT_API FVecU128IxCols +{ + explicit FVecU128IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecU128Cols get(const char* table_name) { return FVecU128Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecU128IxCols get(const char* table_name) { return FVecU128IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecU16Cols +{ + explicit FVecU16Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col> N; +}; + +struct TESTCLIENT_API FVecU16IxCols +{ + explicit FVecU16IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecU16Cols get(const char* table_name) { return FVecU16Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecU16IxCols get(const char* table_name) { return FVecU16IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecU256Cols +{ + explicit FVecU256Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col> N; +}; + +struct TESTCLIENT_API FVecU256IxCols +{ + explicit FVecU256IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecU256Cols get(const char* table_name) { return FVecU256Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecU256IxCols get(const char* table_name) { return FVecU256IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecU32Cols +{ + explicit FVecU32Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col> N; +}; + +struct TESTCLIENT_API FVecU32IxCols +{ + explicit FVecU32IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecU32Cols get(const char* table_name) { return FVecU32Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecU32IxCols get(const char* table_name) { return FVecU32IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecU64Cols +{ + explicit FVecU64Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col> N; +}; + +struct TESTCLIENT_API FVecU64IxCols +{ + explicit FVecU64IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecU64Cols get(const char* table_name) { return FVecU64Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecU64IxCols get(const char* table_name) { return FVecU64IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecU8Cols +{ + explicit FVecU8Cols(const char* TableName) + : N(TableName, "n") {} + + ::SpacetimeDB::query_builder::Col> N; +}; + +struct TESTCLIENT_API FVecU8IxCols +{ + explicit FVecU8IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecU8Cols get(const char* table_name) { return FVecU8Cols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecU8IxCols get(const char* table_name) { return FVecU8IxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecUnitStructCols +{ + explicit FVecUnitStructCols(const char* TableName) + : S(TableName, "s") {} + + ::SpacetimeDB::query_builder::Col> S; +}; + +struct TESTCLIENT_API FVecUnitStructIxCols +{ + explicit FVecUnitStructIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecUnitStructCols get(const char* table_name) { return FVecUnitStructCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecUnitStructIxCols get(const char* table_name) { return FVecUnitStructIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FVecUuidCols +{ + explicit FVecUuidCols(const char* TableName) + : U(TableName, "u") {} + + ::SpacetimeDB::query_builder::Col> U; +}; + +struct TESTCLIENT_API FVecUuidIxCols +{ + explicit FVecUuidIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FVecUuidCols get(const char* table_name) { return FVecUuidCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FVecUuidIxCols get(const char* table_name) { return FVecUuidIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTCLIENT_API FFrom +{ + [[nodiscard]] ::SpacetimeDB::query_builder::Table BtreeU32() const { return ::SpacetimeDB::query_builder::Table("btree_u_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table IndexedSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("indexed_simple_enum"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table LargeTable() const { return ::SpacetimeDB::query_builder::Table("large_table"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneBool() const { return ::SpacetimeDB::query_builder::Table("one_bool"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneByteStruct() const { return ::SpacetimeDB::query_builder::Table("one_byte_struct"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneConnectionId() const { return ::SpacetimeDB::query_builder::Table("one_connection_id"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneEnumWithPayload() const { return ::SpacetimeDB::query_builder::Table("one_enum_with_payload"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneEveryPrimitiveStruct() const { return ::SpacetimeDB::query_builder::Table("one_every_primitive_struct"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneEveryVecStruct() const { return ::SpacetimeDB::query_builder::Table("one_every_vec_struct"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneF32() const { return ::SpacetimeDB::query_builder::Table("one_f_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneF64() const { return ::SpacetimeDB::query_builder::Table("one_f_64"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI128() const { return ::SpacetimeDB::query_builder::Table("one_i_128"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI16() const { return ::SpacetimeDB::query_builder::Table("one_i_16"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI256() const { return ::SpacetimeDB::query_builder::Table("one_i_256"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI32() const { return ::SpacetimeDB::query_builder::Table("one_i_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI64() const { return ::SpacetimeDB::query_builder::Table("one_i_64"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI8() const { return ::SpacetimeDB::query_builder::Table("one_i_8"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneIdentity() const { return ::SpacetimeDB::query_builder::Table("one_identity"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("one_simple_enum"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneString() const { return ::SpacetimeDB::query_builder::Table("one_string"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneTimestamp() const { return ::SpacetimeDB::query_builder::Table("one_timestamp"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU128() const { return ::SpacetimeDB::query_builder::Table("one_u_128"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU16() const { return ::SpacetimeDB::query_builder::Table("one_u_16"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU256() const { return ::SpacetimeDB::query_builder::Table("one_u_256"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU32() const { return ::SpacetimeDB::query_builder::Table("one_u_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU64() const { return ::SpacetimeDB::query_builder::Table("one_u_64"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU8() const { return ::SpacetimeDB::query_builder::Table("one_u_8"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneUnitStruct() const { return ::SpacetimeDB::query_builder::Table("one_unit_struct"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneUuid() const { return ::SpacetimeDB::query_builder::Table("one_uuid"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionEveryPrimitiveStruct() const { return ::SpacetimeDB::query_builder::Table("option_every_primitive_struct"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionI32() const { return ::SpacetimeDB::query_builder::Table("option_i_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionIdentity() const { return ::SpacetimeDB::query_builder::Table("option_identity"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("option_simple_enum"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionString() const { return ::SpacetimeDB::query_builder::Table("option_string"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionUuid() const { return ::SpacetimeDB::query_builder::Table("option_uuid"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionVecOptionI32() const { return ::SpacetimeDB::query_builder::Table("option_vec_option_i_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkBool() const { return ::SpacetimeDB::query_builder::Table("pk_bool"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkConnectionId() const { return ::SpacetimeDB::query_builder::Table("pk_connection_id"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI128() const { return ::SpacetimeDB::query_builder::Table("pk_i_128"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI16() const { return ::SpacetimeDB::query_builder::Table("pk_i_16"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI256() const { return ::SpacetimeDB::query_builder::Table("pk_i_256"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI32() const { return ::SpacetimeDB::query_builder::Table("pk_i_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI64() const { return ::SpacetimeDB::query_builder::Table("pk_i_64"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI8() const { return ::SpacetimeDB::query_builder::Table("pk_i_8"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkIdentity() const { return ::SpacetimeDB::query_builder::Table("pk_identity"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("pk_simple_enum"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkString() const { return ::SpacetimeDB::query_builder::Table("pk_string"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU128() const { return ::SpacetimeDB::query_builder::Table("pk_u_128"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU16() const { return ::SpacetimeDB::query_builder::Table("pk_u_16"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU256() const { return ::SpacetimeDB::query_builder::Table("pk_u_256"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU32() const { return ::SpacetimeDB::query_builder::Table("pk_u_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU32Two() const { return ::SpacetimeDB::query_builder::Table("pk_u_32_two"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU64() const { return ::SpacetimeDB::query_builder::Table("pk_u_64"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU8() const { return ::SpacetimeDB::query_builder::Table("pk_u_8"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkUuid() const { return ::SpacetimeDB::query_builder::Table("pk_uuid"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultEveryPrimitiveStructString() const { return ::SpacetimeDB::query_builder::Table("result_every_primitive_struct_string"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultI32String() const { return ::SpacetimeDB::query_builder::Table("result_i_32_string"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultIdentityString() const { return ::SpacetimeDB::query_builder::Table("result_identity_string"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultSimpleEnumI32() const { return ::SpacetimeDB::query_builder::Table("result_simple_enum_i_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultStringI32() const { return ::SpacetimeDB::query_builder::Table("result_string_i_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultVecI32String() const { return ::SpacetimeDB::query_builder::Table("result_vec_i_32_string"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ScheduledTable() const { return ::SpacetimeDB::query_builder::Table("scheduled_table"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table TableHoldsTable() const { return ::SpacetimeDB::query_builder::Table("table_holds_table"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueBool() const { return ::SpacetimeDB::query_builder::Table("unique_bool"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueConnectionId() const { return ::SpacetimeDB::query_builder::Table("unique_connection_id"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI128() const { return ::SpacetimeDB::query_builder::Table("unique_i_128"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI16() const { return ::SpacetimeDB::query_builder::Table("unique_i_16"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI256() const { return ::SpacetimeDB::query_builder::Table("unique_i_256"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI32() const { return ::SpacetimeDB::query_builder::Table("unique_i_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI64() const { return ::SpacetimeDB::query_builder::Table("unique_i_64"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI8() const { return ::SpacetimeDB::query_builder::Table("unique_i_8"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueIdentity() const { return ::SpacetimeDB::query_builder::Table("unique_identity"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueString() const { return ::SpacetimeDB::query_builder::Table("unique_string"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU128() const { return ::SpacetimeDB::query_builder::Table("unique_u_128"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU16() const { return ::SpacetimeDB::query_builder::Table("unique_u_16"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU256() const { return ::SpacetimeDB::query_builder::Table("unique_u_256"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU32() const { return ::SpacetimeDB::query_builder::Table("unique_u_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU64() const { return ::SpacetimeDB::query_builder::Table("unique_u_64"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU8() const { return ::SpacetimeDB::query_builder::Table("unique_u_8"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueUuid() const { return ::SpacetimeDB::query_builder::Table("unique_uuid"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table Users() const { return ::SpacetimeDB::query_builder::Table("users"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecBool() const { return ::SpacetimeDB::query_builder::Table("vec_bool"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecByteStruct() const { return ::SpacetimeDB::query_builder::Table("vec_byte_struct"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecConnectionId() const { return ::SpacetimeDB::query_builder::Table("vec_connection_id"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecEnumWithPayload() const { return ::SpacetimeDB::query_builder::Table("vec_enum_with_payload"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecEveryPrimitiveStruct() const { return ::SpacetimeDB::query_builder::Table("vec_every_primitive_struct"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecEveryVecStruct() const { return ::SpacetimeDB::query_builder::Table("vec_every_vec_struct"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecF32() const { return ::SpacetimeDB::query_builder::Table("vec_f_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecF64() const { return ::SpacetimeDB::query_builder::Table("vec_f_64"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI128() const { return ::SpacetimeDB::query_builder::Table("vec_i_128"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI16() const { return ::SpacetimeDB::query_builder::Table("vec_i_16"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI256() const { return ::SpacetimeDB::query_builder::Table("vec_i_256"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI32() const { return ::SpacetimeDB::query_builder::Table("vec_i_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI64() const { return ::SpacetimeDB::query_builder::Table("vec_i_64"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI8() const { return ::SpacetimeDB::query_builder::Table("vec_i_8"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecIdentity() const { return ::SpacetimeDB::query_builder::Table("vec_identity"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("vec_simple_enum"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecString() const { return ::SpacetimeDB::query_builder::Table("vec_string"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecTimestamp() const { return ::SpacetimeDB::query_builder::Table("vec_timestamp"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU128() const { return ::SpacetimeDB::query_builder::Table("vec_u_128"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU16() const { return ::SpacetimeDB::query_builder::Table("vec_u_16"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU256() const { return ::SpacetimeDB::query_builder::Table("vec_u_256"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU32() const { return ::SpacetimeDB::query_builder::Table("vec_u_32"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU64() const { return ::SpacetimeDB::query_builder::Table("vec_u_64"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU8() const { return ::SpacetimeDB::query_builder::Table("vec_u_8"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecUnitStruct() const { return ::SpacetimeDB::query_builder::Table("vec_unit_struct"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecUuid() const { return ::SpacetimeDB::query_builder::Table("vec_uuid"); } +}; + +struct TESTCLIENT_API FQueryBuilder +{ + FFrom From; + + static TArray AllTablesSqlQueries() + { + TArray Sql; + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.BtreeU32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.IndexedSimpleEnum().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.LargeTable().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneBool().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneByteStruct().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneConnectionId().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneEnumWithPayload().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneEveryPrimitiveStruct().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneEveryVecStruct().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneF32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneF64().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneI128().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneI16().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneI256().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneI32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneI64().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneI8().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneIdentity().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneSimpleEnum().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneString().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneTimestamp().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneU128().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneU16().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneU256().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneU32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneU64().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneU8().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneUnitStruct().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneUuid().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionEveryPrimitiveStruct().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionI32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionIdentity().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionSimpleEnum().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionString().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionUuid().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionVecOptionI32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkBool().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkConnectionId().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkI128().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkI16().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkI256().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkI32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkI64().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkI8().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkIdentity().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkSimpleEnum().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkString().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU128().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU16().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU256().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU32Two().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU64().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU8().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkUuid().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.ResultEveryPrimitiveStructString().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.ResultI32String().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.ResultIdentityString().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.ResultSimpleEnumI32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.ResultStringI32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.ResultVecI32String().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.ScheduledTable().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.TableHoldsTable().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueBool().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueConnectionId().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueI128().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueI16().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueI256().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueI32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueI64().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueI8().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueIdentity().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueString().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueU128().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueU16().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueU256().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueU32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueU64().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueU8().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueUuid().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.Users().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecBool().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecByteStruct().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecConnectionId().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecEnumWithPayload().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecEveryPrimitiveStruct().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecEveryVecStruct().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecF32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecF64().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecI128().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecI16().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecI256().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecI32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecI64().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecI8().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecIdentity().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecSimpleEnum().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecString().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecTimestamp().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecU128().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecU16().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecU256().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecU32().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecU64().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecU8().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecUnitStruct().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecUuid().into_sql().c_str()))); + return Sql; + } +}; + +struct TESTCLIENT_API FTypedSubscriptionBuilder +{ + explicit FTypedSubscriptionBuilder(UDbConnection* InConn) + : Conn(InConn) {} + + FTypedSubscriptionBuilder& OnApplied(FOnSubscriptionApplied Callback); + FTypedSubscriptionBuilder& OnError(FOnSubscriptionError Callback); + + template + FTypedSubscriptionBuilder& AddQuery(TFn&& Build) + { + FQueryBuilder Q; + auto Query = std::forward(Build)(Q); + static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn, + "Typed subscription queries must return a query_builder table/query expression."); + Sql.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str()))); + return *this; + } + + USubscriptionHandle* Subscribe(); + +private: + UDbConnection* Conn = nullptr; + TArray Sql; + FOnSubscriptionApplied OnAppliedDelegateInternal; + FOnSubscriptionError OnErrorDelegateInternal; +}; + // SubscriptionBuilder class UCLASS(BlueprintType) class TESTCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase @@ -10382,6 +14524,16 @@ class TESTCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase UFUNCTION(BlueprintCallable, Category="SpacetimeDB") USubscriptionHandle* Subscribe(const TArray& SQL); + template + [[nodiscard]] FTypedSubscriptionBuilder AddQuery(TFn&& Build) + { + FTypedSubscriptionBuilder Typed(Conn); + Typed.OnApplied(OnAppliedDelegateInternal); + Typed.OnError(OnErrorDelegateInternal); + Typed.AddQuery(std::forward(Build)); + return Typed; + } + /** Convenience for subscribing to all rows from all tables */ UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") USubscriptionHandle* SubscribeToAllTables(); diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h index 1c4ef086cf8..2216ede8dae 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h @@ -5,8 +5,8 @@ #include "CoreMinimal.h" #include "BSATN/UESpacetimeDB.h" #include "ModuleBindings/Types/SimpleEnumType.g.h" -#include "Kismet/BlueprintFunctionLibrary.h" #include "Types/Builtins.h" +#include "Kismet/BlueprintFunctionLibrary.h" #include "EnumWithPayloadType.g.generated.h" UENUM(BlueprintType) @@ -46,7 +46,7 @@ struct TESTCLIENT_API FEnumWithPayloadType public: FEnumWithPayloadType() = default; - TVariant, uint32, int16, uint8, FSpacetimeDBInt128, FString, int64, uint64, int32, double, FSpacetimeDBInt256, TArray, bool, int8, uint16, FSpacetimeDBUInt128, float, FSpacetimeDBUInt256, FSpacetimeDBConnectionId, TArray, TArray, FSpacetimeDBTimestamp> MessageData; + TVariant, FSpacetimeDBConnectionId, TArray, int8, int16, FSpacetimeDBInt128, FSpacetimeDBIdentity, FSpacetimeDBUuid, uint32, TArray, FSpacetimeDBInt256, bool, uint64, FString, TArray, uint16, FSpacetimeDBUInt128, uint8, int32, int64, double, float> MessageData; UPROPERTY(BlueprintReadOnly) EEnumWithPayloadTag Tag = static_cast(0); diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp index e324c566449..b2b6ac65b18 100644 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp +++ b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -547,6 +547,27 @@ USubscriptionBuilder* UDbConnection::SubscriptionBuilder() Builder->Conn = this; return Builder; } +FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) +{ + OnAppliedDelegateInternal = Callback; + return *this; +} +FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnError(FOnSubscriptionError Callback) +{ + OnErrorDelegateInternal = Callback; + return *this; +} +USubscriptionHandle* FTypedSubscriptionBuilder::Subscribe() +{ + if (!Conn) + { + return nullptr; + } + USubscriptionBuilder* Builder = Conn->SubscriptionBuilder(); + Builder->OnApplied(OnAppliedDelegateInternal); + Builder->OnError(OnErrorDelegateInternal); + return Builder->Subscribe(Sql); +} USubscriptionBuilder* USubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) { OnAppliedDelegateInternal = Callback; @@ -584,7 +605,7 @@ USubscriptionHandle* USubscriptionBuilder::Subscribe(const TArray& SQL) } USubscriptionHandle* USubscriptionBuilder::SubscribeToAllTables() { - return Subscribe({ "SELECT * FROM * " }); + return Subscribe(FQueryBuilder::AllTablesSqlQueries()); } USubscriptionHandle::USubscriptionHandle(UDbConnection* InConn) diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h index c991307b61b..21277cb0b15 100644 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -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 2.0.3 (commit b6045fcc908d2846f8fb26570c2f300f5d685996). +// This was generated using spacetimedb cli version 2.0.5 (commit 047dac974526f5c5aff873026e90177270b10f38). #pragma once #include "CoreMinimal.h" @@ -23,8 +23,12 @@ #include "ModuleBindings/Procedures/WillPanic.g.h" #include "ModuleBindings/ReducerBase.g.h" #include "ModuleBindings/Reducers/ScheduleProc.g.h" +#include "ModuleBindings/Types/MyTableType.g.h" +#include "ModuleBindings/Types/PkUuidType.g.h" +#include "ModuleBindings/Types/ProcInsertsIntoType.g.h" #include "ModuleBindings/Types/ReturnEnumType.g.h" #include "ModuleBindings/Types/ReturnStructType.g.h" +#include "QueryBuilder/query_builder.h" #include "Types/Builtins.h" #include "Types/UnitType.h" #include "SpacetimeDBClient.g.generated.h" @@ -1107,6 +1111,162 @@ class TESTPROCCLIENT_API URemoteProcedures : public UObject class UDbConnection* Conn; }; +// QueryBuilder types +struct TESTPROCCLIENT_API FMyTableCols +{ + explicit FMyTableCols(const char* TableName) + : Field(TableName, "field") {} + + ::SpacetimeDB::query_builder::Col Field; +}; + +struct TESTPROCCLIENT_API FMyTableIxCols +{ + explicit FMyTableIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FMyTableCols get(const char* table_name) { return FMyTableCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FMyTableIxCols get(const char* table_name) { return FMyTableIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTPROCCLIENT_API FPkUuidCols +{ + explicit FPkUuidCols(const char* TableName) + : U(TableName, "u"), Data(TableName, "data") {} + + ::SpacetimeDB::query_builder::Col U; + ::SpacetimeDB::query_builder::Col Data; +}; + +struct TESTPROCCLIENT_API FPkUuidIxCols +{ + explicit FPkUuidIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FPkUuidCols get(const char* table_name) { return FPkUuidCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPkUuidIxCols get(const char* table_name) { return FPkUuidIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTPROCCLIENT_API FProcInsertsIntoCols +{ + explicit FProcInsertsIntoCols(const char* TableName) + : ReducerTs(TableName, "reducer_ts"), ProcedureTs(TableName, "procedure_ts"), X(TableName, "x"), Y(TableName, "y") {} + + ::SpacetimeDB::query_builder::Col ReducerTs; + ::SpacetimeDB::query_builder::Col ProcedureTs; + ::SpacetimeDB::query_builder::Col X; + ::SpacetimeDB::query_builder::Col Y; +}; + +struct TESTPROCCLIENT_API FProcInsertsIntoIxCols +{ + explicit FProcInsertsIntoIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FProcInsertsIntoCols get(const char* table_name) { return FProcInsertsIntoCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FProcInsertsIntoIxCols get(const char* table_name) { return FProcInsertsIntoIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTPROCCLIENT_API FFrom +{ + [[nodiscard]] ::SpacetimeDB::query_builder::Table MyTable() const { return ::SpacetimeDB::query_builder::Table("my_table"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkUuid() const { return ::SpacetimeDB::query_builder::Table("pk_uuid"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ProcInsertsInto() const { return ::SpacetimeDB::query_builder::Table("proc_inserts_into"); } +}; + +struct TESTPROCCLIENT_API FQueryBuilder +{ + FFrom From; + + static TArray AllTablesSqlQueries() + { + TArray Sql; + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.MyTable().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkUuid().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.ProcInsertsInto().into_sql().c_str()))); + return Sql; + } +}; + +struct TESTPROCCLIENT_API FTypedSubscriptionBuilder +{ + explicit FTypedSubscriptionBuilder(UDbConnection* InConn) + : Conn(InConn) {} + + FTypedSubscriptionBuilder& OnApplied(FOnSubscriptionApplied Callback); + FTypedSubscriptionBuilder& OnError(FOnSubscriptionError Callback); + + template + FTypedSubscriptionBuilder& AddQuery(TFn&& Build) + { + FQueryBuilder Q; + auto Query = std::forward(Build)(Q); + static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn, + "Typed subscription queries must return a query_builder table/query expression."); + Sql.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str()))); + return *this; + } + + USubscriptionHandle* Subscribe(); + +private: + UDbConnection* Conn = nullptr; + TArray Sql; + FOnSubscriptionApplied OnAppliedDelegateInternal; + FOnSubscriptionError OnErrorDelegateInternal; +}; + // SubscriptionBuilder class UCLASS(BlueprintType) class TESTPROCCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase @@ -1124,6 +1284,16 @@ class TESTPROCCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase UFUNCTION(BlueprintCallable, Category="SpacetimeDB") USubscriptionHandle* Subscribe(const TArray& SQL); + template + [[nodiscard]] FTypedSubscriptionBuilder AddQuery(TFn&& Build) + { + FTypedSubscriptionBuilder Typed(Conn); + Typed.OnApplied(OnAppliedDelegateInternal); + Typed.OnError(OnErrorDelegateInternal); + Typed.AddQuery(std::forward(Build)); + return Typed; + } + /** Convenience for subscribing to all rows from all tables */ UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") USubscriptionHandle* SubscribeToAllTables(); diff --git a/sdks/unreal/tests/TestViewClient/.vsconfig b/sdks/unreal/tests/TestViewClient/.vsconfig new file mode 100644 index 00000000000..3b919ea7b8f --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/.vsconfig @@ -0,0 +1,17 @@ +{ + "version": "1.0", + "components": [ + "Component.Unreal.Debugger", + "Component.Unreal.Ide", + "Microsoft.Net.Component.4.6.2.TargetingPack", + "Microsoft.VisualStudio.Component.VC.14.38.17.8.ATL", + "Microsoft.VisualStudio.Component.VC.14.38.17.8.x86.x64", + "Microsoft.VisualStudio.Component.VC.Llvm.Clang", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "Microsoft.VisualStudio.Component.Windows11SDK.22621", + "Microsoft.VisualStudio.Workload.CoreEditor", + "Microsoft.VisualStudio.Workload.ManagedDesktop", + "Microsoft.VisualStudio.Workload.NativeDesktop", + "Microsoft.VisualStudio.Workload.NativeGame" + ] +} diff --git a/sdks/unreal/tests/TestViewClient/Config/DefaultEditor.ini b/sdks/unreal/tests/TestViewClient/Config/DefaultEditor.ini new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdks/unreal/tests/TestViewClient/Config/DefaultEditorPerProjectUserSettings.ini b/sdks/unreal/tests/TestViewClient/Config/DefaultEditorPerProjectUserSettings.ini new file mode 100644 index 00000000000..66fac145c2f --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Config/DefaultEditorPerProjectUserSettings.ini @@ -0,0 +1,5 @@ + + +[/Script/TestViewClient.SpacetimeDBSettings] +SpacetimeDbTestName=sdk-test-view + diff --git a/sdks/unreal/tests/TestViewClient/Config/DefaultEngine.ini b/sdks/unreal/tests/TestViewClient/Config/DefaultEngine.ini new file mode 100644 index 00000000000..0239c099c52 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Config/DefaultEngine.ini @@ -0,0 +1,57 @@ +[Zen] +bEnableZen=false +bEnableZenLocal=false + +[/Script/Zen.ZenServiceSettings] +bEnabled=False +bAutoLaunch=False + +[Audio] +UseAudioMixer=True + +[/Script/HardwareTargeting.HardwareTargetingSettings] +TargetedHardwareClass=Desktop +AppliedTargetedHardwareClass=Desktop +DefaultGraphicsPerformance=Maximum +AppliedDefaultGraphicsPerformance=Maximum + +[/Script/WindowsTargetPlatform.WindowsTargetSettings] +DefaultGraphicsRHI=DefaultGraphicsRHI_DX12 +DefaultGraphicsRHI=DefaultGraphicsRHI_DX12 +!D3D12TargetedShaderFormats=ClearArray ++D3D12TargetedShaderFormats=PCD3D_SM6 + +[/Script/Engine.RendererSettings] +r.AllowStaticLighting=0 +r.GenerateMeshDistanceFields=False +r.DynamicGlobalIlluminationMethod=1 +r.ReflectionMethod=1 +r.Shadow.Virtual.Enable=1 +r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True +r.DefaultFeature.LocalExposure.HighlightContrastScale=0.8 +r.DefaultFeature.LocalExposure.ShadowContrastScale=0.8 +r.SkinCache.CompileShaders=True +r.RayTracing.RayTracingProxies.ProjectEnabled=True + +[/Script/WorldPartitionEditor.WorldPartitionEditorSettings] +CommandletClass=Class'/Script/UnrealEd.WorldPartitionConvertCommandlet' + +[/Script/Engine.UserInterfaceSettings] +bAuthorizeAutomaticWidgetVariableCreation=False +FontDPIPreset=Standard +FontDPI=72 + +[/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings] +bEnablePlugin=True +bAllowNetworkConnection=True +SecurityToken=FC2469BA449F3D6AFB81E9A6E6FCBE4B +bIncludeInShipping=False +bAllowExternalStartInShipping=False +bCompileAFSProject=False +bUseCompression=False +bLogFiles=False +bReportStats=False +ConnectionType=USBOnly +bUseManualIPAddress=False +ManualIPAddress= + diff --git a/sdks/unreal/tests/TestViewClient/Config/DefaultGame.ini b/sdks/unreal/tests/TestViewClient/Config/DefaultGame.ini new file mode 100644 index 00000000000..4754b466b8d --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Config/DefaultGame.ini @@ -0,0 +1,5 @@ +[/Script/EngineSettings.GeneralProjectSettings] +ProjectID=9B36AE4A4DF62F180A496F93BE6813D9 + +[/Script/CommonUI.CommonUISettings] +CommonButtonAcceptKeyHandling=TriggerClick diff --git a/sdks/unreal/tests/TestViewClient/Config/DefaultInput.ini b/sdks/unreal/tests/TestViewClient/Config/DefaultInput.ini new file mode 100644 index 00000000000..a72fda22b24 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Config/DefaultInput.ini @@ -0,0 +1,85 @@ +[/Script/Engine.InputSettings] +-AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) +-AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) +-AxisConfig=(AxisKeyName="Mouse2D",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) ++AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Mouse2D",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MouseWheelAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_LeftTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_RightTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_Special_Left_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_Special_Left_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) +bAltEnterTogglesFullscreen=True +bF11TogglesFullscreen=True +bUseMouseForTouch=False +bEnableMouseSmoothing=True +bEnableFOVScaling=True +bCaptureMouseOnLaunch=True +bEnableLegacyInputScales=True +bEnableMotionControls=True +bFilterInputByPlatformUser=False +bShouldFlushPressedKeysOnViewportFocusLost=True +bEnableDynamicComponentInputBinding=True +bAlwaysShowTouchInterface=False +bShowConsoleOnFourFingerTap=True +bEnableGestureRecognizer=False +bUseAutocorrect=False +DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown +DefaultViewportMouseLockMode=LockOnCapture +FOVScale=0.011110 +DoubleClickTime=0.200000 +DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput +DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent +DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.DefaultVirtualJoysticks +-ConsoleKeys=Tilde ++ConsoleKeys=Tilde + diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient.Target.cs b/sdks/unreal/tests/TestViewClient/Source/TestViewClient.Target.cs new file mode 100644 index 00000000000..cbc530e7e6f --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient.Target.cs @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class TestViewClientTarget : TargetRules +{ + public TestViewClientTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Game; + DefaultBuildSettings = BuildSettingsVersion.V5; + + ExtraModuleNames.AddRange( new string[] { "TestViewClient" } ); + } +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp new file mode 100644 index 00000000000..163a1eb56cf --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -0,0 +1,584 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/SpacetimeDBClient.g.h" +#include "DBCache/WithBsatn.h" +#include "BSATN/UEBSATNHelpers.h" +#include "ModuleBindings/Tables/MyPlayerTable.g.h" +#include "ModuleBindings/Tables/MyPlayerAndLevelTable.g.h" +#include "ModuleBindings/Tables/NearbyPlayersTable.g.h" +#include "ModuleBindings/Tables/PlayerTable.g.h" +#include "ModuleBindings/Tables/PlayerLevelTable.g.h" +#include "ModuleBindings/Tables/PlayersAtLevel0Table.g.h" + +UDbConnection::UDbConnection(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) +{ + Db = ObjectInitializer.CreateDefaultSubobject(this, TEXT("RemoteTables")); + Db->Initialize(); + + Reducers = ObjectInitializer.CreateDefaultSubobject(this, TEXT("RemoteReducers")); + Reducers->Conn = this; + + Procedures = ObjectInitializer.CreateDefaultSubobject(this, TEXT("RemoteProcedures")); + Procedures->Conn = this; + + RegisterTable(TEXT("my_player"), Db->MyPlayer); + RegisterTable(TEXT("my_player_and_level"), Db->MyPlayerAndLevel); + RegisterTable(TEXT("nearby_players"), Db->NearbyPlayers); + RegisterTable(TEXT("player"), Db->Player); + RegisterTable(TEXT("player_level"), Db->PlayerLevel); + RegisterTable(TEXT("players_at_level_0"), Db->PlayersAtLevel0); +} + +FContextBase::FContextBase(UDbConnection* InConn) +{ + Db = InConn->Db; + Reducers = InConn->Reducers; + Procedures = InConn->Procedures; + Conn = InConn; +} +bool FContextBase::IsActive() const +{ + return Conn->IsActive(); +} +void FContextBase::Disconnect() +{ + Conn->Disconnect(); +} +USubscriptionBuilder* FContextBase::SubscriptionBuilder() +{ + return Conn->SubscriptionBuilder(); +} +bool FContextBase::TryGetIdentity(FSpacetimeDBIdentity& OutIdentity) const +{ + return Conn->TryGetIdentity(OutIdentity); +} +FSpacetimeDBConnectionId FContextBase::GetConnectionId() const +{ + return Conn->GetConnectionId(); +} + +void URemoteTables::Initialize() +{ + + /** Creating tables */ + MyPlayer = NewObject(this); + MyPlayerAndLevel = NewObject(this); + NearbyPlayers = NewObject(this); + Player = NewObject(this); + PlayerLevel = NewObject(this); + PlayersAtLevel0 = NewObject(this); + /**/ + + /** Initialization */ + MyPlayer->PostInitialize(); + MyPlayerAndLevel->PostInitialize(); + NearbyPlayers->PostInitialize(); + Player->PostInitialize(); + PlayerLevel->PostInitialize(); + PlayersAtLevel0->PostInitialize(); + /**/ +} + +void URemoteReducers::DeletePlayer(const FSpacetimeDBIdentity& Identity) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + FDeletePlayerArgs ReducerArgs(Identity); + const uint32 RequestId = Conn->CallReducerTyped(TEXT("delete_player"), ReducerArgs); + if (RequestId != 0) { Conn->RegisterPendingTypedReducer(RequestId, FReducer::DeletePlayer(ReducerArgs)); } +} + +bool URemoteReducers::InvokeDeletePlayer(const FReducerEventContext& Context, const UDeletePlayerReducer* Args) +{ + if (!OnDeletePlayer.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for DeletePlayer")); + } + return false; + } + + OnDeletePlayer.Broadcast(Context, Args->Identity); + return true; +} + +bool URemoteReducers::InvokeDeletePlayerWithArgs(const FReducerEventContext& Context, const FDeletePlayerArgs& Args) +{ + if (!OnDeletePlayer.IsBound()) + { + if (InternalOnUnhandledReducerError.IsBound()) + { + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for DeletePlayer")); + } + return false; + } + + OnDeletePlayer.Broadcast(Context, Args.Identity); + return true; +} + +void URemoteReducers::InsertPlayer(const FSpacetimeDBIdentity& Identity, const uint64 Level) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + FInsertPlayerArgs ReducerArgs(Identity, Level); + const uint32 RequestId = Conn->CallReducerTyped(TEXT("insert_player"), ReducerArgs); + if (RequestId != 0) { Conn->RegisterPendingTypedReducer(RequestId, FReducer::InsertPlayer(ReducerArgs)); } +} + +bool URemoteReducers::InvokeInsertPlayer(const FReducerEventContext& Context, const UInsertPlayerReducer* Args) +{ + if (!OnInsertPlayer.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertPlayer")); + } + return false; + } + + OnInsertPlayer.Broadcast(Context, Args->Identity, Args->Level); + return true; +} + +bool URemoteReducers::InvokeInsertPlayerWithArgs(const FReducerEventContext& Context, const FInsertPlayerArgs& Args) +{ + if (!OnInsertPlayer.IsBound()) + { + if (InternalOnUnhandledReducerError.IsBound()) + { + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertPlayer")); + } + return false; + } + + OnInsertPlayer.Broadcast(Context, Args.Identity, Args.Level); + return true; +} + +void URemoteReducers::MovePlayer(const int32 Dx, const int32 Dy) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + FMovePlayerArgs ReducerArgs(Dx, Dy); + const uint32 RequestId = Conn->CallReducerTyped(TEXT("move_player"), ReducerArgs); + if (RequestId != 0) { Conn->RegisterPendingTypedReducer(RequestId, FReducer::MovePlayer(ReducerArgs)); } +} + +bool URemoteReducers::InvokeMovePlayer(const FReducerEventContext& Context, const UMovePlayerReducer* Args) +{ + if (!OnMovePlayer.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for MovePlayer")); + } + return false; + } + + OnMovePlayer.Broadcast(Context, Args->Dx, Args->Dy); + return true; +} + +bool URemoteReducers::InvokeMovePlayerWithArgs(const FReducerEventContext& Context, const FMovePlayerArgs& Args) +{ + if (!OnMovePlayer.IsBound()) + { + if (InternalOnUnhandledReducerError.IsBound()) + { + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for MovePlayer")); + } + return false; + } + + OnMovePlayer.Broadcast(Context, Args.Dx, Args.Dy); + return true; +} + +void UDbConnection::PostInitProperties() +{ + Super::PostInitProperties(); + + // Connect OnUnhandledReducerError to Reducers.InternalOnUnhandledReducerError + if (Reducers) + { + Reducers->InternalOnUnhandledReducerError.AddDynamic(this, &UDbConnection::OnUnhandledReducerErrorHandler); + } + + // Connect OnUnhandledProcedureError to Procedures.InternalOnUnhandledProcedureError + if (Procedures) + { + Procedures->InternalOnUnhandledProcedureError.AddDynamic(this, &UDbConnection::OnUnhandledProcedureErrorHandler); + } +} + +UFUNCTION() +void UDbConnection::OnUnhandledReducerErrorHandler(const FReducerEventContext& Context, const FString& Error) +{ + if (OnUnhandledReducerError.IsBound()) + { + OnUnhandledReducerError.Broadcast(Context, Error); + } +} + +UFUNCTION() +void UDbConnection::OnUnhandledProcedureErrorHandler(const FProcedureEventContext& Context, const FString& Error) +{ + if (OnUnhandledProcedureError.IsBound()) + { + OnUnhandledProcedureError.Broadcast(Context, Error); + } +} + +void UDbConnection::RegisterPendingTypedReducer(uint32 RequestId, FReducer Reducer) +{ + Reducer.RequestId = RequestId; + PendingTypedReducers.Add(RequestId, MoveTemp(Reducer)); +} + +bool UDbConnection::TryGetPendingTypedReducer(uint32 RequestId, FReducer& OutReducer) const +{ + if (const FReducer* Found = PendingTypedReducers.Find(RequestId)) + { + OutReducer = *Found; + return true; + } + return false; +} + +bool UDbConnection::TryTakePendingTypedReducer(uint32 RequestId, FReducer& OutReducer) +{ + if (FReducer* Found = PendingTypedReducers.Find(RequestId)) + { + OutReducer = *Found; + PendingTypedReducers.Remove(RequestId); + return true; + } + return false; +} + +void UDbConnection::ReducerEvent(const FReducerEvent& Event) +{ + if (!Reducers) { return; } + + FReducer DecodedReducer; + if (!TryTakePendingTypedReducer(Event.RequestId, DecodedReducer)) + { + const FString ErrorMessage = FString::Printf(TEXT("Reducer result for unknown request_id %u"), Event.RequestId); + HandleProtocolViolation(ErrorMessage); + return; + } + + FTestViewClientReducerEvent ReducerEvent; + ReducerEvent.CallerConnectionId = Event.CallerConnectionId; + ReducerEvent.CallerIdentity = Event.CallerIdentity; + ReducerEvent.EnergyConsumed = Event.EnergyConsumed; + ReducerEvent.Status = Event.Status; + ReducerEvent.Timestamp = Event.Timestamp; + ReducerEvent.Reducer = DecodedReducer; + + FReducerEventContext Context(this, ReducerEvent); + + // Dispatch by typed reducer metadata + const FString& ReducerName = ReducerEvent.Reducer.ReducerName; + + if (ReducerName == TEXT("delete_player")) + { + FDeletePlayerArgs Args = ReducerEvent.Reducer.GetAsDeletePlayer(); + Reducers->InvokeDeletePlayerWithArgs(Context, Args); + return; + } + if (ReducerName == TEXT("insert_player")) + { + FInsertPlayerArgs Args = ReducerEvent.Reducer.GetAsInsertPlayer(); + Reducers->InvokeInsertPlayerWithArgs(Context, Args); + return; + } + if (ReducerName == TEXT("move_player")) + { + FMovePlayerArgs Args = ReducerEvent.Reducer.GetAsMovePlayer(); + Reducers->InvokeMovePlayerWithArgs(Context, Args); + return; + } + + UE_LOG(LogTemp, Warning, TEXT("Unknown reducer: %s"), *ReducerName); +} + +void UDbConnection::ReducerEventFailed(const FReducerEvent& Event, const FString ErrorMessage) +{ + if (!Reducers) { return; } + + FTestViewClientReducerEvent ReducerEvent; + ReducerEvent.CallerConnectionId = Event.CallerConnectionId; + ReducerEvent.CallerIdentity = Event.CallerIdentity; + ReducerEvent.EnergyConsumed = Event.EnergyConsumed; + ReducerEvent.Status = Event.Status; + ReducerEvent.Timestamp = Event.Timestamp; + + FReducerEventContext Context(this, ReducerEvent); + + if (Reducers->InternalOnUnhandledReducerError.IsBound()) + { + Reducers->InternalOnUnhandledReducerError.Broadcast(Context, ErrorMessage); + } +} + +void UDbConnection::ProcedureEventFailed(const FProcedureEvent& Event, const FString ErrorMessage) +{ + if (!Procedures) { return; } + + FTestViewClientProcedureEvent ProcedureEvent; + ProcedureEvent.Status = FSpacetimeDBProcedureStatus::FromStatus(Event.Status); + ProcedureEvent.Timestamp = Event.Timestamp; + + FProcedureEventContext Context(this, ProcedureEvent); + + if (Procedures->InternalOnUnhandledProcedureError.IsBound()) + { + Procedures->InternalOnUnhandledProcedureError.Broadcast(Context, ErrorMessage); + } +} + +UDbConnectionBuilder* UDbConnection::Builder() +{ + return NewObject(); +} +// Added for creating subscriptions +USubscriptionBuilder* UDbConnection::SubscriptionBuilder() +{ + USubscriptionBuilder* Builder = NewObject(this); + Builder->Conn = this; + return Builder; +} +FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) +{ + OnAppliedDelegateInternal = Callback; + return *this; +} +FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnError(FOnSubscriptionError Callback) +{ + OnErrorDelegateInternal = Callback; + return *this; +} +USubscriptionHandle* FTypedSubscriptionBuilder::Subscribe() +{ + if (!Conn) + { + return nullptr; + } + USubscriptionBuilder* Builder = Conn->SubscriptionBuilder(); + Builder->OnApplied(OnAppliedDelegateInternal); + Builder->OnError(OnErrorDelegateInternal); + return Builder->Subscribe(Sql); +} +USubscriptionBuilder* USubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) +{ + OnAppliedDelegateInternal = Callback; + return this; +} +USubscriptionBuilder* USubscriptionBuilder::OnError(FOnSubscriptionError Callback) +{ + OnErrorDelegateInternal = Callback; + return this; +} +USubscriptionHandle* USubscriptionBuilder::Subscribe(const TArray& SQL) +{ + USubscriptionHandle* Handle = NewObject(); + + // Store user callbacks on the handle + Handle->Conn = Conn; + Handle->OnAppliedDelegate = OnAppliedDelegateInternal; + Handle->OnErrorDelegate = OnErrorDelegateInternal; + + // Bind forwarding functions that will convert base contexts + FSubscriptionEventDelegate BaseApplied; + BaseApplied.BindUFunction(Handle, TEXT("ForwardOnApplied")); + OnAppliedBase(BaseApplied); + + FSubscriptionErrorDelegate BaseError; + BaseError.BindUFunction(Handle, TEXT("ForwardOnError")); + OnErrorBase(BaseError); + + SubscribeBase(SQL, Handle); + if (Conn) + { + Conn->StartSubscription(Handle); + } + return Handle; +} +USubscriptionHandle* USubscriptionBuilder::SubscribeToAllTables() +{ + return Subscribe(FQueryBuilder::AllTablesSqlQueries()); +} + +USubscriptionHandle::USubscriptionHandle(UDbConnection* InConn) +{ + Conn = InConn; +} + +void USubscriptionHandle::ForwardOnApplied(const FSubscriptionEventContextBase& BaseCtx) +{ + if (OnAppliedDelegate.IsBound()) + { + FSubscriptionEventContext Ctx(Conn); + OnAppliedDelegate.Execute(Ctx); + } +} + +void USubscriptionHandle::ForwardOnError(const FErrorContextBase& BaseCtx) +{ + if (OnErrorDelegate.IsBound()) + { + FErrorContext Ctx(Conn, BaseCtx.Error); + OnErrorDelegate.Execute(Ctx); + } +} + + +// Cast from parent to child class +UDbConnectionBuilder* UDbConnectionBuilder::WithUri(const FString& InUri) +{ + return Cast(WithUriBase(InUri)); +} +UDbConnectionBuilder* UDbConnectionBuilder::WithDatabaseName(const FString& InName) +{ + return Cast(WithDatabaseNameBase(InName)); +} +UDbConnectionBuilder* UDbConnectionBuilder::WithToken(const FString& InToken) +{ + return Cast(WithTokenBase(InToken)); +} +UDbConnectionBuilder* UDbConnectionBuilder::WithCompression(const ESpacetimeDBCompression& InCompression) +{ + return Cast(WithCompressionBase(InCompression)); +} +UDbConnectionBuilder* UDbConnectionBuilder::OnConnect(FOnConnectDelegate Callback) +{ + OnConnectDelegateInternal = Callback; + return this; +} +UDbConnectionBuilder* UDbConnectionBuilder::OnConnectError(FOnConnectErrorDelegate Callback) +{ + return Cast(OnConnectErrorBase(Callback)); +} +UDbConnectionBuilder* UDbConnectionBuilder::OnDisconnect(FOnDisconnectDelegate Callback) +{ + OnDisconnectDelegateInternal = Callback; + return this; +} +UDbConnection* UDbConnectionBuilder::Build() +{ + UDbConnection* Connection = NewObject(); + + // Store delegates on the connection for later use + Connection->OnConnectDelegate = OnConnectDelegateInternal; + Connection->OnDisconnectDelegate = OnDisconnectDelegateInternal; + + // Wrap delegates so the base builder can bind them + FOnConnectBaseDelegate BaseConnect; + BaseConnect.BindUFunction(Connection, TEXT("ForwardOnConnect")); + Connection->SetOnConnectDelegate(BaseConnect); + OnConnectBase(BaseConnect); + + FOnDisconnectBaseDelegate BaseDisconnect; + BaseDisconnect.BindUFunction(Connection, TEXT("ForwardOnDisconnect")); + Connection->SetOnDisconnectDelegate(BaseDisconnect); + OnDisconnectBase(BaseDisconnect); + + return Cast(BuildConnection(Connection)); +} +void UDbConnection::ForwardOnConnect(UDbConnectionBase* BaseConnection, FSpacetimeDBIdentity InIdentity, const FString& InToken) +{ + if (OnConnectDelegate.IsBound()) + { + OnConnectDelegate.Execute(this, Identity, Token); + } +} +void UDbConnection::ForwardOnDisconnect(UDbConnectionBase* BaseConnection, const FString& Error) +{ + PendingTypedReducers.Empty(); + if (OnDisconnectDelegate.IsBound()) + { + OnDisconnectDelegate.Execute(this, Error); + } +} + + +void UDbConnection::DbUpdate(const FDatabaseUpdateType& Update, const FSpacetimeDBEvent& Event) +{ + FTestViewClientEvent BaseEvent; + BaseEvent.Tag = Event.Tag; + + switch (Event.Tag) + { + case ESpacetimeDBEventTag::Reducer: + { + FReducerEvent ReducerEvent = Event.GetAsReducer(); + FReducer Reducer; + if (!TryGetPendingTypedReducer(ReducerEvent.RequestId, Reducer)) + { + const FString ErrorMessage = FString::Printf(TEXT("Reducer result for unknown request_id %u"), ReducerEvent.RequestId); + HandleProtocolViolation(ErrorMessage); + return; + } + BaseEvent = FTestViewClientEvent::Reducer(Reducer); + break; + } + + case ESpacetimeDBEventTag::SubscribeApplied: + BaseEvent = FTestViewClientEvent::SubscribeApplied(Event.GetAsSubscribeApplied()); + break; + + case ESpacetimeDBEventTag::UnsubscribeApplied: + BaseEvent = FTestViewClientEvent::UnsubscribeApplied(Event.GetAsUnsubscribeApplied()); + break; + + case ESpacetimeDBEventTag::Disconnected: + BaseEvent = FTestViewClientEvent::Disconnected(Event.GetAsDisconnected()); + break; + + case ESpacetimeDBEventTag::Transaction: + BaseEvent = FTestViewClientEvent::Transaction(Event.GetAsTransaction()); + break; + + case ESpacetimeDBEventTag::SubscribeError: + BaseEvent = FTestViewClientEvent::SubscribeError(Event.GetAsSubscribeError()); + break; + + case ESpacetimeDBEventTag::UnknownTransaction: + BaseEvent = FTestViewClientEvent::UnknownTransaction(Event.GetAsUnknownTransaction()); + break; + + default: + break; + } + + FEventContext Context(this, BaseEvent); + // Populate typed reducer args for convenience in table handlers + + ApplyRegisteredTableUpdates(Update, &Context); +} + diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/MyPlayerAndLevelTable.g.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/MyPlayerAndLevelTable.g.cpp new file mode 100644 index 00000000000..a030f0d5c00 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/MyPlayerAndLevelTable.g.cpp @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/MyPlayerAndLevelTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UMyPlayerAndLevelTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> MyPlayerAndLevelTable = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff UMyPlayerAndLevelTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + return Diff; +} + +int32 UMyPlayerAndLevelTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UMyPlayerAndLevelTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/MyPlayerTable.g.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/MyPlayerTable.g.cpp new file mode 100644 index 00000000000..3db5534fdef --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/MyPlayerTable.g.cpp @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/MyPlayerTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UMyPlayerTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> MyPlayerTable = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff UMyPlayerTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + return Diff; +} + +int32 UMyPlayerTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UMyPlayerTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/NearbyPlayersTable.g.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/NearbyPlayersTable.g.cpp new file mode 100644 index 00000000000..68afbc2769e --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/NearbyPlayersTable.g.cpp @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/NearbyPlayersTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UNearbyPlayersTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> NearbyPlayersTable = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff UNearbyPlayersTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + return Diff; +} + +int32 UNearbyPlayersTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UNearbyPlayersTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/PlayerLevelTable.g.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/PlayerLevelTable.g.cpp new file mode 100644 index 00000000000..21c6e688eb0 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/PlayerLevelTable.g.cpp @@ -0,0 +1,53 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/PlayerLevelTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UPlayerLevelTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> PlayerLevelTable = Data->GetOrAdd(TableName); + PlayerLevelTable->AddUniqueConstraint("entity_id", [](const FPlayerLevelType& Row) -> const uint64& { + return Row.EntityId; }); + + EntityId = NewObject(this); + EntityId->SetCache(PlayerLevelTable); + + // Register a new multi-key B-Tree index named "level" on the PlayerLevelTable. + PlayerLevelTable->AddMultiKeyBTreeIndex>( + TEXT("level"), + [](const FPlayerLevelType& Row) + { + // This tuple is stored in the B-Tree index for fast composite key lookups. + return MakeTuple(Row.Level); + } + ); + + Level = NewObject(this); + Level->SetCache(PlayerLevelTable); + + /***/ +} + +FTableAppliedDiff UPlayerLevelTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + return Diff; +} + +int32 UPlayerLevelTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UPlayerLevelTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/PlayerTable.g.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/PlayerTable.g.cpp new file mode 100644 index 00000000000..87379a7a009 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/PlayerTable.g.cpp @@ -0,0 +1,52 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/PlayerTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UPlayerTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> PlayerTable = Data->GetOrAdd(TableName); + PlayerTable->AddUniqueConstraint("entity_id", [](const FPlayerType& Row) -> const uint64& { + return Row.EntityId; }); + PlayerTable->AddUniqueConstraint("identity", [](const FPlayerType& Row) -> const FSpacetimeDBIdentity& { + return Row.Identity; }); + + EntityId = NewObject(this); + EntityId->SetCache(PlayerTable); + + Identity = NewObject(this); + Identity->SetCache(PlayerTable); + + /***/ +} + +FTableAppliedDiff UPlayerTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FPlayerType& Row) + { + return Row.EntityId; + } + ); + + return Diff; +} + +int32 UPlayerTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UPlayerTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/PlayersAtLevel0Table.g.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/PlayersAtLevel0Table.g.cpp new file mode 100644 index 00000000000..53d02318a6b --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/Tables/PlayersAtLevel0Table.g.cpp @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/PlayersAtLevel0Table.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UPlayersAtLevel0Table::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> PlayersAtLevel0Table = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff UPlayersAtLevel0Table::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + return Diff; +} + +int32 UPlayersAtLevel0Table::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UPlayersAtLevel0Table::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/CommonTestFunctions.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/CommonTestFunctions.cpp new file mode 100644 index 00000000000..6244eb3e90d --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/CommonTestFunctions.cpp @@ -0,0 +1 @@ +#include "Tests/CommonTestFunctions.h" diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/SpacetimeFullClientTests.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/SpacetimeFullClientTests.cpp new file mode 100644 index 00000000000..2b91569c029 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/SpacetimeFullClientTests.cpp @@ -0,0 +1,65 @@ +#include "Tests/SpacetimeFullClientTests.h" + +#include "ModuleBindings/SpacetimeDBClient.g.h" + +namespace +{ +static FString ToFString(const std::string& InSql) +{ + return FString(UTF8_TO_TCHAR(InSql.c_str())); +} +} + +bool FViewQueryBuilderDirectSourcesTest::RunTest(const FString& Parameters) +{ + FQueryBuilder Q; + + const FString MyPlayerSql = ToFString(Q.From.MyPlayer().into_sql()); + const FString MyPlayerAndLevelSql = ToFString(Q.From.MyPlayerAndLevel().into_sql()); + const FString PlayersAtLevel0Sql = ToFString(Q.From.PlayersAtLevel0().into_sql()); + const FString NearbyPlayersFilteredSql = ToFString( + Q.From.NearbyPlayers().Where([](const FPlayerLocationCols& Cols) + { + return Cols.Active.Eq(true); + }).into_sql() + ); + + TestEqual(TEXT("my_player sql"), MyPlayerSql, TEXT("SELECT * FROM \"my_player\"")); + TestEqual(TEXT("my_player_and_level sql"), MyPlayerAndLevelSql, TEXT("SELECT * FROM \"my_player_and_level\"")); + TestEqual(TEXT("players_at_level_0 sql"), PlayersAtLevel0Sql, TEXT("SELECT * FROM \"players_at_level_0\"")); + TestEqual( + TEXT("nearby_players filtered sql"), + NearbyPlayersFilteredSql, + TEXT("SELECT * FROM \"nearby_players\" WHERE (\"nearby_players\".\"active\" = TRUE)") + ); + + FTypedSubscriptionBuilder Typed(nullptr); + Typed.AddQuery([](const FQueryBuilder& Query) + { + return Query.From.MyPlayer(); + }).AddQuery([](const FQueryBuilder& Query) + { + return Query.From.PlayersAtLevel0().Where([](const FPlayerCols& Cols) + { + return Cols.EntityId.Eq(static_cast(7)); + }); + }); + + TestTrue(TEXT("typed query builder accepted view sources"), true); + return true; +} + +bool FViewSubscribeAllTablesTest::RunTest(const FString& Parameters) +{ + const TArray Sql = FQueryBuilder::AllTablesSqlQueries(); + + TestEqual(TEXT("all tables count"), Sql.Num(), 6); + TestTrue(TEXT("all tables include player"), Sql.Contains(TEXT("SELECT * FROM \"player\""))); + TestTrue(TEXT("all tables include player_level"), Sql.Contains(TEXT("SELECT * FROM \"player_level\""))); + TestTrue(TEXT("all tables include my_player"), Sql.Contains(TEXT("SELECT * FROM \"my_player\""))); + TestTrue(TEXT("all tables include my_player_and_level"), Sql.Contains(TEXT("SELECT * FROM \"my_player_and_level\""))); + TestTrue(TEXT("all tables include nearby_players"), Sql.Contains(TEXT("SELECT * FROM \"nearby_players\""))); + TestTrue(TEXT("all tables include players_at_level_0"), Sql.Contains(TEXT("SELECT * FROM \"players_at_level_0\""))); + + return true; +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/TestCounter.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/TestCounter.cpp new file mode 100644 index 00000000000..332e61064b2 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/TestCounter.cpp @@ -0,0 +1,87 @@ +#include "Tests/TestCounter.h" + +void FTestCounter::Register(const FString& TestName) +{ + FScopeLock Lock(&Mutex); + if (Registered.Contains(TestName)) + { + UE_LOG(LogTemp, Error, TEXT("Duplicate test name: %s"), *TestName); + } + Registered.Add(TestName); +} + +void FTestCounter::MarkSuccess(const FString& TestName) +{ + FScopeLock Lock(&Mutex); + Outcomes.Add(TestName, { true, FString() }); + UE_LOG(LogTemp, Log, TEXT("Operation success: %s"), *TestName); +} + +void FTestCounter::MarkFailure(const FString& TestName, const FString& Error) +{ + FScopeLock Lock(&Mutex); + Outcomes.Add(TestName, { false, Error }); + UE_LOG(LogTemp, Error, TEXT("Operation failed: %s, %s"), *TestName, *Error); +} + +bool FTestCounter::IsComplete() const +{ + FScopeLock Lock(&Mutex); + return Outcomes.Num() == Registered.Num(); +} + +bool FTestCounter::AllSucceeded() const +{ + FScopeLock Lock(&Mutex); + if (Outcomes.Num() != Registered.Num()) + { + return false; + } + for (const auto& Elem : Outcomes) + { + if (!Elem.Value.bSuccess) + { + return false; + } + } + return true; +} + +TArray FTestCounter::GetFailures() const +{ + FScopeLock Lock(&Mutex); + TArray Failures; + for (const FString& Name : Registered) + { + const FTestOutcome* Outcome = Outcomes.Find(Name); + if (!Outcome) + { + Failures.Add(FString::Printf(TEXT("TIMEOUT: %s"), *Name)); + } + else if (!Outcome->bSuccess) + { + Failures.Add(FString::Printf(TEXT("FAILED: %s: %s"), *Name, *Outcome->Error)); + } + } + return Failures; +} + +TArray FTestCounter::GetSuccesses() const +{ + FScopeLock Lock(&Mutex); + TArray Successes; + for (const FString& Name : Registered) + { + const FTestOutcome* Outcome = Outcomes.Find(Name); + if (Outcome && Outcome->bSuccess) + { + Successes.Add(FString::Printf(TEXT("SUCCESS: %s"), *Name)); + } + } + return Successes; +} + +void FTestCounter::Abort() +{ + bAborted = true; +} \ No newline at end of file diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/TestHandler.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/TestHandler.cpp new file mode 100644 index 00000000000..93b59cedf91 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/TestHandler.cpp @@ -0,0 +1 @@ +#include "Tests/TestHandler.h" diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/ReducerBase.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/ReducerBase.g.h new file mode 100644 index 00000000000..52b29de10e6 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/ReducerBase.g.h @@ -0,0 +1,18 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ReducerBase.g.generated.h" + +// Abstract Reducer base class +UCLASS(Abstract, BlueprintType) +class TESTVIEWCLIENT_API UReducerBase : public UObject +{ + GENERATED_BODY() + +public: + virtual ~UReducerBase() = default; +}; + diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Reducers/DeletePlayer.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Reducers/DeletePlayer.g.h new file mode 100644 index 00000000000..3733a35c41d --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Reducers/DeletePlayer.g.h @@ -0,0 +1,54 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "Types/Builtins.h" +#include "DeletePlayer.g.generated.h" + +// Reducer arguments struct for DeletePlayer +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FDeletePlayerArgs +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBIdentity Identity; + + FDeletePlayerArgs() = default; + + FDeletePlayerArgs(const FSpacetimeDBIdentity& InIdentity) + : Identity(InIdentity) + {} + + + FORCEINLINE bool operator==(const FDeletePlayerArgs& Other) const + { + return Identity == Other.Identity; + } + FORCEINLINE bool operator!=(const FDeletePlayerArgs& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FDeletePlayerArgs, Identity); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API UDeletePlayerReducer : public UReducerBase +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FSpacetimeDBIdentity Identity; + +}; + + diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Reducers/InsertPlayer.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Reducers/InsertPlayer.g.h new file mode 100644 index 00000000000..c3d0f454fc6 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Reducers/InsertPlayer.g.h @@ -0,0 +1,59 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "Types/Builtins.h" +#include "InsertPlayer.g.generated.h" + +// Reducer arguments struct for InsertPlayer +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FInsertPlayerArgs +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBIdentity Identity; + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Level = 0; + + FInsertPlayerArgs() = default; + + FInsertPlayerArgs(const FSpacetimeDBIdentity& InIdentity, const uint64& InLevel) + : Identity(InIdentity), Level(InLevel) + {} + + + FORCEINLINE bool operator==(const FInsertPlayerArgs& Other) const + { + return Identity == Other.Identity && Level == Other.Level; + } + FORCEINLINE bool operator!=(const FInsertPlayerArgs& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FInsertPlayerArgs, Identity, Level); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API UInsertPlayerReducer : public UReducerBase +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FSpacetimeDBIdentity Identity; + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Level = 0; + +}; + + diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Reducers/MovePlayer.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Reducers/MovePlayer.g.h new file mode 100644 index 00000000000..bf6197a9566 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Reducers/MovePlayer.g.h @@ -0,0 +1,58 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "MovePlayer.g.generated.h" + +// Reducer arguments struct for MovePlayer +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FMovePlayerArgs +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") + int32 Dx = 0; + + UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") + int32 Dy = 0; + + FMovePlayerArgs() = default; + + FMovePlayerArgs(const int32& InDx, const int32& InDy) + : Dx(InDx), Dy(InDy) + {} + + + FORCEINLINE bool operator==(const FMovePlayerArgs& Other) const + { + return Dx == Other.Dx && Dy == Other.Dy; + } + FORCEINLINE bool operator!=(const FMovePlayerArgs& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FMovePlayerArgs, Dx, Dy); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API UMovePlayerReducer : public UReducerBase +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + int32 Dx = 0; + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + int32 Dy = 0; + +}; + + diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/SpacetimeDBClient.g.h new file mode 100644 index 00000000000..66679a9cd6a --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -0,0 +1,1153 @@ +// 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 2.0.5 (commit 047dac974526f5c5aff873026e90177270b10f38). + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Connection/Callback.h" +#include "Connection/DbConnectionBase.h" +#include "Connection/DbConnectionBuilder.h" +#include "Connection/Subscription.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "ModuleBindings/Reducers/DeletePlayer.g.h" +#include "ModuleBindings/Reducers/InsertPlayer.g.h" +#include "ModuleBindings/Reducers/MovePlayer.g.h" +#include "ModuleBindings/Types/PlayerAndLevelType.g.h" +#include "ModuleBindings/Types/PlayerLevelType.g.h" +#include "ModuleBindings/Types/PlayerLocationType.g.h" +#include "ModuleBindings/Types/PlayerType.g.h" +#include "QueryBuilder/query_builder.h" +#include "Types/Builtins.h" +#include "SpacetimeDBClient.g.generated.h" + +// Forward declarations +class UDbConnection; +class URemoteTables; +class URemoteReducers; +class URemoteProcedures; +class USubscriptionBuilder; +class USubscriptionHandle; + +/** Forward declaration for tables */ +class UMyPlayerTable; +class UMyPlayerAndLevelTable; +class UNearbyPlayersTable; +class UPlayerTable; +class UPlayerLevelTable; +class UPlayersAtLevel0Table; +/***/ + +// Delegates using the generated connection type. These wrap the base +// delegates defined in the SDK so that projects can work directly with +// UDbConnection without manual casting in user code. +DECLARE_DYNAMIC_DELEGATE_ThreeParams( + FOnConnectDelegate, + UDbConnection*, Connection, + FSpacetimeDBIdentity, Identity, + const FString&, Token); + +DECLARE_DYNAMIC_DELEGATE_TwoParams( + FOnDisconnectDelegate, + UDbConnection*, Connection, + const FString&, Error); + + +// Context classes for event handling + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FContextBase +{ + GENERATED_BODY() + + FContextBase() : Db(nullptr), Reducers(nullptr), Procedures(nullptr), Conn(nullptr) {}; + FContextBase(UDbConnection* InConn); + + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + URemoteTables* Db; + + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + URemoteReducers* Reducers; + + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + URemoteProcedures* Procedures; + + bool IsActive() const; + void Disconnect(); + bool TryGetIdentity(FSpacetimeDBIdentity& OutIdentity) const; + FSpacetimeDBConnectionId GetConnectionId() const; + USubscriptionBuilder* SubscriptionBuilder(); + +protected: + UPROPERTY() + UDbConnection* Conn; + +}; + +UCLASS() +class TESTVIEWCLIENT_API UContextBaseBpLib : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +private: + UFUNCTION(BlueprintPure, Category="SpacetimeDB") + static URemoteTables* GetDb(const FContextBase& Ctx) { return Ctx.Db; } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB") + static URemoteReducers* GetReducers(const FContextBase& Ctx) { return Ctx.Reducers; } + + static URemoteProcedures* GetProcedures(const FContextBase& Ctx) { return Ctx.Procedures; } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB") + static bool IsActive(const FContextBase& Ctx) { return Ctx.IsActive(); } +}; + +UENUM(BlueprintType, Category = "SpacetimeDB") +enum class EReducerTag : uint8 +{ + DeletePlayer, + InsertPlayer, + MovePlayer +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FReducer +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + EReducerTag Tag = static_cast(0); + + TVariant Data; + + // Optional metadata + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + FString ReducerName; + uint32 ReducerId = 0; + uint32 RequestId = 0; + + static FReducer DeletePlayer(const FDeletePlayerArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::DeletePlayer; + Out.Data.Set(Value); + Out.ReducerName = TEXT("delete_player"); + return Out; + } + + FORCEINLINE bool IsDeletePlayer() const { return Tag == EReducerTag::DeletePlayer; } + FORCEINLINE FDeletePlayerArgs GetAsDeletePlayer() const + { + ensureMsgf(IsDeletePlayer(), TEXT("Reducer does not hold DeletePlayer!")); + return Data.Get(); + } + + static FReducer InsertPlayer(const FInsertPlayerArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::InsertPlayer; + Out.Data.Set(Value); + Out.ReducerName = TEXT("insert_player"); + return Out; + } + + FORCEINLINE bool IsInsertPlayer() const { return Tag == EReducerTag::InsertPlayer; } + FORCEINLINE FInsertPlayerArgs GetAsInsertPlayer() const + { + ensureMsgf(IsInsertPlayer(), TEXT("Reducer does not hold InsertPlayer!")); + return Data.Get(); + } + + static FReducer MovePlayer(const FMovePlayerArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::MovePlayer; + Out.Data.Set(Value); + Out.ReducerName = TEXT("move_player"); + return Out; + } + + FORCEINLINE bool IsMovePlayer() const { return Tag == EReducerTag::MovePlayer; } + FORCEINLINE FMovePlayerArgs GetAsMovePlayer() const + { + ensureMsgf(IsMovePlayer(), TEXT("Reducer does not hold MovePlayer!")); + return Data.Get(); + } + + FORCEINLINE bool operator==(const FReducer& Other) const + { + if (Tag != Other.Tag || ReducerId != Other.ReducerId || RequestId != Other.RequestId || ReducerName != Other.ReducerName) return false; + switch (Tag) + { + case EReducerTag::DeletePlayer: + return GetAsDeletePlayer() == Other.GetAsDeletePlayer(); + case EReducerTag::InsertPlayer: + return GetAsInsertPlayer() == Other.GetAsInsertPlayer(); + case EReducerTag::MovePlayer: + return GetAsMovePlayer() == Other.GetAsMovePlayer(); + default: return false; + } + } + FORCEINLINE bool operator!=(const FReducer& Other) const { return !(*this == Other); } +}; + +UCLASS() +class TESTVIEWCLIENT_API UReducerBpLib : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +private: + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer DeletePlayer(const FDeletePlayerArgs& Value) { + return FReducer::DeletePlayer(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsDeletePlayer(const FReducer& Reducer) { return Reducer.IsDeletePlayer(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FDeletePlayerArgs GetAsDeletePlayer(const FReducer& Reducer) { + return Reducer.GetAsDeletePlayer(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer InsertPlayer(const FInsertPlayerArgs& Value) { + return FReducer::InsertPlayer(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsInsertPlayer(const FReducer& Reducer) { return Reducer.IsInsertPlayer(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FInsertPlayerArgs GetAsInsertPlayer(const FReducer& Reducer) { + return Reducer.GetAsInsertPlayer(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer MovePlayer(const FMovePlayerArgs& Value) { + return FReducer::MovePlayer(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsMovePlayer(const FReducer& Reducer) { return Reducer.IsMovePlayer(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FMovePlayerArgs GetAsMovePlayer(const FReducer& Reducer) { + return Reducer.GetAsMovePlayer(); + } +}; + +/** Metadata describing a reducer run. */ +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FTestViewClientReducerEvent +{ + GENERATED_BODY() + + /** Timestamp for when the reducer executed */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBTimestamp Timestamp; + + /** Result status of the reducer */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBStatus Status; + + /** Identity that initiated the call */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBIdentity CallerIdentity; + + /** Connection ID for the caller */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBConnectionId CallerConnectionId; + + /** Energy consumed while executing */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FEnergyQuantaType EnergyConsumed; + + /** Detailed call information */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FReducer Reducer; + + FORCEINLINE bool operator==(const FTestViewClientReducerEvent& Other) const + { + return Status == Other.Status && Timestamp == Other.Timestamp && CallerIdentity == Other.CallerIdentity && + CallerConnectionId == Other.CallerConnectionId && EnergyConsumed == Other.EnergyConsumed && + Reducer == Other.Reducer; + } + + FORCEINLINE bool operator!=(const FTestViewClientReducerEvent& Other) const + { + return !(*this == Other); + } +}; + +// No procedures defined in this module. +/** Metadata describing a procedure run. */ +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FTestViewClientProcedureEvent +{ + GENERATED_BODY() + + /** Timestamp for when the procedure executed */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBTimestamp Timestamp; + + /** Result status of the procedure */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBProcedureStatus Status; + + /** Identity that initiated the call */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBTimeDuration TotalHostExecutionDuration; + + FTestViewClientProcedureEvent() { + } + FTestViewClientProcedureEvent(FProcedureEvent Event) { + Timestamp = Event.Timestamp; + Status = FSpacetimeDBProcedureStatus::FromStatus(Event.Status); + TotalHostExecutionDuration = Event.TotalHostExecutionDuration; + } + FORCEINLINE bool operator==(const FTestViewClientProcedureEvent& Other) const + { + return Status == Other.Status && Timestamp == Other.Timestamp && + TotalHostExecutionDuration == Other.TotalHostExecutionDuration; + } + + FORCEINLINE bool operator!=(const FTestViewClientProcedureEvent& Other) const + { + return !(*this == Other); + } +}; + +/** Represents event with variant message data. */ +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FTestViewClientEvent +{ + GENERATED_BODY() + + /** Tagged union holding reducer call, unit events, or error string */ + TVariant MessageData; + + /** Type tag indicating what this event represents */ + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + ESpacetimeDBEventTag Tag = ESpacetimeDBEventTag::UnknownTransaction; + + /** === Static factory methods ===*/ + static FTestViewClientEvent Reducer(const FReducer& Value) + { + FTestViewClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::Reducer; + Obj.MessageData.Set(Value); + return Obj; + } + + static FTestViewClientEvent SubscribeApplied(const FSpacetimeDBUnit& Value) + { + FTestViewClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::SubscribeApplied; + Obj.MessageData.Set(Value); + return Obj; + } + + static FTestViewClientEvent UnsubscribeApplied(const FSpacetimeDBUnit& Value) + { + FTestViewClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::UnsubscribeApplied; + Obj.MessageData.Set(Value); + return Obj; + } + + static FTestViewClientEvent Disconnected(const FSpacetimeDBUnit& Value) + { + FTestViewClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::Disconnected; + Obj.MessageData.Set(Value); + return Obj; + } + + static FTestViewClientEvent Transaction(const FSpacetimeDBUnit& Value) + { + FTestViewClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::Transaction; + Obj.MessageData.Set(Value); + return Obj; + } + + static FTestViewClientEvent SubscribeError(const FString& Value) + { + FTestViewClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::SubscribeError; + Obj.MessageData.Set(Value); + return Obj; + } + + static FTestViewClientEvent UnknownTransaction(const FSpacetimeDBUnit& Value) + { + FTestViewClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::UnknownTransaction; + Obj.MessageData.Set(Value); + return Obj; + } + + FORCEINLINE bool IsReducer() const { return Tag == ESpacetimeDBEventTag::Reducer; } + FORCEINLINE FReducer GetAsReducer() const + { + ensureMsgf(IsReducer(), TEXT("MessageData does not hold Reducer!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsSubscribeApplied() const { return Tag == ESpacetimeDBEventTag::SubscribeApplied; } + FORCEINLINE FSpacetimeDBUnit GetAsSubscribeApplied() const + { + ensureMsgf(IsSubscribeApplied(), TEXT("MessageData does not hold SubscribeApplied!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsUnsubscribeApplied() const { return Tag == ESpacetimeDBEventTag::UnsubscribeApplied; } + FORCEINLINE FSpacetimeDBUnit GetAsUnsubscribeApplied() const + { + ensureMsgf(IsUnsubscribeApplied(), TEXT("MessageData does not hold UnsubscribeApplied!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsDisconnected() const { return Tag == ESpacetimeDBEventTag::Disconnected; } + FORCEINLINE FSpacetimeDBUnit GetAsDisconnected() const + { + ensureMsgf(IsDisconnected(), TEXT("MessageData does not hold Disconnected!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsTransaction() const { return Tag == ESpacetimeDBEventTag::Transaction; } + FORCEINLINE FSpacetimeDBUnit GetAsTransaction() const + { + ensureMsgf(IsTransaction(), TEXT("MessageData does not hold Transaction!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsSubscribeError() const { return Tag == ESpacetimeDBEventTag::SubscribeError; } + FORCEINLINE FString GetAsSubscribeError() const + { + ensureMsgf(IsSubscribeError(), TEXT("MessageData does not hold SubscribeError!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsUnknownTransaction() const { return Tag == ESpacetimeDBEventTag::UnknownTransaction; } + FORCEINLINE FSpacetimeDBUnit GetAsUnknownTransaction() const + { + ensureMsgf(IsUnknownTransaction(), TEXT("MessageData does not hold UnknownTransaction!")); + return MessageData.Get(); + } + + FORCEINLINE bool operator==(const FTestViewClientEvent& Other) const + { + if (Tag != Other.Tag) return false; + switch (Tag) + { + case ESpacetimeDBEventTag::Reducer: return GetAsReducer() == Other.GetAsReducer(); + case ESpacetimeDBEventTag::SubscribeApplied: return GetAsSubscribeApplied() == Other.GetAsSubscribeApplied(); + case ESpacetimeDBEventTag::UnsubscribeApplied: return GetAsUnsubscribeApplied() == Other.GetAsUnsubscribeApplied(); + case ESpacetimeDBEventTag::Disconnected: return GetAsDisconnected() == Other.GetAsDisconnected(); + case ESpacetimeDBEventTag::Transaction: return GetAsTransaction() == Other.GetAsTransaction(); + case ESpacetimeDBEventTag::SubscribeError: return GetAsSubscribeError() == Other.GetAsSubscribeError(); + case ESpacetimeDBEventTag::UnknownTransaction: return GetAsUnknownTransaction() == Other.GetAsUnknownTransaction(); + default: return false; + } + } + + FORCEINLINE bool operator!=(const FTestViewClientEvent& Other) const + { + return !(*this == Other); + } +}; + +UCLASS() +class TESTVIEWCLIENT_API UTestViewClientEventBpLib : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +private: + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewClientEvent") + static FTestViewClientEvent Reducer(const FReducer& InValue) + { + return FTestViewClientEvent::Reducer(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewClientEvent") + static FTestViewClientEvent SubscribeApplied(const FSpacetimeDBUnit& InValue) + { + return FTestViewClientEvent::SubscribeApplied(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewClientEvent") + static FTestViewClientEvent UnsubscribeApplied(const FSpacetimeDBUnit& InValue) + { + return FTestViewClientEvent::UnsubscribeApplied(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewClientEvent") + static FTestViewClientEvent Disconnected(const FSpacetimeDBUnit& InValue) + { + return FTestViewClientEvent::Disconnected(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewClientEvent") + static FTestViewClientEvent Transaction(const FSpacetimeDBUnit& InValue) + { + return FTestViewClientEvent::Transaction(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewClientEvent") + static FTestViewClientEvent SubscribeError(const FString& InValue) + { + return FTestViewClientEvent::SubscribeError(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewClientEvent") + static FTestViewClientEvent UnknownTransaction(const FSpacetimeDBUnit& InValue) + { + return FTestViewClientEvent::UnknownTransaction(InValue); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static bool IsReducer(const FTestViewClientEvent& Event) { return Event.IsReducer(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static bool IsSubscribeApplied(const FTestViewClientEvent& Event) { return Event.IsSubscribeApplied(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static bool IsUnsubscribeApplied(const FTestViewClientEvent& Event) { return Event.IsUnsubscribeApplied(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static bool IsDisconnected(const FTestViewClientEvent& Event) { return Event.IsDisconnected(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static bool IsTransaction(const FTestViewClientEvent& Event) { return Event.IsTransaction(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static bool IsSubscribeError(const FTestViewClientEvent& Event) { return Event.IsSubscribeError(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static bool IsUnknownTransaction(const FTestViewClientEvent& Event) { return Event.IsUnknownTransaction(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static FReducer GetAsReducer(const FTestViewClientEvent& Event) + { + return Event.GetAsReducer(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static FSpacetimeDBUnit GetAsSubscribeApplied(const FTestViewClientEvent& Event) + { + return Event.GetAsSubscribeApplied(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static FSpacetimeDBUnit GetAsUnsubscribeApplied(const FTestViewClientEvent& Event) + { + return Event.GetAsUnsubscribeApplied(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static FSpacetimeDBUnit GetAsDisconnected(const FTestViewClientEvent& Event) + { + return Event.GetAsDisconnected(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static FSpacetimeDBUnit GetAsTransaction(const FTestViewClientEvent& Event) + { + return Event.GetAsTransaction(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static FString GetAsSubscribeError(const FTestViewClientEvent& Event) + { + return Event.GetAsSubscribeError(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewClientEvent") + static FSpacetimeDBUnit GetAsUnknownTransaction(const FTestViewClientEvent& Event) + { + return Event.GetAsUnknownTransaction(); + } + +}; + + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FEventContext : public FContextBase +{ + GENERATED_BODY() + + FEventContext() = default; + FEventContext(UDbConnection* InConn, const FTestViewClientEvent& InEvent) : FContextBase(InConn), Event(InEvent) {} + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FTestViewClientEvent Event; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FReducerEventContext : public FContextBase +{ + GENERATED_BODY() + + FReducerEventContext() = default; + FReducerEventContext(UDbConnection* InConn, FTestViewClientReducerEvent InEvent) : FContextBase(InConn), Event(InEvent) {} + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FTestViewClientReducerEvent Event; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FProcedureEventContext : public FContextBase +{ + GENERATED_BODY() + + FProcedureEventContext() = default; + FProcedureEventContext(UDbConnection* InConn, FTestViewClientProcedureEvent InEvent) : FContextBase(InConn), Event(InEvent) {} + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FTestViewClientProcedureEvent Event; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FErrorContext : public FContextBase +{ + GENERATED_BODY() + + FErrorContext() = default; + FErrorContext(UDbConnection* InConn, const FString& InError) : FContextBase(InConn), Error(InError) {} + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FString Error; + +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FSubscriptionEventContext : public FContextBase +{ + GENERATED_BODY() + + FSubscriptionEventContext() = default; + FSubscriptionEventContext(UDbConnection* InConn) : FContextBase(InConn) {} + +}; + +DECLARE_DYNAMIC_DELEGATE_OneParam( + FOnSubscriptionApplied, + FSubscriptionEventContext, Context); + +DECLARE_DYNAMIC_DELEGATE_OneParam( + FOnSubscriptionError, + FErrorContext, Context); + +// RemoteTables class +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API URemoteTables : public UObject +{ + GENERATED_BODY() + +public: + void Initialize(); + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UMyPlayerTable* MyPlayer; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UMyPlayerAndLevelTable* MyPlayerAndLevel; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UNearbyPlayersTable* NearbyPlayers; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UPlayerTable* Player; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UPlayerLevelTable* PlayerLevel; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UPlayersAtLevel0Table* PlayersAtLevel0; + +}; + +// RemoteReducers class +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API URemoteReducers : public UObject +{ + GENERATED_BODY() + +public: + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FDeletePlayerHandler, + const FReducerEventContext&, Context, + const FSpacetimeDBIdentity&, Identity + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FDeletePlayerHandler OnDeletePlayer; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void DeletePlayer(const FSpacetimeDBIdentity& Identity); + + bool InvokeDeletePlayer(const FReducerEventContext& Context, const UDeletePlayerReducer* Args); + bool InvokeDeletePlayerWithArgs(const FReducerEventContext& Context, const FDeletePlayerArgs& Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FInsertPlayerHandler, + const FReducerEventContext&, Context, + const FSpacetimeDBIdentity&, Identity, + uint64, Level + ); + // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible + FInsertPlayerHandler OnInsertPlayer; + + // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible + void InsertPlayer(const FSpacetimeDBIdentity& Identity, const uint64 Level); + + bool InvokeInsertPlayer(const FReducerEventContext& Context, const UInsertPlayerReducer* Args); + bool InvokeInsertPlayerWithArgs(const FReducerEventContext& Context, const FInsertPlayerArgs& Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FMovePlayerHandler, + const FReducerEventContext&, Context, + int32, Dx, + int32, Dy + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FMovePlayerHandler OnMovePlayer; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void MovePlayer(const int32 Dx, const int32 Dy); + + bool InvokeMovePlayer(const FReducerEventContext& Context, const UMovePlayerReducer* Args); + bool InvokeMovePlayerWithArgs(const FReducerEventContext& Context, const FMovePlayerArgs& Args); + + // Internal error handling + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FInternalOnUnhandledReducerError, const FReducerEventContext&, Context, const FString&, Error); + FInternalOnUnhandledReducerError InternalOnUnhandledReducerError; + +private: + + friend UDbConnection; + + UPROPERTY() + class UDbConnection* Conn; +}; + +// RemoteProcedures class +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API URemoteProcedures : public UObject +{ + GENERATED_BODY() + +public: + + // Internal error handling + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FInternalOnUnhandledProcedureError, const FProcedureEventContext&, Context, const FString&, Error); + FInternalOnUnhandledProcedureError InternalOnUnhandledProcedureError; + +private: + + friend UDbConnection; + + UPROPERTY() + class UDbConnection* Conn; +}; + +// QueryBuilder types +struct TESTVIEWCLIENT_API FPlayerCols +{ + explicit FPlayerCols(const char* TableName) + : EntityId(TableName, "entity_id"), Identity(TableName, "identity") {} + + ::SpacetimeDB::query_builder::Col EntityId; + ::SpacetimeDB::query_builder::Col Identity; +}; + +struct TESTVIEWCLIENT_API FPlayerIxCols +{ + explicit FPlayerIxCols(const char* TableName) + : EntityId(TableName, "entity_id"), Identity(TableName, "identity") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t EntityId; + ::SpacetimeDB::query_builder::detail::ix_col_member_t Identity; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPlayerCols get(const char* table_name) { return FPlayerCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPlayerIxCols get(const char* table_name) { return FPlayerIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTVIEWCLIENT_API FPlayerAndLevelCols +{ + explicit FPlayerAndLevelCols(const char* TableName) + : EntityId(TableName, "entity_id"), Identity(TableName, "identity"), Level(TableName, "level") {} + + ::SpacetimeDB::query_builder::Col EntityId; + ::SpacetimeDB::query_builder::Col Identity; + ::SpacetimeDB::query_builder::Col Level; +}; + +struct TESTVIEWCLIENT_API FPlayerAndLevelIxCols +{ + explicit FPlayerAndLevelIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FPlayerAndLevelCols get(const char* table_name) { return FPlayerAndLevelCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPlayerAndLevelIxCols get(const char* table_name) { return FPlayerAndLevelIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTVIEWCLIENT_API FPlayerLocationCols +{ + explicit FPlayerLocationCols(const char* TableName) + : EntityId(TableName, "entity_id"), Active(TableName, "active"), X(TableName, "x"), Y(TableName, "y") {} + + ::SpacetimeDB::query_builder::Col EntityId; + ::SpacetimeDB::query_builder::Col Active; + ::SpacetimeDB::query_builder::Col X; + ::SpacetimeDB::query_builder::Col Y; +}; + +struct TESTVIEWCLIENT_API FPlayerLocationIxCols +{ + explicit FPlayerLocationIxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ + + template<> + struct HasCols + { + static FPlayerLocationCols get(const char* table_name) { return FPlayerLocationCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPlayerLocationIxCols get(const char* table_name) { return FPlayerLocationIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTVIEWCLIENT_API FPlayerLevelCols +{ + explicit FPlayerLevelCols(const char* TableName) + : EntityId(TableName, "entity_id"), Level(TableName, "level") {} + + ::SpacetimeDB::query_builder::Col EntityId; + ::SpacetimeDB::query_builder::Col Level; +}; + +struct TESTVIEWCLIENT_API FPlayerLevelIxCols +{ + explicit FPlayerLevelIxCols(const char* TableName) + : EntityId(TableName, "entity_id"), Level(TableName, "level") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t EntityId; + ::SpacetimeDB::query_builder::detail::ix_col_member_t Level; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FPlayerLevelCols get(const char* table_name) { return FPlayerLevelCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FPlayerLevelIxCols get(const char* table_name) { return FPlayerLevelIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTVIEWCLIENT_API FFrom +{ + [[nodiscard]] ::SpacetimeDB::query_builder::Table MyPlayer() const { return ::SpacetimeDB::query_builder::Table("my_player"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table MyPlayerAndLevel() const { return ::SpacetimeDB::query_builder::Table("my_player_and_level"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table NearbyPlayers() const { return ::SpacetimeDB::query_builder::Table("nearby_players"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table Player() const { return ::SpacetimeDB::query_builder::Table("player"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PlayerLevel() const { return ::SpacetimeDB::query_builder::Table("player_level"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PlayersAtLevel0() const { return ::SpacetimeDB::query_builder::Table("players_at_level_0"); } +}; + +struct TESTVIEWCLIENT_API FQueryBuilder +{ + FFrom From; + + static TArray AllTablesSqlQueries() + { + TArray Sql; + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.MyPlayer().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.MyPlayerAndLevel().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.NearbyPlayers().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.Player().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PlayerLevel().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.PlayersAtLevel0().into_sql().c_str()))); + return Sql; + } +}; + +struct TESTVIEWCLIENT_API FTypedSubscriptionBuilder +{ + explicit FTypedSubscriptionBuilder(UDbConnection* InConn) + : Conn(InConn) {} + + FTypedSubscriptionBuilder& OnApplied(FOnSubscriptionApplied Callback); + FTypedSubscriptionBuilder& OnError(FOnSubscriptionError Callback); + + template + FTypedSubscriptionBuilder& AddQuery(TFn&& Build) + { + FQueryBuilder Q; + auto Query = std::forward(Build)(Q); + static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn, + "Typed subscription queries must return a query_builder table/query expression."); + Sql.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str()))); + return *this; + } + + USubscriptionHandle* Subscribe(); + +private: + UDbConnection* Conn = nullptr; + TArray Sql; + FOnSubscriptionApplied OnAppliedDelegateInternal; + FOnSubscriptionError OnErrorDelegateInternal; +}; + +// SubscriptionBuilder class +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase +{ + GENERATED_BODY() + +public: + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + USubscriptionBuilder* OnApplied(FOnSubscriptionApplied Callback); + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + USubscriptionBuilder* OnError(FOnSubscriptionError Callback); + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + USubscriptionHandle* Subscribe(const TArray& SQL); + + template + [[nodiscard]] FTypedSubscriptionBuilder AddQuery(TFn&& Build) + { + FTypedSubscriptionBuilder Typed(Conn); + Typed.OnApplied(OnAppliedDelegateInternal); + Typed.OnError(OnErrorDelegateInternal); + Typed.AddQuery(std::forward(Build)); + return Typed; + } + + /** Convenience for subscribing to all rows from all tables */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + USubscriptionHandle* SubscribeToAllTables(); + + + friend class UDbConnection; + friend class UDbConnectionBase; + +protected: + UPROPERTY() + class UDbConnection* Conn; + + // Delegates stored so Subscribe() can bind forwarding callbacks + FOnSubscriptionApplied OnAppliedDelegateInternal; + FOnSubscriptionError OnErrorDelegateInternal; +}; + +// SubscriptionHandle class +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API USubscriptionHandle : public USubscriptionHandleBase +{ + GENERATED_BODY() + +public: + + USubscriptionHandle() {}; + + explicit USubscriptionHandle(UDbConnection* InConn); + + friend class USubscriptionBuilder; + +private: + UPROPERTY() + class UDbConnection* Conn; + + // Delegates that expose subscription events with connection aware contexts + FOnSubscriptionApplied OnAppliedDelegate; + FOnSubscriptionError OnErrorDelegate; + + UFUNCTION() + void ForwardOnApplied(const FSubscriptionEventContextBase& BaseCtx); + + UFUNCTION() + void ForwardOnError(const FErrorContextBase& BaseCtx); +}; + +/* + @Note: Child class of UDbConnectionBuilderBase. +*/ +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API UDbConnectionBuilder : public UDbConnectionBuilderBase +{ + GENERATED_BODY() +public: + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* WithUri(const FString& InUri); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* WithDatabaseName(const FString& InName); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* WithToken(const FString& InToken); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* WithCompression(const ESpacetimeDBCompression& InCompression); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* OnConnect(FOnConnectDelegate Callback); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* OnConnectError(FOnConnectErrorDelegate Callback); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* OnDisconnect(FOnDisconnectDelegate Callback); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnection* Build(); + +private: + + // Stored delegates which will be forwarded when the connection events occur. + FOnConnectDelegate OnConnectDelegateInternal; + FOnDisconnectDelegate OnDisconnectDelegateInternal; +}; + +// Main DbConnection class +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API UDbConnection : public UDbConnectionBase +{ + GENERATED_BODY() + +public: + explicit UDbConnection(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); + + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + URemoteTables* Db; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + URemoteReducers* Reducers; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + URemoteProcedures* Procedures; + + // Delegates that allow users to bind with the concrete connection type. + FOnConnectDelegate OnConnectDelegate; + FOnDisconnectDelegate OnDisconnectDelegate; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + USubscriptionBuilder* SubscriptionBuilder(); + + /** Static entry point for constructing a connection. */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB", DisplayName = "SpacetimeDB TestViewClient Builder") + static UDbConnectionBuilder* Builder(); + + // Error handling + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnUnhandledReducerError, const FReducerEventContext&, Context, const FString&, Error); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FOnUnhandledReducerError OnUnhandledReducerError; + + // Error handling + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnUnhandledProcedureError, const FProcedureEventContext&, Context, const FString&, Error); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FOnUnhandledProcedureError OnUnhandledProcedureError; + + +protected: + + // Hook up error handling to reducers and procedures + virtual void PostInitProperties() override; + + UFUNCTION() + void ForwardOnConnect(UDbConnectionBase* BaseConnection, FSpacetimeDBIdentity InIdentity, const FString& InToken); + UFUNCTION() + void ForwardOnDisconnect(UDbConnectionBase* BaseConnection, const FString& Error); + + UFUNCTION() + void OnUnhandledReducerErrorHandler(const FReducerEventContext& Context, const FString& Error); + + UFUNCTION() + void OnUnhandledProcedureErrorHandler(const FProcedureEventContext& Context, const FString& Error); + + // Override the DbConnectionBase methods to handle updates and events + virtual void DbUpdate(const FDatabaseUpdateType& Update, const FSpacetimeDBEvent& Event) override; + + // Override the reducer event handler to dispatch events to the appropriate reducers + virtual void ReducerEvent(const FReducerEvent& Event) override; + + // Override the reducer event failed handler + virtual void ReducerEventFailed(const FReducerEvent& Event, const FString ErrorMessage) override; + // Override the procedure event failed handler + virtual void ProcedureEventFailed(const FProcedureEvent& Event, const FString ErrorMessage) override; + + friend class USubscriptionBuilder; + friend class UDbConnectionBuilder; + friend class URemoteReducers; + + // Internal reducer correlation helpers (request_id -> typed reducer) + void RegisterPendingTypedReducer(uint32 RequestId, FReducer Reducer); + bool TryGetPendingTypedReducer(uint32 RequestId, FReducer& OutReducer) const; + bool TryTakePendingTypedReducer(uint32 RequestId, FReducer& OutReducer); + +private: + TMap PendingTypedReducers; +}; + diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/MyPlayerAndLevelTable.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/MyPlayerAndLevelTable.g.h new file mode 100644 index 00000000000..6a49f4bf34c --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/MyPlayerAndLevelTable.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/PlayerAndLevelType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "MyPlayerAndLevelTable.g.generated.h" + +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API UMyPlayerAndLevelTable : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for my_player_and_level table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnMyPlayerAndLevelInsert, + const FEventContext&, Context, + const FPlayerAndLevelType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnMyPlayerAndLevelUpdate, + const FEventContext&, Context, + const FPlayerAndLevelType&, OldRow, + const FPlayerAndLevelType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnMyPlayerAndLevelDelete, + const FEventContext&, Context, + const FPlayerAndLevelType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnMyPlayerAndLevelInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnMyPlayerAndLevelUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnMyPlayerAndLevelDelete OnDelete; + +private: + const FString TableName = TEXT("my_player_and_level"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/MyPlayerTable.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/MyPlayerTable.g.h new file mode 100644 index 00000000000..ca978580203 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/MyPlayerTable.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/PlayerType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "MyPlayerTable.g.generated.h" + +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API UMyPlayerTable : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for my_player table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnMyPlayerInsert, + const FEventContext&, Context, + const FPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnMyPlayerUpdate, + const FEventContext&, Context, + const FPlayerType&, OldRow, + const FPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnMyPlayerDelete, + const FEventContext&, Context, + const FPlayerType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnMyPlayerInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnMyPlayerUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnMyPlayerDelete OnDelete; + +private: + const FString TableName = TEXT("my_player"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/NearbyPlayersTable.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/NearbyPlayersTable.g.h new file mode 100644 index 00000000000..e7978fa5320 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/NearbyPlayersTable.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/PlayerLocationType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "NearbyPlayersTable.g.generated.h" + +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API UNearbyPlayersTable : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for nearby_players table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnNearbyPlayersInsert, + const FEventContext&, Context, + const FPlayerLocationType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnNearbyPlayersUpdate, + const FEventContext&, Context, + const FPlayerLocationType&, OldRow, + const FPlayerLocationType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnNearbyPlayersDelete, + const FEventContext&, Context, + const FPlayerLocationType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnNearbyPlayersInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnNearbyPlayersUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnNearbyPlayersDelete OnDelete; + +private: + const FString TableName = TEXT("nearby_players"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/PlayerLevelTable.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/PlayerLevelTable.g.h new file mode 100644 index 00000000000..dbaa12e754a --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/PlayerLevelTable.g.h @@ -0,0 +1,141 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/PlayerLevelType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "PlayerLevelTable.g.generated.h" + +UCLASS(Blueprintable) +class TESTVIEWCLIENT_API UPlayerLevelEntityIdUniqueIndex : public UObject +{ + GENERATED_BODY() + +private: + // Declare an instance of your templated helper. + // It's private because the UObject wrapper will expose its functionality. + FUniqueIndexHelper> EntityIdIndexHelper; + +public: + UPlayerLevelEntityIdUniqueIndex() + // Initialize the helper with the specific unique index name + : EntityIdIndexHelper("entity_id") { + } + + /** + * Finds a PlayerLevel by their unique entityid. + * @param Key The entityid to search for. + * @return The found FPlayerLevelType, or a default-constructed FPlayerLevelType if not found. + */ + // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible + FPlayerLevelType Find(uint64 Key) + { + // Simply delegate the call to the internal helper + return EntityIdIndexHelper.FindUniqueIndex(Key); + } + + // A public setter to provide the cache to the helper after construction + // This is a common pattern when the cache might be created or provided by another system. + void SetCache(TSharedPtr> InPlayerLevelCache) + { + EntityIdIndexHelper.Cache = InPlayerLevelCache; + } +}; +/***/ + +UCLASS(Blueprintable) +class UPlayerLevelLevelIndex : public UObject +{ + GENERATED_BODY() + +public: + TArray Filter(const uint64& Level) const + { + TArray OutResults; + + LocalCache->FindByMultiKeyBTreeIndex>( + OutResults, + TEXT("level"), + MakeTuple(Level) + ); + + return OutResults; + } + + void SetCache(TSharedPtr> InCache) + { + LocalCache = InCache; + } + +private: + // NOTE: Not exposed to Blueprint because some parameter types are not Blueprint-compatible + void FilterLevel(TArray& OutResults, const uint64& Level) + { + OutResults = Filter(Level); + } + + TSharedPtr> LocalCache; +}; + +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API UPlayerLevelTable : public URemoteTable +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly) + UPlayerLevelEntityIdUniqueIndex* EntityId; + + UPROPERTY(BlueprintReadOnly) + UPlayerLevelLevelIndex* Level; + + void PostInitialize(); + + /** Update function for player_level table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnPlayerLevelInsert, + const FEventContext&, Context, + const FPlayerLevelType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnPlayerLevelUpdate, + const FEventContext&, Context, + const FPlayerLevelType&, OldRow, + const FPlayerLevelType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnPlayerLevelDelete, + const FEventContext&, Context, + const FPlayerLevelType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnPlayerLevelInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnPlayerLevelUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnPlayerLevelDelete OnDelete; + +private: + const FString TableName = TEXT("player_level"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/PlayerTable.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/PlayerTable.g.h new file mode 100644 index 00000000000..acbc7f06735 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/PlayerTable.g.h @@ -0,0 +1,144 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/PlayerType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "PlayerTable.g.generated.h" + +UCLASS(Blueprintable) +class TESTVIEWCLIENT_API UPlayerEntityIdUniqueIndex : public UObject +{ + GENERATED_BODY() + +private: + // Declare an instance of your templated helper. + // It's private because the UObject wrapper will expose its functionality. + FUniqueIndexHelper> EntityIdIndexHelper; + +public: + UPlayerEntityIdUniqueIndex() + // Initialize the helper with the specific unique index name + : EntityIdIndexHelper("entity_id") { + } + + /** + * Finds a Player by their unique entityid. + * @param Key The entityid to search for. + * @return The found FPlayerType, or a default-constructed FPlayerType if not found. + */ + // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible + FPlayerType Find(uint64 Key) + { + // Simply delegate the call to the internal helper + return EntityIdIndexHelper.FindUniqueIndex(Key); + } + + // A public setter to provide the cache to the helper after construction + // This is a common pattern when the cache might be created or provided by another system. + void SetCache(TSharedPtr> InPlayerCache) + { + EntityIdIndexHelper.Cache = InPlayerCache; + } +}; +/***/ + +UCLASS(Blueprintable) +class TESTVIEWCLIENT_API UPlayerIdentityUniqueIndex : public UObject +{ + GENERATED_BODY() + +private: + // Declare an instance of your templated helper. + // It's private because the UObject wrapper will expose its functionality. + FUniqueIndexHelper> IdentityIndexHelper; + +public: + UPlayerIdentityUniqueIndex() + // Initialize the helper with the specific unique index name + : IdentityIndexHelper("identity") { + } + + /** + * Finds a Player by their unique identity. + * @param Key The identity to search for. + * @return The found FPlayerType, or a default-constructed FPlayerType if not found. + */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|PlayerIndex") + FPlayerType Find(FSpacetimeDBIdentity Key) + { + // Simply delegate the call to the internal helper + return IdentityIndexHelper.FindUniqueIndex(Key); + } + + // A public setter to provide the cache to the helper after construction + // This is a common pattern when the cache might be created or provided by another system. + void SetCache(TSharedPtr> InPlayerCache) + { + IdentityIndexHelper.Cache = InPlayerCache; + } +}; +/***/ + +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API UPlayerTable : public URemoteTable +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly) + UPlayerEntityIdUniqueIndex* EntityId; + + UPROPERTY(BlueprintReadOnly) + UPlayerIdentityUniqueIndex* Identity; + + void PostInitialize(); + + /** Update function for player table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnPlayerInsert, + const FEventContext&, Context, + const FPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnPlayerUpdate, + const FEventContext&, Context, + const FPlayerType&, OldRow, + const FPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnPlayerDelete, + const FEventContext&, Context, + const FPlayerType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnPlayerInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnPlayerUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnPlayerDelete OnDelete; + +private: + const FString TableName = TEXT("player"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/PlayersAtLevel0Table.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/PlayersAtLevel0Table.g.h new file mode 100644 index 00000000000..f075e353c30 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Tables/PlayersAtLevel0Table.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/PlayerType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "PlayersAtLevel0Table.g.generated.h" + +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API UPlayersAtLevel0Table : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for players_at_level_0 table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnPlayersAtLevel0Insert, + const FEventContext&, Context, + const FPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnPlayersAtLevel0Update, + const FEventContext&, Context, + const FPlayerType&, OldRow, + const FPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnPlayersAtLevel0Delete, + const FEventContext&, Context, + const FPlayerType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnPlayersAtLevel0Insert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnPlayersAtLevel0Update OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnPlayersAtLevel0Delete OnDelete; + +private: + const FString TableName = TEXT("players_at_level_0"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerAndLevelType.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerAndLevelType.g.h new file mode 100644 index 00000000000..f059a5b9a63 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerAndLevelType.g.h @@ -0,0 +1,54 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "PlayerAndLevelType.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FPlayerAndLevelType +{ + GENERATED_BODY() + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 EntityId = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + FSpacetimeDBIdentity Identity; + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Level = 0; + + FORCEINLINE bool operator==(const FPlayerAndLevelType& Other) const + { + return EntityId == Other.EntityId && Identity == Other.Identity && Level == Other.Level; + } + + FORCEINLINE bool operator!=(const FPlayerAndLevelType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FPlayerAndLevelType. + * Combines the hashes of all fields that are compared in operator==. + * @param PlayerAndLevelType The FPlayerAndLevelType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FPlayerAndLevelType& PlayerAndLevelType) +{ + uint32 Hash = GetTypeHash(PlayerAndLevelType.EntityId); + Hash = HashCombine(Hash, GetTypeHash(PlayerAndLevelType.Identity)); + Hash = HashCombine(Hash, GetTypeHash(PlayerAndLevelType.Level)); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FPlayerAndLevelType); + + UE_SPACETIMEDB_STRUCT(FPlayerAndLevelType, EntityId, Identity, Level); +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerLevelType.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerLevelType.g.h new file mode 100644 index 00000000000..166e205b77a --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerLevelType.g.h @@ -0,0 +1,49 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "PlayerLevelType.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FPlayerLevelType +{ + GENERATED_BODY() + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 EntityId = 0; + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Level = 0; + + FORCEINLINE bool operator==(const FPlayerLevelType& Other) const + { + return EntityId == Other.EntityId && Level == Other.Level; + } + + FORCEINLINE bool operator!=(const FPlayerLevelType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FPlayerLevelType. + * Combines the hashes of all fields that are compared in operator==. + * @param PlayerLevelType The FPlayerLevelType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FPlayerLevelType& PlayerLevelType) +{ + uint32 Hash = GetTypeHash(PlayerLevelType.EntityId); + Hash = HashCombine(Hash, GetTypeHash(PlayerLevelType.Level)); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FPlayerLevelType); + + UE_SPACETIMEDB_STRUCT(FPlayerLevelType, EntityId, Level); +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerLocationType.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerLocationType.g.h new file mode 100644 index 00000000000..cac3775992c --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerLocationType.g.h @@ -0,0 +1,57 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "PlayerLocationType.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FPlayerLocationType +{ + GENERATED_BODY() + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 EntityId = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + bool Active = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + int32 X = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + int32 Y = 0; + + FORCEINLINE bool operator==(const FPlayerLocationType& Other) const + { + return EntityId == Other.EntityId && Active == Other.Active && X == Other.X && Y == Other.Y; + } + + FORCEINLINE bool operator!=(const FPlayerLocationType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FPlayerLocationType. + * Combines the hashes of all fields that are compared in operator==. + * @param PlayerLocationType The FPlayerLocationType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FPlayerLocationType& PlayerLocationType) +{ + uint32 Hash = GetTypeHash(PlayerLocationType.EntityId); + Hash = HashCombine(Hash, GetTypeHash(PlayerLocationType.Active)); + Hash = HashCombine(Hash, GetTypeHash(PlayerLocationType.X)); + Hash = HashCombine(Hash, GetTypeHash(PlayerLocationType.Y)); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FPlayerLocationType); + + UE_SPACETIMEDB_STRUCT(FPlayerLocationType, EntityId, Active, X, Y); +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerType.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerType.g.h new file mode 100644 index 00000000000..afe96d88ab9 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/Types/PlayerType.g.h @@ -0,0 +1,50 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "PlayerType.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FPlayerType +{ + GENERATED_BODY() + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 EntityId = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + FSpacetimeDBIdentity Identity; + + FORCEINLINE bool operator==(const FPlayerType& Other) const + { + return EntityId == Other.EntityId && Identity == Other.Identity; + } + + FORCEINLINE bool operator!=(const FPlayerType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FPlayerType. + * Combines the hashes of all fields that are compared in operator==. + * @param PlayerType The FPlayerType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FPlayerType& PlayerType) +{ + uint32 Hash = GetTypeHash(PlayerType.EntityId); + Hash = HashCombine(Hash, GetTypeHash(PlayerType.Identity)); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FPlayerType); + + UE_SPACETIMEDB_STRUCT(FPlayerType, EntityId, Identity); +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/CommonTestFunctions.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/CommonTestFunctions.h new file mode 100644 index 00000000000..6f70f09beec --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/CommonTestFunctions.h @@ -0,0 +1 @@ +#pragma once diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/PrimitiveHandlerList.def b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/PrimitiveHandlerList.def new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/PrimitiveHandlerList.def @@ -0,0 +1 @@ + diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/SpacetimeFullClientTests.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/SpacetimeFullClientTests.h new file mode 100644 index 00000000000..1d0de3fc794 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/SpacetimeFullClientTests.h @@ -0,0 +1,16 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FViewQueryBuilderDirectSourcesTest, + "SpacetimeDB.TestViewClient.ViewQueryBuilderDirectSourcesTest", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FViewSubscribeAllTablesTest, + "SpacetimeDB.TestViewClient.ViewSubscribeAllTablesTest", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/TestCounter.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/TestCounter.h new file mode 100644 index 00000000000..35b52debcb5 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/TestCounter.h @@ -0,0 +1,35 @@ +#pragma once + +#include "CoreMinimal.h" +#include "HAL/CriticalSection.h" + +struct FTestOutcome +{ + bool bSuccess = false; + FString Error; +}; + +class FTestCounter : public TSharedFromThis +{ +public: + FTestCounter() = default; + + void Register(const FString& TestName); + void MarkSuccess(const FString& TestName); + void MarkFailure(const FString& TestName, const FString& Error); + + bool IsComplete() const; + bool AllSucceeded() const; + TArray GetFailures() const; + TArray GetSuccesses() const; + + void Abort(); + bool IsAborted() const { return bAborted; } + + +private: + mutable FCriticalSection Mutex; + TMap Outcomes; + TSet Registered; + bool bAborted = false; +}; \ No newline at end of file diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/TestHandler.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/TestHandler.h new file mode 100644 index 00000000000..5e8f9ff67bc --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/TestHandler.h @@ -0,0 +1,3 @@ +#pragma once + +class UTestHandler {}; diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/UmbreallaHeaderReducers.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/UmbreallaHeaderReducers.h new file mode 100644 index 00000000000..6f70f09beec --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/UmbreallaHeaderReducers.h @@ -0,0 +1 @@ +#pragma once diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/UmbreallaHeaderTypes.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/UmbreallaHeaderTypes.h new file mode 100644 index 00000000000..6f70f09beec --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/UmbreallaHeaderTypes.h @@ -0,0 +1 @@ +#pragma once diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/UmbreallaHeaderaTables.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/UmbreallaHeaderaTables.h new file mode 100644 index 00000000000..6f70f09beec --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/UmbreallaHeaderaTables.h @@ -0,0 +1 @@ +#pragma once diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClient.Build.cs b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClient.Build.cs new file mode 100644 index 00000000000..84ecb7df9d6 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClient.Build.cs @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using UnrealBuildTool; + +public class TestViewClient : ModuleRules +{ + public TestViewClient(ReadOnlyTargetRules Target) : base(Target) + { + // Set the module type to be a standard module + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + // Set the module to use C++20 standard + CppStandard = CppStandardVersion.Cpp20; + + + // Enable exceptions for this module + bEnableExceptions = true; + + + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "SpacetimeDbSdk" }); + + PrivateDependencyModuleNames.AddRange(new string[] { "DeveloperSettings" }); + + } +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClient.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClient.cpp new file mode 100644 index 00000000000..95d75714381 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClient.cpp @@ -0,0 +1,6 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "TestViewClient.h" +#include "Modules/ModuleManager.h" + +IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, TestViewClient, "TestViewClient"); diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClient.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClient.h new file mode 100644 index 00000000000..90aad9e7e22 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClient.h @@ -0,0 +1,6 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" + diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClientGameModeBase.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClientGameModeBase.cpp new file mode 100644 index 00000000000..c7102b92b21 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClientGameModeBase.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "TestViewClientGameModeBase.h" + diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClientGameModeBase.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClientGameModeBase.h new file mode 100644 index 00000000000..a60387c3a86 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/TestViewClientGameModeBase.h @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/GameModeBase.h" +#include "TestViewClientGameModeBase.generated.h" + +/** + * + */ +UCLASS() +class TESTVIEWCLIENT_API ATestViewClientGameModeBase : public AGameModeBase +{ + GENERATED_BODY() + +}; diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClientEditor.Target.cs b/sdks/unreal/tests/TestViewClient/Source/TestViewClientEditor.Target.cs new file mode 100644 index 00000000000..f10d509c113 --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClientEditor.Target.cs @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class TestViewClientEditorTarget : TargetRules +{ + public TestViewClientEditorTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Editor; + DefaultBuildSettings = BuildSettingsVersion.V5; + + ExtraModuleNames.AddRange( new string[] { "TestViewClient" } ); + } +} diff --git a/sdks/unreal/tests/TestViewClient/TestViewClient.uproject b/sdks/unreal/tests/TestViewClient/TestViewClient.uproject new file mode 100644 index 00000000000..1a6f19cbbcd --- /dev/null +++ b/sdks/unreal/tests/TestViewClient/TestViewClient.uproject @@ -0,0 +1,25 @@ +{ + "FileVersion": 3, + "EngineAssociation": "5.6", + "Category": "", + "Description": "", + "Modules": [ + { + "Name": "TestViewClient", + "Type": "Runtime", + "LoadingPhase": "Default" + } + ], + "Plugins": [ + { + "Name": "ModelingToolsEditorMode", + "Enabled": true, + "TargetAllowList": [ + "Editor" + ] + } + ], + "AdditionalPluginDirectories": [ + "../../src" + ] +} diff --git a/sdks/unreal/tests/TestViewPkClient/.vsconfig b/sdks/unreal/tests/TestViewPkClient/.vsconfig new file mode 100644 index 00000000000..3b919ea7b8f --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/.vsconfig @@ -0,0 +1,17 @@ +{ + "version": "1.0", + "components": [ + "Component.Unreal.Debugger", + "Component.Unreal.Ide", + "Microsoft.Net.Component.4.6.2.TargetingPack", + "Microsoft.VisualStudio.Component.VC.14.38.17.8.ATL", + "Microsoft.VisualStudio.Component.VC.14.38.17.8.x86.x64", + "Microsoft.VisualStudio.Component.VC.Llvm.Clang", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "Microsoft.VisualStudio.Component.Windows11SDK.22621", + "Microsoft.VisualStudio.Workload.CoreEditor", + "Microsoft.VisualStudio.Workload.ManagedDesktop", + "Microsoft.VisualStudio.Workload.NativeDesktop", + "Microsoft.VisualStudio.Workload.NativeGame" + ] +} diff --git a/sdks/unreal/tests/TestViewPkClient/Config/DefaultEditor.ini b/sdks/unreal/tests/TestViewPkClient/Config/DefaultEditor.ini new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdks/unreal/tests/TestViewPkClient/Config/DefaultEditorPerProjectUserSettings.ini b/sdks/unreal/tests/TestViewPkClient/Config/DefaultEditorPerProjectUserSettings.ini new file mode 100644 index 00000000000..58b060183b7 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Config/DefaultEditorPerProjectUserSettings.ini @@ -0,0 +1,5 @@ + + +[/Script/TestViewPkClient.SpacetimeDBSettings] +SpacetimeDbTestName=sdk-test-view-pk + diff --git a/sdks/unreal/tests/TestViewPkClient/Config/DefaultEngine.ini b/sdks/unreal/tests/TestViewPkClient/Config/DefaultEngine.ini new file mode 100644 index 00000000000..0239c099c52 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Config/DefaultEngine.ini @@ -0,0 +1,57 @@ +[Zen] +bEnableZen=false +bEnableZenLocal=false + +[/Script/Zen.ZenServiceSettings] +bEnabled=False +bAutoLaunch=False + +[Audio] +UseAudioMixer=True + +[/Script/HardwareTargeting.HardwareTargetingSettings] +TargetedHardwareClass=Desktop +AppliedTargetedHardwareClass=Desktop +DefaultGraphicsPerformance=Maximum +AppliedDefaultGraphicsPerformance=Maximum + +[/Script/WindowsTargetPlatform.WindowsTargetSettings] +DefaultGraphicsRHI=DefaultGraphicsRHI_DX12 +DefaultGraphicsRHI=DefaultGraphicsRHI_DX12 +!D3D12TargetedShaderFormats=ClearArray ++D3D12TargetedShaderFormats=PCD3D_SM6 + +[/Script/Engine.RendererSettings] +r.AllowStaticLighting=0 +r.GenerateMeshDistanceFields=False +r.DynamicGlobalIlluminationMethod=1 +r.ReflectionMethod=1 +r.Shadow.Virtual.Enable=1 +r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True +r.DefaultFeature.LocalExposure.HighlightContrastScale=0.8 +r.DefaultFeature.LocalExposure.ShadowContrastScale=0.8 +r.SkinCache.CompileShaders=True +r.RayTracing.RayTracingProxies.ProjectEnabled=True + +[/Script/WorldPartitionEditor.WorldPartitionEditorSettings] +CommandletClass=Class'/Script/UnrealEd.WorldPartitionConvertCommandlet' + +[/Script/Engine.UserInterfaceSettings] +bAuthorizeAutomaticWidgetVariableCreation=False +FontDPIPreset=Standard +FontDPI=72 + +[/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings] +bEnablePlugin=True +bAllowNetworkConnection=True +SecurityToken=FC2469BA449F3D6AFB81E9A6E6FCBE4B +bIncludeInShipping=False +bAllowExternalStartInShipping=False +bCompileAFSProject=False +bUseCompression=False +bLogFiles=False +bReportStats=False +ConnectionType=USBOnly +bUseManualIPAddress=False +ManualIPAddress= + diff --git a/sdks/unreal/tests/TestViewPkClient/Config/DefaultGame.ini b/sdks/unreal/tests/TestViewPkClient/Config/DefaultGame.ini new file mode 100644 index 00000000000..4754b466b8d --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Config/DefaultGame.ini @@ -0,0 +1,5 @@ +[/Script/EngineSettings.GeneralProjectSettings] +ProjectID=9B36AE4A4DF62F180A496F93BE6813D9 + +[/Script/CommonUI.CommonUISettings] +CommonButtonAcceptKeyHandling=TriggerClick diff --git a/sdks/unreal/tests/TestViewPkClient/Config/DefaultInput.ini b/sdks/unreal/tests/TestViewPkClient/Config/DefaultInput.ini new file mode 100644 index 00000000000..a72fda22b24 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Config/DefaultInput.ini @@ -0,0 +1,85 @@ +[/Script/Engine.InputSettings] +-AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) +-AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) +-AxisConfig=(AxisKeyName="Mouse2D",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) ++AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Mouse2D",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MouseWheelAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_LeftTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_RightTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_Special_Left_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_Special_Left_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) +bAltEnterTogglesFullscreen=True +bF11TogglesFullscreen=True +bUseMouseForTouch=False +bEnableMouseSmoothing=True +bEnableFOVScaling=True +bCaptureMouseOnLaunch=True +bEnableLegacyInputScales=True +bEnableMotionControls=True +bFilterInputByPlatformUser=False +bShouldFlushPressedKeysOnViewportFocusLost=True +bEnableDynamicComponentInputBinding=True +bAlwaysShowTouchInterface=False +bShowConsoleOnFourFingerTap=True +bEnableGestureRecognizer=False +bUseAutocorrect=False +DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown +DefaultViewportMouseLockMode=LockOnCapture +FOVScale=0.011110 +DoubleClickTime=0.200000 +DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput +DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent +DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.DefaultVirtualJoysticks +-ConsoleKeys=Tilde ++ConsoleKeys=Tilde + diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient.Target.cs b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient.Target.cs new file mode 100644 index 00000000000..32553925636 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient.Target.cs @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class TestViewPkClientTarget : TargetRules +{ + public TestViewPkClientTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Game; + DefaultBuildSettings = BuildSettingsVersion.V5; + + ExtraModuleNames.AddRange( new string[] { "TestViewPkClient" } ); + } +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp new file mode 100644 index 00000000000..42359ff702c --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -0,0 +1,636 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/SpacetimeDBClient.g.h" +#include "DBCache/WithBsatn.h" +#include "BSATN/UEBSATNHelpers.h" +#include "ModuleBindings/Tables/AllViewPkPlayersTable.g.h" +#include "ModuleBindings/Tables/SenderViewPkPlayersATable.g.h" +#include "ModuleBindings/Tables/SenderViewPkPlayersBTable.g.h" +#include "ModuleBindings/Tables/ViewPkMembershipTable.g.h" +#include "ModuleBindings/Tables/ViewPkMembershipSecondaryTable.g.h" +#include "ModuleBindings/Tables/ViewPkPlayerTable.g.h" + +UDbConnection::UDbConnection(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) +{ + Db = ObjectInitializer.CreateDefaultSubobject(this, TEXT("RemoteTables")); + Db->Initialize(); + + Reducers = ObjectInitializer.CreateDefaultSubobject(this, TEXT("RemoteReducers")); + Reducers->Conn = this; + + Procedures = ObjectInitializer.CreateDefaultSubobject(this, TEXT("RemoteProcedures")); + Procedures->Conn = this; + + RegisterTable(TEXT("all_view_pk_players"), Db->AllViewPkPlayers); + RegisterTable(TEXT("sender_view_pk_players_a"), Db->SenderViewPkPlayersA); + RegisterTable(TEXT("sender_view_pk_players_b"), Db->SenderViewPkPlayersB); + RegisterTable(TEXT("view_pk_membership"), Db->ViewPkMembership); + RegisterTable(TEXT("view_pk_membership_secondary"), Db->ViewPkMembershipSecondary); + RegisterTable(TEXT("view_pk_player"), Db->ViewPkPlayer); +} + +FContextBase::FContextBase(UDbConnection* InConn) +{ + Db = InConn->Db; + Reducers = InConn->Reducers; + Procedures = InConn->Procedures; + Conn = InConn; +} +bool FContextBase::IsActive() const +{ + return Conn->IsActive(); +} +void FContextBase::Disconnect() +{ + Conn->Disconnect(); +} +USubscriptionBuilder* FContextBase::SubscriptionBuilder() +{ + return Conn->SubscriptionBuilder(); +} +bool FContextBase::TryGetIdentity(FSpacetimeDBIdentity& OutIdentity) const +{ + return Conn->TryGetIdentity(OutIdentity); +} +FSpacetimeDBConnectionId FContextBase::GetConnectionId() const +{ + return Conn->GetConnectionId(); +} + +void URemoteTables::Initialize() +{ + + /** Creating tables */ + AllViewPkPlayers = NewObject(this); + SenderViewPkPlayersA = NewObject(this); + SenderViewPkPlayersB = NewObject(this); + ViewPkMembership = NewObject(this); + ViewPkMembershipSecondary = NewObject(this); + ViewPkPlayer = NewObject(this); + /**/ + + /** Initialization */ + AllViewPkPlayers->PostInitialize(); + SenderViewPkPlayersA->PostInitialize(); + SenderViewPkPlayersB->PostInitialize(); + ViewPkMembership->PostInitialize(); + ViewPkMembershipSecondary->PostInitialize(); + ViewPkPlayer->PostInitialize(); + /**/ +} + +void URemoteReducers::InsertViewPkMembership(const uint64 Id, const uint64 PlayerId) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + FInsertViewPkMembershipArgs ReducerArgs(Id, PlayerId); + const uint32 RequestId = Conn->CallReducerTyped(TEXT("insert_view_pk_membership"), ReducerArgs); + if (RequestId != 0) { Conn->RegisterPendingTypedReducer(RequestId, FReducer::InsertViewPkMembership(ReducerArgs)); } +} + +bool URemoteReducers::InvokeInsertViewPkMembership(const FReducerEventContext& Context, const UInsertViewPkMembershipReducer* Args) +{ + if (!OnInsertViewPkMembership.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertViewPkMembership")); + } + return false; + } + + OnInsertViewPkMembership.Broadcast(Context, Args->Id, Args->PlayerId); + return true; +} + +bool URemoteReducers::InvokeInsertViewPkMembershipWithArgs(const FReducerEventContext& Context, const FInsertViewPkMembershipArgs& Args) +{ + if (!OnInsertViewPkMembership.IsBound()) + { + if (InternalOnUnhandledReducerError.IsBound()) + { + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertViewPkMembership")); + } + return false; + } + + OnInsertViewPkMembership.Broadcast(Context, Args.Id, Args.PlayerId); + return true; +} + +void URemoteReducers::InsertViewPkMembershipSecondary(const uint64 Id, const uint64 PlayerId) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + FInsertViewPkMembershipSecondaryArgs ReducerArgs(Id, PlayerId); + const uint32 RequestId = Conn->CallReducerTyped(TEXT("insert_view_pk_membership_secondary"), ReducerArgs); + if (RequestId != 0) { Conn->RegisterPendingTypedReducer(RequestId, FReducer::InsertViewPkMembershipSecondary(ReducerArgs)); } +} + +bool URemoteReducers::InvokeInsertViewPkMembershipSecondary(const FReducerEventContext& Context, const UInsertViewPkMembershipSecondaryReducer* Args) +{ + if (!OnInsertViewPkMembershipSecondary.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertViewPkMembershipSecondary")); + } + return false; + } + + OnInsertViewPkMembershipSecondary.Broadcast(Context, Args->Id, Args->PlayerId); + return true; +} + +bool URemoteReducers::InvokeInsertViewPkMembershipSecondaryWithArgs(const FReducerEventContext& Context, const FInsertViewPkMembershipSecondaryArgs& Args) +{ + if (!OnInsertViewPkMembershipSecondary.IsBound()) + { + if (InternalOnUnhandledReducerError.IsBound()) + { + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertViewPkMembershipSecondary")); + } + return false; + } + + OnInsertViewPkMembershipSecondary.Broadcast(Context, Args.Id, Args.PlayerId); + return true; +} + +void URemoteReducers::InsertViewPkPlayer(const uint64 Id, const FString& Name) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + FInsertViewPkPlayerArgs ReducerArgs(Id, Name); + const uint32 RequestId = Conn->CallReducerTyped(TEXT("insert_view_pk_player"), ReducerArgs); + if (RequestId != 0) { Conn->RegisterPendingTypedReducer(RequestId, FReducer::InsertViewPkPlayer(ReducerArgs)); } +} + +bool URemoteReducers::InvokeInsertViewPkPlayer(const FReducerEventContext& Context, const UInsertViewPkPlayerReducer* Args) +{ + if (!OnInsertViewPkPlayer.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertViewPkPlayer")); + } + return false; + } + + OnInsertViewPkPlayer.Broadcast(Context, Args->Id, Args->Name); + return true; +} + +bool URemoteReducers::InvokeInsertViewPkPlayerWithArgs(const FReducerEventContext& Context, const FInsertViewPkPlayerArgs& Args) +{ + if (!OnInsertViewPkPlayer.IsBound()) + { + if (InternalOnUnhandledReducerError.IsBound()) + { + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for InsertViewPkPlayer")); + } + return false; + } + + OnInsertViewPkPlayer.Broadcast(Context, Args.Id, Args.Name); + return true; +} + +void URemoteReducers::UpdateViewPkPlayer(const uint64 Id, const FString& Name) +{ + if (!Conn) + { + UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null")); + return; + } + + FUpdateViewPkPlayerArgs ReducerArgs(Id, Name); + const uint32 RequestId = Conn->CallReducerTyped(TEXT("update_view_pk_player"), ReducerArgs); + if (RequestId != 0) { Conn->RegisterPendingTypedReducer(RequestId, FReducer::UpdateViewPkPlayer(ReducerArgs)); } +} + +bool URemoteReducers::InvokeUpdateViewPkPlayer(const FReducerEventContext& Context, const UUpdateViewPkPlayerReducer* Args) +{ + if (!OnUpdateViewPkPlayer.IsBound()) + { + // Handle unhandled reducer error + if (InternalOnUnhandledReducerError.IsBound()) + { + // TODO: Check Context.Event.Status for Failed/OutOfEnergy cases + // For now, just broadcast any error + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for UpdateViewPkPlayer")); + } + return false; + } + + OnUpdateViewPkPlayer.Broadcast(Context, Args->Id, Args->Name); + return true; +} + +bool URemoteReducers::InvokeUpdateViewPkPlayerWithArgs(const FReducerEventContext& Context, const FUpdateViewPkPlayerArgs& Args) +{ + if (!OnUpdateViewPkPlayer.IsBound()) + { + if (InternalOnUnhandledReducerError.IsBound()) + { + InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for UpdateViewPkPlayer")); + } + return false; + } + + OnUpdateViewPkPlayer.Broadcast(Context, Args.Id, Args.Name); + return true; +} + +void UDbConnection::PostInitProperties() +{ + Super::PostInitProperties(); + + // Connect OnUnhandledReducerError to Reducers.InternalOnUnhandledReducerError + if (Reducers) + { + Reducers->InternalOnUnhandledReducerError.AddDynamic(this, &UDbConnection::OnUnhandledReducerErrorHandler); + } + + // Connect OnUnhandledProcedureError to Procedures.InternalOnUnhandledProcedureError + if (Procedures) + { + Procedures->InternalOnUnhandledProcedureError.AddDynamic(this, &UDbConnection::OnUnhandledProcedureErrorHandler); + } +} + +UFUNCTION() +void UDbConnection::OnUnhandledReducerErrorHandler(const FReducerEventContext& Context, const FString& Error) +{ + if (OnUnhandledReducerError.IsBound()) + { + OnUnhandledReducerError.Broadcast(Context, Error); + } +} + +UFUNCTION() +void UDbConnection::OnUnhandledProcedureErrorHandler(const FProcedureEventContext& Context, const FString& Error) +{ + if (OnUnhandledProcedureError.IsBound()) + { + OnUnhandledProcedureError.Broadcast(Context, Error); + } +} + +void UDbConnection::RegisterPendingTypedReducer(uint32 RequestId, FReducer Reducer) +{ + Reducer.RequestId = RequestId; + PendingTypedReducers.Add(RequestId, MoveTemp(Reducer)); +} + +bool UDbConnection::TryGetPendingTypedReducer(uint32 RequestId, FReducer& OutReducer) const +{ + if (const FReducer* Found = PendingTypedReducers.Find(RequestId)) + { + OutReducer = *Found; + return true; + } + return false; +} + +bool UDbConnection::TryTakePendingTypedReducer(uint32 RequestId, FReducer& OutReducer) +{ + if (FReducer* Found = PendingTypedReducers.Find(RequestId)) + { + OutReducer = *Found; + PendingTypedReducers.Remove(RequestId); + return true; + } + return false; +} + +void UDbConnection::ReducerEvent(const FReducerEvent& Event) +{ + if (!Reducers) { return; } + + FReducer DecodedReducer; + if (!TryTakePendingTypedReducer(Event.RequestId, DecodedReducer)) + { + const FString ErrorMessage = FString::Printf(TEXT("Reducer result for unknown request_id %u"), Event.RequestId); + HandleProtocolViolation(ErrorMessage); + return; + } + + FTestViewPkClientReducerEvent ReducerEvent; + ReducerEvent.CallerConnectionId = Event.CallerConnectionId; + ReducerEvent.CallerIdentity = Event.CallerIdentity; + ReducerEvent.EnergyConsumed = Event.EnergyConsumed; + ReducerEvent.Status = Event.Status; + ReducerEvent.Timestamp = Event.Timestamp; + ReducerEvent.Reducer = DecodedReducer; + + FReducerEventContext Context(this, ReducerEvent); + + // Dispatch by typed reducer metadata + const FString& ReducerName = ReducerEvent.Reducer.ReducerName; + + if (ReducerName == TEXT("insert_view_pk_membership")) + { + FInsertViewPkMembershipArgs Args = ReducerEvent.Reducer.GetAsInsertViewPkMembership(); + Reducers->InvokeInsertViewPkMembershipWithArgs(Context, Args); + return; + } + if (ReducerName == TEXT("insert_view_pk_membership_secondary")) + { + FInsertViewPkMembershipSecondaryArgs Args = ReducerEvent.Reducer.GetAsInsertViewPkMembershipSecondary(); + Reducers->InvokeInsertViewPkMembershipSecondaryWithArgs(Context, Args); + return; + } + if (ReducerName == TEXT("insert_view_pk_player")) + { + FInsertViewPkPlayerArgs Args = ReducerEvent.Reducer.GetAsInsertViewPkPlayer(); + Reducers->InvokeInsertViewPkPlayerWithArgs(Context, Args); + return; + } + if (ReducerName == TEXT("update_view_pk_player")) + { + FUpdateViewPkPlayerArgs Args = ReducerEvent.Reducer.GetAsUpdateViewPkPlayer(); + Reducers->InvokeUpdateViewPkPlayerWithArgs(Context, Args); + return; + } + + UE_LOG(LogTemp, Warning, TEXT("Unknown reducer: %s"), *ReducerName); +} + +void UDbConnection::ReducerEventFailed(const FReducerEvent& Event, const FString ErrorMessage) +{ + if (!Reducers) { return; } + + FTestViewPkClientReducerEvent ReducerEvent; + ReducerEvent.CallerConnectionId = Event.CallerConnectionId; + ReducerEvent.CallerIdentity = Event.CallerIdentity; + ReducerEvent.EnergyConsumed = Event.EnergyConsumed; + ReducerEvent.Status = Event.Status; + ReducerEvent.Timestamp = Event.Timestamp; + + FReducerEventContext Context(this, ReducerEvent); + + if (Reducers->InternalOnUnhandledReducerError.IsBound()) + { + Reducers->InternalOnUnhandledReducerError.Broadcast(Context, ErrorMessage); + } +} + +void UDbConnection::ProcedureEventFailed(const FProcedureEvent& Event, const FString ErrorMessage) +{ + if (!Procedures) { return; } + + FTestViewPkClientProcedureEvent ProcedureEvent; + ProcedureEvent.Status = FSpacetimeDBProcedureStatus::FromStatus(Event.Status); + ProcedureEvent.Timestamp = Event.Timestamp; + + FProcedureEventContext Context(this, ProcedureEvent); + + if (Procedures->InternalOnUnhandledProcedureError.IsBound()) + { + Procedures->InternalOnUnhandledProcedureError.Broadcast(Context, ErrorMessage); + } +} + +UDbConnectionBuilder* UDbConnection::Builder() +{ + return NewObject(); +} +// Added for creating subscriptions +USubscriptionBuilder* UDbConnection::SubscriptionBuilder() +{ + USubscriptionBuilder* Builder = NewObject(this); + Builder->Conn = this; + return Builder; +} +FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) +{ + OnAppliedDelegateInternal = Callback; + return *this; +} +FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnError(FOnSubscriptionError Callback) +{ + OnErrorDelegateInternal = Callback; + return *this; +} +USubscriptionHandle* FTypedSubscriptionBuilder::Subscribe() +{ + if (!Conn) + { + return nullptr; + } + USubscriptionBuilder* Builder = Conn->SubscriptionBuilder(); + Builder->OnApplied(OnAppliedDelegateInternal); + Builder->OnError(OnErrorDelegateInternal); + return Builder->Subscribe(Sql); +} +USubscriptionBuilder* USubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) +{ + OnAppliedDelegateInternal = Callback; + return this; +} +USubscriptionBuilder* USubscriptionBuilder::OnError(FOnSubscriptionError Callback) +{ + OnErrorDelegateInternal = Callback; + return this; +} +USubscriptionHandle* USubscriptionBuilder::Subscribe(const TArray& SQL) +{ + USubscriptionHandle* Handle = NewObject(); + + // Store user callbacks on the handle + Handle->Conn = Conn; + Handle->OnAppliedDelegate = OnAppliedDelegateInternal; + Handle->OnErrorDelegate = OnErrorDelegateInternal; + + // Bind forwarding functions that will convert base contexts + FSubscriptionEventDelegate BaseApplied; + BaseApplied.BindUFunction(Handle, TEXT("ForwardOnApplied")); + OnAppliedBase(BaseApplied); + + FSubscriptionErrorDelegate BaseError; + BaseError.BindUFunction(Handle, TEXT("ForwardOnError")); + OnErrorBase(BaseError); + + SubscribeBase(SQL, Handle); + if (Conn) + { + Conn->StartSubscription(Handle); + } + return Handle; +} +USubscriptionHandle* USubscriptionBuilder::SubscribeToAllTables() +{ + return Subscribe(FQueryBuilder::AllTablesSqlQueries()); +} + +USubscriptionHandle::USubscriptionHandle(UDbConnection* InConn) +{ + Conn = InConn; +} + +void USubscriptionHandle::ForwardOnApplied(const FSubscriptionEventContextBase& BaseCtx) +{ + if (OnAppliedDelegate.IsBound()) + { + FSubscriptionEventContext Ctx(Conn); + OnAppliedDelegate.Execute(Ctx); + } +} + +void USubscriptionHandle::ForwardOnError(const FErrorContextBase& BaseCtx) +{ + if (OnErrorDelegate.IsBound()) + { + FErrorContext Ctx(Conn, BaseCtx.Error); + OnErrorDelegate.Execute(Ctx); + } +} + + +// Cast from parent to child class +UDbConnectionBuilder* UDbConnectionBuilder::WithUri(const FString& InUri) +{ + return Cast(WithUriBase(InUri)); +} +UDbConnectionBuilder* UDbConnectionBuilder::WithDatabaseName(const FString& InName) +{ + return Cast(WithDatabaseNameBase(InName)); +} +UDbConnectionBuilder* UDbConnectionBuilder::WithToken(const FString& InToken) +{ + return Cast(WithTokenBase(InToken)); +} +UDbConnectionBuilder* UDbConnectionBuilder::WithCompression(const ESpacetimeDBCompression& InCompression) +{ + return Cast(WithCompressionBase(InCompression)); +} +UDbConnectionBuilder* UDbConnectionBuilder::OnConnect(FOnConnectDelegate Callback) +{ + OnConnectDelegateInternal = Callback; + return this; +} +UDbConnectionBuilder* UDbConnectionBuilder::OnConnectError(FOnConnectErrorDelegate Callback) +{ + return Cast(OnConnectErrorBase(Callback)); +} +UDbConnectionBuilder* UDbConnectionBuilder::OnDisconnect(FOnDisconnectDelegate Callback) +{ + OnDisconnectDelegateInternal = Callback; + return this; +} +UDbConnection* UDbConnectionBuilder::Build() +{ + UDbConnection* Connection = NewObject(); + + // Store delegates on the connection for later use + Connection->OnConnectDelegate = OnConnectDelegateInternal; + Connection->OnDisconnectDelegate = OnDisconnectDelegateInternal; + + // Wrap delegates so the base builder can bind them + FOnConnectBaseDelegate BaseConnect; + BaseConnect.BindUFunction(Connection, TEXT("ForwardOnConnect")); + Connection->SetOnConnectDelegate(BaseConnect); + OnConnectBase(BaseConnect); + + FOnDisconnectBaseDelegate BaseDisconnect; + BaseDisconnect.BindUFunction(Connection, TEXT("ForwardOnDisconnect")); + Connection->SetOnDisconnectDelegate(BaseDisconnect); + OnDisconnectBase(BaseDisconnect); + + return Cast(BuildConnection(Connection)); +} +void UDbConnection::ForwardOnConnect(UDbConnectionBase* BaseConnection, FSpacetimeDBIdentity InIdentity, const FString& InToken) +{ + if (OnConnectDelegate.IsBound()) + { + OnConnectDelegate.Execute(this, Identity, Token); + } +} +void UDbConnection::ForwardOnDisconnect(UDbConnectionBase* BaseConnection, const FString& Error) +{ + PendingTypedReducers.Empty(); + if (OnDisconnectDelegate.IsBound()) + { + OnDisconnectDelegate.Execute(this, Error); + } +} + + +void UDbConnection::DbUpdate(const FDatabaseUpdateType& Update, const FSpacetimeDBEvent& Event) +{ + FTestViewPkClientEvent BaseEvent; + BaseEvent.Tag = Event.Tag; + + switch (Event.Tag) + { + case ESpacetimeDBEventTag::Reducer: + { + FReducerEvent ReducerEvent = Event.GetAsReducer(); + FReducer Reducer; + if (!TryGetPendingTypedReducer(ReducerEvent.RequestId, Reducer)) + { + const FString ErrorMessage = FString::Printf(TEXT("Reducer result for unknown request_id %u"), ReducerEvent.RequestId); + HandleProtocolViolation(ErrorMessage); + return; + } + BaseEvent = FTestViewPkClientEvent::Reducer(Reducer); + break; + } + + case ESpacetimeDBEventTag::SubscribeApplied: + BaseEvent = FTestViewPkClientEvent::SubscribeApplied(Event.GetAsSubscribeApplied()); + break; + + case ESpacetimeDBEventTag::UnsubscribeApplied: + BaseEvent = FTestViewPkClientEvent::UnsubscribeApplied(Event.GetAsUnsubscribeApplied()); + break; + + case ESpacetimeDBEventTag::Disconnected: + BaseEvent = FTestViewPkClientEvent::Disconnected(Event.GetAsDisconnected()); + break; + + case ESpacetimeDBEventTag::Transaction: + BaseEvent = FTestViewPkClientEvent::Transaction(Event.GetAsTransaction()); + break; + + case ESpacetimeDBEventTag::SubscribeError: + BaseEvent = FTestViewPkClientEvent::SubscribeError(Event.GetAsSubscribeError()); + break; + + case ESpacetimeDBEventTag::UnknownTransaction: + BaseEvent = FTestViewPkClientEvent::UnknownTransaction(Event.GetAsUnknownTransaction()); + break; + + default: + break; + } + + FEventContext Context(this, BaseEvent); + // Populate typed reducer args for convenience in table handlers + + ApplyRegisteredTableUpdates(Update, &Context); +} + diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/AllViewPkPlayersTable.g.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/AllViewPkPlayersTable.g.cpp new file mode 100644 index 00000000000..24c0c58e9f2 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/AllViewPkPlayersTable.g.cpp @@ -0,0 +1,42 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/AllViewPkPlayersTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UAllViewPkPlayersTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> AllViewPkPlayersTable = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff UAllViewPkPlayersTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FViewPkPlayerType& Row) + { + return Row.Id; + } + ); + + return Diff; +} + +int32 UAllViewPkPlayersTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UAllViewPkPlayersTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/SenderViewPkPlayersATable.g.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/SenderViewPkPlayersATable.g.cpp new file mode 100644 index 00000000000..5d772b8f853 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/SenderViewPkPlayersATable.g.cpp @@ -0,0 +1,42 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/SenderViewPkPlayersATable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void USenderViewPkPlayersATable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> SenderViewPkPlayersATable = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff USenderViewPkPlayersATable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FViewPkPlayerType& Row) + { + return Row.Id; + } + ); + + return Diff; +} + +int32 USenderViewPkPlayersATable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray USenderViewPkPlayersATable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/SenderViewPkPlayersBTable.g.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/SenderViewPkPlayersBTable.g.cpp new file mode 100644 index 00000000000..a1d8d919897 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/SenderViewPkPlayersBTable.g.cpp @@ -0,0 +1,42 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/SenderViewPkPlayersBTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void USenderViewPkPlayersBTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> SenderViewPkPlayersBTable = Data->GetOrAdd(TableName); + + /***/ +} + +FTableAppliedDiff USenderViewPkPlayersBTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FViewPkPlayerType& Row) + { + return Row.Id; + } + ); + + return Diff; +} + +int32 USenderViewPkPlayersBTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray USenderViewPkPlayersBTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/ViewPkMembershipSecondaryTable.g.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/ViewPkMembershipSecondaryTable.g.cpp new file mode 100644 index 00000000000..cb8a0acf957 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/ViewPkMembershipSecondaryTable.g.cpp @@ -0,0 +1,60 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/ViewPkMembershipSecondaryTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UViewPkMembershipSecondaryTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> ViewPkMembershipSecondaryTable = Data->GetOrAdd(TableName); + ViewPkMembershipSecondaryTable->AddUniqueConstraint("id", [](const FViewPkMembershipSecondaryType& Row) -> const uint64& { + return Row.Id; }); + + Id = NewObject(this); + Id->SetCache(ViewPkMembershipSecondaryTable); + + // Register a new multi-key B-Tree index named "player_id" on the ViewPkMembershipSecondaryTable. + ViewPkMembershipSecondaryTable->AddMultiKeyBTreeIndex>( + TEXT("player_id"), + [](const FViewPkMembershipSecondaryType& Row) + { + // This tuple is stored in the B-Tree index for fast composite key lookups. + return MakeTuple(Row.PlayerId); + } + ); + + PlayerId = NewObject(this); + PlayerId->SetCache(ViewPkMembershipSecondaryTable); + + /***/ +} + +FTableAppliedDiff UViewPkMembershipSecondaryTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FViewPkMembershipSecondaryType& Row) + { + return Row.Id; + } + ); + + return Diff; +} + +int32 UViewPkMembershipSecondaryTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UViewPkMembershipSecondaryTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/ViewPkMembershipTable.g.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/ViewPkMembershipTable.g.cpp new file mode 100644 index 00000000000..630ba663912 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/ViewPkMembershipTable.g.cpp @@ -0,0 +1,60 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/ViewPkMembershipTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UViewPkMembershipTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> ViewPkMembershipTable = Data->GetOrAdd(TableName); + ViewPkMembershipTable->AddUniqueConstraint("id", [](const FViewPkMembershipType& Row) -> const uint64& { + return Row.Id; }); + + Id = NewObject(this); + Id->SetCache(ViewPkMembershipTable); + + // Register a new multi-key B-Tree index named "player_id" on the ViewPkMembershipTable. + ViewPkMembershipTable->AddMultiKeyBTreeIndex>( + TEXT("player_id"), + [](const FViewPkMembershipType& Row) + { + // This tuple is stored in the B-Tree index for fast composite key lookups. + return MakeTuple(Row.PlayerId); + } + ); + + PlayerId = NewObject(this); + PlayerId->SetCache(ViewPkMembershipTable); + + /***/ +} + +FTableAppliedDiff UViewPkMembershipTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FViewPkMembershipType& Row) + { + return Row.Id; + } + ); + + return Diff; +} + +int32 UViewPkMembershipTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UViewPkMembershipTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/ViewPkPlayerTable.g.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/ViewPkPlayerTable.g.cpp new file mode 100644 index 00000000000..45cebcda47f --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/Tables/ViewPkPlayerTable.g.cpp @@ -0,0 +1,47 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#include "ModuleBindings/Tables/ViewPkPlayerTable.g.h" +#include "DBCache/UniqueIndex.h" +#include "DBCache/BTreeUniqueIndex.h" +#include "DBCache/ClientCache.h" +#include "DBCache/TableCache.h" + +void UViewPkPlayerTable::PostInitialize() +{ + /** Client cache init and setting up indexes*/ + Data = MakeShared>(); + + TSharedPtr> ViewPkPlayerTable = Data->GetOrAdd(TableName); + ViewPkPlayerTable->AddUniqueConstraint("id", [](const FViewPkPlayerType& Row) -> const uint64& { + return Row.Id; }); + + Id = NewObject(this); + Id->SetCache(ViewPkPlayerTable); + + /***/ +} + +FTableAppliedDiff UViewPkPlayerTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FViewPkPlayerType& Row) + { + return Row.Id; + } + ); + + return Diff; +} + +int32 UViewPkPlayerTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UViewPkPlayerTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/CommonTestFunctions.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/CommonTestFunctions.cpp new file mode 100644 index 00000000000..521828acf11 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/CommonTestFunctions.cpp @@ -0,0 +1,171 @@ +#include "Tests/CommonTestFunctions.h" + +void UTestHelperDelegates::HandleConnect(UDbConnection* Conn, FSpacetimeDBIdentity Identity, const FString& Token) +{ + if (OnConnect) + { + OnConnect(Conn, Identity, Token); + } +} + +void UTestHelperDelegates::HandleConnectError(UDbConnection* Conn, const FString& Error) +{ + if (OnConnectError) + { + OnConnectError(Conn, Error); + } +} + +void UTestHelperDelegates::HandleDisconnect(UDbConnection* Conn, const FString& Error) +{ + if (OnDisconnect) + { + OnDisconnect(Conn, Error); + } +} + +void UTestHelperDelegates::HandleSubscriptionApplied(FSubscriptionEventContext Ctx) +{ + if (OnSubscriptionApplied) + { + OnSubscriptionApplied(Ctx); + } +} + +void UTestHelperDelegates::HandleSubscriptionError(FErrorContext Ctx) +{ + if (OnSubscriptionError) + { + OnSubscriptionError(Ctx); + } +} + +UDbConnection* ConnectThen( + TSharedPtr Counter, + const FString& TestName, + TFunction Callback) +{ + FString DbName; + FString DbNameError; + if (!GetDbName(DbName, DbNameError)) + { + return nullptr; + } + + UCredentials::Init(TestName); + + const FString ConnectTestName = FString::Printf(TEXT("on_connect_%s"), *TestName); + Counter->Register(ConnectTestName); + + UTestHelperDelegates* TestHelper = NewObject(); + TestHelper->AddToRoot(); + + TestHelper->OnConnect = [Counter, Callback, ConnectTestName](UDbConnection* Conn, FSpacetimeDBIdentity, const FString&) + { + Callback(Conn); + Counter->MarkSuccess(ConnectTestName); + }; + TestHelper->OnConnectError = [Counter, ConnectTestName](UDbConnection*, const FString& Error) + { + Counter->MarkFailure(ConnectTestName, FString::Printf(TEXT("Connect error: %s"), *Error)); + }; + TestHelper->OnDisconnect = [Counter, ConnectTestName](UDbConnection*, const FString& Error) + { + Counter->MarkFailure(ConnectTestName, FString::Printf(TEXT("Disconnected: %s"), *Error)); + }; + + FOnConnectDelegate ConnectDelegate; + BIND_DELEGATE_SAFE(ConnectDelegate, TestHelper, UTestHelperDelegates, HandleConnect); + + FOnDisconnectDelegate DisconnectDelegate; + BIND_DELEGATE_SAFE(DisconnectDelegate, TestHelper, UTestHelperDelegates, HandleDisconnect); + + FOnConnectErrorDelegate ErrorDelegate; + BIND_DELEGATE_SAFE(ErrorDelegate, TestHelper, UTestHelperDelegates, HandleConnectError); + + UDbConnection* Conn = UDbConnection::Builder() + ->WithUri(TEXT("localhost:3000")) + ->WithDatabaseName(DbName) + ->OnConnect(ConnectDelegate) + ->OnDisconnect(DisconnectDelegate) + ->OnConnectError(ErrorDelegate) + ->Build(); + + if (Conn) + { + Conn->SetAutoTicking(true); + Conn->AddToRoot(); + } + + return Conn; +} + +bool GetDbName(FString& DBName, FString& Error) +{ + const FString DbNameEnv = FPlatformMisc::GetEnvironmentVariable(TEXT("SPACETIME_SDK_TEST_DB_NAME")); + if (!DbNameEnv.IsEmpty()) + { + DBName = DbNameEnv; + return true; + } + + FString CmdValue; + if (FParse::Value(FCommandLine::Get(), TEXT("-SpacetimeDbName="), CmdValue)) + { + DBName = CmdValue; + return true; + } + + Error = TEXT("No DB name. Pass -SpacetimeDbName= or set SPACETIME_SDK_TEST_DB_NAME."); + return false; +} + +bool ValidateParameterConfig(FAutomationTestBase* Test) +{ + FString DbName; + FString DbNameError; + if (!GetDbName(DbName, DbNameError)) + { + Test->AddError(DbNameError); + return false; + } + return true; +} + +bool ReportTestResult(FAutomationTestBase& Test, const FString& TestName, TSharedPtr Counter, bool bTimedOut) +{ + bool bHasFailure = false; + + for (const FString& Msg : Counter->GetFailures()) + { + TESTLOG_FAIL(Test, TEXT("Operation - %s"), *Msg); + bHasFailure = true; + } + for (const FString& Msg : Counter->GetSuccesses()) + { + TESTLOG_SUCCESS(Test, TEXT("Operation - %s"), *Msg); + } + + if (bTimedOut) + { + TESTLOG_FAIL(Test, TEXT("Timed out waiting for operation")); + bHasFailure = true; + } + if (Counter->IsAborted()) + { + TESTLOG_FAIL(Test, TEXT("Test aborted due to precondition failure")); + bHasFailure = true; + } + + if (!bHasFailure) + { + TESTLOG_SUCCESS(Test, TEXT("Test Success")); + Test.TestTrue(*TestName, true); + } + else + { + TESTLOG_FAIL(Test, TEXT("Test failed")); + } + + return !bHasFailure; +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/SpacetimeFullClientTests.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/SpacetimeFullClientTests.cpp new file mode 100644 index 00000000000..555950a68a7 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/SpacetimeFullClientTests.cpp @@ -0,0 +1,220 @@ +#include "Tests/SpacetimeFullClientTests.h" + +#include "Tests/CommonTestFunctions.h" + +#include "ModuleBindings/SpacetimeDBClient.g.h" +#include "ModuleBindings/Tables/AllViewPkPlayersTable.g.h" +#include "ModuleBindings/Tables/SenderViewPkPlayersATable.g.h" + +namespace +{ +static FString ToFString(const std::string& InSql) +{ + return FString(UTF8_TO_TCHAR(InSql.c_str())); +} + +class FWaitForTestCounter : public IAutomationLatentCommand +{ +public: + FWaitForTestCounter(FAutomationTestBase& InTest, const FString& InTestName, TSharedPtr InCounter, double InStartTime) + : Test(InTest) + , TestName(InTestName) + , Counter(MoveTemp(InCounter)) + , StartTime(InStartTime) + {} + + virtual bool Update() override + { + const double Timeout = 90.0; + const bool bStopped = Counter->IsAborted() || Counter->IsComplete() || (FPlatformTime::Seconds() - StartTime > Timeout); + const bool bTimedOut = (FPlatformTime::Seconds() - StartTime > Timeout); + + if (bStopped) + { + ReportTestResult(Test, TestName, Counter, bTimedOut); + } + + return bStopped; + } + +private: + FAutomationTestBase& Test; + FString TestName; + TSharedPtr Counter; + double StartTime = 0.0; +}; +} + +bool FViewPkQueryBuilderDirectSourcesTest::RunTest(const FString& Parameters) +{ + FQueryBuilder Q; + + TestEqual( + TEXT("all_view_pk_players sql"), + ToFString(Q.From.AllViewPkPlayers().into_sql()), + TEXT("SELECT * FROM \"all_view_pk_players\"") + ); + TestEqual( + TEXT("sender_view_pk_players_a sql"), + ToFString(Q.From.SenderViewPkPlayersA().into_sql()), + TEXT("SELECT * FROM \"sender_view_pk_players_a\"") + ); + TestEqual( + TEXT("sender_view_pk_players_b sql"), + ToFString(Q.From.SenderViewPkPlayersB().into_sql()), + TEXT("SELECT * FROM \"sender_view_pk_players_b\"") + ); + TestEqual( + TEXT("view_pk_membership sql"), + ToFString(Q.From.ViewPkMembership().into_sql()), + TEXT("SELECT * FROM \"view_pk_membership\"") + ); + TestEqual( + TEXT("view_pk_membership_secondary sql"), + ToFString(Q.From.ViewPkMembershipSecondary().into_sql()), + TEXT("SELECT * FROM \"view_pk_membership_secondary\"") + ); + TestEqual( + TEXT("view_pk_player sql"), + ToFString(Q.From.ViewPkPlayer().into_sql()), + TEXT("SELECT * FROM \"view_pk_player\"") + ); + + FTypedSubscriptionBuilder Typed(nullptr); + Typed.AddQuery([](const FQueryBuilder& Query) + { + return Query.From.AllViewPkPlayers(); + }).AddQuery([](const FQueryBuilder& Query) + { + return Query.From.ViewPkPlayer().Where([](const FViewPkPlayerCols& Cols) + { + return Cols.Id.Eq(static_cast(1)); + }); + }); + + TestTrue(TEXT("typed query builder accepted pk view sources"), true); + return true; +} + +bool FViewPkQueryBuilderSemijoinTest::RunTest(const FString& Parameters) +{ + FQueryBuilder Q; + + const FString MembershipJoinSql = ToFString( + Q.From.ViewPkMembership().RightSemijoin(Q.From.AllViewPkPlayers(), [](const FViewPkMembershipIxCols& Membership, const FViewPkPlayerIxCols& Player) + { + return Membership.PlayerId.Eq(Player.Id); + }).into_sql() + ); + + const FString SenderViewsJoinSql = ToFString( + Q.From.SenderViewPkPlayersA().RightSemijoin(Q.From.SenderViewPkPlayersB(), [](const FViewPkPlayerIxCols& LeftView, const FViewPkPlayerIxCols& RightView) + { + return LeftView.Id.Eq(RightView.Id); + }).into_sql() + ); + + TestEqual( + TEXT("membership to all_view_pk_players semijoin sql"), + MembershipJoinSql, + TEXT("SELECT \"all_view_pk_players\".* FROM \"view_pk_membership\" JOIN \"all_view_pk_players\" ON \"view_pk_membership\".\"player_id\" = \"all_view_pk_players\".\"id\"") + ); + + TestEqual( + TEXT("sender views semijoin sql"), + SenderViewsJoinSql, + TEXT("SELECT \"sender_view_pk_players_b\".* FROM \"sender_view_pk_players_a\" JOIN \"sender_view_pk_players_b\" ON \"sender_view_pk_players_a\".\"id\" = \"sender_view_pk_players_b\".\"id\"") + ); + + return true; +} + +bool FViewPkSubscribeAllTablesTest::RunTest(const FString& Parameters) +{ + const TArray Sql = FQueryBuilder::AllTablesSqlQueries(); + + TestEqual(TEXT("all tables count"), Sql.Num(), 6); + TestTrue(TEXT("all tables include all_view_pk_players"), Sql.Contains(TEXT("SELECT * FROM \"all_view_pk_players\""))); + TestTrue(TEXT("all tables include sender_view_pk_players_a"), Sql.Contains(TEXT("SELECT * FROM \"sender_view_pk_players_a\""))); + TestTrue(TEXT("all tables include sender_view_pk_players_b"), Sql.Contains(TEXT("SELECT * FROM \"sender_view_pk_players_b\""))); + TestTrue(TEXT("all tables include view_pk_membership"), Sql.Contains(TEXT("SELECT * FROM \"view_pk_membership\""))); + TestTrue(TEXT("all tables include view_pk_membership_secondary"), Sql.Contains(TEXT("SELECT * FROM \"view_pk_membership_secondary\""))); + TestTrue(TEXT("all tables include view_pk_player"), Sql.Contains(TEXT("SELECT * FROM \"view_pk_player\""))); + + return true; +} + +bool FViewPkRuntimeUpdatePairingTest::RunTest(const FString& Parameters) +{ + const FString RuntimeTestName = TEXT("ViewPkRuntimeUpdatePairing"); + + if (!ValidateParameterConfig(this)) + { + return false; + } + + UViewPkRuntimeHandler* Handler = CreateTestHandler(); + Handler->Counter->Register(TEXT("subscription_applied")); + Handler->Counter->Register(TEXT("all_view_pk_players_insert")); + Handler->Counter->Register(TEXT("all_view_pk_players_update")); + Handler->Counter->Register(TEXT("sender_view_pk_players_a_insert")); + Handler->Counter->Register(TEXT("sender_view_pk_players_a_update")); + + ConnectThen(Handler->Counter, RuntimeTestName, [this, Handler](UDbConnection* Conn) + { + Conn->Db->AllViewPkPlayers->OnInsert.AddDynamic(Handler, &UViewPkRuntimeHandler::OnAllViewPkPlayersInsert); + Conn->Db->AllViewPkPlayers->OnUpdate.AddDynamic(Handler, &UViewPkRuntimeHandler::OnAllViewPkPlayersUpdate); + Conn->Db->AllViewPkPlayers->OnDelete.AddDynamic(Handler, &UViewPkRuntimeHandler::OnAllViewPkPlayersDelete); + + Conn->Db->SenderViewPkPlayersA->OnInsert.AddDynamic(Handler, &UViewPkRuntimeHandler::OnSenderViewPkPlayersAInsert); + Conn->Db->SenderViewPkPlayersA->OnUpdate.AddDynamic(Handler, &UViewPkRuntimeHandler::OnSenderViewPkPlayersAUpdate); + Conn->Db->SenderViewPkPlayersA->OnDelete.AddDynamic(Handler, &UViewPkRuntimeHandler::OnSenderViewPkPlayersADelete); + + UTestHelperDelegates* SubHelper = NewObject(); + SubHelper->AddToRoot(); + + SubHelper->OnSubscriptionApplied = [this, Handler, Conn](FSubscriptionEventContext Ctx) + { + if (Conn->Db->AllViewPkPlayers->Count() != 0 || Conn->Db->SenderViewPkPlayersA->Count() != 0) + { + Handler->Counter->MarkFailure(TEXT("subscription_applied"), TEXT("Expected empty view caches before reducers")); + Handler->Counter->Abort(); + return; + } + + Handler->Counter->MarkSuccess(TEXT("subscription_applied")); + + Ctx.Reducers->InsertViewPkPlayer(Handler->ExpectedId, Handler->InitialName); + Ctx.Reducers->InsertViewPkMembership(10, Handler->ExpectedId); + Ctx.Reducers->UpdateViewPkPlayer(Handler->ExpectedId, Handler->UpdatedName); + }; + + SubHelper->OnSubscriptionError = [Handler](FErrorContext Ctx) + { + Handler->Counter->MarkFailure(TEXT("subscription_applied"), FString::Printf(TEXT("Subscription error: %s"), *Ctx.Error)); + Handler->Counter->Abort(); + }; + + FOnSubscriptionApplied AppliedDelegate; + BIND_DELEGATE_SAFE(AppliedDelegate, SubHelper, UTestHelperDelegates, HandleSubscriptionApplied); + + FOnSubscriptionError ErrorDelegate; + BIND_DELEGATE_SAFE(ErrorDelegate, SubHelper, UTestHelperDelegates, HandleSubscriptionError); + + Conn->SubscriptionBuilder() + ->OnApplied(AppliedDelegate) + ->OnError(ErrorDelegate) + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.AllViewPkPlayers(); + }) + .AddQuery([](const FQueryBuilder& Q) + { + return Q.From.SenderViewPkPlayersA(); + }) + .Subscribe(); + }); + + ADD_LATENT_AUTOMATION_COMMAND(FWaitForTestCounter(*this, RuntimeTestName, Handler->Counter, FPlatformTime::Seconds())); + return true; +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/TestCounter.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/TestCounter.cpp new file mode 100644 index 00000000000..332e61064b2 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/TestCounter.cpp @@ -0,0 +1,87 @@ +#include "Tests/TestCounter.h" + +void FTestCounter::Register(const FString& TestName) +{ + FScopeLock Lock(&Mutex); + if (Registered.Contains(TestName)) + { + UE_LOG(LogTemp, Error, TEXT("Duplicate test name: %s"), *TestName); + } + Registered.Add(TestName); +} + +void FTestCounter::MarkSuccess(const FString& TestName) +{ + FScopeLock Lock(&Mutex); + Outcomes.Add(TestName, { true, FString() }); + UE_LOG(LogTemp, Log, TEXT("Operation success: %s"), *TestName); +} + +void FTestCounter::MarkFailure(const FString& TestName, const FString& Error) +{ + FScopeLock Lock(&Mutex); + Outcomes.Add(TestName, { false, Error }); + UE_LOG(LogTemp, Error, TEXT("Operation failed: %s, %s"), *TestName, *Error); +} + +bool FTestCounter::IsComplete() const +{ + FScopeLock Lock(&Mutex); + return Outcomes.Num() == Registered.Num(); +} + +bool FTestCounter::AllSucceeded() const +{ + FScopeLock Lock(&Mutex); + if (Outcomes.Num() != Registered.Num()) + { + return false; + } + for (const auto& Elem : Outcomes) + { + if (!Elem.Value.bSuccess) + { + return false; + } + } + return true; +} + +TArray FTestCounter::GetFailures() const +{ + FScopeLock Lock(&Mutex); + TArray Failures; + for (const FString& Name : Registered) + { + const FTestOutcome* Outcome = Outcomes.Find(Name); + if (!Outcome) + { + Failures.Add(FString::Printf(TEXT("TIMEOUT: %s"), *Name)); + } + else if (!Outcome->bSuccess) + { + Failures.Add(FString::Printf(TEXT("FAILED: %s: %s"), *Name, *Outcome->Error)); + } + } + return Failures; +} + +TArray FTestCounter::GetSuccesses() const +{ + FScopeLock Lock(&Mutex); + TArray Successes; + for (const FString& Name : Registered) + { + const FTestOutcome* Outcome = Outcomes.Find(Name); + if (Outcome && Outcome->bSuccess) + { + Successes.Add(FString::Printf(TEXT("SUCCESS: %s"), *Name)); + } + } + return Successes; +} + +void FTestCounter::Abort() +{ + bAborted = true; +} \ No newline at end of file diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/TestHandler.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/TestHandler.cpp new file mode 100644 index 00000000000..ad1614f45db --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/TestHandler.cpp @@ -0,0 +1,88 @@ +#include "Tests/TestHandler.h" + +namespace +{ +bool ValidateInsertedRow(UViewPkRuntimeHandler* Handler, const FString& StepName, const FViewPkPlayerType& Value) +{ + if (Value.Id != Handler->ExpectedId) + { + Handler->Counter->MarkFailure(StepName, FString::Printf(TEXT("Unexpected id %llu"), static_cast(Value.Id))); + Handler->Counter->Abort(); + return false; + } + if (Value.Name != Handler->InitialName) + { + Handler->Counter->MarkFailure(StepName, FString::Printf(TEXT("Unexpected insert name %s"), *Value.Name)); + Handler->Counter->Abort(); + return false; + } + return true; +} + +bool ValidateUpdatedRows(UViewPkRuntimeHandler* Handler, const FString& StepName, const FViewPkPlayerType& OldValue, const FViewPkPlayerType& NewValue) +{ + if (OldValue.Id != Handler->ExpectedId || NewValue.Id != Handler->ExpectedId) + { + Handler->Counter->MarkFailure(StepName, TEXT("Unexpected row id during update")); + Handler->Counter->Abort(); + return false; + } + if (OldValue.Name != Handler->InitialName) + { + Handler->Counter->MarkFailure(StepName, FString::Printf(TEXT("Unexpected old name %s"), *OldValue.Name)); + Handler->Counter->Abort(); + return false; + } + if (NewValue.Name != Handler->UpdatedName) + { + Handler->Counter->MarkFailure(StepName, FString::Printf(TEXT("Unexpected new name %s"), *NewValue.Name)); + Handler->Counter->Abort(); + return false; + } + return true; +} +} + +void UViewPkRuntimeHandler::OnAllViewPkPlayersInsert(const FEventContext&, const FViewPkPlayerType& Value) +{ + if (ValidateInsertedRow(this, TEXT("all_view_pk_players_insert"), Value)) + { + Counter->MarkSuccess(TEXT("all_view_pk_players_insert")); + } +} + +void UViewPkRuntimeHandler::OnAllViewPkPlayersUpdate(const FEventContext&, const FViewPkPlayerType& OldValue, const FViewPkPlayerType& NewValue) +{ + if (ValidateUpdatedRows(this, TEXT("all_view_pk_players_update"), OldValue, NewValue)) + { + Counter->MarkSuccess(TEXT("all_view_pk_players_update")); + } +} + +void UViewPkRuntimeHandler::OnAllViewPkPlayersDelete(const FEventContext&, const FViewPkPlayerType&) +{ + Counter->MarkFailure(TEXT("all_view_pk_players_update"), TEXT("Unexpected delete for all_view_pk_players")); + Counter->Abort(); +} + +void UViewPkRuntimeHandler::OnSenderViewPkPlayersAInsert(const FEventContext&, const FViewPkPlayerType& Value) +{ + if (ValidateInsertedRow(this, TEXT("sender_view_pk_players_a_insert"), Value)) + { + Counter->MarkSuccess(TEXT("sender_view_pk_players_a_insert")); + } +} + +void UViewPkRuntimeHandler::OnSenderViewPkPlayersAUpdate(const FEventContext&, const FViewPkPlayerType& OldValue, const FViewPkPlayerType& NewValue) +{ + if (ValidateUpdatedRows(this, TEXT("sender_view_pk_players_a_update"), OldValue, NewValue)) + { + Counter->MarkSuccess(TEXT("sender_view_pk_players_a_update")); + } +} + +void UViewPkRuntimeHandler::OnSenderViewPkPlayersADelete(const FEventContext&, const FViewPkPlayerType&) +{ + Counter->MarkFailure(TEXT("sender_view_pk_players_a_update"), TEXT("Unexpected delete for sender_view_pk_players_a")); + Counter->Abort(); +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/ReducerBase.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/ReducerBase.g.h new file mode 100644 index 00000000000..d0f1a4547d0 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/ReducerBase.g.h @@ -0,0 +1,18 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ReducerBase.g.generated.h" + +// Abstract Reducer base class +UCLASS(Abstract, BlueprintType) +class TESTVIEWPKCLIENT_API UReducerBase : public UObject +{ + GENERATED_BODY() + +public: + virtual ~UReducerBase() = default; +}; + diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/InsertViewPkMembership.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/InsertViewPkMembership.g.h new file mode 100644 index 00000000000..31d069e5894 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/InsertViewPkMembership.g.h @@ -0,0 +1,58 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "InsertViewPkMembership.g.generated.h" + +// Reducer arguments struct for InsertViewPkMembership +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FInsertViewPkMembershipArgs +{ + GENERATED_BODY() + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Id = 0; + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 PlayerId = 0; + + FInsertViewPkMembershipArgs() = default; + + FInsertViewPkMembershipArgs(const uint64& InId, const uint64& InPlayerId) + : Id(InId), PlayerId(InPlayerId) + {} + + + FORCEINLINE bool operator==(const FInsertViewPkMembershipArgs& Other) const + { + return Id == Other.Id && PlayerId == Other.PlayerId; + } + FORCEINLINE bool operator!=(const FInsertViewPkMembershipArgs& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FInsertViewPkMembershipArgs, Id, PlayerId); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API UInsertViewPkMembershipReducer : public UReducerBase +{ + GENERATED_BODY() + +public: + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Id = 0; + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 PlayerId = 0; + +}; + + diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/InsertViewPkMembershipSecondary.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/InsertViewPkMembershipSecondary.g.h new file mode 100644 index 00000000000..ca330a28f06 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/InsertViewPkMembershipSecondary.g.h @@ -0,0 +1,58 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "InsertViewPkMembershipSecondary.g.generated.h" + +// Reducer arguments struct for InsertViewPkMembershipSecondary +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FInsertViewPkMembershipSecondaryArgs +{ + GENERATED_BODY() + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Id = 0; + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 PlayerId = 0; + + FInsertViewPkMembershipSecondaryArgs() = default; + + FInsertViewPkMembershipSecondaryArgs(const uint64& InId, const uint64& InPlayerId) + : Id(InId), PlayerId(InPlayerId) + {} + + + FORCEINLINE bool operator==(const FInsertViewPkMembershipSecondaryArgs& Other) const + { + return Id == Other.Id && PlayerId == Other.PlayerId; + } + FORCEINLINE bool operator!=(const FInsertViewPkMembershipSecondaryArgs& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FInsertViewPkMembershipSecondaryArgs, Id, PlayerId); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API UInsertViewPkMembershipSecondaryReducer : public UReducerBase +{ + GENERATED_BODY() + +public: + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Id = 0; + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 PlayerId = 0; + +}; + + diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/InsertViewPkPlayer.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/InsertViewPkPlayer.g.h new file mode 100644 index 00000000000..f52e692d386 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/InsertViewPkPlayer.g.h @@ -0,0 +1,58 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "InsertViewPkPlayer.g.generated.h" + +// Reducer arguments struct for InsertViewPkPlayer +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FInsertViewPkPlayerArgs +{ + GENERATED_BODY() + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Id = 0; + + UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") + FString Name; + + FInsertViewPkPlayerArgs() = default; + + FInsertViewPkPlayerArgs(const uint64& InId, const FString& InName) + : Id(InId), Name(InName) + {} + + + FORCEINLINE bool operator==(const FInsertViewPkPlayerArgs& Other) const + { + return Id == Other.Id && Name == Other.Name; + } + FORCEINLINE bool operator!=(const FInsertViewPkPlayerArgs& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FInsertViewPkPlayerArgs, Id, Name); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API UInsertViewPkPlayerReducer : public UReducerBase +{ + GENERATED_BODY() + +public: + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Id = 0; + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FString Name; + +}; + + diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/UpdateViewPkPlayer.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/UpdateViewPkPlayer.g.h new file mode 100644 index 00000000000..204e288af84 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Reducers/UpdateViewPkPlayer.g.h @@ -0,0 +1,58 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "UpdateViewPkPlayer.g.generated.h" + +// Reducer arguments struct for UpdateViewPkPlayer +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FUpdateViewPkPlayerArgs +{ + GENERATED_BODY() + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Id = 0; + + UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB") + FString Name; + + FUpdateViewPkPlayerArgs() = default; + + FUpdateViewPkPlayerArgs(const uint64& InId, const FString& InName) + : Id(InId), Name(InName) + {} + + + FORCEINLINE bool operator==(const FUpdateViewPkPlayerArgs& Other) const + { + return Id == Other.Id && Name == Other.Name; + } + FORCEINLINE bool operator!=(const FUpdateViewPkPlayerArgs& Other) const + { + return !(*this == Other); + } +}; + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_STRUCT(FUpdateViewPkPlayerArgs, Id, Name); +} + +// Reducer class for internal dispatching +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API UUpdateViewPkPlayerReducer : public UReducerBase +{ + GENERATED_BODY() + +public: + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Id = 0; + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FString Name; + +}; + + diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/SpacetimeDBClient.g.h new file mode 100644 index 00000000000..a8e02fe167a --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -0,0 +1,1165 @@ +// 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 2.0.5 (commit 047dac974526f5c5aff873026e90177270b10f38). + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Connection/Callback.h" +#include "Connection/DbConnectionBase.h" +#include "Connection/DbConnectionBuilder.h" +#include "Connection/Subscription.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "ModuleBindings/Reducers/InsertViewPkMembership.g.h" +#include "ModuleBindings/Reducers/InsertViewPkMembershipSecondary.g.h" +#include "ModuleBindings/Reducers/InsertViewPkPlayer.g.h" +#include "ModuleBindings/Reducers/UpdateViewPkPlayer.g.h" +#include "ModuleBindings/Types/ViewPkMembershipSecondaryType.g.h" +#include "ModuleBindings/Types/ViewPkMembershipType.g.h" +#include "ModuleBindings/Types/ViewPkPlayerType.g.h" +#include "QueryBuilder/query_builder.h" +#include "Types/Builtins.h" +#include "SpacetimeDBClient.g.generated.h" + +// Forward declarations +class UDbConnection; +class URemoteTables; +class URemoteReducers; +class URemoteProcedures; +class USubscriptionBuilder; +class USubscriptionHandle; + +/** Forward declaration for tables */ +class UAllViewPkPlayersTable; +class USenderViewPkPlayersATable; +class USenderViewPkPlayersBTable; +class UViewPkMembershipTable; +class UViewPkMembershipSecondaryTable; +class UViewPkPlayerTable; +/***/ + +// Delegates using the generated connection type. These wrap the base +// delegates defined in the SDK so that projects can work directly with +// UDbConnection without manual casting in user code. +DECLARE_DYNAMIC_DELEGATE_ThreeParams( + FOnConnectDelegate, + UDbConnection*, Connection, + FSpacetimeDBIdentity, Identity, + const FString&, Token); + +DECLARE_DYNAMIC_DELEGATE_TwoParams( + FOnDisconnectDelegate, + UDbConnection*, Connection, + const FString&, Error); + + +// Context classes for event handling + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FContextBase +{ + GENERATED_BODY() + + FContextBase() : Db(nullptr), Reducers(nullptr), Procedures(nullptr), Conn(nullptr) {}; + FContextBase(UDbConnection* InConn); + + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + URemoteTables* Db; + + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + URemoteReducers* Reducers; + + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + URemoteProcedures* Procedures; + + bool IsActive() const; + void Disconnect(); + bool TryGetIdentity(FSpacetimeDBIdentity& OutIdentity) const; + FSpacetimeDBConnectionId GetConnectionId() const; + USubscriptionBuilder* SubscriptionBuilder(); + +protected: + UPROPERTY() + UDbConnection* Conn; + +}; + +UCLASS() +class TESTVIEWPKCLIENT_API UContextBaseBpLib : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +private: + UFUNCTION(BlueprintPure, Category="SpacetimeDB") + static URemoteTables* GetDb(const FContextBase& Ctx) { return Ctx.Db; } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB") + static URemoteReducers* GetReducers(const FContextBase& Ctx) { return Ctx.Reducers; } + + static URemoteProcedures* GetProcedures(const FContextBase& Ctx) { return Ctx.Procedures; } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB") + static bool IsActive(const FContextBase& Ctx) { return Ctx.IsActive(); } +}; + +UENUM(BlueprintType, Category = "SpacetimeDB") +enum class EReducerTag : uint8 +{ + InsertViewPkMembership, + InsertViewPkMembershipSecondary, + InsertViewPkPlayer, + UpdateViewPkPlayer +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FReducer +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + EReducerTag Tag = static_cast(0); + + TVariant Data; + + // Optional metadata + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + FString ReducerName; + uint32 ReducerId = 0; + uint32 RequestId = 0; + + static FReducer InsertViewPkMembership(const FInsertViewPkMembershipArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::InsertViewPkMembership; + Out.Data.Set(Value); + Out.ReducerName = TEXT("insert_view_pk_membership"); + return Out; + } + + FORCEINLINE bool IsInsertViewPkMembership() const { return Tag == EReducerTag::InsertViewPkMembership; } + FORCEINLINE FInsertViewPkMembershipArgs GetAsInsertViewPkMembership() const + { + ensureMsgf(IsInsertViewPkMembership(), TEXT("Reducer does not hold InsertViewPkMembership!")); + return Data.Get(); + } + + static FReducer InsertViewPkMembershipSecondary(const FInsertViewPkMembershipSecondaryArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::InsertViewPkMembershipSecondary; + Out.Data.Set(Value); + Out.ReducerName = TEXT("insert_view_pk_membership_secondary"); + return Out; + } + + FORCEINLINE bool IsInsertViewPkMembershipSecondary() const { return Tag == EReducerTag::InsertViewPkMembershipSecondary; } + FORCEINLINE FInsertViewPkMembershipSecondaryArgs GetAsInsertViewPkMembershipSecondary() const + { + ensureMsgf(IsInsertViewPkMembershipSecondary(), TEXT("Reducer does not hold InsertViewPkMembershipSecondary!")); + return Data.Get(); + } + + static FReducer InsertViewPkPlayer(const FInsertViewPkPlayerArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::InsertViewPkPlayer; + Out.Data.Set(Value); + Out.ReducerName = TEXT("insert_view_pk_player"); + return Out; + } + + FORCEINLINE bool IsInsertViewPkPlayer() const { return Tag == EReducerTag::InsertViewPkPlayer; } + FORCEINLINE FInsertViewPkPlayerArgs GetAsInsertViewPkPlayer() const + { + ensureMsgf(IsInsertViewPkPlayer(), TEXT("Reducer does not hold InsertViewPkPlayer!")); + return Data.Get(); + } + + static FReducer UpdateViewPkPlayer(const FUpdateViewPkPlayerArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::UpdateViewPkPlayer; + Out.Data.Set(Value); + Out.ReducerName = TEXT("update_view_pk_player"); + return Out; + } + + FORCEINLINE bool IsUpdateViewPkPlayer() const { return Tag == EReducerTag::UpdateViewPkPlayer; } + FORCEINLINE FUpdateViewPkPlayerArgs GetAsUpdateViewPkPlayer() const + { + ensureMsgf(IsUpdateViewPkPlayer(), TEXT("Reducer does not hold UpdateViewPkPlayer!")); + return Data.Get(); + } + + FORCEINLINE bool operator==(const FReducer& Other) const + { + if (Tag != Other.Tag || ReducerId != Other.ReducerId || RequestId != Other.RequestId || ReducerName != Other.ReducerName) return false; + switch (Tag) + { + case EReducerTag::InsertViewPkMembership: + return GetAsInsertViewPkMembership() == Other.GetAsInsertViewPkMembership(); + case EReducerTag::InsertViewPkMembershipSecondary: + return GetAsInsertViewPkMembershipSecondary() == Other.GetAsInsertViewPkMembershipSecondary(); + case EReducerTag::InsertViewPkPlayer: + return GetAsInsertViewPkPlayer() == Other.GetAsInsertViewPkPlayer(); + case EReducerTag::UpdateViewPkPlayer: + return GetAsUpdateViewPkPlayer() == Other.GetAsUpdateViewPkPlayer(); + default: return false; + } + } + FORCEINLINE bool operator!=(const FReducer& Other) const { return !(*this == Other); } +}; + +UCLASS() +class TESTVIEWPKCLIENT_API UReducerBpLib : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +private: + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer InsertViewPkMembership(const FInsertViewPkMembershipArgs& Value) { + return FReducer::InsertViewPkMembership(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsInsertViewPkMembership(const FReducer& Reducer) { return Reducer.IsInsertViewPkMembership(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FInsertViewPkMembershipArgs GetAsInsertViewPkMembership(const FReducer& Reducer) { + return Reducer.GetAsInsertViewPkMembership(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer InsertViewPkMembershipSecondary(const FInsertViewPkMembershipSecondaryArgs& Value) { + return FReducer::InsertViewPkMembershipSecondary(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsInsertViewPkMembershipSecondary(const FReducer& Reducer) { return Reducer.IsInsertViewPkMembershipSecondary(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FInsertViewPkMembershipSecondaryArgs GetAsInsertViewPkMembershipSecondary(const FReducer& Reducer) { + return Reducer.GetAsInsertViewPkMembershipSecondary(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer InsertViewPkPlayer(const FInsertViewPkPlayerArgs& Value) { + return FReducer::InsertViewPkPlayer(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsInsertViewPkPlayer(const FReducer& Reducer) { return Reducer.IsInsertViewPkPlayer(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FInsertViewPkPlayerArgs GetAsInsertViewPkPlayer(const FReducer& Reducer) { + return Reducer.GetAsInsertViewPkPlayer(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer UpdateViewPkPlayer(const FUpdateViewPkPlayerArgs& Value) { + return FReducer::UpdateViewPkPlayer(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsUpdateViewPkPlayer(const FReducer& Reducer) { return Reducer.IsUpdateViewPkPlayer(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FUpdateViewPkPlayerArgs GetAsUpdateViewPkPlayer(const FReducer& Reducer) { + return Reducer.GetAsUpdateViewPkPlayer(); + } +}; + +/** Metadata describing a reducer run. */ +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FTestViewPkClientReducerEvent +{ + GENERATED_BODY() + + /** Timestamp for when the reducer executed */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBTimestamp Timestamp; + + /** Result status of the reducer */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBStatus Status; + + /** Identity that initiated the call */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBIdentity CallerIdentity; + + /** Connection ID for the caller */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBConnectionId CallerConnectionId; + + /** Energy consumed while executing */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FEnergyQuantaType EnergyConsumed; + + /** Detailed call information */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FReducer Reducer; + + FORCEINLINE bool operator==(const FTestViewPkClientReducerEvent& Other) const + { + return Status == Other.Status && Timestamp == Other.Timestamp && CallerIdentity == Other.CallerIdentity && + CallerConnectionId == Other.CallerConnectionId && EnergyConsumed == Other.EnergyConsumed && + Reducer == Other.Reducer; + } + + FORCEINLINE bool operator!=(const FTestViewPkClientReducerEvent& Other) const + { + return !(*this == Other); + } +}; + +// No procedures defined in this module. +/** Metadata describing a procedure run. */ +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FTestViewPkClientProcedureEvent +{ + GENERATED_BODY() + + /** Timestamp for when the procedure executed */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBTimestamp Timestamp; + + /** Result status of the procedure */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBProcedureStatus Status; + + /** Identity that initiated the call */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBTimeDuration TotalHostExecutionDuration; + + FTestViewPkClientProcedureEvent() { + } + FTestViewPkClientProcedureEvent(FProcedureEvent Event) { + Timestamp = Event.Timestamp; + Status = FSpacetimeDBProcedureStatus::FromStatus(Event.Status); + TotalHostExecutionDuration = Event.TotalHostExecutionDuration; + } + FORCEINLINE bool operator==(const FTestViewPkClientProcedureEvent& Other) const + { + return Status == Other.Status && Timestamp == Other.Timestamp && + TotalHostExecutionDuration == Other.TotalHostExecutionDuration; + } + + FORCEINLINE bool operator!=(const FTestViewPkClientProcedureEvent& Other) const + { + return !(*this == Other); + } +}; + +/** Represents event with variant message data. */ +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FTestViewPkClientEvent +{ + GENERATED_BODY() + + /** Tagged union holding reducer call, unit events, or error string */ + TVariant MessageData; + + /** Type tag indicating what this event represents */ + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + ESpacetimeDBEventTag Tag = ESpacetimeDBEventTag::UnknownTransaction; + + /** === Static factory methods ===*/ + static FTestViewPkClientEvent Reducer(const FReducer& Value) + { + FTestViewPkClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::Reducer; + Obj.MessageData.Set(Value); + return Obj; + } + + static FTestViewPkClientEvent SubscribeApplied(const FSpacetimeDBUnit& Value) + { + FTestViewPkClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::SubscribeApplied; + Obj.MessageData.Set(Value); + return Obj; + } + + static FTestViewPkClientEvent UnsubscribeApplied(const FSpacetimeDBUnit& Value) + { + FTestViewPkClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::UnsubscribeApplied; + Obj.MessageData.Set(Value); + return Obj; + } + + static FTestViewPkClientEvent Disconnected(const FSpacetimeDBUnit& Value) + { + FTestViewPkClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::Disconnected; + Obj.MessageData.Set(Value); + return Obj; + } + + static FTestViewPkClientEvent Transaction(const FSpacetimeDBUnit& Value) + { + FTestViewPkClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::Transaction; + Obj.MessageData.Set(Value); + return Obj; + } + + static FTestViewPkClientEvent SubscribeError(const FString& Value) + { + FTestViewPkClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::SubscribeError; + Obj.MessageData.Set(Value); + return Obj; + } + + static FTestViewPkClientEvent UnknownTransaction(const FSpacetimeDBUnit& Value) + { + FTestViewPkClientEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::UnknownTransaction; + Obj.MessageData.Set(Value); + return Obj; + } + + FORCEINLINE bool IsReducer() const { return Tag == ESpacetimeDBEventTag::Reducer; } + FORCEINLINE FReducer GetAsReducer() const + { + ensureMsgf(IsReducer(), TEXT("MessageData does not hold Reducer!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsSubscribeApplied() const { return Tag == ESpacetimeDBEventTag::SubscribeApplied; } + FORCEINLINE FSpacetimeDBUnit GetAsSubscribeApplied() const + { + ensureMsgf(IsSubscribeApplied(), TEXT("MessageData does not hold SubscribeApplied!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsUnsubscribeApplied() const { return Tag == ESpacetimeDBEventTag::UnsubscribeApplied; } + FORCEINLINE FSpacetimeDBUnit GetAsUnsubscribeApplied() const + { + ensureMsgf(IsUnsubscribeApplied(), TEXT("MessageData does not hold UnsubscribeApplied!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsDisconnected() const { return Tag == ESpacetimeDBEventTag::Disconnected; } + FORCEINLINE FSpacetimeDBUnit GetAsDisconnected() const + { + ensureMsgf(IsDisconnected(), TEXT("MessageData does not hold Disconnected!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsTransaction() const { return Tag == ESpacetimeDBEventTag::Transaction; } + FORCEINLINE FSpacetimeDBUnit GetAsTransaction() const + { + ensureMsgf(IsTransaction(), TEXT("MessageData does not hold Transaction!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsSubscribeError() const { return Tag == ESpacetimeDBEventTag::SubscribeError; } + FORCEINLINE FString GetAsSubscribeError() const + { + ensureMsgf(IsSubscribeError(), TEXT("MessageData does not hold SubscribeError!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsUnknownTransaction() const { return Tag == ESpacetimeDBEventTag::UnknownTransaction; } + FORCEINLINE FSpacetimeDBUnit GetAsUnknownTransaction() const + { + ensureMsgf(IsUnknownTransaction(), TEXT("MessageData does not hold UnknownTransaction!")); + return MessageData.Get(); + } + + FORCEINLINE bool operator==(const FTestViewPkClientEvent& Other) const + { + if (Tag != Other.Tag) return false; + switch (Tag) + { + case ESpacetimeDBEventTag::Reducer: return GetAsReducer() == Other.GetAsReducer(); + case ESpacetimeDBEventTag::SubscribeApplied: return GetAsSubscribeApplied() == Other.GetAsSubscribeApplied(); + case ESpacetimeDBEventTag::UnsubscribeApplied: return GetAsUnsubscribeApplied() == Other.GetAsUnsubscribeApplied(); + case ESpacetimeDBEventTag::Disconnected: return GetAsDisconnected() == Other.GetAsDisconnected(); + case ESpacetimeDBEventTag::Transaction: return GetAsTransaction() == Other.GetAsTransaction(); + case ESpacetimeDBEventTag::SubscribeError: return GetAsSubscribeError() == Other.GetAsSubscribeError(); + case ESpacetimeDBEventTag::UnknownTransaction: return GetAsUnknownTransaction() == Other.GetAsUnknownTransaction(); + default: return false; + } + } + + FORCEINLINE bool operator!=(const FTestViewPkClientEvent& Other) const + { + return !(*this == Other); + } +}; + +UCLASS() +class TESTVIEWPKCLIENT_API UTestViewPkClientEventBpLib : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +private: + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewPkClientEvent") + static FTestViewPkClientEvent Reducer(const FReducer& InValue) + { + return FTestViewPkClientEvent::Reducer(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewPkClientEvent") + static FTestViewPkClientEvent SubscribeApplied(const FSpacetimeDBUnit& InValue) + { + return FTestViewPkClientEvent::SubscribeApplied(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewPkClientEvent") + static FTestViewPkClientEvent UnsubscribeApplied(const FSpacetimeDBUnit& InValue) + { + return FTestViewPkClientEvent::UnsubscribeApplied(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewPkClientEvent") + static FTestViewPkClientEvent Disconnected(const FSpacetimeDBUnit& InValue) + { + return FTestViewPkClientEvent::Disconnected(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewPkClientEvent") + static FTestViewPkClientEvent Transaction(const FSpacetimeDBUnit& InValue) + { + return FTestViewPkClientEvent::Transaction(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewPkClientEvent") + static FTestViewPkClientEvent SubscribeError(const FString& InValue) + { + return FTestViewPkClientEvent::SubscribeError(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|TestViewPkClientEvent") + static FTestViewPkClientEvent UnknownTransaction(const FSpacetimeDBUnit& InValue) + { + return FTestViewPkClientEvent::UnknownTransaction(InValue); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static bool IsReducer(const FTestViewPkClientEvent& Event) { return Event.IsReducer(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static bool IsSubscribeApplied(const FTestViewPkClientEvent& Event) { return Event.IsSubscribeApplied(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static bool IsUnsubscribeApplied(const FTestViewPkClientEvent& Event) { return Event.IsUnsubscribeApplied(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static bool IsDisconnected(const FTestViewPkClientEvent& Event) { return Event.IsDisconnected(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static bool IsTransaction(const FTestViewPkClientEvent& Event) { return Event.IsTransaction(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static bool IsSubscribeError(const FTestViewPkClientEvent& Event) { return Event.IsSubscribeError(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static bool IsUnknownTransaction(const FTestViewPkClientEvent& Event) { return Event.IsUnknownTransaction(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static FReducer GetAsReducer(const FTestViewPkClientEvent& Event) + { + return Event.GetAsReducer(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static FSpacetimeDBUnit GetAsSubscribeApplied(const FTestViewPkClientEvent& Event) + { + return Event.GetAsSubscribeApplied(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static FSpacetimeDBUnit GetAsUnsubscribeApplied(const FTestViewPkClientEvent& Event) + { + return Event.GetAsUnsubscribeApplied(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static FSpacetimeDBUnit GetAsDisconnected(const FTestViewPkClientEvent& Event) + { + return Event.GetAsDisconnected(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static FSpacetimeDBUnit GetAsTransaction(const FTestViewPkClientEvent& Event) + { + return Event.GetAsTransaction(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static FString GetAsSubscribeError(const FTestViewPkClientEvent& Event) + { + return Event.GetAsSubscribeError(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|TestViewPkClientEvent") + static FSpacetimeDBUnit GetAsUnknownTransaction(const FTestViewPkClientEvent& Event) + { + return Event.GetAsUnknownTransaction(); + } + +}; + + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FEventContext : public FContextBase +{ + GENERATED_BODY() + + FEventContext() = default; + FEventContext(UDbConnection* InConn, const FTestViewPkClientEvent& InEvent) : FContextBase(InConn), Event(InEvent) {} + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FTestViewPkClientEvent Event; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FReducerEventContext : public FContextBase +{ + GENERATED_BODY() + + FReducerEventContext() = default; + FReducerEventContext(UDbConnection* InConn, FTestViewPkClientReducerEvent InEvent) : FContextBase(InConn), Event(InEvent) {} + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FTestViewPkClientReducerEvent Event; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FProcedureEventContext : public FContextBase +{ + GENERATED_BODY() + + FProcedureEventContext() = default; + FProcedureEventContext(UDbConnection* InConn, FTestViewPkClientProcedureEvent InEvent) : FContextBase(InConn), Event(InEvent) {} + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FTestViewPkClientProcedureEvent Event; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FErrorContext : public FContextBase +{ + GENERATED_BODY() + + FErrorContext() = default; + FErrorContext(UDbConnection* InConn, const FString& InError) : FContextBase(InConn), Error(InError) {} + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FString Error; + +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FSubscriptionEventContext : public FContextBase +{ + GENERATED_BODY() + + FSubscriptionEventContext() = default; + FSubscriptionEventContext(UDbConnection* InConn) : FContextBase(InConn) {} + +}; + +DECLARE_DYNAMIC_DELEGATE_OneParam( + FOnSubscriptionApplied, + FSubscriptionEventContext, Context); + +DECLARE_DYNAMIC_DELEGATE_OneParam( + FOnSubscriptionError, + FErrorContext, Context); + +// RemoteTables class +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API URemoteTables : public UObject +{ + GENERATED_BODY() + +public: + void Initialize(); + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UAllViewPkPlayersTable* AllViewPkPlayers; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + USenderViewPkPlayersATable* SenderViewPkPlayersA; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + USenderViewPkPlayersBTable* SenderViewPkPlayersB; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UViewPkMembershipTable* ViewPkMembership; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UViewPkMembershipSecondaryTable* ViewPkMembershipSecondary; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UViewPkPlayerTable* ViewPkPlayer; + +}; + +// RemoteReducers class +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API URemoteReducers : public UObject +{ + GENERATED_BODY() + +public: + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FInsertViewPkMembershipHandler, + const FReducerEventContext&, Context, + uint64, Id, + uint64, PlayerId + ); + // NOTE: Not exposed to Blueprint because uint64, uint64 types are not Blueprint-compatible + FInsertViewPkMembershipHandler OnInsertViewPkMembership; + + // NOTE: Not exposed to Blueprint because uint64, uint64 types are not Blueprint-compatible + void InsertViewPkMembership(const uint64 Id, const uint64 PlayerId); + + bool InvokeInsertViewPkMembership(const FReducerEventContext& Context, const UInsertViewPkMembershipReducer* Args); + bool InvokeInsertViewPkMembershipWithArgs(const FReducerEventContext& Context, const FInsertViewPkMembershipArgs& Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FInsertViewPkMembershipSecondaryHandler, + const FReducerEventContext&, Context, + uint64, Id, + uint64, PlayerId + ); + // NOTE: Not exposed to Blueprint because uint64, uint64 types are not Blueprint-compatible + FInsertViewPkMembershipSecondaryHandler OnInsertViewPkMembershipSecondary; + + // NOTE: Not exposed to Blueprint because uint64, uint64 types are not Blueprint-compatible + void InsertViewPkMembershipSecondary(const uint64 Id, const uint64 PlayerId); + + bool InvokeInsertViewPkMembershipSecondary(const FReducerEventContext& Context, const UInsertViewPkMembershipSecondaryReducer* Args); + bool InvokeInsertViewPkMembershipSecondaryWithArgs(const FReducerEventContext& Context, const FInsertViewPkMembershipSecondaryArgs& Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FInsertViewPkPlayerHandler, + const FReducerEventContext&, Context, + uint64, Id, + const FString&, Name + ); + // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible + FInsertViewPkPlayerHandler OnInsertViewPkPlayer; + + // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible + void InsertViewPkPlayer(const uint64 Id, const FString& Name); + + bool InvokeInsertViewPkPlayer(const FReducerEventContext& Context, const UInsertViewPkPlayerReducer* Args); + bool InvokeInsertViewPkPlayerWithArgs(const FReducerEventContext& Context, const FInsertViewPkPlayerArgs& Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FUpdateViewPkPlayerHandler, + const FReducerEventContext&, Context, + uint64, Id, + const FString&, Name + ); + // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible + FUpdateViewPkPlayerHandler OnUpdateViewPkPlayer; + + // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible + void UpdateViewPkPlayer(const uint64 Id, const FString& Name); + + bool InvokeUpdateViewPkPlayer(const FReducerEventContext& Context, const UUpdateViewPkPlayerReducer* Args); + bool InvokeUpdateViewPkPlayerWithArgs(const FReducerEventContext& Context, const FUpdateViewPkPlayerArgs& Args); + + // Internal error handling + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FInternalOnUnhandledReducerError, const FReducerEventContext&, Context, const FString&, Error); + FInternalOnUnhandledReducerError InternalOnUnhandledReducerError; + +private: + + friend UDbConnection; + + UPROPERTY() + class UDbConnection* Conn; +}; + +// RemoteProcedures class +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API URemoteProcedures : public UObject +{ + GENERATED_BODY() + +public: + + // Internal error handling + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FInternalOnUnhandledProcedureError, const FProcedureEventContext&, Context, const FString&, Error); + FInternalOnUnhandledProcedureError InternalOnUnhandledProcedureError; + +private: + + friend UDbConnection; + + UPROPERTY() + class UDbConnection* Conn; +}; + +// QueryBuilder types +struct TESTVIEWPKCLIENT_API FViewPkPlayerCols +{ + explicit FViewPkPlayerCols(const char* TableName) + : Id(TableName, "id"), Name(TableName, "name") {} + + ::SpacetimeDB::query_builder::Col Id; + ::SpacetimeDB::query_builder::Col Name; +}; + +struct TESTVIEWPKCLIENT_API FViewPkPlayerIxCols +{ + explicit FViewPkPlayerIxCols(const char* TableName) + : Id(TableName, "id") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t Id; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FViewPkPlayerCols get(const char* table_name) { return FViewPkPlayerCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FViewPkPlayerIxCols get(const char* table_name) { return FViewPkPlayerIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTVIEWPKCLIENT_API FViewPkMembershipCols +{ + explicit FViewPkMembershipCols(const char* TableName) + : Id(TableName, "id"), PlayerId(TableName, "player_id") {} + + ::SpacetimeDB::query_builder::Col Id; + ::SpacetimeDB::query_builder::Col PlayerId; +}; + +struct TESTVIEWPKCLIENT_API FViewPkMembershipIxCols +{ + explicit FViewPkMembershipIxCols(const char* TableName) + : Id(TableName, "id"), PlayerId(TableName, "player_id") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t Id; + ::SpacetimeDB::query_builder::detail::ix_col_member_t PlayerId; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FViewPkMembershipCols get(const char* table_name) { return FViewPkMembershipCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FViewPkMembershipIxCols get(const char* table_name) { return FViewPkMembershipIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTVIEWPKCLIENT_API FViewPkMembershipSecondaryCols +{ + explicit FViewPkMembershipSecondaryCols(const char* TableName) + : Id(TableName, "id"), PlayerId(TableName, "player_id") {} + + ::SpacetimeDB::query_builder::Col Id; + ::SpacetimeDB::query_builder::Col PlayerId; +}; + +struct TESTVIEWPKCLIENT_API FViewPkMembershipSecondaryIxCols +{ + explicit FViewPkMembershipSecondaryIxCols(const char* TableName) + : Id(TableName, "id"), PlayerId(TableName, "player_id") {} + + ::SpacetimeDB::query_builder::detail::ix_col_member_t Id; + ::SpacetimeDB::query_builder::detail::ix_col_member_t PlayerId; +}; + +namespace SpacetimeDB::query_builder +{ + inline std::true_type indexed_member_lookup(member_tag); + inline std::true_type indexed_member_lookup(member_tag); + + template<> + struct HasCols + { + static FViewPkMembershipSecondaryCols get(const char* table_name) { return FViewPkMembershipSecondaryCols(table_name); } + }; + + template<> + struct HasIxCols + { + static FViewPkMembershipSecondaryIxCols get(const char* table_name) { return FViewPkMembershipSecondaryIxCols(table_name); } + }; + + template<> + struct CanBeLookupTable : std::true_type {}; +} + +struct TESTVIEWPKCLIENT_API FFrom +{ + [[nodiscard]] ::SpacetimeDB::query_builder::Table AllViewPkPlayers() const { return ::SpacetimeDB::query_builder::Table("all_view_pk_players"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table SenderViewPkPlayersA() const { return ::SpacetimeDB::query_builder::Table("sender_view_pk_players_a"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table SenderViewPkPlayersB() const { return ::SpacetimeDB::query_builder::Table("sender_view_pk_players_b"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ViewPkMembership() const { return ::SpacetimeDB::query_builder::Table("view_pk_membership"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ViewPkMembershipSecondary() const { return ::SpacetimeDB::query_builder::Table("view_pk_membership_secondary"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ViewPkPlayer() const { return ::SpacetimeDB::query_builder::Table("view_pk_player"); } +}; + +struct TESTVIEWPKCLIENT_API FQueryBuilder +{ + FFrom From; + + static TArray AllTablesSqlQueries() + { + TArray Sql; + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.AllViewPkPlayers().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.SenderViewPkPlayersA().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.SenderViewPkPlayersB().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.ViewPkMembership().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.ViewPkMembershipSecondary().into_sql().c_str()))); + Sql.Add(FString(UTF8_TO_TCHAR(FQueryBuilder().From.ViewPkPlayer().into_sql().c_str()))); + return Sql; + } +}; + +struct TESTVIEWPKCLIENT_API FTypedSubscriptionBuilder +{ + explicit FTypedSubscriptionBuilder(UDbConnection* InConn) + : Conn(InConn) {} + + FTypedSubscriptionBuilder& OnApplied(FOnSubscriptionApplied Callback); + FTypedSubscriptionBuilder& OnError(FOnSubscriptionError Callback); + + template + FTypedSubscriptionBuilder& AddQuery(TFn&& Build) + { + FQueryBuilder Q; + auto Query = std::forward(Build)(Q); + static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn, + "Typed subscription queries must return a query_builder table/query expression."); + Sql.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str()))); + return *this; + } + + USubscriptionHandle* Subscribe(); + +private: + UDbConnection* Conn = nullptr; + TArray Sql; + FOnSubscriptionApplied OnAppliedDelegateInternal; + FOnSubscriptionError OnErrorDelegateInternal; +}; + +// SubscriptionBuilder class +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase +{ + GENERATED_BODY() + +public: + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + USubscriptionBuilder* OnApplied(FOnSubscriptionApplied Callback); + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + USubscriptionBuilder* OnError(FOnSubscriptionError Callback); + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + USubscriptionHandle* Subscribe(const TArray& SQL); + + template + [[nodiscard]] FTypedSubscriptionBuilder AddQuery(TFn&& Build) + { + FTypedSubscriptionBuilder Typed(Conn); + Typed.OnApplied(OnAppliedDelegateInternal); + Typed.OnError(OnErrorDelegateInternal); + Typed.AddQuery(std::forward(Build)); + return Typed; + } + + /** Convenience for subscribing to all rows from all tables */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + USubscriptionHandle* SubscribeToAllTables(); + + + friend class UDbConnection; + friend class UDbConnectionBase; + +protected: + UPROPERTY() + class UDbConnection* Conn; + + // Delegates stored so Subscribe() can bind forwarding callbacks + FOnSubscriptionApplied OnAppliedDelegateInternal; + FOnSubscriptionError OnErrorDelegateInternal; +}; + +// SubscriptionHandle class +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API USubscriptionHandle : public USubscriptionHandleBase +{ + GENERATED_BODY() + +public: + + USubscriptionHandle() {}; + + explicit USubscriptionHandle(UDbConnection* InConn); + + friend class USubscriptionBuilder; + +private: + UPROPERTY() + class UDbConnection* Conn; + + // Delegates that expose subscription events with connection aware contexts + FOnSubscriptionApplied OnAppliedDelegate; + FOnSubscriptionError OnErrorDelegate; + + UFUNCTION() + void ForwardOnApplied(const FSubscriptionEventContextBase& BaseCtx); + + UFUNCTION() + void ForwardOnError(const FErrorContextBase& BaseCtx); +}; + +/* + @Note: Child class of UDbConnectionBuilderBase. +*/ +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API UDbConnectionBuilder : public UDbConnectionBuilderBase +{ + GENERATED_BODY() +public: + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* WithUri(const FString& InUri); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* WithDatabaseName(const FString& InName); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* WithToken(const FString& InToken); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* WithCompression(const ESpacetimeDBCompression& InCompression); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* OnConnect(FOnConnectDelegate Callback); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* OnConnectError(FOnConnectErrorDelegate Callback); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* OnDisconnect(FOnDisconnectDelegate Callback); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnection* Build(); + +private: + + // Stored delegates which will be forwarded when the connection events occur. + FOnConnectDelegate OnConnectDelegateInternal; + FOnDisconnectDelegate OnDisconnectDelegateInternal; +}; + +// Main DbConnection class +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API UDbConnection : public UDbConnectionBase +{ + GENERATED_BODY() + +public: + explicit UDbConnection(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); + + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + URemoteTables* Db; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + URemoteReducers* Reducers; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + URemoteProcedures* Procedures; + + // Delegates that allow users to bind with the concrete connection type. + FOnConnectDelegate OnConnectDelegate; + FOnDisconnectDelegate OnDisconnectDelegate; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + USubscriptionBuilder* SubscriptionBuilder(); + + /** Static entry point for constructing a connection. */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB", DisplayName = "SpacetimeDB TestViewPkClient Builder") + static UDbConnectionBuilder* Builder(); + + // Error handling + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnUnhandledReducerError, const FReducerEventContext&, Context, const FString&, Error); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FOnUnhandledReducerError OnUnhandledReducerError; + + // Error handling + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnUnhandledProcedureError, const FProcedureEventContext&, Context, const FString&, Error); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FOnUnhandledProcedureError OnUnhandledProcedureError; + + +protected: + + // Hook up error handling to reducers and procedures + virtual void PostInitProperties() override; + + UFUNCTION() + void ForwardOnConnect(UDbConnectionBase* BaseConnection, FSpacetimeDBIdentity InIdentity, const FString& InToken); + UFUNCTION() + void ForwardOnDisconnect(UDbConnectionBase* BaseConnection, const FString& Error); + + UFUNCTION() + void OnUnhandledReducerErrorHandler(const FReducerEventContext& Context, const FString& Error); + + UFUNCTION() + void OnUnhandledProcedureErrorHandler(const FProcedureEventContext& Context, const FString& Error); + + // Override the DbConnectionBase methods to handle updates and events + virtual void DbUpdate(const FDatabaseUpdateType& Update, const FSpacetimeDBEvent& Event) override; + + // Override the reducer event handler to dispatch events to the appropriate reducers + virtual void ReducerEvent(const FReducerEvent& Event) override; + + // Override the reducer event failed handler + virtual void ReducerEventFailed(const FReducerEvent& Event, const FString ErrorMessage) override; + // Override the procedure event failed handler + virtual void ProcedureEventFailed(const FProcedureEvent& Event, const FString ErrorMessage) override; + + friend class USubscriptionBuilder; + friend class UDbConnectionBuilder; + friend class URemoteReducers; + + // Internal reducer correlation helpers (request_id -> typed reducer) + void RegisterPendingTypedReducer(uint32 RequestId, FReducer Reducer); + bool TryGetPendingTypedReducer(uint32 RequestId, FReducer& OutReducer) const; + bool TryTakePendingTypedReducer(uint32 RequestId, FReducer& OutReducer); + +private: + TMap PendingTypedReducers; +}; + diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/AllViewPkPlayersTable.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/AllViewPkPlayersTable.g.h new file mode 100644 index 00000000000..0a0879db4e1 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/AllViewPkPlayersTable.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/ViewPkPlayerType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "AllViewPkPlayersTable.g.generated.h" + +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API UAllViewPkPlayersTable : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for all_view_pk_players table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnAllViewPkPlayersInsert, + const FEventContext&, Context, + const FViewPkPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnAllViewPkPlayersUpdate, + const FEventContext&, Context, + const FViewPkPlayerType&, OldRow, + const FViewPkPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnAllViewPkPlayersDelete, + const FEventContext&, Context, + const FViewPkPlayerType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnAllViewPkPlayersInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnAllViewPkPlayersUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnAllViewPkPlayersDelete OnDelete; + +private: + const FString TableName = TEXT("all_view_pk_players"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/SenderViewPkPlayersATable.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/SenderViewPkPlayersATable.g.h new file mode 100644 index 00000000000..b0ee3b0a181 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/SenderViewPkPlayersATable.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/ViewPkPlayerType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "SenderViewPkPlayersATable.g.generated.h" + +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API USenderViewPkPlayersATable : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for sender_view_pk_players_a table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnSenderViewPkPlayersAInsert, + const FEventContext&, Context, + const FViewPkPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnSenderViewPkPlayersAUpdate, + const FEventContext&, Context, + const FViewPkPlayerType&, OldRow, + const FViewPkPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnSenderViewPkPlayersADelete, + const FEventContext&, Context, + const FViewPkPlayerType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnSenderViewPkPlayersAInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnSenderViewPkPlayersAUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnSenderViewPkPlayersADelete OnDelete; + +private: + const FString TableName = TEXT("sender_view_pk_players_a"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/SenderViewPkPlayersBTable.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/SenderViewPkPlayersBTable.g.h new file mode 100644 index 00000000000..c47ab25f1a3 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/SenderViewPkPlayersBTable.g.h @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/ViewPkPlayerType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "SenderViewPkPlayersBTable.g.generated.h" + +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API USenderViewPkPlayersBTable : public URemoteTable +{ + GENERATED_BODY() + +public: + void PostInitialize(); + + /** Update function for sender_view_pk_players_b table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnSenderViewPkPlayersBInsert, + const FEventContext&, Context, + const FViewPkPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnSenderViewPkPlayersBUpdate, + const FEventContext&, Context, + const FViewPkPlayerType&, OldRow, + const FViewPkPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnSenderViewPkPlayersBDelete, + const FEventContext&, Context, + const FViewPkPlayerType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnSenderViewPkPlayersBInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnSenderViewPkPlayersBUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnSenderViewPkPlayersBDelete OnDelete; + +private: + const FString TableName = TEXT("sender_view_pk_players_b"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/ViewPkMembershipSecondaryTable.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/ViewPkMembershipSecondaryTable.g.h new file mode 100644 index 00000000000..017c4f7d462 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/ViewPkMembershipSecondaryTable.g.h @@ -0,0 +1,141 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/ViewPkMembershipSecondaryType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "ViewPkMembershipSecondaryTable.g.generated.h" + +UCLASS(Blueprintable) +class TESTVIEWPKCLIENT_API UViewPkMembershipSecondaryIdUniqueIndex : public UObject +{ + GENERATED_BODY() + +private: + // Declare an instance of your templated helper. + // It's private because the UObject wrapper will expose its functionality. + FUniqueIndexHelper> IdIndexHelper; + +public: + UViewPkMembershipSecondaryIdUniqueIndex() + // Initialize the helper with the specific unique index name + : IdIndexHelper("id") { + } + + /** + * Finds a ViewPkMembershipSecondary by their unique id. + * @param Key The id to search for. + * @return The found FViewPkMembershipSecondaryType, or a default-constructed FViewPkMembershipSecondaryType if not found. + */ + // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible + FViewPkMembershipSecondaryType Find(uint64 Key) + { + // Simply delegate the call to the internal helper + return IdIndexHelper.FindUniqueIndex(Key); + } + + // A public setter to provide the cache to the helper after construction + // This is a common pattern when the cache might be created or provided by another system. + void SetCache(TSharedPtr> InViewPkMembershipSecondaryCache) + { + IdIndexHelper.Cache = InViewPkMembershipSecondaryCache; + } +}; +/***/ + +UCLASS(Blueprintable) +class UViewPkMembershipSecondaryPlayerIdIndex : public UObject +{ + GENERATED_BODY() + +public: + TArray Filter(const uint64& PlayerId) const + { + TArray OutResults; + + LocalCache->FindByMultiKeyBTreeIndex>( + OutResults, + TEXT("player_id"), + MakeTuple(PlayerId) + ); + + return OutResults; + } + + void SetCache(TSharedPtr> InCache) + { + LocalCache = InCache; + } + +private: + // NOTE: Not exposed to Blueprint because some parameter types are not Blueprint-compatible + void FilterPlayerId(TArray& OutResults, const uint64& PlayerId) + { + OutResults = Filter(PlayerId); + } + + TSharedPtr> LocalCache; +}; + +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API UViewPkMembershipSecondaryTable : public URemoteTable +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly) + UViewPkMembershipSecondaryIdUniqueIndex* Id; + + UPROPERTY(BlueprintReadOnly) + UViewPkMembershipSecondaryPlayerIdIndex* PlayerId; + + void PostInitialize(); + + /** Update function for view_pk_membership_secondary table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnViewPkMembershipSecondaryInsert, + const FEventContext&, Context, + const FViewPkMembershipSecondaryType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnViewPkMembershipSecondaryUpdate, + const FEventContext&, Context, + const FViewPkMembershipSecondaryType&, OldRow, + const FViewPkMembershipSecondaryType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnViewPkMembershipSecondaryDelete, + const FEventContext&, Context, + const FViewPkMembershipSecondaryType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnViewPkMembershipSecondaryInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnViewPkMembershipSecondaryUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnViewPkMembershipSecondaryDelete OnDelete; + +private: + const FString TableName = TEXT("view_pk_membership_secondary"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/ViewPkMembershipTable.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/ViewPkMembershipTable.g.h new file mode 100644 index 00000000000..bcb477f4801 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/ViewPkMembershipTable.g.h @@ -0,0 +1,141 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/ViewPkMembershipType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "ViewPkMembershipTable.g.generated.h" + +UCLASS(Blueprintable) +class TESTVIEWPKCLIENT_API UViewPkMembershipIdUniqueIndex : public UObject +{ + GENERATED_BODY() + +private: + // Declare an instance of your templated helper. + // It's private because the UObject wrapper will expose its functionality. + FUniqueIndexHelper> IdIndexHelper; + +public: + UViewPkMembershipIdUniqueIndex() + // Initialize the helper with the specific unique index name + : IdIndexHelper("id") { + } + + /** + * Finds a ViewPkMembership by their unique id. + * @param Key The id to search for. + * @return The found FViewPkMembershipType, or a default-constructed FViewPkMembershipType if not found. + */ + // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible + FViewPkMembershipType Find(uint64 Key) + { + // Simply delegate the call to the internal helper + return IdIndexHelper.FindUniqueIndex(Key); + } + + // A public setter to provide the cache to the helper after construction + // This is a common pattern when the cache might be created or provided by another system. + void SetCache(TSharedPtr> InViewPkMembershipCache) + { + IdIndexHelper.Cache = InViewPkMembershipCache; + } +}; +/***/ + +UCLASS(Blueprintable) +class UViewPkMembershipPlayerIdIndex : public UObject +{ + GENERATED_BODY() + +public: + TArray Filter(const uint64& PlayerId) const + { + TArray OutResults; + + LocalCache->FindByMultiKeyBTreeIndex>( + OutResults, + TEXT("player_id"), + MakeTuple(PlayerId) + ); + + return OutResults; + } + + void SetCache(TSharedPtr> InCache) + { + LocalCache = InCache; + } + +private: + // NOTE: Not exposed to Blueprint because some parameter types are not Blueprint-compatible + void FilterPlayerId(TArray& OutResults, const uint64& PlayerId) + { + OutResults = Filter(PlayerId); + } + + TSharedPtr> LocalCache; +}; + +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API UViewPkMembershipTable : public URemoteTable +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly) + UViewPkMembershipIdUniqueIndex* Id; + + UPROPERTY(BlueprintReadOnly) + UViewPkMembershipPlayerIdIndex* PlayerId; + + void PostInitialize(); + + /** Update function for view_pk_membership table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnViewPkMembershipInsert, + const FEventContext&, Context, + const FViewPkMembershipType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnViewPkMembershipUpdate, + const FEventContext&, Context, + const FViewPkMembershipType&, OldRow, + const FViewPkMembershipType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnViewPkMembershipDelete, + const FEventContext&, Context, + const FViewPkMembershipType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnViewPkMembershipInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnViewPkMembershipUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnViewPkMembershipDelete OnDelete; + +private: + const FString TableName = TEXT("view_pk_membership"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/ViewPkPlayerTable.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/ViewPkPlayerTable.g.h new file mode 100644 index 00000000000..380246018c2 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Tables/ViewPkPlayerTable.g.h @@ -0,0 +1,104 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Types/Builtins.h" +#include "ModuleBindings/Types/ViewPkPlayerType.g.h" +#include "Tables/RemoteTable.h" +#include "DBCache/WithBsatn.h" +#include "DBCache/TableHandle.h" +#include "DBCache/TableCache.h" +#include "ViewPkPlayerTable.g.generated.h" + +UCLASS(Blueprintable) +class TESTVIEWPKCLIENT_API UViewPkPlayerIdUniqueIndex : public UObject +{ + GENERATED_BODY() + +private: + // Declare an instance of your templated helper. + // It's private because the UObject wrapper will expose its functionality. + FUniqueIndexHelper> IdIndexHelper; + +public: + UViewPkPlayerIdUniqueIndex() + // Initialize the helper with the specific unique index name + : IdIndexHelper("id") { + } + + /** + * Finds a ViewPkPlayer by their unique id. + * @param Key The id to search for. + * @return The found FViewPkPlayerType, or a default-constructed FViewPkPlayerType if not found. + */ + // NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible + FViewPkPlayerType Find(uint64 Key) + { + // Simply delegate the call to the internal helper + return IdIndexHelper.FindUniqueIndex(Key); + } + + // A public setter to provide the cache to the helper after construction + // This is a common pattern when the cache might be created or provided by another system. + void SetCache(TSharedPtr> InViewPkPlayerCache) + { + IdIndexHelper.Cache = InViewPkPlayerCache; + } +}; +/***/ + +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API UViewPkPlayerTable : public URemoteTable +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly) + UViewPkPlayerIdUniqueIndex* Id; + + void PostInitialize(); + + /** Update function for view_pk_player table*/ + FTableAppliedDiff Update(TArray> InsertsRef, TArray> DeletesRef); + + /** Number of subscribed rows currently in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + int32 Count() const; + + /** Return all subscribed rows in the cache */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + TArray Iter() const; + + // Table Events + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnViewPkPlayerInsert, + const FEventContext&, Context, + const FViewPkPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( + FOnViewPkPlayerUpdate, + const FEventContext&, Context, + const FViewPkPlayerType&, OldRow, + const FViewPkPlayerType&, NewRow); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FOnViewPkPlayerDelete, + const FEventContext&, Context, + const FViewPkPlayerType&, DeletedRow); + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnViewPkPlayerInsert OnInsert; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnViewPkPlayerUpdate OnUpdate; + + UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events") + FOnViewPkPlayerDelete OnDelete; + +private: + const FString TableName = TEXT("view_pk_player"); + + TSharedPtr> Data; +}; diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Types/ViewPkMembershipSecondaryType.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Types/ViewPkMembershipSecondaryType.g.h new file mode 100644 index 00000000000..aa50b8d2b77 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Types/ViewPkMembershipSecondaryType.g.h @@ -0,0 +1,49 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ViewPkMembershipSecondaryType.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FViewPkMembershipSecondaryType +{ + GENERATED_BODY() + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Id = 0; + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 PlayerId = 0; + + FORCEINLINE bool operator==(const FViewPkMembershipSecondaryType& Other) const + { + return Id == Other.Id && PlayerId == Other.PlayerId; + } + + FORCEINLINE bool operator!=(const FViewPkMembershipSecondaryType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FViewPkMembershipSecondaryType. + * Combines the hashes of all fields that are compared in operator==. + * @param ViewPkMembershipSecondaryType The FViewPkMembershipSecondaryType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FViewPkMembershipSecondaryType& ViewPkMembershipSecondaryType) +{ + uint32 Hash = GetTypeHash(ViewPkMembershipSecondaryType.Id); + Hash = HashCombine(Hash, GetTypeHash(ViewPkMembershipSecondaryType.PlayerId)); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FViewPkMembershipSecondaryType); + + UE_SPACETIMEDB_STRUCT(FViewPkMembershipSecondaryType, Id, PlayerId); +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Types/ViewPkMembershipType.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Types/ViewPkMembershipType.g.h new file mode 100644 index 00000000000..77842753aab --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Types/ViewPkMembershipType.g.h @@ -0,0 +1,49 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ViewPkMembershipType.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FViewPkMembershipType +{ + GENERATED_BODY() + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Id = 0; + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 PlayerId = 0; + + FORCEINLINE bool operator==(const FViewPkMembershipType& Other) const + { + return Id == Other.Id && PlayerId == Other.PlayerId; + } + + FORCEINLINE bool operator!=(const FViewPkMembershipType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FViewPkMembershipType. + * Combines the hashes of all fields that are compared in operator==. + * @param ViewPkMembershipType The FViewPkMembershipType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FViewPkMembershipType& ViewPkMembershipType) +{ + uint32 Hash = GetTypeHash(ViewPkMembershipType.Id); + Hash = HashCombine(Hash, GetTypeHash(ViewPkMembershipType.PlayerId)); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FViewPkMembershipType); + + UE_SPACETIMEDB_STRUCT(FViewPkMembershipType, Id, PlayerId); +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Types/ViewPkPlayerType.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Types/ViewPkPlayerType.g.h new file mode 100644 index 00000000000..afb955b37ef --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/Types/ViewPkPlayerType.g.h @@ -0,0 +1,49 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "ViewPkPlayerType.g.generated.h" + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FViewPkPlayerType +{ + GENERATED_BODY() + + // NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements + uint64 Id = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + FString Name; + + FORCEINLINE bool operator==(const FViewPkPlayerType& Other) const + { + return Id == Other.Id && Name == Other.Name; + } + + FORCEINLINE bool operator!=(const FViewPkPlayerType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FViewPkPlayerType. + * Combines the hashes of all fields that are compared in operator==. + * @param ViewPkPlayerType The FViewPkPlayerType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FViewPkPlayerType& ViewPkPlayerType) +{ + uint32 Hash = GetTypeHash(ViewPkPlayerType.Id); + Hash = HashCombine(Hash, GetTypeHash(ViewPkPlayerType.Name)); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FViewPkPlayerType); + + UE_SPACETIMEDB_STRUCT(FViewPkPlayerType, Id, Name); +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/CommonTestFunctions.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/CommonTestFunctions.h new file mode 100644 index 00000000000..b0e2c2666e6 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/CommonTestFunctions.h @@ -0,0 +1,74 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "Tests/TestCounter.h" + +#include "Connection/Callback.h" +#include "Connection/Credentials.h" +#include "ModuleBindings/SpacetimeDBClient.g.h" + +#include "CommonTestFunctions.generated.h" + +#define TESTLOG_SUCCESS(Test, Format, ...) \ + do \ + { \ + const FString UserMessage = FString::Printf(Format, ##__VA_ARGS__); \ + const FString LogMessage = FString::Printf(TEXT(" + %s"), *UserMessage); \ + UE_LOG(LogTemp, Log, TEXT("%s"), *LogMessage); \ + Test.AddInfo(LogMessage); \ + } while (false) + +#define TESTLOG_FAIL(Test, Format, ...) \ + do \ + { \ + const FString UserMessage = FString::Printf(Format, ##__VA_ARGS__); \ + const FString LogMessage = FString::Printf(TEXT(" x %s"), *UserMessage); \ + UE_LOG(LogTemp, Error, TEXT("%s"), *LogMessage); \ + Test.AddError(LogMessage); \ + } while (false) + +UCLASS() +class TESTVIEWPKCLIENT_API UTestHelperDelegates : public UObject +{ + GENERATED_BODY() + +public: + TFunction OnConnect; + UFUNCTION() + void HandleConnect(UDbConnection* Conn, FSpacetimeDBIdentity Identity, const FString& Token); + + TFunction OnConnectError; + UFUNCTION() + void HandleConnectError(UDbConnection* Conn, const FString& Error); + + TFunction OnDisconnect; + UFUNCTION() + void HandleDisconnect(UDbConnection* Conn, const FString& Error); + + TFunction OnSubscriptionApplied; + UFUNCTION() + void HandleSubscriptionApplied(FSubscriptionEventContext Ctx); + + TFunction OnSubscriptionError; + UFUNCTION() + void HandleSubscriptionError(FErrorContext Ctx); +}; + +UDbConnection* ConnectThen( + TSharedPtr Counter, + const FString& TestName, + TFunction Callback); + +bool GetDbName(FString& DBName, FString& Error); +bool ValidateParameterConfig(FAutomationTestBase* Test); +bool ReportTestResult(FAutomationTestBase& Test, const FString& TestName, TSharedPtr Counter, bool bTimedOut); + +template +T* CreateTestHandler() +{ + T* Handler = NewObject(GetTransientPackage()); + Handler->AddToRoot(); + Handler->Counter = MakeShared(); + return Handler; +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/PrimitiveHandlerList.def b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/PrimitiveHandlerList.def new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/PrimitiveHandlerList.def @@ -0,0 +1 @@ + diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/SpacetimeFullClientTests.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/SpacetimeFullClientTests.h new file mode 100644 index 00000000000..884dc30efa9 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/SpacetimeFullClientTests.h @@ -0,0 +1,29 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "Tests/TestHandler.h" + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FViewPkQueryBuilderDirectSourcesTest, + "SpacetimeDB.TestViewPkClient.ViewPkQueryBuilderDirectSourcesTest", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FViewPkQueryBuilderSemijoinTest, + "SpacetimeDB.TestViewPkClient.ViewPkQueryBuilderSemijoinTest", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FViewPkSubscribeAllTablesTest, + "SpacetimeDB.TestViewPkClient.ViewPkSubscribeAllTablesTest", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FViewPkRuntimeUpdatePairingTest, + "SpacetimeDB.TestViewPkClient.ViewPkRuntimeUpdatePairingTest", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/TestCounter.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/TestCounter.h new file mode 100644 index 00000000000..35b52debcb5 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/TestCounter.h @@ -0,0 +1,35 @@ +#pragma once + +#include "CoreMinimal.h" +#include "HAL/CriticalSection.h" + +struct FTestOutcome +{ + bool bSuccess = false; + FString Error; +}; + +class FTestCounter : public TSharedFromThis +{ +public: + FTestCounter() = default; + + void Register(const FString& TestName); + void MarkSuccess(const FString& TestName); + void MarkFailure(const FString& TestName, const FString& Error); + + bool IsComplete() const; + bool AllSucceeded() const; + TArray GetFailures() const; + TArray GetSuccesses() const; + + void Abort(); + bool IsAborted() const { return bAborted; } + + +private: + mutable FCriticalSection Mutex; + TMap Outcomes; + TSet Registered; + bool bAborted = false; +}; \ No newline at end of file diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/TestHandler.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/TestHandler.h new file mode 100644 index 00000000000..cf36e740c98 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/TestHandler.h @@ -0,0 +1,47 @@ +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" + +#include "ModuleBindings/SpacetimeDBClient.g.h" +#include "Tests/TestCounter.h" + +#include "TestHandler.generated.h" + +UCLASS() +class TESTVIEWPKCLIENT_API UTestHandler : public UObject +{ + GENERATED_BODY() + +public: + TSharedPtr Counter; +}; + +UCLASS() +class TESTVIEWPKCLIENT_API UViewPkRuntimeHandler : public UTestHandler +{ + GENERATED_BODY() + +public: + uint64 ExpectedId = 1; + FString InitialName = TEXT("before"); + FString UpdatedName = TEXT("after"); + + UFUNCTION() + void OnAllViewPkPlayersInsert(const FEventContext& Context, const FViewPkPlayerType& Value); + + UFUNCTION() + void OnAllViewPkPlayersUpdate(const FEventContext& Context, const FViewPkPlayerType& OldValue, const FViewPkPlayerType& NewValue); + + UFUNCTION() + void OnAllViewPkPlayersDelete(const FEventContext& Context, const FViewPkPlayerType& Value); + + UFUNCTION() + void OnSenderViewPkPlayersAInsert(const FEventContext& Context, const FViewPkPlayerType& Value); + + UFUNCTION() + void OnSenderViewPkPlayersAUpdate(const FEventContext& Context, const FViewPkPlayerType& OldValue, const FViewPkPlayerType& NewValue); + + UFUNCTION() + void OnSenderViewPkPlayersADelete(const FEventContext& Context, const FViewPkPlayerType& Value); +}; diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/UmbreallaHeaderReducers.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/UmbreallaHeaderReducers.h new file mode 100644 index 00000000000..6f70f09beec --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/UmbreallaHeaderReducers.h @@ -0,0 +1 @@ +#pragma once diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/UmbreallaHeaderTypes.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/UmbreallaHeaderTypes.h new file mode 100644 index 00000000000..6f70f09beec --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/UmbreallaHeaderTypes.h @@ -0,0 +1 @@ +#pragma once diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/UmbreallaHeaderaTables.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/UmbreallaHeaderaTables.h new file mode 100644 index 00000000000..6f70f09beec --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/UmbreallaHeaderaTables.h @@ -0,0 +1 @@ +#pragma once diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClient.Build.cs b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClient.Build.cs new file mode 100644 index 00000000000..3567944f689 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClient.Build.cs @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using UnrealBuildTool; + +public class TestViewPkClient : ModuleRules +{ + public TestViewPkClient(ReadOnlyTargetRules Target) : base(Target) + { + // Set the module type to be a standard module + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + // Set the module to use C++20 standard + CppStandard = CppStandardVersion.Cpp20; + + + // Enable exceptions for this module + bEnableExceptions = true; + + + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "SpacetimeDbSdk" }); + + PrivateDependencyModuleNames.AddRange(new string[] { "DeveloperSettings" }); + + } +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClient.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClient.cpp new file mode 100644 index 00000000000..7d8a2ef715d --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClient.cpp @@ -0,0 +1,6 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "TestViewPkClient.h" +#include "Modules/ModuleManager.h" + +IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, TestViewPkClient, "TestViewPkClient"); diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClient.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClient.h new file mode 100644 index 00000000000..90aad9e7e22 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClient.h @@ -0,0 +1,6 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" + diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClientGameModeBase.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClientGameModeBase.cpp new file mode 100644 index 00000000000..674d6a37ebb --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClientGameModeBase.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "TestViewPkClientGameModeBase.h" + diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClientGameModeBase.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClientGameModeBase.h new file mode 100644 index 00000000000..f041de9c976 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/TestViewPkClientGameModeBase.h @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/GameModeBase.h" +#include "TestViewPkClientGameModeBase.generated.h" + +/** + * + */ +UCLASS() +class TESTVIEWPKCLIENT_API ATestViewPkClientGameModeBase : public AGameModeBase +{ + GENERATED_BODY() + +}; diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClientEditor.Target.cs b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClientEditor.Target.cs new file mode 100644 index 00000000000..b8438c36e51 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClientEditor.Target.cs @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class TestViewPkClientEditorTarget : TargetRules +{ + public TestViewPkClientEditorTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Editor; + DefaultBuildSettings = BuildSettingsVersion.V5; + + ExtraModuleNames.AddRange( new string[] { "TestViewPkClient" } ); + } +} diff --git a/sdks/unreal/tests/TestViewPkClient/TestViewPkClient.uproject b/sdks/unreal/tests/TestViewPkClient/TestViewPkClient.uproject new file mode 100644 index 00000000000..f9be1f0cca1 --- /dev/null +++ b/sdks/unreal/tests/TestViewPkClient/TestViewPkClient.uproject @@ -0,0 +1,25 @@ +{ + "FileVersion": 3, + "EngineAssociation": "5.6", + "Category": "", + "Description": "", + "Modules": [ + { + "Name": "TestViewPkClient", + "Type": "Runtime", + "LoadingPhase": "Default" + } + ], + "Plugins": [ + { + "Name": "ModelingToolsEditorMode", + "Enabled": true, + "TargetAllowList": [ + "Editor" + ] + } + ], + "AdditionalPluginDirectories": [ + "../../src" + ] +} diff --git a/sdks/unreal/tests/test_view.rs b/sdks/unreal/tests/test_view.rs new file mode 100644 index 00000000000..e0863669e5f --- /dev/null +++ b/sdks/unreal/tests/test_view.rs @@ -0,0 +1,28 @@ +mod sdk_unreal_harness; +use sdk_unreal_harness::{make_test_with_suite, TestSuite}; + +use serial_test::serial; +use std::env; + +const SDK_TEST_SUITE: TestSuite = TestSuite { + module: "sdk-test-view", + client_root: concat!(env!("CARGO_MANIFEST_DIR"), "/tests/TestViewClient"), + unreal_module: "TestViewClient", + uproject_file: "TestViewClient.uproject", +}; + +fn make_test(test_name: &str) -> spacetimedb_testing::sdk::Test { + make_test_with_suite(&SDK_TEST_SUITE, test_name) +} + +#[test] +#[serial(ViewGroup)] +fn unreal_view_query_builder_direct_sources() { + make_test("ViewQueryBuilderDirectSourcesTest").run(); +} + +#[test] +#[serial(ViewGroup)] +fn unreal_view_subscribe_all_tables() { + make_test("ViewSubscribeAllTablesTest").run(); +} diff --git a/sdks/unreal/tests/test_view_pk.rs b/sdks/unreal/tests/test_view_pk.rs new file mode 100644 index 00000000000..665d8113cf2 --- /dev/null +++ b/sdks/unreal/tests/test_view_pk.rs @@ -0,0 +1,40 @@ +mod sdk_unreal_harness; +use sdk_unreal_harness::{make_test_with_suite, TestSuite}; + +use serial_test::serial; +use std::env; + +const SDK_TEST_SUITE: TestSuite = TestSuite { + module: "sdk-test-view-pk", + client_root: concat!(env!("CARGO_MANIFEST_DIR"), "/tests/TestViewPkClient"), + unreal_module: "TestViewPkClient", + uproject_file: "TestViewPkClient.uproject", +}; + +fn make_test(test_name: &str) -> spacetimedb_testing::sdk::Test { + make_test_with_suite(&SDK_TEST_SUITE, test_name) +} + +#[test] +#[serial(ViewPkGroup)] +fn unreal_view_pk_query_builder_direct_sources() { + make_test("ViewPkQueryBuilderDirectSourcesTest").run(); +} + +#[test] +#[serial(ViewPkGroup)] +fn unreal_view_pk_query_builder_semijoin() { + make_test("ViewPkQueryBuilderSemijoinTest").run(); +} + +#[test] +#[serial(ViewPkGroup)] +fn unreal_view_pk_subscribe_all_tables() { + make_test("ViewPkSubscribeAllTablesTest").run(); +} + +#[test] +#[serial(ViewPkGroup)] +fn unreal_view_pk_runtime_update_pairing() { + make_test("ViewPkRuntimeUpdatePairingTest").run(); +} From 4bcd055cc40080074f03663386be87c2e00604e0 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Mon, 23 Mar 2026 16:02:35 -0700 Subject: [PATCH 2/4] Refactor to switch the query builder to pass cols + indexes with the table metadata --- crates/codegen/src/unrealcpp.rs | 228 +- .../SpacetimeDbSdk/Public/QueryBuilder/join.h | 315 +-- .../Public/QueryBuilder/query_builder.h | 85 +- .../Public/QueryBuilder/table.h | 171 +- .../ModuleBindings/SpacetimeDBClient.g.h | 2158 ++++------------- .../Types/EnumWithPayloadType.g.h | 4 +- .../ModuleBindings/SpacetimeDBClient.g.h | 59 +- .../ModuleBindings/Types/ReturnEnumType.g.h | 2 +- .../Tests/SpacetimeFullClientTests.cpp | 2 +- .../ModuleBindings/SpacetimeDBClient.g.h | 141 +- .../Tests/SpacetimeFullClientTests.cpp | 4 +- .../ModuleBindings/SpacetimeDBClient.g.h | 150 +- 12 files changed, 986 insertions(+), 2333 deletions(-) diff --git a/crates/codegen/src/unrealcpp.rs b/crates/codegen/src/unrealcpp.rs index ec17b383ad8..c66c7d5fb76 100644 --- a/crates/codegen/src/unrealcpp.rs +++ b/crates/codegen/src/unrealcpp.rs @@ -1,7 +1,7 @@ //! Autogenerated Unreal‑C++ code‑gen backend for SpacetimeDB CLI use crate::code_indenter::CodeIndenter; use crate::util::{ - fmt_fn, iter_table_names_and_types, iter_tables, print_auto_generated_file_comment, + fmt_fn, iter_table_names_and_types, iter_tables, iter_views, print_auto_generated_file_comment, print_auto_generated_version_comment, CodegenVisibility, }; use crate::util::{iter_indexes, iter_procedures, iter_reducers}; @@ -16,6 +16,7 @@ use spacetimedb_schema::schema::{Schema, TableSchema}; use spacetimedb_schema::type_for_generate::{ AlgebraicTypeDef, AlgebraicTypeUse, PlainEnumTypeDef, ProductTypeDef, SumTypeDef, }; +use std::collections::HashMap; use std::fmt::{self}; use std::ops::Deref; use std::path::Path; @@ -2974,51 +2975,50 @@ fn generate_query_builder_types( api_macro: &str, module_name: &str, ) { - struct QueryBuilderRowMeta { + struct QueryBuilderSourceMeta { row_struct: String, cols_struct: String, ix_cols_struct: String, fields: Vec<(String, String, String)>, singleton_indexed_fields: Vec, + source_name: String, + source_pascal: String, can_be_lookup: bool, } writeln!(output, "// QueryBuilder types"); - let mut row_metas = Vec::::new(); + let mut source_metas = Vec::::new(); - for (table_name, _accessor_name, product_type_ref) in iter_table_names_and_types(module, visibility) { - let product_type = module.typespace_for_generate()[product_type_ref] + let singleton_indexed_fields_for_schema = |schema: &TableSchema, product_type: &ProductTypeDef| { + let mut singleton_indexed_fields = Vec::::new(); + for (columns, constraints) in schema.backcompat_column_constraints() { + if columns.len() != 1 { + continue; + } + if !(constraints.has_indexed() || constraints.has_unique() || constraints.has_primary_key()) { + continue; + } + let col_idx = columns.iter().next().expect("singleton column").idx(); + let (field_name, _) = &product_type.elements[col_idx]; + singleton_indexed_fields.push(field_name.deref().to_case(Case::Pascal)); + } + singleton_indexed_fields + }; + + for table in iter_tables(module, visibility) { + let product_type = module.typespace_for_generate()[table.product_type_ref] .as_product() .expect("query builder source should be a product type"); - let row_struct = format!("F{}Type", type_ref_name(module_prefix, module, product_type_ref)); - let row_type_name = row_struct - .strip_suffix("Type") - .expect("row struct should end with Type") - .to_string(); - - let is_event = iter_tables(module, visibility) - .find(|table| table.name == *table_name) - .map(|table| table.is_event) - .unwrap_or(false); - - let singleton_indexed_fields: Vec = iter_tables(module, visibility) - .find(|table| table.name == *table_name) - .map(|table| { - let table_product_type = module.typespace_for_generate()[table.product_type_ref] - .as_product() - .expect("table schema should be a product type"); - iter_indexes(table) - .filter_map(|idx| { - let col = idx.algorithm.columns().as_singleton()?; - let (field_name, _) = &table_product_type.elements[col.idx()]; - Some(field_name.deref().to_case(Case::Pascal)) - }) - .collect() - }) - .unwrap_or_default(); + let row_struct = format!("F{}Type", type_ref_name(module_prefix, module, table.product_type_ref)); + let source_pascal = table.accessor_name.deref().to_case(Case::Pascal); + let schema = TableSchema::from_module_def(module, table, (), 0.into()) + .validated() + .expect("table schema should validate for query builder codegen"); - let row_fields = product_type + let singleton_indexed_fields = singleton_indexed_fields_for_schema(&schema, product_type); + + let fields = product_type .elements .iter() .map(|(field_name, field_ty)| { @@ -3030,39 +3030,94 @@ fn generate_query_builder_types( }) .collect::>(); - if let Some(existing) = row_metas.iter_mut().find(|meta| meta.row_struct == row_struct) { - for field_name in singleton_indexed_fields { - if !existing.singleton_indexed_fields.contains(&field_name) { - existing.singleton_indexed_fields.push(field_name); - } - } - if !is_event { - existing.can_be_lookup = true; - } - continue; - } + source_metas.push(QueryBuilderSourceMeta { + row_struct, + cols_struct: format!("F{source_pascal}Cols"), + ix_cols_struct: format!("F{source_pascal}IxCols"), + fields, + singleton_indexed_fields, + source_name: table.name.deref().to_string(), + source_pascal, + can_be_lookup: !table.is_event, + }); + } + + for view in iter_views(module) { + let product_type = module.typespace_for_generate()[view.product_type_ref] + .as_product() + .expect("query builder source should be a product type"); + let row_struct = format!("F{}Type", type_ref_name(module_prefix, module, view.product_type_ref)); + let source_pascal = view.accessor_name.deref().to_case(Case::Pascal); + let schema = TableSchema::from_view_def_for_codegen(module, view) + .validated() + .expect("view schema should validate for query builder codegen"); + + let singleton_indexed_fields = singleton_indexed_fields_for_schema(&schema, product_type); + + let fields = product_type + .elements + .iter() + .map(|(field_name, field_ty)| { + ( + field_name.deref().to_string(), + field_name.deref().to_case(Case::Pascal), + cpp_ty_fmt_with_module(module_prefix, module, field_ty, module_name).to_string(), + ) + }) + .collect::>(); - row_metas.push(QueryBuilderRowMeta { + source_metas.push(QueryBuilderSourceMeta { row_struct, - cols_struct: format!("{row_type_name}Cols"), - ix_cols_struct: format!("{row_type_name}IxCols"), - fields: row_fields, + cols_struct: format!("F{source_pascal}Cols"), + ix_cols_struct: format!("F{source_pascal}IxCols"), + fields, singleton_indexed_fields, - can_be_lookup: !is_event, + source_name: view.name.deref().to_string(), + source_pascal, + can_be_lookup: true, }); } - for row_meta in &row_metas { - let row_struct = &row_meta.row_struct; - let cols_struct = &row_meta.cols_struct; - let ix_cols_struct = &row_meta.ix_cols_struct; - let singleton_indexed_fields = &row_meta.singleton_indexed_fields; + let mut row_struct_counts = HashMap::::new(); + for source_meta in &source_metas { + *row_struct_counts.entry(source_meta.row_struct.clone()).or_default() += 1; + } + for source_meta in &mut source_metas { + if row_struct_counts.get(&source_meta.row_struct).copied().unwrap_or_default() == 1 { + let row_type_name = source_meta + .row_struct + .strip_prefix('F') + .and_then(|name| name.strip_suffix("Type")) + .expect("row struct should match F*Type"); + source_meta.cols_struct = format!("F{row_type_name}Cols"); + source_meta.ix_cols_struct = format!("F{row_type_name}IxCols"); + } + } + + source_metas.sort_by(|a, b| a.source_pascal.cmp(&b.source_pascal)); + + let mut declared_helper_structs = HashSet::::new(); + for source_meta in &source_metas { + if declared_helper_structs.insert(source_meta.cols_struct.clone()) { + writeln!(output, "struct {api_macro} {};", source_meta.cols_struct); + } + if declared_helper_structs.insert(source_meta.ix_cols_struct.clone()) { + writeln!(output, "struct {api_macro} {};", source_meta.ix_cols_struct); + } + } + writeln!(output); + + for source_meta in &source_metas { + let row_struct = &source_meta.row_struct; + let cols_struct = &source_meta.cols_struct; + let ix_cols_struct = &source_meta.ix_cols_struct; + let singleton_indexed_fields = &source_meta.singleton_indexed_fields; writeln!(output, "struct {api_macro} {cols_struct}"); writeln!(output, "{{"); writeln!(output, " explicit {cols_struct}(const char* TableName)"); write!(output, " : "); - for (idx, (field_name_raw, field_name_pascal, _field_type)) in row_meta.fields.iter().enumerate() { + for (idx, (field_name_raw, field_name_pascal, _field_type)) in source_meta.fields.iter().enumerate() { if idx > 0 { write!(output, ", "); } @@ -3075,7 +3130,7 @@ fn generate_query_builder_types( } writeln!(output, " {{}}"); writeln!(output); - for (_field_name_raw, field_name_pascal, field_type) in &row_meta.fields { + for (_field_name_raw, field_name_pascal, field_type) in &source_meta.fields { writeln!( output, " ::SpacetimeDB::query_builder::Col<{row_struct}, {field_type}> {field_name_pascal};" @@ -3089,7 +3144,7 @@ fn generate_query_builder_types( writeln!(output, " explicit {ix_cols_struct}(const char* TableName)"); if !singleton_indexed_fields.is_empty() { write!(output, " : "); - for (idx, (field_name_raw, field_name_pascal, _field_type)) in row_meta + for (idx, (field_name_raw, field_name_pascal, _field_type)) in source_meta .fields .iter() .filter(|(_field_name_raw, field_name_pascal, _)| singleton_indexed_fields.contains(field_name_pascal)) @@ -3108,66 +3163,45 @@ fn generate_query_builder_types( } writeln!(output, " {{}}"); writeln!(output); - for (_field_name_raw, field_name_pascal, field_type) in row_meta + for (_field_name_raw, field_name_pascal, field_type) in source_meta .fields .iter() .filter(|(_field_name_raw, field_name_pascal, _)| singleton_indexed_fields.contains(field_name_pascal)) { writeln!( output, - " ::SpacetimeDB::query_builder::detail::ix_col_member_t<{row_struct}, {field_type}, &{row_struct}::{field_name_pascal}> {field_name_pascal};" + " ::SpacetimeDB::query_builder::IxCol<{row_struct}, {field_type}> {field_name_pascal};" ); } writeln!(output, "}};"); writeln!(output); - writeln!(output, "namespace SpacetimeDB::query_builder"); - writeln!(output, "{{"); - for field_name_pascal in singleton_indexed_fields { - writeln!( - output, - " inline std::true_type indexed_member_lookup(member_tag<{row_struct}, &{row_struct}::{field_name_pascal}>);" - ); - } - writeln!(output); - writeln!(output, " template<>"); - writeln!(output, " struct HasCols<{row_struct}>"); - writeln!(output, " {{"); - writeln!( - output, - " static {cols_struct} get(const char* table_name) {{ return {cols_struct}(table_name); }}" - ); - writeln!(output, " }};"); - writeln!(output); - writeln!(output, " template<>"); - writeln!(output, " struct HasIxCols<{row_struct}>"); - writeln!(output, " {{"); - writeln!( - output, - " static {ix_cols_struct} get(const char* table_name) {{ return {ix_cols_struct}(table_name); }}" - ); - writeln!(output, " }};"); - if row_meta.can_be_lookup { - writeln!(output); + if source_meta.can_be_lookup { + writeln!(output, "namespace SpacetimeDB::query_builder"); + writeln!(output, "{{"); writeln!(output, " template<>"); writeln!( output, - " struct CanBeLookupTable<{row_struct}> : std::true_type {{}};" + " struct CanBeLookupTable> : std::true_type {{}};" ); + writeln!(output, "}}"); + writeln!(output); } - writeln!(output, "}}"); - writeln!(output); } writeln!(output, "struct {api_macro} F{module_prefix}From"); writeln!(output, "{{"); - for (table_name, accessor_name, product_type_ref) in iter_table_names_and_types(module, visibility) { - let row_struct = format!("F{}Type", type_ref_name(module_prefix, module, product_type_ref)); - let source_pascal = accessor_name.deref().to_case(Case::Pascal); + for source_meta in &source_metas { + let row_struct = &source_meta.row_struct; + let source_pascal = &source_meta.source_pascal; + let cols_struct = &source_meta.cols_struct; + let ix_cols_struct = &source_meta.ix_cols_struct; writeln!( output, - " [[nodiscard]] ::SpacetimeDB::query_builder::Table<{row_struct}> {source_pascal}() const {{ return ::SpacetimeDB::query_builder::Table<{row_struct}>(\"{}\"); }}", - table_name.deref() + " [[nodiscard]] ::SpacetimeDB::query_builder::Table<{row_struct}, {cols_struct}, {ix_cols_struct}> {source_pascal}() const {{ return ::SpacetimeDB::query_builder::Table<{row_struct}, {cols_struct}, {ix_cols_struct}>(\"{}\", {cols_struct}(\"{}\"), {ix_cols_struct}(\"{}\")); }}", + source_meta.source_name, + source_meta.source_name, + source_meta.source_name ); } writeln!(output, "}};"); @@ -3180,8 +3214,8 @@ fn generate_query_builder_types( writeln!(output, " static TArray AllTablesSqlQueries()"); writeln!(output, " {{"); writeln!(output, " TArray Sql;"); - for (_table_name, accessor_name, _product_type_ref) in iter_table_names_and_types(module, visibility) { - let source_pascal = accessor_name.deref().to_case(Case::Pascal); + for source_meta in &source_metas { + let source_pascal = &source_meta.source_pascal; writeln!( output, " Sql.Add(FString(UTF8_TO_TCHAR(F{module_prefix}QueryBuilder().From.{source_pascal}().into_sql().c_str())));" @@ -3294,7 +3328,7 @@ fn generate_subscription_builder_class(output: &mut UnrealCppAutogen, module_pre writeln!(output); writeln!( output, - " /** Convenience for subscribing to all rows from all tables */" + " /** Convenience for subscribing to all rows from all public sources, including views */" ); writeln!(output, " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); writeln!( diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/join.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/join.h index dfc95c02736..4fe9e18c7a4 100644 --- a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/join.h +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/join.h @@ -11,14 +11,6 @@ namespace SpacetimeDB::query_builder { template struct IxJoinEq; -template -struct member_tag {}; - -inline std::false_type indexed_member_lookup(...); - -template -inline constexpr bool is_indexed_member_v = decltype(indexed_member_lookup(member_tag{}))::value; - template class IxCol { public: @@ -87,115 +79,44 @@ class IxCol { friend class IxCol; }; -namespace detail { - -template -inline constexpr bool delayed_is_indexed_member_v = is_indexed_member_v; - -template -class MaybeIxCol { -public: - constexpr MaybeIxCol() = default; - constexpr MaybeIxCol(const char* table_name, const char* column_name) - : column_(table_name, column_name) {} - - template - [[nodiscard]] auto eq(const MaybeIxCol& rhs) const { - static_assert( - is_indexed_member_v && is_indexed_member_v, - "Semijoin predicates may only use single-column indexed fields."); - return IxJoinEq{column_, rhs.column_}; - } - template - [[nodiscard]] auto Eq(const MaybeIxCol& rhs) const { - return eq(rhs); - } - - template - [[nodiscard]] BoolExpr eq(const TRhs& rhs) const { - return compare(BoolExpr::Kind::Eq, rhs); - } - template - [[nodiscard]] BoolExpr Eq(const TRhs& rhs) const { return eq(rhs); } - template - [[nodiscard]] BoolExpr ne(const TRhs& rhs) const { - return compare(BoolExpr::Kind::Ne, rhs); - } - template - [[nodiscard]] BoolExpr Neq(const TRhs& rhs) const { return ne(rhs); } - template - [[nodiscard]] BoolExpr gt(const TRhs& rhs) const { - return compare(BoolExpr::Kind::Gt, rhs); - } - template - [[nodiscard]] BoolExpr Gt(const TRhs& rhs) const { return gt(rhs); } - template - [[nodiscard]] BoolExpr lt(const TRhs& rhs) const { - return compare(BoolExpr::Kind::Lt, rhs); - } - template - [[nodiscard]] BoolExpr Lt(const TRhs& rhs) const { return lt(rhs); } - template - [[nodiscard]] BoolExpr gte(const TRhs& rhs) const { - return compare(BoolExpr::Kind::Gte, rhs); - } - template - [[nodiscard]] BoolExpr Gte(const TRhs& rhs) const { return gte(rhs); } - template - [[nodiscard]] BoolExpr lte(const TRhs& rhs) const { - return compare(BoolExpr::Kind::Lte, rhs); - } - template - [[nodiscard]] BoolExpr Lte(const TRhs& rhs) const { return lte(rhs); } - - [[nodiscard]] constexpr const ColumnRef& column_ref() const { return column_; } - -private: - template - [[nodiscard]] BoolExpr compare(typename BoolExpr::Kind kind, const TRhs& rhs) const { - return BoolExpr::compare(kind, detail::Operand::column(column_), detail::to_operand(rhs)); - } - - ColumnRef column_{}; - - template - friend class MaybeIxCol; -}; - -template -using ix_col_member_t = MaybeIxCol; -// HasIxCols currently exposes all fields through MaybeIxCol so table/view macros can stay uniform. -// Non-indexed fields are rejected when .eq() is used in a semijoin predicate. - -} // namespace detail - template struct IxJoinEq { ColumnRef lhs; ColumnRef rhs; }; -template +template class LeftSemiJoin { public: - using row_type = TRow; - - LeftSemiJoin(ColumnRef lhs, const char* right_table, const char* right_column, std::optional> where_expr = std::nullopt) - : lhs_(lhs), right_table_(right_table), right_column_(right_column), where_expr_(std::move(where_expr)) {} + using row_type = TLeftRow; + + LeftSemiJoin( + Table left, + Table right, + ColumnRef left_join_ref, + ColumnRef right_join_ref, + std::optional> where_expr = std::nullopt) + : left_(std::move(left)) + , right_(std::move(right)) + , left_join_ref_(left_join_ref) + , right_join_ref_(right_join_ref) + , where_expr_(std::move(where_expr)) {} template [[nodiscard]] LeftSemiJoin where(TFn&& predicate) const { - auto extra = detail::make_bool_expr(std::forward(predicate)(HasCols::get(lhs_.table_name()))); - return LeftSemiJoin(lhs_, right_table_, right_column_, where_expr_ ? where_expr_->and_(extra) : std::optional>(std::move(extra))); + auto extra = detail::make_bool_expr(std::forward(predicate)(left_.cols())); + return LeftSemiJoin(left_, right_, left_join_ref_, right_join_ref_, where_expr_ ? where_expr_->and_(extra) : std::optional>(std::move(extra))); } + template [[nodiscard]] LeftSemiJoin where_ix(TFn&& predicate) const { - auto extra = detail::make_bool_expr(std::forward(predicate)(HasCols::get(lhs_.table_name()), HasIxCols::get(lhs_.table_name()))); - return LeftSemiJoin(lhs_, right_table_, right_column_, where_expr_ ? where_expr_->and_(extra) : std::optional>(std::move(extra))); + auto extra = detail::make_bool_expr(std::forward(predicate)(left_.cols(), left_.ix_cols())); + return LeftSemiJoin(left_, right_, left_join_ref_, right_join_ref_, where_expr_ ? where_expr_->and_(extra) : std::optional>(std::move(extra))); } + template [[nodiscard]] LeftSemiJoin Where(TFn&& predicate) const { - if constexpr (std::is_invocable_v::get(lhs_.table_name())), decltype(HasIxCols::get(lhs_.table_name()))>) { + if constexpr (std::is_invocable_v) { return where_ix(std::forward(predicate)); } else { return where(std::forward(predicate)); @@ -211,69 +132,74 @@ class LeftSemiJoin { return Where(std::forward(predicate)); } - [[nodiscard]] RawQuery build() const { + [[nodiscard]] RawQuery build() const { std::string sql; sql.reserve( 48 + - (std::char_traits::length(lhs_.table_name()) * 3) + - std::char_traits::length(right_table_) * 2 + - std::char_traits::length(lhs_.column_name()) + - std::char_traits::length(right_column_)); + (std::char_traits::length(left_.name()) * 3) + + std::char_traits::length(right_.name()) * 2 + + std::char_traits::length(left_join_ref_.column_name()) + + std::char_traits::length(right_join_ref_.column_name())); sql += "SELECT \""; - sql += lhs_.table_name(); + sql += left_.name(); sql += "\".* FROM \""; - sql += lhs_.table_name(); + sql += left_.name(); sql += "\" JOIN \""; - sql += right_table_; - sql += "\" ON \""; - sql += lhs_.table_name(); - sql += "\".\""; - sql += lhs_.column_name(); - sql += "\" = \""; - sql += right_table_; - sql += "\".\""; - sql += right_column_; - sql += "\""; + sql += right_.name(); + sql += "\" ON "; + sql += left_join_ref_.format(); + sql += " = "; + sql += right_join_ref_.format(); if (where_expr_) { sql += " WHERE " + where_expr_->format(); } - return RawQuery(std::move(sql)); + return RawQuery(std::move(sql)); } [[nodiscard]] std::string into_sql() const { return build().into_sql(); } private: - ColumnRef lhs_; - const char* right_table_; - const char* right_column_; - std::optional> where_expr_; + Table left_; + Table right_; + ColumnRef left_join_ref_; + ColumnRef right_join_ref_; + std::optional> where_expr_; }; -template +template class RightSemiJoin { public: using row_type = TRightRow; RightSemiJoin( - ColumnRef lhs, - ColumnRef rhs, + Table left, + Table right, + ColumnRef left_join_ref, + ColumnRef right_join_ref, std::optional> left_where_expr = std::nullopt, std::optional> right_where_expr = std::nullopt) - : lhs_(lhs), rhs_(rhs), left_where_expr_(std::move(left_where_expr)), right_where_expr_(std::move(right_where_expr)) {} + : left_(std::move(left)) + , right_(std::move(right)) + , left_join_ref_(left_join_ref) + , right_join_ref_(right_join_ref) + , left_where_expr_(std::move(left_where_expr)) + , right_where_expr_(std::move(right_where_expr)) {} template [[nodiscard]] RightSemiJoin where(TFn&& predicate) const { - auto extra = detail::make_bool_expr(std::forward(predicate)(HasCols::get(rhs_.table_name()))); - return RightSemiJoin(lhs_, rhs_, left_where_expr_, right_where_expr_ ? right_where_expr_->and_(extra) : std::optional>(std::move(extra))); + auto extra = detail::make_bool_expr(std::forward(predicate)(right_.cols())); + return RightSemiJoin(left_, right_, left_join_ref_, right_join_ref_, left_where_expr_, right_where_expr_ ? right_where_expr_->and_(extra) : std::optional>(std::move(extra))); } + template [[nodiscard]] RightSemiJoin where_ix(TFn&& predicate) const { - auto extra = detail::make_bool_expr(std::forward(predicate)(HasCols::get(rhs_.table_name()), HasIxCols::get(rhs_.table_name()))); - return RightSemiJoin(lhs_, rhs_, left_where_expr_, right_where_expr_ ? right_where_expr_->and_(extra) : std::optional>(std::move(extra))); + auto extra = detail::make_bool_expr(std::forward(predicate)(right_.cols(), right_.ix_cols())); + return RightSemiJoin(left_, right_, left_join_ref_, right_join_ref_, left_where_expr_, right_where_expr_ ? right_where_expr_->and_(extra) : std::optional>(std::move(extra))); } + template [[nodiscard]] RightSemiJoin Where(TFn&& predicate) const { - if constexpr (std::is_invocable_v::get(rhs_.table_name())), decltype(HasIxCols::get(rhs_.table_name()))>) { + if constexpr (std::is_invocable_v) { return where_ix(std::forward(predicate)); } else { return where(std::forward(predicate)); @@ -293,25 +219,20 @@ class RightSemiJoin { std::string sql; sql.reserve( 48 + - (std::char_traits::length(lhs_.table_name()) * 2) + - (std::char_traits::length(rhs_.table_name()) * 3) + - std::char_traits::length(lhs_.column_name()) + - std::char_traits::length(rhs_.column_name())); + (std::char_traits::length(left_.name()) * 2) + + (std::char_traits::length(right_.name()) * 3) + + std::char_traits::length(left_join_ref_.column_name()) + + std::char_traits::length(right_join_ref_.column_name())); sql += "SELECT \""; - sql += rhs_.table_name(); + sql += right_.name(); sql += "\".* FROM \""; - sql += lhs_.table_name(); + sql += left_.name(); sql += "\" JOIN \""; - sql += rhs_.table_name(); - sql += "\" ON \""; - sql += lhs_.table_name(); - sql += "\".\""; - sql += lhs_.column_name(); - sql += "\" = \""; - sql += rhs_.table_name(); - sql += "\".\""; - sql += rhs_.column_name(); - sql += "\""; + sql += right_.name(); + sql += "\" ON "; + sql += left_join_ref_.format(); + sql += " = "; + sql += right_join_ref_.format(); if (left_where_expr_ && right_where_expr_) { sql += " WHERE "; @@ -332,83 +253,89 @@ class RightSemiJoin { [[nodiscard]] std::string into_sql() const { return build().into_sql(); } private: - ColumnRef lhs_; - ColumnRef rhs_; + Table left_; + Table right_; + ColumnRef left_join_ref_; + ColumnRef right_join_ref_; std::optional> left_where_expr_; std::optional> right_where_expr_; }; namespace detail { -template -[[nodiscard]] LeftSemiJoin left_semijoin_impl(const Table& left, const Table& right, TFn&& predicate) { - static_assert(can_be_lookup_table_v, "Lookup side of a semijoin must opt in via CanBeLookupTable."); - static_assert(requires { HasIxCols::get(left.name()); }, "Left side of a semijoin must provide HasIxCols."); - static_assert(requires { HasIxCols::get(right.name()); }, "Lookup side of a semijoin must provide HasIxCols."); - const auto join = std::forward(predicate)(HasIxCols::get(left.name()), HasIxCols::get(right.name())); - return LeftSemiJoin(join.lhs, right.name(), join.rhs.column_name()); +template +[[nodiscard]] auto left_semijoin_impl(const Table& left, const Table& right, TFn&& predicate) { + static_assert( + can_be_lookup_table_v>, + "Semijoin predicates require the right-hand source to opt into CanBeLookupTable." + ); + const auto join = std::forward(predicate)(left.ix_cols(), right.ix_cols()); + return LeftSemiJoin(left, right, join.lhs, join.rhs); } -template -[[nodiscard]] LeftSemiJoin left_semijoin_impl(const FromWhere& left, const Table& right, TFn&& predicate) { - static_assert(can_be_lookup_table_v, "Lookup side of a semijoin must opt in via CanBeLookupTable."); - static_assert(requires { HasIxCols::get(left.table_name()); }, "Left side of a semijoin must provide HasIxCols."); - static_assert(requires { HasIxCols::get(right.name()); }, "Lookup side of a semijoin must provide HasIxCols."); - const auto join = std::forward(predicate)(HasIxCols::get(left.table_name()), HasIxCols::get(right.name())); - return LeftSemiJoin(join.lhs, right.name(), join.rhs.column_name(), left.expr()); +template +[[nodiscard]] auto left_semijoin_impl(const FromWhere& left, const Table& right, TFn&& predicate) { + static_assert( + can_be_lookup_table_v>, + "Semijoin predicates require the right-hand source to opt into CanBeLookupTable." + ); + const auto join = std::forward(predicate)(left.table().ix_cols(), right.ix_cols()); + return LeftSemiJoin(left.table(), right, join.lhs, join.rhs, left.expr()); } -template -[[nodiscard]] RightSemiJoin right_semijoin_impl(const Table& left, const Table& right, TFn&& predicate) { - static_assert(can_be_lookup_table_v, "Lookup side of a semijoin must opt in via CanBeLookupTable."); - static_assert(requires { HasIxCols::get(left.name()); }, "Left side of a semijoin must provide HasIxCols."); - static_assert(requires { HasIxCols::get(right.name()); }, "Lookup side of a semijoin must provide HasIxCols."); - const auto join = std::forward(predicate)(HasIxCols::get(left.name()), HasIxCols::get(right.name())); - return RightSemiJoin(join.lhs, join.rhs); +template +[[nodiscard]] auto right_semijoin_impl(const Table& left, const Table& right, TFn&& predicate) { + static_assert( + can_be_lookup_table_v>, + "Semijoin predicates require the right-hand source to opt into CanBeLookupTable." + ); + const auto join = std::forward(predicate)(left.ix_cols(), right.ix_cols()); + return RightSemiJoin(left, right, join.lhs, join.rhs); } -template -[[nodiscard]] RightSemiJoin right_semijoin_impl(const FromWhere& left, const Table& right, TFn&& predicate) { - static_assert(can_be_lookup_table_v, "Lookup side of a semijoin must opt in via CanBeLookupTable."); - static_assert(requires { HasIxCols::get(left.table_name()); }, "Left side of a semijoin must provide HasIxCols."); - static_assert(requires { HasIxCols::get(right.name()); }, "Lookup side of a semijoin must provide HasIxCols."); - const auto join = std::forward(predicate)(HasIxCols::get(left.table_name()), HasIxCols::get(right.name())); - return RightSemiJoin(join.lhs, join.rhs, left.expr()); +template +[[nodiscard]] auto right_semijoin_impl(const FromWhere& left, const Table& right, TFn&& predicate) { + static_assert( + can_be_lookup_table_v>, + "Semijoin predicates require the right-hand source to opt into CanBeLookupTable." + ); + const auto join = std::forward(predicate)(left.table().ix_cols(), right.ix_cols()); + return RightSemiJoin(left.table(), right, join.lhs, join.rhs, left.expr()); } } // namespace detail -template -template -[[nodiscard]] LeftSemiJoin Table::left_semijoin(const Table& right, TFn&& predicate) const { +template +template +[[nodiscard]] auto Table::left_semijoin(const Table& right, TFn&& predicate) const { return detail::left_semijoin_impl(*this, right, std::forward(predicate)); } -template -template -[[nodiscard]] RightSemiJoin Table::right_semijoin(const Table& right, TFn&& predicate) const { +template +template +[[nodiscard]] auto Table::right_semijoin(const Table& right, TFn&& predicate) const { return detail::right_semijoin_impl(*this, right, std::forward(predicate)); } -template -template -[[nodiscard]] LeftSemiJoin FromWhere::left_semijoin(const Table& right, TFn&& predicate) const { +template +template +[[nodiscard]] auto FromWhere::left_semijoin(const Table& right, TFn&& predicate) const { return detail::left_semijoin_impl(*this, right, std::forward(predicate)); } -template -template -[[nodiscard]] RightSemiJoin FromWhere::right_semijoin(const Table& right, TFn&& predicate) const { +template +template +[[nodiscard]] auto FromWhere::right_semijoin(const Table& right, TFn&& predicate) const { return detail::right_semijoin_impl(*this, right, std::forward(predicate)); } -template -struct query_row_type> { - using type = TRow; +template +struct query_row_type> { + using type = TLeftRow; }; -template -struct query_row_type> { +template +struct query_row_type> { using type = TRightRow; }; diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/query_builder.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/query_builder.h index c8386a19f0f..81603930504 100644 --- a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/query_builder.h +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/query_builder.h @@ -4,96 +4,19 @@ #include "QueryBuilder/join.h" #include "QueryBuilder/table.h" -#include -#include -#include +#include namespace SpacetimeDB { template using Query = query_builder::RawQuery; -namespace detail { - -template -struct NamedQuerySourceTag { - using type = TRow; - const char* __table_name_internal; -}; - -struct NotAQuerySourceTag {}; - -template -struct query_source_row_type {}; - -template -concept HasQuerySourceRowType = requires { - typename query_source_row_type>::type; -}; - -template -using query_source_row_type_t = typename query_source_row_type>::type; - -template - requires query_builder::QueryBuilderReturn -struct query_source_row_type { - using type = query_builder::query_row_type_t; -}; - -template -struct query_source_row_type> { - using type = TRow; -}; - -template -struct query_source_row_type> { - using type = TRow; -}; - -template -constexpr auto MakeQuerySourceTag(const char* source_name) { - if constexpr (HasQuerySourceRowType) { - return NamedQuerySourceTag>{source_name}; - } else { - return NotAQuerySourceTag{}; - } -} - -template -constexpr const char* GetQuerySourceName(const TSourceTag& tag) { - return tag.__table_name_internal; -} - -} // namespace detail - class QueryBuilder { public: - template - [[nodiscard]] constexpr query_builder::Table table(const char* table_name) const { - return query_builder::Table(table_name); + template + [[nodiscard]] constexpr query_builder::Table table(const char* table_name, TCols cols, TIxCols ix_cols) const { + return query_builder::Table(table_name, std::move(cols), std::move(ix_cols)); } - - template - [[nodiscard]] constexpr auto table(TTableTag tag) const - -> query_builder::Table::type> { - using Tag = std::remove_cvref_t; - using TRow = typename Tag::type; - // Tags may refer to either base tables or published view relations. - return query_builder::Table(detail::GetQuerySourceName(tag)); - } - - template - [[nodiscard]] constexpr auto operator()(TTableTag tag) const - -> query_builder::Table::type> { - return table(tag); - } - - template - [[nodiscard]] constexpr auto operator[](TTableTag tag) const - -> query_builder::Table::type> { - return table(tag); - } - }; } // namespace SpacetimeDB diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/table.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/table.h index d86e60ec63d..b9d18bde50b 100644 --- a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/table.h +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/table.h @@ -18,16 +18,22 @@ namespace SpacetimeDB::query_builder { template struct query_row_type; -template +template class Table; -template +template class FromWhere; -template +template +struct CanBeLookupTable : std::false_type {}; + +template +inline constexpr bool can_be_lookup_table_v = CanBeLookupTable>::value; + +template class LeftSemiJoin; -template +template class RightSemiJoin; template @@ -56,8 +62,8 @@ class RawQuery { std::string sql_; }; -template -concept QueryLike = requires(const TRow& query) { +template +concept QueryLike = requires(const T& query) { { query.into_sql() } -> std::convertible_to; }; @@ -66,43 +72,19 @@ concept QueryBuilderReturn = requires { typename query_row_type_t; } && QueryLike>; -template -struct HasCols; - -template -struct HasIxCols; - -template -struct CanBeLookupTable : std::false_type {}; - -namespace detail { - -template -struct row_tag {}; - -inline std::false_type lookup_table_allowed(...); - -template -auto adl_lookup_table_allowed(int) -> decltype(lookup_table_allowed(row_tag{})); - -template -std::false_type adl_lookup_table_allowed(...); - -} // namespace detail - -template -inline constexpr bool can_be_lookup_table_v = - CanBeLookupTable::value || decltype(detail::adl_lookup_table_allowed(0))::value; - -template +template class Table { public: using row_type = TRow; + using cols_type = TCols; + using ix_cols_type = TIxCols; - explicit constexpr Table(const char* table_name) - : table_name_(table_name) {} + constexpr Table(const char* table_name, TCols cols, TIxCols ix_cols) + : table_name_(table_name), cols_(std::move(cols)), ix_cols_(std::move(ix_cols)) {} [[nodiscard]] constexpr const char* name() const { return table_name_; } + [[nodiscard]] constexpr const TCols& cols() const { return cols_; } + [[nodiscard]] constexpr const TIxCols& ix_cols() const { return ix_cols_; } [[nodiscard]] RawQuery build() const { std::string sql; @@ -118,11 +100,25 @@ class Table { } template - [[nodiscard]] auto where(TFn&& predicate) const; + [[nodiscard]] auto where(TFn&& predicate) const { + auto expr = detail::make_bool_expr(std::forward(predicate)(cols_)); + return FromWhere(*this, std::move(expr)); + } + template - [[nodiscard]] auto where_ix(TFn&& predicate) const; + [[nodiscard]] auto where_ix(TFn&& predicate) const { + auto expr = detail::make_bool_expr(std::forward(predicate)(cols_, ix_cols_)); + return FromWhere(*this, std::move(expr)); + } + template - [[nodiscard]] auto Where(TFn&& predicate) const; + [[nodiscard]] auto Where(TFn&& predicate) const { + if constexpr (std::is_invocable_v) { + return where_ix(std::forward(predicate)); + } else { + return where(std::forward(predicate)); + } + } template [[nodiscard]] auto filter(TFn&& predicate) const { @@ -133,41 +129,46 @@ class Table { return Where(std::forward(predicate)); } - template - [[nodiscard]] LeftSemiJoin left_semijoin(const Table& right, TFn&& predicate) const; - template - [[nodiscard]] LeftSemiJoin LeftSemijoin(const Table& right, TFn&& predicate) const { + template + [[nodiscard]] auto left_semijoin(const Table& right, TFn&& predicate) const; + template + [[nodiscard]] auto LeftSemijoin(const Table& right, TFn&& predicate) const { return left_semijoin(right, std::forward(predicate)); } - template - [[nodiscard]] RightSemiJoin right_semijoin(const Table& right, TFn&& predicate) const; - template - [[nodiscard]] RightSemiJoin RightSemijoin(const Table& right, TFn&& predicate) const { + template + [[nodiscard]] auto right_semijoin(const Table& right, TFn&& predicate) const; + template + [[nodiscard]] auto RightSemijoin(const Table& right, TFn&& predicate) const { return right_semijoin(right, std::forward(predicate)); } private: const char* table_name_; + TCols cols_; + TIxCols ix_cols_; }; -template +template class FromWhere { public: using row_type = TRow; + using cols_type = TCols; + using ix_cols_type = TIxCols; - constexpr FromWhere(const char* table_name, BoolExpr expr) - : table_name_(table_name), expr_(std::move(expr)) {} + constexpr FromWhere(Table table, BoolExpr expr) + : table_(std::move(table)), expr_(std::move(expr)) {} - [[nodiscard]] constexpr const char* table_name() const { return table_name_; } + [[nodiscard]] constexpr const char* table_name() const { return table_.name(); } [[nodiscard]] const BoolExpr& expr() const { return expr_; } + [[nodiscard]] constexpr const Table& table() const { return table_; } [[nodiscard]] RawQuery build() const { std::string predicate = expr_.format(); std::string sql; - sql.reserve(24 + std::char_traits::length(table_name_) + predicate.size()); + sql.reserve(24 + std::char_traits::length(table_.name()) + predicate.size()); sql += "SELECT * FROM \""; - sql += table_name_; + sql += table_.name(); sql += "\" WHERE "; sql += predicate; return RawQuery(std::move(sql)); @@ -179,17 +180,19 @@ class FromWhere { template [[nodiscard]] FromWhere where(TFn&& predicate) const { - auto extra = detail::make_bool_expr(std::forward(predicate)(HasCols::get(table_name_))); - return FromWhere(table_name_, expr_.and_(extra)); + auto extra = detail::make_bool_expr(std::forward(predicate)(table_.cols())); + return FromWhere(table_, expr_.and_(extra)); } + template [[nodiscard]] FromWhere where_ix(TFn&& predicate) const { - auto extra = detail::make_bool_expr(std::forward(predicate)(HasCols::get(table_name_), HasIxCols::get(table_name_))); - return FromWhere(table_name_, expr_.and_(extra)); + auto extra = detail::make_bool_expr(std::forward(predicate)(table_.cols(), table_.ix_cols())); + return FromWhere(table_, expr_.and_(extra)); } + template [[nodiscard]] FromWhere Where(TFn&& predicate) const { - if constexpr (std::is_invocable_v::get(table_name_)), decltype(HasIxCols::get(table_name_))>) { + if constexpr (std::is_invocable_v) { return where_ix(std::forward(predicate)); } else { return where(std::forward(predicate)); @@ -205,61 +208,37 @@ class FromWhere { return Where(std::forward(predicate)); } - template - [[nodiscard]] LeftSemiJoin left_semijoin(const Table& right, TFn&& predicate) const; - template - [[nodiscard]] LeftSemiJoin LeftSemijoin(const Table& right, TFn&& predicate) const { + template + [[nodiscard]] auto left_semijoin(const Table& right, TFn&& predicate) const; + template + [[nodiscard]] auto LeftSemijoin(const Table& right, TFn&& predicate) const { return left_semijoin(right, std::forward(predicate)); } - template - [[nodiscard]] RightSemiJoin right_semijoin(const Table& right, TFn&& predicate) const; - template - [[nodiscard]] RightSemiJoin RightSemijoin(const Table& right, TFn&& predicate) const { + template + [[nodiscard]] auto right_semijoin(const Table& right, TFn&& predicate) const; + template + [[nodiscard]] auto RightSemijoin(const Table& right, TFn&& predicate) const { return right_semijoin(right, std::forward(predicate)); } private: - const char* table_name_; + Table table_; BoolExpr expr_; }; -template -template -[[nodiscard]] auto Table::where(TFn&& predicate) const { - auto expr = detail::make_bool_expr(std::forward(predicate)(HasCols::get(table_name_))); - return FromWhere(table_name_, std::move(expr)); -} - -template -template -[[nodiscard]] auto Table::where_ix(TFn&& predicate) const { - auto expr = detail::make_bool_expr(std::forward(predicate)(HasCols::get(table_name_), HasIxCols::get(table_name_))); - return FromWhere(table_name_, std::move(expr)); -} - -template -template -[[nodiscard]] auto Table::Where(TFn&& predicate) const { - if constexpr (std::is_invocable_v::get(table_name_)), decltype(HasIxCols::get(table_name_))>) { - return where_ix(std::forward(predicate)); - } else { - return where(std::forward(predicate)); - } -} - template struct query_row_type> { using type = TRow; }; -template -struct query_row_type> { +template +struct query_row_type> { using type = TRow; }; -template -struct query_row_type> { +template +struct query_row_type> { using type = TRow; }; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h index 793a2328dc9..5685bd44c6a 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -10470,6 +10470,221 @@ class TESTCLIENT_API URemoteProcedures : public UObject }; // QueryBuilder types +struct TESTCLIENT_API FBTreeU32Cols; +struct TESTCLIENT_API FBTreeU32IxCols; +struct TESTCLIENT_API FIndexedSimpleEnumCols; +struct TESTCLIENT_API FIndexedSimpleEnumIxCols; +struct TESTCLIENT_API FLargeTableCols; +struct TESTCLIENT_API FLargeTableIxCols; +struct TESTCLIENT_API FOneBoolCols; +struct TESTCLIENT_API FOneBoolIxCols; +struct TESTCLIENT_API FOneByteStructCols; +struct TESTCLIENT_API FOneByteStructIxCols; +struct TESTCLIENT_API FOneConnectionIdCols; +struct TESTCLIENT_API FOneConnectionIdIxCols; +struct TESTCLIENT_API FOneEnumWithPayloadCols; +struct TESTCLIENT_API FOneEnumWithPayloadIxCols; +struct TESTCLIENT_API FOneEveryPrimitiveStructCols; +struct TESTCLIENT_API FOneEveryPrimitiveStructIxCols; +struct TESTCLIENT_API FOneEveryVecStructCols; +struct TESTCLIENT_API FOneEveryVecStructIxCols; +struct TESTCLIENT_API FOneF32Cols; +struct TESTCLIENT_API FOneF32IxCols; +struct TESTCLIENT_API FOneF64Cols; +struct TESTCLIENT_API FOneF64IxCols; +struct TESTCLIENT_API FOneI128Cols; +struct TESTCLIENT_API FOneI128IxCols; +struct TESTCLIENT_API FOneI16Cols; +struct TESTCLIENT_API FOneI16IxCols; +struct TESTCLIENT_API FOneI256Cols; +struct TESTCLIENT_API FOneI256IxCols; +struct TESTCLIENT_API FOneI32Cols; +struct TESTCLIENT_API FOneI32IxCols; +struct TESTCLIENT_API FOneI64Cols; +struct TESTCLIENT_API FOneI64IxCols; +struct TESTCLIENT_API FOneI8Cols; +struct TESTCLIENT_API FOneI8IxCols; +struct TESTCLIENT_API FOneIdentityCols; +struct TESTCLIENT_API FOneIdentityIxCols; +struct TESTCLIENT_API FOneSimpleEnumCols; +struct TESTCLIENT_API FOneSimpleEnumIxCols; +struct TESTCLIENT_API FOneStringCols; +struct TESTCLIENT_API FOneStringIxCols; +struct TESTCLIENT_API FOneTimestampCols; +struct TESTCLIENT_API FOneTimestampIxCols; +struct TESTCLIENT_API FOneU128Cols; +struct TESTCLIENT_API FOneU128IxCols; +struct TESTCLIENT_API FOneU16Cols; +struct TESTCLIENT_API FOneU16IxCols; +struct TESTCLIENT_API FOneU256Cols; +struct TESTCLIENT_API FOneU256IxCols; +struct TESTCLIENT_API FOneU32Cols; +struct TESTCLIENT_API FOneU32IxCols; +struct TESTCLIENT_API FOneU64Cols; +struct TESTCLIENT_API FOneU64IxCols; +struct TESTCLIENT_API FOneU8Cols; +struct TESTCLIENT_API FOneU8IxCols; +struct TESTCLIENT_API FOneUnitStructCols; +struct TESTCLIENT_API FOneUnitStructIxCols; +struct TESTCLIENT_API FOneUuidCols; +struct TESTCLIENT_API FOneUuidIxCols; +struct TESTCLIENT_API FOptionEveryPrimitiveStructCols; +struct TESTCLIENT_API FOptionEveryPrimitiveStructIxCols; +struct TESTCLIENT_API FOptionI32Cols; +struct TESTCLIENT_API FOptionI32IxCols; +struct TESTCLIENT_API FOptionIdentityCols; +struct TESTCLIENT_API FOptionIdentityIxCols; +struct TESTCLIENT_API FOptionSimpleEnumCols; +struct TESTCLIENT_API FOptionSimpleEnumIxCols; +struct TESTCLIENT_API FOptionStringCols; +struct TESTCLIENT_API FOptionStringIxCols; +struct TESTCLIENT_API FOptionUuidCols; +struct TESTCLIENT_API FOptionUuidIxCols; +struct TESTCLIENT_API FOptionVecOptionI32Cols; +struct TESTCLIENT_API FOptionVecOptionI32IxCols; +struct TESTCLIENT_API FPkBoolCols; +struct TESTCLIENT_API FPkBoolIxCols; +struct TESTCLIENT_API FPkConnectionIdCols; +struct TESTCLIENT_API FPkConnectionIdIxCols; +struct TESTCLIENT_API FPkI128Cols; +struct TESTCLIENT_API FPkI128IxCols; +struct TESTCLIENT_API FPkI16Cols; +struct TESTCLIENT_API FPkI16IxCols; +struct TESTCLIENT_API FPkI256Cols; +struct TESTCLIENT_API FPkI256IxCols; +struct TESTCLIENT_API FPkI32Cols; +struct TESTCLIENT_API FPkI32IxCols; +struct TESTCLIENT_API FPkI64Cols; +struct TESTCLIENT_API FPkI64IxCols; +struct TESTCLIENT_API FPkI8Cols; +struct TESTCLIENT_API FPkI8IxCols; +struct TESTCLIENT_API FPkIdentityCols; +struct TESTCLIENT_API FPkIdentityIxCols; +struct TESTCLIENT_API FPkSimpleEnumCols; +struct TESTCLIENT_API FPkSimpleEnumIxCols; +struct TESTCLIENT_API FPkStringCols; +struct TESTCLIENT_API FPkStringIxCols; +struct TESTCLIENT_API FPkU128Cols; +struct TESTCLIENT_API FPkU128IxCols; +struct TESTCLIENT_API FPkU16Cols; +struct TESTCLIENT_API FPkU16IxCols; +struct TESTCLIENT_API FPkU256Cols; +struct TESTCLIENT_API FPkU256IxCols; +struct TESTCLIENT_API FPkU32Cols; +struct TESTCLIENT_API FPkU32IxCols; +struct TESTCLIENT_API FPkU32TwoCols; +struct TESTCLIENT_API FPkU32TwoIxCols; +struct TESTCLIENT_API FPkU64Cols; +struct TESTCLIENT_API FPkU64IxCols; +struct TESTCLIENT_API FPkU8Cols; +struct TESTCLIENT_API FPkU8IxCols; +struct TESTCLIENT_API FPkUuidCols; +struct TESTCLIENT_API FPkUuidIxCols; +struct TESTCLIENT_API FResultEveryPrimitiveStructStringCols; +struct TESTCLIENT_API FResultEveryPrimitiveStructStringIxCols; +struct TESTCLIENT_API FResultI32StringCols; +struct TESTCLIENT_API FResultI32StringIxCols; +struct TESTCLIENT_API FResultIdentityStringCols; +struct TESTCLIENT_API FResultIdentityStringIxCols; +struct TESTCLIENT_API FResultSimpleEnumI32Cols; +struct TESTCLIENT_API FResultSimpleEnumI32IxCols; +struct TESTCLIENT_API FResultStringI32Cols; +struct TESTCLIENT_API FResultStringI32IxCols; +struct TESTCLIENT_API FResultVecI32StringCols; +struct TESTCLIENT_API FResultVecI32StringIxCols; +struct TESTCLIENT_API FScheduledTableCols; +struct TESTCLIENT_API FScheduledTableIxCols; +struct TESTCLIENT_API FTableHoldsTableCols; +struct TESTCLIENT_API FTableHoldsTableIxCols; +struct TESTCLIENT_API FUniqueBoolCols; +struct TESTCLIENT_API FUniqueBoolIxCols; +struct TESTCLIENT_API FUniqueConnectionIdCols; +struct TESTCLIENT_API FUniqueConnectionIdIxCols; +struct TESTCLIENT_API FUniqueI128Cols; +struct TESTCLIENT_API FUniqueI128IxCols; +struct TESTCLIENT_API FUniqueI16Cols; +struct TESTCLIENT_API FUniqueI16IxCols; +struct TESTCLIENT_API FUniqueI256Cols; +struct TESTCLIENT_API FUniqueI256IxCols; +struct TESTCLIENT_API FUniqueI32Cols; +struct TESTCLIENT_API FUniqueI32IxCols; +struct TESTCLIENT_API FUniqueI64Cols; +struct TESTCLIENT_API FUniqueI64IxCols; +struct TESTCLIENT_API FUniqueI8Cols; +struct TESTCLIENT_API FUniqueI8IxCols; +struct TESTCLIENT_API FUniqueIdentityCols; +struct TESTCLIENT_API FUniqueIdentityIxCols; +struct TESTCLIENT_API FUniqueStringCols; +struct TESTCLIENT_API FUniqueStringIxCols; +struct TESTCLIENT_API FUniqueU128Cols; +struct TESTCLIENT_API FUniqueU128IxCols; +struct TESTCLIENT_API FUniqueU16Cols; +struct TESTCLIENT_API FUniqueU16IxCols; +struct TESTCLIENT_API FUniqueU256Cols; +struct TESTCLIENT_API FUniqueU256IxCols; +struct TESTCLIENT_API FUniqueU32Cols; +struct TESTCLIENT_API FUniqueU32IxCols; +struct TESTCLIENT_API FUniqueU64Cols; +struct TESTCLIENT_API FUniqueU64IxCols; +struct TESTCLIENT_API FUniqueU8Cols; +struct TESTCLIENT_API FUniqueU8IxCols; +struct TESTCLIENT_API FUniqueUuidCols; +struct TESTCLIENT_API FUniqueUuidIxCols; +struct TESTCLIENT_API FUsersCols; +struct TESTCLIENT_API FUsersIxCols; +struct TESTCLIENT_API FVecBoolCols; +struct TESTCLIENT_API FVecBoolIxCols; +struct TESTCLIENT_API FVecByteStructCols; +struct TESTCLIENT_API FVecByteStructIxCols; +struct TESTCLIENT_API FVecConnectionIdCols; +struct TESTCLIENT_API FVecConnectionIdIxCols; +struct TESTCLIENT_API FVecEnumWithPayloadCols; +struct TESTCLIENT_API FVecEnumWithPayloadIxCols; +struct TESTCLIENT_API FVecEveryPrimitiveStructCols; +struct TESTCLIENT_API FVecEveryPrimitiveStructIxCols; +struct TESTCLIENT_API FVecEveryVecStructCols; +struct TESTCLIENT_API FVecEveryVecStructIxCols; +struct TESTCLIENT_API FVecF32Cols; +struct TESTCLIENT_API FVecF32IxCols; +struct TESTCLIENT_API FVecF64Cols; +struct TESTCLIENT_API FVecF64IxCols; +struct TESTCLIENT_API FVecI128Cols; +struct TESTCLIENT_API FVecI128IxCols; +struct TESTCLIENT_API FVecI16Cols; +struct TESTCLIENT_API FVecI16IxCols; +struct TESTCLIENT_API FVecI256Cols; +struct TESTCLIENT_API FVecI256IxCols; +struct TESTCLIENT_API FVecI32Cols; +struct TESTCLIENT_API FVecI32IxCols; +struct TESTCLIENT_API FVecI64Cols; +struct TESTCLIENT_API FVecI64IxCols; +struct TESTCLIENT_API FVecI8Cols; +struct TESTCLIENT_API FVecI8IxCols; +struct TESTCLIENT_API FVecIdentityCols; +struct TESTCLIENT_API FVecIdentityIxCols; +struct TESTCLIENT_API FVecSimpleEnumCols; +struct TESTCLIENT_API FVecSimpleEnumIxCols; +struct TESTCLIENT_API FVecStringCols; +struct TESTCLIENT_API FVecStringIxCols; +struct TESTCLIENT_API FVecTimestampCols; +struct TESTCLIENT_API FVecTimestampIxCols; +struct TESTCLIENT_API FVecU128Cols; +struct TESTCLIENT_API FVecU128IxCols; +struct TESTCLIENT_API FVecU16Cols; +struct TESTCLIENT_API FVecU16IxCols; +struct TESTCLIENT_API FVecU256Cols; +struct TESTCLIENT_API FVecU256IxCols; +struct TESTCLIENT_API FVecU32Cols; +struct TESTCLIENT_API FVecU32IxCols; +struct TESTCLIENT_API FVecU64Cols; +struct TESTCLIENT_API FVecU64IxCols; +struct TESTCLIENT_API FVecU8Cols; +struct TESTCLIENT_API FVecU8IxCols; +struct TESTCLIENT_API FVecUnitStructCols; +struct TESTCLIENT_API FVecUnitStructIxCols; +struct TESTCLIENT_API FVecUuidCols; +struct TESTCLIENT_API FVecUuidIxCols; + struct TESTCLIENT_API FBTreeU32Cols { explicit FBTreeU32Cols(const char* TableName) @@ -10484,27 +10699,13 @@ struct TESTCLIENT_API FBTreeU32IxCols explicit FBTreeU32IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FBTreeU32Cols get(const char* table_name) { return FBTreeU32Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FBTreeU32IxCols get(const char* table_name) { return FBTreeU32IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FIndexedSimpleEnumCols @@ -10520,27 +10721,13 @@ struct TESTCLIENT_API FIndexedSimpleEnumIxCols explicit FIndexedSimpleEnumIxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FIndexedSimpleEnumCols get(const char* table_name) { return FIndexedSimpleEnumCols(table_name); } - }; - template<> - struct HasIxCols - { - static FIndexedSimpleEnumIxCols get(const char* table_name) { return FIndexedSimpleEnumIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FLargeTableCols @@ -10581,21 +10768,8 @@ struct TESTCLIENT_API FLargeTableIxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FLargeTableCols get(const char* table_name) { return FLargeTableCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FLargeTableIxCols get(const char* table_name) { return FLargeTableIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneBoolCols @@ -10615,21 +10789,8 @@ struct TESTCLIENT_API FOneBoolIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneBoolCols get(const char* table_name) { return FOneBoolCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneBoolIxCols get(const char* table_name) { return FOneBoolIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneByteStructCols @@ -10649,21 +10810,8 @@ struct TESTCLIENT_API FOneByteStructIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneByteStructCols get(const char* table_name) { return FOneByteStructCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneByteStructIxCols get(const char* table_name) { return FOneByteStructIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneConnectionIdCols @@ -10683,21 +10831,8 @@ struct TESTCLIENT_API FOneConnectionIdIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneConnectionIdCols get(const char* table_name) { return FOneConnectionIdCols(table_name); } - }; - template<> - struct HasIxCols - { - static FOneConnectionIdIxCols get(const char* table_name) { return FOneConnectionIdIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneEnumWithPayloadCols @@ -10717,21 +10852,8 @@ struct TESTCLIENT_API FOneEnumWithPayloadIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneEnumWithPayloadCols get(const char* table_name) { return FOneEnumWithPayloadCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneEnumWithPayloadIxCols get(const char* table_name) { return FOneEnumWithPayloadIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneEveryPrimitiveStructCols @@ -10751,21 +10873,8 @@ struct TESTCLIENT_API FOneEveryPrimitiveStructIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneEveryPrimitiveStructCols get(const char* table_name) { return FOneEveryPrimitiveStructCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneEveryPrimitiveStructIxCols get(const char* table_name) { return FOneEveryPrimitiveStructIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneEveryVecStructCols @@ -10785,21 +10894,8 @@ struct TESTCLIENT_API FOneEveryVecStructIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneEveryVecStructCols get(const char* table_name) { return FOneEveryVecStructCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneEveryVecStructIxCols get(const char* table_name) { return FOneEveryVecStructIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneF32Cols @@ -10819,21 +10915,8 @@ struct TESTCLIENT_API FOneF32IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneF32Cols get(const char* table_name) { return FOneF32Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FOneF32IxCols get(const char* table_name) { return FOneF32IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneF64Cols @@ -10853,21 +10936,8 @@ struct TESTCLIENT_API FOneF64IxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FOneF64Cols get(const char* table_name) { return FOneF64Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneF64IxCols get(const char* table_name) { return FOneF64IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneI128Cols @@ -10887,21 +10957,8 @@ struct TESTCLIENT_API FOneI128IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneI128Cols get(const char* table_name) { return FOneI128Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneI128IxCols get(const char* table_name) { return FOneI128IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneI16Cols @@ -10921,21 +10978,8 @@ struct TESTCLIENT_API FOneI16IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneI16Cols get(const char* table_name) { return FOneI16Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneI16IxCols get(const char* table_name) { return FOneI16IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneI256Cols @@ -10955,21 +10999,8 @@ struct TESTCLIENT_API FOneI256IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneI256Cols get(const char* table_name) { return FOneI256Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FOneI256IxCols get(const char* table_name) { return FOneI256IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneI32Cols @@ -10989,21 +11020,8 @@ struct TESTCLIENT_API FOneI32IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneI32Cols get(const char* table_name) { return FOneI32Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneI32IxCols get(const char* table_name) { return FOneI32IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneI64Cols @@ -11023,21 +11041,8 @@ struct TESTCLIENT_API FOneI64IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneI64Cols get(const char* table_name) { return FOneI64Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneI64IxCols get(const char* table_name) { return FOneI64IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneI8Cols @@ -11057,21 +11062,8 @@ struct TESTCLIENT_API FOneI8IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneI8Cols get(const char* table_name) { return FOneI8Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneI8IxCols get(const char* table_name) { return FOneI8IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneIdentityCols @@ -11091,21 +11083,8 @@ struct TESTCLIENT_API FOneIdentityIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneIdentityCols get(const char* table_name) { return FOneIdentityCols(table_name); } - }; - template<> - struct HasIxCols - { - static FOneIdentityIxCols get(const char* table_name) { return FOneIdentityIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneSimpleEnumCols @@ -11125,21 +11104,8 @@ struct TESTCLIENT_API FOneSimpleEnumIxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FOneSimpleEnumCols get(const char* table_name) { return FOneSimpleEnumCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneSimpleEnumIxCols get(const char* table_name) { return FOneSimpleEnumIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneStringCols @@ -11159,21 +11125,8 @@ struct TESTCLIENT_API FOneStringIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneStringCols get(const char* table_name) { return FOneStringCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneStringIxCols get(const char* table_name) { return FOneStringIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneTimestampCols @@ -11193,21 +11146,8 @@ struct TESTCLIENT_API FOneTimestampIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneTimestampCols get(const char* table_name) { return FOneTimestampCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneTimestampIxCols get(const char* table_name) { return FOneTimestampIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneU128Cols @@ -11227,21 +11167,8 @@ struct TESTCLIENT_API FOneU128IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneU128Cols get(const char* table_name) { return FOneU128Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FOneU128IxCols get(const char* table_name) { return FOneU128IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneU16Cols @@ -11261,21 +11188,8 @@ struct TESTCLIENT_API FOneU16IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneU16Cols get(const char* table_name) { return FOneU16Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneU16IxCols get(const char* table_name) { return FOneU16IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneU256Cols @@ -11295,21 +11209,8 @@ struct TESTCLIENT_API FOneU256IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneU256Cols get(const char* table_name) { return FOneU256Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneU256IxCols get(const char* table_name) { return FOneU256IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneU32Cols @@ -11329,21 +11230,8 @@ struct TESTCLIENT_API FOneU32IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneU32Cols get(const char* table_name) { return FOneU32Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneU32IxCols get(const char* table_name) { return FOneU32IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneU64Cols @@ -11363,21 +11251,8 @@ struct TESTCLIENT_API FOneU64IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneU64Cols get(const char* table_name) { return FOneU64Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FOneU64IxCols get(const char* table_name) { return FOneU64IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneU8Cols @@ -11397,21 +11272,8 @@ struct TESTCLIENT_API FOneU8IxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FOneU8Cols get(const char* table_name) { return FOneU8Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneU8IxCols get(const char* table_name) { return FOneU8IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneUnitStructCols @@ -11431,21 +11293,8 @@ struct TESTCLIENT_API FOneUnitStructIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneUnitStructCols get(const char* table_name) { return FOneUnitStructCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneUnitStructIxCols get(const char* table_name) { return FOneUnitStructIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOneUuidCols @@ -11465,21 +11314,8 @@ struct TESTCLIENT_API FOneUuidIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOneUuidCols get(const char* table_name) { return FOneUuidCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOneUuidIxCols get(const char* table_name) { return FOneUuidIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOptionEveryPrimitiveStructCols @@ -11499,21 +11335,8 @@ struct TESTCLIENT_API FOptionEveryPrimitiveStructIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOptionEveryPrimitiveStructCols get(const char* table_name) { return FOptionEveryPrimitiveStructCols(table_name); } - }; - template<> - struct HasIxCols - { - static FOptionEveryPrimitiveStructIxCols get(const char* table_name) { return FOptionEveryPrimitiveStructIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOptionI32Cols @@ -11533,21 +11356,8 @@ struct TESTCLIENT_API FOptionI32IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOptionI32Cols get(const char* table_name) { return FOptionI32Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOptionI32IxCols get(const char* table_name) { return FOptionI32IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOptionIdentityCols @@ -11567,21 +11377,8 @@ struct TESTCLIENT_API FOptionIdentityIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOptionIdentityCols get(const char* table_name) { return FOptionIdentityCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOptionIdentityIxCols get(const char* table_name) { return FOptionIdentityIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOptionSimpleEnumCols @@ -11601,21 +11398,8 @@ struct TESTCLIENT_API FOptionSimpleEnumIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOptionSimpleEnumCols get(const char* table_name) { return FOptionSimpleEnumCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOptionSimpleEnumIxCols get(const char* table_name) { return FOptionSimpleEnumIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOptionStringCols @@ -11635,21 +11419,8 @@ struct TESTCLIENT_API FOptionStringIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOptionStringCols get(const char* table_name) { return FOptionStringCols(table_name); } - }; - template<> - struct HasIxCols - { - static FOptionStringIxCols get(const char* table_name) { return FOptionStringIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOptionUuidCols @@ -11669,21 +11440,8 @@ struct TESTCLIENT_API FOptionUuidIxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FOptionUuidCols get(const char* table_name) { return FOptionUuidCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOptionUuidIxCols get(const char* table_name) { return FOptionUuidIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FOptionVecOptionI32Cols @@ -11703,21 +11461,8 @@ struct TESTCLIENT_API FOptionVecOptionI32IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FOptionVecOptionI32Cols get(const char* table_name) { return FOptionVecOptionI32Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FOptionVecOptionI32IxCols get(const char* table_name) { return FOptionVecOptionI32IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkBoolCols @@ -11734,28 +11479,14 @@ struct TESTCLIENT_API FPkBoolIxCols explicit FPkBoolIxCols(const char* TableName) : B(TableName, "b") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t B; + ::SpacetimeDB::query_builder::IxCol B; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FPkBoolCols get(const char* table_name) { return FPkBoolCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkBoolIxCols get(const char* table_name) { return FPkBoolIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; -} + struct CanBeLookupTable> : std::true_type {}; +} struct TESTCLIENT_API FPkConnectionIdCols { @@ -11771,27 +11502,13 @@ struct TESTCLIENT_API FPkConnectionIdIxCols explicit FPkConnectionIdIxCols(const char* TableName) : A(TableName, "a") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t A; + ::SpacetimeDB::query_builder::IxCol A; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkConnectionIdCols get(const char* table_name) { return FPkConnectionIdCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkConnectionIdIxCols get(const char* table_name) { return FPkConnectionIdIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkI128Cols @@ -11808,27 +11525,13 @@ struct TESTCLIENT_API FPkI128IxCols explicit FPkI128IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FPkI128Cols get(const char* table_name) { return FPkI128Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkI128IxCols get(const char* table_name) { return FPkI128IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkI16Cols @@ -11845,27 +11548,13 @@ struct TESTCLIENT_API FPkI16IxCols explicit FPkI16IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkI16Cols get(const char* table_name) { return FPkI16Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FPkI16IxCols get(const char* table_name) { return FPkI16IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkI256Cols @@ -11882,27 +11571,13 @@ struct TESTCLIENT_API FPkI256IxCols explicit FPkI256IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkI256Cols get(const char* table_name) { return FPkI256Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FPkI256IxCols get(const char* table_name) { return FPkI256IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkI32Cols @@ -11919,27 +11594,13 @@ struct TESTCLIENT_API FPkI32IxCols explicit FPkI32IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkI32Cols get(const char* table_name) { return FPkI32Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkI32IxCols get(const char* table_name) { return FPkI32IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkI64Cols @@ -11956,27 +11617,13 @@ struct TESTCLIENT_API FPkI64IxCols explicit FPkI64IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkI64Cols get(const char* table_name) { return FPkI64Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FPkI64IxCols get(const char* table_name) { return FPkI64IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkI8Cols @@ -11993,27 +11640,13 @@ struct TESTCLIENT_API FPkI8IxCols explicit FPkI8IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkI8Cols get(const char* table_name) { return FPkI8Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkI8IxCols get(const char* table_name) { return FPkI8IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkIdentityCols @@ -12030,27 +11663,13 @@ struct TESTCLIENT_API FPkIdentityIxCols explicit FPkIdentityIxCols(const char* TableName) : I(TableName, "i") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t I; + ::SpacetimeDB::query_builder::IxCol I; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkIdentityCols get(const char* table_name) { return FPkIdentityCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkIdentityIxCols get(const char* table_name) { return FPkIdentityIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkSimpleEnumCols @@ -12067,27 +11686,13 @@ struct TESTCLIENT_API FPkSimpleEnumIxCols explicit FPkSimpleEnumIxCols(const char* TableName) : A(TableName, "a") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t A; + ::SpacetimeDB::query_builder::IxCol A; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkSimpleEnumCols get(const char* table_name) { return FPkSimpleEnumCols(table_name); } - }; - template<> - struct HasIxCols - { - static FPkSimpleEnumIxCols get(const char* table_name) { return FPkSimpleEnumIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkStringCols @@ -12104,27 +11709,13 @@ struct TESTCLIENT_API FPkStringIxCols explicit FPkStringIxCols(const char* TableName) : S(TableName, "s") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t S; + ::SpacetimeDB::query_builder::IxCol S; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FPkStringCols get(const char* table_name) { return FPkStringCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkStringIxCols get(const char* table_name) { return FPkStringIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkU128Cols @@ -12141,27 +11732,13 @@ struct TESTCLIENT_API FPkU128IxCols explicit FPkU128IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FPkU128Cols get(const char* table_name) { return FPkU128Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkU128IxCols get(const char* table_name) { return FPkU128IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkU16Cols @@ -12178,27 +11755,13 @@ struct TESTCLIENT_API FPkU16IxCols explicit FPkU16IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FPkU16Cols get(const char* table_name) { return FPkU16Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkU16IxCols get(const char* table_name) { return FPkU16IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkU256Cols @@ -12215,27 +11778,13 @@ struct TESTCLIENT_API FPkU256IxCols explicit FPkU256IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkU256Cols get(const char* table_name) { return FPkU256Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkU256IxCols get(const char* table_name) { return FPkU256IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkU32Cols @@ -12252,27 +11801,13 @@ struct TESTCLIENT_API FPkU32IxCols explicit FPkU32IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkU32Cols get(const char* table_name) { return FPkU32Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FPkU32IxCols get(const char* table_name) { return FPkU32IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkU32TwoCols @@ -12289,27 +11824,13 @@ struct TESTCLIENT_API FPkU32TwoIxCols explicit FPkU32TwoIxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FPkU32TwoCols get(const char* table_name) { return FPkU32TwoCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkU32TwoIxCols get(const char* table_name) { return FPkU32TwoIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkU64Cols @@ -12326,27 +11847,13 @@ struct TESTCLIENT_API FPkU64IxCols explicit FPkU64IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkU64Cols get(const char* table_name) { return FPkU64Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FPkU64IxCols get(const char* table_name) { return FPkU64IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkU8Cols @@ -12363,27 +11870,13 @@ struct TESTCLIENT_API FPkU8IxCols explicit FPkU8IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkU8Cols get(const char* table_name) { return FPkU8Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkU8IxCols get(const char* table_name) { return FPkU8IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FPkUuidCols @@ -12400,27 +11893,13 @@ struct TESTCLIENT_API FPkUuidIxCols explicit FPkUuidIxCols(const char* TableName) : U(TableName, "u") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t U; + ::SpacetimeDB::query_builder::IxCol U; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FPkUuidCols get(const char* table_name) { return FPkUuidCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPkUuidIxCols get(const char* table_name) { return FPkUuidIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FResultEveryPrimitiveStructStringCols @@ -12440,21 +11919,8 @@ struct TESTCLIENT_API FResultEveryPrimitiveStructStringIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FResultEveryPrimitiveStructStringCols get(const char* table_name) { return FResultEveryPrimitiveStructStringCols(table_name); } - }; - template<> - struct HasIxCols - { - static FResultEveryPrimitiveStructStringIxCols get(const char* table_name) { return FResultEveryPrimitiveStructStringIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FResultI32StringCols @@ -12474,21 +11940,8 @@ struct TESTCLIENT_API FResultI32StringIxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FResultI32StringCols get(const char* table_name) { return FResultI32StringCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FResultI32StringIxCols get(const char* table_name) { return FResultI32StringIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FResultIdentityStringCols @@ -12508,21 +11961,8 @@ struct TESTCLIENT_API FResultIdentityStringIxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FResultIdentityStringCols get(const char* table_name) { return FResultIdentityStringCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FResultIdentityStringIxCols get(const char* table_name) { return FResultIdentityStringIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FResultSimpleEnumI32Cols @@ -12542,21 +11982,8 @@ struct TESTCLIENT_API FResultSimpleEnumI32IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FResultSimpleEnumI32Cols get(const char* table_name) { return FResultSimpleEnumI32Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FResultSimpleEnumI32IxCols get(const char* table_name) { return FResultSimpleEnumI32IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FResultStringI32Cols @@ -12576,21 +12003,8 @@ struct TESTCLIENT_API FResultStringI32IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FResultStringI32Cols get(const char* table_name) { return FResultStringI32Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FResultStringI32IxCols get(const char* table_name) { return FResultStringI32IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FResultVecI32StringCols @@ -12610,21 +12024,8 @@ struct TESTCLIENT_API FResultVecI32StringIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FResultVecI32StringCols get(const char* table_name) { return FResultVecI32StringCols(table_name); } - }; - template<> - struct HasIxCols - { - static FResultVecI32StringIxCols get(const char* table_name) { return FResultVecI32StringIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FScheduledTableCols @@ -12642,27 +12043,13 @@ struct TESTCLIENT_API FScheduledTableIxCols explicit FScheduledTableIxCols(const char* TableName) : ScheduledId(TableName, "scheduled_id") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t ScheduledId; + ::SpacetimeDB::query_builder::IxCol ScheduledId; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FScheduledTableCols get(const char* table_name) { return FScheduledTableCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FScheduledTableIxCols get(const char* table_name) { return FScheduledTableIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FTableHoldsTableCols @@ -12683,21 +12070,8 @@ struct TESTCLIENT_API FTableHoldsTableIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FTableHoldsTableCols get(const char* table_name) { return FTableHoldsTableCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FTableHoldsTableIxCols get(const char* table_name) { return FTableHoldsTableIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueBoolCols @@ -12714,27 +12088,13 @@ struct TESTCLIENT_API FUniqueBoolIxCols explicit FUniqueBoolIxCols(const char* TableName) : B(TableName, "b") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t B; + ::SpacetimeDB::query_builder::IxCol B; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FUniqueBoolCols get(const char* table_name) { return FUniqueBoolCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUniqueBoolIxCols get(const char* table_name) { return FUniqueBoolIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueConnectionIdCols @@ -12751,27 +12111,13 @@ struct TESTCLIENT_API FUniqueConnectionIdIxCols explicit FUniqueConnectionIdIxCols(const char* TableName) : A(TableName, "a") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t A; + ::SpacetimeDB::query_builder::IxCol A; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FUniqueConnectionIdCols get(const char* table_name) { return FUniqueConnectionIdCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUniqueConnectionIdIxCols get(const char* table_name) { return FUniqueConnectionIdIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueI128Cols @@ -12788,27 +12134,13 @@ struct TESTCLIENT_API FUniqueI128IxCols explicit FUniqueI128IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FUniqueI128Cols get(const char* table_name) { return FUniqueI128Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FUniqueI128IxCols get(const char* table_name) { return FUniqueI128IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueI16Cols @@ -12825,27 +12157,13 @@ struct TESTCLIENT_API FUniqueI16IxCols explicit FUniqueI16IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FUniqueI16Cols get(const char* table_name) { return FUniqueI16Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUniqueI16IxCols get(const char* table_name) { return FUniqueI16IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueI256Cols @@ -12862,27 +12180,13 @@ struct TESTCLIENT_API FUniqueI256IxCols explicit FUniqueI256IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FUniqueI256Cols get(const char* table_name) { return FUniqueI256Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUniqueI256IxCols get(const char* table_name) { return FUniqueI256IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueI32Cols @@ -12899,27 +12203,13 @@ struct TESTCLIENT_API FUniqueI32IxCols explicit FUniqueI32IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FUniqueI32Cols get(const char* table_name) { return FUniqueI32Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUniqueI32IxCols get(const char* table_name) { return FUniqueI32IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueI64Cols @@ -12936,27 +12226,13 @@ struct TESTCLIENT_API FUniqueI64IxCols explicit FUniqueI64IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FUniqueI64Cols get(const char* table_name) { return FUniqueI64Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUniqueI64IxCols get(const char* table_name) { return FUniqueI64IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueI8Cols @@ -12973,27 +12249,13 @@ struct TESTCLIENT_API FUniqueI8IxCols explicit FUniqueI8IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FUniqueI8Cols get(const char* table_name) { return FUniqueI8Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FUniqueI8IxCols get(const char* table_name) { return FUniqueI8IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueIdentityCols @@ -13010,27 +12272,13 @@ struct TESTCLIENT_API FUniqueIdentityIxCols explicit FUniqueIdentityIxCols(const char* TableName) : I(TableName, "i") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t I; + ::SpacetimeDB::query_builder::IxCol I; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FUniqueIdentityCols get(const char* table_name) { return FUniqueIdentityCols(table_name); } - }; - template<> - struct HasIxCols - { - static FUniqueIdentityIxCols get(const char* table_name) { return FUniqueIdentityIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueStringCols @@ -13047,27 +12295,13 @@ struct TESTCLIENT_API FUniqueStringIxCols explicit FUniqueStringIxCols(const char* TableName) : S(TableName, "s") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t S; + ::SpacetimeDB::query_builder::IxCol S; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FUniqueStringCols get(const char* table_name) { return FUniqueStringCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUniqueStringIxCols get(const char* table_name) { return FUniqueStringIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueU128Cols @@ -13084,27 +12318,13 @@ struct TESTCLIENT_API FUniqueU128IxCols explicit FUniqueU128IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FUniqueU128Cols get(const char* table_name) { return FUniqueU128Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FUniqueU128IxCols get(const char* table_name) { return FUniqueU128IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueU16Cols @@ -13121,27 +12341,13 @@ struct TESTCLIENT_API FUniqueU16IxCols explicit FUniqueU16IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FUniqueU16Cols get(const char* table_name) { return FUniqueU16Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUniqueU16IxCols get(const char* table_name) { return FUniqueU16IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueU256Cols @@ -13158,27 +12364,13 @@ struct TESTCLIENT_API FUniqueU256IxCols explicit FUniqueU256IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FUniqueU256Cols get(const char* table_name) { return FUniqueU256Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUniqueU256IxCols get(const char* table_name) { return FUniqueU256IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueU32Cols @@ -13195,27 +12387,13 @@ struct TESTCLIENT_API FUniqueU32IxCols explicit FUniqueU32IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FUniqueU32Cols get(const char* table_name) { return FUniqueU32Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FUniqueU32IxCols get(const char* table_name) { return FUniqueU32IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueU64Cols @@ -13232,27 +12410,13 @@ struct TESTCLIENT_API FUniqueU64IxCols explicit FUniqueU64IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FUniqueU64Cols get(const char* table_name) { return FUniqueU64Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUniqueU64IxCols get(const char* table_name) { return FUniqueU64IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueU8Cols @@ -13269,27 +12433,13 @@ struct TESTCLIENT_API FUniqueU8IxCols explicit FUniqueU8IxCols(const char* TableName) : N(TableName, "n") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t N; + ::SpacetimeDB::query_builder::IxCol N; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FUniqueU8Cols get(const char* table_name) { return FUniqueU8Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUniqueU8IxCols get(const char* table_name) { return FUniqueU8IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUniqueUuidCols @@ -13306,27 +12456,13 @@ struct TESTCLIENT_API FUniqueUuidIxCols explicit FUniqueUuidIxCols(const char* TableName) : U(TableName, "u") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t U; + ::SpacetimeDB::query_builder::IxCol U; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FUniqueUuidCols get(const char* table_name) { return FUniqueUuidCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUniqueUuidIxCols get(const char* table_name) { return FUniqueUuidIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FUsersCols @@ -13343,27 +12479,13 @@ struct TESTCLIENT_API FUsersIxCols explicit FUsersIxCols(const char* TableName) : Identity(TableName, "identity") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t Identity; + ::SpacetimeDB::query_builder::IxCol Identity; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - - template<> - struct HasCols - { - static FUsersCols get(const char* table_name) { return FUsersCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FUsersIxCols get(const char* table_name) { return FUsersIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecBoolCols @@ -13383,21 +12505,8 @@ struct TESTCLIENT_API FVecBoolIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecBoolCols get(const char* table_name) { return FVecBoolCols(table_name); } - }; - template<> - struct HasIxCols - { - static FVecBoolIxCols get(const char* table_name) { return FVecBoolIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecByteStructCols @@ -13417,21 +12526,8 @@ struct TESTCLIENT_API FVecByteStructIxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FVecByteStructCols get(const char* table_name) { return FVecByteStructCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecByteStructIxCols get(const char* table_name) { return FVecByteStructIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecConnectionIdCols @@ -13451,21 +12547,8 @@ struct TESTCLIENT_API FVecConnectionIdIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecConnectionIdCols get(const char* table_name) { return FVecConnectionIdCols(table_name); } - }; - template<> - struct HasIxCols - { - static FVecConnectionIdIxCols get(const char* table_name) { return FVecConnectionIdIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecEnumWithPayloadCols @@ -13485,21 +12568,8 @@ struct TESTCLIENT_API FVecEnumWithPayloadIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecEnumWithPayloadCols get(const char* table_name) { return FVecEnumWithPayloadCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecEnumWithPayloadIxCols get(const char* table_name) { return FVecEnumWithPayloadIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecEveryPrimitiveStructCols @@ -13519,21 +12589,8 @@ struct TESTCLIENT_API FVecEveryPrimitiveStructIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecEveryPrimitiveStructCols get(const char* table_name) { return FVecEveryPrimitiveStructCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecEveryPrimitiveStructIxCols get(const char* table_name) { return FVecEveryPrimitiveStructIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecEveryVecStructCols @@ -13553,21 +12610,8 @@ struct TESTCLIENT_API FVecEveryVecStructIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecEveryVecStructCols get(const char* table_name) { return FVecEveryVecStructCols(table_name); } - }; - template<> - struct HasIxCols - { - static FVecEveryVecStructIxCols get(const char* table_name) { return FVecEveryVecStructIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecF32Cols @@ -13587,21 +12631,8 @@ struct TESTCLIENT_API FVecF32IxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FVecF32Cols get(const char* table_name) { return FVecF32Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecF32IxCols get(const char* table_name) { return FVecF32IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecF64Cols @@ -13621,21 +12652,8 @@ struct TESTCLIENT_API FVecF64IxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FVecF64Cols get(const char* table_name) { return FVecF64Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecF64IxCols get(const char* table_name) { return FVecF64IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecI128Cols @@ -13655,21 +12673,8 @@ struct TESTCLIENT_API FVecI128IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecI128Cols get(const char* table_name) { return FVecI128Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecI128IxCols get(const char* table_name) { return FVecI128IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecI16Cols @@ -13689,21 +12694,8 @@ struct TESTCLIENT_API FVecI16IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecI16Cols get(const char* table_name) { return FVecI16Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecI16IxCols get(const char* table_name) { return FVecI16IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecI256Cols @@ -13723,21 +12715,8 @@ struct TESTCLIENT_API FVecI256IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecI256Cols get(const char* table_name) { return FVecI256Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FVecI256IxCols get(const char* table_name) { return FVecI256IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecI32Cols @@ -13757,21 +12736,8 @@ struct TESTCLIENT_API FVecI32IxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FVecI32Cols get(const char* table_name) { return FVecI32Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecI32IxCols get(const char* table_name) { return FVecI32IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecI64Cols @@ -13791,21 +12757,8 @@ struct TESTCLIENT_API FVecI64IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecI64Cols get(const char* table_name) { return FVecI64Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecI64IxCols get(const char* table_name) { return FVecI64IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecI8Cols @@ -13825,21 +12778,8 @@ struct TESTCLIENT_API FVecI8IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecI8Cols get(const char* table_name) { return FVecI8Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecI8IxCols get(const char* table_name) { return FVecI8IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecIdentityCols @@ -13859,21 +12799,8 @@ struct TESTCLIENT_API FVecIdentityIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecIdentityCols get(const char* table_name) { return FVecIdentityCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecIdentityIxCols get(const char* table_name) { return FVecIdentityIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecSimpleEnumCols @@ -13893,21 +12820,8 @@ struct TESTCLIENT_API FVecSimpleEnumIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecSimpleEnumCols get(const char* table_name) { return FVecSimpleEnumCols(table_name); } - }; - template<> - struct HasIxCols - { - static FVecSimpleEnumIxCols get(const char* table_name) { return FVecSimpleEnumIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecStringCols @@ -13927,21 +12841,8 @@ struct TESTCLIENT_API FVecStringIxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FVecStringCols get(const char* table_name) { return FVecStringCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecStringIxCols get(const char* table_name) { return FVecStringIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecTimestampCols @@ -13961,21 +12862,8 @@ struct TESTCLIENT_API FVecTimestampIxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FVecTimestampCols get(const char* table_name) { return FVecTimestampCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecTimestampIxCols get(const char* table_name) { return FVecTimestampIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecU128Cols @@ -13995,21 +12883,8 @@ struct TESTCLIENT_API FVecU128IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecU128Cols get(const char* table_name) { return FVecU128Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecU128IxCols get(const char* table_name) { return FVecU128IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecU16Cols @@ -14029,21 +12904,8 @@ struct TESTCLIENT_API FVecU16IxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FVecU16Cols get(const char* table_name) { return FVecU16Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecU16IxCols get(const char* table_name) { return FVecU16IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecU256Cols @@ -14063,21 +12925,8 @@ struct TESTCLIENT_API FVecU256IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecU256Cols get(const char* table_name) { return FVecU256Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FVecU256IxCols get(const char* table_name) { return FVecU256IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecU32Cols @@ -14097,21 +12946,8 @@ struct TESTCLIENT_API FVecU32IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecU32Cols get(const char* table_name) { return FVecU32Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FVecU32IxCols get(const char* table_name) { return FVecU32IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecU64Cols @@ -14131,21 +12967,8 @@ struct TESTCLIENT_API FVecU64IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecU64Cols get(const char* table_name) { return FVecU64Cols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecU64IxCols get(const char* table_name) { return FVecU64IxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecU8Cols @@ -14165,21 +12988,8 @@ struct TESTCLIENT_API FVecU8IxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecU8Cols get(const char* table_name) { return FVecU8Cols(table_name); } - }; - template<> - struct HasIxCols - { - static FVecU8IxCols get(const char* table_name) { return FVecU8IxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecUnitStructCols @@ -14199,21 +13009,8 @@ struct TESTCLIENT_API FVecUnitStructIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecUnitStructCols get(const char* table_name) { return FVecUnitStructCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecUnitStructIxCols get(const char* table_name) { return FVecUnitStructIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FVecUuidCols @@ -14233,132 +13030,119 @@ struct TESTCLIENT_API FVecUuidIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FVecUuidCols get(const char* table_name) { return FVecUuidCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FVecUuidIxCols get(const char* table_name) { return FVecUuidIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTCLIENT_API FFrom { - [[nodiscard]] ::SpacetimeDB::query_builder::Table BtreeU32() const { return ::SpacetimeDB::query_builder::Table("btree_u_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table IndexedSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("indexed_simple_enum"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table LargeTable() const { return ::SpacetimeDB::query_builder::Table("large_table"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneBool() const { return ::SpacetimeDB::query_builder::Table("one_bool"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneByteStruct() const { return ::SpacetimeDB::query_builder::Table("one_byte_struct"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneConnectionId() const { return ::SpacetimeDB::query_builder::Table("one_connection_id"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneEnumWithPayload() const { return ::SpacetimeDB::query_builder::Table("one_enum_with_payload"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneEveryPrimitiveStruct() const { return ::SpacetimeDB::query_builder::Table("one_every_primitive_struct"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneEveryVecStruct() const { return ::SpacetimeDB::query_builder::Table("one_every_vec_struct"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneF32() const { return ::SpacetimeDB::query_builder::Table("one_f_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneF64() const { return ::SpacetimeDB::query_builder::Table("one_f_64"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI128() const { return ::SpacetimeDB::query_builder::Table("one_i_128"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI16() const { return ::SpacetimeDB::query_builder::Table("one_i_16"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI256() const { return ::SpacetimeDB::query_builder::Table("one_i_256"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI32() const { return ::SpacetimeDB::query_builder::Table("one_i_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI64() const { return ::SpacetimeDB::query_builder::Table("one_i_64"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI8() const { return ::SpacetimeDB::query_builder::Table("one_i_8"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneIdentity() const { return ::SpacetimeDB::query_builder::Table("one_identity"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("one_simple_enum"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneString() const { return ::SpacetimeDB::query_builder::Table("one_string"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneTimestamp() const { return ::SpacetimeDB::query_builder::Table("one_timestamp"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU128() const { return ::SpacetimeDB::query_builder::Table("one_u_128"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU16() const { return ::SpacetimeDB::query_builder::Table("one_u_16"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU256() const { return ::SpacetimeDB::query_builder::Table("one_u_256"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU32() const { return ::SpacetimeDB::query_builder::Table("one_u_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU64() const { return ::SpacetimeDB::query_builder::Table("one_u_64"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU8() const { return ::SpacetimeDB::query_builder::Table("one_u_8"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneUnitStruct() const { return ::SpacetimeDB::query_builder::Table("one_unit_struct"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OneUuid() const { return ::SpacetimeDB::query_builder::Table("one_uuid"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionEveryPrimitiveStruct() const { return ::SpacetimeDB::query_builder::Table("option_every_primitive_struct"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionI32() const { return ::SpacetimeDB::query_builder::Table("option_i_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionIdentity() const { return ::SpacetimeDB::query_builder::Table("option_identity"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("option_simple_enum"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionString() const { return ::SpacetimeDB::query_builder::Table("option_string"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionUuid() const { return ::SpacetimeDB::query_builder::Table("option_uuid"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionVecOptionI32() const { return ::SpacetimeDB::query_builder::Table("option_vec_option_i_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkBool() const { return ::SpacetimeDB::query_builder::Table("pk_bool"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkConnectionId() const { return ::SpacetimeDB::query_builder::Table("pk_connection_id"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI128() const { return ::SpacetimeDB::query_builder::Table("pk_i_128"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI16() const { return ::SpacetimeDB::query_builder::Table("pk_i_16"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI256() const { return ::SpacetimeDB::query_builder::Table("pk_i_256"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI32() const { return ::SpacetimeDB::query_builder::Table("pk_i_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI64() const { return ::SpacetimeDB::query_builder::Table("pk_i_64"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI8() const { return ::SpacetimeDB::query_builder::Table("pk_i_8"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkIdentity() const { return ::SpacetimeDB::query_builder::Table("pk_identity"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("pk_simple_enum"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkString() const { return ::SpacetimeDB::query_builder::Table("pk_string"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU128() const { return ::SpacetimeDB::query_builder::Table("pk_u_128"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU16() const { return ::SpacetimeDB::query_builder::Table("pk_u_16"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU256() const { return ::SpacetimeDB::query_builder::Table("pk_u_256"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU32() const { return ::SpacetimeDB::query_builder::Table("pk_u_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU32Two() const { return ::SpacetimeDB::query_builder::Table("pk_u_32_two"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU64() const { return ::SpacetimeDB::query_builder::Table("pk_u_64"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU8() const { return ::SpacetimeDB::query_builder::Table("pk_u_8"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkUuid() const { return ::SpacetimeDB::query_builder::Table("pk_uuid"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultEveryPrimitiveStructString() const { return ::SpacetimeDB::query_builder::Table("result_every_primitive_struct_string"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultI32String() const { return ::SpacetimeDB::query_builder::Table("result_i_32_string"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultIdentityString() const { return ::SpacetimeDB::query_builder::Table("result_identity_string"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultSimpleEnumI32() const { return ::SpacetimeDB::query_builder::Table("result_simple_enum_i_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultStringI32() const { return ::SpacetimeDB::query_builder::Table("result_string_i_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultVecI32String() const { return ::SpacetimeDB::query_builder::Table("result_vec_i_32_string"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table ScheduledTable() const { return ::SpacetimeDB::query_builder::Table("scheduled_table"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table TableHoldsTable() const { return ::SpacetimeDB::query_builder::Table("table_holds_table"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueBool() const { return ::SpacetimeDB::query_builder::Table("unique_bool"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueConnectionId() const { return ::SpacetimeDB::query_builder::Table("unique_connection_id"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI128() const { return ::SpacetimeDB::query_builder::Table("unique_i_128"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI16() const { return ::SpacetimeDB::query_builder::Table("unique_i_16"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI256() const { return ::SpacetimeDB::query_builder::Table("unique_i_256"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI32() const { return ::SpacetimeDB::query_builder::Table("unique_i_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI64() const { return ::SpacetimeDB::query_builder::Table("unique_i_64"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI8() const { return ::SpacetimeDB::query_builder::Table("unique_i_8"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueIdentity() const { return ::SpacetimeDB::query_builder::Table("unique_identity"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueString() const { return ::SpacetimeDB::query_builder::Table("unique_string"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU128() const { return ::SpacetimeDB::query_builder::Table("unique_u_128"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU16() const { return ::SpacetimeDB::query_builder::Table("unique_u_16"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU256() const { return ::SpacetimeDB::query_builder::Table("unique_u_256"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU32() const { return ::SpacetimeDB::query_builder::Table("unique_u_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU64() const { return ::SpacetimeDB::query_builder::Table("unique_u_64"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU8() const { return ::SpacetimeDB::query_builder::Table("unique_u_8"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueUuid() const { return ::SpacetimeDB::query_builder::Table("unique_uuid"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table Users() const { return ::SpacetimeDB::query_builder::Table("users"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecBool() const { return ::SpacetimeDB::query_builder::Table("vec_bool"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecByteStruct() const { return ::SpacetimeDB::query_builder::Table("vec_byte_struct"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecConnectionId() const { return ::SpacetimeDB::query_builder::Table("vec_connection_id"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecEnumWithPayload() const { return ::SpacetimeDB::query_builder::Table("vec_enum_with_payload"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecEveryPrimitiveStruct() const { return ::SpacetimeDB::query_builder::Table("vec_every_primitive_struct"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecEveryVecStruct() const { return ::SpacetimeDB::query_builder::Table("vec_every_vec_struct"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecF32() const { return ::SpacetimeDB::query_builder::Table("vec_f_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecF64() const { return ::SpacetimeDB::query_builder::Table("vec_f_64"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI128() const { return ::SpacetimeDB::query_builder::Table("vec_i_128"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI16() const { return ::SpacetimeDB::query_builder::Table("vec_i_16"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI256() const { return ::SpacetimeDB::query_builder::Table("vec_i_256"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI32() const { return ::SpacetimeDB::query_builder::Table("vec_i_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI64() const { return ::SpacetimeDB::query_builder::Table("vec_i_64"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI8() const { return ::SpacetimeDB::query_builder::Table("vec_i_8"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecIdentity() const { return ::SpacetimeDB::query_builder::Table("vec_identity"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("vec_simple_enum"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecString() const { return ::SpacetimeDB::query_builder::Table("vec_string"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecTimestamp() const { return ::SpacetimeDB::query_builder::Table("vec_timestamp"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU128() const { return ::SpacetimeDB::query_builder::Table("vec_u_128"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU16() const { return ::SpacetimeDB::query_builder::Table("vec_u_16"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU256() const { return ::SpacetimeDB::query_builder::Table("vec_u_256"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU32() const { return ::SpacetimeDB::query_builder::Table("vec_u_32"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU64() const { return ::SpacetimeDB::query_builder::Table("vec_u_64"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU8() const { return ::SpacetimeDB::query_builder::Table("vec_u_8"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecUnitStruct() const { return ::SpacetimeDB::query_builder::Table("vec_unit_struct"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table VecUuid() const { return ::SpacetimeDB::query_builder::Table("vec_uuid"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table BtreeU32() const { return ::SpacetimeDB::query_builder::Table("btree_u_32", FBTreeU32Cols("btree_u_32"), FBTreeU32IxCols("btree_u_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table IndexedSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("indexed_simple_enum", FIndexedSimpleEnumCols("indexed_simple_enum"), FIndexedSimpleEnumIxCols("indexed_simple_enum")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table LargeTable() const { return ::SpacetimeDB::query_builder::Table("large_table", FLargeTableCols("large_table"), FLargeTableIxCols("large_table")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneBool() const { return ::SpacetimeDB::query_builder::Table("one_bool", FOneBoolCols("one_bool"), FOneBoolIxCols("one_bool")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneByteStruct() const { return ::SpacetimeDB::query_builder::Table("one_byte_struct", FOneByteStructCols("one_byte_struct"), FOneByteStructIxCols("one_byte_struct")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneConnectionId() const { return ::SpacetimeDB::query_builder::Table("one_connection_id", FOneConnectionIdCols("one_connection_id"), FOneConnectionIdIxCols("one_connection_id")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneEnumWithPayload() const { return ::SpacetimeDB::query_builder::Table("one_enum_with_payload", FOneEnumWithPayloadCols("one_enum_with_payload"), FOneEnumWithPayloadIxCols("one_enum_with_payload")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneEveryPrimitiveStruct() const { return ::SpacetimeDB::query_builder::Table("one_every_primitive_struct", FOneEveryPrimitiveStructCols("one_every_primitive_struct"), FOneEveryPrimitiveStructIxCols("one_every_primitive_struct")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneEveryVecStruct() const { return ::SpacetimeDB::query_builder::Table("one_every_vec_struct", FOneEveryVecStructCols("one_every_vec_struct"), FOneEveryVecStructIxCols("one_every_vec_struct")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneF32() const { return ::SpacetimeDB::query_builder::Table("one_f_32", FOneF32Cols("one_f_32"), FOneF32IxCols("one_f_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneF64() const { return ::SpacetimeDB::query_builder::Table("one_f_64", FOneF64Cols("one_f_64"), FOneF64IxCols("one_f_64")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI128() const { return ::SpacetimeDB::query_builder::Table("one_i_128", FOneI128Cols("one_i_128"), FOneI128IxCols("one_i_128")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI16() const { return ::SpacetimeDB::query_builder::Table("one_i_16", FOneI16Cols("one_i_16"), FOneI16IxCols("one_i_16")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI256() const { return ::SpacetimeDB::query_builder::Table("one_i_256", FOneI256Cols("one_i_256"), FOneI256IxCols("one_i_256")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI32() const { return ::SpacetimeDB::query_builder::Table("one_i_32", FOneI32Cols("one_i_32"), FOneI32IxCols("one_i_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI64() const { return ::SpacetimeDB::query_builder::Table("one_i_64", FOneI64Cols("one_i_64"), FOneI64IxCols("one_i_64")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneI8() const { return ::SpacetimeDB::query_builder::Table("one_i_8", FOneI8Cols("one_i_8"), FOneI8IxCols("one_i_8")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneIdentity() const { return ::SpacetimeDB::query_builder::Table("one_identity", FOneIdentityCols("one_identity"), FOneIdentityIxCols("one_identity")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("one_simple_enum", FOneSimpleEnumCols("one_simple_enum"), FOneSimpleEnumIxCols("one_simple_enum")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneString() const { return ::SpacetimeDB::query_builder::Table("one_string", FOneStringCols("one_string"), FOneStringIxCols("one_string")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneTimestamp() const { return ::SpacetimeDB::query_builder::Table("one_timestamp", FOneTimestampCols("one_timestamp"), FOneTimestampIxCols("one_timestamp")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU128() const { return ::SpacetimeDB::query_builder::Table("one_u_128", FOneU128Cols("one_u_128"), FOneU128IxCols("one_u_128")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU16() const { return ::SpacetimeDB::query_builder::Table("one_u_16", FOneU16Cols("one_u_16"), FOneU16IxCols("one_u_16")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU256() const { return ::SpacetimeDB::query_builder::Table("one_u_256", FOneU256Cols("one_u_256"), FOneU256IxCols("one_u_256")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU32() const { return ::SpacetimeDB::query_builder::Table("one_u_32", FOneU32Cols("one_u_32"), FOneU32IxCols("one_u_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU64() const { return ::SpacetimeDB::query_builder::Table("one_u_64", FOneU64Cols("one_u_64"), FOneU64IxCols("one_u_64")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneU8() const { return ::SpacetimeDB::query_builder::Table("one_u_8", FOneU8Cols("one_u_8"), FOneU8IxCols("one_u_8")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneUnitStruct() const { return ::SpacetimeDB::query_builder::Table("one_unit_struct", FOneUnitStructCols("one_unit_struct"), FOneUnitStructIxCols("one_unit_struct")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OneUuid() const { return ::SpacetimeDB::query_builder::Table("one_uuid", FOneUuidCols("one_uuid"), FOneUuidIxCols("one_uuid")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionEveryPrimitiveStruct() const { return ::SpacetimeDB::query_builder::Table("option_every_primitive_struct", FOptionEveryPrimitiveStructCols("option_every_primitive_struct"), FOptionEveryPrimitiveStructIxCols("option_every_primitive_struct")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionI32() const { return ::SpacetimeDB::query_builder::Table("option_i_32", FOptionI32Cols("option_i_32"), FOptionI32IxCols("option_i_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionIdentity() const { return ::SpacetimeDB::query_builder::Table("option_identity", FOptionIdentityCols("option_identity"), FOptionIdentityIxCols("option_identity")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("option_simple_enum", FOptionSimpleEnumCols("option_simple_enum"), FOptionSimpleEnumIxCols("option_simple_enum")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionString() const { return ::SpacetimeDB::query_builder::Table("option_string", FOptionStringCols("option_string"), FOptionStringIxCols("option_string")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionUuid() const { return ::SpacetimeDB::query_builder::Table("option_uuid", FOptionUuidCols("option_uuid"), FOptionUuidIxCols("option_uuid")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table OptionVecOptionI32() const { return ::SpacetimeDB::query_builder::Table("option_vec_option_i_32", FOptionVecOptionI32Cols("option_vec_option_i_32"), FOptionVecOptionI32IxCols("option_vec_option_i_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkBool() const { return ::SpacetimeDB::query_builder::Table("pk_bool", FPkBoolCols("pk_bool"), FPkBoolIxCols("pk_bool")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkConnectionId() const { return ::SpacetimeDB::query_builder::Table("pk_connection_id", FPkConnectionIdCols("pk_connection_id"), FPkConnectionIdIxCols("pk_connection_id")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI128() const { return ::SpacetimeDB::query_builder::Table("pk_i_128", FPkI128Cols("pk_i_128"), FPkI128IxCols("pk_i_128")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI16() const { return ::SpacetimeDB::query_builder::Table("pk_i_16", FPkI16Cols("pk_i_16"), FPkI16IxCols("pk_i_16")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI256() const { return ::SpacetimeDB::query_builder::Table("pk_i_256", FPkI256Cols("pk_i_256"), FPkI256IxCols("pk_i_256")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI32() const { return ::SpacetimeDB::query_builder::Table("pk_i_32", FPkI32Cols("pk_i_32"), FPkI32IxCols("pk_i_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI64() const { return ::SpacetimeDB::query_builder::Table("pk_i_64", FPkI64Cols("pk_i_64"), FPkI64IxCols("pk_i_64")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkI8() const { return ::SpacetimeDB::query_builder::Table("pk_i_8", FPkI8Cols("pk_i_8"), FPkI8IxCols("pk_i_8")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkIdentity() const { return ::SpacetimeDB::query_builder::Table("pk_identity", FPkIdentityCols("pk_identity"), FPkIdentityIxCols("pk_identity")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("pk_simple_enum", FPkSimpleEnumCols("pk_simple_enum"), FPkSimpleEnumIxCols("pk_simple_enum")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkString() const { return ::SpacetimeDB::query_builder::Table("pk_string", FPkStringCols("pk_string"), FPkStringIxCols("pk_string")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU128() const { return ::SpacetimeDB::query_builder::Table("pk_u_128", FPkU128Cols("pk_u_128"), FPkU128IxCols("pk_u_128")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU16() const { return ::SpacetimeDB::query_builder::Table("pk_u_16", FPkU16Cols("pk_u_16"), FPkU16IxCols("pk_u_16")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU256() const { return ::SpacetimeDB::query_builder::Table("pk_u_256", FPkU256Cols("pk_u_256"), FPkU256IxCols("pk_u_256")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU32() const { return ::SpacetimeDB::query_builder::Table("pk_u_32", FPkU32Cols("pk_u_32"), FPkU32IxCols("pk_u_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU32Two() const { return ::SpacetimeDB::query_builder::Table("pk_u_32_two", FPkU32TwoCols("pk_u_32_two"), FPkU32TwoIxCols("pk_u_32_two")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU64() const { return ::SpacetimeDB::query_builder::Table("pk_u_64", FPkU64Cols("pk_u_64"), FPkU64IxCols("pk_u_64")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkU8() const { return ::SpacetimeDB::query_builder::Table("pk_u_8", FPkU8Cols("pk_u_8"), FPkU8IxCols("pk_u_8")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkUuid() const { return ::SpacetimeDB::query_builder::Table("pk_uuid", FPkUuidCols("pk_uuid"), FPkUuidIxCols("pk_uuid")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultEveryPrimitiveStructString() const { return ::SpacetimeDB::query_builder::Table("result_every_primitive_struct_string", FResultEveryPrimitiveStructStringCols("result_every_primitive_struct_string"), FResultEveryPrimitiveStructStringIxCols("result_every_primitive_struct_string")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultI32String() const { return ::SpacetimeDB::query_builder::Table("result_i_32_string", FResultI32StringCols("result_i_32_string"), FResultI32StringIxCols("result_i_32_string")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultIdentityString() const { return ::SpacetimeDB::query_builder::Table("result_identity_string", FResultIdentityStringCols("result_identity_string"), FResultIdentityStringIxCols("result_identity_string")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultSimpleEnumI32() const { return ::SpacetimeDB::query_builder::Table("result_simple_enum_i_32", FResultSimpleEnumI32Cols("result_simple_enum_i_32"), FResultSimpleEnumI32IxCols("result_simple_enum_i_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultStringI32() const { return ::SpacetimeDB::query_builder::Table("result_string_i_32", FResultStringI32Cols("result_string_i_32"), FResultStringI32IxCols("result_string_i_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ResultVecI32String() const { return ::SpacetimeDB::query_builder::Table("result_vec_i_32_string", FResultVecI32StringCols("result_vec_i_32_string"), FResultVecI32StringIxCols("result_vec_i_32_string")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ScheduledTable() const { return ::SpacetimeDB::query_builder::Table("scheduled_table", FScheduledTableCols("scheduled_table"), FScheduledTableIxCols("scheduled_table")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table TableHoldsTable() const { return ::SpacetimeDB::query_builder::Table("table_holds_table", FTableHoldsTableCols("table_holds_table"), FTableHoldsTableIxCols("table_holds_table")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueBool() const { return ::SpacetimeDB::query_builder::Table("unique_bool", FUniqueBoolCols("unique_bool"), FUniqueBoolIxCols("unique_bool")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueConnectionId() const { return ::SpacetimeDB::query_builder::Table("unique_connection_id", FUniqueConnectionIdCols("unique_connection_id"), FUniqueConnectionIdIxCols("unique_connection_id")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI128() const { return ::SpacetimeDB::query_builder::Table("unique_i_128", FUniqueI128Cols("unique_i_128"), FUniqueI128IxCols("unique_i_128")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI16() const { return ::SpacetimeDB::query_builder::Table("unique_i_16", FUniqueI16Cols("unique_i_16"), FUniqueI16IxCols("unique_i_16")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI256() const { return ::SpacetimeDB::query_builder::Table("unique_i_256", FUniqueI256Cols("unique_i_256"), FUniqueI256IxCols("unique_i_256")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI32() const { return ::SpacetimeDB::query_builder::Table("unique_i_32", FUniqueI32Cols("unique_i_32"), FUniqueI32IxCols("unique_i_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI64() const { return ::SpacetimeDB::query_builder::Table("unique_i_64", FUniqueI64Cols("unique_i_64"), FUniqueI64IxCols("unique_i_64")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueI8() const { return ::SpacetimeDB::query_builder::Table("unique_i_8", FUniqueI8Cols("unique_i_8"), FUniqueI8IxCols("unique_i_8")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueIdentity() const { return ::SpacetimeDB::query_builder::Table("unique_identity", FUniqueIdentityCols("unique_identity"), FUniqueIdentityIxCols("unique_identity")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueString() const { return ::SpacetimeDB::query_builder::Table("unique_string", FUniqueStringCols("unique_string"), FUniqueStringIxCols("unique_string")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU128() const { return ::SpacetimeDB::query_builder::Table("unique_u_128", FUniqueU128Cols("unique_u_128"), FUniqueU128IxCols("unique_u_128")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU16() const { return ::SpacetimeDB::query_builder::Table("unique_u_16", FUniqueU16Cols("unique_u_16"), FUniqueU16IxCols("unique_u_16")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU256() const { return ::SpacetimeDB::query_builder::Table("unique_u_256", FUniqueU256Cols("unique_u_256"), FUniqueU256IxCols("unique_u_256")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU32() const { return ::SpacetimeDB::query_builder::Table("unique_u_32", FUniqueU32Cols("unique_u_32"), FUniqueU32IxCols("unique_u_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU64() const { return ::SpacetimeDB::query_builder::Table("unique_u_64", FUniqueU64Cols("unique_u_64"), FUniqueU64IxCols("unique_u_64")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueU8() const { return ::SpacetimeDB::query_builder::Table("unique_u_8", FUniqueU8Cols("unique_u_8"), FUniqueU8IxCols("unique_u_8")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table UniqueUuid() const { return ::SpacetimeDB::query_builder::Table("unique_uuid", FUniqueUuidCols("unique_uuid"), FUniqueUuidIxCols("unique_uuid")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table Users() const { return ::SpacetimeDB::query_builder::Table("users", FUsersCols("users"), FUsersIxCols("users")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecBool() const { return ::SpacetimeDB::query_builder::Table("vec_bool", FVecBoolCols("vec_bool"), FVecBoolIxCols("vec_bool")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecByteStruct() const { return ::SpacetimeDB::query_builder::Table("vec_byte_struct", FVecByteStructCols("vec_byte_struct"), FVecByteStructIxCols("vec_byte_struct")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecConnectionId() const { return ::SpacetimeDB::query_builder::Table("vec_connection_id", FVecConnectionIdCols("vec_connection_id"), FVecConnectionIdIxCols("vec_connection_id")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecEnumWithPayload() const { return ::SpacetimeDB::query_builder::Table("vec_enum_with_payload", FVecEnumWithPayloadCols("vec_enum_with_payload"), FVecEnumWithPayloadIxCols("vec_enum_with_payload")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecEveryPrimitiveStruct() const { return ::SpacetimeDB::query_builder::Table("vec_every_primitive_struct", FVecEveryPrimitiveStructCols("vec_every_primitive_struct"), FVecEveryPrimitiveStructIxCols("vec_every_primitive_struct")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecEveryVecStruct() const { return ::SpacetimeDB::query_builder::Table("vec_every_vec_struct", FVecEveryVecStructCols("vec_every_vec_struct"), FVecEveryVecStructIxCols("vec_every_vec_struct")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecF32() const { return ::SpacetimeDB::query_builder::Table("vec_f_32", FVecF32Cols("vec_f_32"), FVecF32IxCols("vec_f_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecF64() const { return ::SpacetimeDB::query_builder::Table("vec_f_64", FVecF64Cols("vec_f_64"), FVecF64IxCols("vec_f_64")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI128() const { return ::SpacetimeDB::query_builder::Table("vec_i_128", FVecI128Cols("vec_i_128"), FVecI128IxCols("vec_i_128")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI16() const { return ::SpacetimeDB::query_builder::Table("vec_i_16", FVecI16Cols("vec_i_16"), FVecI16IxCols("vec_i_16")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI256() const { return ::SpacetimeDB::query_builder::Table("vec_i_256", FVecI256Cols("vec_i_256"), FVecI256IxCols("vec_i_256")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI32() const { return ::SpacetimeDB::query_builder::Table("vec_i_32", FVecI32Cols("vec_i_32"), FVecI32IxCols("vec_i_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI64() const { return ::SpacetimeDB::query_builder::Table("vec_i_64", FVecI64Cols("vec_i_64"), FVecI64IxCols("vec_i_64")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecI8() const { return ::SpacetimeDB::query_builder::Table("vec_i_8", FVecI8Cols("vec_i_8"), FVecI8IxCols("vec_i_8")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecIdentity() const { return ::SpacetimeDB::query_builder::Table("vec_identity", FVecIdentityCols("vec_identity"), FVecIdentityIxCols("vec_identity")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecSimpleEnum() const { return ::SpacetimeDB::query_builder::Table("vec_simple_enum", FVecSimpleEnumCols("vec_simple_enum"), FVecSimpleEnumIxCols("vec_simple_enum")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecString() const { return ::SpacetimeDB::query_builder::Table("vec_string", FVecStringCols("vec_string"), FVecStringIxCols("vec_string")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecTimestamp() const { return ::SpacetimeDB::query_builder::Table("vec_timestamp", FVecTimestampCols("vec_timestamp"), FVecTimestampIxCols("vec_timestamp")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU128() const { return ::SpacetimeDB::query_builder::Table("vec_u_128", FVecU128Cols("vec_u_128"), FVecU128IxCols("vec_u_128")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU16() const { return ::SpacetimeDB::query_builder::Table("vec_u_16", FVecU16Cols("vec_u_16"), FVecU16IxCols("vec_u_16")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU256() const { return ::SpacetimeDB::query_builder::Table("vec_u_256", FVecU256Cols("vec_u_256"), FVecU256IxCols("vec_u_256")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU32() const { return ::SpacetimeDB::query_builder::Table("vec_u_32", FVecU32Cols("vec_u_32"), FVecU32IxCols("vec_u_32")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU64() const { return ::SpacetimeDB::query_builder::Table("vec_u_64", FVecU64Cols("vec_u_64"), FVecU64IxCols("vec_u_64")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecU8() const { return ::SpacetimeDB::query_builder::Table("vec_u_8", FVecU8Cols("vec_u_8"), FVecU8IxCols("vec_u_8")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecUnitStruct() const { return ::SpacetimeDB::query_builder::Table("vec_unit_struct", FVecUnitStructCols("vec_unit_struct"), FVecUnitStructIxCols("vec_unit_struct")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table VecUuid() const { return ::SpacetimeDB::query_builder::Table("vec_uuid", FVecUuidCols("vec_uuid"), FVecUuidIxCols("vec_uuid")); } }; struct TESTCLIENT_API FQueryBuilder @@ -14534,7 +13318,7 @@ class TESTCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase return Typed; } - /** Convenience for subscribing to all rows from all tables */ + /** Convenience for subscribing to all rows from all public sources, including views */ UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") USubscriptionHandle* SubscribeToAllTables(); diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h index 2216ede8dae..98834a02d59 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h @@ -4,9 +4,9 @@ #pragma once #include "CoreMinimal.h" #include "BSATN/UESpacetimeDB.h" +#include "Kismet/BlueprintFunctionLibrary.h" #include "ModuleBindings/Types/SimpleEnumType.g.h" #include "Types/Builtins.h" -#include "Kismet/BlueprintFunctionLibrary.h" #include "EnumWithPayloadType.g.generated.h" UENUM(BlueprintType) @@ -46,7 +46,7 @@ struct TESTCLIENT_API FEnumWithPayloadType public: FEnumWithPayloadType() = default; - TVariant, FSpacetimeDBConnectionId, TArray, int8, int16, FSpacetimeDBInt128, FSpacetimeDBIdentity, FSpacetimeDBUuid, uint32, TArray, FSpacetimeDBInt256, bool, uint64, FString, TArray, uint16, FSpacetimeDBUInt128, uint8, int32, int64, double, float> MessageData; + TVariant, FSpacetimeDBUInt128, TArray, bool, int64, int16, uint16, FSpacetimeDBInt256, FSpacetimeDBInt128, float, uint8, FSpacetimeDBConnectionId, TArray, double, FString, int32, uint64, TArray, uint32, FSpacetimeDBUInt256, int8> MessageData; UPROPERTY(BlueprintReadOnly) EEnumWithPayloadTag Tag = static_cast(0); diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h index 21277cb0b15..55fd0f324a6 100644 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -1114,6 +1114,7 @@ class TESTPROCCLIENT_API URemoteProcedures : public UObject // QueryBuilder types struct TESTPROCCLIENT_API FMyTableCols { + using legacy_type = FMyTableCols; explicit FMyTableCols(const char* TableName) : Field(TableName, "field") {} @@ -1122,6 +1123,7 @@ struct TESTPROCCLIENT_API FMyTableCols struct TESTPROCCLIENT_API FMyTableIxCols { + using legacy_type = FMyTableIxCols; explicit FMyTableIxCols(const char* TableName) {} @@ -1129,25 +1131,13 @@ struct TESTPROCCLIENT_API FMyTableIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FMyTableCols get(const char* table_name) { return FMyTableCols(table_name); } - }; - template<> - struct HasIxCols - { - static FMyTableIxCols get(const char* table_name) { return FMyTableIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTPROCCLIENT_API FPkUuidCols { + using legacy_type = FPkUuidCols; explicit FPkUuidCols(const char* TableName) : U(TableName, "u"), Data(TableName, "data") {} @@ -1157,6 +1147,7 @@ struct TESTPROCCLIENT_API FPkUuidCols struct TESTPROCCLIENT_API FPkUuidIxCols { + using legacy_type = FPkUuidIxCols; explicit FPkUuidIxCols(const char* TableName) {} @@ -1164,25 +1155,13 @@ struct TESTPROCCLIENT_API FPkUuidIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FPkUuidCols get(const char* table_name) { return FPkUuidCols(table_name); } - }; - template<> - struct HasIxCols - { - static FPkUuidIxCols get(const char* table_name) { return FPkUuidIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTPROCCLIENT_API FProcInsertsIntoCols { + using legacy_type = FProcInsertsIntoCols; explicit FProcInsertsIntoCols(const char* TableName) : ReducerTs(TableName, "reducer_ts"), ProcedureTs(TableName, "procedure_ts"), X(TableName, "x"), Y(TableName, "y") {} @@ -1194,6 +1173,7 @@ struct TESTPROCCLIENT_API FProcInsertsIntoCols struct TESTPROCCLIENT_API FProcInsertsIntoIxCols { + using legacy_type = FProcInsertsIntoIxCols; explicit FProcInsertsIntoIxCols(const char* TableName) {} @@ -1201,28 +1181,15 @@ struct TESTPROCCLIENT_API FProcInsertsIntoIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FProcInsertsIntoCols get(const char* table_name) { return FProcInsertsIntoCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FProcInsertsIntoIxCols get(const char* table_name) { return FProcInsertsIntoIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTPROCCLIENT_API FFrom { - [[nodiscard]] ::SpacetimeDB::query_builder::Table MyTable() const { return ::SpacetimeDB::query_builder::Table("my_table"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PkUuid() const { return ::SpacetimeDB::query_builder::Table("pk_uuid"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table ProcInsertsInto() const { return ::SpacetimeDB::query_builder::Table("proc_inserts_into"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table MyTable() const { return ::SpacetimeDB::query_builder::Table("my_table", FMyTableCols("my_table"), FMyTableIxCols("my_table")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PkUuid() const { return ::SpacetimeDB::query_builder::Table("pk_uuid", FPkUuidCols("pk_uuid"), FPkUuidIxCols("pk_uuid")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ProcInsertsInto() const { return ::SpacetimeDB::query_builder::Table("proc_inserts_into", FProcInsertsIntoCols("proc_inserts_into"), FProcInsertsIntoIxCols("proc_inserts_into")); } }; struct TESTPROCCLIENT_API FQueryBuilder @@ -1294,7 +1261,7 @@ class TESTPROCCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase return Typed; } - /** Convenience for subscribing to all rows from all tables */ + /** Convenience for subscribing to all rows from all public sources, including views */ UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") USubscriptionHandle* SubscribeToAllTables(); diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Types/ReturnEnumType.g.h b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Types/ReturnEnumType.g.h index a0235284c48..14b4b797c33 100644 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Types/ReturnEnumType.g.h +++ b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Types/ReturnEnumType.g.h @@ -22,7 +22,7 @@ struct TESTPROCCLIENT_API FReturnEnumType public: FReturnEnumType() = default; - TVariant MessageData; + TVariant MessageData; UPROPERTY(BlueprintReadOnly) EReturnEnumTag Tag = static_cast(0); diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/SpacetimeFullClientTests.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/SpacetimeFullClientTests.cpp index 2b91569c029..c8364b3ae91 100644 --- a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/SpacetimeFullClientTests.cpp +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/SpacetimeFullClientTests.cpp @@ -39,7 +39,7 @@ bool FViewQueryBuilderDirectSourcesTest::RunTest(const FString& Parameters) return Query.From.MyPlayer(); }).AddQuery([](const FQueryBuilder& Query) { - return Query.From.PlayersAtLevel0().Where([](const FPlayerCols& Cols) + return Query.From.PlayersAtLevel0().Where([](const FPlayersAtLevel0Cols& Cols) { return Cols.EntityId.Eq(static_cast(7)); }); diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/SpacetimeDBClient.g.h index 66679a9cd6a..63cac5c2734 100644 --- a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -758,43 +758,39 @@ class TESTVIEWCLIENT_API URemoteProcedures : public UObject }; // QueryBuilder types -struct TESTVIEWCLIENT_API FPlayerCols +struct TESTVIEWCLIENT_API FMyPlayerCols; +struct TESTVIEWCLIENT_API FMyPlayerIxCols; +struct TESTVIEWCLIENT_API FPlayerAndLevelCols; +struct TESTVIEWCLIENT_API FPlayerAndLevelIxCols; +struct TESTVIEWCLIENT_API FPlayerLocationCols; +struct TESTVIEWCLIENT_API FPlayerLocationIxCols; +struct TESTVIEWCLIENT_API FPlayerCols; +struct TESTVIEWCLIENT_API FPlayerIxCols; +struct TESTVIEWCLIENT_API FPlayerLevelCols; +struct TESTVIEWCLIENT_API FPlayerLevelIxCols; +struct TESTVIEWCLIENT_API FPlayersAtLevel0Cols; +struct TESTVIEWCLIENT_API FPlayersAtLevel0IxCols; + +struct TESTVIEWCLIENT_API FMyPlayerCols { - explicit FPlayerCols(const char* TableName) + explicit FMyPlayerCols(const char* TableName) : EntityId(TableName, "entity_id"), Identity(TableName, "identity") {} ::SpacetimeDB::query_builder::Col EntityId; ::SpacetimeDB::query_builder::Col Identity; }; -struct TESTVIEWCLIENT_API FPlayerIxCols +struct TESTVIEWCLIENT_API FMyPlayerIxCols { - explicit FPlayerIxCols(const char* TableName) - : EntityId(TableName, "entity_id"), Identity(TableName, "identity") {} + explicit FMyPlayerIxCols(const char* TableName) + {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t EntityId; - ::SpacetimeDB::query_builder::detail::ix_col_member_t Identity; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FPlayerCols get(const char* table_name) { return FPlayerCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPlayerIxCols get(const char* table_name) { return FPlayerIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTVIEWCLIENT_API FPlayerAndLevelCols @@ -816,21 +812,8 @@ struct TESTVIEWCLIENT_API FPlayerAndLevelIxCols namespace SpacetimeDB::query_builder { - - template<> - struct HasCols - { - static FPlayerAndLevelCols get(const char* table_name) { return FPlayerAndLevelCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FPlayerAndLevelIxCols get(const char* table_name) { return FPlayerAndLevelIxCols(table_name); } - }; - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTVIEWCLIENT_API FPlayerLocationCols @@ -853,21 +836,32 @@ struct TESTVIEWCLIENT_API FPlayerLocationIxCols namespace SpacetimeDB::query_builder { - template<> - struct HasCols - { - static FPlayerLocationCols get(const char* table_name) { return FPlayerLocationCols(table_name); } - }; + struct CanBeLookupTable> : std::true_type {}; +} - template<> - struct HasIxCols - { - static FPlayerLocationIxCols get(const char* table_name) { return FPlayerLocationIxCols(table_name); } - }; +struct TESTVIEWCLIENT_API FPlayerCols +{ + explicit FPlayerCols(const char* TableName) + : EntityId(TableName, "entity_id"), Identity(TableName, "identity") {} + + ::SpacetimeDB::query_builder::Col EntityId; + ::SpacetimeDB::query_builder::Col Identity; +}; + +struct TESTVIEWCLIENT_API FPlayerIxCols +{ + explicit FPlayerIxCols(const char* TableName) + : EntityId(TableName, "entity_id"), Identity(TableName, "identity") {} + ::SpacetimeDB::query_builder::IxCol EntityId; + ::SpacetimeDB::query_builder::IxCol Identity; +}; + +namespace SpacetimeDB::query_builder +{ template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTVIEWCLIENT_API FPlayerLevelCols @@ -884,39 +878,46 @@ struct TESTVIEWCLIENT_API FPlayerLevelIxCols explicit FPlayerLevelIxCols(const char* TableName) : EntityId(TableName, "entity_id"), Level(TableName, "level") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t EntityId; - ::SpacetimeDB::query_builder::detail::ix_col_member_t Level; + ::SpacetimeDB::query_builder::IxCol EntityId; + ::SpacetimeDB::query_builder::IxCol Level; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FPlayerLevelCols get(const char* table_name) { return FPlayerLevelCols(table_name); } - }; + struct CanBeLookupTable> : std::true_type {}; +} - template<> - struct HasIxCols - { - static FPlayerLevelIxCols get(const char* table_name) { return FPlayerLevelIxCols(table_name); } - }; +struct TESTVIEWCLIENT_API FPlayersAtLevel0Cols +{ + explicit FPlayersAtLevel0Cols(const char* TableName) + : EntityId(TableName, "entity_id"), Identity(TableName, "identity") {} + + ::SpacetimeDB::query_builder::Col EntityId; + ::SpacetimeDB::query_builder::Col Identity; +}; +struct TESTVIEWCLIENT_API FPlayersAtLevel0IxCols +{ + explicit FPlayersAtLevel0IxCols(const char* TableName) + {} + +}; + +namespace SpacetimeDB::query_builder +{ template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTVIEWCLIENT_API FFrom { - [[nodiscard]] ::SpacetimeDB::query_builder::Table MyPlayer() const { return ::SpacetimeDB::query_builder::Table("my_player"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table MyPlayerAndLevel() const { return ::SpacetimeDB::query_builder::Table("my_player_and_level"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table NearbyPlayers() const { return ::SpacetimeDB::query_builder::Table("nearby_players"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table Player() const { return ::SpacetimeDB::query_builder::Table("player"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PlayerLevel() const { return ::SpacetimeDB::query_builder::Table("player_level"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table PlayersAtLevel0() const { return ::SpacetimeDB::query_builder::Table("players_at_level_0"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table MyPlayer() const { return ::SpacetimeDB::query_builder::Table("my_player", FMyPlayerCols("my_player"), FMyPlayerIxCols("my_player")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table MyPlayerAndLevel() const { return ::SpacetimeDB::query_builder::Table("my_player_and_level", FPlayerAndLevelCols("my_player_and_level"), FPlayerAndLevelIxCols("my_player_and_level")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table NearbyPlayers() const { return ::SpacetimeDB::query_builder::Table("nearby_players", FPlayerLocationCols("nearby_players"), FPlayerLocationIxCols("nearby_players")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table Player() const { return ::SpacetimeDB::query_builder::Table("player", FPlayerCols("player"), FPlayerIxCols("player")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PlayerLevel() const { return ::SpacetimeDB::query_builder::Table("player_level", FPlayerLevelCols("player_level"), FPlayerLevelIxCols("player_level")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table PlayersAtLevel0() const { return ::SpacetimeDB::query_builder::Table("players_at_level_0", FPlayersAtLevel0Cols("players_at_level_0"), FPlayersAtLevel0IxCols("players_at_level_0")); } }; struct TESTVIEWCLIENT_API FQueryBuilder @@ -991,7 +992,7 @@ class TESTVIEWCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase return Typed; } - /** Convenience for subscribing to all rows from all tables */ + /** Convenience for subscribing to all rows from all public sources, including views */ UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") USubscriptionHandle* SubscribeToAllTables(); diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/SpacetimeFullClientTests.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/SpacetimeFullClientTests.cpp index 555950a68a7..6b71fc3e616 100644 --- a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/SpacetimeFullClientTests.cpp +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/SpacetimeFullClientTests.cpp @@ -101,14 +101,14 @@ bool FViewPkQueryBuilderSemijoinTest::RunTest(const FString& Parameters) FQueryBuilder Q; const FString MembershipJoinSql = ToFString( - Q.From.ViewPkMembership().RightSemijoin(Q.From.AllViewPkPlayers(), [](const FViewPkMembershipIxCols& Membership, const FViewPkPlayerIxCols& Player) + Q.From.ViewPkMembership().RightSemijoin(Q.From.AllViewPkPlayers(), [](const FViewPkMembershipIxCols& Membership, const FAllViewPkPlayersIxCols& Player) { return Membership.PlayerId.Eq(Player.Id); }).into_sql() ); const FString SenderViewsJoinSql = ToFString( - Q.From.SenderViewPkPlayersA().RightSemijoin(Q.From.SenderViewPkPlayersB(), [](const FViewPkPlayerIxCols& LeftView, const FViewPkPlayerIxCols& RightView) + Q.From.SenderViewPkPlayersA().RightSemijoin(Q.From.SenderViewPkPlayersB(), [](const FSenderViewPkPlayersAIxCols& LeftView, const FSenderViewPkPlayersBIxCols& RightView) { return LeftView.Id.Eq(RightView.Id); }).into_sql() diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/SpacetimeDBClient.g.h index a8e02fe167a..238733a23f7 100644 --- a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -806,41 +806,86 @@ class TESTVIEWPKCLIENT_API URemoteProcedures : public UObject }; // QueryBuilder types -struct TESTVIEWPKCLIENT_API FViewPkPlayerCols +struct TESTVIEWPKCLIENT_API FAllViewPkPlayersCols; +struct TESTVIEWPKCLIENT_API FAllViewPkPlayersIxCols; +struct TESTVIEWPKCLIENT_API FSenderViewPkPlayersACols; +struct TESTVIEWPKCLIENT_API FSenderViewPkPlayersAIxCols; +struct TESTVIEWPKCLIENT_API FSenderViewPkPlayersBCols; +struct TESTVIEWPKCLIENT_API FSenderViewPkPlayersBIxCols; +struct TESTVIEWPKCLIENT_API FViewPkMembershipCols; +struct TESTVIEWPKCLIENT_API FViewPkMembershipIxCols; +struct TESTVIEWPKCLIENT_API FViewPkMembershipSecondaryCols; +struct TESTVIEWPKCLIENT_API FViewPkMembershipSecondaryIxCols; +struct TESTVIEWPKCLIENT_API FViewPkPlayerCols; +struct TESTVIEWPKCLIENT_API FViewPkPlayerIxCols; + +struct TESTVIEWPKCLIENT_API FAllViewPkPlayersCols { - explicit FViewPkPlayerCols(const char* TableName) + explicit FAllViewPkPlayersCols(const char* TableName) : Id(TableName, "id"), Name(TableName, "name") {} ::SpacetimeDB::query_builder::Col Id; ::SpacetimeDB::query_builder::Col Name; }; -struct TESTVIEWPKCLIENT_API FViewPkPlayerIxCols +struct TESTVIEWPKCLIENT_API FAllViewPkPlayersIxCols { - explicit FViewPkPlayerIxCols(const char* TableName) + explicit FAllViewPkPlayersIxCols(const char* TableName) : Id(TableName, "id") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t Id; + ::SpacetimeDB::query_builder::IxCol Id; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FViewPkPlayerCols get(const char* table_name) { return FViewPkPlayerCols(table_name); } - }; + struct CanBeLookupTable> : std::true_type {}; +} + +struct TESTVIEWPKCLIENT_API FSenderViewPkPlayersACols +{ + explicit FSenderViewPkPlayersACols(const char* TableName) + : Id(TableName, "id"), Name(TableName, "name") {} + + ::SpacetimeDB::query_builder::Col Id; + ::SpacetimeDB::query_builder::Col Name; +}; + +struct TESTVIEWPKCLIENT_API FSenderViewPkPlayersAIxCols +{ + explicit FSenderViewPkPlayersAIxCols(const char* TableName) + : Id(TableName, "id") {} + ::SpacetimeDB::query_builder::IxCol Id; +}; + +namespace SpacetimeDB::query_builder +{ template<> - struct HasIxCols - { - static FViewPkPlayerIxCols get(const char* table_name) { return FViewPkPlayerIxCols(table_name); } - }; + struct CanBeLookupTable> : std::true_type {}; +} + +struct TESTVIEWPKCLIENT_API FSenderViewPkPlayersBCols +{ + explicit FSenderViewPkPlayersBCols(const char* TableName) + : Id(TableName, "id"), Name(TableName, "name") {} + + ::SpacetimeDB::query_builder::Col Id; + ::SpacetimeDB::query_builder::Col Name; +}; + +struct TESTVIEWPKCLIENT_API FSenderViewPkPlayersBIxCols +{ + explicit FSenderViewPkPlayersBIxCols(const char* TableName) + : Id(TableName, "id") {} + ::SpacetimeDB::query_builder::IxCol Id; +}; + +namespace SpacetimeDB::query_builder +{ template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTVIEWPKCLIENT_API FViewPkMembershipCols @@ -857,29 +902,14 @@ struct TESTVIEWPKCLIENT_API FViewPkMembershipIxCols explicit FViewPkMembershipIxCols(const char* TableName) : Id(TableName, "id"), PlayerId(TableName, "player_id") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t Id; - ::SpacetimeDB::query_builder::detail::ix_col_member_t PlayerId; + ::SpacetimeDB::query_builder::IxCol Id; + ::SpacetimeDB::query_builder::IxCol PlayerId; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FViewPkMembershipCols get(const char* table_name) { return FViewPkMembershipCols(table_name); } - }; - - template<> - struct HasIxCols - { - static FViewPkMembershipIxCols get(const char* table_name) { return FViewPkMembershipIxCols(table_name); } - }; - - template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTVIEWPKCLIENT_API FViewPkMembershipSecondaryCols @@ -896,39 +926,47 @@ struct TESTVIEWPKCLIENT_API FViewPkMembershipSecondaryIxCols explicit FViewPkMembershipSecondaryIxCols(const char* TableName) : Id(TableName, "id"), PlayerId(TableName, "player_id") {} - ::SpacetimeDB::query_builder::detail::ix_col_member_t Id; - ::SpacetimeDB::query_builder::detail::ix_col_member_t PlayerId; + ::SpacetimeDB::query_builder::IxCol Id; + ::SpacetimeDB::query_builder::IxCol PlayerId; }; namespace SpacetimeDB::query_builder { - inline std::true_type indexed_member_lookup(member_tag); - inline std::true_type indexed_member_lookup(member_tag); - template<> - struct HasCols - { - static FViewPkMembershipSecondaryCols get(const char* table_name) { return FViewPkMembershipSecondaryCols(table_name); } - }; + struct CanBeLookupTable> : std::true_type {}; +} - template<> - struct HasIxCols - { - static FViewPkMembershipSecondaryIxCols get(const char* table_name) { return FViewPkMembershipSecondaryIxCols(table_name); } - }; +struct TESTVIEWPKCLIENT_API FViewPkPlayerCols +{ + explicit FViewPkPlayerCols(const char* TableName) + : Id(TableName, "id"), Name(TableName, "name") {} + + ::SpacetimeDB::query_builder::Col Id; + ::SpacetimeDB::query_builder::Col Name; +}; + +struct TESTVIEWPKCLIENT_API FViewPkPlayerIxCols +{ + explicit FViewPkPlayerIxCols(const char* TableName) + : Id(TableName, "id") {} + ::SpacetimeDB::query_builder::IxCol Id; +}; + +namespace SpacetimeDB::query_builder +{ template<> - struct CanBeLookupTable : std::true_type {}; + struct CanBeLookupTable> : std::true_type {}; } struct TESTVIEWPKCLIENT_API FFrom { - [[nodiscard]] ::SpacetimeDB::query_builder::Table AllViewPkPlayers() const { return ::SpacetimeDB::query_builder::Table("all_view_pk_players"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table SenderViewPkPlayersA() const { return ::SpacetimeDB::query_builder::Table("sender_view_pk_players_a"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table SenderViewPkPlayersB() const { return ::SpacetimeDB::query_builder::Table("sender_view_pk_players_b"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table ViewPkMembership() const { return ::SpacetimeDB::query_builder::Table("view_pk_membership"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table ViewPkMembershipSecondary() const { return ::SpacetimeDB::query_builder::Table("view_pk_membership_secondary"); } - [[nodiscard]] ::SpacetimeDB::query_builder::Table ViewPkPlayer() const { return ::SpacetimeDB::query_builder::Table("view_pk_player"); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table AllViewPkPlayers() const { return ::SpacetimeDB::query_builder::Table("all_view_pk_players", FAllViewPkPlayersCols("all_view_pk_players"), FAllViewPkPlayersIxCols("all_view_pk_players")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table SenderViewPkPlayersA() const { return ::SpacetimeDB::query_builder::Table("sender_view_pk_players_a", FSenderViewPkPlayersACols("sender_view_pk_players_a"), FSenderViewPkPlayersAIxCols("sender_view_pk_players_a")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table SenderViewPkPlayersB() const { return ::SpacetimeDB::query_builder::Table("sender_view_pk_players_b", FSenderViewPkPlayersBCols("sender_view_pk_players_b"), FSenderViewPkPlayersBIxCols("sender_view_pk_players_b")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ViewPkMembership() const { return ::SpacetimeDB::query_builder::Table("view_pk_membership", FViewPkMembershipCols("view_pk_membership"), FViewPkMembershipIxCols("view_pk_membership")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ViewPkMembershipSecondary() const { return ::SpacetimeDB::query_builder::Table("view_pk_membership_secondary", FViewPkMembershipSecondaryCols("view_pk_membership_secondary"), FViewPkMembershipSecondaryIxCols("view_pk_membership_secondary")); } + [[nodiscard]] ::SpacetimeDB::query_builder::Table ViewPkPlayer() const { return ::SpacetimeDB::query_builder::Table("view_pk_player", FViewPkPlayerCols("view_pk_player"), FViewPkPlayerIxCols("view_pk_player")); } }; struct TESTVIEWPKCLIENT_API FQueryBuilder @@ -1003,7 +1041,7 @@ class TESTVIEWPKCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBas return Typed; } - /** Convenience for subscribing to all rows from all tables */ + /** Convenience for subscribing to all rows from all public sources, including views */ UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") USubscriptionHandle* SubscribeToAllTables(); From 2009a36e27b7127421bbd9b1a71a2c759376c8b1 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Fri, 10 Apr 2026 14:52:35 -0700 Subject: [PATCH 3/4] Adding Unreal Blueprint support for Query Builder --- crates/codegen/src/unrealcpp.rs | 544 +- .../SpacetimeDbSdk/Public/QueryBuilder/expr.h | 21 +- .../ModuleBindings/SpacetimeDBClient.g.cpp | 891 ++- .../Tests/SpacetimeFullClientTests.cpp | 71 +- .../ModuleBindings/SpacetimeDBClient.g.h | 5812 ++++++++++++++++- .../Public/Tests/SpacetimeFullClientTests.h | 1 + .../ModuleBindings/SpacetimeDBClient.g.cpp | 59 +- .../ModuleBindings/SpacetimeDBClient.g.h | 741 ++- .../ModuleBindings/SpacetimeDBClient.g.cpp | 83 +- .../Private/Tests/CommonTestFunctions.cpp | 170 + .../Tests/SpacetimeFullClientTests.cpp | 135 +- .../Private/Tests/TestHandler.cpp | 24 + .../ModuleBindings/SpacetimeDBClient.g.h | 866 ++- .../Public/Tests/CommonTestFunctions.h | 73 + .../Public/Tests/SpacetimeFullClientTests.h | 12 + .../TestViewClient/Public/Tests/TestHandler.h | 35 +- .../ModuleBindings/SpacetimeDBClient.g.cpp | 83 +- .../Tests/SpacetimeFullClientTests.cpp | 41 +- .../ModuleBindings/SpacetimeDBClient.g.h | 839 ++- .../Public/Tests/SpacetimeFullClientTests.h | 6 + sdks/unreal/tests/test.rs | 6 + sdks/unreal/tests/test_view.rs | 12 + sdks/unreal/tests/test_view_pk.rs | 6 + 23 files changed, 10247 insertions(+), 284 deletions(-) diff --git a/crates/codegen/src/unrealcpp.rs b/crates/codegen/src/unrealcpp.rs index c66c7d5fb76..bdb761ca590 100644 --- a/crates/codegen/src/unrealcpp.rs +++ b/crates/codegen/src/unrealcpp.rs @@ -1009,7 +1009,13 @@ impl Lang for UnrealCpp<'_> { ); // SubscriptionBuilder class - generate_subscription_builder_class(&mut client_h, self.module_prefix, &self.get_api_macro()); + generate_subscription_builder_class( + &mut client_h, + module, + options.visibility, + self.module_prefix, + &self.get_api_macro(), + ); // SubscriptionHandle class generate_subscription_handle_class(&mut client_h, self.module_prefix, &self.get_api_macro()); @@ -2975,11 +2981,128 @@ fn generate_query_builder_types( api_macro: &str, module_name: &str, ) { + #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] + enum BlueprintPredicateKind { + Bool, + U8, + I32, + I64, + F32, + F64, + String, + Identity, + ConnectionId, + Timestamp, + Uuid, + } + + fn supports_blueprint_query_filter(module: &ModuleDef, ty: &AlgebraicTypeUse) -> bool { + match ty { + AlgebraicTypeUse::Primitive(_) + | AlgebraicTypeUse::String + | AlgebraicTypeUse::Identity + | AlgebraicTypeUse::ConnectionId + | AlgebraicTypeUse::Timestamp + | AlgebraicTypeUse::Uuid => is_blueprintable(module, ty), + _ => false, + } + } + + fn blueprint_predicate_kind(ty: &AlgebraicTypeUse) -> Option { + match ty { + AlgebraicTypeUse::Primitive(PrimitiveType::Bool) => Some(BlueprintPredicateKind::Bool), + AlgebraicTypeUse::Primitive(PrimitiveType::U8) => Some(BlueprintPredicateKind::U8), + AlgebraicTypeUse::Primitive(PrimitiveType::I32) => Some(BlueprintPredicateKind::I32), + AlgebraicTypeUse::Primitive(PrimitiveType::I64) => Some(BlueprintPredicateKind::I64), + AlgebraicTypeUse::Primitive(PrimitiveType::F32) => Some(BlueprintPredicateKind::F32), + AlgebraicTypeUse::Primitive(PrimitiveType::F64) => Some(BlueprintPredicateKind::F64), + AlgebraicTypeUse::String => Some(BlueprintPredicateKind::String), + AlgebraicTypeUse::Identity => Some(BlueprintPredicateKind::Identity), + AlgebraicTypeUse::ConnectionId => Some(BlueprintPredicateKind::ConnectionId), + AlgebraicTypeUse::Timestamp => Some(BlueprintPredicateKind::Timestamp), + AlgebraicTypeUse::Uuid => Some(BlueprintPredicateKind::Uuid), + _ => None, + } + } + + fn blueprint_predicate_kind_name(kind: BlueprintPredicateKind) -> &'static str { + match kind { + BlueprintPredicateKind::Bool => "Bool", + BlueprintPredicateKind::U8 => "UInt8", + BlueprintPredicateKind::I32 => "Int32", + BlueprintPredicateKind::I64 => "Int64", + BlueprintPredicateKind::F32 => "Float", + BlueprintPredicateKind::F64 => "Double", + BlueprintPredicateKind::String => "String", + BlueprintPredicateKind::Identity => "Identity", + BlueprintPredicateKind::ConnectionId => "ConnectionId", + BlueprintPredicateKind::Timestamp => "Timestamp", + BlueprintPredicateKind::Uuid => "Uuid", + } + } + + fn blueprint_predicate_kinds() -> &'static [BlueprintPredicateKind] { + &[ + BlueprintPredicateKind::Bool, + BlueprintPredicateKind::U8, + BlueprintPredicateKind::I32, + BlueprintPredicateKind::I64, + BlueprintPredicateKind::F32, + BlueprintPredicateKind::F64, + BlueprintPredicateKind::String, + BlueprintPredicateKind::Identity, + BlueprintPredicateKind::ConnectionId, + BlueprintPredicateKind::Timestamp, + BlueprintPredicateKind::Uuid, + ] + } + + fn blueprint_predicate_kind_ty(kind: BlueprintPredicateKind) -> AlgebraicTypeUse { + match kind { + BlueprintPredicateKind::Bool => AlgebraicTypeUse::Primitive(PrimitiveType::Bool), + BlueprintPredicateKind::U8 => AlgebraicTypeUse::Primitive(PrimitiveType::U8), + BlueprintPredicateKind::I32 => AlgebraicTypeUse::Primitive(PrimitiveType::I32), + BlueprintPredicateKind::I64 => AlgebraicTypeUse::Primitive(PrimitiveType::I64), + BlueprintPredicateKind::F32 => AlgebraicTypeUse::Primitive(PrimitiveType::F32), + BlueprintPredicateKind::F64 => AlgebraicTypeUse::Primitive(PrimitiveType::F64), + BlueprintPredicateKind::String => AlgebraicTypeUse::String, + BlueprintPredicateKind::Identity => AlgebraicTypeUse::Identity, + BlueprintPredicateKind::ConnectionId => AlgebraicTypeUse::ConnectionId, + BlueprintPredicateKind::Timestamp => AlgebraicTypeUse::Timestamp, + BlueprintPredicateKind::Uuid => AlgebraicTypeUse::Uuid, + } + } + + fn blueprint_predicate_kind_supports_ordering(kind: BlueprintPredicateKind) -> bool { + !matches!( + kind, + BlueprintPredicateKind::Bool + | BlueprintPredicateKind::String + | BlueprintPredicateKind::Identity + | BlueprintPredicateKind::ConnectionId + | BlueprintPredicateKind::Uuid + ) + } + + fn blueprint_predicate_kind_spec( + module_prefix: &str, + module: &ModuleDef, + module_name: &str, + kind: BlueprintPredicateKind, + ) -> (String, bool, bool) { + let ty = blueprint_predicate_kind_ty(kind); + ( + cpp_ty_fmt_blueprint_compatible(module_prefix, module, &ty, module_name).to_string(), + should_pass_by_value_in_delegate(module, &ty), + blueprint_predicate_kind_supports_ordering(kind), + ) + } + struct QueryBuilderSourceMeta { row_struct: String, cols_struct: String, ix_cols_struct: String, - fields: Vec<(String, String, String)>, + fields: Vec<(String, String, String, AlgebraicTypeUse)>, singleton_indexed_fields: Vec, source_name: String, source_pascal: String, @@ -3026,14 +3149,15 @@ fn generate_query_builder_types( field_name.deref().to_string(), field_name.deref().to_case(Case::Pascal), cpp_ty_fmt_with_module(module_prefix, module, field_ty, module_name).to_string(), + field_ty.clone(), ) }) .collect::>(); source_metas.push(QueryBuilderSourceMeta { row_struct, - cols_struct: format!("F{source_pascal}Cols"), - ix_cols_struct: format!("F{source_pascal}IxCols"), + cols_struct: format!("F{module_prefix}{source_pascal}Cols"), + ix_cols_struct: format!("F{module_prefix}{source_pascal}IxCols"), fields, singleton_indexed_fields, source_name: table.name.deref().to_string(), @@ -3062,14 +3186,15 @@ fn generate_query_builder_types( field_name.deref().to_string(), field_name.deref().to_case(Case::Pascal), cpp_ty_fmt_with_module(module_prefix, module, field_ty, module_name).to_string(), + field_ty.clone(), ) }) .collect::>(); source_metas.push(QueryBuilderSourceMeta { row_struct, - cols_struct: format!("F{source_pascal}Cols"), - ix_cols_struct: format!("F{source_pascal}IxCols"), + cols_struct: format!("F{module_prefix}{source_pascal}Cols"), + ix_cols_struct: format!("F{module_prefix}{source_pascal}IxCols"), fields, singleton_indexed_fields, source_name: view.name.deref().to_string(), @@ -3117,7 +3242,7 @@ fn generate_query_builder_types( writeln!(output, "{{"); writeln!(output, " explicit {cols_struct}(const char* TableName)"); write!(output, " : "); - for (idx, (field_name_raw, field_name_pascal, _field_type)) in source_meta.fields.iter().enumerate() { + for (idx, (field_name_raw, field_name_pascal, _field_type, _field_ty)) in source_meta.fields.iter().enumerate() { if idx > 0 { write!(output, ", "); } @@ -3130,7 +3255,7 @@ fn generate_query_builder_types( } writeln!(output, " {{}}"); writeln!(output); - for (_field_name_raw, field_name_pascal, field_type) in &source_meta.fields { + for (_field_name_raw, field_name_pascal, field_type, _field_ty) in &source_meta.fields { writeln!( output, " ::SpacetimeDB::query_builder::Col<{row_struct}, {field_type}> {field_name_pascal};" @@ -3144,10 +3269,10 @@ fn generate_query_builder_types( writeln!(output, " explicit {ix_cols_struct}(const char* TableName)"); if !singleton_indexed_fields.is_empty() { write!(output, " : "); - for (idx, (field_name_raw, field_name_pascal, _field_type)) in source_meta + for (idx, (field_name_raw, field_name_pascal, _field_type, _field_ty)) in source_meta .fields .iter() - .filter(|(_field_name_raw, field_name_pascal, _)| singleton_indexed_fields.contains(field_name_pascal)) + .filter(|(_field_name_raw, field_name_pascal, _, _)| singleton_indexed_fields.contains(field_name_pascal)) .enumerate() { if idx > 0 { @@ -3163,10 +3288,10 @@ fn generate_query_builder_types( } writeln!(output, " {{}}"); writeln!(output); - for (_field_name_raw, field_name_pascal, field_type) in source_meta + for (_field_name_raw, field_name_pascal, field_type, _field_ty) in source_meta .fields .iter() - .filter(|(_field_name_raw, field_name_pascal, _)| singleton_indexed_fields.contains(field_name_pascal)) + .filter(|(_field_name_raw, field_name_pascal, _, _)| singleton_indexed_fields.contains(field_name_pascal)) { writeln!( output, @@ -3226,64 +3351,290 @@ fn generate_query_builder_types( writeln!(output, "}};"); writeln!(output); - writeln!(output, "struct {api_macro} F{module_prefix}TypedSubscriptionBuilder"); + let blueprint_query_struct = format!("F{module_prefix}BlueprintQuery"); + let blueprint_predicate_struct = format!("F{module_prefix}BlueprintPredicate"); + writeln!(output, "USTRUCT(BlueprintType)"); + writeln!(output, "struct {api_macro} {blueprint_query_struct}"); writeln!(output, "{{"); + writeln!(output, " GENERATED_BODY()"); + writeln!(output); + writeln!(output, " UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=\"SpacetimeDB|Queries\")"); + writeln!(output, " FString Sql;"); + writeln!(output); + writeln!(output, " UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=\"SpacetimeDB|Queries\")"); + writeln!(output, " FString ResultSourceName;"); + writeln!(output, "}};"); + writeln!(output); + + writeln!(output, "USTRUCT(BlueprintType)"); + writeln!(output, "struct {api_macro} {blueprint_predicate_struct}"); + writeln!(output, "{{"); + writeln!(output, " GENERATED_BODY()"); + writeln!(output); + writeln!(output, " UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=\"SpacetimeDB|Queries\")"); + writeln!(output, " FString Sql;"); + writeln!(output); + writeln!(output, " UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=\"SpacetimeDB|Queries\")"); + writeln!(output, " FString ResultSourceName;"); + writeln!(output, "}};"); + writeln!(output); + + for source_meta in &source_metas { + let source_pascal = &source_meta.source_pascal; + let query_struct = format!("F{module_prefix}{source_pascal}Query"); + writeln!(output, "USTRUCT(BlueprintType)"); + writeln!(output, "struct {api_macro} {query_struct}"); + writeln!(output, "{{"); + writeln!(output, " GENERATED_BODY()"); + writeln!(output); + writeln!(output, " UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=\"SpacetimeDB|Queries\")"); + writeln!(output, " FString Sql;"); + writeln!(output); + writeln!(output, " UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=\"SpacetimeDB|Queries\")"); + writeln!(output, " FString ResultSourceName;"); + writeln!(output, "}};"); + writeln!(output); + } + + for kind in blueprint_predicate_kinds() { + let column_struct = + format!("F{module_prefix}Blueprint{}Column", blueprint_predicate_kind_name(*kind)); + writeln!(output, "USTRUCT(BlueprintType)"); + writeln!(output, "struct {api_macro} {column_struct}"); + writeln!(output, "{{"); + writeln!(output, " GENERATED_BODY()"); + writeln!(output); + writeln!(output, " UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=\"SpacetimeDB|Queries\")"); + writeln!(output, " FString ResultSourceName;"); + writeln!(output); + writeln!(output, " UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=\"SpacetimeDB|Queries\")"); + writeln!(output, " FString ColumnName;"); + writeln!(output, "}};"); + writeln!(output); + } + + writeln!(output, "UCLASS(BlueprintType)"); writeln!( output, - " explicit F{module_prefix}TypedSubscriptionBuilder(U{module_prefix}DbConnection* InConn)" + "class {api_macro} U{module_prefix}QueryBuilderBlueprintLibrary : public UBlueprintFunctionLibrary" ); - writeln!(output, " : Conn(InConn) {{}}"); + writeln!(output, "{{"); + writeln!(output, " GENERATED_BODY()"); + writeln!(output); + writeln!(output, "public:"); writeln!(output); + + for source_meta in &source_metas { + let source_pascal = &source_meta.source_pascal; + let source_name = &source_meta.source_name; + let query_struct = format!("F{module_prefix}{source_pascal}Query"); + + writeln!( + output, + " UFUNCTION(BlueprintPure, Category=\"SpacetimeDB|Queries|{source_pascal}\", meta=(DisplayName=\"From {source_pascal}\"))" + ); + writeln!(output, " static {query_struct} From{source_pascal}()"); + writeln!(output, " {{"); + writeln!(output, " {query_struct} Query;"); + writeln!( + output, + " Query.Sql = FString(UTF8_TO_TCHAR(F{module_prefix}QueryBuilder().From.{source_pascal}().into_sql().c_str()));" + ); + writeln!(output, " Query.ResultSourceName = TEXT(\"{source_name}\");"); + writeln!(output, " return Query;"); + writeln!(output, " }}"); + writeln!(output); + + writeln!( + output, + " UFUNCTION(BlueprintPure, Category=\"SpacetimeDB|Queries|{source_pascal}\", meta=(DisplayName=\"To Query\", BlueprintAutocast))" + ); + writeln!( + output, + " static {blueprint_query_struct} Conv_{source_pascal}QueryToBlueprintQuery(const {query_struct}& Query)" + ); + writeln!(output, " {{"); + writeln!(output, " {blueprint_query_struct} GenericQuery;"); + writeln!(output, " GenericQuery.Sql = Query.Sql;"); + writeln!(output, " GenericQuery.ResultSourceName = Query.ResultSourceName;"); + writeln!(output, " return GenericQuery;"); + writeln!(output, " }}"); + writeln!(output); + + for (field_name_raw, field_name_pascal, _field_type, field_ty) in &source_meta.fields { + if !supports_blueprint_query_filter(module, field_ty) { + continue; + } + let Some(kind) = blueprint_predicate_kind(field_ty) else { + continue; + }; + let column_struct = + format!("F{module_prefix}Blueprint{}Column", blueprint_predicate_kind_name(kind)); + writeln!( + output, + " UFUNCTION(BlueprintPure, Category=\"SpacetimeDB|Queries|{source_pascal}|Columns\", meta=(DisplayName=\"{source_pascal} {field_name_pascal}\"))" + ); + writeln!(output, " static {column_struct} {source_pascal}{field_name_pascal}(const {query_struct}& Query)"); + writeln!(output, " {{"); + writeln!(output, " {column_struct} Column;"); + writeln!( + output, + " Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT(\"{source_name}\") : Query.ResultSourceName;" + ); + writeln!(output, " Column.ColumnName = TEXT(\"{field_name_raw}\");"); + writeln!(output, " return Column;"); + writeln!(output, " }}"); + writeln!(output); + } + + writeln!( + output, + " UFUNCTION(BlueprintPure, Category=\"SpacetimeDB|Queries|{source_pascal}\", meta=(DisplayName=\"{source_pascal} Where\"))" + ); + writeln!( + output, + " static {query_struct} {source_pascal}Where({query_struct} Query, const {blueprint_predicate_struct}& Predicate)" + ); + writeln!(output, " {{"); + writeln!(output, " if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty())"); + writeln!(output, " {{"); + writeln!(output, " return Query;"); + writeln!(output, " }}"); + writeln!(output, " Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql);"); + writeln!(output, " return Query;"); + writeln!(output, " }}"); + writeln!(output); + } + + for kind in blueprint_predicate_kinds() { + let (blueprint_type, pass_by_value, supports_ordering) = + blueprint_predicate_kind_spec(module_prefix, module, module_name, *kind); + let kind_suffix = blueprint_predicate_kind_name(*kind); + let kind_display = blueprint_predicate_kind_name(*kind); + let column_struct = format!("F{module_prefix}Blueprint{kind_suffix}Column"); + let value_param = if pass_by_value { + format!("const {blueprint_type} Value") + } else { + format!("const {blueprint_type}& Value") + }; + + writeln!( + output, + " UFUNCTION(BlueprintPure, Category=\"SpacetimeDB|Queries|Predicates\", meta=(DisplayName=\"{kind_display} Equal\", CompactNodeTitle=\"==\", Keywords=\"== equal\"))" + ); + writeln!( + output, + " static {blueprint_predicate_struct} {kind_suffix}Equal(const {column_struct}& Column, {value_param})" + ); + writeln!(output, " {{"); + writeln!(output, " {blueprint_predicate_struct} Predicate;"); + writeln!(output, " Predicate.ResultSourceName = Column.ResultSourceName;"); + writeln!( + output, + " Predicate.Sql = FString::Printf(TEXT(\"\\\"%s\\\".\\\"%s\\\" = %s\"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str()));" + ); + writeln!(output, " return Predicate;"); + writeln!(output, " }}"); + writeln!(output); + + if supports_ordering { + for (fn_suffix, display_name, compact_title, sql_op, keywords) in [ + ("GreaterThan", format!("{kind_display} Greater Than"), ">", ">", "> greater"), + ("GreaterEqual", format!("{kind_display} Greater Equal"), ">=", ">=" , ">= greater equal"), + ("LessThan", format!("{kind_display} Less Than"), "<", "<", "< less"), + ("LessEqual", format!("{kind_display} Less Equal"), "<=", "<=", "<= less equal"), + ] { + writeln!( + output, + " UFUNCTION(BlueprintPure, Category=\"SpacetimeDB|Queries|Predicates\", meta=(DisplayName=\"{display_name}\", CompactNodeTitle=\"{compact_title}\", Keywords=\"{keywords}\"))" + ); + writeln!( + output, + " static {blueprint_predicate_struct} {kind_suffix}{fn_suffix}(const {column_struct}& Column, {value_param})" + ); + writeln!(output, " {{"); + writeln!(output, " {blueprint_predicate_struct} Predicate;"); + writeln!(output, " Predicate.ResultSourceName = Column.ResultSourceName;"); + writeln!( + output, + " Predicate.Sql = FString::Printf(TEXT(\"\\\"%s\\\".\\\"%s\\\" {sql_op} %s\"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str()));" + ); + writeln!(output, " return Predicate;"); + writeln!(output, " }}"); + writeln!(output); + } + } + } + writeln!( output, - " F{module_prefix}TypedSubscriptionBuilder& OnApplied(F{module_prefix}OnSubscriptionApplied Callback);" + " UFUNCTION(BlueprintPure, Category=\"SpacetimeDB|Queries|Predicates\", meta=(DisplayName=\"AND\", CompactNodeTitle=\"AND\", Keywords=\"and &&\"))" ); writeln!( output, - " F{module_prefix}TypedSubscriptionBuilder& OnError(F{module_prefix}OnSubscriptionError Callback);" + " static {blueprint_predicate_struct} And(const {blueprint_predicate_struct}& A, const {blueprint_predicate_struct}& B)" ); + writeln!(output, " {{"); + writeln!(output, " {blueprint_predicate_struct} Predicate;"); + writeln!(output, " Predicate.ResultSourceName = A.ResultSourceName;"); + writeln!(output, " Predicate.Sql = FString::Printf(TEXT(\"(%s) AND (%s)\"), *A.Sql, *B.Sql);"); + writeln!(output, " return Predicate;"); + writeln!(output, " }}"); writeln!(output); - writeln!(output, " template"); + writeln!( output, - " F{module_prefix}TypedSubscriptionBuilder& AddQuery(TFn&& Build)" + " UFUNCTION(BlueprintPure, Category=\"SpacetimeDB|Queries|Predicates\", meta=(DisplayName=\"OR\", CompactNodeTitle=\"OR\", Keywords=\"or ||\"))" ); - writeln!(output, " {{"); - writeln!(output, " F{module_prefix}QueryBuilder Q;"); - writeln!(output, " auto Query = std::forward(Build)(Q);"); writeln!( output, - " static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn," + " static {blueprint_predicate_struct} Or(const {blueprint_predicate_struct}& A, const {blueprint_predicate_struct}& B)" ); + writeln!(output, " {{"); + writeln!(output, " {blueprint_predicate_struct} Predicate;"); + writeln!(output, " Predicate.ResultSourceName = A.ResultSourceName;"); + writeln!(output, " Predicate.Sql = FString::Printf(TEXT(\"(%s) OR (%s)\"), *A.Sql, *B.Sql);"); + writeln!(output, " return Predicate;"); + writeln!(output, " }}"); + writeln!(output); + writeln!( output, - " \"Typed subscription queries must return a query_builder table/query expression.\");" + " UFUNCTION(BlueprintPure, Category=\"SpacetimeDB|Queries|Predicates\", meta=(DisplayName=\"NOT\", CompactNodeTitle=\"NOT\", Keywords=\"not !\"))" ); writeln!( output, - " Sql.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str())));" + " static {blueprint_predicate_struct} Not(const {blueprint_predicate_struct}& A)" ); - writeln!(output, " return *this;"); + writeln!(output, " {{"); + writeln!(output, " {blueprint_predicate_struct} Predicate;"); + writeln!(output, " Predicate.ResultSourceName = A.ResultSourceName;"); + writeln!(output, " Predicate.Sql = FString::Printf(TEXT(\"NOT (%s)\"), *A.Sql);"); + writeln!(output, " return Predicate;"); writeln!(output, " }}"); writeln!(output); - writeln!(output, " U{module_prefix}SubscriptionHandle* Subscribe();"); - writeln!(output); + writeln!(output, "private:"); - writeln!(output, " U{module_prefix}DbConnection* Conn = nullptr;"); - writeln!(output, " TArray Sql;"); - writeln!( - output, - " F{module_prefix}OnSubscriptionApplied OnAppliedDelegateInternal;" - ); - writeln!( - output, - " F{module_prefix}OnSubscriptionError OnErrorDelegateInternal;" - ); + writeln!(output, " static FString AppendPredicate(const FString& Sql, const FString& Predicate)"); + writeln!(output, " {{"); + writeln!(output, " if (Sql.Contains(TEXT(\" WHERE \")))"); + writeln!(output, " {{"); + writeln!(output, " return Sql + TEXT(\" AND (\") + Predicate + TEXT(\")\");"); + writeln!(output, " }}"); + writeln!(output, " return Sql + TEXT(\" WHERE (\") + Predicate + TEXT(\")\");"); + writeln!(output, " }}"); writeln!(output, "}};"); writeln!(output); } -fn generate_subscription_builder_class(output: &mut UnrealCppAutogen, module_prefix: &str, api_macro: &str) { +fn generate_subscription_builder_class( + output: &mut UnrealCppAutogen, + module: &ModuleDef, + visibility: CodegenVisibility, + module_prefix: &str, + api_macro: &str, +) { + let blueprint_query_struct = format!("F{module_prefix}BlueprintQuery"); writeln!(output, "// SubscriptionBuilder class"); writeln!(output, "UCLASS(BlueprintType)"); writeln!( @@ -3308,6 +3659,8 @@ fn generate_subscription_builder_class(output: &mut UnrealCppAutogen, module_pre ); writeln!(output); writeln!(output, " UFUNCTION(BlueprintCallable, Category=\"SpacetimeDB\")"); + writeln!(output, " U{module_prefix}SubscriptionHandle* Subscribe();"); + writeln!(output); writeln!( output, " U{module_prefix}SubscriptionHandle* Subscribe(const TArray& SQL);" @@ -3316,16 +3669,45 @@ fn generate_subscription_builder_class(output: &mut UnrealCppAutogen, module_pre writeln!(output, " template"); writeln!( output, - " [[nodiscard]] F{module_prefix}TypedSubscriptionBuilder AddQuery(TFn&& Build)" + " U{module_prefix}SubscriptionBuilder* AddQuery(TFn&& Build)" ); writeln!(output, " {{"); - writeln!(output, " F{module_prefix}TypedSubscriptionBuilder Typed(Conn);"); - writeln!(output, " Typed.OnApplied(OnAppliedDelegateInternal);"); - writeln!(output, " Typed.OnError(OnErrorDelegateInternal);"); - writeln!(output, " Typed.AddQuery(std::forward(Build));"); - writeln!(output, " return Typed;"); + writeln!(output, " F{module_prefix}QueryBuilder Q;"); + writeln!(output, " auto Query = std::forward(Build)(Q);"); + writeln!( + output, + " static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn," + ); + writeln!( + output, + " \"Typed subscription queries must return a query_builder table/query expression.\");" + ); + writeln!( + output, + " PendingSqlQueries.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str())));" + ); + writeln!(output, " return this;"); writeln!(output, " }}"); writeln!(output); + writeln!(output, " UFUNCTION(BlueprintCallable, Category=\"SpacetimeDB\", meta=(DisplayName=\"AddQuery\", ScriptName=\"AddQuery\"))"); + writeln!( + output, + " U{module_prefix}SubscriptionBuilder* AddBlueprintQuery(const {blueprint_query_struct}& Query);" + ); + writeln!(output); + let mut blueprint_sources = iter_tables(module, visibility) + .map(|t| t.accessor_name.deref().to_case(Case::Pascal)) + .chain(iter_views(module).map(|v| v.accessor_name.deref().to_case(Case::Pascal))) + .collect::>(); + blueprint_sources.sort(); + for source_pascal in blueprint_sources { + let query_struct = format!("F{module_prefix}{source_pascal}Query"); + writeln!( + output, + " U{module_prefix}SubscriptionBuilder* Add{source_pascal}Query(const {query_struct}& Query);" + ); + writeln!(output); + } writeln!( output, " /** Convenience for subscribing to all rows from all public sources, including views */" @@ -3344,6 +3726,9 @@ fn generate_subscription_builder_class(output: &mut UnrealCppAutogen, module_pre writeln!(output, " UPROPERTY()"); writeln!(output, " class U{module_prefix}DbConnection* Conn;"); writeln!(output); + writeln!(output, " UPROPERTY()"); + writeln!(output, " TArray PendingSqlQueries;"); + writeln!(output); writeln!( output, " // Delegates stored so Subscribe() can bind forwarding callbacks" @@ -3633,6 +4018,7 @@ fn generate_client_implementation( module_prefix: &str, module_name: &str, ) { + let blueprint_query_struct = format!("F{module_prefix}BlueprintQuery"); // U{module_prefix}DbConnection constructor writeln!( output, @@ -4016,52 +4402,28 @@ fn generate_client_implementation( writeln!(output, "}}"); writeln!( output, - "F{module_prefix}TypedSubscriptionBuilder& F{module_prefix}TypedSubscriptionBuilder::OnApplied(F{module_prefix}OnSubscriptionApplied Callback)" + "U{module_prefix}SubscriptionBuilder* U{module_prefix}SubscriptionBuilder::OnApplied(F{module_prefix}OnSubscriptionApplied Callback)" ); writeln!(output, "{{"); writeln!(output, "\tOnAppliedDelegateInternal = Callback;"); - writeln!(output, "\treturn *this;"); + writeln!(output, "\treturn this;"); writeln!(output, "}}"); writeln!( output, - "F{module_prefix}TypedSubscriptionBuilder& F{module_prefix}TypedSubscriptionBuilder::OnError(F{module_prefix}OnSubscriptionError Callback)" + "U{module_prefix}SubscriptionBuilder* U{module_prefix}SubscriptionBuilder::OnError(F{module_prefix}OnSubscriptionError Callback)" ); writeln!(output, "{{"); writeln!(output, "\tOnErrorDelegateInternal = Callback;"); - writeln!(output, "\treturn *this;"); - writeln!(output, "}}"); - writeln!( - output, - "U{module_prefix}SubscriptionHandle* F{module_prefix}TypedSubscriptionBuilder::Subscribe()" - ); - writeln!(output, "{{"); - writeln!(output, "\tif (!Conn)"); - writeln!(output, "\t{{"); - writeln!(output, "\t\treturn nullptr;"); - writeln!(output, "\t}}"); - writeln!( - output, - "\tU{module_prefix}SubscriptionBuilder* Builder = Conn->SubscriptionBuilder();" - ); - writeln!(output, "\tBuilder->OnApplied(OnAppliedDelegateInternal);"); - writeln!(output, "\tBuilder->OnError(OnErrorDelegateInternal);"); - writeln!(output, "\treturn Builder->Subscribe(Sql);"); - writeln!(output, "}}"); - writeln!( - output, - "U{module_prefix}SubscriptionBuilder* U{module_prefix}SubscriptionBuilder::OnApplied(F{module_prefix}OnSubscriptionApplied Callback)" - ); - writeln!(output, "{{"); - writeln!(output, "\tOnAppliedDelegateInternal = Callback;"); writeln!(output, "\treturn this;"); writeln!(output, "}}"); writeln!( output, - "U{module_prefix}SubscriptionBuilder* U{module_prefix}SubscriptionBuilder::OnError(F{module_prefix}OnSubscriptionError Callback)" + "U{module_prefix}SubscriptionHandle* U{module_prefix}SubscriptionBuilder::Subscribe()" ); writeln!(output, "{{"); - writeln!(output, "\tOnErrorDelegateInternal = Callback;"); - writeln!(output, "\treturn this;"); + writeln!(output, "\tconst TArray SqlQueries = PendingSqlQueries;"); + writeln!(output, "\tPendingSqlQueries.Empty();"); + writeln!(output, "\treturn Subscribe(SqlQueries);"); writeln!(output, "}}"); writeln!( output, @@ -4105,6 +4467,34 @@ fn generate_client_implementation( writeln!(output, "\treturn Subscribe(F{module_prefix}QueryBuilder::AllTablesSqlQueries());"); writeln!(output, "}}"); writeln!(output); + writeln!( + output, + "U{module_prefix}SubscriptionBuilder* U{module_prefix}SubscriptionBuilder::AddBlueprintQuery(const {blueprint_query_struct}& Query)" + ); + writeln!(output, "{{"); + writeln!(output, "\tPendingSqlQueries.Add(Query.Sql);"); + writeln!(output, "\treturn this;"); + writeln!(output, "}}"); + writeln!(output); + let mut blueprint_sources = iter_tables(module, visibility) + .map(|t| t.accessor_name.deref().to_case(Case::Pascal)) + .chain(iter_views(module).map(|v| v.accessor_name.deref().to_case(Case::Pascal))) + .collect::>(); + blueprint_sources.sort(); + for source_pascal in blueprint_sources { + let query_struct = format!("F{module_prefix}{source_pascal}Query"); + writeln!( + output, + "U{module_prefix}SubscriptionBuilder* U{module_prefix}SubscriptionBuilder::Add{source_pascal}Query(const {query_struct}& Query)" + ); + writeln!(output, "{{"); + writeln!(output, "\t{blueprint_query_struct} GenericQuery;"); + writeln!(output, "\tGenericQuery.Sql = Query.Sql;"); + writeln!(output, "\tGenericQuery.ResultSourceName = Query.ResultSourceName;"); + writeln!(output, "\treturn AddBlueprintQuery(GenericQuery);"); + writeln!(output, "}}"); + writeln!(output); + } writeln!( output, "U{module_prefix}SubscriptionHandle::U{module_prefix}SubscriptionHandle(U{module_prefix}DbConnection* InConn)" @@ -4248,7 +4638,7 @@ fn generate_client_implementation( writeln!(output, "{{"); writeln!(output, "\tif (OnConnectDelegate.IsBound())"); writeln!(output, "\t{{"); - writeln!(output, "\t\tOnConnectDelegate.Execute(this, Identity, Token);"); + writeln!(output, "\t\tOnConnectDelegate.Execute(this, InIdentity, InToken);"); writeln!(output, "\t}}"); writeln!(output, "}}"); writeln!( diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr.h index b20bd641bad..3eae6bc8dd4 100644 --- a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr.h +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -95,11 +96,21 @@ inline std::string literal_sql(bool value) { return value ? "TRUE" : "FALSE"; } inline std::string literal_sql(const ::SpacetimeDb::Identity& value) { return "0x" + value.to_hex_string(); } inline std::string literal_sql(const ::SpacetimeDb::ConnectionId& value) { return "0x" + value.to_string(); } inline std::string literal_sql(const ::SpacetimeDb::Timestamp& value) { return quote_string(trim_timestamp_fraction(value.to_string())); } -inline std::string literal_sql(const FSpacetimeDBIdentity& value) { return std::string(TCHAR_TO_UTF8(*value.ToHex())); } -inline std::string literal_sql(const FSpacetimeDBConnectionId& value) { return std::string(TCHAR_TO_UTF8(*value.ToHex())); } +inline std::string ensure_hex_prefix(std::string value) { + if (value.rfind("0x", 0) == 0 || value.rfind("0X", 0) == 0) { + return value; + } + return "0x" + value; +} +inline std::string literal_sql(const FSpacetimeDBIdentity& value) { return ensure_hex_prefix(std::string(TCHAR_TO_UTF8(*value.ToHex()))); } +inline std::string literal_sql(const FSpacetimeDBConnectionId& value) { return ensure_hex_prefix(std::string(TCHAR_TO_UTF8(*value.ToHex()))); } +inline std::string literal_sql(const FSpacetimeDBUuid& value) { + return quote_string(TCHAR_TO_UTF8(*value.ToString())); +} inline std::string literal_sql(const FSpacetimeDBTimestamp& value) { return quote_string(trim_timestamp_fraction(TCHAR_TO_UTF8(*value.ToString()))); } +std::string literal_sql(const FSpacetimeDBTimeDuration& value) = delete; inline std::string literal_sql(const std::vector& value) { std::ostringstream out; out << "0x" << std::hex << std::setfill('0'); @@ -125,15 +136,17 @@ inline std::string literal_sql(const FSpacetimeDBInt128& value) { return TCHAR_T inline std::string literal_sql(const FSpacetimeDBUInt256& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } inline std::string literal_sql(const FSpacetimeDBInt256& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } -inline std::string format_floating_point(double value) { +template +inline std::string format_floating_point(TFloat value) { std::ostringstream out; out.imbue(std::locale::classic()); + out << std::setprecision(std::numeric_limits::max_digits10); out << value; return out.str(); } inline std::string literal_sql(float value) { - return format_floating_point(static_cast(value)); + return format_floating_point(value); } inline std::string literal_sql(double value) { diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp index b9655b02486..259fc04d14c 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -10911,27 +10911,6 @@ USubscriptionBuilder* UDbConnection::SubscriptionBuilder() Builder->Conn = this; return Builder; } -FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) -{ - OnAppliedDelegateInternal = Callback; - return *this; -} -FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnError(FOnSubscriptionError Callback) -{ - OnErrorDelegateInternal = Callback; - return *this; -} -USubscriptionHandle* FTypedSubscriptionBuilder::Subscribe() -{ - if (!Conn) - { - return nullptr; - } - USubscriptionBuilder* Builder = Conn->SubscriptionBuilder(); - Builder->OnApplied(OnAppliedDelegateInternal); - Builder->OnError(OnErrorDelegateInternal); - return Builder->Subscribe(Sql); -} USubscriptionBuilder* USubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) { OnAppliedDelegateInternal = Callback; @@ -10942,6 +10921,12 @@ USubscriptionBuilder* USubscriptionBuilder::OnError(FOnSubscriptionError Callbac OnErrorDelegateInternal = Callback; return this; } +USubscriptionHandle* USubscriptionBuilder::Subscribe() +{ + const TArray SqlQueries = PendingSqlQueries; + PendingSqlQueries.Empty(); + return Subscribe(SqlQueries); +} USubscriptionHandle* USubscriptionBuilder::Subscribe(const TArray& SQL) { USubscriptionHandle* Handle = NewObject(); @@ -10972,6 +10957,868 @@ USubscriptionHandle* USubscriptionBuilder::SubscribeToAllTables() return Subscribe(FQueryBuilder::AllTablesSqlQueries()); } +USubscriptionBuilder* USubscriptionBuilder::AddBlueprintQuery(const FBlueprintQuery& Query) +{ + PendingSqlQueries.Add(Query.Sql); + return this; +} + +USubscriptionBuilder* USubscriptionBuilder::AddBtreeU32Query(const FBtreeU32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddIndexedSimpleEnumQuery(const FIndexedSimpleEnumQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddLargeTableQuery(const FLargeTableQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneBoolQuery(const FOneBoolQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneByteStructQuery(const FOneByteStructQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneConnectionIdQuery(const FOneConnectionIdQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneEnumWithPayloadQuery(const FOneEnumWithPayloadQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneEveryPrimitiveStructQuery(const FOneEveryPrimitiveStructQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneEveryVecStructQuery(const FOneEveryVecStructQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneF32Query(const FOneF32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneF64Query(const FOneF64Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneI128Query(const FOneI128Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneI16Query(const FOneI16Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneI256Query(const FOneI256Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneI32Query(const FOneI32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneI64Query(const FOneI64Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneI8Query(const FOneI8Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneIdentityQuery(const FOneIdentityQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneSimpleEnumQuery(const FOneSimpleEnumQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneStringQuery(const FOneStringQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneTimestampQuery(const FOneTimestampQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneU128Query(const FOneU128Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneU16Query(const FOneU16Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneU256Query(const FOneU256Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneU32Query(const FOneU32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneU64Query(const FOneU64Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneU8Query(const FOneU8Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneUnitStructQuery(const FOneUnitStructQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOneUuidQuery(const FOneUuidQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOptionEveryPrimitiveStructQuery(const FOptionEveryPrimitiveStructQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOptionI32Query(const FOptionI32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOptionIdentityQuery(const FOptionIdentityQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOptionSimpleEnumQuery(const FOptionSimpleEnumQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOptionStringQuery(const FOptionStringQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOptionUuidQuery(const FOptionUuidQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddOptionVecOptionI32Query(const FOptionVecOptionI32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkBoolQuery(const FPkBoolQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkConnectionIdQuery(const FPkConnectionIdQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkI128Query(const FPkI128Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkI16Query(const FPkI16Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkI256Query(const FPkI256Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkI32Query(const FPkI32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkI64Query(const FPkI64Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkI8Query(const FPkI8Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkIdentityQuery(const FPkIdentityQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkSimpleEnumQuery(const FPkSimpleEnumQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkStringQuery(const FPkStringQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkU128Query(const FPkU128Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkU16Query(const FPkU16Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkU256Query(const FPkU256Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkU32Query(const FPkU32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkU32TwoQuery(const FPkU32TwoQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkU64Query(const FPkU64Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkU8Query(const FPkU8Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkUuidQuery(const FPkUuidQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddResultEveryPrimitiveStructStringQuery(const FResultEveryPrimitiveStructStringQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddResultI32StringQuery(const FResultI32StringQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddResultIdentityStringQuery(const FResultIdentityStringQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddResultSimpleEnumI32Query(const FResultSimpleEnumI32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddResultStringI32Query(const FResultStringI32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddResultVecI32StringQuery(const FResultVecI32StringQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddScheduledTableQuery(const FScheduledTableQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddTableHoldsTableQuery(const FTableHoldsTableQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueBoolQuery(const FUniqueBoolQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueConnectionIdQuery(const FUniqueConnectionIdQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueI128Query(const FUniqueI128Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueI16Query(const FUniqueI16Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueI256Query(const FUniqueI256Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueI32Query(const FUniqueI32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueI64Query(const FUniqueI64Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueI8Query(const FUniqueI8Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueIdentityQuery(const FUniqueIdentityQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueStringQuery(const FUniqueStringQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueU128Query(const FUniqueU128Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueU16Query(const FUniqueU16Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueU256Query(const FUniqueU256Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueU32Query(const FUniqueU32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueU64Query(const FUniqueU64Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueU8Query(const FUniqueU8Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUniqueUuidQuery(const FUniqueUuidQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddUsersQuery(const FUsersQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecBoolQuery(const FVecBoolQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecByteStructQuery(const FVecByteStructQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecConnectionIdQuery(const FVecConnectionIdQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecEnumWithPayloadQuery(const FVecEnumWithPayloadQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecEveryPrimitiveStructQuery(const FVecEveryPrimitiveStructQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecEveryVecStructQuery(const FVecEveryVecStructQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecF32Query(const FVecF32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecF64Query(const FVecF64Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecI128Query(const FVecI128Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecI16Query(const FVecI16Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecI256Query(const FVecI256Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecI32Query(const FVecI32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecI64Query(const FVecI64Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecI8Query(const FVecI8Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecIdentityQuery(const FVecIdentityQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecSimpleEnumQuery(const FVecSimpleEnumQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecStringQuery(const FVecStringQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecTimestampQuery(const FVecTimestampQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecU128Query(const FVecU128Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecU16Query(const FVecU16Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecU256Query(const FVecU256Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecU32Query(const FVecU32Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecU64Query(const FVecU64Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecU8Query(const FVecU8Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecUnitStructQuery(const FVecUnitStructQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddVecUuidQuery(const FVecUuidQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + USubscriptionHandle::USubscriptionHandle(UDbConnection* InConn) { Conn = InConn; @@ -11052,7 +11899,7 @@ void UDbConnection::ForwardOnConnect(UDbConnectionBase* BaseConnection, FSpaceti { if (OnConnectDelegate.IsBound()) { - OnConnectDelegate.Execute(this, Identity, Token); + OnConnectDelegate.Execute(this, InIdentity, InToken); } } void UDbConnection::ForwardOnDisconnect(UDbConnectionBase* BaseConnection, const FString& Error) diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/SpacetimeFullClientTests.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/SpacetimeFullClientTests.cpp index 18a9ae8635d..21651bd0f54 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/SpacetimeFullClientTests.cpp +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/Tests/SpacetimeFullClientTests.cpp @@ -113,28 +113,28 @@ static void CompileTypedQueryBuilderSmoke(UDbConnection* Conn) return Cols.N.Eq(static_cast(1)); }); }) - .AddQuery([](const FQueryBuilder& Q) + ->AddQuery([](const FQueryBuilder& Q) { return Q.From.OneString().Where([](const FOneStringCols& Cols) { return Cols.S.Eq(TEXT("typed-query-builder")); }); }) - .AddQuery([](const FQueryBuilder& Q) + ->AddQuery([](const FQueryBuilder& Q) { return Q.From.OneTimestamp().Where([](const FOneTimestampCols& Cols) { return Cols.T.Gte(FSpacetimeDBTimestamp(1)); }); }) - .AddQuery([](const FQueryBuilder& Q) + ->AddQuery([](const FQueryBuilder& Q) { return Q.From.PkU32().LeftSemijoin(Q.From.UniqueU32(), [](const FPkU32IxCols& Left, const FUniqueU32IxCols& Right) { return Left.N.Eq(Right.N); }); }) - .AddQuery([](const FQueryBuilder& Q) + ->AddQuery([](const FQueryBuilder& Q) { return Q.From.UniqueU32().Where([](const FUniqueU32Cols&, const FUniqueU32IxCols& Ix) { @@ -142,6 +142,69 @@ static void CompileTypedQueryBuilderSmoke(UDbConnection* Conn) }); }); } + +bool FBlueprintQueryBuilderBasicFlowTest::RunTest(const FString& Parameters) +{ + FOneU8Query Query = UQueryBuilderBlueprintLibrary::FromOneU8(); + TestEqual(TEXT("blueprint one_u_8 base sql"), Query.Sql, TEXT("SELECT * FROM \"one_u_8\"")); + + const FBlueprintPredicate Predicate = UQueryBuilderBlueprintLibrary::UInt8Equal( + UQueryBuilderBlueprintLibrary::OneU8N(Query), + static_cast(1)); + Query = UQueryBuilderBlueprintLibrary::OneU8Where(Query, Predicate); + TestEqual( + TEXT("blueprint one_u_8 filtered sql"), + Query.Sql, + TEXT("SELECT * FROM \"one_u_8\" WHERE (\"one_u_8\".\"n\" = 1)") + ); + + USubscriptionBuilder* Builder = NewObject(); + USubscriptionHandle* Handle = Builder->AddOneU8Query(Query)->Subscribe(); + TestNotNull(TEXT("blueprint one_u_8 handle"), Handle); + TestEqual(TEXT("blueprint one_u_8 builder sql count"), Handle->GetQuerySqls().Num(), 1); + TestEqual(TEXT("blueprint one_u_8 builder sql"), Handle->GetQuerySqls()[0], Query.Sql); + + const FString TypedDoubleSql = FString( + UTF8_TO_TCHAR( + FQueryBuilder() + .From.OneF64() + .Where([](const FOneF64Cols& Cols) + { + return Cols.F.Eq(0.123456789); + }) + .into_sql() + .c_str())); + TestEqual( + TEXT("typed one_f_64 precise sql"), + TypedDoubleSql, + TEXT("SELECT * FROM \"one_f_64\" WHERE (\"one_f_64\".\"f\" = 0.123456789)") + ); + + FOneF64Query DoubleQuery = UQueryBuilderBlueprintLibrary::FromOneF64(); + DoubleQuery = UQueryBuilderBlueprintLibrary::OneF64Where( + DoubleQuery, + UQueryBuilderBlueprintLibrary::DoubleEqual( + UQueryBuilderBlueprintLibrary::OneF64F(DoubleQuery), + 0.123456789)); + TestEqual( + TEXT("blueprint one_f_64 precise sql"), + DoubleQuery.Sql, + TEXT("SELECT * FROM \"one_f_64\" WHERE (\"one_f_64\".\"f\" = 0.123456789)") + ); + + FOneStringQuery StringQuery = UQueryBuilderBlueprintLibrary::FromOneString(); + StringQuery = UQueryBuilderBlueprintLibrary::OneStringWhere( + StringQuery, + UQueryBuilderBlueprintLibrary::StringEqual( + UQueryBuilderBlueprintLibrary::OneStringS(StringQuery), + TEXT("reuse-check"))); + USubscriptionHandle* SecondHandle = Builder->AddOneStringQuery(StringQuery)->Subscribe(); + TestNotNull(TEXT("second subscribe handle"), SecondHandle); + TestEqual(TEXT("second subscribe builder sql count"), SecondHandle->GetQuerySqls().Num(), 1); + TestEqual(TEXT("second subscribe builder sql"), SecondHandle->GetQuerySqls()[0], StringQuery.Sql); + + return true; +} // bool FInsertPrimitiveTest::RunTest(const FString &Parameters) diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h index 5685bd44c6a..a24a3ff403f 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -13263,32 +13263,5573 @@ struct TESTCLIENT_API FQueryBuilder } }; -struct TESTCLIENT_API FTypedSubscriptionBuilder +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintPredicate +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBtreeU32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FIndexedSimpleEnumQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FLargeTableQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneBoolQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneByteStructQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneConnectionIdQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneEnumWithPayloadQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneEveryPrimitiveStructQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneEveryVecStructQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneF32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneF64Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneI128Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneI16Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneI256Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneI32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneI64Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneI8Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneIdentityQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneSimpleEnumQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneStringQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneTimestampQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneU128Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneU16Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneU256Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneU32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneU64Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneU8Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneUnitStructQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOneUuidQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOptionEveryPrimitiveStructQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOptionI32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOptionIdentityQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOptionSimpleEnumQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOptionStringQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOptionUuidQuery { - explicit FTypedSubscriptionBuilder(UDbConnection* InConn) - : Conn(InConn) {} + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FOptionVecOptionI32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkBoolQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkConnectionIdQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkI128Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkI16Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkI256Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkI32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkI64Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkI8Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkIdentityQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkSimpleEnumQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkStringQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkU128Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkU16Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkU256Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkU32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkU32TwoQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkU64Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkU8Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FPkUuidQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FResultEveryPrimitiveStructStringQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FResultI32StringQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FResultIdentityStringQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FResultSimpleEnumI32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FResultStringI32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FResultVecI32StringQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FScheduledTableQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FTableHoldsTableQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueBoolQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueConnectionIdQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueI128Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueI16Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueI256Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueI32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueI64Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueI8Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueIdentityQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueStringQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueU128Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueU16Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueU256Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueU32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueU64Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueU8Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUniqueUuidQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FUsersQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecBoolQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecByteStructQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecConnectionIdQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecEnumWithPayloadQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecEveryPrimitiveStructQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecEveryVecStructQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecF32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecF64Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecI128Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecI16Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecI256Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecI32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecI64Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecI8Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecIdentityQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecSimpleEnumQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecStringQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecTimestampQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecU128Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecU16Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecU256Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecU32Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecU64Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecU8Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecUnitStructQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FVecUuidQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintBoolColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintUInt8Column +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintInt32Column +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintInt64Column +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintFloatColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintDoubleColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintStringColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintIdentityColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintConnectionIdColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintTimestampColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTCLIENT_API FBlueprintUuidColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +UCLASS(BlueprintType) +class TESTCLIENT_API UQueryBuilderBlueprintLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|BtreeU32", meta=(DisplayName="From BtreeU32")) + static FBtreeU32Query FromBtreeU32() + { + FBtreeU32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.BtreeU32().into_sql().c_str())); + Query.ResultSourceName = TEXT("btree_u_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|BtreeU32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_BtreeU32QueryToBlueprintQuery(const FBtreeU32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|BtreeU32|Columns", meta=(DisplayName="BtreeU32 Data")) + static FBlueprintInt32Column BtreeU32Data(const FBtreeU32Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("btree_u_32") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|BtreeU32", meta=(DisplayName="BtreeU32 Where")) + static FBtreeU32Query BtreeU32Where(FBtreeU32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|IndexedSimpleEnum", meta=(DisplayName="From IndexedSimpleEnum")) + static FIndexedSimpleEnumQuery FromIndexedSimpleEnum() + { + FIndexedSimpleEnumQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.IndexedSimpleEnum().into_sql().c_str())); + Query.ResultSourceName = TEXT("indexed_simple_enum"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|IndexedSimpleEnum", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_IndexedSimpleEnumQueryToBlueprintQuery(const FIndexedSimpleEnumQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|IndexedSimpleEnum", meta=(DisplayName="IndexedSimpleEnum Where")) + static FIndexedSimpleEnumQuery IndexedSimpleEnumWhere(FIndexedSimpleEnumQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|LargeTable", meta=(DisplayName="From LargeTable")) + static FLargeTableQuery FromLargeTable() + { + FLargeTableQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.LargeTable().into_sql().c_str())); + Query.ResultSourceName = TEXT("large_table"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|LargeTable", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_LargeTableQueryToBlueprintQuery(const FLargeTableQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|LargeTable|Columns", meta=(DisplayName="LargeTable A")) + static FBlueprintUInt8Column LargeTableA(const FLargeTableQuery& Query) + { + FBlueprintUInt8Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("large_table") : Query.ResultSourceName; + Column.ColumnName = TEXT("a"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|LargeTable|Columns", meta=(DisplayName="LargeTable I")) + static FBlueprintInt32Column LargeTableI(const FLargeTableQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("large_table") : Query.ResultSourceName; + Column.ColumnName = TEXT("i"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|LargeTable|Columns", meta=(DisplayName="LargeTable J")) + static FBlueprintInt64Column LargeTableJ(const FLargeTableQuery& Query) + { + FBlueprintInt64Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("large_table") : Query.ResultSourceName; + Column.ColumnName = TEXT("j"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|LargeTable|Columns", meta=(DisplayName="LargeTable M")) + static FBlueprintBoolColumn LargeTableM(const FLargeTableQuery& Query) + { + FBlueprintBoolColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("large_table") : Query.ResultSourceName; + Column.ColumnName = TEXT("m"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|LargeTable|Columns", meta=(DisplayName="LargeTable N")) + static FBlueprintFloatColumn LargeTableN(const FLargeTableQuery& Query) + { + FBlueprintFloatColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("large_table") : Query.ResultSourceName; + Column.ColumnName = TEXT("n"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|LargeTable|Columns", meta=(DisplayName="LargeTable O")) + static FBlueprintDoubleColumn LargeTableO(const FLargeTableQuery& Query) + { + FBlueprintDoubleColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("large_table") : Query.ResultSourceName; + Column.ColumnName = TEXT("o"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|LargeTable|Columns", meta=(DisplayName="LargeTable P")) + static FBlueprintStringColumn LargeTableP(const FLargeTableQuery& Query) + { + FBlueprintStringColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("large_table") : Query.ResultSourceName; + Column.ColumnName = TEXT("p"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|LargeTable", meta=(DisplayName="LargeTable Where")) + static FLargeTableQuery LargeTableWhere(FLargeTableQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneBool", meta=(DisplayName="From OneBool")) + static FOneBoolQuery FromOneBool() + { + FOneBoolQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneBool().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_bool"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneBool", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneBoolQueryToBlueprintQuery(const FOneBoolQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneBool|Columns", meta=(DisplayName="OneBool B")) + static FBlueprintBoolColumn OneBoolB(const FOneBoolQuery& Query) + { + FBlueprintBoolColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("one_bool") : Query.ResultSourceName; + Column.ColumnName = TEXT("b"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneBool", meta=(DisplayName="OneBool Where")) + static FOneBoolQuery OneBoolWhere(FOneBoolQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneByteStruct", meta=(DisplayName="From OneByteStruct")) + static FOneByteStructQuery FromOneByteStruct() + { + FOneByteStructQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneByteStruct().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_byte_struct"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneByteStruct", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneByteStructQueryToBlueprintQuery(const FOneByteStructQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneByteStruct", meta=(DisplayName="OneByteStruct Where")) + static FOneByteStructQuery OneByteStructWhere(FOneByteStructQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneConnectionId", meta=(DisplayName="From OneConnectionId")) + static FOneConnectionIdQuery FromOneConnectionId() + { + FOneConnectionIdQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneConnectionId().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_connection_id"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneConnectionId", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneConnectionIdQueryToBlueprintQuery(const FOneConnectionIdQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneConnectionId|Columns", meta=(DisplayName="OneConnectionId A")) + static FBlueprintConnectionIdColumn OneConnectionIdA(const FOneConnectionIdQuery& Query) + { + FBlueprintConnectionIdColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("one_connection_id") : Query.ResultSourceName; + Column.ColumnName = TEXT("a"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneConnectionId", meta=(DisplayName="OneConnectionId Where")) + static FOneConnectionIdQuery OneConnectionIdWhere(FOneConnectionIdQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneEnumWithPayload", meta=(DisplayName="From OneEnumWithPayload")) + static FOneEnumWithPayloadQuery FromOneEnumWithPayload() + { + FOneEnumWithPayloadQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneEnumWithPayload().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_enum_with_payload"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneEnumWithPayload", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneEnumWithPayloadQueryToBlueprintQuery(const FOneEnumWithPayloadQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneEnumWithPayload", meta=(DisplayName="OneEnumWithPayload Where")) + static FOneEnumWithPayloadQuery OneEnumWithPayloadWhere(FOneEnumWithPayloadQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneEveryPrimitiveStruct", meta=(DisplayName="From OneEveryPrimitiveStruct")) + static FOneEveryPrimitiveStructQuery FromOneEveryPrimitiveStruct() + { + FOneEveryPrimitiveStructQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneEveryPrimitiveStruct().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_every_primitive_struct"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneEveryPrimitiveStruct", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneEveryPrimitiveStructQueryToBlueprintQuery(const FOneEveryPrimitiveStructQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneEveryPrimitiveStruct", meta=(DisplayName="OneEveryPrimitiveStruct Where")) + static FOneEveryPrimitiveStructQuery OneEveryPrimitiveStructWhere(FOneEveryPrimitiveStructQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneEveryVecStruct", meta=(DisplayName="From OneEveryVecStruct")) + static FOneEveryVecStructQuery FromOneEveryVecStruct() + { + FOneEveryVecStructQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneEveryVecStruct().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_every_vec_struct"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneEveryVecStruct", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneEveryVecStructQueryToBlueprintQuery(const FOneEveryVecStructQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneEveryVecStruct", meta=(DisplayName="OneEveryVecStruct Where")) + static FOneEveryVecStructQuery OneEveryVecStructWhere(FOneEveryVecStructQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneF32", meta=(DisplayName="From OneF32")) + static FOneF32Query FromOneF32() + { + FOneF32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneF32().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_f_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneF32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneF32QueryToBlueprintQuery(const FOneF32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneF32|Columns", meta=(DisplayName="OneF32 F")) + static FBlueprintFloatColumn OneF32F(const FOneF32Query& Query) + { + FBlueprintFloatColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("one_f_32") : Query.ResultSourceName; + Column.ColumnName = TEXT("f"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneF32", meta=(DisplayName="OneF32 Where")) + static FOneF32Query OneF32Where(FOneF32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneF64", meta=(DisplayName="From OneF64")) + static FOneF64Query FromOneF64() + { + FOneF64Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneF64().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_f_64"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneF64", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneF64QueryToBlueprintQuery(const FOneF64Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneF64|Columns", meta=(DisplayName="OneF64 F")) + static FBlueprintDoubleColumn OneF64F(const FOneF64Query& Query) + { + FBlueprintDoubleColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("one_f_64") : Query.ResultSourceName; + Column.ColumnName = TEXT("f"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneF64", meta=(DisplayName="OneF64 Where")) + static FOneF64Query OneF64Where(FOneF64Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI128", meta=(DisplayName="From OneI128")) + static FOneI128Query FromOneI128() + { + FOneI128Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneI128().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_i_128"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI128", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneI128QueryToBlueprintQuery(const FOneI128Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI128", meta=(DisplayName="OneI128 Where")) + static FOneI128Query OneI128Where(FOneI128Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI16", meta=(DisplayName="From OneI16")) + static FOneI16Query FromOneI16() + { + FOneI16Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneI16().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_i_16"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI16", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneI16QueryToBlueprintQuery(const FOneI16Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI16", meta=(DisplayName="OneI16 Where")) + static FOneI16Query OneI16Where(FOneI16Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI256", meta=(DisplayName="From OneI256")) + static FOneI256Query FromOneI256() + { + FOneI256Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneI256().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_i_256"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI256", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneI256QueryToBlueprintQuery(const FOneI256Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI256", meta=(DisplayName="OneI256 Where")) + static FOneI256Query OneI256Where(FOneI256Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI32", meta=(DisplayName="From OneI32")) + static FOneI32Query FromOneI32() + { + FOneI32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneI32().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_i_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneI32QueryToBlueprintQuery(const FOneI32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI32|Columns", meta=(DisplayName="OneI32 N")) + static FBlueprintInt32Column OneI32N(const FOneI32Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("one_i_32") : Query.ResultSourceName; + Column.ColumnName = TEXT("n"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI32", meta=(DisplayName="OneI32 Where")) + static FOneI32Query OneI32Where(FOneI32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI64", meta=(DisplayName="From OneI64")) + static FOneI64Query FromOneI64() + { + FOneI64Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneI64().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_i_64"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI64", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneI64QueryToBlueprintQuery(const FOneI64Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI64|Columns", meta=(DisplayName="OneI64 N")) + static FBlueprintInt64Column OneI64N(const FOneI64Query& Query) + { + FBlueprintInt64Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("one_i_64") : Query.ResultSourceName; + Column.ColumnName = TEXT("n"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI64", meta=(DisplayName="OneI64 Where")) + static FOneI64Query OneI64Where(FOneI64Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI8", meta=(DisplayName="From OneI8")) + static FOneI8Query FromOneI8() + { + FOneI8Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneI8().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_i_8"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI8", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneI8QueryToBlueprintQuery(const FOneI8Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneI8", meta=(DisplayName="OneI8 Where")) + static FOneI8Query OneI8Where(FOneI8Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneIdentity", meta=(DisplayName="From OneIdentity")) + static FOneIdentityQuery FromOneIdentity() + { + FOneIdentityQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneIdentity().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_identity"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneIdentity", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneIdentityQueryToBlueprintQuery(const FOneIdentityQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneIdentity|Columns", meta=(DisplayName="OneIdentity I")) + static FBlueprintIdentityColumn OneIdentityI(const FOneIdentityQuery& Query) + { + FBlueprintIdentityColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("one_identity") : Query.ResultSourceName; + Column.ColumnName = TEXT("i"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneIdentity", meta=(DisplayName="OneIdentity Where")) + static FOneIdentityQuery OneIdentityWhere(FOneIdentityQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneSimpleEnum", meta=(DisplayName="From OneSimpleEnum")) + static FOneSimpleEnumQuery FromOneSimpleEnum() + { + FOneSimpleEnumQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneSimpleEnum().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_simple_enum"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneSimpleEnum", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneSimpleEnumQueryToBlueprintQuery(const FOneSimpleEnumQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneSimpleEnum", meta=(DisplayName="OneSimpleEnum Where")) + static FOneSimpleEnumQuery OneSimpleEnumWhere(FOneSimpleEnumQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneString", meta=(DisplayName="From OneString")) + static FOneStringQuery FromOneString() + { + FOneStringQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneString().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_string"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneString", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneStringQueryToBlueprintQuery(const FOneStringQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneString|Columns", meta=(DisplayName="OneString S")) + static FBlueprintStringColumn OneStringS(const FOneStringQuery& Query) + { + FBlueprintStringColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("one_string") : Query.ResultSourceName; + Column.ColumnName = TEXT("s"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneString", meta=(DisplayName="OneString Where")) + static FOneStringQuery OneStringWhere(FOneStringQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneTimestamp", meta=(DisplayName="From OneTimestamp")) + static FOneTimestampQuery FromOneTimestamp() + { + FOneTimestampQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneTimestamp().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_timestamp"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneTimestamp", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneTimestampQueryToBlueprintQuery(const FOneTimestampQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneTimestamp|Columns", meta=(DisplayName="OneTimestamp T")) + static FBlueprintTimestampColumn OneTimestampT(const FOneTimestampQuery& Query) + { + FBlueprintTimestampColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("one_timestamp") : Query.ResultSourceName; + Column.ColumnName = TEXT("t"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneTimestamp", meta=(DisplayName="OneTimestamp Where")) + static FOneTimestampQuery OneTimestampWhere(FOneTimestampQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU128", meta=(DisplayName="From OneU128")) + static FOneU128Query FromOneU128() + { + FOneU128Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneU128().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_u_128"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU128", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneU128QueryToBlueprintQuery(const FOneU128Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU128", meta=(DisplayName="OneU128 Where")) + static FOneU128Query OneU128Where(FOneU128Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU16", meta=(DisplayName="From OneU16")) + static FOneU16Query FromOneU16() + { + FOneU16Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneU16().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_u_16"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU16", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneU16QueryToBlueprintQuery(const FOneU16Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU16", meta=(DisplayName="OneU16 Where")) + static FOneU16Query OneU16Where(FOneU16Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU256", meta=(DisplayName="From OneU256")) + static FOneU256Query FromOneU256() + { + FOneU256Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneU256().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_u_256"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU256", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneU256QueryToBlueprintQuery(const FOneU256Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU256", meta=(DisplayName="OneU256 Where")) + static FOneU256Query OneU256Where(FOneU256Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU32", meta=(DisplayName="From OneU32")) + static FOneU32Query FromOneU32() + { + FOneU32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneU32().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_u_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneU32QueryToBlueprintQuery(const FOneU32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU32", meta=(DisplayName="OneU32 Where")) + static FOneU32Query OneU32Where(FOneU32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU64", meta=(DisplayName="From OneU64")) + static FOneU64Query FromOneU64() + { + FOneU64Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneU64().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_u_64"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU64", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneU64QueryToBlueprintQuery(const FOneU64Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU64", meta=(DisplayName="OneU64 Where")) + static FOneU64Query OneU64Where(FOneU64Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU8", meta=(DisplayName="From OneU8")) + static FOneU8Query FromOneU8() + { + FOneU8Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneU8().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_u_8"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU8", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneU8QueryToBlueprintQuery(const FOneU8Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU8|Columns", meta=(DisplayName="OneU8 N")) + static FBlueprintUInt8Column OneU8N(const FOneU8Query& Query) + { + FBlueprintUInt8Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("one_u_8") : Query.ResultSourceName; + Column.ColumnName = TEXT("n"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneU8", meta=(DisplayName="OneU8 Where")) + static FOneU8Query OneU8Where(FOneU8Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneUnitStruct", meta=(DisplayName="From OneUnitStruct")) + static FOneUnitStructQuery FromOneUnitStruct() + { + FOneUnitStructQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneUnitStruct().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_unit_struct"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneUnitStruct", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneUnitStructQueryToBlueprintQuery(const FOneUnitStructQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneUnitStruct", meta=(DisplayName="OneUnitStruct Where")) + static FOneUnitStructQuery OneUnitStructWhere(FOneUnitStructQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneUuid", meta=(DisplayName="From OneUuid")) + static FOneUuidQuery FromOneUuid() + { + FOneUuidQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OneUuid().into_sql().c_str())); + Query.ResultSourceName = TEXT("one_uuid"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneUuid", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OneUuidQueryToBlueprintQuery(const FOneUuidQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneUuid|Columns", meta=(DisplayName="OneUuid U")) + static FBlueprintUuidColumn OneUuidU(const FOneUuidQuery& Query) + { + FBlueprintUuidColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("one_uuid") : Query.ResultSourceName; + Column.ColumnName = TEXT("u"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OneUuid", meta=(DisplayName="OneUuid Where")) + static FOneUuidQuery OneUuidWhere(FOneUuidQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionEveryPrimitiveStruct", meta=(DisplayName="From OptionEveryPrimitiveStruct")) + static FOptionEveryPrimitiveStructQuery FromOptionEveryPrimitiveStruct() + { + FOptionEveryPrimitiveStructQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionEveryPrimitiveStruct().into_sql().c_str())); + Query.ResultSourceName = TEXT("option_every_primitive_struct"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionEveryPrimitiveStruct", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OptionEveryPrimitiveStructQueryToBlueprintQuery(const FOptionEveryPrimitiveStructQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionEveryPrimitiveStruct", meta=(DisplayName="OptionEveryPrimitiveStruct Where")) + static FOptionEveryPrimitiveStructQuery OptionEveryPrimitiveStructWhere(FOptionEveryPrimitiveStructQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionI32", meta=(DisplayName="From OptionI32")) + static FOptionI32Query FromOptionI32() + { + FOptionI32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionI32().into_sql().c_str())); + Query.ResultSourceName = TEXT("option_i_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionI32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OptionI32QueryToBlueprintQuery(const FOptionI32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionI32", meta=(DisplayName="OptionI32 Where")) + static FOptionI32Query OptionI32Where(FOptionI32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionIdentity", meta=(DisplayName="From OptionIdentity")) + static FOptionIdentityQuery FromOptionIdentity() + { + FOptionIdentityQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionIdentity().into_sql().c_str())); + Query.ResultSourceName = TEXT("option_identity"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionIdentity", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OptionIdentityQueryToBlueprintQuery(const FOptionIdentityQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionIdentity", meta=(DisplayName="OptionIdentity Where")) + static FOptionIdentityQuery OptionIdentityWhere(FOptionIdentityQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionSimpleEnum", meta=(DisplayName="From OptionSimpleEnum")) + static FOptionSimpleEnumQuery FromOptionSimpleEnum() + { + FOptionSimpleEnumQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionSimpleEnum().into_sql().c_str())); + Query.ResultSourceName = TEXT("option_simple_enum"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionSimpleEnum", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OptionSimpleEnumQueryToBlueprintQuery(const FOptionSimpleEnumQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionSimpleEnum", meta=(DisplayName="OptionSimpleEnum Where")) + static FOptionSimpleEnumQuery OptionSimpleEnumWhere(FOptionSimpleEnumQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionString", meta=(DisplayName="From OptionString")) + static FOptionStringQuery FromOptionString() + { + FOptionStringQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionString().into_sql().c_str())); + Query.ResultSourceName = TEXT("option_string"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionString", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OptionStringQueryToBlueprintQuery(const FOptionStringQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionString", meta=(DisplayName="OptionString Where")) + static FOptionStringQuery OptionStringWhere(FOptionStringQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionUuid", meta=(DisplayName="From OptionUuid")) + static FOptionUuidQuery FromOptionUuid() + { + FOptionUuidQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionUuid().into_sql().c_str())); + Query.ResultSourceName = TEXT("option_uuid"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionUuid", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OptionUuidQueryToBlueprintQuery(const FOptionUuidQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionUuid", meta=(DisplayName="OptionUuid Where")) + static FOptionUuidQuery OptionUuidWhere(FOptionUuidQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionVecOptionI32", meta=(DisplayName="From OptionVecOptionI32")) + static FOptionVecOptionI32Query FromOptionVecOptionI32() + { + FOptionVecOptionI32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.OptionVecOptionI32().into_sql().c_str())); + Query.ResultSourceName = TEXT("option_vec_option_i_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionVecOptionI32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_OptionVecOptionI32QueryToBlueprintQuery(const FOptionVecOptionI32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|OptionVecOptionI32", meta=(DisplayName="OptionVecOptionI32 Where")) + static FOptionVecOptionI32Query OptionVecOptionI32Where(FOptionVecOptionI32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkBool", meta=(DisplayName="From PkBool")) + static FPkBoolQuery FromPkBool() + { + FPkBoolQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkBool().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_bool"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkBool", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkBoolQueryToBlueprintQuery(const FPkBoolQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkBool|Columns", meta=(DisplayName="PkBool B")) + static FBlueprintBoolColumn PkBoolB(const FPkBoolQuery& Query) + { + FBlueprintBoolColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_bool") : Query.ResultSourceName; + Column.ColumnName = TEXT("b"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkBool|Columns", meta=(DisplayName="PkBool Data")) + static FBlueprintInt32Column PkBoolData(const FPkBoolQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_bool") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkBool", meta=(DisplayName="PkBool Where")) + static FPkBoolQuery PkBoolWhere(FPkBoolQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkConnectionId", meta=(DisplayName="From PkConnectionId")) + static FPkConnectionIdQuery FromPkConnectionId() + { + FPkConnectionIdQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkConnectionId().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_connection_id"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkConnectionId", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkConnectionIdQueryToBlueprintQuery(const FPkConnectionIdQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkConnectionId|Columns", meta=(DisplayName="PkConnectionId A")) + static FBlueprintConnectionIdColumn PkConnectionIdA(const FPkConnectionIdQuery& Query) + { + FBlueprintConnectionIdColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_connection_id") : Query.ResultSourceName; + Column.ColumnName = TEXT("a"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkConnectionId|Columns", meta=(DisplayName="PkConnectionId Data")) + static FBlueprintInt32Column PkConnectionIdData(const FPkConnectionIdQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_connection_id") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkConnectionId", meta=(DisplayName="PkConnectionId Where")) + static FPkConnectionIdQuery PkConnectionIdWhere(FPkConnectionIdQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI128", meta=(DisplayName="From PkI128")) + static FPkI128Query FromPkI128() + { + FPkI128Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkI128().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_i_128"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI128", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkI128QueryToBlueprintQuery(const FPkI128Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI128|Columns", meta=(DisplayName="PkI128 Data")) + static FBlueprintInt32Column PkI128Data(const FPkI128Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_i_128") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI128", meta=(DisplayName="PkI128 Where")) + static FPkI128Query PkI128Where(FPkI128Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI16", meta=(DisplayName="From PkI16")) + static FPkI16Query FromPkI16() + { + FPkI16Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkI16().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_i_16"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI16", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkI16QueryToBlueprintQuery(const FPkI16Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI16|Columns", meta=(DisplayName="PkI16 Data")) + static FBlueprintInt32Column PkI16Data(const FPkI16Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_i_16") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI16", meta=(DisplayName="PkI16 Where")) + static FPkI16Query PkI16Where(FPkI16Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI256", meta=(DisplayName="From PkI256")) + static FPkI256Query FromPkI256() + { + FPkI256Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkI256().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_i_256"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI256", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkI256QueryToBlueprintQuery(const FPkI256Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI256|Columns", meta=(DisplayName="PkI256 Data")) + static FBlueprintInt32Column PkI256Data(const FPkI256Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_i_256") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI256", meta=(DisplayName="PkI256 Where")) + static FPkI256Query PkI256Where(FPkI256Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI32", meta=(DisplayName="From PkI32")) + static FPkI32Query FromPkI32() + { + FPkI32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkI32().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_i_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkI32QueryToBlueprintQuery(const FPkI32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI32|Columns", meta=(DisplayName="PkI32 N")) + static FBlueprintInt32Column PkI32N(const FPkI32Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_i_32") : Query.ResultSourceName; + Column.ColumnName = TEXT("n"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI32|Columns", meta=(DisplayName="PkI32 Data")) + static FBlueprintInt32Column PkI32Data(const FPkI32Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_i_32") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI32", meta=(DisplayName="PkI32 Where")) + static FPkI32Query PkI32Where(FPkI32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI64", meta=(DisplayName="From PkI64")) + static FPkI64Query FromPkI64() + { + FPkI64Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkI64().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_i_64"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI64", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkI64QueryToBlueprintQuery(const FPkI64Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI64|Columns", meta=(DisplayName="PkI64 N")) + static FBlueprintInt64Column PkI64N(const FPkI64Query& Query) + { + FBlueprintInt64Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_i_64") : Query.ResultSourceName; + Column.ColumnName = TEXT("n"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI64|Columns", meta=(DisplayName="PkI64 Data")) + static FBlueprintInt32Column PkI64Data(const FPkI64Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_i_64") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI64", meta=(DisplayName="PkI64 Where")) + static FPkI64Query PkI64Where(FPkI64Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI8", meta=(DisplayName="From PkI8")) + static FPkI8Query FromPkI8() + { + FPkI8Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkI8().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_i_8"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI8", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkI8QueryToBlueprintQuery(const FPkI8Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI8|Columns", meta=(DisplayName="PkI8 Data")) + static FBlueprintInt32Column PkI8Data(const FPkI8Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_i_8") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkI8", meta=(DisplayName="PkI8 Where")) + static FPkI8Query PkI8Where(FPkI8Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkIdentity", meta=(DisplayName="From PkIdentity")) + static FPkIdentityQuery FromPkIdentity() + { + FPkIdentityQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkIdentity().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_identity"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkIdentity", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkIdentityQueryToBlueprintQuery(const FPkIdentityQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkIdentity|Columns", meta=(DisplayName="PkIdentity I")) + static FBlueprintIdentityColumn PkIdentityI(const FPkIdentityQuery& Query) + { + FBlueprintIdentityColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_identity") : Query.ResultSourceName; + Column.ColumnName = TEXT("i"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkIdentity|Columns", meta=(DisplayName="PkIdentity Data")) + static FBlueprintInt32Column PkIdentityData(const FPkIdentityQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_identity") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkIdentity", meta=(DisplayName="PkIdentity Where")) + static FPkIdentityQuery PkIdentityWhere(FPkIdentityQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkSimpleEnum", meta=(DisplayName="From PkSimpleEnum")) + static FPkSimpleEnumQuery FromPkSimpleEnum() + { + FPkSimpleEnumQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkSimpleEnum().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_simple_enum"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkSimpleEnum", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkSimpleEnumQueryToBlueprintQuery(const FPkSimpleEnumQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkSimpleEnum|Columns", meta=(DisplayName="PkSimpleEnum Data")) + static FBlueprintInt32Column PkSimpleEnumData(const FPkSimpleEnumQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_simple_enum") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkSimpleEnum", meta=(DisplayName="PkSimpleEnum Where")) + static FPkSimpleEnumQuery PkSimpleEnumWhere(FPkSimpleEnumQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkString", meta=(DisplayName="From PkString")) + static FPkStringQuery FromPkString() + { + FPkStringQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkString().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_string"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkString", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkStringQueryToBlueprintQuery(const FPkStringQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkString|Columns", meta=(DisplayName="PkString S")) + static FBlueprintStringColumn PkStringS(const FPkStringQuery& Query) + { + FBlueprintStringColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_string") : Query.ResultSourceName; + Column.ColumnName = TEXT("s"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkString|Columns", meta=(DisplayName="PkString Data")) + static FBlueprintInt32Column PkStringData(const FPkStringQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_string") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkString", meta=(DisplayName="PkString Where")) + static FPkStringQuery PkStringWhere(FPkStringQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU128", meta=(DisplayName="From PkU128")) + static FPkU128Query FromPkU128() + { + FPkU128Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU128().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_u_128"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU128", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkU128QueryToBlueprintQuery(const FPkU128Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU128|Columns", meta=(DisplayName="PkU128 Data")) + static FBlueprintInt32Column PkU128Data(const FPkU128Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_u_128") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU128", meta=(DisplayName="PkU128 Where")) + static FPkU128Query PkU128Where(FPkU128Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU16", meta=(DisplayName="From PkU16")) + static FPkU16Query FromPkU16() + { + FPkU16Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU16().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_u_16"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU16", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkU16QueryToBlueprintQuery(const FPkU16Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU16|Columns", meta=(DisplayName="PkU16 Data")) + static FBlueprintInt32Column PkU16Data(const FPkU16Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_u_16") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU16", meta=(DisplayName="PkU16 Where")) + static FPkU16Query PkU16Where(FPkU16Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU256", meta=(DisplayName="From PkU256")) + static FPkU256Query FromPkU256() + { + FPkU256Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU256().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_u_256"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU256", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkU256QueryToBlueprintQuery(const FPkU256Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU256|Columns", meta=(DisplayName="PkU256 Data")) + static FBlueprintInt32Column PkU256Data(const FPkU256Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_u_256") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU256", meta=(DisplayName="PkU256 Where")) + static FPkU256Query PkU256Where(FPkU256Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU32", meta=(DisplayName="From PkU32")) + static FPkU32Query FromPkU32() + { + FPkU32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU32().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_u_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkU32QueryToBlueprintQuery(const FPkU32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU32|Columns", meta=(DisplayName="PkU32 Data")) + static FBlueprintInt32Column PkU32Data(const FPkU32Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_u_32") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU32", meta=(DisplayName="PkU32 Where")) + static FPkU32Query PkU32Where(FPkU32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU32Two", meta=(DisplayName="From PkU32Two")) + static FPkU32TwoQuery FromPkU32Two() + { + FPkU32TwoQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU32Two().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_u_32_two"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU32Two", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkU32TwoQueryToBlueprintQuery(const FPkU32TwoQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU32Two|Columns", meta=(DisplayName="PkU32Two Data")) + static FBlueprintInt32Column PkU32TwoData(const FPkU32TwoQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_u_32_two") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU32Two", meta=(DisplayName="PkU32Two Where")) + static FPkU32TwoQuery PkU32TwoWhere(FPkU32TwoQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU64", meta=(DisplayName="From PkU64")) + static FPkU64Query FromPkU64() + { + FPkU64Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU64().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_u_64"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU64", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkU64QueryToBlueprintQuery(const FPkU64Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU64|Columns", meta=(DisplayName="PkU64 Data")) + static FBlueprintInt32Column PkU64Data(const FPkU64Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_u_64") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU64", meta=(DisplayName="PkU64 Where")) + static FPkU64Query PkU64Where(FPkU64Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU8", meta=(DisplayName="From PkU8")) + static FPkU8Query FromPkU8() + { + FPkU8Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkU8().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_u_8"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU8", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkU8QueryToBlueprintQuery(const FPkU8Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU8|Columns", meta=(DisplayName="PkU8 N")) + static FBlueprintUInt8Column PkU8N(const FPkU8Query& Query) + { + FBlueprintUInt8Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_u_8") : Query.ResultSourceName; + Column.ColumnName = TEXT("n"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU8|Columns", meta=(DisplayName="PkU8 Data")) + static FBlueprintInt32Column PkU8Data(const FPkU8Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_u_8") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkU8", meta=(DisplayName="PkU8 Where")) + static FPkU8Query PkU8Where(FPkU8Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkUuid", meta=(DisplayName="From PkUuid")) + static FPkUuidQuery FromPkUuid() + { + FPkUuidQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkUuid().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_uuid"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkUuid", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkUuidQueryToBlueprintQuery(const FPkUuidQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkUuid|Columns", meta=(DisplayName="PkUuid U")) + static FBlueprintUuidColumn PkUuidU(const FPkUuidQuery& Query) + { + FBlueprintUuidColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_uuid") : Query.ResultSourceName; + Column.ColumnName = TEXT("u"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkUuid|Columns", meta=(DisplayName="PkUuid Data")) + static FBlueprintInt32Column PkUuidData(const FPkUuidQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_uuid") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkUuid", meta=(DisplayName="PkUuid Where")) + static FPkUuidQuery PkUuidWhere(FPkUuidQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultEveryPrimitiveStructString", meta=(DisplayName="From ResultEveryPrimitiveStructString")) + static FResultEveryPrimitiveStructStringQuery FromResultEveryPrimitiveStructString() + { + FResultEveryPrimitiveStructStringQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.ResultEveryPrimitiveStructString().into_sql().c_str())); + Query.ResultSourceName = TEXT("result_every_primitive_struct_string"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultEveryPrimitiveStructString", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_ResultEveryPrimitiveStructStringQueryToBlueprintQuery(const FResultEveryPrimitiveStructStringQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultEveryPrimitiveStructString", meta=(DisplayName="ResultEveryPrimitiveStructString Where")) + static FResultEveryPrimitiveStructStringQuery ResultEveryPrimitiveStructStringWhere(FResultEveryPrimitiveStructStringQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultI32String", meta=(DisplayName="From ResultI32String")) + static FResultI32StringQuery FromResultI32String() + { + FResultI32StringQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.ResultI32String().into_sql().c_str())); + Query.ResultSourceName = TEXT("result_i_32_string"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultI32String", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_ResultI32StringQueryToBlueprintQuery(const FResultI32StringQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultI32String", meta=(DisplayName="ResultI32String Where")) + static FResultI32StringQuery ResultI32StringWhere(FResultI32StringQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultIdentityString", meta=(DisplayName="From ResultIdentityString")) + static FResultIdentityStringQuery FromResultIdentityString() + { + FResultIdentityStringQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.ResultIdentityString().into_sql().c_str())); + Query.ResultSourceName = TEXT("result_identity_string"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultIdentityString", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_ResultIdentityStringQueryToBlueprintQuery(const FResultIdentityStringQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultIdentityString", meta=(DisplayName="ResultIdentityString Where")) + static FResultIdentityStringQuery ResultIdentityStringWhere(FResultIdentityStringQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultSimpleEnumI32", meta=(DisplayName="From ResultSimpleEnumI32")) + static FResultSimpleEnumI32Query FromResultSimpleEnumI32() + { + FResultSimpleEnumI32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.ResultSimpleEnumI32().into_sql().c_str())); + Query.ResultSourceName = TEXT("result_simple_enum_i_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultSimpleEnumI32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_ResultSimpleEnumI32QueryToBlueprintQuery(const FResultSimpleEnumI32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultSimpleEnumI32", meta=(DisplayName="ResultSimpleEnumI32 Where")) + static FResultSimpleEnumI32Query ResultSimpleEnumI32Where(FResultSimpleEnumI32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultStringI32", meta=(DisplayName="From ResultStringI32")) + static FResultStringI32Query FromResultStringI32() + { + FResultStringI32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.ResultStringI32().into_sql().c_str())); + Query.ResultSourceName = TEXT("result_string_i_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultStringI32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_ResultStringI32QueryToBlueprintQuery(const FResultStringI32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultStringI32", meta=(DisplayName="ResultStringI32 Where")) + static FResultStringI32Query ResultStringI32Where(FResultStringI32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultVecI32String", meta=(DisplayName="From ResultVecI32String")) + static FResultVecI32StringQuery FromResultVecI32String() + { + FResultVecI32StringQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.ResultVecI32String().into_sql().c_str())); + Query.ResultSourceName = TEXT("result_vec_i_32_string"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultVecI32String", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_ResultVecI32StringQueryToBlueprintQuery(const FResultVecI32StringQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ResultVecI32String", meta=(DisplayName="ResultVecI32String Where")) + static FResultVecI32StringQuery ResultVecI32StringWhere(FResultVecI32StringQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ScheduledTable", meta=(DisplayName="From ScheduledTable")) + static FScheduledTableQuery FromScheduledTable() + { + FScheduledTableQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.ScheduledTable().into_sql().c_str())); + Query.ResultSourceName = TEXT("scheduled_table"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ScheduledTable", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_ScheduledTableQueryToBlueprintQuery(const FScheduledTableQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ScheduledTable|Columns", meta=(DisplayName="ScheduledTable Text")) + static FBlueprintStringColumn ScheduledTableText(const FScheduledTableQuery& Query) + { + FBlueprintStringColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("scheduled_table") : Query.ResultSourceName; + Column.ColumnName = TEXT("text"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ScheduledTable", meta=(DisplayName="ScheduledTable Where")) + static FScheduledTableQuery ScheduledTableWhere(FScheduledTableQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|TableHoldsTable", meta=(DisplayName="From TableHoldsTable")) + static FTableHoldsTableQuery FromTableHoldsTable() + { + FTableHoldsTableQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.TableHoldsTable().into_sql().c_str())); + Query.ResultSourceName = TEXT("table_holds_table"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|TableHoldsTable", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_TableHoldsTableQueryToBlueprintQuery(const FTableHoldsTableQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|TableHoldsTable", meta=(DisplayName="TableHoldsTable Where")) + static FTableHoldsTableQuery TableHoldsTableWhere(FTableHoldsTableQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueBool", meta=(DisplayName="From UniqueBool")) + static FUniqueBoolQuery FromUniqueBool() + { + FUniqueBoolQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueBool().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_bool"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueBool", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueBoolQueryToBlueprintQuery(const FUniqueBoolQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueBool|Columns", meta=(DisplayName="UniqueBool B")) + static FBlueprintBoolColumn UniqueBoolB(const FUniqueBoolQuery& Query) + { + FBlueprintBoolColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_bool") : Query.ResultSourceName; + Column.ColumnName = TEXT("b"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueBool|Columns", meta=(DisplayName="UniqueBool Data")) + static FBlueprintInt32Column UniqueBoolData(const FUniqueBoolQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_bool") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueBool", meta=(DisplayName="UniqueBool Where")) + static FUniqueBoolQuery UniqueBoolWhere(FUniqueBoolQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueConnectionId", meta=(DisplayName="From UniqueConnectionId")) + static FUniqueConnectionIdQuery FromUniqueConnectionId() + { + FUniqueConnectionIdQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueConnectionId().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_connection_id"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueConnectionId", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueConnectionIdQueryToBlueprintQuery(const FUniqueConnectionIdQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueConnectionId|Columns", meta=(DisplayName="UniqueConnectionId A")) + static FBlueprintConnectionIdColumn UniqueConnectionIdA(const FUniqueConnectionIdQuery& Query) + { + FBlueprintConnectionIdColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_connection_id") : Query.ResultSourceName; + Column.ColumnName = TEXT("a"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueConnectionId|Columns", meta=(DisplayName="UniqueConnectionId Data")) + static FBlueprintInt32Column UniqueConnectionIdData(const FUniqueConnectionIdQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_connection_id") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueConnectionId", meta=(DisplayName="UniqueConnectionId Where")) + static FUniqueConnectionIdQuery UniqueConnectionIdWhere(FUniqueConnectionIdQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI128", meta=(DisplayName="From UniqueI128")) + static FUniqueI128Query FromUniqueI128() + { + FUniqueI128Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueI128().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_i_128"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI128", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueI128QueryToBlueprintQuery(const FUniqueI128Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI128|Columns", meta=(DisplayName="UniqueI128 Data")) + static FBlueprintInt32Column UniqueI128Data(const FUniqueI128Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_i_128") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI128", meta=(DisplayName="UniqueI128 Where")) + static FUniqueI128Query UniqueI128Where(FUniqueI128Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI16", meta=(DisplayName="From UniqueI16")) + static FUniqueI16Query FromUniqueI16() + { + FUniqueI16Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueI16().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_i_16"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI16", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueI16QueryToBlueprintQuery(const FUniqueI16Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI16|Columns", meta=(DisplayName="UniqueI16 Data")) + static FBlueprintInt32Column UniqueI16Data(const FUniqueI16Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_i_16") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI16", meta=(DisplayName="UniqueI16 Where")) + static FUniqueI16Query UniqueI16Where(FUniqueI16Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI256", meta=(DisplayName="From UniqueI256")) + static FUniqueI256Query FromUniqueI256() + { + FUniqueI256Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueI256().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_i_256"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI256", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueI256QueryToBlueprintQuery(const FUniqueI256Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI256|Columns", meta=(DisplayName="UniqueI256 Data")) + static FBlueprintInt32Column UniqueI256Data(const FUniqueI256Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_i_256") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI256", meta=(DisplayName="UniqueI256 Where")) + static FUniqueI256Query UniqueI256Where(FUniqueI256Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI32", meta=(DisplayName="From UniqueI32")) + static FUniqueI32Query FromUniqueI32() + { + FUniqueI32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueI32().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_i_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueI32QueryToBlueprintQuery(const FUniqueI32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI32|Columns", meta=(DisplayName="UniqueI32 N")) + static FBlueprintInt32Column UniqueI32N(const FUniqueI32Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_i_32") : Query.ResultSourceName; + Column.ColumnName = TEXT("n"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI32|Columns", meta=(DisplayName="UniqueI32 Data")) + static FBlueprintInt32Column UniqueI32Data(const FUniqueI32Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_i_32") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI32", meta=(DisplayName="UniqueI32 Where")) + static FUniqueI32Query UniqueI32Where(FUniqueI32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI64", meta=(DisplayName="From UniqueI64")) + static FUniqueI64Query FromUniqueI64() + { + FUniqueI64Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueI64().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_i_64"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI64", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueI64QueryToBlueprintQuery(const FUniqueI64Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI64|Columns", meta=(DisplayName="UniqueI64 N")) + static FBlueprintInt64Column UniqueI64N(const FUniqueI64Query& Query) + { + FBlueprintInt64Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_i_64") : Query.ResultSourceName; + Column.ColumnName = TEXT("n"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI64|Columns", meta=(DisplayName="UniqueI64 Data")) + static FBlueprintInt32Column UniqueI64Data(const FUniqueI64Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_i_64") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI64", meta=(DisplayName="UniqueI64 Where")) + static FUniqueI64Query UniqueI64Where(FUniqueI64Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI8", meta=(DisplayName="From UniqueI8")) + static FUniqueI8Query FromUniqueI8() + { + FUniqueI8Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueI8().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_i_8"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI8", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueI8QueryToBlueprintQuery(const FUniqueI8Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI8|Columns", meta=(DisplayName="UniqueI8 Data")) + static FBlueprintInt32Column UniqueI8Data(const FUniqueI8Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_i_8") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueI8", meta=(DisplayName="UniqueI8 Where")) + static FUniqueI8Query UniqueI8Where(FUniqueI8Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueIdentity", meta=(DisplayName="From UniqueIdentity")) + static FUniqueIdentityQuery FromUniqueIdentity() + { + FUniqueIdentityQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueIdentity().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_identity"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueIdentity", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueIdentityQueryToBlueprintQuery(const FUniqueIdentityQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueIdentity|Columns", meta=(DisplayName="UniqueIdentity I")) + static FBlueprintIdentityColumn UniqueIdentityI(const FUniqueIdentityQuery& Query) + { + FBlueprintIdentityColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_identity") : Query.ResultSourceName; + Column.ColumnName = TEXT("i"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueIdentity|Columns", meta=(DisplayName="UniqueIdentity Data")) + static FBlueprintInt32Column UniqueIdentityData(const FUniqueIdentityQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_identity") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueIdentity", meta=(DisplayName="UniqueIdentity Where")) + static FUniqueIdentityQuery UniqueIdentityWhere(FUniqueIdentityQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueString", meta=(DisplayName="From UniqueString")) + static FUniqueStringQuery FromUniqueString() + { + FUniqueStringQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueString().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_string"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueString", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueStringQueryToBlueprintQuery(const FUniqueStringQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueString|Columns", meta=(DisplayName="UniqueString S")) + static FBlueprintStringColumn UniqueStringS(const FUniqueStringQuery& Query) + { + FBlueprintStringColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_string") : Query.ResultSourceName; + Column.ColumnName = TEXT("s"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueString|Columns", meta=(DisplayName="UniqueString Data")) + static FBlueprintInt32Column UniqueStringData(const FUniqueStringQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_string") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueString", meta=(DisplayName="UniqueString Where")) + static FUniqueStringQuery UniqueStringWhere(FUniqueStringQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU128", meta=(DisplayName="From UniqueU128")) + static FUniqueU128Query FromUniqueU128() + { + FUniqueU128Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueU128().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_u_128"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU128", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueU128QueryToBlueprintQuery(const FUniqueU128Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU128|Columns", meta=(DisplayName="UniqueU128 Data")) + static FBlueprintInt32Column UniqueU128Data(const FUniqueU128Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_u_128") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU128", meta=(DisplayName="UniqueU128 Where")) + static FUniqueU128Query UniqueU128Where(FUniqueU128Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU16", meta=(DisplayName="From UniqueU16")) + static FUniqueU16Query FromUniqueU16() + { + FUniqueU16Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueU16().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_u_16"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU16", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueU16QueryToBlueprintQuery(const FUniqueU16Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU16|Columns", meta=(DisplayName="UniqueU16 Data")) + static FBlueprintInt32Column UniqueU16Data(const FUniqueU16Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_u_16") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU16", meta=(DisplayName="UniqueU16 Where")) + static FUniqueU16Query UniqueU16Where(FUniqueU16Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU256", meta=(DisplayName="From UniqueU256")) + static FUniqueU256Query FromUniqueU256() + { + FUniqueU256Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueU256().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_u_256"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU256", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueU256QueryToBlueprintQuery(const FUniqueU256Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU256|Columns", meta=(DisplayName="UniqueU256 Data")) + static FBlueprintInt32Column UniqueU256Data(const FUniqueU256Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_u_256") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU256", meta=(DisplayName="UniqueU256 Where")) + static FUniqueU256Query UniqueU256Where(FUniqueU256Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU32", meta=(DisplayName="From UniqueU32")) + static FUniqueU32Query FromUniqueU32() + { + FUniqueU32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueU32().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_u_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueU32QueryToBlueprintQuery(const FUniqueU32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU32|Columns", meta=(DisplayName="UniqueU32 Data")) + static FBlueprintInt32Column UniqueU32Data(const FUniqueU32Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_u_32") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU32", meta=(DisplayName="UniqueU32 Where")) + static FUniqueU32Query UniqueU32Where(FUniqueU32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU64", meta=(DisplayName="From UniqueU64")) + static FUniqueU64Query FromUniqueU64() + { + FUniqueU64Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueU64().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_u_64"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU64", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueU64QueryToBlueprintQuery(const FUniqueU64Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU64|Columns", meta=(DisplayName="UniqueU64 Data")) + static FBlueprintInt32Column UniqueU64Data(const FUniqueU64Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_u_64") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU64", meta=(DisplayName="UniqueU64 Where")) + static FUniqueU64Query UniqueU64Where(FUniqueU64Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU8", meta=(DisplayName="From UniqueU8")) + static FUniqueU8Query FromUniqueU8() + { + FUniqueU8Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueU8().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_u_8"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU8", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueU8QueryToBlueprintQuery(const FUniqueU8Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU8|Columns", meta=(DisplayName="UniqueU8 N")) + static FBlueprintUInt8Column UniqueU8N(const FUniqueU8Query& Query) + { + FBlueprintUInt8Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_u_8") : Query.ResultSourceName; + Column.ColumnName = TEXT("n"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU8|Columns", meta=(DisplayName="UniqueU8 Data")) + static FBlueprintInt32Column UniqueU8Data(const FUniqueU8Query& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_u_8") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueU8", meta=(DisplayName="UniqueU8 Where")) + static FUniqueU8Query UniqueU8Where(FUniqueU8Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueUuid", meta=(DisplayName="From UniqueUuid")) + static FUniqueUuidQuery FromUniqueUuid() + { + FUniqueUuidQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.UniqueUuid().into_sql().c_str())); + Query.ResultSourceName = TEXT("unique_uuid"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueUuid", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UniqueUuidQueryToBlueprintQuery(const FUniqueUuidQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueUuid|Columns", meta=(DisplayName="UniqueUuid U")) + static FBlueprintUuidColumn UniqueUuidU(const FUniqueUuidQuery& Query) + { + FBlueprintUuidColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_uuid") : Query.ResultSourceName; + Column.ColumnName = TEXT("u"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueUuid|Columns", meta=(DisplayName="UniqueUuid Data")) + static FBlueprintInt32Column UniqueUuidData(const FUniqueUuidQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("unique_uuid") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|UniqueUuid", meta=(DisplayName="UniqueUuid Where")) + static FUniqueUuidQuery UniqueUuidWhere(FUniqueUuidQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Users", meta=(DisplayName="From Users")) + static FUsersQuery FromUsers() + { + FUsersQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.Users().into_sql().c_str())); + Query.ResultSourceName = TEXT("users"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Users", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_UsersQueryToBlueprintQuery(const FUsersQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Users|Columns", meta=(DisplayName="Users Identity")) + static FBlueprintIdentityColumn UsersIdentity(const FUsersQuery& Query) + { + FBlueprintIdentityColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("users") : Query.ResultSourceName; + Column.ColumnName = TEXT("identity"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Users|Columns", meta=(DisplayName="Users Name")) + static FBlueprintStringColumn UsersName(const FUsersQuery& Query) + { + FBlueprintStringColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("users") : Query.ResultSourceName; + Column.ColumnName = TEXT("name"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Users", meta=(DisplayName="Users Where")) + static FUsersQuery UsersWhere(FUsersQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecBool", meta=(DisplayName="From VecBool")) + static FVecBoolQuery FromVecBool() + { + FVecBoolQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecBool().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_bool"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecBool", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecBoolQueryToBlueprintQuery(const FVecBoolQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecBool", meta=(DisplayName="VecBool Where")) + static FVecBoolQuery VecBoolWhere(FVecBoolQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecByteStruct", meta=(DisplayName="From VecByteStruct")) + static FVecByteStructQuery FromVecByteStruct() + { + FVecByteStructQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecByteStruct().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_byte_struct"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecByteStruct", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecByteStructQueryToBlueprintQuery(const FVecByteStructQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecByteStruct", meta=(DisplayName="VecByteStruct Where")) + static FVecByteStructQuery VecByteStructWhere(FVecByteStructQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecConnectionId", meta=(DisplayName="From VecConnectionId")) + static FVecConnectionIdQuery FromVecConnectionId() + { + FVecConnectionIdQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecConnectionId().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_connection_id"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecConnectionId", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecConnectionIdQueryToBlueprintQuery(const FVecConnectionIdQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecConnectionId", meta=(DisplayName="VecConnectionId Where")) + static FVecConnectionIdQuery VecConnectionIdWhere(FVecConnectionIdQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecEnumWithPayload", meta=(DisplayName="From VecEnumWithPayload")) + static FVecEnumWithPayloadQuery FromVecEnumWithPayload() + { + FVecEnumWithPayloadQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecEnumWithPayload().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_enum_with_payload"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecEnumWithPayload", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecEnumWithPayloadQueryToBlueprintQuery(const FVecEnumWithPayloadQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecEnumWithPayload", meta=(DisplayName="VecEnumWithPayload Where")) + static FVecEnumWithPayloadQuery VecEnumWithPayloadWhere(FVecEnumWithPayloadQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecEveryPrimitiveStruct", meta=(DisplayName="From VecEveryPrimitiveStruct")) + static FVecEveryPrimitiveStructQuery FromVecEveryPrimitiveStruct() + { + FVecEveryPrimitiveStructQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecEveryPrimitiveStruct().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_every_primitive_struct"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecEveryPrimitiveStruct", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecEveryPrimitiveStructQueryToBlueprintQuery(const FVecEveryPrimitiveStructQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecEveryPrimitiveStruct", meta=(DisplayName="VecEveryPrimitiveStruct Where")) + static FVecEveryPrimitiveStructQuery VecEveryPrimitiveStructWhere(FVecEveryPrimitiveStructQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecEveryVecStruct", meta=(DisplayName="From VecEveryVecStruct")) + static FVecEveryVecStructQuery FromVecEveryVecStruct() + { + FVecEveryVecStructQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecEveryVecStruct().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_every_vec_struct"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecEveryVecStruct", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecEveryVecStructQueryToBlueprintQuery(const FVecEveryVecStructQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecEveryVecStruct", meta=(DisplayName="VecEveryVecStruct Where")) + static FVecEveryVecStructQuery VecEveryVecStructWhere(FVecEveryVecStructQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecF32", meta=(DisplayName="From VecF32")) + static FVecF32Query FromVecF32() + { + FVecF32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecF32().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_f_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecF32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecF32QueryToBlueprintQuery(const FVecF32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecF32", meta=(DisplayName="VecF32 Where")) + static FVecF32Query VecF32Where(FVecF32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecF64", meta=(DisplayName="From VecF64")) + static FVecF64Query FromVecF64() + { + FVecF64Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecF64().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_f_64"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecF64", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecF64QueryToBlueprintQuery(const FVecF64Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecF64", meta=(DisplayName="VecF64 Where")) + static FVecF64Query VecF64Where(FVecF64Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI128", meta=(DisplayName="From VecI128")) + static FVecI128Query FromVecI128() + { + FVecI128Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecI128().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_i_128"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI128", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecI128QueryToBlueprintQuery(const FVecI128Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI128", meta=(DisplayName="VecI128 Where")) + static FVecI128Query VecI128Where(FVecI128Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI16", meta=(DisplayName="From VecI16")) + static FVecI16Query FromVecI16() + { + FVecI16Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecI16().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_i_16"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI16", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecI16QueryToBlueprintQuery(const FVecI16Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI16", meta=(DisplayName="VecI16 Where")) + static FVecI16Query VecI16Where(FVecI16Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI256", meta=(DisplayName="From VecI256")) + static FVecI256Query FromVecI256() + { + FVecI256Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecI256().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_i_256"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI256", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecI256QueryToBlueprintQuery(const FVecI256Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI256", meta=(DisplayName="VecI256 Where")) + static FVecI256Query VecI256Where(FVecI256Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI32", meta=(DisplayName="From VecI32")) + static FVecI32Query FromVecI32() + { + FVecI32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecI32().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_i_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecI32QueryToBlueprintQuery(const FVecI32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI32", meta=(DisplayName="VecI32 Where")) + static FVecI32Query VecI32Where(FVecI32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI64", meta=(DisplayName="From VecI64")) + static FVecI64Query FromVecI64() + { + FVecI64Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecI64().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_i_64"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI64", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecI64QueryToBlueprintQuery(const FVecI64Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI64", meta=(DisplayName="VecI64 Where")) + static FVecI64Query VecI64Where(FVecI64Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI8", meta=(DisplayName="From VecI8")) + static FVecI8Query FromVecI8() + { + FVecI8Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecI8().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_i_8"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI8", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecI8QueryToBlueprintQuery(const FVecI8Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecI8", meta=(DisplayName="VecI8 Where")) + static FVecI8Query VecI8Where(FVecI8Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecIdentity", meta=(DisplayName="From VecIdentity")) + static FVecIdentityQuery FromVecIdentity() + { + FVecIdentityQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecIdentity().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_identity"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecIdentity", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecIdentityQueryToBlueprintQuery(const FVecIdentityQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecIdentity", meta=(DisplayName="VecIdentity Where")) + static FVecIdentityQuery VecIdentityWhere(FVecIdentityQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecSimpleEnum", meta=(DisplayName="From VecSimpleEnum")) + static FVecSimpleEnumQuery FromVecSimpleEnum() + { + FVecSimpleEnumQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecSimpleEnum().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_simple_enum"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecSimpleEnum", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecSimpleEnumQueryToBlueprintQuery(const FVecSimpleEnumQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecSimpleEnum", meta=(DisplayName="VecSimpleEnum Where")) + static FVecSimpleEnumQuery VecSimpleEnumWhere(FVecSimpleEnumQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecString", meta=(DisplayName="From VecString")) + static FVecStringQuery FromVecString() + { + FVecStringQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecString().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_string"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecString", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecStringQueryToBlueprintQuery(const FVecStringQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecString", meta=(DisplayName="VecString Where")) + static FVecStringQuery VecStringWhere(FVecStringQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecTimestamp", meta=(DisplayName="From VecTimestamp")) + static FVecTimestampQuery FromVecTimestamp() + { + FVecTimestampQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecTimestamp().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_timestamp"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecTimestamp", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecTimestampQueryToBlueprintQuery(const FVecTimestampQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecTimestamp", meta=(DisplayName="VecTimestamp Where")) + static FVecTimestampQuery VecTimestampWhere(FVecTimestampQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU128", meta=(DisplayName="From VecU128")) + static FVecU128Query FromVecU128() + { + FVecU128Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecU128().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_u_128"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU128", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecU128QueryToBlueprintQuery(const FVecU128Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU128", meta=(DisplayName="VecU128 Where")) + static FVecU128Query VecU128Where(FVecU128Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU16", meta=(DisplayName="From VecU16")) + static FVecU16Query FromVecU16() + { + FVecU16Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecU16().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_u_16"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU16", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecU16QueryToBlueprintQuery(const FVecU16Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU16", meta=(DisplayName="VecU16 Where")) + static FVecU16Query VecU16Where(FVecU16Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU256", meta=(DisplayName="From VecU256")) + static FVecU256Query FromVecU256() + { + FVecU256Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecU256().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_u_256"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU256", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecU256QueryToBlueprintQuery(const FVecU256Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU256", meta=(DisplayName="VecU256 Where")) + static FVecU256Query VecU256Where(FVecU256Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU32", meta=(DisplayName="From VecU32")) + static FVecU32Query FromVecU32() + { + FVecU32Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecU32().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_u_32"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU32", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecU32QueryToBlueprintQuery(const FVecU32Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU32", meta=(DisplayName="VecU32 Where")) + static FVecU32Query VecU32Where(FVecU32Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU64", meta=(DisplayName="From VecU64")) + static FVecU64Query FromVecU64() + { + FVecU64Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecU64().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_u_64"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU64", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecU64QueryToBlueprintQuery(const FVecU64Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU64", meta=(DisplayName="VecU64 Where")) + static FVecU64Query VecU64Where(FVecU64Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU8", meta=(DisplayName="From VecU8")) + static FVecU8Query FromVecU8() + { + FVecU8Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecU8().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_u_8"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU8", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecU8QueryToBlueprintQuery(const FVecU8Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecU8", meta=(DisplayName="VecU8 Where")) + static FVecU8Query VecU8Where(FVecU8Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecUnitStruct", meta=(DisplayName="From VecUnitStruct")) + static FVecUnitStructQuery FromVecUnitStruct() + { + FVecUnitStructQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecUnitStruct().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_unit_struct"); + return Query; + } - FTypedSubscriptionBuilder& OnApplied(FOnSubscriptionApplied Callback); - FTypedSubscriptionBuilder& OnError(FOnSubscriptionError Callback); + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecUnitStruct", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecUnitStructQueryToBlueprintQuery(const FVecUnitStructQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } - template - FTypedSubscriptionBuilder& AddQuery(TFn&& Build) + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecUnitStruct", meta=(DisplayName="VecUnitStruct Where")) + static FVecUnitStructQuery VecUnitStructWhere(FVecUnitStructQuery Query, const FBlueprintPredicate& Predicate) { - FQueryBuilder Q; - auto Query = std::forward(Build)(Q); - static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn, - "Typed subscription queries must return a query_builder table/query expression."); - Sql.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str()))); - return *this; + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; } - USubscriptionHandle* Subscribe(); + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecUuid", meta=(DisplayName="From VecUuid")) + static FVecUuidQuery FromVecUuid() + { + FVecUuidQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.VecUuid().into_sql().c_str())); + Query.ResultSourceName = TEXT("vec_uuid"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecUuid", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_VecUuidQueryToBlueprintQuery(const FVecUuidQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|VecUuid", meta=(DisplayName="VecUuid Where")) + static FVecUuidQuery VecUuidWhere(FVecUuidQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Bool Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate BoolEqual(const FBlueprintBoolColumn& Column, const bool Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate UInt8Equal(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate UInt8GreaterThan(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate UInt8GreaterEqual(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate UInt8LessThan(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate UInt8LessEqual(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate Int32Equal(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate Int32GreaterThan(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate Int32GreaterEqual(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate Int32LessThan(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate Int32LessEqual(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate Int64Equal(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate Int64GreaterThan(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate Int64GreaterEqual(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate Int64LessThan(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate Int64LessEqual(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate FloatEqual(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate FloatGreaterThan(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate FloatGreaterEqual(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate FloatLessThan(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate FloatLessEqual(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate DoubleEqual(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate DoubleGreaterThan(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate DoubleGreaterEqual(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate DoubleLessThan(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate DoubleLessEqual(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="String Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate StringEqual(const FBlueprintStringColumn& Column, const FString& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Identity Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate IdentityEqual(const FBlueprintIdentityColumn& Column, const FSpacetimeDBIdentity& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="ConnectionId Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate ConnectionIdEqual(const FBlueprintConnectionIdColumn& Column, const FSpacetimeDBConnectionId& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate TimestampEqual(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate TimestampGreaterThan(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate TimestampGreaterEqual(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate TimestampLessThan(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate TimestampLessEqual(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Uuid Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate UuidEqual(const FBlueprintUuidColumn& Column, const FSpacetimeDBUuid& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="AND", CompactNodeTitle="AND", Keywords="and &&")) + static FBlueprintPredicate And(const FBlueprintPredicate& A, const FBlueprintPredicate& B) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = A.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("(%s) AND (%s)"), *A.Sql, *B.Sql); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="OR", CompactNodeTitle="OR", Keywords="or ||")) + static FBlueprintPredicate Or(const FBlueprintPredicate& A, const FBlueprintPredicate& B) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = A.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("(%s) OR (%s)"), *A.Sql, *B.Sql); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="NOT", CompactNodeTitle="NOT", Keywords="not !")) + static FBlueprintPredicate Not(const FBlueprintPredicate& A) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = A.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("NOT (%s)"), *A.Sql); + return Predicate; + } private: - UDbConnection* Conn = nullptr; - TArray Sql; - FOnSubscriptionApplied OnAppliedDelegateInternal; - FOnSubscriptionError OnErrorDelegateInternal; + static FString AppendPredicate(const FString& Sql, const FString& Predicate) + { + if (Sql.Contains(TEXT(" WHERE "))) + { + return Sql + TEXT(" AND (") + Predicate + TEXT(")"); + } + return Sql + TEXT(" WHERE (") + Predicate + TEXT(")"); + } }; // SubscriptionBuilder class @@ -13306,18 +18847,238 @@ class TESTCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase USubscriptionBuilder* OnError(FOnSubscriptionError Callback); UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + USubscriptionHandle* Subscribe(); + USubscriptionHandle* Subscribe(const TArray& SQL); template - [[nodiscard]] FTypedSubscriptionBuilder AddQuery(TFn&& Build) + USubscriptionBuilder* AddQuery(TFn&& Build) { - FTypedSubscriptionBuilder Typed(Conn); - Typed.OnApplied(OnAppliedDelegateInternal); - Typed.OnError(OnErrorDelegateInternal); - Typed.AddQuery(std::forward(Build)); - return Typed; + FQueryBuilder Q; + auto Query = std::forward(Build)(Q); + static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn, + "Typed subscription queries must return a query_builder table/query expression."); + PendingSqlQueries.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str()))); + return this; } + UFUNCTION(BlueprintCallable, Category="SpacetimeDB", meta=(DisplayName="AddQuery", ScriptName="AddQuery")) + USubscriptionBuilder* AddBlueprintQuery(const FBlueprintQuery& Query); + + USubscriptionBuilder* AddBtreeU32Query(const FBtreeU32Query& Query); + + USubscriptionBuilder* AddIndexedSimpleEnumQuery(const FIndexedSimpleEnumQuery& Query); + + USubscriptionBuilder* AddLargeTableQuery(const FLargeTableQuery& Query); + + USubscriptionBuilder* AddOneBoolQuery(const FOneBoolQuery& Query); + + USubscriptionBuilder* AddOneByteStructQuery(const FOneByteStructQuery& Query); + + USubscriptionBuilder* AddOneConnectionIdQuery(const FOneConnectionIdQuery& Query); + + USubscriptionBuilder* AddOneEnumWithPayloadQuery(const FOneEnumWithPayloadQuery& Query); + + USubscriptionBuilder* AddOneEveryPrimitiveStructQuery(const FOneEveryPrimitiveStructQuery& Query); + + USubscriptionBuilder* AddOneEveryVecStructQuery(const FOneEveryVecStructQuery& Query); + + USubscriptionBuilder* AddOneF32Query(const FOneF32Query& Query); + + USubscriptionBuilder* AddOneF64Query(const FOneF64Query& Query); + + USubscriptionBuilder* AddOneI128Query(const FOneI128Query& Query); + + USubscriptionBuilder* AddOneI16Query(const FOneI16Query& Query); + + USubscriptionBuilder* AddOneI256Query(const FOneI256Query& Query); + + USubscriptionBuilder* AddOneI32Query(const FOneI32Query& Query); + + USubscriptionBuilder* AddOneI64Query(const FOneI64Query& Query); + + USubscriptionBuilder* AddOneI8Query(const FOneI8Query& Query); + + USubscriptionBuilder* AddOneIdentityQuery(const FOneIdentityQuery& Query); + + USubscriptionBuilder* AddOneSimpleEnumQuery(const FOneSimpleEnumQuery& Query); + + USubscriptionBuilder* AddOneStringQuery(const FOneStringQuery& Query); + + USubscriptionBuilder* AddOneTimestampQuery(const FOneTimestampQuery& Query); + + USubscriptionBuilder* AddOneU128Query(const FOneU128Query& Query); + + USubscriptionBuilder* AddOneU16Query(const FOneU16Query& Query); + + USubscriptionBuilder* AddOneU256Query(const FOneU256Query& Query); + + USubscriptionBuilder* AddOneU32Query(const FOneU32Query& Query); + + USubscriptionBuilder* AddOneU64Query(const FOneU64Query& Query); + + USubscriptionBuilder* AddOneU8Query(const FOneU8Query& Query); + + USubscriptionBuilder* AddOneUnitStructQuery(const FOneUnitStructQuery& Query); + + USubscriptionBuilder* AddOneUuidQuery(const FOneUuidQuery& Query); + + USubscriptionBuilder* AddOptionEveryPrimitiveStructQuery(const FOptionEveryPrimitiveStructQuery& Query); + + USubscriptionBuilder* AddOptionI32Query(const FOptionI32Query& Query); + + USubscriptionBuilder* AddOptionIdentityQuery(const FOptionIdentityQuery& Query); + + USubscriptionBuilder* AddOptionSimpleEnumQuery(const FOptionSimpleEnumQuery& Query); + + USubscriptionBuilder* AddOptionStringQuery(const FOptionStringQuery& Query); + + USubscriptionBuilder* AddOptionUuidQuery(const FOptionUuidQuery& Query); + + USubscriptionBuilder* AddOptionVecOptionI32Query(const FOptionVecOptionI32Query& Query); + + USubscriptionBuilder* AddPkBoolQuery(const FPkBoolQuery& Query); + + USubscriptionBuilder* AddPkConnectionIdQuery(const FPkConnectionIdQuery& Query); + + USubscriptionBuilder* AddPkI128Query(const FPkI128Query& Query); + + USubscriptionBuilder* AddPkI16Query(const FPkI16Query& Query); + + USubscriptionBuilder* AddPkI256Query(const FPkI256Query& Query); + + USubscriptionBuilder* AddPkI32Query(const FPkI32Query& Query); + + USubscriptionBuilder* AddPkI64Query(const FPkI64Query& Query); + + USubscriptionBuilder* AddPkI8Query(const FPkI8Query& Query); + + USubscriptionBuilder* AddPkIdentityQuery(const FPkIdentityQuery& Query); + + USubscriptionBuilder* AddPkSimpleEnumQuery(const FPkSimpleEnumQuery& Query); + + USubscriptionBuilder* AddPkStringQuery(const FPkStringQuery& Query); + + USubscriptionBuilder* AddPkU128Query(const FPkU128Query& Query); + + USubscriptionBuilder* AddPkU16Query(const FPkU16Query& Query); + + USubscriptionBuilder* AddPkU256Query(const FPkU256Query& Query); + + USubscriptionBuilder* AddPkU32Query(const FPkU32Query& Query); + + USubscriptionBuilder* AddPkU32TwoQuery(const FPkU32TwoQuery& Query); + + USubscriptionBuilder* AddPkU64Query(const FPkU64Query& Query); + + USubscriptionBuilder* AddPkU8Query(const FPkU8Query& Query); + + USubscriptionBuilder* AddPkUuidQuery(const FPkUuidQuery& Query); + + USubscriptionBuilder* AddResultEveryPrimitiveStructStringQuery(const FResultEveryPrimitiveStructStringQuery& Query); + + USubscriptionBuilder* AddResultI32StringQuery(const FResultI32StringQuery& Query); + + USubscriptionBuilder* AddResultIdentityStringQuery(const FResultIdentityStringQuery& Query); + + USubscriptionBuilder* AddResultSimpleEnumI32Query(const FResultSimpleEnumI32Query& Query); + + USubscriptionBuilder* AddResultStringI32Query(const FResultStringI32Query& Query); + + USubscriptionBuilder* AddResultVecI32StringQuery(const FResultVecI32StringQuery& Query); + + USubscriptionBuilder* AddScheduledTableQuery(const FScheduledTableQuery& Query); + + USubscriptionBuilder* AddTableHoldsTableQuery(const FTableHoldsTableQuery& Query); + + USubscriptionBuilder* AddUniqueBoolQuery(const FUniqueBoolQuery& Query); + + USubscriptionBuilder* AddUniqueConnectionIdQuery(const FUniqueConnectionIdQuery& Query); + + USubscriptionBuilder* AddUniqueI128Query(const FUniqueI128Query& Query); + + USubscriptionBuilder* AddUniqueI16Query(const FUniqueI16Query& Query); + + USubscriptionBuilder* AddUniqueI256Query(const FUniqueI256Query& Query); + + USubscriptionBuilder* AddUniqueI32Query(const FUniqueI32Query& Query); + + USubscriptionBuilder* AddUniqueI64Query(const FUniqueI64Query& Query); + + USubscriptionBuilder* AddUniqueI8Query(const FUniqueI8Query& Query); + + USubscriptionBuilder* AddUniqueIdentityQuery(const FUniqueIdentityQuery& Query); + + USubscriptionBuilder* AddUniqueStringQuery(const FUniqueStringQuery& Query); + + USubscriptionBuilder* AddUniqueU128Query(const FUniqueU128Query& Query); + + USubscriptionBuilder* AddUniqueU16Query(const FUniqueU16Query& Query); + + USubscriptionBuilder* AddUniqueU256Query(const FUniqueU256Query& Query); + + USubscriptionBuilder* AddUniqueU32Query(const FUniqueU32Query& Query); + + USubscriptionBuilder* AddUniqueU64Query(const FUniqueU64Query& Query); + + USubscriptionBuilder* AddUniqueU8Query(const FUniqueU8Query& Query); + + USubscriptionBuilder* AddUniqueUuidQuery(const FUniqueUuidQuery& Query); + + USubscriptionBuilder* AddUsersQuery(const FUsersQuery& Query); + + USubscriptionBuilder* AddVecBoolQuery(const FVecBoolQuery& Query); + + USubscriptionBuilder* AddVecByteStructQuery(const FVecByteStructQuery& Query); + + USubscriptionBuilder* AddVecConnectionIdQuery(const FVecConnectionIdQuery& Query); + + USubscriptionBuilder* AddVecEnumWithPayloadQuery(const FVecEnumWithPayloadQuery& Query); + + USubscriptionBuilder* AddVecEveryPrimitiveStructQuery(const FVecEveryPrimitiveStructQuery& Query); + + USubscriptionBuilder* AddVecEveryVecStructQuery(const FVecEveryVecStructQuery& Query); + + USubscriptionBuilder* AddVecF32Query(const FVecF32Query& Query); + + USubscriptionBuilder* AddVecF64Query(const FVecF64Query& Query); + + USubscriptionBuilder* AddVecI128Query(const FVecI128Query& Query); + + USubscriptionBuilder* AddVecI16Query(const FVecI16Query& Query); + + USubscriptionBuilder* AddVecI256Query(const FVecI256Query& Query); + + USubscriptionBuilder* AddVecI32Query(const FVecI32Query& Query); + + USubscriptionBuilder* AddVecI64Query(const FVecI64Query& Query); + + USubscriptionBuilder* AddVecI8Query(const FVecI8Query& Query); + + USubscriptionBuilder* AddVecIdentityQuery(const FVecIdentityQuery& Query); + + USubscriptionBuilder* AddVecSimpleEnumQuery(const FVecSimpleEnumQuery& Query); + + USubscriptionBuilder* AddVecStringQuery(const FVecStringQuery& Query); + + USubscriptionBuilder* AddVecTimestampQuery(const FVecTimestampQuery& Query); + + USubscriptionBuilder* AddVecU128Query(const FVecU128Query& Query); + + USubscriptionBuilder* AddVecU16Query(const FVecU16Query& Query); + + USubscriptionBuilder* AddVecU256Query(const FVecU256Query& Query); + + USubscriptionBuilder* AddVecU32Query(const FVecU32Query& Query); + + USubscriptionBuilder* AddVecU64Query(const FVecU64Query& Query); + + USubscriptionBuilder* AddVecU8Query(const FVecU8Query& Query); + + USubscriptionBuilder* AddVecUnitStructQuery(const FVecUnitStructQuery& Query); + + USubscriptionBuilder* AddVecUuidQuery(const FVecUuidQuery& Query); + /** Convenience for subscribing to all rows from all public sources, including views */ UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") USubscriptionHandle* SubscribeToAllTables(); @@ -13330,6 +19091,9 @@ class TESTCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase UPROPERTY() class UDbConnection* Conn; + UPROPERTY() + TArray PendingSqlQueries; + // Delegates stored so Subscribe() can bind forwarding callbacks FOnSubscriptionApplied OnAppliedDelegateInternal; FOnSubscriptionError OnErrorDelegateInternal; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/SpacetimeFullClientTests.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/SpacetimeFullClientTests.h index 02b26831c9f..03e154d1a11 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/SpacetimeFullClientTests.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/Tests/SpacetimeFullClientTests.h @@ -132,3 +132,4 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST(FOverlappingSubscriptionsTest, "SpacetimeDB.Tes IMPLEMENT_SIMPLE_AUTOMATION_TEST(FInsertCallUuidV4Test, "SpacetimeDB.TestClient.InsertCallUuidV4Test", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) IMPLEMENT_SIMPLE_AUTOMATION_TEST(FInsertCallUuidV7Test, "SpacetimeDB.TestClient.InsertCallUuidV7Test", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FBlueprintQueryBuilderBasicFlowTest, "SpacetimeDB.TestClient.BlueprintQueryBuilderBasicFlowTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp index b2b6ac65b18..7ab3f3c71f5 100644 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp +++ b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -547,27 +547,6 @@ USubscriptionBuilder* UDbConnection::SubscriptionBuilder() Builder->Conn = this; return Builder; } -FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) -{ - OnAppliedDelegateInternal = Callback; - return *this; -} -FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnError(FOnSubscriptionError Callback) -{ - OnErrorDelegateInternal = Callback; - return *this; -} -USubscriptionHandle* FTypedSubscriptionBuilder::Subscribe() -{ - if (!Conn) - { - return nullptr; - } - USubscriptionBuilder* Builder = Conn->SubscriptionBuilder(); - Builder->OnApplied(OnAppliedDelegateInternal); - Builder->OnError(OnErrorDelegateInternal); - return Builder->Subscribe(Sql); -} USubscriptionBuilder* USubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) { OnAppliedDelegateInternal = Callback; @@ -578,6 +557,12 @@ USubscriptionBuilder* USubscriptionBuilder::OnError(FOnSubscriptionError Callbac OnErrorDelegateInternal = Callback; return this; } +USubscriptionHandle* USubscriptionBuilder::Subscribe() +{ + const TArray SqlQueries = PendingSqlQueries; + PendingSqlQueries.Empty(); + return Subscribe(SqlQueries); +} USubscriptionHandle* USubscriptionBuilder::Subscribe(const TArray& SQL) { USubscriptionHandle* Handle = NewObject(); @@ -608,6 +593,36 @@ USubscriptionHandle* USubscriptionBuilder::SubscribeToAllTables() return Subscribe(FQueryBuilder::AllTablesSqlQueries()); } +USubscriptionBuilder* USubscriptionBuilder::AddBlueprintQuery(const FBlueprintQuery& Query) +{ + PendingSqlQueries.Add(Query.Sql); + return this; +} + +USubscriptionBuilder* USubscriptionBuilder::AddMyTableQuery(const FMyTableQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPkUuidQuery(const FPkUuidQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddProcInsertsIntoQuery(const FProcInsertsIntoQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + USubscriptionHandle::USubscriptionHandle(UDbConnection* InConn) { Conn = InConn; @@ -688,7 +703,7 @@ void UDbConnection::ForwardOnConnect(UDbConnectionBase* BaseConnection, FSpaceti { if (OnConnectDelegate.IsBound()) { - OnConnectDelegate.Execute(this, Identity, Token); + OnConnectDelegate.Execute(this, InIdentity, InToken); } } void UDbConnection::ForwardOnDisconnect(UDbConnectionBase* BaseConnection, const FString& Error) diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h index 55fd0f324a6..93e6412bc41 100644 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -1112,9 +1112,15 @@ class TESTPROCCLIENT_API URemoteProcedures : public UObject }; // QueryBuilder types +struct TESTPROCCLIENT_API FMyTableCols; +struct TESTPROCCLIENT_API FMyTableIxCols; +struct TESTPROCCLIENT_API FPkUuidCols; +struct TESTPROCCLIENT_API FPkUuidIxCols; +struct TESTPROCCLIENT_API FProcInsertsIntoCols; +struct TESTPROCCLIENT_API FProcInsertsIntoIxCols; + struct TESTPROCCLIENT_API FMyTableCols { - using legacy_type = FMyTableCols; explicit FMyTableCols(const char* TableName) : Field(TableName, "field") {} @@ -1123,7 +1129,6 @@ struct TESTPROCCLIENT_API FMyTableCols struct TESTPROCCLIENT_API FMyTableIxCols { - using legacy_type = FMyTableIxCols; explicit FMyTableIxCols(const char* TableName) {} @@ -1137,7 +1142,6 @@ namespace SpacetimeDB::query_builder struct TESTPROCCLIENT_API FPkUuidCols { - using legacy_type = FPkUuidCols; explicit FPkUuidCols(const char* TableName) : U(TableName, "u"), Data(TableName, "data") {} @@ -1147,7 +1151,6 @@ struct TESTPROCCLIENT_API FPkUuidCols struct TESTPROCCLIENT_API FPkUuidIxCols { - using legacy_type = FPkUuidIxCols; explicit FPkUuidIxCols(const char* TableName) {} @@ -1161,7 +1164,6 @@ namespace SpacetimeDB::query_builder struct TESTPROCCLIENT_API FProcInsertsIntoCols { - using legacy_type = FProcInsertsIntoCols; explicit FProcInsertsIntoCols(const char* TableName) : ReducerTs(TableName, "reducer_ts"), ProcedureTs(TableName, "procedure_ts"), X(TableName, "x"), Y(TableName, "y") {} @@ -1173,7 +1175,6 @@ struct TESTPROCCLIENT_API FProcInsertsIntoCols struct TESTPROCCLIENT_API FProcInsertsIntoIxCols { - using legacy_type = FProcInsertsIntoIxCols; explicit FProcInsertsIntoIxCols(const char* TableName) {} @@ -1206,32 +1207,697 @@ struct TESTPROCCLIENT_API FQueryBuilder } }; -struct TESTPROCCLIENT_API FTypedSubscriptionBuilder +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintQuery { - explicit FTypedSubscriptionBuilder(UDbConnection* InConn) - : Conn(InConn) {} + GENERATED_BODY() - FTypedSubscriptionBuilder& OnApplied(FOnSubscriptionApplied Callback); - FTypedSubscriptionBuilder& OnError(FOnSubscriptionError Callback); + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; - template - FTypedSubscriptionBuilder& AddQuery(TFn&& Build) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintPredicate +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FMyTableQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FPkUuidQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FProcInsertsIntoQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintBoolColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintUInt8Column +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintInt32Column +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintInt64Column +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintFloatColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintDoubleColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintStringColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintIdentityColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintConnectionIdColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintTimestampColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTPROCCLIENT_API FBlueprintUuidColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +UCLASS(BlueprintType) +class TESTPROCCLIENT_API UQueryBuilderBlueprintLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|MyTable", meta=(DisplayName="From MyTable")) + static FMyTableQuery FromMyTable() { - FQueryBuilder Q; - auto Query = std::forward(Build)(Q); - static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn, - "Typed subscription queries must return a query_builder table/query expression."); - Sql.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str()))); - return *this; + FMyTableQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.MyTable().into_sql().c_str())); + Query.ResultSourceName = TEXT("my_table"); + return Query; } - USubscriptionHandle* Subscribe(); + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|MyTable", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_MyTableQueryToBlueprintQuery(const FMyTableQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|MyTable", meta=(DisplayName="MyTable Where")) + static FMyTableQuery MyTableWhere(FMyTableQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkUuid", meta=(DisplayName="From PkUuid")) + static FPkUuidQuery FromPkUuid() + { + FPkUuidQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PkUuid().into_sql().c_str())); + Query.ResultSourceName = TEXT("pk_uuid"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkUuid", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PkUuidQueryToBlueprintQuery(const FPkUuidQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkUuid|Columns", meta=(DisplayName="PkUuid U")) + static FBlueprintUuidColumn PkUuidU(const FPkUuidQuery& Query) + { + FBlueprintUuidColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_uuid") : Query.ResultSourceName; + Column.ColumnName = TEXT("u"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkUuid|Columns", meta=(DisplayName="PkUuid Data")) + static FBlueprintUInt8Column PkUuidData(const FPkUuidQuery& Query) + { + FBlueprintUInt8Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("pk_uuid") : Query.ResultSourceName; + Column.ColumnName = TEXT("data"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PkUuid", meta=(DisplayName="PkUuid Where")) + static FPkUuidQuery PkUuidWhere(FPkUuidQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ProcInsertsInto", meta=(DisplayName="From ProcInsertsInto")) + static FProcInsertsIntoQuery FromProcInsertsInto() + { + FProcInsertsIntoQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.ProcInsertsInto().into_sql().c_str())); + Query.ResultSourceName = TEXT("proc_inserts_into"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ProcInsertsInto", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_ProcInsertsIntoQueryToBlueprintQuery(const FProcInsertsIntoQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ProcInsertsInto|Columns", meta=(DisplayName="ProcInsertsInto ReducerTs")) + static FBlueprintTimestampColumn ProcInsertsIntoReducerTs(const FProcInsertsIntoQuery& Query) + { + FBlueprintTimestampColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("proc_inserts_into") : Query.ResultSourceName; + Column.ColumnName = TEXT("reducer_ts"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ProcInsertsInto|Columns", meta=(DisplayName="ProcInsertsInto ProcedureTs")) + static FBlueprintTimestampColumn ProcInsertsIntoProcedureTs(const FProcInsertsIntoQuery& Query) + { + FBlueprintTimestampColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("proc_inserts_into") : Query.ResultSourceName; + Column.ColumnName = TEXT("procedure_ts"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ProcInsertsInto|Columns", meta=(DisplayName="ProcInsertsInto X")) + static FBlueprintUInt8Column ProcInsertsIntoX(const FProcInsertsIntoQuery& Query) + { + FBlueprintUInt8Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("proc_inserts_into") : Query.ResultSourceName; + Column.ColumnName = TEXT("x"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ProcInsertsInto|Columns", meta=(DisplayName="ProcInsertsInto Y")) + static FBlueprintUInt8Column ProcInsertsIntoY(const FProcInsertsIntoQuery& Query) + { + FBlueprintUInt8Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("proc_inserts_into") : Query.ResultSourceName; + Column.ColumnName = TEXT("y"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ProcInsertsInto", meta=(DisplayName="ProcInsertsInto Where")) + static FProcInsertsIntoQuery ProcInsertsIntoWhere(FProcInsertsIntoQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Bool Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate BoolEqual(const FBlueprintBoolColumn& Column, const bool Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate UInt8Equal(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate UInt8GreaterThan(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate UInt8GreaterEqual(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate UInt8LessThan(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate UInt8LessEqual(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate Int32Equal(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate Int32GreaterThan(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate Int32GreaterEqual(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate Int32LessThan(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate Int32LessEqual(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate Int64Equal(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate Int64GreaterThan(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate Int64GreaterEqual(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate Int64LessThan(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate Int64LessEqual(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate FloatEqual(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate FloatGreaterThan(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate FloatGreaterEqual(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate FloatLessThan(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate FloatLessEqual(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate DoubleEqual(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate DoubleGreaterThan(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate DoubleGreaterEqual(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate DoubleLessThan(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate DoubleLessEqual(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="String Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate StringEqual(const FBlueprintStringColumn& Column, const FString& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Identity Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate IdentityEqual(const FBlueprintIdentityColumn& Column, const FSpacetimeDBIdentity& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="ConnectionId Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate ConnectionIdEqual(const FBlueprintConnectionIdColumn& Column, const FSpacetimeDBConnectionId& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate TimestampEqual(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate TimestampGreaterThan(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate TimestampGreaterEqual(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate TimestampLessThan(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate TimestampLessEqual(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Uuid Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate UuidEqual(const FBlueprintUuidColumn& Column, const FSpacetimeDBUuid& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="AND", CompactNodeTitle="AND", Keywords="and &&")) + static FBlueprintPredicate And(const FBlueprintPredicate& A, const FBlueprintPredicate& B) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = A.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("(%s) AND (%s)"), *A.Sql, *B.Sql); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="OR", CompactNodeTitle="OR", Keywords="or ||")) + static FBlueprintPredicate Or(const FBlueprintPredicate& A, const FBlueprintPredicate& B) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = A.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("(%s) OR (%s)"), *A.Sql, *B.Sql); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="NOT", CompactNodeTitle="NOT", Keywords="not !")) + static FBlueprintPredicate Not(const FBlueprintPredicate& A) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = A.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("NOT (%s)"), *A.Sql); + return Predicate; + } private: - UDbConnection* Conn = nullptr; - TArray Sql; - FOnSubscriptionApplied OnAppliedDelegateInternal; - FOnSubscriptionError OnErrorDelegateInternal; + static FString AppendPredicate(const FString& Sql, const FString& Predicate) + { + if (Sql.Contains(TEXT(" WHERE "))) + { + return Sql + TEXT(" AND (") + Predicate + TEXT(")"); + } + return Sql + TEXT(" WHERE (") + Predicate + TEXT(")"); + } }; // SubscriptionBuilder class @@ -1249,18 +1915,30 @@ class TESTPROCCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase USubscriptionBuilder* OnError(FOnSubscriptionError Callback); UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + USubscriptionHandle* Subscribe(); + USubscriptionHandle* Subscribe(const TArray& SQL); template - [[nodiscard]] FTypedSubscriptionBuilder AddQuery(TFn&& Build) + USubscriptionBuilder* AddQuery(TFn&& Build) { - FTypedSubscriptionBuilder Typed(Conn); - Typed.OnApplied(OnAppliedDelegateInternal); - Typed.OnError(OnErrorDelegateInternal); - Typed.AddQuery(std::forward(Build)); - return Typed; + FQueryBuilder Q; + auto Query = std::forward(Build)(Q); + static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn, + "Typed subscription queries must return a query_builder table/query expression."); + PendingSqlQueries.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str()))); + return this; } + UFUNCTION(BlueprintCallable, Category="SpacetimeDB", meta=(DisplayName="AddQuery", ScriptName="AddQuery")) + USubscriptionBuilder* AddBlueprintQuery(const FBlueprintQuery& Query); + + USubscriptionBuilder* AddMyTableQuery(const FMyTableQuery& Query); + + USubscriptionBuilder* AddPkUuidQuery(const FPkUuidQuery& Query); + + USubscriptionBuilder* AddProcInsertsIntoQuery(const FProcInsertsIntoQuery& Query); + /** Convenience for subscribing to all rows from all public sources, including views */ UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") USubscriptionHandle* SubscribeToAllTables(); @@ -1273,6 +1951,9 @@ class TESTPROCCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase UPROPERTY() class UDbConnection* Conn; + UPROPERTY() + TArray PendingSqlQueries; + // Delegates stored so Subscribe() can bind forwarding callbacks FOnSubscriptionApplied OnAppliedDelegateInternal; FOnSubscriptionError OnErrorDelegateInternal; diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp index 163a1eb56cf..fe1df981db1 100644 --- a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -373,27 +373,6 @@ USubscriptionBuilder* UDbConnection::SubscriptionBuilder() Builder->Conn = this; return Builder; } -FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) -{ - OnAppliedDelegateInternal = Callback; - return *this; -} -FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnError(FOnSubscriptionError Callback) -{ - OnErrorDelegateInternal = Callback; - return *this; -} -USubscriptionHandle* FTypedSubscriptionBuilder::Subscribe() -{ - if (!Conn) - { - return nullptr; - } - USubscriptionBuilder* Builder = Conn->SubscriptionBuilder(); - Builder->OnApplied(OnAppliedDelegateInternal); - Builder->OnError(OnErrorDelegateInternal); - return Builder->Subscribe(Sql); -} USubscriptionBuilder* USubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) { OnAppliedDelegateInternal = Callback; @@ -404,6 +383,12 @@ USubscriptionBuilder* USubscriptionBuilder::OnError(FOnSubscriptionError Callbac OnErrorDelegateInternal = Callback; return this; } +USubscriptionHandle* USubscriptionBuilder::Subscribe() +{ + const TArray SqlQueries = PendingSqlQueries; + PendingSqlQueries.Empty(); + return Subscribe(SqlQueries); +} USubscriptionHandle* USubscriptionBuilder::Subscribe(const TArray& SQL) { USubscriptionHandle* Handle = NewObject(); @@ -434,6 +419,60 @@ USubscriptionHandle* USubscriptionBuilder::SubscribeToAllTables() return Subscribe(FQueryBuilder::AllTablesSqlQueries()); } +USubscriptionBuilder* USubscriptionBuilder::AddBlueprintQuery(const FBlueprintQuery& Query) +{ + PendingSqlQueries.Add(Query.Sql); + return this; +} + +USubscriptionBuilder* USubscriptionBuilder::AddMyPlayerQuery(const FMyPlayerQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddMyPlayerAndLevelQuery(const FMyPlayerAndLevelQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddNearbyPlayersQuery(const FNearbyPlayersQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPlayerQuery(const FPlayerQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPlayerLevelQuery(const FPlayerLevelQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddPlayersAtLevel0Query(const FPlayersAtLevel0Query& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + USubscriptionHandle::USubscriptionHandle(UDbConnection* InConn) { Conn = InConn; @@ -514,7 +553,7 @@ void UDbConnection::ForwardOnConnect(UDbConnectionBase* BaseConnection, FSpaceti { if (OnConnectDelegate.IsBound()) { - OnConnectDelegate.Execute(this, Identity, Token); + OnConnectDelegate.Execute(this, InIdentity, InToken); } } void UDbConnection::ForwardOnDisconnect(UDbConnectionBase* BaseConnection, const FString& Error) diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/CommonTestFunctions.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/CommonTestFunctions.cpp index 6244eb3e90d..521828acf11 100644 --- a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/CommonTestFunctions.cpp +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/CommonTestFunctions.cpp @@ -1 +1,171 @@ #include "Tests/CommonTestFunctions.h" + +void UTestHelperDelegates::HandleConnect(UDbConnection* Conn, FSpacetimeDBIdentity Identity, const FString& Token) +{ + if (OnConnect) + { + OnConnect(Conn, Identity, Token); + } +} + +void UTestHelperDelegates::HandleConnectError(UDbConnection* Conn, const FString& Error) +{ + if (OnConnectError) + { + OnConnectError(Conn, Error); + } +} + +void UTestHelperDelegates::HandleDisconnect(UDbConnection* Conn, const FString& Error) +{ + if (OnDisconnect) + { + OnDisconnect(Conn, Error); + } +} + +void UTestHelperDelegates::HandleSubscriptionApplied(FSubscriptionEventContext Ctx) +{ + if (OnSubscriptionApplied) + { + OnSubscriptionApplied(Ctx); + } +} + +void UTestHelperDelegates::HandleSubscriptionError(FErrorContext Ctx) +{ + if (OnSubscriptionError) + { + OnSubscriptionError(Ctx); + } +} + +UDbConnection* ConnectThen( + TSharedPtr Counter, + const FString& TestName, + TFunction Callback) +{ + FString DbName; + FString DbNameError; + if (!GetDbName(DbName, DbNameError)) + { + return nullptr; + } + + UCredentials::Init(TestName); + + const FString ConnectTestName = FString::Printf(TEXT("on_connect_%s"), *TestName); + Counter->Register(ConnectTestName); + + UTestHelperDelegates* TestHelper = NewObject(); + TestHelper->AddToRoot(); + + TestHelper->OnConnect = [Counter, Callback, ConnectTestName](UDbConnection* Conn, FSpacetimeDBIdentity, const FString&) + { + Callback(Conn); + Counter->MarkSuccess(ConnectTestName); + }; + TestHelper->OnConnectError = [Counter, ConnectTestName](UDbConnection*, const FString& Error) + { + Counter->MarkFailure(ConnectTestName, FString::Printf(TEXT("Connect error: %s"), *Error)); + }; + TestHelper->OnDisconnect = [Counter, ConnectTestName](UDbConnection*, const FString& Error) + { + Counter->MarkFailure(ConnectTestName, FString::Printf(TEXT("Disconnected: %s"), *Error)); + }; + + FOnConnectDelegate ConnectDelegate; + BIND_DELEGATE_SAFE(ConnectDelegate, TestHelper, UTestHelperDelegates, HandleConnect); + + FOnDisconnectDelegate DisconnectDelegate; + BIND_DELEGATE_SAFE(DisconnectDelegate, TestHelper, UTestHelperDelegates, HandleDisconnect); + + FOnConnectErrorDelegate ErrorDelegate; + BIND_DELEGATE_SAFE(ErrorDelegate, TestHelper, UTestHelperDelegates, HandleConnectError); + + UDbConnection* Conn = UDbConnection::Builder() + ->WithUri(TEXT("localhost:3000")) + ->WithDatabaseName(DbName) + ->OnConnect(ConnectDelegate) + ->OnDisconnect(DisconnectDelegate) + ->OnConnectError(ErrorDelegate) + ->Build(); + + if (Conn) + { + Conn->SetAutoTicking(true); + Conn->AddToRoot(); + } + + return Conn; +} + +bool GetDbName(FString& DBName, FString& Error) +{ + const FString DbNameEnv = FPlatformMisc::GetEnvironmentVariable(TEXT("SPACETIME_SDK_TEST_DB_NAME")); + if (!DbNameEnv.IsEmpty()) + { + DBName = DbNameEnv; + return true; + } + + FString CmdValue; + if (FParse::Value(FCommandLine::Get(), TEXT("-SpacetimeDbName="), CmdValue)) + { + DBName = CmdValue; + return true; + } + + Error = TEXT("No DB name. Pass -SpacetimeDbName= or set SPACETIME_SDK_TEST_DB_NAME."); + return false; +} + +bool ValidateParameterConfig(FAutomationTestBase* Test) +{ + FString DbName; + FString DbNameError; + if (!GetDbName(DbName, DbNameError)) + { + Test->AddError(DbNameError); + return false; + } + return true; +} + +bool ReportTestResult(FAutomationTestBase& Test, const FString& TestName, TSharedPtr Counter, bool bTimedOut) +{ + bool bHasFailure = false; + + for (const FString& Msg : Counter->GetFailures()) + { + TESTLOG_FAIL(Test, TEXT("Operation - %s"), *Msg); + bHasFailure = true; + } + for (const FString& Msg : Counter->GetSuccesses()) + { + TESTLOG_SUCCESS(Test, TEXT("Operation - %s"), *Msg); + } + + if (bTimedOut) + { + TESTLOG_FAIL(Test, TEXT("Timed out waiting for operation")); + bHasFailure = true; + } + if (Counter->IsAborted()) + { + TESTLOG_FAIL(Test, TEXT("Test aborted due to precondition failure")); + bHasFailure = true; + } + + if (!bHasFailure) + { + TESTLOG_SUCCESS(Test, TEXT("Test Success")); + Test.TestTrue(*TestName, true); + } + else + { + TESTLOG_FAIL(Test, TEXT("Test failed")); + } + + return !bHasFailure; +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/SpacetimeFullClientTests.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/SpacetimeFullClientTests.cpp index c8364b3ae91..aa182d538f1 100644 --- a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/SpacetimeFullClientTests.cpp +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/SpacetimeFullClientTests.cpp @@ -1,6 +1,10 @@ #include "Tests/SpacetimeFullClientTests.h" +#include "Tests/CommonTestFunctions.h" +#include "Tests/TestHandler.h" + #include "ModuleBindings/SpacetimeDBClient.g.h" +#include "ModuleBindings/Tables/PlayersAtLevel0Table.g.h" namespace { @@ -8,6 +12,37 @@ static FString ToFString(const std::string& InSql) { return FString(UTF8_TO_TCHAR(InSql.c_str())); } + +class FWaitForTestCounter : public IAutomationLatentCommand +{ +public: + FWaitForTestCounter(FAutomationTestBase& InTest, const FString& InTestName, TSharedPtr InCounter, double InStartTime) + : Test(InTest) + , TestName(InTestName) + , Counter(MoveTemp(InCounter)) + , StartTime(InStartTime) + {} + + virtual bool Update() override + { + const double Timeout = 90.0; + const bool bStopped = Counter->IsAborted() || Counter->IsComplete() || (FPlatformTime::Seconds() - StartTime > Timeout); + const bool bTimedOut = (FPlatformTime::Seconds() - StartTime > Timeout); + + if (bStopped) + { + ReportTestResult(Test, TestName, Counter, bTimedOut); + } + + return bStopped; + } + +private: + FAutomationTestBase& Test; + FString TestName; + TSharedPtr Counter; + double StartTime = 0.0; +}; } bool FViewQueryBuilderDirectSourcesTest::RunTest(const FString& Parameters) @@ -33,11 +68,11 @@ bool FViewQueryBuilderDirectSourcesTest::RunTest(const FString& Parameters) TEXT("SELECT * FROM \"nearby_players\" WHERE (\"nearby_players\".\"active\" = TRUE)") ); - FTypedSubscriptionBuilder Typed(nullptr); - Typed.AddQuery([](const FQueryBuilder& Query) + USubscriptionBuilder* Builder = NewObject(); + Builder->AddQuery([](const FQueryBuilder& Query) { return Query.From.MyPlayer(); - }).AddQuery([](const FQueryBuilder& Query) + })->AddQuery([](const FQueryBuilder& Query) { return Query.From.PlayersAtLevel0().Where([](const FPlayersAtLevel0Cols& Cols) { @@ -63,3 +98,97 @@ bool FViewSubscribeAllTablesTest::RunTest(const FString& Parameters) return true; } + +bool FViewBlueprintQueryBuilderFlowTest::RunTest(const FString& Parameters) +{ + FNearbyPlayersQuery Query = UQueryBuilderBlueprintLibrary::FromNearbyPlayers(); + TestEqual(TEXT("blueprint nearby players base sql"), Query.Sql, TEXT("SELECT * FROM \"nearby_players\"")); + + const FBlueprintPredicate Active = UQueryBuilderBlueprintLibrary::BoolEqual( + UQueryBuilderBlueprintLibrary::NearbyPlayersActive(Query), + true); + const FBlueprintPredicate MinX = UQueryBuilderBlueprintLibrary::Int32GreaterEqual( + UQueryBuilderBlueprintLibrary::NearbyPlayersX(Query), + 0); + Query = UQueryBuilderBlueprintLibrary::NearbyPlayersWhere( + Query, + UQueryBuilderBlueprintLibrary::And(Active, MinX)); + TestEqual( + TEXT("blueprint nearby players filtered sql"), + Query.Sql, + TEXT("SELECT * FROM \"nearby_players\" WHERE ((\"nearby_players\".\"active\" = TRUE) AND (\"nearby_players\".\"x\" >= 0))") + ); + + USubscriptionBuilder* Builder = NewObject(); + USubscriptionHandle* Handle = Builder->AddNearbyPlayersQuery(Query)->Subscribe(); + TestNotNull(TEXT("blueprint nearby players handle"), Handle); + TestEqual(TEXT("blueprint nearby players builder sql count"), Handle->GetQuerySqls().Num(), 1); + TestEqual(TEXT("blueprint nearby players builder sql"), Handle->GetQuerySqls()[0], Query.Sql); + + return true; +} + +bool FViewBlueprintQueryBuilderRuntimeTest::RunTest(const FString& Parameters) +{ + const FString RuntimeTestName = TEXT("ViewBlueprintQueryBuilderRuntime"); + + if (!ValidateParameterConfig(this)) + { + return false; + } + + UViewBlueprintRuntimeHandler* Handler = CreateTestHandler(); + Handler->Counter->Register(TEXT("subscription_applied")); + Handler->Counter->Register(TEXT("players_at_level_0_insert")); + + ConnectThen(Handler->Counter, RuntimeTestName, [this, Handler](UDbConnection* Conn) + { + Conn->Db->PlayersAtLevel0->OnInsert.AddDynamic(Handler, &UViewBlueprintRuntimeHandler::OnPlayersAtLevel0Insert); + Conn->Db->PlayersAtLevel0->OnUpdate.AddDynamic(Handler, &UViewBlueprintRuntimeHandler::OnPlayersAtLevel0Update); + Conn->Db->PlayersAtLevel0->OnDelete.AddDynamic(Handler, &UViewBlueprintRuntimeHandler::OnPlayersAtLevel0Delete); + + UTestHelperDelegates* SubHelper = NewObject(); + SubHelper->AddToRoot(); + + SubHelper->OnSubscriptionApplied = [this, Handler, Conn](FSubscriptionEventContext Ctx) + { + if (Conn->Db->PlayersAtLevel0->Count() != 0) + { + Handler->Counter->MarkFailure(TEXT("subscription_applied"), TEXT("Expected empty players_at_level_0 cache before reducers")); + Handler->Counter->Abort(); + return; + } + + Handler->Counter->MarkSuccess(TEXT("subscription_applied")); + Ctx.Reducers->InsertPlayer(Handler->ExpectedIdentity, static_cast(0)); + }; + + SubHelper->OnSubscriptionError = [Handler](FErrorContext Ctx) + { + Handler->Counter->MarkFailure(TEXT("subscription_applied"), FString::Printf(TEXT("Subscription error: %s"), *Ctx.Error)); + Handler->Counter->Abort(); + }; + + FOnSubscriptionApplied AppliedDelegate; + BIND_DELEGATE_SAFE(AppliedDelegate, SubHelper, UTestHelperDelegates, HandleSubscriptionApplied); + + FOnSubscriptionError ErrorDelegate; + BIND_DELEGATE_SAFE(ErrorDelegate, SubHelper, UTestHelperDelegates, HandleSubscriptionError); + + FPlayersAtLevel0Query Query = UQueryBuilderBlueprintLibrary::FromPlayersAtLevel0(); + Query = UQueryBuilderBlueprintLibrary::PlayersAtLevel0Where( + Query, + UQueryBuilderBlueprintLibrary::IdentityEqual( + UQueryBuilderBlueprintLibrary::PlayersAtLevel0Identity(Query), + Handler->ExpectedIdentity)); + + Conn->SubscriptionBuilder() + ->OnApplied(AppliedDelegate) + ->OnError(ErrorDelegate) + ->AddPlayersAtLevel0Query(Query) + ->Subscribe(); + }); + + ADD_LATENT_AUTOMATION_COMMAND(FWaitForTestCounter(*this, RuntimeTestName, Handler->Counter, FPlatformTime::Seconds())); + return true; +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/TestHandler.cpp b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/TestHandler.cpp index 93b59cedf91..d1b8da42646 100644 --- a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/TestHandler.cpp +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Private/Tests/TestHandler.cpp @@ -1 +1,25 @@ #include "Tests/TestHandler.h" + +void UViewBlueprintRuntimeHandler::OnPlayersAtLevel0Insert(const FEventContext&, const FPlayerType& Value) +{ + if (Value.Identity != ExpectedIdentity) + { + Counter->MarkFailure(TEXT("players_at_level_0_insert"), FString::Printf(TEXT("Unexpected identity %s"), *Value.Identity.ToHex())); + Counter->Abort(); + return; + } + + Counter->MarkSuccess(TEXT("players_at_level_0_insert")); +} + +void UViewBlueprintRuntimeHandler::OnPlayersAtLevel0Update(const FEventContext&, const FPlayerType&, const FPlayerType&) +{ + Counter->MarkFailure(TEXT("players_at_level_0_insert"), TEXT("Unexpected update for players_at_level_0")); + Counter->Abort(); +} + +void UViewBlueprintRuntimeHandler::OnPlayersAtLevel0Delete(const FEventContext&, const FPlayerType&) +{ + Counter->MarkFailure(TEXT("players_at_level_0_insert"), TEXT("Unexpected delete for players_at_level_0")); + Counter->Abort(); +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/SpacetimeDBClient.g.h index 63cac5c2734..d800da278c7 100644 --- a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -937,32 +937,829 @@ struct TESTVIEWCLIENT_API FQueryBuilder } }; -struct TESTVIEWCLIENT_API FTypedSubscriptionBuilder +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintQuery { - explicit FTypedSubscriptionBuilder(UDbConnection* InConn) - : Conn(InConn) {} + GENERATED_BODY() - FTypedSubscriptionBuilder& OnApplied(FOnSubscriptionApplied Callback); - FTypedSubscriptionBuilder& OnError(FOnSubscriptionError Callback); + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; - template - FTypedSubscriptionBuilder& AddQuery(TFn&& Build) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintPredicate +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FMyPlayerQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FMyPlayerAndLevelQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FNearbyPlayersQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FPlayerQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FPlayerLevelQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FPlayersAtLevel0Query +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintBoolColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintUInt8Column +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintInt32Column +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintInt64Column +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintFloatColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintDoubleColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintStringColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintIdentityColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintConnectionIdColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintTimestampColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWCLIENT_API FBlueprintUuidColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +UCLASS(BlueprintType) +class TESTVIEWCLIENT_API UQueryBuilderBlueprintLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|MyPlayer", meta=(DisplayName="From MyPlayer")) + static FMyPlayerQuery FromMyPlayer() { - FQueryBuilder Q; - auto Query = std::forward(Build)(Q); - static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn, - "Typed subscription queries must return a query_builder table/query expression."); - Sql.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str()))); - return *this; + FMyPlayerQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.MyPlayer().into_sql().c_str())); + Query.ResultSourceName = TEXT("my_player"); + return Query; } - USubscriptionHandle* Subscribe(); + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|MyPlayer", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_MyPlayerQueryToBlueprintQuery(const FMyPlayerQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|MyPlayer|Columns", meta=(DisplayName="MyPlayer Identity")) + static FBlueprintIdentityColumn MyPlayerIdentity(const FMyPlayerQuery& Query) + { + FBlueprintIdentityColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("my_player") : Query.ResultSourceName; + Column.ColumnName = TEXT("identity"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|MyPlayer", meta=(DisplayName="MyPlayer Where")) + static FMyPlayerQuery MyPlayerWhere(FMyPlayerQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|MyPlayerAndLevel", meta=(DisplayName="From MyPlayerAndLevel")) + static FMyPlayerAndLevelQuery FromMyPlayerAndLevel() + { + FMyPlayerAndLevelQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.MyPlayerAndLevel().into_sql().c_str())); + Query.ResultSourceName = TEXT("my_player_and_level"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|MyPlayerAndLevel", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_MyPlayerAndLevelQueryToBlueprintQuery(const FMyPlayerAndLevelQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|MyPlayerAndLevel|Columns", meta=(DisplayName="MyPlayerAndLevel Identity")) + static FBlueprintIdentityColumn MyPlayerAndLevelIdentity(const FMyPlayerAndLevelQuery& Query) + { + FBlueprintIdentityColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("my_player_and_level") : Query.ResultSourceName; + Column.ColumnName = TEXT("identity"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|MyPlayerAndLevel", meta=(DisplayName="MyPlayerAndLevel Where")) + static FMyPlayerAndLevelQuery MyPlayerAndLevelWhere(FMyPlayerAndLevelQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|NearbyPlayers", meta=(DisplayName="From NearbyPlayers")) + static FNearbyPlayersQuery FromNearbyPlayers() + { + FNearbyPlayersQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.NearbyPlayers().into_sql().c_str())); + Query.ResultSourceName = TEXT("nearby_players"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|NearbyPlayers", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_NearbyPlayersQueryToBlueprintQuery(const FNearbyPlayersQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|NearbyPlayers|Columns", meta=(DisplayName="NearbyPlayers Active")) + static FBlueprintBoolColumn NearbyPlayersActive(const FNearbyPlayersQuery& Query) + { + FBlueprintBoolColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("nearby_players") : Query.ResultSourceName; + Column.ColumnName = TEXT("active"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|NearbyPlayers|Columns", meta=(DisplayName="NearbyPlayers X")) + static FBlueprintInt32Column NearbyPlayersX(const FNearbyPlayersQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("nearby_players") : Query.ResultSourceName; + Column.ColumnName = TEXT("x"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|NearbyPlayers|Columns", meta=(DisplayName="NearbyPlayers Y")) + static FBlueprintInt32Column NearbyPlayersY(const FNearbyPlayersQuery& Query) + { + FBlueprintInt32Column Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("nearby_players") : Query.ResultSourceName; + Column.ColumnName = TEXT("y"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|NearbyPlayers", meta=(DisplayName="NearbyPlayers Where")) + static FNearbyPlayersQuery NearbyPlayersWhere(FNearbyPlayersQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Player", meta=(DisplayName="From Player")) + static FPlayerQuery FromPlayer() + { + FPlayerQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.Player().into_sql().c_str())); + Query.ResultSourceName = TEXT("player"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Player", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PlayerQueryToBlueprintQuery(const FPlayerQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Player|Columns", meta=(DisplayName="Player Identity")) + static FBlueprintIdentityColumn PlayerIdentity(const FPlayerQuery& Query) + { + FBlueprintIdentityColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("player") : Query.ResultSourceName; + Column.ColumnName = TEXT("identity"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Player", meta=(DisplayName="Player Where")) + static FPlayerQuery PlayerWhere(FPlayerQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PlayerLevel", meta=(DisplayName="From PlayerLevel")) + static FPlayerLevelQuery FromPlayerLevel() + { + FPlayerLevelQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PlayerLevel().into_sql().c_str())); + Query.ResultSourceName = TEXT("player_level"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PlayerLevel", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PlayerLevelQueryToBlueprintQuery(const FPlayerLevelQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PlayerLevel", meta=(DisplayName="PlayerLevel Where")) + static FPlayerLevelQuery PlayerLevelWhere(FPlayerLevelQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PlayersAtLevel0", meta=(DisplayName="From PlayersAtLevel0")) + static FPlayersAtLevel0Query FromPlayersAtLevel0() + { + FPlayersAtLevel0Query Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.PlayersAtLevel0().into_sql().c_str())); + Query.ResultSourceName = TEXT("players_at_level_0"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PlayersAtLevel0", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_PlayersAtLevel0QueryToBlueprintQuery(const FPlayersAtLevel0Query& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PlayersAtLevel0|Columns", meta=(DisplayName="PlayersAtLevel0 Identity")) + static FBlueprintIdentityColumn PlayersAtLevel0Identity(const FPlayersAtLevel0Query& Query) + { + FBlueprintIdentityColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("players_at_level_0") : Query.ResultSourceName; + Column.ColumnName = TEXT("identity"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|PlayersAtLevel0", meta=(DisplayName="PlayersAtLevel0 Where")) + static FPlayersAtLevel0Query PlayersAtLevel0Where(FPlayersAtLevel0Query Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Bool Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate BoolEqual(const FBlueprintBoolColumn& Column, const bool Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate UInt8Equal(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate UInt8GreaterThan(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate UInt8GreaterEqual(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate UInt8LessThan(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate UInt8LessEqual(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate Int32Equal(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate Int32GreaterThan(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate Int32GreaterEqual(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate Int32LessThan(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate Int32LessEqual(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate Int64Equal(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate Int64GreaterThan(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate Int64GreaterEqual(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate Int64LessThan(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate Int64LessEqual(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate FloatEqual(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate FloatGreaterThan(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate FloatGreaterEqual(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate FloatLessThan(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate FloatLessEqual(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate DoubleEqual(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate DoubleGreaterThan(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate DoubleGreaterEqual(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate DoubleLessThan(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate DoubleLessEqual(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="String Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate StringEqual(const FBlueprintStringColumn& Column, const FString& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Identity Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate IdentityEqual(const FBlueprintIdentityColumn& Column, const FSpacetimeDBIdentity& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="ConnectionId Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate ConnectionIdEqual(const FBlueprintConnectionIdColumn& Column, const FSpacetimeDBConnectionId& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate TimestampEqual(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate TimestampGreaterThan(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate TimestampGreaterEqual(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate TimestampLessThan(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate TimestampLessEqual(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Uuid Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate UuidEqual(const FBlueprintUuidColumn& Column, const FSpacetimeDBUuid& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="AND", CompactNodeTitle="AND", Keywords="and &&")) + static FBlueprintPredicate And(const FBlueprintPredicate& A, const FBlueprintPredicate& B) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = A.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("(%s) AND (%s)"), *A.Sql, *B.Sql); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="OR", CompactNodeTitle="OR", Keywords="or ||")) + static FBlueprintPredicate Or(const FBlueprintPredicate& A, const FBlueprintPredicate& B) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = A.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("(%s) OR (%s)"), *A.Sql, *B.Sql); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="NOT", CompactNodeTitle="NOT", Keywords="not !")) + static FBlueprintPredicate Not(const FBlueprintPredicate& A) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = A.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("NOT (%s)"), *A.Sql); + return Predicate; + } private: - UDbConnection* Conn = nullptr; - TArray Sql; - FOnSubscriptionApplied OnAppliedDelegateInternal; - FOnSubscriptionError OnErrorDelegateInternal; + static FString AppendPredicate(const FString& Sql, const FString& Predicate) + { + if (Sql.Contains(TEXT(" WHERE "))) + { + return Sql + TEXT(" AND (") + Predicate + TEXT(")"); + } + return Sql + TEXT(" WHERE (") + Predicate + TEXT(")"); + } }; // SubscriptionBuilder class @@ -980,18 +1777,36 @@ class TESTVIEWCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase USubscriptionBuilder* OnError(FOnSubscriptionError Callback); UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + USubscriptionHandle* Subscribe(); + USubscriptionHandle* Subscribe(const TArray& SQL); template - [[nodiscard]] FTypedSubscriptionBuilder AddQuery(TFn&& Build) + USubscriptionBuilder* AddQuery(TFn&& Build) { - FTypedSubscriptionBuilder Typed(Conn); - Typed.OnApplied(OnAppliedDelegateInternal); - Typed.OnError(OnErrorDelegateInternal); - Typed.AddQuery(std::forward(Build)); - return Typed; + FQueryBuilder Q; + auto Query = std::forward(Build)(Q); + static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn, + "Typed subscription queries must return a query_builder table/query expression."); + PendingSqlQueries.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str()))); + return this; } + UFUNCTION(BlueprintCallable, Category="SpacetimeDB", meta=(DisplayName="AddQuery", ScriptName="AddQuery")) + USubscriptionBuilder* AddBlueprintQuery(const FBlueprintQuery& Query); + + USubscriptionBuilder* AddMyPlayerQuery(const FMyPlayerQuery& Query); + + USubscriptionBuilder* AddMyPlayerAndLevelQuery(const FMyPlayerAndLevelQuery& Query); + + USubscriptionBuilder* AddNearbyPlayersQuery(const FNearbyPlayersQuery& Query); + + USubscriptionBuilder* AddPlayerQuery(const FPlayerQuery& Query); + + USubscriptionBuilder* AddPlayerLevelQuery(const FPlayerLevelQuery& Query); + + USubscriptionBuilder* AddPlayersAtLevel0Query(const FPlayersAtLevel0Query& Query); + /** Convenience for subscribing to all rows from all public sources, including views */ UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") USubscriptionHandle* SubscribeToAllTables(); @@ -1004,6 +1819,9 @@ class TESTVIEWCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBase UPROPERTY() class UDbConnection* Conn; + UPROPERTY() + TArray PendingSqlQueries; + // Delegates stored so Subscribe() can bind forwarding callbacks FOnSubscriptionApplied OnAppliedDelegateInternal; FOnSubscriptionError OnErrorDelegateInternal; diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/CommonTestFunctions.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/CommonTestFunctions.h index 6f70f09beec..8a52c88e03b 100644 --- a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/CommonTestFunctions.h +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/CommonTestFunctions.h @@ -1 +1,74 @@ #pragma once + +#include "CoreMinimal.h" +#include "Misc/AutomationTest.h" +#include "Tests/TestCounter.h" + +#include "Connection/Callback.h" +#include "Connection/Credentials.h" +#include "ModuleBindings/SpacetimeDBClient.g.h" + +#include "CommonTestFunctions.generated.h" + +#define TESTLOG_SUCCESS(Test, Format, ...) \ + do \ + { \ + const FString UserMessage = FString::Printf(Format, ##__VA_ARGS__); \ + const FString LogMessage = FString::Printf(TEXT(" + %s"), *UserMessage); \ + UE_LOG(LogTemp, Log, TEXT("%s"), *LogMessage); \ + Test.AddInfo(LogMessage); \ + } while (false) + +#define TESTLOG_FAIL(Test, Format, ...) \ + do \ + { \ + const FString UserMessage = FString::Printf(Format, ##__VA_ARGS__); \ + const FString LogMessage = FString::Printf(TEXT(" x %s"), *UserMessage); \ + UE_LOG(LogTemp, Error, TEXT("%s"), *LogMessage); \ + Test.AddError(LogMessage); \ + } while (false) + +UCLASS() +class TESTVIEWCLIENT_API UTestHelperDelegates : public UObject +{ + GENERATED_BODY() + +public: + TFunction OnConnect; + UFUNCTION() + void HandleConnect(UDbConnection* Conn, FSpacetimeDBIdentity Identity, const FString& Token); + + TFunction OnConnectError; + UFUNCTION() + void HandleConnectError(UDbConnection* Conn, const FString& Error); + + TFunction OnDisconnect; + UFUNCTION() + void HandleDisconnect(UDbConnection* Conn, const FString& Error); + + TFunction OnSubscriptionApplied; + UFUNCTION() + void HandleSubscriptionApplied(FSubscriptionEventContext Ctx); + + TFunction OnSubscriptionError; + UFUNCTION() + void HandleSubscriptionError(FErrorContext Ctx); +}; + +UDbConnection* ConnectThen( + TSharedPtr Counter, + const FString& TestName, + TFunction Callback); + +bool GetDbName(FString& DBName, FString& Error); +bool ValidateParameterConfig(FAutomationTestBase* Test); +bool ReportTestResult(FAutomationTestBase& Test, const FString& TestName, TSharedPtr Counter, bool bTimedOut); + +template +T* CreateTestHandler() +{ + T* Handler = NewObject(GetTransientPackage()); + Handler->AddToRoot(); + Handler->Counter = MakeShared(); + return Handler; +} diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/SpacetimeFullClientTests.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/SpacetimeFullClientTests.h index 1d0de3fc794..5da4a816e9e 100644 --- a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/SpacetimeFullClientTests.h +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/SpacetimeFullClientTests.h @@ -14,3 +14,15 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( "SpacetimeDB.TestViewClient.ViewSubscribeAllTablesTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter ) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FViewBlueprintQueryBuilderFlowTest, + "SpacetimeDB.TestViewClient.ViewBlueprintQueryBuilderFlowTest", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FViewBlueprintQueryBuilderRuntimeTest, + "SpacetimeDB.TestViewClient.ViewBlueprintQueryBuilderRuntimeTest", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) diff --git a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/TestHandler.h b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/TestHandler.h index 5e8f9ff67bc..ba5eef092cb 100644 --- a/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/TestHandler.h +++ b/sdks/unreal/tests/TestViewClient/Source/TestViewClient/Public/Tests/TestHandler.h @@ -1,3 +1,36 @@ #pragma once -class UTestHandler {}; +#include "CoreMinimal.h" +#include "UObject/Object.h" + +#include "ModuleBindings/SpacetimeDBClient.g.h" +#include "Tests/TestCounter.h" + +#include "TestHandler.generated.h" + +UCLASS() +class TESTVIEWCLIENT_API UTestHandler : public UObject +{ + GENERATED_BODY() + +public: + TSharedPtr Counter; +}; + +UCLASS() +class TESTVIEWCLIENT_API UViewBlueprintRuntimeHandler : public UTestHandler +{ + GENERATED_BODY() + +public: + FSpacetimeDBIdentity ExpectedIdentity = FSpacetimeDBIdentity::FromHex(TEXT("0x1111111111111111111111111111111111111111111111111111111111111111")); + + UFUNCTION() + void OnPlayersAtLevel0Insert(const FEventContext& Context, const FPlayerType& Value); + + UFUNCTION() + void OnPlayersAtLevel0Update(const FEventContext& Context, const FPlayerType& OldValue, const FPlayerType& NewValue); + + UFUNCTION() + void OnPlayersAtLevel0Delete(const FEventContext& Context, const FPlayerType& Value); +}; diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp index 42359ff702c..4e5f435f936 100644 --- a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -425,27 +425,6 @@ USubscriptionBuilder* UDbConnection::SubscriptionBuilder() Builder->Conn = this; return Builder; } -FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) -{ - OnAppliedDelegateInternal = Callback; - return *this; -} -FTypedSubscriptionBuilder& FTypedSubscriptionBuilder::OnError(FOnSubscriptionError Callback) -{ - OnErrorDelegateInternal = Callback; - return *this; -} -USubscriptionHandle* FTypedSubscriptionBuilder::Subscribe() -{ - if (!Conn) - { - return nullptr; - } - USubscriptionBuilder* Builder = Conn->SubscriptionBuilder(); - Builder->OnApplied(OnAppliedDelegateInternal); - Builder->OnError(OnErrorDelegateInternal); - return Builder->Subscribe(Sql); -} USubscriptionBuilder* USubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback) { OnAppliedDelegateInternal = Callback; @@ -456,6 +435,12 @@ USubscriptionBuilder* USubscriptionBuilder::OnError(FOnSubscriptionError Callbac OnErrorDelegateInternal = Callback; return this; } +USubscriptionHandle* USubscriptionBuilder::Subscribe() +{ + const TArray SqlQueries = PendingSqlQueries; + PendingSqlQueries.Empty(); + return Subscribe(SqlQueries); +} USubscriptionHandle* USubscriptionBuilder::Subscribe(const TArray& SQL) { USubscriptionHandle* Handle = NewObject(); @@ -486,6 +471,60 @@ USubscriptionHandle* USubscriptionBuilder::SubscribeToAllTables() return Subscribe(FQueryBuilder::AllTablesSqlQueries()); } +USubscriptionBuilder* USubscriptionBuilder::AddBlueprintQuery(const FBlueprintQuery& Query) +{ + PendingSqlQueries.Add(Query.Sql); + return this; +} + +USubscriptionBuilder* USubscriptionBuilder::AddAllViewPkPlayersQuery(const FAllViewPkPlayersQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddSenderViewPkPlayersAQuery(const FSenderViewPkPlayersAQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddSenderViewPkPlayersBQuery(const FSenderViewPkPlayersBQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddViewPkMembershipQuery(const FViewPkMembershipQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddViewPkMembershipSecondaryQuery(const FViewPkMembershipSecondaryQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + +USubscriptionBuilder* USubscriptionBuilder::AddViewPkPlayerQuery(const FViewPkPlayerQuery& Query) +{ + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return AddBlueprintQuery(GenericQuery); +} + USubscriptionHandle::USubscriptionHandle(UDbConnection* InConn) { Conn = InConn; @@ -566,7 +605,7 @@ void UDbConnection::ForwardOnConnect(UDbConnectionBase* BaseConnection, FSpaceti { if (OnConnectDelegate.IsBound()) { - OnConnectDelegate.Execute(this, Identity, Token); + OnConnectDelegate.Execute(this, InIdentity, InToken); } } void UDbConnection::ForwardOnDisconnect(UDbConnectionBase* BaseConnection, const FString& Error) diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/SpacetimeFullClientTests.cpp b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/SpacetimeFullClientTests.cpp index 6b71fc3e616..da064e154f2 100644 --- a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/SpacetimeFullClientTests.cpp +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Private/Tests/SpacetimeFullClientTests.cpp @@ -80,11 +80,11 @@ bool FViewPkQueryBuilderDirectSourcesTest::RunTest(const FString& Parameters) TEXT("SELECT * FROM \"view_pk_player\"") ); - FTypedSubscriptionBuilder Typed(nullptr); - Typed.AddQuery([](const FQueryBuilder& Query) + USubscriptionBuilder* Builder = NewObject(); + Builder->AddQuery([](const FQueryBuilder& Query) { return Query.From.AllViewPkPlayers(); - }).AddQuery([](const FQueryBuilder& Query) + })->AddQuery([](const FQueryBuilder& Query) { return Query.From.ViewPkPlayer().Where([](const FViewPkPlayerCols& Cols) { @@ -208,13 +208,44 @@ bool FViewPkRuntimeUpdatePairingTest::RunTest(const FString& Parameters) { return Q.From.AllViewPkPlayers(); }) - .AddQuery([](const FQueryBuilder& Q) + ->AddQuery([](const FQueryBuilder& Q) { return Q.From.SenderViewPkPlayersA(); }) - .Subscribe(); + ->Subscribe(); }); ADD_LATENT_AUTOMATION_COMMAND(FWaitForTestCounter(*this, RuntimeTestName, Handler->Counter, FPlatformTime::Seconds())); return true; } + +bool FViewPkBlueprintQueryBuilderFlowTest::RunTest(const FString& Parameters) +{ + FAllViewPkPlayersQuery Query = UQueryBuilderBlueprintLibrary::FromAllViewPkPlayers(); + + TestEqual( + TEXT("blueprint all_view_pk_players base sql"), + Query.Sql, + TEXT("SELECT * FROM \"all_view_pk_players\"") + ); + + Query = UQueryBuilderBlueprintLibrary::AllViewPkPlayersWhere( + Query, + UQueryBuilderBlueprintLibrary::StringEqual( + UQueryBuilderBlueprintLibrary::AllViewPkPlayersName(Query), + TEXT("Alice"))); + TestEqual( + TEXT("blueprint pk view filtered sql"), + Query.Sql, + TEXT("SELECT * FROM \"all_view_pk_players\" WHERE (\"all_view_pk_players\".\"name\" = 'Alice')") + ); + TestEqual(TEXT("blueprint pk view result source"), Query.ResultSourceName, TEXT("all_view_pk_players")); + + USubscriptionBuilder* Builder = NewObject(); + USubscriptionHandle* Handle = Builder->AddAllViewPkPlayersQuery(Query)->Subscribe(); + TestNotNull(TEXT("blueprint pk view handle"), Handle); + TestEqual(TEXT("blueprint pk view builder sql count"), Handle->GetQuerySqls().Num(), 1); + TestEqual(TEXT("blueprint pk view builder sql"), Handle->GetQuerySqls()[0], Query.Sql); + + return true; +} diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/SpacetimeDBClient.g.h index 238733a23f7..fd1e16772c6 100644 --- a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -986,32 +986,802 @@ struct TESTVIEWPKCLIENT_API FQueryBuilder } }; -struct TESTVIEWPKCLIENT_API FTypedSubscriptionBuilder +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintQuery { - explicit FTypedSubscriptionBuilder(UDbConnection* InConn) - : Conn(InConn) {} + GENERATED_BODY() - FTypedSubscriptionBuilder& OnApplied(FOnSubscriptionApplied Callback); - FTypedSubscriptionBuilder& OnError(FOnSubscriptionError Callback); + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; - template - FTypedSubscriptionBuilder& AddQuery(TFn&& Build) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintPredicate +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FAllViewPkPlayersQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FSenderViewPkPlayersAQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FSenderViewPkPlayersBQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FViewPkMembershipQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FViewPkMembershipSecondaryQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FViewPkPlayerQuery +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString Sql; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintBoolColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintUInt8Column +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintInt32Column +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintInt64Column +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintFloatColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintDoubleColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintStringColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintIdentityColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintConnectionIdColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintTimestampColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +USTRUCT(BlueprintType) +struct TESTVIEWPKCLIENT_API FBlueprintUuidColumn +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ResultSourceName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB|Queries") + FString ColumnName; +}; + +UCLASS(BlueprintType) +class TESTVIEWPKCLIENT_API UQueryBuilderBlueprintLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|AllViewPkPlayers", meta=(DisplayName="From AllViewPkPlayers")) + static FAllViewPkPlayersQuery FromAllViewPkPlayers() { - FQueryBuilder Q; - auto Query = std::forward(Build)(Q); - static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn, - "Typed subscription queries must return a query_builder table/query expression."); - Sql.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str()))); - return *this; + FAllViewPkPlayersQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.AllViewPkPlayers().into_sql().c_str())); + Query.ResultSourceName = TEXT("all_view_pk_players"); + return Query; } - USubscriptionHandle* Subscribe(); + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|AllViewPkPlayers", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_AllViewPkPlayersQueryToBlueprintQuery(const FAllViewPkPlayersQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|AllViewPkPlayers|Columns", meta=(DisplayName="AllViewPkPlayers Name")) + static FBlueprintStringColumn AllViewPkPlayersName(const FAllViewPkPlayersQuery& Query) + { + FBlueprintStringColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("all_view_pk_players") : Query.ResultSourceName; + Column.ColumnName = TEXT("name"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|AllViewPkPlayers", meta=(DisplayName="AllViewPkPlayers Where")) + static FAllViewPkPlayersQuery AllViewPkPlayersWhere(FAllViewPkPlayersQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|SenderViewPkPlayersA", meta=(DisplayName="From SenderViewPkPlayersA")) + static FSenderViewPkPlayersAQuery FromSenderViewPkPlayersA() + { + FSenderViewPkPlayersAQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.SenderViewPkPlayersA().into_sql().c_str())); + Query.ResultSourceName = TEXT("sender_view_pk_players_a"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|SenderViewPkPlayersA", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_SenderViewPkPlayersAQueryToBlueprintQuery(const FSenderViewPkPlayersAQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|SenderViewPkPlayersA|Columns", meta=(DisplayName="SenderViewPkPlayersA Name")) + static FBlueprintStringColumn SenderViewPkPlayersAName(const FSenderViewPkPlayersAQuery& Query) + { + FBlueprintStringColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("sender_view_pk_players_a") : Query.ResultSourceName; + Column.ColumnName = TEXT("name"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|SenderViewPkPlayersA", meta=(DisplayName="SenderViewPkPlayersA Where")) + static FSenderViewPkPlayersAQuery SenderViewPkPlayersAWhere(FSenderViewPkPlayersAQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|SenderViewPkPlayersB", meta=(DisplayName="From SenderViewPkPlayersB")) + static FSenderViewPkPlayersBQuery FromSenderViewPkPlayersB() + { + FSenderViewPkPlayersBQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.SenderViewPkPlayersB().into_sql().c_str())); + Query.ResultSourceName = TEXT("sender_view_pk_players_b"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|SenderViewPkPlayersB", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_SenderViewPkPlayersBQueryToBlueprintQuery(const FSenderViewPkPlayersBQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|SenderViewPkPlayersB|Columns", meta=(DisplayName="SenderViewPkPlayersB Name")) + static FBlueprintStringColumn SenderViewPkPlayersBName(const FSenderViewPkPlayersBQuery& Query) + { + FBlueprintStringColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("sender_view_pk_players_b") : Query.ResultSourceName; + Column.ColumnName = TEXT("name"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|SenderViewPkPlayersB", meta=(DisplayName="SenderViewPkPlayersB Where")) + static FSenderViewPkPlayersBQuery SenderViewPkPlayersBWhere(FSenderViewPkPlayersBQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ViewPkMembership", meta=(DisplayName="From ViewPkMembership")) + static FViewPkMembershipQuery FromViewPkMembership() + { + FViewPkMembershipQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.ViewPkMembership().into_sql().c_str())); + Query.ResultSourceName = TEXT("view_pk_membership"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ViewPkMembership", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_ViewPkMembershipQueryToBlueprintQuery(const FViewPkMembershipQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ViewPkMembership", meta=(DisplayName="ViewPkMembership Where")) + static FViewPkMembershipQuery ViewPkMembershipWhere(FViewPkMembershipQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ViewPkMembershipSecondary", meta=(DisplayName="From ViewPkMembershipSecondary")) + static FViewPkMembershipSecondaryQuery FromViewPkMembershipSecondary() + { + FViewPkMembershipSecondaryQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.ViewPkMembershipSecondary().into_sql().c_str())); + Query.ResultSourceName = TEXT("view_pk_membership_secondary"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ViewPkMembershipSecondary", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_ViewPkMembershipSecondaryQueryToBlueprintQuery(const FViewPkMembershipSecondaryQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ViewPkMembershipSecondary", meta=(DisplayName="ViewPkMembershipSecondary Where")) + static FViewPkMembershipSecondaryQuery ViewPkMembershipSecondaryWhere(FViewPkMembershipSecondaryQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ViewPkPlayer", meta=(DisplayName="From ViewPkPlayer")) + static FViewPkPlayerQuery FromViewPkPlayer() + { + FViewPkPlayerQuery Query; + Query.Sql = FString(UTF8_TO_TCHAR(FQueryBuilder().From.ViewPkPlayer().into_sql().c_str())); + Query.ResultSourceName = TEXT("view_pk_player"); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ViewPkPlayer", meta=(DisplayName="To Query", BlueprintAutocast)) + static FBlueprintQuery Conv_ViewPkPlayerQueryToBlueprintQuery(const FViewPkPlayerQuery& Query) + { + FBlueprintQuery GenericQuery; + GenericQuery.Sql = Query.Sql; + GenericQuery.ResultSourceName = Query.ResultSourceName; + return GenericQuery; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ViewPkPlayer|Columns", meta=(DisplayName="ViewPkPlayer Name")) + static FBlueprintStringColumn ViewPkPlayerName(const FViewPkPlayerQuery& Query) + { + FBlueprintStringColumn Column; + Column.ResultSourceName = Query.ResultSourceName.IsEmpty() ? TEXT("view_pk_player") : Query.ResultSourceName; + Column.ColumnName = TEXT("name"); + return Column; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|ViewPkPlayer", meta=(DisplayName="ViewPkPlayer Where")) + static FViewPkPlayerQuery ViewPkPlayerWhere(FViewPkPlayerQuery Query, const FBlueprintPredicate& Predicate) + { + if (Query.ResultSourceName != Predicate.ResultSourceName || Predicate.Sql.IsEmpty()) + { + return Query; + } + Query.Sql = AppendPredicate(Query.Sql, Predicate.Sql); + return Query; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Bool Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate BoolEqual(const FBlueprintBoolColumn& Column, const bool Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate UInt8Equal(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate UInt8GreaterThan(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate UInt8GreaterEqual(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate UInt8LessThan(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="UInt8 Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate UInt8LessEqual(const FBlueprintUInt8Column& Column, const uint8 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate Int32Equal(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate Int32GreaterThan(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate Int32GreaterEqual(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate Int32LessThan(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int32 Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate Int32LessEqual(const FBlueprintInt32Column& Column, const int32 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate Int64Equal(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate Int64GreaterThan(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate Int64GreaterEqual(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate Int64LessThan(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Int64 Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate Int64LessEqual(const FBlueprintInt64Column& Column, const int64 Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate FloatEqual(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate FloatGreaterThan(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate FloatGreaterEqual(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate FloatLessThan(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Float Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate FloatLessEqual(const FBlueprintFloatColumn& Column, const float Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate DoubleEqual(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate DoubleGreaterThan(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate DoubleGreaterEqual(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate DoubleLessThan(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Double Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate DoubleLessEqual(const FBlueprintDoubleColumn& Column, const double Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="String Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate StringEqual(const FBlueprintStringColumn& Column, const FString& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Identity Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate IdentityEqual(const FBlueprintIdentityColumn& Column, const FSpacetimeDBIdentity& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="ConnectionId Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate ConnectionIdEqual(const FBlueprintConnectionIdColumn& Column, const FSpacetimeDBConnectionId& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate TimestampEqual(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Greater Than", CompactNodeTitle=">", Keywords="> greater")) + static FBlueprintPredicate TimestampGreaterThan(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" > %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Greater Equal", CompactNodeTitle=">=", Keywords=">= greater equal")) + static FBlueprintPredicate TimestampGreaterEqual(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" >= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Less Than", CompactNodeTitle="<", Keywords="< less")) + static FBlueprintPredicate TimestampLessThan(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" < %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Timestamp Less Equal", CompactNodeTitle="<=", Keywords="<= less equal")) + static FBlueprintPredicate TimestampLessEqual(const FBlueprintTimestampColumn& Column, const FSpacetimeDBTimestamp& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" <= %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="Uuid Equal", CompactNodeTitle="==", Keywords="== equal")) + static FBlueprintPredicate UuidEqual(const FBlueprintUuidColumn& Column, const FSpacetimeDBUuid& Value) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = Column.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("\"%s\".\"%s\" = %s"), *Column.ResultSourceName, *Column.ColumnName, UTF8_TO_TCHAR(::SpacetimeDB::query_builder::detail::literal_sql(Value).c_str())); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="AND", CompactNodeTitle="AND", Keywords="and &&")) + static FBlueprintPredicate And(const FBlueprintPredicate& A, const FBlueprintPredicate& B) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = A.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("(%s) AND (%s)"), *A.Sql, *B.Sql); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="OR", CompactNodeTitle="OR", Keywords="or ||")) + static FBlueprintPredicate Or(const FBlueprintPredicate& A, const FBlueprintPredicate& B) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = A.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("(%s) OR (%s)"), *A.Sql, *B.Sql); + return Predicate; + } + + UFUNCTION(BlueprintPure, Category="SpacetimeDB|Queries|Predicates", meta=(DisplayName="NOT", CompactNodeTitle="NOT", Keywords="not !")) + static FBlueprintPredicate Not(const FBlueprintPredicate& A) + { + FBlueprintPredicate Predicate; + Predicate.ResultSourceName = A.ResultSourceName; + Predicate.Sql = FString::Printf(TEXT("NOT (%s)"), *A.Sql); + return Predicate; + } private: - UDbConnection* Conn = nullptr; - TArray Sql; - FOnSubscriptionApplied OnAppliedDelegateInternal; - FOnSubscriptionError OnErrorDelegateInternal; + static FString AppendPredicate(const FString& Sql, const FString& Predicate) + { + if (Sql.Contains(TEXT(" WHERE "))) + { + return Sql + TEXT(" AND (") + Predicate + TEXT(")"); + } + return Sql + TEXT(" WHERE (") + Predicate + TEXT(")"); + } }; // SubscriptionBuilder class @@ -1029,18 +1799,36 @@ class TESTVIEWPKCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBas USubscriptionBuilder* OnError(FOnSubscriptionError Callback); UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + USubscriptionHandle* Subscribe(); + USubscriptionHandle* Subscribe(const TArray& SQL); template - [[nodiscard]] FTypedSubscriptionBuilder AddQuery(TFn&& Build) + USubscriptionBuilder* AddQuery(TFn&& Build) { - FTypedSubscriptionBuilder Typed(Conn); - Typed.OnApplied(OnAppliedDelegateInternal); - Typed.OnError(OnErrorDelegateInternal); - Typed.AddQuery(std::forward(Build)); - return Typed; + FQueryBuilder Q; + auto Query = std::forward(Build)(Q); + static_assert(::SpacetimeDB::query_builder::QueryBuilderReturn, + "Typed subscription queries must return a query_builder table/query expression."); + PendingSqlQueries.Add(FString(UTF8_TO_TCHAR(Query.into_sql().c_str()))); + return this; } + UFUNCTION(BlueprintCallable, Category="SpacetimeDB", meta=(DisplayName="AddQuery", ScriptName="AddQuery")) + USubscriptionBuilder* AddBlueprintQuery(const FBlueprintQuery& Query); + + USubscriptionBuilder* AddAllViewPkPlayersQuery(const FAllViewPkPlayersQuery& Query); + + USubscriptionBuilder* AddSenderViewPkPlayersAQuery(const FSenderViewPkPlayersAQuery& Query); + + USubscriptionBuilder* AddSenderViewPkPlayersBQuery(const FSenderViewPkPlayersBQuery& Query); + + USubscriptionBuilder* AddViewPkMembershipQuery(const FViewPkMembershipQuery& Query); + + USubscriptionBuilder* AddViewPkMembershipSecondaryQuery(const FViewPkMembershipSecondaryQuery& Query); + + USubscriptionBuilder* AddViewPkPlayerQuery(const FViewPkPlayerQuery& Query); + /** Convenience for subscribing to all rows from all public sources, including views */ UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") USubscriptionHandle* SubscribeToAllTables(); @@ -1053,6 +1841,9 @@ class TESTVIEWPKCLIENT_API USubscriptionBuilder : public USubscriptionBuilderBas UPROPERTY() class UDbConnection* Conn; + UPROPERTY() + TArray PendingSqlQueries; + // Delegates stored so Subscribe() can bind forwarding callbacks FOnSubscriptionApplied OnAppliedDelegateInternal; FOnSubscriptionError OnErrorDelegateInternal; diff --git a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/SpacetimeFullClientTests.h b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/SpacetimeFullClientTests.h index 884dc30efa9..c957be034b4 100644 --- a/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/SpacetimeFullClientTests.h +++ b/sdks/unreal/tests/TestViewPkClient/Source/TestViewPkClient/Public/Tests/SpacetimeFullClientTests.h @@ -27,3 +27,9 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( "SpacetimeDB.TestViewPkClient.ViewPkRuntimeUpdatePairingTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter ) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FViewPkBlueprintQueryBuilderFlowTest, + "SpacetimeDB.TestViewPkClient.ViewPkBlueprintQueryBuilderFlowTest", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) diff --git a/sdks/unreal/tests/test.rs b/sdks/unreal/tests/test.rs index 2700f10ec14..b92696b01b2 100644 --- a/sdks/unreal/tests/test.rs +++ b/sdks/unreal/tests/test.rs @@ -309,3 +309,9 @@ fn unreal_overlapping_subscriptions() { fn unreal_insert_result_okay() { make_test("InsertResultOkTest").run(); } + +#[test] +#[serial(Group6)] +fn unreal_blueprint_query_builder_basic_flow() { + make_test("BlueprintQueryBuilderBasicFlowTest").run(); +} diff --git a/sdks/unreal/tests/test_view.rs b/sdks/unreal/tests/test_view.rs index e0863669e5f..5df4d2d4dab 100644 --- a/sdks/unreal/tests/test_view.rs +++ b/sdks/unreal/tests/test_view.rs @@ -26,3 +26,15 @@ fn unreal_view_query_builder_direct_sources() { fn unreal_view_subscribe_all_tables() { make_test("ViewSubscribeAllTablesTest").run(); } + +#[test] +#[serial(ViewGroup)] +fn unreal_view_blueprint_query_builder_flow() { + make_test("ViewBlueprintQueryBuilderFlowTest").run(); +} + +#[test] +#[serial(ViewGroup)] +fn unreal_view_blueprint_query_builder_runtime() { + make_test("ViewBlueprintQueryBuilderRuntimeTest").run(); +} diff --git a/sdks/unreal/tests/test_view_pk.rs b/sdks/unreal/tests/test_view_pk.rs index 665d8113cf2..5a78abcb7d1 100644 --- a/sdks/unreal/tests/test_view_pk.rs +++ b/sdks/unreal/tests/test_view_pk.rs @@ -38,3 +38,9 @@ fn unreal_view_pk_subscribe_all_tables() { fn unreal_view_pk_runtime_update_pairing() { make_test("ViewPkRuntimeUpdatePairingTest").run(); } + +#[test] +#[serial(ViewPkGroup)] +fn unreal_view_pk_blueprint_query_builder_flow() { + make_test("ViewPkBlueprintQueryBuilderFlowTest").run(); +} From 9512fb79daf50318f3248363da11a6bf6db2f596 Mon Sep 17 00:00:00 2001 From: Jason Larabie Date: Wed, 15 Apr 2026 07:26:00 -0700 Subject: [PATCH 4/4] Updated core query builder to match with the C++ core and added documentation --- .../00400-subscriptions.md | 166 +++++++++++++++- .../00600-clients/00800-unreal-reference.md | 177 +++++++++++++++++- .../00100-how-to/00600-migrating-to-2.0.md | 24 ++- .../ue-blueprint-group-subscriptions.png | Bin 0 -> 241827 bytes .../ue-blueprint-quick-start.png | Bin 0 -> 327997 bytes .../ue-blueprint-unsubscription-1.png | Bin 0 -> 153093 bytes .../ue-blueprint-unsubscription-2.png | Bin 0 -> 216571 bytes .../SpacetimeDbSdk/Public/QueryBuilder/expr.h | 46 +---- .../QueryBuilder/expr_unreal_adapters.h | 51 +++++ .../SpacetimeDbSdk/Public/QueryBuilder/join.h | 8 +- .../Public/QueryBuilder/query_builder.h | 76 ++++++++ .../Public/QueryBuilder/table.h | 55 ++++-- .../Types/EnumWithPayloadType.g.h | 4 +- .../ModuleBindings/Types/ReturnEnumType.g.h | 2 +- 14 files changed, 529 insertions(+), 80 deletions(-) create mode 100644 docs/static/images/unreal/subscriptions/ue-blueprint-group-subscriptions.png create mode 100644 docs/static/images/unreal/subscriptions/ue-blueprint-quick-start.png create mode 100644 docs/static/images/unreal/subscriptions/ue-blueprint-unsubscription-1.png create mode 100644 docs/static/images/unreal/subscriptions/ue-blueprint-unsubscription-2.png create mode 100644 sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr_unreal_adapters.h diff --git a/docs/docs/00200-core-concepts/00400-subscriptions.md b/docs/docs/00200-core-concepts/00400-subscriptions.md index 04f84d9e9bd..18d4f6fc6b6 100644 --- a/docs/docs/00200-core-concepts/00400-subscriptions.md +++ b/docs/docs/00200-core-concepts/00400-subscriptions.md @@ -139,11 +139,69 @@ conn.db().user().on_update(|ctx, old_user, new_user| { }); ``` + + + +```cpp +// Connect to the database +FOnConnectDelegate ConnectDelegate; +BIND_DELEGATE_SAFE(ConnectDelegate, this, AMyActor, OnConnected); + +Conn = UDbConnection::Builder() + ->WithUri(TEXT("wss://maincloud.spacetimedb.com")) + ->WithDatabaseName(TEXT("my_module")) + ->OnConnect(ConnectDelegate) + ->Build(); + +// React to new rows being inserted +Conn->Db->User->OnInsert.AddDynamic(this, &AMyActor::OnUserInsert); + +// React to rows being deleted +Conn->Db->User->OnDelete.AddDynamic(this, &AMyActor::OnUserDelete); + +// React to rows being updated +Conn->Db->User->OnUpdate.AddDynamic(this, &AMyActor::OnUserUpdate); + +void AMyActor::OnConnected(UDbConnection* Connection, FSpacetimeDBIdentity Identity, const FString& Token) +{ + FOnSubscriptionApplied SubscriptionAppliedDelegate; + BIND_DELEGATE_SAFE(SubscriptionAppliedDelegate, this, AMyActor, OnSubscriptionApplied); + + Connection->SubscriptionBuilder() + ->OnApplied(SubscriptionAppliedDelegate) + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.User(); + }) + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.Message(); + }) + ->Subscribe(); +} + +void AMyActor::OnSubscriptionApplied(const FSubscriptionEventContext& Context) +{ + UE_LOG(LogTemp, Log, TEXT("Subscription ready!")); + + // Initial data is now in the client cache + for (const FUserType& User : Context.Db->User->Iter()) + { + UE_LOG(LogTemp, Log, TEXT("User: %s"), *User.Name); + } +} +``` + + + + +![Unreal Blueprint quick start subscription graph](/images/unreal/subscriptions/ue-blueprint-quick-start.png) + :::tip Typed Query Builders -Type-safe query builders are available in TypeScript, C#, and Rust and are the recommended default. They provide auto-completion and compile-time type checking. For complete API details, see [TypeScript](./00600-clients/00700-typescript-reference.md#query-builder-api), [C#](./00600-clients/00600-csharp-reference.md#query-builder-api), and [Rust](./00600-clients/00500-rust-reference.md#query-builder-api) references. +Type-safe query builders are available in TypeScript, C#, Rust, and Unreal and are the recommended default. They provide auto-completion and compile-time type checking. For complete API details, see [TypeScript](./00600-clients/00700-typescript-reference.md#query-builder-api), [C#](./00600-clients/00600-csharp-reference.md#query-builder-api), [Rust](./00600-clients/00500-rust-reference.md#query-builder-api), and [Unreal](./00600-clients/00800-unreal-reference.md#query-builder-api) references. ::: ## How Subscriptions Work @@ -169,16 +227,20 @@ All SDKs expose a builder API for creating subscriptions: - Register an error callback: runs if subscription registration fails or a subscription later terminates with an error. - Subscribe with one or more queries. +In Unreal, inspect the initial subscribed data set in `OnApplied`. Use table callbacks like `OnInsert`, `OnDelete`, and `OnUpdate` for later live changes. + ### Query Forms -All SDKs support subscriptions. TypeScript, C#, and Rust support query builders (recommended), while Unreal uses query strings: +All SDKs support subscriptions. Query builders are the recommended default across SDKs, with raw SQL available where needed: | SDK | Typed Query Builder Support | Entry Point | | --- | --- | --- | | TypeScript | Yes | `tables..where(...)` passed to `subscribe(...)` | | C# | Yes | `SubscriptionBuilder.AddQuery(...).Subscribe()` | | Rust | Yes | `subscription_builder().add_query(...).subscribe()` | -| Unreal | No | Query strings passed to `Subscribe(...)` | +| Unreal | Yes | `SubscriptionBuilder.AddQuery(...).Subscribe()` | + +Unreal also supports raw SQL subscriptions through `Subscribe(const TArray& SQL)` when you need direct SQL control. ### Subscription Handles @@ -198,6 +260,7 @@ Subscribing returns a handle that manages an individual subscription lifecycle. - [Rust subscription API](./00600-clients/00500-rust-reference.md#subscribe-to-queries) - [Rust query builder API](./00600-clients/00500-rust-reference.md#query-builder-api) - [Unreal subscription API](./00600-clients/00800-unreal-reference.md#subscriptions) +- [Unreal query builder API](./00600-clients/00800-unreal-reference.md#query-builder-api) ## Best Practices for Optimizing Server Compute and Reducing Serialization Overhead @@ -265,7 +328,7 @@ var globalSubscriptions = conn // May unsubscribe to shop_items as player advances var shopSubscription = conn .SubscriptionBuilder() - .AddQuery(q => q.From.ShopItems().Where(r => r.RequiredLevel.Lte(5U))) + .AddQuery(q => q.From.ShopItems().Where(r => r.RequiredLevel.Lte(5))) .Subscribe(); ``` @@ -285,10 +348,45 @@ let global_subscriptions = conn // May unsubscribe to shop_items as player advances let shop_subscription = conn .subscription_builder() - .add_query(|q| q.from.shop_items().r#where(|r| r.required_level.lte(5u32))) + .add_query(|q| q.from.shop_items().r#where(|r| r.required_level.lte(5))) .subscribe(); ``` + + + +```cpp +UDbConnection* Conn = ConnectToDB(); + +// Never need to unsubscribe from global subscriptions +USubscriptionHandle* GlobalSubscriptions = Conn->SubscriptionBuilder() + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.Announcements(); + }) + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.Badges(); + }) + ->Subscribe(); + +// May unsubscribe from ShopItems as player advances +USubscriptionHandle* ShopSubscription = Conn->SubscriptionBuilder() + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.ShopItems().Where([](const FShopItemsCols& Row) + { + return Row.RequiredLevel.Lte(5); + }); + }) + ->Subscribe(); +``` + + + + +![Unreal Blueprint grouped subscriptions graph](/images/unreal/subscriptions/ue-blueprint-group-subscriptions.png) + @@ -349,14 +447,14 @@ var conn = ConnectToDB(); var shopSubscription = conn .SubscriptionBuilder() .AddQuery(q => q.From.ExchangeRates()) - .AddQuery(q => q.From.ShopItems().Where(r => r.RequiredLevel.Lte(5U))) + .AddQuery(q => q.From.ShopItems().Where(r => r.RequiredLevel.Lte(5))) .Subscribe(); // New subscription: player now at level 6, which overlaps with the previous query. var newShopSubscription = conn .SubscriptionBuilder() .AddQuery(q => q.From.ExchangeRates()) - .AddQuery(q => q.From.ShopItems().Where(r => r.RequiredLevel.Lte(6U))) + .AddQuery(q => q.From.ShopItems().Where(r => r.RequiredLevel.Lte(6))) .Subscribe(); // Unsubscribe from the old subscription once the new one is in place. @@ -376,14 +474,14 @@ let conn: DbConnection = connect_to_db(); let shop_subscription = conn .subscription_builder() .add_query(|q| q.from.exchange_rates()) - .add_query(|q| q.from.shop_items().r#where(|r| r.required_level.lte(5u32))) + .add_query(|q| q.from.shop_items().r#where(|r| r.required_level.lte(5))) .subscribe(); // New subscription: player now at level 6, which overlaps with the previous query. let new_shop_subscription = conn .subscription_builder() .add_query(|q| q.from.exchange_rates()) - .add_query(|q| q.from.shop_items().r#where(|r| r.required_level.lte(6u32))) + .add_query(|q| q.from.shop_items().r#where(|r| r.required_level.lte(6))) .subscribe(); // Unsubscribe from the old subscription once the new one is active. @@ -392,6 +490,56 @@ if shop_subscription.is_active() { } ``` + + + +```cpp +UDbConnection* Conn = ConnectToDB(); + +// Initial subscription: player at level 5. +USubscriptionHandle* ShopSubscription = Conn->SubscriptionBuilder() + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.ExchangeRates(); + }) + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.ShopItems().Where([](const FShopItemsCols& Row) + { + return Row.RequiredLevel.Lte(5); + }); + }) + ->Subscribe(); + +// New subscription: player now at level 6, which overlaps with the previous query. +USubscriptionHandle* NewShopSubscription = Conn->SubscriptionBuilder() + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.ExchangeRates(); + }) + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.ShopItems().Where([](const FShopItemsCols& Row) + { + return Row.RequiredLevel.Lte(6); + }); + }) + ->Subscribe(); + +// Unsubscribe from the old subscription once the new one is in place. +if (ShopSubscription->IsActive()) +{ + ShopSubscription->Unsubscribe(); +} +``` + + + + +![Unreal Blueprint new overlapping subscription graph](/images/unreal/subscriptions/ue-blueprint-unsubscription-1.png) + +![Unreal Blueprint unsubscribe old subscription graph](/images/unreal/subscriptions/ue-blueprint-unsubscription-2.png) + diff --git a/docs/docs/00200-core-concepts/00600-clients/00800-unreal-reference.md b/docs/docs/00200-core-concepts/00600-clients/00800-unreal-reference.md index 906d62f3b0a..3dbe63caa8e 100644 --- a/docs/docs/00200-core-concepts/00600-clients/00800-unreal-reference.md +++ b/docs/docs/00200-core-concepts/00600-clients/00800-unreal-reference.md @@ -21,6 +21,7 @@ Before diving into the reference, you may want to review: | [Access the client cache](#access-the-client-cache) | Access to your local view of the database. | | [Observe and invoke reducers](#observe-and-invoke-reducers) | Send requests to the database to run reducers, and register callbacks for reducer results on the calling connection. | | [Subscriptions](#subscriptions) | Subscribe to queries and manage subscription lifecycle. | +| [Query Builder API](#query-builder-api) | Build typed subscription queries in Unreal C++ and Blueprint. | | [Identify a client](#identify-a-client) | Types for identifying users and client connections. | ## Project setup @@ -496,6 +497,8 @@ The generated `On` delegates are the Unreal equivalent of a per-call ca Create subscriptions to receive updates for specific queries using the `USubscriptionBuilder` and `USubscriptionHandle` classes. +For Unreal C++, the recommended default is to build subscriptions with `AddQuery(...)` and then call parameterless `Subscribe()`. Raw SQL subscriptions remain available when you need to provide SQL directly. + | Name | Description | | -------------------------------------------------- | ---------------------------------- | | [USubscriptionBuilder](#type-usubscriptionbuilder) | Build and configure subscriptions. | @@ -512,6 +515,11 @@ class USubscriptionBuilder UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") USubscriptionBuilder* OnError(FOnSubscriptionError Callback); + USubscriptionBuilder* AddQuery(TFunctionRef BuildQuery); + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + USubscriptionHandle* Subscribe(); + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") USubscriptionHandle* Subscribe(const TArray& SQL); @@ -536,13 +544,29 @@ USubscriptionBuilder* OnError(FOnSubscriptionError Callback); Register a callback to run if the subscription fails. +#### Method `AddQuery` + +```cpp +USubscriptionBuilder* AddQuery(TFunctionRef BuildQuery); +``` + +Append a typed query to the builder. The callback receives an `FQueryBuilder`, typically named `Q`, and returns a generated query source or filtered query. Call `AddQuery(...)` once per table or view query you want to subscribe to, then finish with parameterless `Subscribe()`. + #### Method `Subscribe` +```cpp +USubscriptionHandle* Subscribe(); +``` + +Subscribe to the typed queries accumulated with `AddQuery(...)` and return a handle for managing the subscription. + +#### Method `Subscribe` (SQL overload) + ```cpp USubscriptionHandle* Subscribe(const TArray& SQL); ``` -Subscribe to the provided SQL queries and return a handle for managing the subscription. +Subscribe to the provided SQL queries and return a handle for managing the subscription. Use this when you need to write SQL directly instead of using the typed query builder. #### Method `SubscribeToAllTables` @@ -552,6 +576,8 @@ USubscriptionHandle* SubscribeToAllTables(); Subscribe to all public tables in the module. +`SubscribeToAllTables()` is useful for quick prototypes and small modules. Prefer typed queries for production subscriptions so the subscription set stays explicit. + ### Type `USubscriptionHandle` ```cpp @@ -614,6 +640,129 @@ TArray GetQuerySqls() const; Get the SQL queries associated with this subscription. +## Query Builder API + +Use the Unreal query builder to build typed subscriptions in C++ and Blueprint. + +In C++, a query typically starts from the generated `FQueryBuilder` passed to `AddQuery(...)`, selects a source from `Q.From`, and optionally applies `Where(...)` with generated column objects: + +```cpp +USubscriptionHandle* Handle = Conn->SubscriptionBuilder() + ->OnApplied(FOnSubscriptionApplied::CreateUObject(this, &AMyActor::OnSubscriptionApplied)) + ->OnError(FOnSubscriptionError::CreateUObject(this, &AMyActor::OnSubscriptionError)) + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.Player().Where([](const FPlayerCols& Cols) + { + return Cols.Level.Gte(1).And(Cols.DisplayName.Neq(TEXT("Guest"))); + }); + }) + ->Subscribe(); +``` + +The generated query-builder surface is module-specific. Sources, column sets, and query return types are generated from your schema and views. + +### Query sources + +Each public table or subscribed query source is available under `Q.From` using a generated method: + +```cpp +Q.From.Player() +Q.From.ActivePlayerLocations() +Q.From.PlayersAtLevel0() +``` + +Event tables are not subscribed implicitly. Subscribe to them with an explicit query just like any other source: + +```cpp +Conn->SubscriptionBuilder() + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.DamageEvent(); + }) + ->Subscribe(); +``` + +### Predicates + +Generated column objects expose typed predicate methods such as: + +- `Eq` +- `Neq` +- `Gt` +- `Lt` +- `Gte` +- `Lte` + +Predicates can be combined with: + +- `And` +- `Or` +- `Not` + +Example: + +```cpp +Conn->SubscriptionBuilder() + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.Player().Where([](const FPlayerCols& Cols) + { + return Cols.Level.Gte(3).And(Cols.IsOnline.Eq(true)); + }); + }) + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.ActivePlayerLocations().Where([](const FActivePlayerLocationsCols& Cols) + { + return Cols.X.Gte(10).And(Cols.Y.Lte(400)); + }); + }) + ->Subscribe(); +``` + +### Blueprint availability + +The Unreal query builder is available in both C++ and Blueprint. + +In Blueprint, generated nodes expose the same overall flow: + +- source query nodes +- column nodes +- predicate nodes +- `Where` +- `AddQuery` +- `Subscribe` + +Blueprint uses generated source-specific query types for authoring and converts them at the `AddQuery` boundary automatically. + +For example, a Blueprint subscription to online players at level 3 or higher would follow this node flow: + +```text +From Player +├─> Player Level +│ └─> Int32 Greater Equal (3) +├─> Player IsOnline +│ └─> Bool Equal (true) +└─> Player Where + └─> AND + ├─> Int32 Greater Equal (3) + └─> Bool Equal (true) + +Player Where +└─> AddQuery + └─> Subscribe +``` + +The exact node names are generated from your schema, so `Player`, `Level`, and `IsOnline` will vary by module. + +### Notes and limitations + +- `OnApplied` is the right place to inspect the initial subscribed result set in the client cache. +- `OnInsert`, `OnUpdate`, and `OnDelete` are for subsequent live changes after the subscription is active. +- `TimeDuration` query predicates are currently unsupported. +- Raw SQL subscriptions remain available when you need manual SQL control. + ## Identify a client ### Type `FSpacetimeDBIdentity` @@ -669,7 +818,7 @@ struct FSpacetimeDBTimestamp ## Example usage -Here's a complete example of connecting to SpacetimeDB, subscribing to tables, and handling events: +Here's a complete example of connecting to SpacetimeDB, subscribing with the typed query builder, and handling events: ```cpp // In your Actor's BeginPlay() @@ -706,10 +855,22 @@ void AMyActor::OnConnected(UDbConnection* Connection, FSpacetimeDBIdentity Ident // Save token for future connections UCredentials::SaveToken(Token); - // Subscribe to all tables + // Subscribe with typed queries USubscriptionHandle* Handle = Connection->SubscriptionBuilder() ->OnApplied(FOnSubscriptionApplied::CreateUObject(this, &AMyActor::OnSubscriptionApplied)) - ->SubscribeToAllTables(); + ->OnError(FOnSubscriptionError::CreateUObject(this, &AMyActor::OnSubscriptionError)) + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.User(); + }) + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.Message().Where([](const FMessageCols& Cols) + { + return Cols.ChannelId.Eq(1); + }); + }) + ->Subscribe(); } void AMyActor::OnUserInsert(const FEventContext& Context, const FUserType& NewRow) @@ -730,3 +891,11 @@ void AMyActor::SendMessage(const FString& Text) } } ``` + +For small modules or quick debugging sessions, you can still subscribe to every public table: + +```cpp +USubscriptionHandle* Handle = Conn->SubscriptionBuilder() + ->OnApplied(FOnSubscriptionApplied::CreateUObject(this, &AMyActor::OnSubscriptionApplied)) + ->SubscribeToAllTables(); +``` diff --git a/docs/docs/00300-resources/00100-how-to/00600-migrating-to-2.0.md b/docs/docs/00300-resources/00100-how-to/00600-migrating-to-2.0.md index d3de7a145c3..8f70388d274 100644 --- a/docs/docs/00300-resources/00100-how-to/00600-migrating-to-2.0.md +++ b/docs/docs/00300-resources/00100-how-to/00600-migrating-to-2.0.md @@ -399,7 +399,11 @@ Conn->Db->DamageEvent->OnInsert.AddDynamic(this, &AMyActor::OnDamageEvent); Conn->SubscriptionBuilder() ->OnApplied(OnAppliedDelegate) ->OnError(OnErrorDelegate) - ->Subscribe({ TEXT("SELECT * FROM damage_event") }); + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.DamageEvent(); + }) + ->Subscribe(); ``` @@ -585,14 +589,18 @@ ctx.subscription_builder() ```cpp -// 2.0 -- same as 1.0 today +// 2.0 -- typed query builder Conn->SubscriptionBuilder() ->OnApplied(OnAppliedDelegate) ->OnError(OnErrorDelegate) - ->Subscribe({ TEXT("SELECT * FROM person") }); + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.Person(); + }) + ->Subscribe(); ``` -The Unreal SDK does not expose typed query builders yet. For now, use SQL strings. Typed query builder support is planned. +Unreal 2.0 now supports typed query-builder subscriptions in C++. Use `AddQuery(...)` as the default for table and event-table subscriptions. @@ -640,7 +648,11 @@ ctx.subscription_builder() Conn->SubscriptionBuilder() ->OnApplied(OnAppliedDelegate) ->OnError(OnErrorDelegate) - ->Subscribe({ TEXT("SELECT * FROM damage_event") }); + ->AddQuery([](const FQueryBuilder& Q) + { + return Q.From.DamageEvent(); + }) + ->Subscribe(); ``` @@ -1782,6 +1794,8 @@ spacetime sql "SELECT * FROM my_table" - Replace with `_then()` callbacks for your own reducer calls - Unreal: replace with generated `On` delegates on the calling connection - Replace with event tables + `on_insert` for cross-client notifications +- [ ] Migrate Unreal subscription SQL strings to typed queries where appropriate + - Use `Conn->SubscriptionBuilder()->AddQuery(...)->Subscribe()` instead of `Subscribe({ TEXT("SELECT ...") })` - [ ] Update `Event::UnknownTransaction` matches to `Event::Transaction` - [ ] For each reducer whose args you were observing from other clients: 1. Create an `#[table(..., event)]` on the server diff --git a/docs/static/images/unreal/subscriptions/ue-blueprint-group-subscriptions.png b/docs/static/images/unreal/subscriptions/ue-blueprint-group-subscriptions.png new file mode 100644 index 0000000000000000000000000000000000000000..b7f8f42e1b44d3e877813f37ecbf0498f8fbfbe6 GIT binary patch literal 241827 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 HTSxp4aq!d* literal 0 HcmV?d00001 diff --git a/docs/static/images/unreal/subscriptions/ue-blueprint-quick-start.png b/docs/static/images/unreal/subscriptions/ue-blueprint-quick-start.png new file mode 100644 index 0000000000000000000000000000000000000000..a13d67e244f1c8d18f0246d1a6fc7f6e127230e0 GIT binary patch literal 327997 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 z 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 XR39pnaAWYf)kfcq1D zH}rLWssuGcxEZ~=hdAkkhC_>R6TQOIJ?c4PH~Lqh9FLi|DwFB;?u4Flt4FTw3b~D0 z&85u1`~&F~n8)|F-JQD{$S3`Y>FOnKA_D^zT%JqznER?g79-BU7<3A{JeD*$Vx6x# z#`|9kmP^MK0P5v}tWc*ez+h9c`{7T02)ugg<=Y5_dMabAsQ7hF9EXVNRF9(i{8v6b z_hEI>w>l$~X%^&!JIKK0HBJ(VmnwppTwYUF>9hsu&sId)Oq7?BlT%4T{u-9%3|qR zW3aFn$OX*UH+PUnByR{^0==ZQkKW$05K9&K znG2SJs`S*UQ&3g48u>WO9kBw z$j^=i-MaqXaAV7>3j+EUK}i|vp9;p<^Q}Wim+roso^W`Z;28Vd!N0|pM5_DK;tiUP zJqA_{q-JNXX|e6%m22{S^m_+qf7G0;tl_8}QpeFt z5txmW`Eetojf2w8>4$SZblIscf*~Ox&ePFOB+Iz9i1xzzh3qssRcRpITc0((KULPF zt9t$62|R8SUA%_JzRAmL_Zf5>ptDZZ_rR%X-1j)8c6F$M`DF9-1wE=nGI+!r{OrT$ zyHk!Z{{bYL^l_1)T$f|XlMV-X;<20u?-*=*eWtGJ8InfisD3xlD?iiwh<$Mv{&W&U zVgEp_%u?#2FO zzTCcwRu@>_=PvHy)6h5g-8e(OcYbUC7;oqWjFThNa{YVx->mS3gP)A#Q7<m% zx$~>58V?_qUK9!iCa`n0JY;U1t?jZXDnRjGqW89h@O{SHegjQ`g{GCld^&1B{mz|) zRE^CJGGH;xH!1(}YBpiqeqEUib?ysgbH^)j@|ZA8dXYV6YbQOCIY6swU7V)$Emb{u z|M1#S$_MsnZ$mIXTOz7iPM0VomBU9V+ADJnsNkeAmK-Kh^5GusPV={1g(xIbS|1%# z(l^qxYm|umj+{v3^v`AN{`93vO)Exl(XaoQOHl;}=~vt4_Wte~OQE22enD*$8|+-d zOX?@Nf^Ik`uhSXlybbj8Lr7k7nCEitZIvu_eosp~&lfXuh7;WU-glyr!f5*^FfP5V z3gnX-y1vKp$)^apc?1?GD-&CXJ%LOaqUQ(Y4@6Xr7!yDA(+i`wjLtRH9pA{!9wal@ z(#g9?BPmw3=&H8#hSRRt@wx7S|M=`_?4Rzd>@X@7o!;69JPeU&3rv{jv?iwn+WP_E z9;A9KQ?ffx5JAl?SULcF=;hbp+t_vAt_!SAdo$-fR`(n@?^TYvH33rfb)Z86_%cah z&1Qt2-2-j(6XxWdF;99;c2|-c`Nl-B-4ScWP9d}F`pRQ>GPKwxR6RWwH5m|GHMib;<`#|*BONUB`^ktbF@4{GkM z*$=My+s=a)$NZ~Hv{Xcldi()}eAs=F*}Gmh$dW~7r!BT3aPSQ(KZ3~>mYEOeur#c- zw*Qz6p_c9$q2w8gaRjbc4I*I))0@UF8l3wWZzAI zb^;M)_nuFZRR|R$BY@O=`mtYVTzm|IUX3W5gPJS=ev9CL1MrMBG(n+*Ti#WTu=De0 zdbuP)zCsQdZVVJz1d4y{2M{&w15-v5-$GFza5^1yy?bm4fibTP?pNwq9xOfn%tSR7 zv07-z4_ zKX=Rph7)YTxzXH)y&5Ar!!$;08kdJV2AwI{R4%ir7_+JHmr`bQoPEEb93-9`F_0eV zSa#0Q@17KQ%GiYQna;jX1D8O^E&M_Gll;s?40XlHm|hb#vjP$OEA8B$C9j#B8MKaz zF}KD%&!`q(PQQ75Dvt<`HNHSv+DXo-H)VfEBk46K&HMO%^2h+xolzJ>Gr5f$&4YYf zp!S^C=S&aGcp+$H`3Ion6d;Tp1fwbIGv3A&q_PLY0#09h1~(~xX_cu!$@TT zKD$+;&3Ph}UhN`#D_HcMM#+syWykkyvwa74Xh`v^xc=IUdp}-6-Ts2ovaCcNV`hP$Cw(J+Rkd5ZZyn{;x;SZNv+e9%U8`$~?bOYRJy8n2)$o?t zjaY9y9I{K>J=YX{5;z7Q4m;|c!s^os?dxxYdvBW2r&;ZGqlCJoB_v`Wr$tyWe^5>g zPk%AfFG0KTh?W1%O~y=1PJd+q^)n1WvmSX-h+gcu{(IlT%RYPiHA*x{3Jmi_0mO|D z$>DovUVMJzIe$xn7HxxZ<`Pu0kp9C&-hx81OXA>IQfR8W#P>B43t(ALq3kh1Da&k6 zde`OH+uky^5pfE7IWpH}Vm^xNPw)FKB}1lr)6sHKp&VY!LC;eVg9O}~Ut4h-dt{;C z%F@NHm)37Ua)bMrC*SJ+oEfkMvQBe#yXN^F1h9Tj6!)fETv`+Zu^?M$X9WdZj_!0^ zf_X#vIQk@rH-N40_#K>TV}D3fhc7SWd26*^kXILMU*}Gn`grO}4R-Yts+ehO5shpC zO>F3a%PbsP6a&Vo9DaU!cMrt7-Zb}V!Gx3zlrWhp#;ms!NV>%VQBKTNNC~ym!R-bQ zv0({9R#V#%WZ!?n83o_pGi5JIsmgw9D;uD5B&*Jc|t+bgTwO$TJ z`Ls&bv%>VIXT=H_AbJYmhvzT>4m0rLX!#-6oRE2+_UY57VOKoM%FE-}U1(t{8E~Lz zFxfP})>BsCVoLI?CgbxRMSU$Z^OGdey6Q}eL(`-vLL$GRp8(V;ZBP0F!ia|heDkMa zPb*deA3dUa&p;$59`=r`OYT4}NlKna%Ox>vA2-j1H*-njSr(% zOhWHRWu@mP>$Wzv4Sl6JcvuG4!J>TFn9pne_P2((EL-l^mw`kKLDfG` zhaFIki}quz^0REqL>!DLf}vTua+6m6wSR`dp+S5tVfXt@uY=O9(BX|GrX#E)l%8<+ z*djy&IsD@x9+D>QKDxA297s}ouCL;)SBA;~>hUnk6Zo8fk$m?q4>%Yc7ram=_!f;G z$F%GO!8=u7emt+syVR*?!~|+Z;Fls?eGqE^wd#Of+y_@kv6d`F3oyK?e7U|tWHg}r zS)1I3D1qz4D!mERg*%rdSl0e(Muw|38i`!+-gan4^)@k-Ka0CyEo-%xPt7)bM z3z9Y2C-H4+>cS+>wyHZ(y7HNfoFAXX)==Axj5&Y^`0k}Gki04jz{7I3H*_h83fA%T3TqttDr@nr;>VYeI`YfeBZfu= z^CNS>TvPm;C-hG(v4MAJCz``@^|HYC1T8JC%)-n>3nA73&?dFZZb5pds{)Iv_XRe!M>Hds|x( z;M%loQei+a4VYVi24l1qjKXYH0oooeH5t&_fND7s__Jkd_SV-cHMoCU$Di<-CM{g* zOurq??2G~Gyx4qG_9Pmn<)e!uWlQSN5xL;HXgKGiDD#AQTeWV4_Ot5p2l-ewo`MmL z3>CIUA?3avN@kuB2x`b(guE&tel#LTY$aQHAB*)NMNLeGho~5u>hf{Ii8+q0OodZ} zrnL)pn!x=Z66$Yp_+j555|3c3!j&n$4fD0MBmuWb#@5MD7XEgqiAoocvbt>yQ_L8( za!!Oj*aFf~h{DGl^khP@TiSfR8c)+Bu`%YoCexGe3y_z(y1E*3^}ik%G!_AmC(ry{ zULG~5GhzNIH*yUcwJfe3*MV47FSH(fimJ*arL9ENUafHa;S1c7e#wFCh>CTL9fY>+ zoV=PuyT-@Y1Sp!|?HIe6`N)i=OAyhqySrP?Obkf6fFcYC(HUtQtGMEUExpYMd@Dj~ zFborUgKpu`PbX&I_5H{zEPxi{4@e^~OJ=4H9fMDQBRuKjnZR2o z0pG8n#*BzcWnNeD+yZhK+&}%mwGA3brq^@@f-~4a2;ZY9CVZlDeKa8*xU7N=;y2gx z5EO*o>Ma=#iA1i|l(8!eM>j0EnzgO3ivrcn?eX9#GA^2ov`+7UD}L}iURfA zk9QjoiVVT(z$WZur1JR-z0CAmXjC*AuxkSU89ZKq%C;=ag#9&+#4lc?puqHh{~nj0 z?8p&PbueR~y=G+!-a@%YqF!AD#Y_eOLnR83uuQD1EfltSxq|N9cmTvTpnO3XtlnH& z9trv*mFtBgNrgzM4;$&WPo?dZB5(~-U_xsg=9C?B{jaygqCRS$R`nIU*hV_g!^j37l7s0Vn#iX?jJ5>=1yjHVcWCYavffIu8Cf{X$) zre2grZ1|+bn|?o2^?p~dqY%NzjyLg3Xs|Aa=?g?G)N+EpR{3^`Fl6=%O*)93B|NGs z?KniD#cybYdGvLPOWo^?N5+s>)_M0@mZOZ}Y&U6d6-scyDcNHls<3E3u%8^6x&Ah@ z{>$BUd>aF(Xdw9_L+_8hQ#M0HIpCqsSEp{(o6C6QpqUMjb#)H9-BfL=FSSp9lm2xp zh>MMBLM)8?1qX#R45syrcW#GR#6EuVRt|qi--!9|+vb=CVlx3>1!4t&Jrl%fGc6!9TKYlVv_v+Q_xcSBkXhWv!wcb*A8WN zCA<@b(#^gLsj1x-tXWoW?)uVOgKl+3Tv9)-R`|MXYl>q>C02a;p%7OP{`P}L_3T>l zuL*fnhMnr|>+8F}MR^c?p!L8!b~z)azCgIL%mvuRiqh~$7;G>159E%r1$ z21!1O+Lz)&uILC2sN{Q|{Yv{KvA3+FOmT3>M8bP?^IN8)4>We1YY-tUJeS+hY|8zAG3fuXc>UUhRu(>k=8KC-2?duPBkwT39#LFPen>ugM2|Q0Uih9pqPXx-oK~)Z<5+?2WIG8u&hLd zgbQ>Vb58NWi4*qQdFS^ZU7|HI0`VoyhtZ0^+^l`zI9;=2VrToe{Nvg-!!Mmyp|A-j zKOXV*u9rq}jZ+b|=f_KA-rQLuOHv>;bvSoyY1?ui#V8m_(G*q8CcFLFZ*FUIhIC_h zj0#vxlD{_5^Ya`p{e9F#FnzUy0AO8!t!W7`kpGJv{J(uEqKgy- z^^gg-=yd$qSL{D34p*VG^Y}S$im-;n&m}HwL$7ptU9K6*43{`A_`Ln*lm0v$`!M5< zb{ANP|84jm1ucTCDIk~0tnXqs*I!N`+3UuFI^0VuM_l7hrdbbEMi=HncWa+>Kdne&qV>A@pvV>vYK3hk-L9?tAJ3&I}XK|4Rh&rTRejW|*+@F5+zZs?fRh9Lp zLcZwNuc(D8FJ~wSes8kIQB@BF7ArD7;X=zkXsW9D zd^B|70(EB0XG_rVwTw;_T%g`di!-G%@04&r-y8SbwPl@{PWzkH%)ef;xudP^UPa=2 zMrIRj2N=H^FLfi7BMYdp#cgqb)P9&A4V94OqXZ|~1(d3r*!ATlWN}T)tY$S60La{(GhNYy1!OSevqwj8ItwC*-~xko)|D z(+B=*nLJrcG#u?I5IRa?Was-6BtRJf=5UAB3ZMDY@$r#5gv#lEY=Zw7V1?&F!EOHf z4|1zS9TMMm%963@_{mBdU?l#}7f8MXIC5Id!C*vOSJadZ58q)E^WjNictACYT_RA703Am8WZ(LEsi%li z5DYl0*;#f%UnBD@=A@IYIe#2-O!e@WepzE0B)pp&bvvapl2~RC?DhEVnJ^X z1{l}B7xiD&j?cp6)_$JPj1*fe*TzVts?T;DJ2Uphcyb{gG;NmR|^qg&Qi2AjAh)p<(n%YQ6iAb7b^gZIpUJ z49?*(;+UqrI$#n%JS>M@Uikk%X!p6S=XvwLtubRZ@`RB8d3C-fLv~0@{m-j$;0+gm z?0;EC>~W;$UUslBfV@_E| zzEs<2q9+tJvts$XK$X6X)XGwuRr=0E=V6lB^NDF{7Ae1SB>Ss&Hm^O5j}q-XV-|?EQ0-H)5Hd z@X_Ah23beMi_{psl@?N^(eBgJhs7l&`eH1PDHuLYg?_jne)DSwfy6eHFM-?&W%YPc zDGH+)@aWZ1HE+CnqE^vo9bv2a?J&m_uJk|F{8s^)IXQh(Q&TPI^)1me$Rn>?ia6@_ z>g%RHjYr=MAt|mxS7$jQE(N*1Z}`v5=(>*2&e{#b#g`8`2meF5z`t=Qv!CavfNvXF zU2~w}5!8Yo=C0$_PlU^3W1VZi`E-X(cLYqGAd&y?JDVaDvC&``P7fN3J#-~`#Io@} zC)eFDU2axVC=kvE8|`-EdRm~b^ZdD$wKYlqE5oXr}t*fT)GcC-Kz@O;rWpQGG06{S;Nu7Y3LV&H=0$>CPrFWUdcd={M9`q zo(O2^s&-T?lLZ%_*x#>gx%)MZH?PEsTp;~`K1Eb{b~eggNU{j0X@i}m~4YBttzMqIYMf7{jih(ldp=ot#0iFVHwJ20gxtK=QX&2|=gRj}OjVsExz(1Hvl zn&&w5eeCSFDy58qec`j0pO$)a3ddu%D8vWp1cEZI)7K4(JyIpt2fxxPKuqvJI;VYl zk1*zvA@YaZdIm$fMp@(!GN_-Wc)z$|#ed2h;X>WGvGE^jC;1fb--kzG74*dTABA>>14xlV&zQnR=fYf5hKqP zKtfn7t7N{niR8p$D;wfST5PeAv-es|t2W7%%9maWAJ6CDzzKsD=4$cZ?~-`zC)BlJ zbo1%?2VX7MpJRq2$Ddx^Vo*EkeZ0fO9w5Dj_Xs^DwztZom218m{d8cF~B)KkIK z?Vc;|oW7x6gY@jLeOD)_@#ST@`T9@9gY(sfQv^m4NPk%x-r4!Mc-fW>aYdlqQ&Fpl zo!L%!m8CRD4dPl=U!?kMg2qMn<~l!B7+>r0jl)s_®_?w$xsmwFukX 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 z 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

{#)sBv>Ey}ErHr|IX`Y_6B=1Fx(;sLfZB4- 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 literal 0 HcmV?d00001 diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr.h index 3eae6bc8dd4..a005a248cf9 100644 --- a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr.h +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr.h @@ -1,15 +1,14 @@ #pragma once -#include "CoreMinimal.h" #include "BSATN/Core/timestamp.h" #include "BSATN/Core/types.h" -#include "Types/Builtins.h" +#include #include +#include #include #include #include -#include #include #include #include @@ -86,31 +85,12 @@ inline std::string trim_timestamp_fraction(std::string value) { inline std::string literal_sql(const std::string& value) { return quote_string(value); } inline std::string literal_sql(std::string_view value) { return quote_string(value); } inline std::string literal_sql(const char* value) { return quote_string(value == nullptr ? "" : value); } -inline std::string literal_sql(const TCHAR* value) { - return quote_string(value == nullptr ? "" : TCHAR_TO_UTF8(value)); -} -inline std::string literal_sql(const FString& value) { - return quote_string(TCHAR_TO_UTF8(*value)); -} inline std::string literal_sql(bool value) { return value ? "TRUE" : "FALSE"; } inline std::string literal_sql(const ::SpacetimeDb::Identity& value) { return "0x" + value.to_hex_string(); } inline std::string literal_sql(const ::SpacetimeDb::ConnectionId& value) { return "0x" + value.to_string(); } inline std::string literal_sql(const ::SpacetimeDb::Timestamp& value) { return quote_string(trim_timestamp_fraction(value.to_string())); } -inline std::string ensure_hex_prefix(std::string value) { - if (value.rfind("0x", 0) == 0 || value.rfind("0X", 0) == 0) { - return value; - } - return "0x" + value; -} -inline std::string literal_sql(const FSpacetimeDBIdentity& value) { return ensure_hex_prefix(std::string(TCHAR_TO_UTF8(*value.ToHex()))); } -inline std::string literal_sql(const FSpacetimeDBConnectionId& value) { return ensure_hex_prefix(std::string(TCHAR_TO_UTF8(*value.ToHex()))); } -inline std::string literal_sql(const FSpacetimeDBUuid& value) { - return quote_string(TCHAR_TO_UTF8(*value.ToString())); -} -inline std::string literal_sql(const FSpacetimeDBTimestamp& value) { - return quote_string(trim_timestamp_fraction(TCHAR_TO_UTF8(*value.ToString()))); -} -std::string literal_sql(const FSpacetimeDBTimeDuration& value) = delete; +#include "QueryBuilder/expr_unreal_adapters.h" + inline std::string literal_sql(const std::vector& value) { std::ostringstream out; out << "0x" << std::hex << std::setfill('0'); @@ -119,25 +99,19 @@ inline std::string literal_sql(const std::vector& value) { } return out.str(); } -inline std::string literal_sql(const TArray& value) { - std::ostringstream out; - out << "0x" << std::hex << std::setfill('0'); - for (uint8 byte : value) { - out << std::setw(2) << static_cast(byte); - } - return out.str(); -} inline std::string literal_sql(const ::SpacetimeDb::u128& value) { return value.to_string(); } inline std::string literal_sql(const ::SpacetimeDb::i128& value) { return value.to_string(); } inline std::string literal_sql(const ::SpacetimeDb::u256& value) { return value.to_string(); } inline std::string literal_sql(const ::SpacetimeDb::i256& value) { return value.to_string(); } -inline std::string literal_sql(const FSpacetimeDBUInt128& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } -inline std::string literal_sql(const FSpacetimeDBInt128& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } -inline std::string literal_sql(const FSpacetimeDBUInt256& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } -inline std::string literal_sql(const FSpacetimeDBInt256& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } template inline std::string format_floating_point(TFloat value) { + char buffer[64]; + const auto result = std::to_chars(buffer, buffer + sizeof(buffer), value, std::chars_format::general); + if (result.ec == std::errc{}) { + return std::string(buffer, result.ptr); + } + std::ostringstream out; out.imbue(std::locale::classic()); out << std::setprecision(std::numeric_limits::max_digits10); diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr_unreal_adapters.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr_unreal_adapters.h new file mode 100644 index 00000000000..3c4e27d22e4 --- /dev/null +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/expr_unreal_adapters.h @@ -0,0 +1,51 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Types/Builtins.h" + +inline std::string literal_sql(const TCHAR* value) { + return quote_string(value == nullptr ? "" : TCHAR_TO_UTF8(value)); +} + +inline std::string literal_sql(const FString& value) { + return quote_string(TCHAR_TO_UTF8(*value)); +} + +inline std::string ensure_hex_prefix(std::string value) { + if (value.rfind("0x", 0) == 0 || value.rfind("0X", 0) == 0) { + return value; + } + return "0x" + value; +} + +inline std::string literal_sql(const FSpacetimeDBIdentity& value) { + return ensure_hex_prefix(std::string(TCHAR_TO_UTF8(*value.ToHex()))); +} + +inline std::string literal_sql(const FSpacetimeDBConnectionId& value) { + return ensure_hex_prefix(std::string(TCHAR_TO_UTF8(*value.ToHex()))); +} + +inline std::string literal_sql(const FSpacetimeDBUuid& value) { + return quote_string(TCHAR_TO_UTF8(*value.ToString())); +} + +inline std::string literal_sql(const FSpacetimeDBTimestamp& value) { + return quote_string(trim_timestamp_fraction(TCHAR_TO_UTF8(*value.ToString()))); +} + +std::string literal_sql(const FSpacetimeDBTimeDuration& value) = delete; + +inline std::string literal_sql(const TArray& value) { + std::ostringstream out; + out << "0x" << std::hex << std::setfill('0'); + for (uint8 byte : value) { + out << std::setw(2) << static_cast(byte); + } + return out.str(); +} + +inline std::string literal_sql(const FSpacetimeDBUInt128& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } +inline std::string literal_sql(const FSpacetimeDBInt128& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } +inline std::string literal_sql(const FSpacetimeDBUInt256& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } +inline std::string literal_sql(const FSpacetimeDBInt256& value) { return TCHAR_TO_UTF8(*value.ToDecimalString()); } diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/join.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/join.h index 4fe9e18c7a4..636d9474a28 100644 --- a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/join.h +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/join.h @@ -267,7 +267,7 @@ template& left, const Table& right, TFn&& predicate) { static_assert( can_be_lookup_table_v>, - "Semijoin predicates require the right-hand source to opt into CanBeLookupTable." + "Lookup side of a semijoin must opt in via CanBeLookupTable." ); const auto join = std::forward(predicate)(left.ix_cols(), right.ix_cols()); return LeftSemiJoin(left, right, join.lhs, join.rhs); @@ -277,7 +277,7 @@ template& left, const Table& right, TFn&& predicate) { static_assert( can_be_lookup_table_v>, - "Semijoin predicates require the right-hand source to opt into CanBeLookupTable." + "Lookup side of a semijoin must opt in via CanBeLookupTable." ); const auto join = std::forward(predicate)(left.table().ix_cols(), right.ix_cols()); return LeftSemiJoin(left.table(), right, join.lhs, join.rhs, left.expr()); @@ -287,7 +287,7 @@ template& left, const Table& right, TFn&& predicate) { static_assert( can_be_lookup_table_v>, - "Semijoin predicates require the right-hand source to opt into CanBeLookupTable." + "Lookup side of a semijoin must opt in via CanBeLookupTable." ); const auto join = std::forward(predicate)(left.ix_cols(), right.ix_cols()); return RightSemiJoin(left, right, join.lhs, join.rhs); @@ -297,7 +297,7 @@ template& left, const Table& right, TFn&& predicate) { static_assert( can_be_lookup_table_v>, - "Semijoin predicates require the right-hand source to opt into CanBeLookupTable." + "Lookup side of a semijoin must opt in via CanBeLookupTable." ); const auto join = std::forward(predicate)(left.table().ix_cols(), right.ix_cols()); return RightSemiJoin(left.table(), right, join.lhs, join.rhs, left.expr()); diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/query_builder.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/query_builder.h index 81603930504..8b06502e337 100644 --- a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/query_builder.h +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/query_builder.h @@ -4,19 +4,95 @@ #include "QueryBuilder/join.h" #include "QueryBuilder/table.h" +#include +#include #include +#include namespace SpacetimeDB { template using Query = query_builder::RawQuery; +namespace detail { + +template +struct NamedQuerySourceTag { + using type = TRow; + const char* __table_name_internal; +}; + +struct NotAQuerySourceTag {}; + +template +struct query_source_row_type {}; + +template +concept HasQuerySourceRowType = requires { + typename query_source_row_type>::type; +}; + +template +using query_source_row_type_t = typename query_source_row_type>::type; + +template + requires query_builder::QueryBuilderReturn +struct query_source_row_type { + using type = query_builder::query_row_type_t; +}; + +template +struct query_source_row_type> { + using type = TRow; +}; + +template +struct query_source_row_type> { + using type = TRow; +}; + +template +constexpr auto MakeQuerySourceTag(const char* source_name) { + if constexpr (HasQuerySourceRowType) { + return NamedQuerySourceTag>{source_name}; + } else { + return NotAQuerySourceTag{}; + } +} + +template +constexpr const char* GetQuerySourceName(const TSourceTag& tag) { + return tag.__table_name_internal; +} + +} // namespace detail + class QueryBuilder { public: template [[nodiscard]] constexpr query_builder::Table table(const char* table_name, TCols cols, TIxCols ix_cols) const { return query_builder::Table(table_name, std::move(cols), std::move(ix_cols)); } + + template + [[nodiscard]] constexpr auto table(TTableTag tag) const + -> query_builder::Table< + typename std::remove_cvref_t::type, + decltype(query_builder::HasCols::type>::get(std::declval())), + decltype(query_builder::HasIxCols::type>::get(std::declval()))> { + using TRow = typename std::remove_cvref_t::type; + const char* table_name = detail::GetQuerySourceName(tag); + return table( + table_name, + query_builder::HasCols::get(table_name), + query_builder::HasIxCols::get(table_name)); + } + + template + [[nodiscard]] constexpr auto operator[](TTableTag tag) const + -> decltype(table(tag)) { + return table(tag); + } }; } // namespace SpacetimeDB diff --git a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/table.h b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/table.h index b9d18bde50b..e899efc396f 100644 --- a/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/table.h +++ b/sdks/unreal/src/SpacetimeDbSdk/Source/SpacetimeDbSdk/Public/QueryBuilder/table.h @@ -1,8 +1,10 @@ #pragma once -#if 0 -// bindings-cpp source include kept here for traceability: -// #include "spacetimedb/bsatn/traits.h" +#ifndef SPACETIMEDB_QUERY_BUILDER_ENABLE_BSATN +#define SPACETIMEDB_QUERY_BUILDER_ENABLE_BSATN 0 +#endif + +#if SPACETIMEDB_QUERY_BUILDER_ENABLE_BSATN #include "BSATN/Core/traits.h" #endif #include "QueryBuilder/expr.h" @@ -25,16 +27,13 @@ template class FromWhere; template -struct CanBeLookupTable : std::false_type {}; +struct HasCols; template -inline constexpr bool can_be_lookup_table_v = CanBeLookupTable>::value; - -template -class LeftSemiJoin; +struct HasIxCols; -template -class RightSemiJoin; +template +struct CanBeLookupTable : std::false_type {}; template using query_row_type_t = typename query_row_type>::type; @@ -72,6 +71,31 @@ concept QueryBuilderReturn = requires { typename query_row_type_t; } && QueryLike>; +namespace detail { + +template +struct row_tag {}; + +inline std::false_type lookup_table_allowed(...); + +template +auto adl_lookup_table_allowed(int) -> decltype(lookup_table_allowed(row_tag{})); + +template +std::false_type adl_lookup_table_allowed(...); + +} // namespace detail + +template +inline constexpr bool can_be_lookup_row_v = + CanBeLookupTable::value || decltype(detail::adl_lookup_table_allowed(0))::value; + +template +inline constexpr bool can_be_lookup_table_v = CanBeLookupTable>::value; + +template +struct CanBeLookupTable> : std::bool_constant> {}; + template class Table { public: @@ -244,14 +268,7 @@ struct query_row_type> { } // namespace SpacetimeDB::query_builder -#if 0 -// Intentionally disabled in Unreal v1. -// These bindings-cpp-only bsatn/algebraic_type hooks support module-side query-view -// metadata handling for RawQuery. The Unreal client query builder reuses the SQL -// generation core but does not participate in bindings-cpp module view registration. -// -// Source of truth: jlarabie/cpp-query-builder -// crates/bindings-cpp/include/spacetimedb/query_builder/table.h +#if SPACETIMEDB_QUERY_BUILDER_ENABLE_BSATN namespace SpacetimeDB::bsatn { template struct algebraic_type_of<::SpacetimeDB::query_builder::RawQuery> { @@ -282,5 +299,5 @@ struct bsatn_traits<::SpacetimeDB::query_builder::RawQuery> { return algebraic_type_of<::SpacetimeDB::query_builder::RawQuery>::get(); } }; -} +} // namespace SpacetimeDB::bsatn #endif diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h index 98834a02d59..1a763d5ef20 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h @@ -4,8 +4,8 @@ #pragma once #include "CoreMinimal.h" #include "BSATN/UESpacetimeDB.h" -#include "Kismet/BlueprintFunctionLibrary.h" #include "ModuleBindings/Types/SimpleEnumType.g.h" +#include "Kismet/BlueprintFunctionLibrary.h" #include "Types/Builtins.h" #include "EnumWithPayloadType.g.generated.h" @@ -46,7 +46,7 @@ struct TESTCLIENT_API FEnumWithPayloadType public: FEnumWithPayloadType() = default; - TVariant, FSpacetimeDBUInt128, TArray, bool, int64, int16, uint16, FSpacetimeDBInt256, FSpacetimeDBInt128, float, uint8, FSpacetimeDBConnectionId, TArray, double, FString, int32, uint64, TArray, uint32, FSpacetimeDBUInt256, int8> MessageData; + TVariant, bool, FSpacetimeDBTimestamp, FSpacetimeDBUuid, TArray, float, double, FString, FSpacetimeDBIdentity, uint16, uint32, uint64, FSpacetimeDBUInt256, int16, FSpacetimeDBUInt128, uint8, int32, int64, FSpacetimeDBInt128, int8, FSpacetimeDBInt256, TArray, TArray> MessageData; UPROPERTY(BlueprintReadOnly) EEnumWithPayloadTag Tag = static_cast(0); diff --git a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Types/ReturnEnumType.g.h b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Types/ReturnEnumType.g.h index 14b4b797c33..a0235284c48 100644 --- a/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Types/ReturnEnumType.g.h +++ b/sdks/unreal/tests/TestProcClient/Source/TestProcClient/Public/ModuleBindings/Types/ReturnEnumType.g.h @@ -22,7 +22,7 @@ struct TESTPROCCLIENT_API FReturnEnumType public: FReturnEnumType() = default; - TVariant MessageData; + TVariant MessageData; UPROPERTY(BlueprintReadOnly) EReturnEnumTag Tag = static_cast(0);