AddJoinsReWriter disassociates Select expressions and GroupBy key expressions
Description
Environment
None
is duplicated by
is related to
Activity
Show:
Alex ZaytsevMay 1, 2017 at 3:42 AM
Closing issues resolved in 4.1.0
AntonAugust 18, 2015 at 11:30 AM
Duncan MunroJuly 7, 2015 at 3:57 PM
Duncan MunroJuly 7, 2015 at 3:52 PMEdited
It turns out that the root of this issue is really still the same problem from https://nhibernate.jira.com/browse/NH-3797#icft=NH-3797 which is that conditional statements in the SELECT clause were not generating CASE statements in the SQL. Instead, the sub-expressions from the conditional were being extracted as SELECT elements and joins were being made in weird ways, especially on the test expression of the conditional.
My solution is to allow the conditional statement to be projected into SQL (if possible), including parameters.
This actually fixes the root problem and negates the changes made in pull request #432
Fixed
Details
Details
Assignee
Alex Zaytsev
Alex ZaytsevReporter
Duncan Munro
Duncan MunroComponents
Fix versions
Affects versions
Priority
Who's Looking?
Open Who's Looking?
Created June 26, 2015 at 9:40 PM
Updated May 1, 2017 at 3:42 AM
Resolved July 7, 2015 at 11:43 PM
Who's Looking?
The fix for NH-3797: Computed GroupBys don't work if they have constantsClosed didn't take into account GROUP BY keys that generated joins.
When a join is needed, both the SELECT and GROUP BY expressions are re-written with {{QuerySourceReferenceExpression}}s referencing joins.
The problem is that the extracted GROUP BY keys no longer match the SELECT expression tree in any way. In fact, the existing GROUP BY keys no longer match at all, so we don't get the expected handling of the SELECT clause when it produces the HQL tree.
Example Query
db.OrderLines.GroupBy(o => o.Order.Customer.CustomerId == null ? 0 : 1).Select(g => new { Key = g.Key, Count = g.Count() })
Generates
select order1_.CustomerId as col_0_0_, cast(count(*) as int4) as col_1_0_ from OrderLines orderline0_ left outer join Orders order1_ on orderline0_.OrderId=order1_.OrderId group by cast(case when order1_.CustomerId is null then :p0 else :p1 end as int4); :p0 = 0 [Type: Int32 (0)], :p1 = 1 [Type: Int32 (0)
Should generate
select cast(case when order0_.CustomerId is null then :p0 else :p1 end as int4) as col_0_0_, cast(count(*) as int4) as col_1_0_ from Orders order0_ group by cast(case when order0_.CustomerId is null then :p0 else :p1 end as int4); :p0 = 0 [Type: Int32 (0)], :p1 = 1 [Type: Int32 (0)]