Skip to content

Commit

Permalink
Fix #9558 - Relational: UDF calls are generated unquoted
Browse files Browse the repository at this point in the history
Tweak SQL gen to delimit function calls that have a schema.
  • Loading branch information
anpete committed Feb 5, 2018
1 parent ca3aa0f commit 168145c
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 39 deletions.
7 changes: 4 additions & 3 deletions src/EFCore.Relational/DbFunctionAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public DbFunctionAttribute([NotNull] string functionName, [CanBeNull] string sch
/// </summary>
public virtual string FunctionName
{
get { return _functionName; }
get => _functionName;
[param: NotNull]
set
{
Expand All @@ -57,8 +57,9 @@ public virtual string FunctionName
/// </summary>
public virtual string Schema
{
get { return _schema; }
[param: CanBeNull] set { _schema = value; }
get => _schema;
[param: CanBeNull]
set => _schema = value;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Microsoft.EntityFrameworkCore.Query.Expressions
/// <summary>
/// Represents a SQL function call expression.
/// </summary>
[DebuggerDisplay("{ToString()}")]
[DebuggerDisplay("{" + nameof(ToString) + "()}")]
public class SqlFunctionExpression : Expression
{
private readonly ReadOnlyCollection<Expression> _arguments;
Expand Down
14 changes: 13 additions & 1 deletion src/EFCore.Relational/Query/Sql/DefaultQuerySqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1409,24 +1409,36 @@ public virtual Expression VisitLike(LikeExpression likeExpression)
public virtual Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression)
{
var parentTypeMapping = _typeMapping;

_typeMapping = null;

var wroteSchema = false;

if (sqlFunctionExpression.Instance != null)
{
Visit(sqlFunctionExpression.Instance);

_relationalCommandBuilder.Append(".");
}
else if (!string.IsNullOrWhiteSpace(sqlFunctionExpression.Schema))
{
_relationalCommandBuilder
.Append(SqlGenerator.DelimitIdentifier(sqlFunctionExpression.Schema))
.Append(".");

wroteSchema = true;
}

_relationalCommandBuilder.Append(sqlFunctionExpression.FunctionName);
_relationalCommandBuilder
.Append(
wroteSchema
? SqlGenerator.DelimitIdentifier(sqlFunctionExpression.FunctionName)
: sqlFunctionExpression.FunctionName);

_relationalCommandBuilder.Append("(");

_typeMapping = null;

GenerateList(sqlFunctionExpression.Arguments);

_relationalCommandBuilder.Append(")");
Expand Down
4 changes: 2 additions & 2 deletions test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2245,7 +2245,7 @@ public void Default_schema_applied_when_no_function_schema()
Assert.Equal(2, result);

AssertSql(
@"SELECT TOP(2) [foo].AddOne([w].[Val])
@"SELECT TOP(2) [foo].[AddOne]([w].[Val])
FROM [foo].[Widgets] AS [w]
WHERE [w].[Val] = 1");
}
Expand All @@ -2264,7 +2264,7 @@ public void Default_schema_function_schema_overrides()
Assert.Equal(3, result);

AssertSql(
@"SELECT TOP(2) [dbo].AddTwo([w].[Val])
@"SELECT TOP(2) [dbo].[AddTwo]([w].[Val])
FROM [foo].[Widgets] AS [w]
WHERE [w].[Val] = 1");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ public void Scalar_Function_Constant_Parameter_Static()
AssertSql(
@"@__customerId_0='1'
SELECT [dbo].CustomerOrderCount(@__customerId_0)
SELECT [dbo].[CustomerOrderCount](@__customerId_0)
FROM [Customers] AS [c]");
}
}
Expand All @@ -335,7 +335,7 @@ public void Scalar_Function_Anonymous_Type_Select_Correlated_Static()
Assert.Equal(3, cust.OrderCount);

AssertSql(
@"SELECT TOP(2) [c].[LastName], [dbo].CustomerOrderCount([c].[Id]) AS [OrderCount]
@"SELECT TOP(2) [c].[LastName], [dbo].[CustomerOrderCount]([c].[Id]) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = 1");
}
Expand All @@ -358,7 +358,7 @@ public void Scalar_Function_Anonymous_Type_Select_Not_Correlated_Static()
Assert.Equal(3, cust.OrderCount);

AssertSql(
@"SELECT TOP(2) [c].[LastName], [dbo].CustomerOrderCount(1) AS [OrderCount]
@"SELECT TOP(2) [c].[LastName], [dbo].[CustomerOrderCount](1) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = 1");
}
Expand Down Expand Up @@ -386,7 +386,7 @@ public void Scalar_Function_Anonymous_Type_Select_Parameter_Static()
@"@__customerId_1='1'
@__customerId_0='1'
SELECT TOP(2) [c].[LastName], [dbo].CustomerOrderCount(@__customerId_1) AS [OrderCount]
SELECT TOP(2) [c].[LastName], [dbo].[CustomerOrderCount](@__customerId_1) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = @__customerId_0");
}
Expand Down Expand Up @@ -416,7 +416,7 @@ public void Scalar_Function_Anonymous_Type_Select_Nested_Static()
@__customerId_2='3'
@__customerId_0='3'
SELECT TOP(2) [c].[LastName], [dbo].StarValue(@__starCount_1, [dbo].CustomerOrderCount(@__customerId_2)) AS [OrderCount]
SELECT TOP(2) [c].[LastName], [dbo].[StarValue](@__starCount_1, [dbo].[CustomerOrderCount](@__customerId_2)) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = @__customerId_0");
}
Expand All @@ -436,7 +436,7 @@ where UDFSqlContext.IsTopCustomerStatic(c.Id)
AssertSql(
@"SELECT LOWER(CONVERT(VARCHAR(11), [c].[Id]))
FROM [Customers] AS [c]
WHERE [dbo].IsTopCustomer([c].[Id]) = 1");
WHERE [dbo].[IsTopCustomer]([c].[Id]) = 1");
}
}

