Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query: Add interface to get ITableBase for root level table sources #28020

Merged
merged 1 commit into from
May 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ protected override Expression VisitExtension(Expression extensionExpression)
_sqlExpressionFactory.Select(
fromSqlQueryRootExpression.EntityType,
new FromSqlExpression(
fromSqlQueryRootExpression.EntityType.GetDefaultMappings().Single().Table.Name[..1]
.ToLowerInvariant(),
fromSqlQueryRootExpression.EntityType.GetDefaultMappings().Single().Table,
fromSqlQueryRootExpression.Sql,
fromSqlQueryRootExpression.Argument)));

Expand Down Expand Up @@ -127,9 +126,14 @@ protected override Expression VisitExtension(Expression extensionExpression)
when queryRootExpression.GetType() == typeof(QueryRootExpression)
&& queryRootExpression.EntityType.GetSqlQueryMappings().FirstOrDefault(m => m.IsDefaultSqlQueryMapping)?.SqlQuery is
ISqlQuery sqlQuery:
return Visit(
new FromSqlQueryRootExpression(
queryRootExpression.EntityType, sqlQuery.Sql, Expression.Constant(Array.Empty<object>(), typeof(object[]))));
return CreateShapedQueryExpression(
queryRootExpression.EntityType,
_sqlExpressionFactory.Select(
queryRootExpression.EntityType,
new FromSqlExpression(
queryRootExpression.EntityType.GetDefaultMappings().Single().Table,
sqlQuery.Sql,
Expression.Constant(Array.Empty<object>(), typeof(object[])))));

case GroupByShaperExpression groupByShaperExpression:
var groupShapedQueryExpression = groupByShaperExpression.GroupingEnumerable;
Expand Down
8 changes: 1 addition & 7 deletions src/EFCore.Relational/Query/SqlExpressionFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -637,13 +637,7 @@ private void AddConditions(SelectExpression selectExpression, IEntityType entity
return;
}

var table = selectExpression.Tables[0] switch
{
TableExpression te => te.Table,
TableValuedFunctionExpression tvfe => tvfe.StoreFunction,
_ => entityType.GetDefaultMappings().Single().Table,
};

