Skip to content
Closed
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
34 changes: 34 additions & 0 deletions src/EFCore.Relational/Query/SqlExpressionFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,40 @@ private SqlExpression ApplyTypeMappingOnSqlBinary(
}

case ExpressionType.Add:
inferredTypeMapping = typeMapping;

if (inferredTypeMapping is null)
{
// Infer null size (nvarchar(max)) if either side has no size.
// Note that for constants, we could instead look at the value length; but that requires we know the type mappings which
// can have a size (string/byte[], maybe something else?).
var inferredSize = left.TypeMapping?.Size is int leftSize && right.TypeMapping?.Size is int rightSize
? leftSize + rightSize
: (int?)null;

// Unless both sides are fixed length, the result isn't fixed length.
var inferredFixedLength = left.TypeMapping?.IsFixedLength is true && right.TypeMapping?.IsFixedLength is true;
// Default to Unicode unless both sides are non-unicode.
var inferredUnicode = !(left.TypeMapping?.IsUnicode is false && right.TypeMapping?.IsUnicode is false);

var baseTypeMapping = left.TypeMapping
?? right.TypeMapping
?? ApplyDefaultTypeMapping(left).TypeMapping
?? throw new InvalidOperationException("Couldn't find type mapping");

inferredTypeMapping = baseTypeMapping.Size == inferredSize
&& baseTypeMapping.IsFixedLength == inferredFixedLength
&& baseTypeMapping.IsUnicode == inferredUnicode
? baseTypeMapping
: _typeMappingSource.FindMapping(
baseTypeMapping.ClrType, storeTypeName: null, keyOrIndex: false, inferredUnicode, inferredSize,
rowVersion: false, inferredFixedLength, baseTypeMapping.Precision, baseTypeMapping.Scale);
}

resultType = inferredTypeMapping?.ClrType ?? left.Type;
resultTypeMapping = inferredTypeMapping;
break;

case ExpressionType.Subtract:
case ExpressionType.Multiply:
case ExpressionType.Divide:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5659,4 +5659,26 @@ public virtual Task Subquery_with_navigation_inside_inline_collection(bool async
=> AssertQuery(
async,
ss => ss.Set<Customer>().Where(c => new[] { 100, c.Orders.Count }.Sum() > 101));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Contains_over_concatenated_columns_with_different_sizes(bool async)
{
var data = new[] { "ALFKI" + "Alfreds Futterkiste", "ANATR" + "Ana Trujillo Emparedados y helados" };

return AssertQuery(
async,
ss => ss.Set<Customer>().Where(c => data.Contains(c.CustomerID + c.CompanyName)));
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Contains_over_concatenated_column_and_constant(bool async)
{
var data = new[] { "ALFKI" + "SomeConstant", "ANATR" + "SomeConstant" };

return AssertQuery(
async,
ss => ss.Set<Customer>().Where(c => data.Contains(c.CustomerID + "SomeConstant")));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7277,6 +7277,40 @@ FROM [Orders] AS [o]
""");
}

public override async Task Contains_over_concatenated_columns_with_different_sizes(bool async)
{
await base.Contains_over_concatenated_columns_with_different_sizes (async);

AssertSql(
"""
@__data_0='["ALFKIAlfreds Futterkiste","ANATRAna Trujillo Emparedados y helados"]' (Size = 4000)

SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
FROM [Customers] AS [c]
WHERE [c].[CustomerID] + [c].[CompanyName] IN (
SELECT [d].[value]
FROM OPENJSON(@__data_0) WITH ([value] nvarchar(45) '$') AS [d]
)
""");
}

public override async Task Contains_over_concatenated_column_and_constant(bool async)
{
await base.Contains_over_concatenated_column_and_constant (async);

AssertSql(
"""
@__data_0='["ALFKISomeConstant","ANATRSomeConstant"]' (Size = 4000)

SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
FROM [Customers] AS [c]
WHERE [c].[CustomerID] + N'SomeConstant' IN (
SELECT [d].[value]
FROM OPENJSON(@__data_0) WITH ([value] nvarchar(max) '$') AS [d]
)
""");
}

private void AssertSql(params string[] expected)
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);

Expand Down