Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
551f436
Disallowing one reference column to reference multiple columns in ano…
ayush3797 Dec 20, 2023
879a740
Removing redundant relationship
ayush3797 Jan 31, 2024
0918e46
resolving conflicts
ayush3797 Jan 31, 2024
8cacda9
updating exception
ayush3797 Feb 7, 2024
2180adf
updating logic to take care of order of fk definitions
ayush3797 Feb 7, 2024
fa7b3c4
adding comment
ayush3797 Feb 7, 2024
bd49238
refactor
ayush3797 Feb 7, 2024
2b3df6a
saving progress
ayush3797 Feb 7, 2024
02d64b3
nits
ayush3797 Feb 7, 2024
d990c0b
adding summary
ayush3797 Feb 16, 2024
2307080
removing redundant fk definition
ayush3797 Feb 16, 2024
ae2217e
removing unused fn
ayush3797 Feb 16, 2024
325e258
Condensing conditions
ayush3797 Feb 19, 2024
92b1686
clarifying comments
ayush3797 Feb 19, 2024
c154ae5
Merge branch 'main' into dev/agarwalayush/removingWrongFK
ayush3797 Feb 19, 2024
9b938a4
Merge branch 'main' into dev/agarwalayush/removingWrongFK
ayush3797 Feb 20, 2024
dacc356
Update src/Core/Services/MetadataProviders/SqlMetadataProvider.cs
ayush3797 Feb 22, 2024
c2b7da0
Update src/Core/Services/MetadataProviders/SqlMetadataProvider.cs
ayush3797 Feb 22, 2024
bfa4146
Update src/Core/Services/MetadataProviders/SqlMetadataProvider.cs
ayush3797 Feb 22, 2024
67a8170
Adding tests
ayush3797 Feb 27, 2024
a3611bc
Adding tests
ayush3797 Feb 27, 2024
eec0ba8
saving progress
ayush3797 Feb 28, 2024
530c2db
Merge branch 'dev/agarwalayush/removingWrongFK' of https://github.com…
ayush3797 Feb 29, 2024
590373e
addressing review
ayush3797 Mar 5, 2024
9ab2bff
reverting conn string change
ayush3797 Mar 13, 2024
60b2568
removing unnecessary tests
ayush3797 Mar 13, 2024
fa9b335
reverting unnecessary change
ayush3797 Mar 13, 2024
9f11389
reverting config change
ayush3797 Mar 13, 2024
728d4b5
Adding method summary
ayush3797 Mar 13, 2024
f92b8fc
Merge branch 'main' into dev/agarwalayush/removingWrongFK
seantleonard Mar 20, 2024
9d69d1c
nits
ayush3797 Mar 21, 2024
f296106
Merge branch 'dev/agarwalayush/removingWrongFK' of https://github.com…
ayush3797 Mar 21, 2024
1348cb6
add debugger displaynames to objects in DatabaseObject.cs classes to …
seantleonard Mar 25, 2024
f59b724
fix issues raised in #1940. Self joining table results in proper resu…
seantleonard Mar 26, 2024
2b25bfa
Fixed self-joining relationship causing null values in response. Upda…
seantleonard Mar 27, 2024
301bbcb
updated test asserts, updated logic to preserve old function for link…
seantleonard Mar 28, 2024
5a09b5a
Merge branch 'main' into dev/sean/selfReferencingRelationship
seantleonard Mar 28, 2024
ccbbe6b
address review feedback for function and var naming. also removed err…
seantleonard Mar 28, 2024
bdb1692
revised comments.
seantleonard Mar 30, 2024
0a4a975
Merge branch 'dev/sean/selfReferencingRelationship' of https://github…
seantleonard Mar 30, 2024
3fe9564
fixing confusing conditional when validting whether any fk referencin…
seantleonard Mar 30, 2024
194916a
accept merge conflict resolution suggestion.
seantleonard Apr 1, 2024
6f42f52
updating linking table logic.
seantleonard Apr 1, 2024
4da2040
merged main with conflict resolution
seantleonard Apr 1, 2024
14b89bc
Resolved errors and only process self-join relationships (excluding t…
seantleonard Apr 4, 2024
9a2c861
merge conflict resolution
seantleonard Apr 25, 2024
2432c54
Update comments and summaries.
seantleonard Apr 26, 2024
83e4afb
More comment clarification
seantleonard Apr 26, 2024
ac0f96a
fix unit tests to have newest field count and fix the expected/actual…
seantleonard Apr 26, 2024
d5ffdc5
merge main and resolved conflicts in sqlmetadataprovider
seantleonard Apr 26, 2024
1c94d0f
formatting.
seantleonard Apr 26, 2024
f54afe0
updated config generators and config for dwsql/mssql plus db deploy f…
seantleonard Apr 26, 2024
37cfec3
updated comment spelling.
seantleonard Apr 26, 2024
6f339c0
update *sql-commands.txt to include "dbo_DimAccount" entity used for …
seantleonard Apr 26, 2024
5dbed4a
updating *sql-commands.txt to have proper 'add' verb and also updated…
seantleonard Apr 26, 2024
a3c0fdd
update comments
seantleonard Apr 26, 2024
21f1697
updated param / variable name used to represent subqueryTableAlias. I…
seantleonard Apr 26, 2024
fbd4c49
clarifying comments in AddJoinPredicatesForSelfJoinedEntity. and adde…
seantleonard Apr 26, 2024
eb9ae60
update to make comments accurate when processing relationships.
seantleonard Apr 26, 2024
a84c78e
update spacing
seantleonard Apr 26, 2024
849cc46
clarifiying comments and spacing. added helper IsSelfJoiningRelations…
seantleonard Apr 27, 2024
55f969a
fix verified file using output of CLI tool.
seantleonard Apr 27, 2024
4cb2fbf
update tests to use mysql
seantleonard Apr 29, 2024
ba02f72
match config to dab cli output config for DimAccounts entity.
seantleonard Apr 29, 2024
a49a60b
pg add
seantleonard Apr 29, 2024
6e5f4f4
adds fix from #2175 in order to get pg integration tests passing.
seantleonard Apr 29, 2024
8e3d8c5
merge conflict resolution (just comments) for sqlmetadataprovider
seantleonard May 1, 2024
c442dc1
update verified tests for mysql and pg to support dbo_DimAccount
seantleonard May 1, 2024
678f0dd
fix source name from DimAccount to dimaccount for both pg and mysql c…
seantleonard May 1, 2024
b333753
Merge branch 'main' into dev/sean/selfReferencingRelationship
seantleonard May 1, 2024
b71dd55
fix pg mysql scripts/verified.
seantleonard May 1, 2024
44feab4
update to correct pg commands. Couldn't repro the error locally even …
seantleonard May 2, 2024
5f016bc
Merge branch 'main' into dev/sean/selfReferencingRelationship
seantleonard May 2, 2024
713704e
remove unused code and add comments to entityrelationshipkey specifiy…
seantleonard May 7, 2024
82da84e
Merge branch 'main' into dev/sean/selfReferencingRelationship
seantleonard May 7, 2024
71a4551
updated serialization tests to accommodate removed property.
seantleonard May 7, 2024
bbeb4a2
update comment for RelationshipRole and add newline to mssql config. …
seantleonard May 7, 2024
d3d705c
Merge branch 'dev/sean/selfReferencingRelationship' of https://github…
seantleonard May 7, 2024
d36936f
Fix comment grammar.
seantleonard May 9, 2024
0cba4c4
Merge branch 'main' into dev/sean/selfReferencingRelationship
seantleonard May 9, 2024
143dca7
Merge branch 'main' into dev/sean/selfReferencingRelationship
seantleonard May 9, 2024
37fc3f6
added this change to consolidate the referencing/referenced columns …
seantleonard May 9, 2024
8ea5283
Merge branch 'main' into dev/sean/selfReferencingRelationship
Aniruddh25 May 10, 2024
126738d
update npgsql per dotnet format verbose emitted package version issue.
seantleonard May 10, 2024
e1c4c49
update npgsql to 8.0.3 per https://github.com/advisories/GHSA-x9vc-6h…
seantleonard May 10, 2024
c16b32c
update npgsql to 7.0.7 to avoid jsonserialization error with 8+. also…
seantleonard May 10, 2024
4de9a9b
Merge branch 'main' into dev/sean/selfReferencingRelationship
seantleonard May 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion config-generators/dwsql-commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,7 @@ update GetBooks --config "dab-config.DwSql.json" --permissions "authenticated:ex
update GetBook --config "dab-config.DwSql.json" --permissions "authenticated:execute" --rest.methods "Get"
update CountBooks --config "dab-config.DwSql.json" --permissions "authenticated:execute"
update Sales --config "dab-config.DwSql.json" --permissions "authenticated:*"
update GetAuthorsHistoryByFirstName --config "dab-config.DwSql.json" --permissions "authenticated:execute"
update GetAuthorsHistoryByFirstName --config "dab-config.DwSql.json" --permissions "authenticated:execute"
add dbo_DimAccount --config "dab-config.DwSql.json" --source "DimAccount" --permissions "anonymous:*" --rest true --graphql true
update dbo_DimAccount --config "dab-config.DwSql.json" --relationship parent_account --target.entity dbo_DimAccount --cardinality one --relationship.fields "ParentAccountKey:AccountKey"
update dbo_DimAccount --config "dab-config.DwSql.json" --relationship child_accounts --target.entity dbo_DimAccount --cardinality many --relationship.fields "AccountKey:ParentAccountKey"
3 changes: 3 additions & 0 deletions config-generators/mssql-commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,6 @@ update series --config "dab-config.MsSql.json" --permissions "TestNestedFilterMa
update series --config "dab-config.MsSql.json" --permissions "TestNestedFilterOneMany_ColumnForbidden:read"
update series --config "dab-config.MsSql.json" --permissions "TestNestedFilterOneMany_EntityReadForbidden:read"
update DefaultBuiltInFunction --config "dab-config.MsSql.json" --permissions "anonymous:create" --fields.exclude "current_date,next_date"
add dbo_DimAccount --config "dab-config.MsSql.json" --source "DimAccount" --permissions "anonymous:*" --rest true --graphql true
update dbo_DimAccount --config "dab-config.MsSql.json" --relationship parent_account --target.entity dbo_DimAccount --cardinality one --relationship.fields "ParentAccountKey:AccountKey"
update dbo_DimAccount --config "dab-config.MsSql.json" --relationship child_accounts --target.entity dbo_DimAccount --cardinality many --relationship.fields "AccountKey:ParentAccountKey"
3 changes: 3 additions & 0 deletions config-generators/mysql-commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,6 @@ update Sales --config "dab-config.MySql.json" --permissions "authenticated:*"
update Bookmarks --config "dab-config.MySql.json" --permissions "authenticated:*"
update MappedBookmarks --config "dab-config.MySql.json" --permissions "authenticated:*" --map "id:bkid,bkname:name"
update DefaultBuiltInFunction --config "dab-config.MySql.json" --permissions "anonymous:create" --fields.exclude "current_date,next_date"
add dbo_DimAccount --config "dab-config.MySql.json" --source "dimaccount" --permissions "anonymous:*" --rest true --graphql true
update dbo_DimAccount --config "dab-config.MySql.json" --relationship parent_account --target.entity dbo_DimAccount --cardinality one --relationship.fields "ParentAccountKey:AccountKey"
update dbo_DimAccount --config "dab-config.MySql.json" --relationship child_accounts --target.entity dbo_DimAccount --cardinality many --relationship.fields "AccountKey:ParentAccountKey"
4 changes: 4 additions & 0 deletions config-generators/postgresql-commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,7 @@ update series --config "dab-config.PostgreSql.json" --permissions "TestNestedFil
update series --config "dab-config.PostgreSql.json" --permissions "TestNestedFilterOneMany_ColumnForbidden:read"
update series --config "dab-config.PostgreSql.json" --permissions "TestNestedFilterOneMany_EntityReadForbidden:read"
update DefaultBuiltInFunction --config "dab-config.PostgreSql.json" --permissions "anonymous:create" --fields.exclude "current_date,next_date"
add dbo_DimAccount --config "dab-config.PostgreSql.json" --source "dimaccount" --permissions "anonymous:*" --rest true --graphql true
update dbo_DimAccount --config "dab-config.PostgreSql.json" --map "parentaccountkey:ParentAccountKey,accountkey:AccountKey"
update dbo_DimAccount --config "dab-config.PostgreSql.json" --relationship parent_account --target.entity dbo_DimAccount --cardinality one --relationship.fields "parentaccountkey:accountkey"
update dbo_DimAccount --config "dab-config.PostgreSql.json" --relationship child_accounts --target.entity dbo_DimAccount --cardinality many --relationship.fields "accountkey:parentaccountkey"
90 changes: 88 additions & 2 deletions src/Config/DatabasePrimitives/DatabaseObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,9 @@ public class ViewDefinition : SourceDefinition { }
public class RelationshipMetadata
{
/// <summary>
/// Dictionary of target entity name to ForeignKeyDefinition.
/// Dictionary tracking ForeignKeyDefinitions for a given target entity.
/// key: {targetEntityName}
/// value: [{ForeignKeyDefinition},{...}]
/// </summary>
[JsonInclude]
public Dictionary<string, List<ForeignKeyDefinition>> TargetEntityToFkDefinitionMap { get; private set; }
Expand Down Expand Up @@ -271,9 +273,28 @@ public ColumnDefinition(Type systemType)
}
}