Expand All @@ -458,7 +458,7 @@ where UDFSqlContext.GetCustomerWithMostOrdersAfterDateStatic(startDate) == c.Id
SELECT TOP(2) [c].[Id]
FROM [Customers] AS [c]
WHERE [dbo].GetCustomerWithMostOrdersAfterDate(@__startDate_0) = [c].[Id]");
WHERE [dbo].[GetCustomerWithMostOrdersAfterDate](@__startDate_0) = [c].[Id]");
}
}

Expand All @@ -481,7 +481,7 @@ public void Scalar_Function_Where_Parameter_Static()
SELECT TOP(2) [c].[Id]
FROM [Customers] AS [c]
WHERE [c].[Id] = [dbo].GetCustomerWithMostOrdersAfterDate([dbo].GetReportingPeriodStartDate(@__period_0))");
WHERE [c].[Id] = [dbo].[GetCustomerWithMostOrdersAfterDate]([dbo].[GetReportingPeriodStartDate](@__period_0))");
}
}

Expand All @@ -501,7 +501,7 @@ public void Scalar_Function_Where_Nested_Static()
AssertSql(
@"SELECT TOP(2) [c].[Id]
FROM [Customers] AS [c]
WHERE [c].[Id] = [dbo].GetCustomerWithMostOrdersAfterDate([dbo].GetReportingPeriodStartDate(0))");
WHERE [c].[Id] = [dbo].[GetCustomerWithMostOrdersAfterDate]([dbo].[GetReportingPeriodStartDate](0))");
}
}

Expand All @@ -523,7 +523,7 @@ public void Scalar_Function_Let_Correlated_Static()
Assert.Equal(2, cust.OrderCount);

AssertSql(
@"SELECT TOP(2) [c].[LastName], [dbo].CustomerOrderCount([c].[Id]) AS [OrderCount]
@"SELECT TOP(2) [c].[LastName], [dbo].[CustomerOrderCount]([c].[Id]) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = 2");
}
Expand All @@ -547,7 +547,7 @@ public void Scalar_Function_Let_Not_Correlated_Static()
Assert.Equal(2, cust.OrderCount);

AssertSql(
@"SELECT TOP(2) [c].[LastName], [dbo].CustomerOrderCount(2) AS [OrderCount]
@"SELECT TOP(2) [c].[LastName], [dbo].[CustomerOrderCount](2) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = 2");
}
Expand Down Expand Up @@ -576,7 +576,7 @@ public void Scalar_Function_Let_Not_Parameter_Static()
@"@__customerId_0='2'
@__customerId_1='2'
SELECT TOP(2) [c].[LastName], [dbo].CustomerOrderCount(@__customerId_0) AS [OrderCount]
SELECT TOP(2) [c].[LastName], [dbo].[CustomerOrderCount](@__customerId_0) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = @__customerId_1");
}
Expand Down Expand Up @@ -607,7 +607,7 @@ public void Scalar_Function_Let_Nested_Static()
@__customerId_1='1'
@__customerId_2='1'
SELECT TOP(2) [c].[LastName], [dbo].StarValue(@__starCount_0, [dbo].CustomerOrderCount(@__customerId_1)) AS [OrderCount]
SELECT TOP(2) [c].[LastName], [dbo].[StarValue](@__starCount_0, [dbo].[CustomerOrderCount](@__customerId_1)) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = @__customerId_2");
}
Expand Down Expand Up @@ -823,7 +823,7 @@ public void Scalar_Nested_Function_BCL_UDF_Static()
AssertSql(
@"SELECT TOP(2) [c].[Id]
FROM [Customers] AS [c]
WHERE 3 = ABS([dbo].CustomerOrderCount([c].[Id]))");
WHERE 3 = ABS([dbo].[CustomerOrderCount]([c].[Id]))");
}
}

