diff --git a/config-generators/dwsql-commands.txt b/config-generators/dwsql-commands.txt index 3f2167be60..ed61622dc8 100644 --- a/config-generators/dwsql-commands.txt +++ b/config-generators/dwsql-commands.txt @@ -120,9 +120,9 @@ update Broker --config "dab-config.DwSql.json" --permissions "authenticated:crea update WebsiteUser --config "dab-config.DwSql.json" --permissions "authenticated:create,read,delete,update" --rest false --graphql "websiteUser:websiteUsers" update SupportedType --config "dab-config.DwSql.json" --map "id:typeid" --permissions "authenticated:create,read,delete,update" update Tree --config "dab-config.DwSql.json" --rest true --graphql false --permissions "authenticated:create,read,update,delete" --map "species:Scientific Name,region:United State's Region" -update Shrub --config "dab-config.DwSql.json" --permissions "authenticated:create,read,update,delete" --map "species:fancyName" +update Shrub --config "dab-config.DwSql.json" --permissions "authenticated:create,read,update,delete" --map "species:fancyName" --relationship fungus --cardinality one --target.entity Fungus --relationship.fields "species:habitat" update Fungus --config "dab-config.DwSql.json" --permissions "authenticated:create,read,update,delete" --map "spores:hazards" --rest true -update Fungus --config "dab-config.DwSql.json" --permissions "policy_tester_01:read" --fields.include "*" --policy-database "@item.region ne 'northeast'" +update Fungus --config "dab-config.DwSql.json" --permissions "policy_tester_01:read" --fields.include "*" --policy-database "@item.region ne 'northeast'" --relationship Shrub --cardinality one --target.entity Shrub --relationship.fields "habitat:species" update books_view_all --config "dab-config.DwSql.json" --permissions "authenticated:create,read,update,delete" --rest true --graphql true update books_view_with_mapping --config "dab-config.DwSql.json" --map "id:book_id" update series --config "dab-config.DwSql.json" --relationship comics --target.entity Comic --cardinality many --relationship.fields "id:series_id" diff --git a/config-generators/mssql-commands.txt b/config-generators/mssql-commands.txt index 8f5f4df7fc..93ce772508 100644 --- a/config-generators/mssql-commands.txt +++ b/config-generators/mssql-commands.txt @@ -147,9 +147,9 @@ update series --config "dab-config.MsSql.json" --relationship comics --target.en update stocks_price --config "dab-config.MsSql.json" --relationship Stock --target.entity Stock --cardinality one update Broker --config "dab-config.MsSql.json" --permissions "authenticated:create,update,read,delete" --graphql false update Tree --config "dab-config.MsSql.json" --rest true --graphql false --permissions "authenticated:create,read,update,delete" --map "species:Scientific Name,region:United State's Region" -update Shrub --config "dab-config.MsSql.json" --permissions "authenticated:create,read,update,delete" --map "species:fancyName" +update Shrub --config "dab-config.MsSql.json" --permissions "authenticated:create,read,update,delete" --map "species:fancyName" --relationship fungus --cardinality one --target.entity Fungus --relationship.fields "species:habitat" update Fungus --config "dab-config.MsSql.json" --permissions "authenticated:create,read,update,delete" --map "spores:hazards" --rest true -update Fungus --config "dab-config.MsSql.json" --permissions "policy_tester_01:read" --fields.include "*" --policy-database "@item.region ne 'northeast'" +update Fungus --config "dab-config.MsSql.json" --permissions "policy_tester_01:read" --fields.include "*" --policy-database "@item.region ne 'northeast'" --relationship Shrub --cardinality one --target.entity Shrub --relationship.fields "habitat:species" update books_view_all --config "dab-config.MsSql.json" --permissions "authenticated:create,read,update,delete" --rest true --graphql true update stocks_view_selected --config "dab-config.MsSql.json" --permissions "authenticated:create,read,update,delete" update books_publishers_view_composite --config "dab-config.MsSql.json" --permissions "authenticated:create,read,update,delete" diff --git a/config-generators/mysql-commands.txt b/config-generators/mysql-commands.txt index 955e7a7c20..d322c8722a 100644 --- a/config-generators/mysql-commands.txt +++ b/config-generators/mysql-commands.txt @@ -108,9 +108,9 @@ update Comic --config "dab-config.MySql.json" --permissions "authenticated:creat update series --config "dab-config.MySql.json" --relationship comics --target.entity Comic --cardinality many update Broker --config "dab-config.MySql.json" --permissions "authenticated:create,update,read,delete" --graphql false update Tree --config "dab-config.MySql.json" --rest true --graphql false --permissions "authenticated:create,read,update,delete" --map "species:Scientific Name,region:United State's Region" -update Shrub --config "dab-config.MySql.json" --permissions "authenticated:create,read,update,delete" --map "species:fancyName" +update Shrub --config "dab-config.MySql.json" --permissions "authenticated:create,read,update,delete" --map "species:fancyName" --relationship fungus --cardinality one --target.entity Fungus --relationship.fields "species:habitat" update Fungus --config "dab-config.MySql.json" --permissions "authenticated:create,read,update,delete" --map "spores:hazards" --rest true -update Fungus --config "dab-config.MySql.json" --permissions "policy_tester_01:read" --fields.include "*" --policy-database "@item.region ne 'northeast'" +update Fungus --config "dab-config.MySql.json" --permissions "policy_tester_01:read" --fields.include "*" --policy-database "@item.region ne 'northeast'" --relationship Shrub --cardinality one --target.entity Shrub --relationship.fields "habitat:species" update books_view_all --config "dab-config.MySql.json" --permissions "authenticated:create,read,update,delete" --rest true --graphql true update stocks_view_selected --config "dab-config.MySql.json" --permissions "authenticated:create,read,update,delete" update books_publishers_view_composite --config "dab-config.MySql.json" --permissions "authenticated:create,read,update,delete" diff --git a/config-generators/postgresql-commands.txt b/config-generators/postgresql-commands.txt index 3988fe9415..355408de0e 100644 --- a/config-generators/postgresql-commands.txt +++ b/config-generators/postgresql-commands.txt @@ -112,9 +112,9 @@ update Comic --config "dab-config.PostgreSql.json" --permissions "authenticated: update series --config "dab-config.PostgreSql.json" --relationship comics --target.entity Comic --cardinality many update Broker --config "dab-config.PostgreSql.json" --permissions "authenticated:create,update,read,delete" --graphql false update Tree --config "dab-config.PostgreSql.json" --rest true --graphql false --permissions "authenticated:create,read,update,delete" --map "species:Scientific Name,region:United State's Region" -update Shrub --config "dab-config.PostgreSql.json" --permissions "authenticated:create,read,update,delete" --map "species:fancyName" +update Shrub --config "dab-config.PostgreSql.json" --permissions "authenticated:create,read,update,delete" --map "species:fancyName" --relationship fungus --cardinality one --target.entity Fungus --relationship.fields "species:habitat" update Fungus --config "dab-config.PostgreSql.json" --permissions "authenticated:create,read,update,delete" --map "spores:hazards" --rest true -update Fungus --config "dab-config.PostgreSql.json" --permissions "policy_tester_01:read" --fields.include "*" --policy-database "@item.region ne 'northeast'" +update Fungus --config "dab-config.PostgreSql.json" --permissions "policy_tester_01:read" --fields.include "*" --policy-database "@item.region ne 'northeast'" --relationship Shrub --cardinality one --target.entity Shrub --relationship.fields "habitat:species" update books_view_with_mapping --config "dab-config.PostgreSql.json" --map "id:book_id" update BookWebsitePlacement --config "dab-config.PostgreSql.json" --relationship books --target.entity Book --cardinality one update SupportedType --config "dab-config.PostgreSql.json" --map "id:typeid" --permissions "authenticated:create,read,delete,update" diff --git a/src/Core/Configurations/RuntimeConfigValidator.cs b/src/Core/Configurations/RuntimeConfigValidator.cs index 61f9f8f252..c27bc598c4 100644 --- a/src/Core/Configurations/RuntimeConfigValidator.cs +++ b/src/Core/Configurations/RuntimeConfigValidator.cs @@ -1078,9 +1078,9 @@ public void ValidateRelationshipsInConfig(RuntimeConfig runtimeConfig, IMetadata /// works because C# is pass by reference for referenced class types. /// /// List in which to aggregate the invalid fields. - /// List of the fields to check for existence in backing DB. + /// List of the backing fields to check for existence in backing DB. /// The name of the entity that we check for backing columns. - /// The sqlMetadataProvider used to lookup if the fields are valid columns in DB. + /// The sqlMetadataProvider used to lookup if the backing fields are valid columns in DB. private static void GetFieldsNotBackedByColumnsInDB( List invalidColumns, string[] fields, @@ -1090,7 +1090,9 @@ private static void GetFieldsNotBackedByColumnsInDB( invalidColumns.Clear(); foreach (string field in fields) { - if (!sqlMetadataProvider.TryGetBackingColumn(entityName, field, out _)) + // We call this function because the keyset are the backing columns + // which is what want to validate. + if (!sqlMetadataProvider.TryGetExposedColumnName(entityName, field, out _)) { invalidColumns.Add(field); } diff --git a/src/Service.Tests/DatabaseSchema-DwSql.sql b/src/Service.Tests/DatabaseSchema-DwSql.sql index 53f3e77100..930dee5349 100644 --- a/src/Service.Tests/DatabaseSchema-DwSql.sql +++ b/src/Service.Tests/DatabaseSchema-DwSql.sql @@ -342,7 +342,9 @@ VALUES (7, 'Journal7', null, null); INSERT INTO aow(NoteNum, DetailAssessmentAndPlanning, WagingWar, StrategicAttack) VALUES (1, 'chapter one notes: ', 'chapter two notes: ', 'chapter three notes: '); INSERT INTO trees(treeId, species, region, height) VALUES (1, 'Tsuga terophylla', 'Pacific Northwest', '30m'), (2, 'Pseudotsuga menziesii', 'Pacific Northwest', '40m'); +INSERT INTO trees(treeId, species, region, height) VALUES (4, 'test', 'Pacific Northwest', '0m'); INSERT INTO fungi(speciesid, region, habitat) VALUES (1, 'northeast', 'forest'), (2, 'southwest', 'sand'); +INSERT INTO fungi(speciesid, region, habitat) VALUES (3, 'northeast', 'test'); INSERT INTO type_table(id, short_types, int_types, long_types, string_types, nvarchar_string_types, single_types, float_types, decimal_types, diff --git a/src/Service.Tests/DatabaseSchema-MsSql.sql b/src/Service.Tests/DatabaseSchema-MsSql.sql index 1e74e8a590..ad2a989650 100644 --- a/src/Service.Tests/DatabaseSchema-MsSql.sql +++ b/src/Service.Tests/DatabaseSchema-MsSql.sql @@ -600,8 +600,11 @@ INSERT INTO stocks(categoryid, pieceid, categoryName) VALUES (1, 1, 'SciFi'), (2 INSERT INTO stocks_price(categoryid, pieceid, price, is_wholesale_price) VALUES (2, 1, 100.57, 1), (1, 1, 42.75, 0), (100, 99, NULL, NULL); INSERT INTO stocks_price(categoryid, pieceid, instant, price, is_wholesale_price) VALUES (2, 1, '2023-08-21 15:11:04', 100.57, 1); INSERT INTO trees(treeId, species, region, height) VALUES (1, 'Tsuga terophylla', 'Pacific Northwest', '30m'), (2, 'Pseudotsuga menziesii', 'Pacific Northwest', '40m'); +INSERT INTO trees(treeId, species, region, height) VALUES (4, 'test', 'Pacific Northwest', '0m'); INSERT INTO aow(NoteNum, DetailAssessmentAndPlanning, WagingWar, StrategicAttack) VALUES (1, 'chapter one notes: ', 'chapter two notes: ', 'chapter three notes: '); INSERT INTO fungi(speciesid, region, habitat) VALUES (1, 'northeast', 'forest'), (2, 'southwest', 'sand'); +INSERT INTO fungi(speciesid, region, habitat) VALUES (3, 'northeast', 'test'); + SET IDENTITY_INSERT authors_history ON INSERT INTO authors_history(id, first_name, middle_name, last_name, year_of_publish, books_published) diff --git a/src/Service.Tests/DatabaseSchema-MySql.sql b/src/Service.Tests/DatabaseSchema-MySql.sql index 583f3a251a..f884eae35f 100644 --- a/src/Service.Tests/DatabaseSchema-MySql.sql +++ b/src/Service.Tests/DatabaseSchema-MySql.sql @@ -378,7 +378,9 @@ INSERT INTO type_table(id, byte_types, short_types, int_types, long_types, strin (4, 255, 32767, 2147483647, 9223372036854775807, 'null', 3.4E38, 1.7E308, 2.929292E-14, true, '9999-12-31 23:59:59', 0xFFFFFFFF), (5, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO trees(treeId, species, region, height) VALUES (1, 'Tsuga terophylla', 'Pacific Northwest', '30m'), (2, 'Pseudotsuga menziesii', 'Pacific Northwest', '40m'); +INSERT INTO trees(treeId, species, region, height) VALUES (4, 'test', 'Pacific Northwest', '0m'); INSERT INTO fungi(speciesid, region, habitat) VALUES (1, 'northeast', 'forest'), (2, 'southwest', 'sand'); +INSERT INTO fungi(speciesid, region, habitat) VALUES (3, 'northeast', 'test'); INSERT INTO notebooks(id, notebookname, color, ownername) VALUES (1, 'Notebook1', 'red', 'Sean'), (2, 'Notebook2', 'green', 'Ani'), (3, 'Notebook3', 'blue', 'Jarupat'), (4, 'Notebook4', 'yellow', 'Aaron'); INSERT INTO journals(id, journalname, color, ownername) VALUES diff --git a/src/Service.Tests/DatabaseSchema-PostgreSql.sql b/src/Service.Tests/DatabaseSchema-PostgreSql.sql index c715dcaff4..14d6386969 100644 --- a/src/Service.Tests/DatabaseSchema-PostgreSql.sql +++ b/src/Service.Tests/DatabaseSchema-PostgreSql.sql @@ -384,7 +384,9 @@ INSERT INTO type_table(id, short_types, int_types, long_types, string_types, sin (5, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO type_table(id, uuid_types) values(10, 'D1D021A8-47B4-4AE4-B718-98E89C41A161'); INSERT INTO trees("treeId", species, region, height) VALUES (1, 'Tsuga terophylla', 'Pacific Northwest', '30m'), (2, 'Pseudotsuga menziesii', 'Pacific Northwest', '40m'); +INSERT INTO trees("treeId", species, region, height) VALUES (4, 'test', 'Pacific Northwest', '0m'); INSERT INTO fungi(speciesid, region, habitat) VALUES (1, 'northeast', 'forest'), (2, 'southwest', 'sand'); +INSERT INTO fungi(speciesid, region, habitat) VALUES (3, 'northeast', 'test'); INSERT INTO notebooks(id, noteBookName, color, ownerName) VALUES (1, 'Notebook1', 'red', 'Sean'), (2, 'Notebook2', 'green', 'Ani'), (3, 'Notebook3', 'blue', 'Jarupat'), (4, 'Notebook4', 'yellow', 'Aaron'); INSERT INTO journals(id, journalname, color, ownername) VALUES diff --git a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMsSql.verified.txt b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMsSql.verified.txt index 88cacecfd3..6fd33a28d1 100644 --- a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMsSql.verified.txt +++ b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMsSql.verified.txt @@ -1829,6 +1829,17 @@ ], Mappings: { species: fancyName + }, + Relationships: { + fungus: { + TargetEntity: Fungus, + SourceFields: [ + species + ], + TargetFields: [ + habitat + ] + } } } }, @@ -1900,6 +1911,17 @@ ], Mappings: { spores: hazards + }, + Relationships: { + Shrub: { + TargetEntity: Shrub, + SourceFields: [ + habitat + ], + TargetFields: [ + species + ] + } } } }, diff --git a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMySql.verified.txt b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMySql.verified.txt index c38e5e2207..e5e46779cb 100644 --- a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMySql.verified.txt +++ b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMySql.verified.txt @@ -1279,6 +1279,17 @@ ], Mappings: { species: fancyName + }, + Relationships: { + fungus: { + TargetEntity: Fungus, + SourceFields: [ + species + ], + TargetFields: [ + habitat + ] + } } } }, @@ -1350,6 +1361,17 @@ ], Mappings: { spores: hazards + }, + Relationships: { + Shrub: { + TargetEntity: Shrub, + SourceFields: [ + habitat + ], + TargetFields: [ + species + ] + } } } }, diff --git a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForPostgreSql.verified.txt b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForPostgreSql.verified.txt index 37d159df58..2bcebc1232 100644 --- a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForPostgreSql.verified.txt +++ b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForPostgreSql.verified.txt @@ -1376,6 +1376,17 @@ ], Mappings: { species: fancyName + }, + Relationships: { + fungus: { + TargetEntity: Fungus, + SourceFields: [ + species + ], + TargetFields: [ + habitat + ] + } } } }, @@ -1447,6 +1458,17 @@ ], Mappings: { spores: hazards + }, + Relationships: { + Shrub: { + TargetEntity: Shrub, + SourceFields: [ + habitat + ], + TargetFields: [ + species + ] + } } } }, diff --git a/src/Service.Tests/SqlTests/GraphQLQueryTests/DwSqlGraphQLQueryTests.cs b/src/Service.Tests/SqlTests/GraphQLQueryTests/DwSqlGraphQLQueryTests.cs index 4dca82f9be..27d292d500 100644 --- a/src/Service.Tests/SqlTests/GraphQLQueryTests/DwSqlGraphQLQueryTests.cs +++ b/src/Service.Tests/SqlTests/GraphQLQueryTests/DwSqlGraphQLQueryTests.cs @@ -97,6 +97,31 @@ ORDER BY [table0].[id] ASC await OneToOneJoinQuery(dwSqlQuery); } + /// + /// Test query on One-To-One relationship when the fields defining + /// the relationship in the entity include fields that are mapped in + /// that same entity. + /// + /// + [TestMethod] + public async Task OneToOneJoinQueryWithMappedFieldNamesInRelationship() + { + string dwSqlQuery = @" + SELECT COALESCE('['+STRING_AGG('{'+N'""fancyName"":' + ISNULL('""' + STRING_ESCAPE([fancyName],'json') + '""','null')+','+N'""fungus"":' + ISNULL([fungus],'null')+'}',', ')+']','[]') + FROM ( + SELECT TOP 100 [table0].[species] AS [fancyName], + (SELECT TOP 1 '{""habitat"":""' + STRING_ESCAPE([table1].[habitat], 'json') + '""}' + FROM [dbo].[fungi] AS [table1] + WHERE [table0].[species] = [table1].[habitat] AND [table1].[habitat] = [table0].[species] + ORDER BY [table1].[speciesid] ASC) AS [fungus] + FROM [dbo].[trees] AS [table0] + WHERE 1 = 1 + ORDER BY [table0].[treeId] ASC + ) AS [table0]"; + + await OneToOneJoinQueryWithMappedFieldNamesInRelationship(dwSqlQuery); + } + /// /// Test getting a single item by use of primary key /// diff --git a/src/Service.Tests/SqlTests/GraphQLQueryTests/GraphQLQueryTestBase.cs b/src/Service.Tests/SqlTests/GraphQLQueryTests/GraphQLQueryTestBase.cs index ac00e98b1e..7a380ba7ac 100644 --- a/src/Service.Tests/SqlTests/GraphQLQueryTests/GraphQLQueryTestBase.cs +++ b/src/Service.Tests/SqlTests/GraphQLQueryTests/GraphQLQueryTestBase.cs @@ -575,6 +575,32 @@ public async Task OneToOneJoinQuery(string dbQuery) SqlTestHelper.PerformTestEqualJsonStrings(expected, actual.GetProperty("items").ToString()); } + /// + /// Test One-To-One relationship when the fields defining + /// the relationship in the entity include fields that are mapped in + /// that same entity. + /// + [TestMethod] + public async Task OneToOneJoinQueryWithMappedFieldNamesInRelationship(string dbQuery) + { + string graphQLQueryName = "shrubs"; + string graphQLQuery = @"query { + shrubs { + items { + fancyName + fungus { + habitat + } + } + } + }"; + + JsonElement actual = await base.ExecuteGraphQLRequestAsync(graphQLQuery, graphQLQueryName, isAuthenticated: false); + string expected = await GetDatabaseResultAsync(dbQuery); + + SqlTestHelper.PerformTestEqualJsonStrings(expected, actual.GetProperty("items").ToString()); + } + /// /// This deeply nests a many-to-one/one-to-many join multiple times to /// show that it still results in a valid query. diff --git a/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLQueryTests.cs b/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLQueryTests.cs index bd74b6836b..57693c96a5 100644 --- a/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLQueryTests.cs +++ b/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLQueryTests.cs @@ -104,6 +104,34 @@ FOR JSON PATH await OneToOneJoinQuery(msSqlQuery); } + /// + /// Test query on One-To-One relationship when the fields defining + /// the relationship in the entity include fields that are mapped in + /// that same entity. + /// + [TestMethod] + public async Task OneToOneJoinQueryWithMappedFieldNamesInRelationship() + { + string msSqlQuery = @" + SELECT TOP 100 [table0].[species] AS [fancyName] + ,JSON_QUERY([table1_subq].[data]) AS [fungus] + FROM [dbo].[trees] AS [table0] + OUTER APPLY ( + SELECT TOP 1 [table1].[habitat] AS [habitat] + FROM [dbo].[fungi] AS [table1] + WHERE [table1].[habitat] = [table0].[species] + ORDER BY [table1].[habitat] ASC + FOR JSON PATH + ,INCLUDE_NULL_VALUES + ,WITHOUT_ARRAY_WRAPPER + ) AS [table1_subq]([data]) + WHERE 1 = 1 + FOR JSON PATH + ,INCLUDE_NULL_VALUES"; + + await OneToOneJoinQueryWithMappedFieldNamesInRelationship(msSqlQuery); + } + [TestMethod] public async Task QueryWithSingleColumnPrimaryKey() { diff --git a/src/Service.Tests/SqlTests/GraphQLQueryTests/MySqlGraphQLQueryTests.cs b/src/Service.Tests/SqlTests/GraphQLQueryTests/MySqlGraphQLQueryTests.cs index ca6af1f5e9..f0a27c7be3 100644 --- a/src/Service.Tests/SqlTests/GraphQLQueryTests/MySqlGraphQLQueryTests.cs +++ b/src/Service.Tests/SqlTests/GraphQLQueryTests/MySqlGraphQLQueryTests.cs @@ -128,6 +128,34 @@ ORDER BY `table0`.`id` ASC LIMIT 100 await OneToOneJoinQuery(mySqlQuery); } + /// + /// Test query on One-To-One relationship when the fields defining + /// the relationship in the entity include fields that are mapped in + /// that same entity. + /// + [TestMethod] + public async Task OneToOneJoinQueryWithMappedFieldNamesInRelationship() + { + string mySqlQuery = @" + SELECT COALESCE(JSON_ARRAYAGG(JSON_OBJECT('fancyName', `subq7`.`fancyName`, 'fungus', `subq7`.`fungus`)), JSON_ARRAY()) AS `data` + FROM ( + SELECT `table0`.`species` AS `fancyName`, + `table1_subq`.`data` AS `fungus` + FROM `trees` AS `table0` + LEFT OUTER JOIN LATERAL(SELECT JSON_OBJECT('habitat', `subq6`.`habitat`) AS `data` FROM ( + SELECT `table1`.`habitat` AS `habitat` + FROM `fungi` AS `table1` + WHERE `table1`.`habitat` = `table0`.`species` + ORDER BY `table1`.`habitat` ASC LIMIT 1 + ) AS `subq6`) AS `table1_subq` ON TRUE + WHERE 1 = 1 + LIMIT 100 + ) AS `subq7` + "; + + await OneToOneJoinQueryWithMappedFieldNamesInRelationship(mySqlQuery); + } + [TestMethod] public async Task QueryWithSingleColumnPrimaryKey() { diff --git a/src/Service.Tests/SqlTests/GraphQLQueryTests/PostgreSqlGraphQLQueryTests.cs b/src/Service.Tests/SqlTests/GraphQLQueryTests/PostgreSqlGraphQLQueryTests.cs index 789e4de853..f0a56bd131 100644 --- a/src/Service.Tests/SqlTests/GraphQLQueryTests/PostgreSqlGraphQLQueryTests.cs +++ b/src/Service.Tests/SqlTests/GraphQLQueryTests/PostgreSqlGraphQLQueryTests.cs @@ -91,6 +91,35 @@ ORDER BY ""table0"".""id"" ASC await OneToOneJoinQuery(postgresQuery); } + /// + /// Test query on One-To-One relationship when the fields defining + /// the relationship in the entity include fields that are mapped in + /// that same entity. + /// + [TestMethod] + public async Task OneToOneJoinQueryWithMappedFieldNamesInRelationship() + { + string postgresQuery = @" +SELECT COALESCE(jsonb_agg(to_jsonb(""subq7"")), '[]') AS ""data"" +FROM + (SELECT ""table0"".""species"" AS ""fancyName"", + ""table1_subq"".""data"" AS ""fungus"" + FROM ""public"".""trees"" AS ""table0"" + LEFT OUTER JOIN LATERAL + (SELECT to_jsonb(""subq6"") AS ""data"" + FROM + (SELECT ""table1"".""habitat"" AS ""habitat"" + FROM ""public"".""fungi"" AS ""table1"" + WHERE ""table1"".""habitat"" = ""table0"".""species"" + ORDER BY ""table1"".""habitat"" ASC + LIMIT 1) AS ""subq6"") AS ""table1_subq"" ON TRUE + WHERE 1 = 1 + LIMIT 100) AS ""subq7"" + "; + + await OneToOneJoinQueryWithMappedFieldNamesInRelationship(postgresQuery); + } + [TestMethod] public async Task QueryWithSingleColumnPrimaryKey() { diff --git a/src/Service.Tests/SqlTests/RestApiTests/Find/DwSqlFindApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Find/DwSqlFindApiTests.cs index e1a17bc4bc..5ebd469f84 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Find/DwSqlFindApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Find/DwSqlFindApiTests.cs @@ -436,7 +436,7 @@ public class DwSqlFindApiTests : FindApiTestBase { "FindTestWithDifferentMappingAfterSingleKeyPaginationAndOrderBy", $"SELECT TOP 101 [treeId], [species] AS [fancyName], [region], [height] FROM { _integrationMappingTable } " + - $"WHERE [trees].[treeId] < 2 " + + $"WHERE [trees].[species] > 'Pseudotsuga menziesii' " + $"ORDER BY [trees].[species] asc, [trees].[treeId] asc " + $"FOR JSON PATH, INCLUDE_NULL_VALUES" }, diff --git a/src/Service.Tests/SqlTests/RestApiTests/Find/MsSqlFindApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Find/MsSqlFindApiTests.cs index cee5305a5a..38383c0af4 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Find/MsSqlFindApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Find/MsSqlFindApiTests.cs @@ -444,7 +444,7 @@ public class MsSqlFindApiTests : FindApiTestBase { "FindTestWithDifferentMappingAfterSingleKeyPaginationAndOrderBy", $"SELECT TOP 101 [treeId], [species] AS [fancyName], [region], [height] FROM { _integrationMappingTable } " + - $"WHERE [trees].[treeId] < 2 " + + $"WHERE [trees].[species] > 'Pseudotsuga menziesii' " + $"ORDER BY [trees].[species] asc, [trees].[treeId] asc " + $"FOR JSON PATH, INCLUDE_NULL_VALUES" }, diff --git a/src/Service.Tests/SqlTests/RestApiTests/Find/MySqlFindApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Find/MySqlFindApiTests.cs index db385edbcc..0b19f52cd3 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Find/MySqlFindApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Find/MySqlFindApiTests.cs @@ -812,7 +812,7 @@ SELECT JSON_ARRAYAGG(JSON_OBJECT('treeId', treeId, 'fancyName', species, 'region FROM ( SELECT * FROM " + _integrationMappingTable + @" - WHERE treeId < 2 + WHERE species > 'Pseudotsuga menziesii' ORDER BY species asc, treeId asc LIMIT 101 ) AS subq" diff --git a/src/Service.Tests/SqlTests/RestApiTests/Find/PostgreSqlFindApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Find/PostgreSqlFindApiTests.cs index ab99890579..612b0885e0 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Find/PostgreSqlFindApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Find/PostgreSqlFindApiTests.cs @@ -820,9 +820,9 @@ LIMIT 1 @" SELECT json_agg(to_jsonb(subq)) AS data FROM ( - SELECT ""treeId"", ""species"" AS ""fancyName"", ""region"", ""height"" + SELECT ""treeId"", species AS ""fancyName"", region, height FROM " + _integrationMappingTable + @" - WHERE ""treeId"" < 2 + WHERE species > 'Pseudotsuga menziesii' ORDER BY species asc, ""treeId"" asc LIMIT 101 ) AS subq diff --git a/src/Service.Tests/Unittests/ConfigValidationUnitTests.cs b/src/Service.Tests/Unittests/ConfigValidationUnitTests.cs index 3d0cd3e030..dfcbfc4f34 100644 --- a/src/Service.Tests/Unittests/ConfigValidationUnitTests.cs +++ b/src/Service.Tests/Unittests/ConfigValidationUnitTests.cs @@ -410,7 +410,7 @@ string relationshipEntity x.ParseSchemaAndDbTableName("TEST_SOURCE_LINK")).Returns(("dbo", "TEST_SOURCE_LINK")); string discard; - _sqlMetadataProvider.Setup(x => x.TryGetBackingColumn(It.IsAny(), It.IsAny(), out discard)).Returns(true); + _sqlMetadataProvider.Setup(x => x.TryGetExposedColumnName(It.IsAny(), It.IsAny(), out discard)).Returns(true); Mock _metadataProviderFactory = new(); _metadataProviderFactory.Setup(x => x.GetMetadataProvider(It.IsAny())).Returns(_sqlMetadataProvider.Object); @@ -664,8 +664,8 @@ public void TestRelationshipWithoutSourceAndTargetFieldsAsValidBackingColumns( _sqlMetadataProvider.Setup>(x => x.EntityToDatabaseObject).Returns(mockDictionaryForEntityDatabaseObject); string discard; - _sqlMetadataProvider.Setup(x => x.TryGetBackingColumn(It.IsAny(), "noBackingColumn", out discard)).Returns(false); - _sqlMetadataProvider.Setup(x => x.TryGetBackingColumn(It.IsAny(), "backingColumn", out discard)).Returns(true); + _sqlMetadataProvider.Setup(x => x.TryGetExposedColumnName(It.IsAny(), "noBackingColumn", out discard)).Returns(false); + _sqlMetadataProvider.Setup(x => x.TryGetExposedColumnName(It.IsAny(), "backingColumn", out discard)).Returns(true); Mock _metadataProviderFactory = new(); _metadataProviderFactory.Setup(x => x.GetMetadataProvider(It.IsAny())).Returns(_sqlMetadataProvider.Object); @@ -795,7 +795,7 @@ public void TestRelationshipWithoutLinkingSourceAndTargetFieldsMatching( x.EntityToDatabaseObject).Returns(mockDictionaryForEntityDatabaseObject); string discard; - _sqlMetadataProvider.Setup(x => x.TryGetBackingColumn(It.IsAny(), It.IsAny(), out discard)).Returns(true); + _sqlMetadataProvider.Setup(x => x.TryGetExposedColumnName(It.IsAny(), It.IsAny(), out discard)).Returns(true); Mock _metadataProviderFactory = new(); _metadataProviderFactory.Setup(x => x.GetMetadataProvider(It.IsAny())).Returns(_sqlMetadataProvider.Object); diff --git a/src/Service.Tests/dab-config.DwSql.json b/src/Service.Tests/dab-config.DwSql.json index f698420a41..f0cc3a091c 100644 --- a/src/Service.Tests/dab-config.DwSql.json +++ b/src/Service.Tests/dab-config.DwSql.json @@ -1465,6 +1465,16 @@ ], "mappings": { "species": "fancyName" + }, + "relationships": { + "fungus": { + "cardinality": "one", + "target.entity": "Fungus", + "source.fields": [ "species" ], + "target.fields": [ "habitat" ], + "linking.source.fields": [], + "linking.target.fields": [] + } } }, "Fungus": { @@ -1540,6 +1550,16 @@ ], "mappings": { "spores": "hazards" + }, + "relationships": { + "shrub": { + "cardinality": "one", + "target.entity": "Shrub", + "source.fields": [ "habitat" ], + "target.fields": [ "species" ], + "linking.source.fields": [], + "linking.target.fields": [] + } } }, "books_view_all": { diff --git a/src/Service.Tests/dab-config.MsSql.json b/src/Service.Tests/dab-config.MsSql.json index aa80ef6f14..f9cf57d3c3 100644 --- a/src/Service.Tests/dab-config.MsSql.json +++ b/src/Service.Tests/dab-config.MsSql.json @@ -1929,6 +1929,16 @@ ], "mappings": { "species": "fancyName" + }, + "relationships": { + "fungus": { + "cardinality": "one", + "target.entity": "Fungus", + "source.fields": [ "species" ], + "target.fields": [ "habitat" ], + "linking.source.fields": [], + "linking.target.fields": [] + } } }, "Fungus": { @@ -2001,6 +2011,16 @@ ], "mappings": { "spores": "hazards" + }, + "relationships": { + "shrub": { + "cardinality": "one", + "target.entity": "Shrub", + "source.fields": [ "habitat" ], + "target.fields": [ "species" ], + "linking.source.fields": [], + "linking.target.fields": [] + } } }, "books_view_all": { diff --git a/src/Service.Tests/dab-config.MySql.json b/src/Service.Tests/dab-config.MySql.json index 97e245f2a0..e8401fcdcb 100644 --- a/src/Service.Tests/dab-config.MySql.json +++ b/src/Service.Tests/dab-config.MySql.json @@ -1355,6 +1355,16 @@ ], "mappings": { "species": "fancyName" + }, + "relationships": { + "fungus": { + "cardinality": "one", + "target.entity": "Fungus", + "source.fields": [ "species" ], + "target.fields": [ "habitat" ], + "linking.source.fields": [], + "linking.target.fields": [] + } } }, "Fungus": { @@ -1427,6 +1437,16 @@ ], "mappings": { "spores": "hazards" + }, + "relationships": { + "shrub": { + "cardinality": "one", + "target.entity": "Shrub", + "source.fields": [ "habitat" ], + "target.fields": [ "species" ], + "linking.source.fields": [], + "linking.target.fields": [] + } } }, "books_view_all": { diff --git a/src/Service.Tests/dab-config.PostgreSql.json b/src/Service.Tests/dab-config.PostgreSql.json index bb8c518511..4de845ea33 100644 --- a/src/Service.Tests/dab-config.PostgreSql.json +++ b/src/Service.Tests/dab-config.PostgreSql.json @@ -1452,6 +1452,16 @@ ], "mappings": { "species": "fancyName" + }, + "relationships": { + "fungus": { + "cardinality": "one", + "target.entity": "Fungus", + "source.fields": [ "species" ], + "target.fields": [ "habitat" ], + "linking.source.fields": [], + "linking.target.fields": [] + } } }, "Fungus": { @@ -1524,6 +1534,16 @@ ], "mappings": { "spores": "hazards" + }, + "relationships": { + "shrub": { + "cardinality": "one", + "target.entity": "Shrub", + "source.fields": [ "habitat" ], + "target.fields": [ "species" ], + "linking.source.fields": [], + "linking.target.fields": [] + } } }, "User_NonAutogenRelationshipColumn": {