Skip to content

Commit

Permalink
Add immutable annotation support to TableExpressionBase
Browse files Browse the repository at this point in the history
Resolves #28120

Only SelectExpression does mutable way, all other expressions will recreate with new annotations.
  • Loading branch information
smitpatel committed Aug 11, 2022
1 parent b57a40b commit 30d4b22
Show file tree
Hide file tree
Showing 18 changed files with 150 additions and 176 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1321,11 +1321,6 @@ entityShaperExpression.ValueBufferExpression is ProjectionBindingExpression proj

return innerShaper;
}

private static Expression AddConvertToObject(Expression expression)
=> expression.Type.IsValueType
? Expression.Convert(expression, typeof(object))
: expression;
}

private ShapedQueryExpression TranslateTwoParameterSelector(ShapedQueryExpression source, LambdaExpression resultSelector)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1655,11 +1655,11 @@ SelectExpression BuildInnerSelectExpressionForOwnedTypeMappedToDifferentTable(
: foreignKey.PrincipalKey.Properties[0]);

var sourceTable = FindRootTableExpressionForColumn(sourceColumn);
var ownedTable = new TableExpression(targetTable);
TableExpressionBase ownedTable = new TableExpression(targetTable);

foreach (var annotation in sourceTable.GetAnnotations())
{
ownedTable.SetAnnotation(annotation.Name, annotation.Value);
ownedTable = ownedTable.AddAnnotation(annotation.Name, annotation.Value);
}

return _sqlExpressionFactory.Select(targetEntityType, ownedTable);
Expand Down Expand Up @@ -1688,11 +1688,6 @@ static TableExpressionBase FindRootTableExpressionForColumn(ColumnExpression col
}
}

private static Expression AddConvertToObject(Expression expression)
=> expression.Type.IsValueType
? Expression.Convert(expression, typeof(object))
: expression;

private EntityProjectionExpression GetEntityProjectionExpression(EntityShaperExpression entityShaperExpression)
=> entityShaperExpression.ValueBufferExpression switch
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public virtual CrossApplyExpression Update(TableExpressionBase table)
? new CrossApplyExpression(table, GetAnnotations())
: this;

/// <inheritdoc />
protected override TableExpressionBase CreateWithAnnotations(IEnumerable<IAnnotation> annotations)
=> new CrossApplyExpression(Table, GetAnnotations());

/// <inheritdoc />
protected override void Print(ExpressionPrinter expressionPrinter)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public virtual CrossJoinExpression Update(TableExpressionBase table)
? new CrossJoinExpression(table, GetAnnotations())
: this;

/// <inheritdoc />
protected override TableExpressionBase CreateWithAnnotations(IEnumerable<IAnnotation> annotations)
=> new CrossJoinExpression(Table, annotations);