Expand Down Expand Up @@ -857,7 +857,7 @@ public void Scalar_Nested_Function_UDF_BCL_Static()
AssertSql(
@"SELECT TOP(2) [c].[Id]
FROM [Customers] AS [c]
WHERE 3 = [dbo].CustomerOrderCount(ABS([c].[Id]))");
WHERE 3 = [dbo].[CustomerOrderCount](ABS([c].[Id]))");
}
}

Expand All @@ -873,7 +873,7 @@ public void Nullable_navigation_property_access_preserves_schema_for_sql_functio

Assert.Equal("Customer", result);
AssertSql(
@"SELECT TOP(1) [dbo].IdentityString([o.Customer].[FirstName])
@"SELECT TOP(1) [dbo].[IdentityString]([o.Customer].[FirstName])
FROM [Orders] AS [o]
LEFT JOIN [Customers] AS [o.Customer] ON [o].[CustomerId] = [o.Customer].[Id]
ORDER BY [o].[Id]");
Expand All @@ -900,7 +900,7 @@ public void Scalar_Function_Non_Static()
Assert.Equal(custName.LastName, "$$One");

AssertSql(
@"SELECT TOP(2) [dbo].StarValue(4, [c].[Id]) AS [Id], [dbo].DollarValue(2, [c].[LastName]) AS [LastName]
@"SELECT TOP(2) [dbo].[StarValue](4, [c].[Id]) AS [Id], [dbo].[DollarValue](2, [c].[LastName]) AS [LastName]
FROM [Customers] AS [c]
WHERE [c].[Id] = 1");
}
Expand Down Expand Up @@ -977,7 +977,7 @@ public void Scalar_Function_Constant_Parameter_Instance()
AssertSql(
@"@__customerId_1='1'
SELECT [dbo].CustomerOrderCount(@__customerId_1)
SELECT [dbo].[CustomerOrderCount](@__customerId_1)
FROM [Customers] AS [c]");
}
}
Expand All @@ -999,7 +999,7 @@ public void Scalar_Function_Anonymous_Type_Select_Correlated_Instance()
Assert.Equal(3, cust.OrderCount);

AssertSql(
@"SELECT TOP(2) [c].[LastName], [dbo].CustomerOrderCount([c].[Id]) AS [OrderCount]
@"SELECT TOP(2) [c].[LastName], [dbo].[CustomerOrderCount]([c].[Id]) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = 1");
}
Expand All @@ -1022,7 +1022,7 @@ public void Scalar_Function_Anonymous_Type_Select_Not_Correlated_Instance()
Assert.Equal(3, cust.OrderCount);

AssertSql(
@"SELECT TOP(2) [c].[LastName], [dbo].CustomerOrderCount(1) AS [OrderCount]
@"SELECT TOP(2) [c].[LastName], [dbo].[CustomerOrderCount](1) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = 1");
}
Expand Down Expand Up @@ -1050,7 +1050,7 @@ public void Scalar_Function_Anonymous_Type_Select_Parameter_Instance()
@"@__customerId_2='1'
@__customerId_0='1'
SELECT TOP(2) [c].[LastName], [dbo].CustomerOrderCount(@__customerId_2) AS [OrderCount]
SELECT TOP(2) [c].[LastName], [dbo].[CustomerOrderCount](@__customerId_2) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = @__customerId_0");
}
Expand Down Expand Up @@ -1080,7 +1080,7 @@ public void Scalar_Function_Anonymous_Type_Select_Nested_Instance()
@__customerId_4='3'
@__customerId_0='3'
SELECT TOP(2) [c].[LastName], [dbo].StarValue(@__starCount_2, [dbo].CustomerOrderCount(@__customerId_4)) AS [OrderCount]
SELECT TOP(2) [c].[LastName], [dbo].[StarValue](@__starCount_2, [dbo].[CustomerOrderCount](@__customerId_4)) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = @__customerId_0");
}
Expand All @@ -1100,7 +1100,7 @@ where context.IsTopCustomerInstance(c.Id)
AssertSql(
@"SELECT LOWER(CONVERT(VARCHAR(11), [c].[Id]))
FROM [Customers] AS [c]
WHERE [dbo].IsTopCustomer([c].[Id]) = 1");
WHERE [dbo].[IsTopCustomer]([c].[Id]) = 1");
}
}