var table = ((ITableBasedExpression)selectExpression.Tables[0]).Table;
if (table.IsOptional(entityType))
{
var entityProjectionExpression = GetMappedEntityProjectionExpression(selectExpression);
Expand Down
32 changes: 24 additions & 8 deletions src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,40 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions;
/// not used in application code.
/// </para>
/// </summary>
public class FromSqlExpression : TableExpressionBase, IClonableTableExpressionBase
public class FromSqlExpression : TableExpressionBase, IClonableTableExpressionBase, ITableBasedExpression
{
private readonly ITableBase _table;

/// <summary>
/// Creates a new instance of the <see cref="FromSqlExpression" /> class.
/// </summary>
/// <param name="alias">A string alias for the table source.</param>
/// <param name="defaultTableBase">A default table base associated with this table source.</param>
/// <param name="sql">A user-provided custom SQL for the table source.</param>
/// <param name="arguments">A user-provided parameters to pass to the custom SQL.</param>
public FromSqlExpression(string alias, string sql, Expression arguments)
: this(alias, sql, arguments, annotations: null)
public FromSqlExpression(ITableBase defaultTableBase, string sql, Expression arguments)
: this(defaultTableBase.Name[..1].ToLowerInvariant(), defaultTableBase, sql, arguments, annotations: null)
{
Sql = sql;
Arguments = arguments;
}

// See issue#21660/21627
///// <summary>
///// Creates a new instance of the <see cref="FromSqlExpression" /> class.
///// </summary>
///// <param name="sqlQuery">A sql query associated with this table source.</param>
//public FromSqlExpression(ISqlQuery sqlQuery)
// : this(sqlQuery, sqlQuery.Sql, Constant(Array.Empty<object>(), typeof(object[])))
//{
//}

private FromSqlExpression(
string alias,
ITableBase tableBase,
string sql,
Expression arguments,
IEnumerable<IAnnotation>? annotations)
: base(alias, annotations)
{
_table = tableBase;
Sql = sql;
Arguments = arguments;
}
Expand Down Expand Up @@ -68,16 +80,19 @@ public override string? Alias
/// <returns>This expression if no children changed, or an expression with the updated children.</returns>
public virtual FromSqlExpression Update(Expression arguments)
=> arguments != Arguments
? new FromSqlExpression(Alias, Sql, arguments)
? new FromSqlExpression(Alias, _table, Sql, arguments, GetAnnotations())
: this;

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

/// <inheritdoc />
protected override Expression VisitChildren(ExpressionVisitor visitor)
=> this;

/// <inheritdoc />
public virtual TableExpressionBase Clone()
=> new FromSqlExpression(Alias, Sql, Arguments, GetAnnotations());
=> new FromSqlExpression(Alias, _table, Sql, Arguments, GetAnnotations());

/// <inheritdoc />
protected override void Print(ExpressionPrinter expressionPrinter)
Expand All @@ -95,6 +110,7 @@ public override bool Equals(object? obj)

private bool Equals(FromSqlExpression fromSqlExpression)
=> base.Equals(fromSqlExpression)
&& _table == fromSqlExpression._table
&& Sql == fromSqlExpression.Sql
&& ExpressionEqualityComparer.Instance.Equals(Arguments, fromSqlExpression.Arguments);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions;

/// <summary>
/// <para>
/// An interface that gives access to <see cref="ITableBase"/> associated with given table source.
/// </para>
/// <para>
/// This type is typically used by database providers (and other extensions). It is generally
/// not used in application code.
/// </para>
/// </summary>
public interface ITableBasedExpression
{
/// <summary>
/// The <see cref="ITableBase"/> associated with given table source.
/// </summary>
ITableBase Table { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -374,13 +374,7 @@ internal SelectExpression(IEntityType entityType, TableExpressionBase tableExpre
throw new InvalidOperationException(RelationalStrings.SelectExpressionNonTphWithCustomTable(entityType.DisplayName()));
}

var table = tableExpressionBase switch
{
TableExpression tableExpression => tableExpression.Table,
TableValuedFunctionExpression tableValuedFunctionExpression => tableValuedFunctionExpression.StoreFunction,
_ => entityType.GetDefaultMappings().Single().Table
};

var table = ((ITableBasedExpression)tableExpressionBase).Table;
var tableReferenceExpression = new TableReferenceExpression(this, tableExpressionBase.Alias!);
AddTable(tableExpressionBase, tableReferenceExpression);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions;
/// application or database provider code. If this is a problem for your application or provider, then please file
/// an issue at <see href="https://github.com/dotnet/efcore">github.com/dotnet/efcore</see>.
/// </remarks>
public sealed class TableExpression : TableExpressionBase, IClonableTableExpressionBase
public sealed class TableExpression : TableExpressionBase, IClonableTableExpressionBase, ITableBasedExpression
{
internal TableExpression(ITableBase table)
: this(table, annotations: null)
Expand All @@ -28,6 +28,9 @@ private TableExpression(ITableBase table, IEnumerable<IAnnotation>? annotations)
Table = table;
}

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

/// <inheritdoc />
protected override void Print(ExpressionPrinter expressionPrinter)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions;
/// not used in application code.
/// </para>
/// </summary>
public class TableValuedFunctionExpression : TableExpressionBase
public class TableValuedFunctionExpression : TableExpressionBase, ITableBasedExpression
{
/// <summary>
/// Creates a new instance of the <see cref="TableValuedFunctionExpression" /> class.
Expand Down Expand Up @@ -61,6 +61,9 @@ public override string? Alias
/// </summary>
public virtual IReadOnlyList<SqlExpression> Arguments { get; }

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

/// <inheritdoc />
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
Expand Down