Sqlite: transform CROSS APPLY to projection when possible
- 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
Assessment
This issue has not been assessed yet.