Expand All @@ -1122,7 +1122,7 @@ where context.GetCustomerWithMostOrdersAfterDateInstance(startDate) == c.Id
SELECT TOP(2) [c].[Id]
FROM [Customers] AS [c]
WHERE [dbo].GetCustomerWithMostOrdersAfterDate(@__startDate_1) = [c].[Id]");
WHERE [dbo].[GetCustomerWithMostOrdersAfterDate](@__startDate_1) = [c].[Id]");
}
}

Expand All @@ -1145,7 +1145,7 @@ public void Scalar_Function_Where_Parameter_Instance()
SELECT TOP(2) [c].[Id]
FROM [Customers] AS [c]
WHERE [c].[Id] = [dbo].GetCustomerWithMostOrdersAfterDate([dbo].GetReportingPeriodStartDate(@__period_2))");
WHERE [c].[Id] = [dbo].[GetCustomerWithMostOrdersAfterDate]([dbo].[GetReportingPeriodStartDate](@__period_2))");
}
}

Expand All @@ -1165,7 +1165,7 @@ public void Scalar_Function_Where_Nested_Instance()
AssertSql(
@"SELECT TOP(2) [c].[Id]
FROM [Customers] AS [c]
WHERE [c].[Id] = [dbo].GetCustomerWithMostOrdersAfterDate([dbo].GetReportingPeriodStartDate(0))");
WHERE [c].[Id] = [dbo].[GetCustomerWithMostOrdersAfterDate]([dbo].[GetReportingPeriodStartDate](0))");
}
}

Expand All @@ -1187,7 +1187,7 @@ public void Scalar_Function_Let_Correlated_Instance()
Assert.Equal(2, cust.OrderCount);

AssertSql(
@"SELECT TOP(2) [c].[LastName], [dbo].CustomerOrderCount([c].[Id]) AS [OrderCount]
@"SELECT TOP(2) [c].[LastName], [dbo].[CustomerOrderCount]([c].[Id]) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = 2");
}
Expand All @@ -1211,7 +1211,7 @@ public void Scalar_Function_Let_Not_Correlated_Instance()
Assert.Equal(2, cust.OrderCount);

AssertSql(
@"SELECT TOP(2) [c].[LastName], [dbo].CustomerOrderCount(2) AS [OrderCount]
@"SELECT TOP(2) [c].[LastName], [dbo].[CustomerOrderCount](2) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = 2");
}
Expand Down Expand Up @@ -1240,7 +1240,7 @@ public void Scalar_Function_Let_Not_Parameter_Instance()
@"@__8__locals1_customerId_1='2'
@__8__locals1_customerId_2='2'
SELECT TOP(2) [c].[LastName], [dbo].CustomerOrderCount(@__8__locals1_customerId_1) AS [OrderCount]
SELECT TOP(2) [c].[LastName], [dbo].[CustomerOrderCount](@__8__locals1_customerId_1) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = @__8__locals1_customerId_2");
}
Expand Down Expand Up @@ -1271,7 +1271,7 @@ public void Scalar_Function_Let_Nested_Instance()
@__customerId_3='1'
@__customerId_4='1'
SELECT TOP(2) [c].[LastName], [dbo].StarValue(@__starCount_1, [dbo].CustomerOrderCount(@__customerId_3)) AS [OrderCount]
SELECT TOP(2) [c].[LastName], [dbo].[StarValue](@__starCount_1, [dbo].[CustomerOrderCount](@__customerId_3)) AS [OrderCount]
FROM [Customers] AS [c]
WHERE [c].[Id] = @__customerId_4");
}
Expand Down Expand Up @@ -1487,7 +1487,7 @@ public void Scalar_Nested_Function_BCL_UDF_Instance()
AssertSql(
@"SELECT TOP(2) [c].[Id]
FROM [Customers] AS [c]
WHERE 3 = ABS([dbo].CustomerOrderCount([c].[Id]))");
WHERE 3 = ABS([dbo].[CustomerOrderCount]([c].[Id]))");
}
}

Expand Down Expand Up @@ -1521,7 +1521,7 @@ public void Scalar_Nested_Function_UDF_BCL_Instance()
AssertSql(
@"SELECT TOP(2) [c].[Id]
FROM [Customers] AS [c]
WHERE 3 = [dbo].CustomerOrderCount(ABS([c].[Id]))");
WHERE 3 = [dbo].[CustomerOrderCount](ABS([c].[Id]))");
}
}

Expand Down

0 comments on commit 168145c

Please sign in to comment.