/// <inheritdoc />
protected override void Print(ExpressionPrinter expressionPrinter)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ public virtual ExceptExpression Update(SelectExpression source1, SelectExpressio
? new ExceptExpression(Alias, source1, source2, IsDistinct, GetAnnotations())
: this;

/// <inheritdoc />
protected override TableExpressionBase CreateWithAnnotations(IEnumerable<IAnnotation> annotations)
=> new ExceptExpression(Alias, Source1, Source2, IsDistinct, annotations);

/// <inheritdoc />
protected override void Print(ExpressionPrinter expressionPrinter)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ public virtual FromSqlExpression Update(Expression arguments)
? new FromSqlExpression(Alias, _table, Sql, arguments, GetAnnotations())
: this;

/// <inheritdoc />
protected override TableExpressionBase CreateWithAnnotations(IEnumerable<IAnnotation> annotations)
=> new FromSqlExpression(Alias, _table, Sql, Arguments, annotations);

/// <inheritdoc />
ITableBase ITableBasedExpression.Table => _table;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ public virtual InnerJoinExpression Update(TableExpressionBase table, SqlExpressi
? new InnerJoinExpression(table, joinPredicate, GetAnnotations())
: this;

/// <inheritdoc />
protected override TableExpressionBase CreateWithAnnotations(IEnumerable<IAnnotation> annotations)
=> new InnerJoinExpression(Table, JoinPredicate, annotations);

/// <inheritdoc />
protected override void Print(ExpressionPrinter expressionPrinter)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ public virtual IntersectExpression Update(SelectExpression source1, SelectExpres
? new IntersectExpression(Alias, source1, source2, IsDistinct, GetAnnotations())
: this;

/// <inheritdoc />
protected override TableExpressionBase CreateWithAnnotations(IEnumerable<IAnnotation> annotations)
=> new IntersectExpression(Alias, Source1, Source2, IsDistinct, annotations);

/// <inheritdoc />
protected override void Print(ExpressionPrinter expressionPrinter)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ public virtual LeftJoinExpression Update(TableExpressionBase table, SqlExpressio
? new LeftJoinExpression(table, joinPredicate, GetAnnotations())
: this;

/// <inheritdoc />
protected override TableExpressionBase CreateWithAnnotations(IEnumerable<IAnnotation> annotations)
=> new LeftJoinExpression(Table, JoinPredicate, annotations);

/// <inheritdoc />
protected override void Print(ExpressionPrinter expressionPrinter)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public virtual OuterApplyExpression Update(TableExpressionBase table)
? new OuterApplyExpression(table, GetAnnotations())
: this;

/// <inheritdoc />
protected override TableExpressionBase CreateWithAnnotations(IEnumerable<IAnnotation> annotations)
=> new OuterApplyExpression(Table, annotations);

/// <inheritdoc />
protected override void Print(ExpressionPrinter expressionPrinter)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,9 @@ public TpcTablesExpression Prune(IReadOnlyList<string> discriminatorValues)
// This is implementation detail hence visitors are not supposed to see inside unless they really need to.
protected override Expression VisitChildren(ExpressionVisitor visitor) => this;

protected override TableExpressionBase CreateWithAnnotations(IEnumerable<IAnnotation> annotations)
=> new TpcTablesExpression(Alias, EntityType, SelectExpressions, annotations);

protected override void Print(ExpressionPrinter expressionPrinter)
{
expressionPrinter.AppendLine("(");
Expand Down
46 changes: 45 additions & 1 deletion src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public sealed partial class SelectExpression : TableExpressionBase
private readonly List<string?> _aliasForClientProjections = new();
private CloningExpressionVisitor? _cloningExpressionVisitor;

private SortedDictionary<string, IAnnotation>? _annotations;

#if DEBUG
private List<string>? _removedAliases;
#endif
Expand All @@ -68,13 +70,22 @@ private SelectExpression(
List<SqlExpression> groupBy,
List<OrderingExpression> orderings,
IEnumerable<IAnnotation> annotations)
: base(alias, annotations)
: base(alias)
{
_projection = projections;
_tables = tables;
_tableReferences = tableReferences;
_groupBy = groupBy;
_orderings = orderings;

if (annotations != null)
{
_annotations = new SortedDictionary<string, IAnnotation>();
foreach (var annotation in annotations)
{
_annotations[annotation.Name] = annotation;
}
}
}

private SelectExpression(string? alias)
Expand Down Expand Up @@ -3776,6 +3787,39 @@ public SelectExpression Update(
return newSelectExpression;
}

/// <inheritdoc />
protected override TableExpressionBase CreateWithAnnotations(IEnumerable<IAnnotation> annotations)
=> throw new NotImplementedException("inconceivable");

/// <inheritdoc />
public override TableExpressionBase AddAnnotation(string name, object? value)
{
var oldAnnotation = FindAnnotation(name);
if (oldAnnotation != null)
{
return Equals(oldAnnotation.Value, value)
? this
: throw new InvalidOperationException(CoreStrings.DuplicateAnnotation(name, this.Print()));
}

_annotations ??= new();
_annotations[name] = new Annotation(name, value);

return this;
}

/// <inheritdoc />
public override IAnnotation? FindAnnotation(string name)
=> _annotations == null
? null
: _annotations.TryGetValue(name, out var annotation)
? annotation
: null;

/// <inheritdoc />
public override IEnumerable<IAnnotation> GetAnnotations()
=> _annotations?.Values ?? Enumerable.Empty<IAnnotation>();

/// <inheritdoc />
protected override void Print(ExpressionPrinter expressionPrinter)
{
Expand Down
41 changes: 22 additions & 19 deletions src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,6 @@ private TableExpression(ITableBase table, IEnumerable<IAnnotation>? annotations)
Table = table;
}

/// <inheritdoc />
ITableBase ITableBasedExpression.Table => Table;

/// <inheritdoc />
protected override void Print(ExpressionPrinter expressionPrinter)
{
if (!string.IsNullOrEmpty(Schema))
{
expressionPrinter.Append(Schema).Append(".");
}

expressionPrinter.Append(Name);
PrintAnnotations(expressionPrinter);

expressionPrinter.Append(" AS ").Append(Alias);
}

/// <summary>
/// The alias assigned to this table source.
/// </summary>
Expand All @@ -71,8 +54,28 @@ public override string? Alias
public ITableBase Table { get; }

/// <inheritdoc />
public TableExpressionBase Clone()
=> new TableExpression(Table, GetAnnotations()) { Alias = Alias };
protected override TableExpressionBase CreateWithAnnotations(IEnumerable<IAnnotation> annotations)
=> new TableExpression(Table, annotations) { Alias = Alias };

/// <inheritdoc />
ITableBase ITableBasedExpression.Table => Table;

/// <inheritdoc />
protected override void Print(ExpressionPrinter expressionPrinter)
{
if (!string.IsNullOrEmpty(Schema))
{
expressionPrinter.Append(Schema).Append(".");
}

expressionPrinter.Append(Name);
PrintAnnotations(expressionPrinter);

expressionPrinter.Append(" AS ").Append(Alias);
}

/// <inheritdoc />
public TableExpressionBase Clone() => CreateWithAnnotations(GetAnnotations());

/// <inheritdoc />
public override bool Equals(object? obj)
Expand Down
Loading

0 comments on commit 30d4b22

Please sign in to comment.