Skip to content

Logic for lifting DefaultIfEmpty out of SelectMany (to LEFT JOIN/OUTER APPLY) is incorrect #33343

@KvaKoZyaBBrr

Description

@KvaKoZyaBBrr

I have entities:

class MyRecord<T>
{
    public T Item {get;set;}
}
class JoinResult<T1, T2>
{
    public T1 Left { get; set; }
    public T2 Right { get; set; }
}
class  TestItem
{
    public int EntityId {get;set;}
    public string Name {get;set;}
    public int ParentId {get;set;} // link to TestItem.EntityId
}
class  TestQuery
{
    public int QueryId {get;set;}
}

And when Im try get all childs for requested items ordered by desc which has linked query I use next linq:

DbSet<MyRecord<long>>().FromSql(select * from unnest({0}), object[] { NpgsqlParameter<MyRecord<long>[]> })
.SelectMany(pk => dataContext.TestItems
    .Where(item => pk.Item == item.ParentId)
    .SelectMany(
        collectionSelector: entity => dataContext.TestQueries
            .Where(a => a.QueryId == entity.EntityId)
            .DefaultIfEmpty(), 
        resultSelector: (left, right) => new JoinResult<TestItem, TestQuery>{ 
            Left = left, 
            Right = right 
        }
    )
    .OrderByDescending(result => result.Right.ObjectId)
    .Select(result => result.Left))

I expect DefaultIfEmpty change inner SelectMany to leftJoin inside join by outer SelectMany smth

SELECT t0.EntityId, t0.Name, t0.ParentId
FROM (
    select * from unnest(ARRAY[101,102])
) AS e
JOIN LATERAL (
    SELECT c.EntityId, c.Name, c.ParentId
    FROM items AS c
    LEFT JOIN LATERAL (
        SELECT s.QueryId
        FROM queries AS q
        WHERE q.QueryId = c.EntityId
    ) AS t ON TRUE
    WHERE e.unnest = c.ParentId
    ORDER BY t.QueryId DESC
) AS t0 ON TRUE

But I get

SELECT t0.EntityId, t0.Name, t0.ParentId
FROM (
    select * from unnest(ARRAY[101,102])
) AS e
LEFT JOIN LATERAL (
    SELECT c.EntityId, c.Name, c.ParentId
    FROM items AS c
    JOIN LATERAL (
        SELECT s.QueryId
        FROM queries AS q
        WHERE q.QueryId = c.EntityId
    ) AS t ON TRUE
    WHERE e.unnest = c.ParentId
    ORDER BY t.QueryId DESC
) AS t0 ON TRUE

How can I change this behaviour?

Metadata

Metadata

Assignees

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions