in src/Core/Resolvers/Sql Query Structures/BaseSqlQueryStructure.cs [232:338]
public void AddJoinPredicatesForRelatedEntity(
string targetEntityName,
string relatedSourceAlias,
BaseSqlQueryStructure subQuery)
{
SourceDefinition sourceDefinition = GetUnderlyingSourceDefinition();
DatabaseObject relatedEntityDbObject = MetadataProvider.EntityToDatabaseObject[targetEntityName];
SourceDefinition relatedEntitySourceDefinition = MetadataProvider.GetSourceDefinition(targetEntityName);
if (// Search for the foreign key information either in the source or target entity.
sourceDefinition.SourceEntityRelationshipMap.TryGetValue(
EntityName,
out RelationshipMetadata? relationshipMetadata)
&& relationshipMetadata.TargetEntityToFkDefinitionMap.TryGetValue(
targetEntityName,
out List<ForeignKeyDefinition>? foreignKeyDefinitions)
|| relatedEntitySourceDefinition.SourceEntityRelationshipMap.TryGetValue(
targetEntityName, out relationshipMetadata)
&& relationshipMetadata.TargetEntityToFkDefinitionMap.TryGetValue(
EntityName,
out foreignKeyDefinitions))
{
Dictionary<DatabaseObject, string> associativeTableAndAliases = new();
// 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.
foreach (ForeignKeyDefinition foreignKeyDefinition in foreignKeyDefinitions)
{
// First identify which side of the relationship, this fk definition
// is looking at.
if (foreignKeyDefinition.Pair.ReferencingDbTable.Equals(DatabaseObject))
{
// Case where fk in parent entity references the nested entity.
// Verify this is a valid fk definition before adding the join predicate.
if (foreignKeyDefinition.ReferencingColumns.Count > 0
&& foreignKeyDefinition.ReferencedColumns.Count > 0)
{
subQuery.Predicates.AddRange(CreateJoinPredicates(
SourceAlias,
foreignKeyDefinition.ReferencingColumns,
relatedSourceAlias,
foreignKeyDefinition.ReferencedColumns));
}
}
else if (foreignKeyDefinition.Pair.ReferencingDbTable.Equals(relatedEntityDbObject))
{
// Case where fk in nested entity references the parent entity.
if (foreignKeyDefinition.ReferencingColumns.Count > 0
&& foreignKeyDefinition.ReferencedColumns.Count > 0)
{
subQuery.Predicates.AddRange(CreateJoinPredicates(
relatedSourceAlias,
foreignKeyDefinition.ReferencingColumns,
SourceAlias,
foreignKeyDefinition.ReferencedColumns));
}
}
else
{
DatabaseObject associativeTableDbObject =
foreignKeyDefinition.Pair.ReferencingDbTable;
// Case when the linking object is the referencing table
if (!associativeTableAndAliases.TryGetValue(
associativeTableDbObject,
out string? associativeTableAlias))
{
// this is the first fk definition found for this associative table.
// create an alias for it and store for later lookup.
associativeTableAlias = CreateTableAlias();
associativeTableAndAliases.Add(associativeTableDbObject, associativeTableAlias);
}
if (foreignKeyDefinition.Pair.ReferencedDbTable.Equals(DatabaseObject))
{
subQuery.Predicates.AddRange(CreateJoinPredicates(
associativeTableAlias,
foreignKeyDefinition.ReferencingColumns,
SourceAlias,
foreignKeyDefinition.ReferencedColumns));
}
else
{
subQuery.Joins.Add(new SqlJoinStructure
(
associativeTableDbObject,
associativeTableAlias,
CreateJoinPredicates(
associativeTableAlias,
foreignKeyDefinition.ReferencingColumns,
relatedSourceAlias,
foreignKeyDefinition.ReferencedColumns
).ToList()
));
}
}
}
}
else
{
throw new DataApiBuilderException(
message: $"Could not find relationship between entities: {EntityName} and " +
$"{targetEntityName}.",
statusCode: HttpStatusCode.BadRequest,
subStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest);
}
}