dotnet / dotnet/efcore

Sqlite: transform CROSS APPLY to projection when possible

Open
#34,375 0 comments 1 reaction 0 assignees View on GitHub
area-query area-sqlite consider-for-next-release customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

Consider the following query, where Contacts is mapped to a JSON column:

```c#
_ = context.Clients
.Select(c => new ClientDto
{
Id = c.Id,
Name = c.Name,
Contacts = c.Contacts.Select(contact => new ContactDto
{
FirstName = contact.FirstName,
LastName = contact.LastName,
Address = contact.Address,
Email = contact.Email,
PhoneNumber = contact.PhoneNumber
}).ToList()
});
```

EF translates the inner Select to a CROSS APPLY, with OPENJSON (on SQL Server) to extract the JSON data as relational for materialization:

```sql
SELECT [c].[Id], [c].[Name], JSON_VALUE([c0].[value], '$.FirstName'), JSON_VALUE([c0].[value], '$.LastName'), JSON_VALUE([c0].[value], '$.Address'), JSON_VALUE([c0].[value], '$.Email'), JSON_VALUE([c0].[value], '$.PhoneNumber'), [c0].[key]
FROM [Clients] AS [c]
OUTER APPLY OPENJSON([c].[Contacts], '$') AS [c0]
ORDER BY [c].[Id], CAST([c0].[key] AS int)
```

This fails on SQLite, because CROSS/OUTER APPLY isn't supported there.

If the CROSS APPLY is only referenced in the projection (and not e.g. in a filter), then it should be able to transform the query to replace the CROSS APPLY with a projection subquery instead. This seems particularly useful around SQLite JSON processing, as above.

Note the similarity with #34256, where we do the opposite, lifting a subquery projection to CROSS APPLY on SQL Server (where an aggregate function is involved).

Initially raised in #34367

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.