Skip to content

Commit

Permalink
Sqlite: Support translation of ToString
Browse files Browse the repository at this point in the history
  • Loading branch information
ralmsdeveloper authored and smitpatel committed Oct 30, 2020
1 parent 4699660 commit 1e0bdda
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public SqliteMethodCallTranslatorProvider([NotNull] RelationalMethodCallTranslat
new SqliteByteArrayMethodTranslator(sqlExpressionFactory),
new SqliteDateTimeAddTranslator(sqlExpressionFactory),
new SqliteMathTranslator(sqlExpressionFactory),
new SqliteObjectToStringTranslator(sqlExpressionFactory),
new SqliteStringMethodTranslator(sqlExpressionFactory)
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal
{
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public class SqliteObjectToStringTranslator : IMethodCallTranslator
{
private static readonly HashSet<Type> _typeMapping = new HashSet<Type>
{
typeof(int),
typeof(long),
typeof(Guid),
typeof(byte),
typeof(byte[]),
typeof(decimal),
typeof(double),
typeof(float),
typeof(char),
typeof(short),
typeof(DateTime),
typeof(DateTimeOffset),
typeof(TimeSpan),
typeof(uint),
typeof(ushort),
typeof(sbyte),
typeof(bool),
};

private readonly ISqlExpressionFactory _sqlExpressionFactory;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public SqliteObjectToStringTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory)
=> _sqlExpressionFactory = sqlExpressionFactory;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList<SqlExpression> arguments)
{
Check.NotNull(method, nameof(method));
Check.NotNull(arguments, nameof(arguments));

return method.Name == nameof(ToString)
&& arguments.Count == 0
&& instance != null
&& _typeMapping.Contains(instance.Type.UnwrapNullableType())
? _sqlExpressionFactory.Convert(instance, typeof(string))
: null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1500,7 +1500,7 @@ public override void Object_to_string_conversion()
base.Object_to_string_conversion();

AssertSql(
@"SELECT ""b"".""TestSignedByte"", ""b"".""TestByte"", ""b"".""TestInt16"", ""b"".""TestUnsignedInt16"", ""b"".""TestInt32"", ""b"".""TestUnsignedInt32"", ""b"".""TestInt64"", ""b"".""TestUnsignedInt64"", ""b"".""TestSingle"", ""b"".""TestDouble"", ""b"".""TestDecimal"", ""b"".""TestCharacter"", ""b"".""TestDateTime"", ""b"".""TestDateTimeOffset"", ""b"".""TestTimeSpan""
@"SELECT CAST(""b"".""TestSignedByte"" AS TEXT), CAST(""b"".""TestByte"" AS TEXT), CAST(""b"".""TestInt16"" AS TEXT), CAST(""b"".""TestUnsignedInt16"" AS TEXT), CAST(""b"".""TestInt32"" AS TEXT), CAST(""b"".""TestUnsignedInt32"" AS TEXT), CAST(""b"".""TestInt64"" AS TEXT), ""b"".""TestUnsignedInt64"", CAST(""b"".""TestSingle"" AS TEXT), CAST(""b"".""TestDouble"" AS TEXT), CAST(""b"".""TestDecimal"" AS TEXT), CAST(""b"".""TestCharacter"" AS TEXT), CAST(""b"".""TestDateTime"" AS TEXT), CAST(""b"".""TestDateTimeOffset"" AS TEXT), CAST(""b"".""TestTimeSpan"" AS TEXT)
FROM ""BuiltInDataTypes"" AS ""b""
WHERE ""b"".""Id"" = 13");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ public ConvertToProviderTypesSqliteTest(ConvertToProviderTypesSqliteFixture fixt
//fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper);
}

public override void Object_to_string_conversion()
{
// Return values are not string
}

public class ConvertToProviderTypesSqliteFixture : ConvertToProviderTypesFixtureBase
{
public override bool StrictEquality
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ public override void Where_bool_gets_converted_to_equality_when_value_conversion
WHERE ""b"".""IndexerVisible"" <> 'Aye'");
}

public override void Object_to_string_conversion()
{
// Return values are not string
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,15 @@ public class NorthwindMiscellaneousQuerySqliteTest : NorthwindMiscellaneousQuery
//Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper);
}

public override Task Query_expression_with_to_string_and_contains(bool async)
=> AssertTranslationFailed(() => base.Query_expression_with_to_string_and_contains(async));
public override async Task Query_expression_with_to_string_and_contains(bool async)
{
await base.Query_expression_with_to_string_and_contains(async);

AssertSql(
@"SELECT ""o"".""CustomerID""
FROM ""Orders"" AS ""o""
WHERE ""o"".""OrderDate"" IS NOT NULL AND (('10' = '') OR (instr(CAST(""o"".""EmployeeID"" AS TEXT), '10') > 0))");
}

public override async Task Take_Skip(bool async)
{
Expand Down

0 comments on commit 1e0bdda

Please sign in to comment.