Skip to content

Commit

Permalink
Query: Add interface to get ITableBase for root level table sources
Browse files Browse the repository at this point in the history
  • Loading branch information
smitpatel committed May 13, 2022
1 parent deb3a87 commit b7d76c4
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 29 deletions.
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

0 comments on commit b7d76c4

Please sign in to comment.