[DebuggerDisplay("ReferencingDbTable = {Pair.ReferencingDbTable.FullName} (Count = {ReferencingColumns.Count}), ReferencedDbTable = {Pair.ReferencedDbTable.FullName} (Count = {ReferencedColumns.Count})")]
[DebuggerDisplay("Relationship: {RelationshipName} ReferencingDbTable = {Pair.ReferencingDbTable.FullName} (Count = {ReferencingColumns.Count}), ReferencedDbTable = {Pair.ReferencedDbTable.FullName} (Count = {ReferencedColumns.Count})")]
public class ForeignKeyDefinition
{
public string SourceEntityName { get; set; } = string.Empty;

/// <summary>
/// Identifies whether the referencing entity is the target, source, or linking entity.
/// Enables Resolve{Target/Source}Columns() functions to return the correct columns.
/// </summary>
public RelationshipRole ReferencingEntityRole { get; init; } = RelationshipRole.None;

/// <summary>
/// Identifies whether the referenced entity is the target, source, or linking entity.
/// Enables Resolve{Target/Source}Columns() functions to return the correct columns.
/// </summary>
public RelationshipRole ReferencedEntityRole { get; init; } = RelationshipRole.None;

/// <summary>
/// The relationship name defined for the relationship in the runtime config.
/// </summary>
public string RelationshipName { get; init; } = string.Empty;

/// <summary>
/// The referencing and referenced table pair.
/// </summary>
Expand All @@ -293,6 +314,56 @@ public class ForeignKeyDefinition
/// </summary>
public List<string> ReferencingColumns { get; set; } = new();

/// <summary>
/// Resolves the target columns based on the role of the referencing and referenced entities.
/// The role of the referencing and referenced entities is important because
/// target entity can either be the "referenced" or "referencing" entity.
/// </summary>
/// <returns>List of the target entity's columns</returns>
/// <exception cref="Exception">Raised when the ForeignKeyDefinition represents a relationship
/// between a source (source fields) and linking object (linking source fields).</exception>
public List<string> ResolveTargetColumns()
{
if (ReferencingEntityRole == RelationshipRole.Target)
{
return ReferencingColumns;
}
else if (ReferencedEntityRole == RelationshipRole.Target)
{
return ReferencedColumns;
}
else
{
throw new Exception(
message: "Unable to resolve target columns because this ForeignKeyDefinition relates a target entity and linking object.");
}
}

/// <summary>
/// Resolves the source columns based on the role of the referencing and referenced entities.
/// The role of the referencing and referenced entities is important because
/// source entity can either be the "referenced" or "referencing" entity.
/// </summary>
/// <returns>List of the source entity's columns</returns>
/// <exception cref="Exception">Raised when the ForeignKeyDefinition represents a relationship
/// between a target (target columns) and linking object (linking target fields).</exception>
public List<string> ResolveSourceColumns()
{
if (ReferencingEntityRole == RelationshipRole.Source)
{
return ReferencingColumns;
}
else if (ReferencedEntityRole == RelationshipRole.Source)
{
return ReferencedColumns;
}
else
{
throw new Exception(
message: "Unable to resolve source columns because this ForeignKeyDefinition relates a source entity and linking object.");
}
}

public override bool Equals(object? other)
{
return Equals(other as ForeignKeyDefinition);
Expand All @@ -316,12 +387,27 @@ public override int GetHashCode()
[DebuggerDisplay("ReferencingDbTable = {ReferencingDbTable.FullName}, ReferencedDbTable = {ReferencedDbTable.FullName}")]
public class RelationShipPair
{
/// <summary>
/// Relationship name specified in the runtime config.
/// </summary>
public string RelationshipName { get; set; } = string.Empty;

public RelationShipPair() { }

public RelationShipPair(
DatabaseTable referencingDbObject,
DatabaseTable referencedDbObject)
{
ReferencingDbTable = referencingDbObject;
ReferencedDbTable = referencedDbObject;
}

public RelationShipPair(
string relationshipName,
DatabaseTable referencingDbObject,
DatabaseTable referencedDbObject)
{
RelationshipName = relationshipName;
ReferencingDbTable = referencingDbObject;
ReferencedDbTable = referencedDbObject;
}
Expand Down
49 changes: 49 additions & 0 deletions src/Config/ObjectModel/EntityRelationshipKey.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Diagnostics;

namespace Azure.DataApiBuilder.Config.ObjectModel
{
/// <summary>
/// Identifies a specific value pair:
/// 1. entity name
/// 2. relationship name
/// Which can be used to uniquely identify a relationship (ForeignKeyDefinition object(s)).
/// </summary>
[DebuggerDisplay("{EntityName} - {RelationshipName}")]
public class EntityRelationshipKey
{
/// <summary>
/// Source entity name which contains the relationship configuration.
/// </summary>
public string EntityName { get; set; }
public string RelationshipName { get; set; }

public EntityRelationshipKey(string entityName, string relationshipName)
{
EntityName = entityName;
RelationshipName = relationshipName;
}

public override bool Equals(object? other)
{
return Equals(other as EntityRelationshipKey);
}

public bool Equals(EntityRelationshipKey? other)
{
if (other == null)
{
return false;
}

return EntityName.Equals(other.EntityName) && RelationshipName.Equals(other.RelationshipName);
}

public override int GetHashCode()
{
return HashCode.Combine(EntityName, RelationshipName);
}
}
}
21 changes: 21 additions & 0 deletions src/Config/ObjectModel/RelationshipRole.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace Azure.DataApiBuilder.Config.ObjectModel;

/// <summary>
/// Denotes the role of a referencing or referenced table in a relationship.
/// Default value is None because the role is only resolved to help DAB
/// create join predicates for self-referencing relationships.
/// In non self-join relationships, DAB uses the ForeignKeyDefinition.RelationShipPair
/// to determine the referencing/referenced entity. RelationShipPair isn't sufficient
/// for self-join relationships because the DatabaseObjects used to represent the pair
/// reference the same object: e.g. both Referenced/Referencing entity would point to 'dbo.MyTable'
/// </summary>
public enum RelationshipRole
{
None,
Source,
Target,
Linking
}
6 changes: 3 additions & 3 deletions src/Core/Models/GraphQLFilterParsers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -425,9 +425,9 @@ private void HandleNestedFilterForSql(
// Add JoinPredicates to the subquery query structure so a predicate connecting
// the outer table is added to the where clause of subquery
existsQuery.AddJoinPredicatesForRelatedEntity(
queryStructure.EntityName,
queryStructure.SourceAlias,
existsQuery);
targetEntityName: queryStructure.EntityName,
relatedSourceAlias: queryStructure.SourceAlias,
subQuery: existsQuery);

// The right operand is the SqlExistsQueryStructure.
PredicateOperand right = new(existsQuery);
Expand Down
3 changes: 1 addition & 2 deletions src/Core/Models/SqlQueryStructures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,7 @@ public ulong Current()
}

/// <summary>
/// A simple class that is used to hold the information about joins that
/// are part of a SQL query.
/// Holds the information about joins that are part of a SQL query.
/// <summary>
/// <param name="DbObject">The name of the database object containing table metadata like joined tables.</param>
/// <param name="TableAlias">The alias of the table that is joined with.</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,85 @@ public Type GetColumnSystemType(string columnName)
/// <summary>
/// Based on the relationship metadata involving referenced and
/// referencing columns of a foreign key, add the join predicates
/// to the subquery Query structure created for the given target entity Name
/// and related source alias.
/// to the subquery QueryStructure created for the given target's entity name
/// and related target table source alias (name of table used in subquery).
/// There are only a couple of options for the foreign key - we only use the
/// valid foreign key definition. It is guaranteed at least one fk definition
/// will be valid since the MetadataProvider.ValidateAllFkHaveBeenInferred.
/// </summary>
/// <param name="fkLookupKey">{entityName, relationshipName} used to lookup foreign key metadata.</param>
/// <param name="targetEntityName">Related(target) entity's name.</param>
/// <param name="subqueryTargetTableAlias">The alias assigned for the underlying source of this related entity.</param>
/// <param name="subQuery">The subquery to which the join predicates are to be added.</param>
public void AddJoinPredicatesForRelationship(
EntityRelationshipKey fkLookupKey,
string targetEntityName,
string subqueryTargetTableAlias,
BaseSqlQueryStructure subQuery)
{
if (string.Equals(fkLookupKey.EntityName, targetEntityName))
{
AddJoinPredicatesForSelfJoinedEntity(
fkLookupKey: fkLookupKey,
subqueryTargetTableAlias: subqueryTargetTableAlias,
subQuery: subQuery);
}
else
{
AddJoinPredicatesForRelatedEntity(
targetEntityName: targetEntityName,
relatedSourceAlias: subqueryTargetTableAlias,
subQuery: subQuery);
}
}

/// <summary>
/// Add query predicates for self-joined entity.
/// Example pseudo tsql to illustrate what the predicates enable:
/// SELECT [columns] FROM [SqlQueryStructure.SourceAlias] // table0
/// JSON_QUERY(...) AS [fkLookupKey.relationshipName] // RelationshipName represents the sub query.
/// OUTER APPLY (
/// // The param 'subQuery' captures the contents of this OUTER APPLY
/// SELECT [columns] FROM [functionParams.subqueryTargetTableAlias] // table1
/// WHERE [table0].[fk.SourceColumn] = [table1].[fk.TargetColumn]
/// )
/// WHERE [table0].[fk.SourceColumn] = [@param value from request]
///
/// Process self-joining entity relationship. Excludes support for processing
/// self-joining relationships in GraphQL query filters (nested filter entities).
/// </summary>
/// <param name="fkLookupKey">{entityName, relationshipName} used to lookup foreign key metadata.</param>
/// <param name="subqueryTargetTableAlias">The table alias of the target entity/ subject of the sub-query.</param>
/// <param name="subQuery">The subquery to which the join predicates are to be added.</param>
/// <exception cref="DataApiBuilderException">Raised when an entity's relationship config is not found in the
/// metadata provider.</exception>
private void AddJoinPredicatesForSelfJoinedEntity(
EntityRelationshipKey fkLookupKey,
string subqueryTargetTableAlias,
BaseSqlQueryStructure subQuery)
{
if (MetadataProvider.RelationshipToFkDefinition.TryGetValue(key: fkLookupKey, out ForeignKeyDefinition? fkDef))
{
subQuery.Predicates.AddRange(
CreateJoinPredicates(
leftTableAlias: SourceAlias,
leftColumnNames: fkDef.ResolveSourceColumns(),
rightTableAlias: subqueryTargetTableAlias,
rightColumnNames: fkDef.ResolveTargetColumns()));
}
else
{
throw new DataApiBuilderException(
message: $"Could not find relationship between self-joined entity: {EntityName}.",
statusCode: HttpStatusCode.BadRequest,
subStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest);
}
}

/// <summary>
/// Based on the relationship metadata involving referenced and
/// referencing columns of a foreign key, add the join predicates
/// to the subquery Query structure created for linking objects.
/// There are only a couple of options for the foreign key - we only use the
/// valid foreign key definition. It is guaranteed at least one fk definition
/// will be valid since the MetadataProvider.ValidateAllFkHaveBeenInferred.
Expand Down Expand Up @@ -174,8 +251,8 @@ public void AddJoinPredicatesForRelatedEntity(
out foreignKeyDefinitions))
{
Dictionary<DatabaseObject, string> associativeTableAndAliases = new();
// For One-One and One-Many, not all fk definitions would be valid
// but at least 1 will be.
// For One-One and One-Many, not all fk definitions are valid
// and at least 1 will be.
// Identify the side of the relationship first, then check if its valid
// by ensuring the referencing and referenced column count > 0
// before adding the predicates.
Expand Down
14 changes: 9 additions & 5 deletions src/Core/Resolvers/Sql Query Structures/SqlQueryStructure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -791,11 +791,15 @@ private void AddGraphQLFields(IReadOnlyList<ISelectionNode> selections, RuntimeC
// use the _underlyingType from the subquery which will be overridden appropriately if the query is paginated
ObjectType subunderlyingType = subquery._underlyingFieldType;
string targetEntityName = MetadataProvider.GetEntityName(subunderlyingType.Name);
string subtableAlias = subquery.SourceAlias;

AddJoinPredicatesForRelatedEntity(targetEntityName, subtableAlias, subquery);

string subqueryAlias = $"{subtableAlias}_subq";
string subqueryTableAlias = subquery.SourceAlias;
EntityRelationshipKey currentEntityRelationshipKey = new(EntityName, relationshipName: fieldName);
AddJoinPredicatesForRelationship(
fkLookupKey: currentEntityRelationshipKey,
targetEntityName,
subqueryTargetTableAlias: subqueryTableAlias,
subquery);

string subqueryAlias = $"{subqueryTableAlias}_subq";
JoinQueries.Add(subqueryAlias, subquery);
Columns.Add(new LabelledColumn(tableSchema: subquery.DatabaseObject.SchemaName,
tableName: subquery.DatabaseObject.Name,
Expand Down
Loading