Skip to content

Commit

Permalink
Small tweak to support primitive collections within owned JSON entities
Browse files Browse the repository at this point in the history
  • Loading branch information
roji committed Apr 23, 2023
1 parent 191dc68 commit 4542fc8
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -255,19 +255,26 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp

var translated = base.VisitMethodCall(methodCallExpression);

// Attempt to translate access into a primitive collection property
if (translated == QueryCompilationContext.NotTranslatedExpression
&& _sqlTranslator.TryTranslatePropertyAccess(methodCallExpression, out var propertyAccessExpression)
&& propertyAccessExpression is ColumnExpression
&& propertyAccessExpression is
{
TypeMapping.ElementTypeMapping: RelationalTypeMapping elementTypeMapping
} columnExpression
&& TranslateCollection(
columnExpression,
elementTypeMapping,
columnExpression.Name[..1].ToLowerInvariant())
is { } primitiveCollectionTranslation)
{
return primitiveCollectionTranslation;
} collectionPropertyAccessExpression)
{
var tableAlias = collectionPropertyAccessExpression switch
{
ColumnExpression c => c.Name[..1].ToLowerInvariant(),
JsonScalarExpression { Path: [.., { PropertyName: string propertyName }] } => propertyName[..1].ToLowerInvariant(),
_ => "j"
};

if (TranslateCollection(collectionPropertyAccessExpression, elementTypeMapping, tableAlias) is
{ } primitiveCollectionTranslation)
{
return primitiveCollectionTranslation;
}
}

return translated;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,37 @@ public abstract class NonSharedPrimitiveCollectionsQueryRelationalTestBase : Non
public override Task Array_of_byte()
=> AssertTranslationFailed(() => TestArray((byte)1, (byte)2));

[ConditionalFact]
public virtual async Task Column_collection_inside_json_owned_entity()
{
var contextFactory = await InitializeAsync<TestContext>(
onModelCreating: mb => mb.Entity<TestOwner>().OwnsOne(t => t.Owned, b => b.ToJson()),
seed: context =>
{
context.AddRange(
new TestOwner { Owned = new TestOwned { Strings = new[] { "foo", "bar" } } },
new TestOwner { Owned = new TestOwned { Strings = new[] { "baz" } } });
context.SaveChanges();
});

await using var context = contextFactory.CreateContext();

var result = await context.Set<TestOwner>().SingleAsync(o => o.Owned.Strings.Count() == 2);
Assert.Equivalent(new[] { "foo", "bar" }, result.Owned.Strings);
}

protected class TestOwner
{
public int Id { get; set; }
public TestOwned Owned { get; set; }
}

[Owned]
protected class TestOwned
{
public string[] Strings { get; set; }
}

protected TestSqlLoggerFactory TestSqlLoggerFactory
=> (TestSqlLoggerFactory)ListLoggerFactory;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,20 @@ SELECT COUNT(*)
""");
}

public override async Task Column_collection_inside_json_owned_entity()
{
await base.Column_collection_inside_json_owned_entity();

AssertSql(
"""
SELECT TOP(2) [t].[Id], [t].[Owned]
FROM [TestOwner] AS [t]
WHERE (
SELECT COUNT(*)
FROM OpenJson(JSON_VALUE([t].[Owned], '$.Strings')) AS [s]) = 2
""");
}

[ConditionalFact]
public virtual async Task Same_parameter_with_different_type_mappings()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,19 @@ public override async Task Array_of_geometry_is_not_supported()

#endregion Support for specific element types

public override async Task Column_collection_inside_json_owned_entity()
{
await base.Column_collection_inside_json_owned_entity();

AssertSql(
"""
SELECT "t"."Id", "t"."Owned"
FROM "TestOwner" AS "t"
WHERE json_array_length(json_extract("t"."Owned", '$.Strings')) = 2
LIMIT 2
""");
}

protected override ITestStoreFactory TestStoreFactory
=> SqliteTestStoreFactory.Instance;
}

0 comments on commit 4542fc8

Please sign in to comment.