Hello -
I'd like to start development on that bug (which I suggested myself).
To recap, here is a (trivial consequence of the) problem in short
(this is from the source code in the attachment to NH-2583, which
would become a new unit test for NH):
The following 4 queries should all return the same result:
var result = session.Query<MyBO>();
var result = session.Query<MyBO>()
.Where(bo => true);
var result = session.Query<MyBO>()
.Where(bo =>
bo.BO1 != null && bo.BO1.I2 == 101
|| true);
var result = session.Query<MyBO>()
.Where(bo =>
bo.BO1 != null && bo.BO1.I2 == 101
|| bo.Id == bo.Id + 0);
Actually, the latter two yield too small results. The reason is that
referenced classes are always joined via an inner join (or rather, a
"table" join). When there is a boolean or operator involved, such
joins must be replaced with left (outer) joins and some more logic.
For more details and a non-trivial example, see the NH-2583 JIRA
report.
So, now, I'd like to repair this - however, I'm not at all fluent in
the architecture+design of the Linq-->HqlTree generation machinery.
I'd appreciate if someone who knows that code could remotely pair with
me on this - or at least comment on my suggestions & attempts.
Here is my first suggestion where and how to repair this: In
AddLeftJoinsReWriter, add the following
public override void VisitWhereClause(WhereClause whereClause,
QueryModel queryModel, int index) {
base.VisitWhereClause(whereClause, queryModel, index);
// 1. Collect all member expressions that are *above* an
boolean or operator.
// These do not need new handling - they can be joined as
inner joins.
...
// 2. Traverse all member expressions that are ONLY below
boolean or operators; and replace
// the member access with a LeftJoin.
// During this traversal, pull up the necessary PK checks
"just below" the boolean or operator -
// this means that
// lhs -OR- rhs
// is replaced with
// (lhs -AND- (AND of all paths and PK properties in
lhs: PK property IS NOT NULL)
// -OR
// (rhs -AND- (AND of all paths and PK properties in
rhs: PK property IS NOT NULL)
...
// ??? 3. Replace all "table joins" with inner joins - at
least in SQL Server, mixing table joins
// (the ones with , and an = in the where clause) and
outer joins can lead to nasty error messages
// that names are not recognized (reason: each [comma-
separated] part of a from clause is sort of
// separate name scope for joins).
...
}
Of course, I'd have to convince you that the replacement of the
expressions as suggested in step 2. is
* necessary (isn't there a simpler way?); and
* sufficient (will all be ok afterwards?)
When we agree on this, I would appreciate a discussion and feedback on
* step 3. - I think it is necessary, but I'm not sure
* the placement of this code at all (e.g., should it be moved to a
separate ReWriter, because it muddles the code / responsibilites of
the current AddLeftJoinsReWriter?).
Many thanks and best regards!
Harald M.