Patrick - Thanks for the thanks - but you did the main work to make it "production-ready" ... and I would have liked to contribute more, but this and that and whatever always came up with higher priority.
The next problem in this area is, as I see it, the failing outer joins in sub-selects (http://216.121.112.228/browse/NH-2648), which is IMHO necessary to get correct Any behavior (http://216.121.112.228/browse/NH-2649); but as the joins already fail in (Java) Hibernate, it is probably not too easy ... Regards Harald -------- Original-Nachricht -------- > Datum: Sun, 26 Jun 2011 19:18:16 -0600 > Von: Patrick Earl <[email protected]> > An: [email protected] > Betreff: Re: RE: [nhibernate-development] NH-2583 - Query with || operator > and navigations (many-to-one) creates wrong joins > Just to bring this old and long thread back to life for a brief > moment, I committed my new version of the algorithm and resolved the > issue. I'm very thankful for the work that Harald did to make this > happen... especially in framing the important question of whether a > member expression will produce true if emptily outer joined. I've > been looking at this problem on and off since the start of this > thread, and after a few mornings of insight (after several evenings of > head bashing), I was able to make the connection to an easy to > understand solution to the problem, which has the potential for even > inner join optimization in even complex scenarios. > > So in summary... thanks Harald... and I think we're done with this one > for now. :) > > Patrick Earl > > On Sun, Apr 24, 2011 at 3:45 PM, Fabio Maulo <[email protected]> wrote: > > Just a very minus-little.. > > Patrick, > > That work is may be "managed" by query-substitution (true -> 1), we > should > > never use 0 for false and 1 for true during the conversion of a Linq to > HQL. > > The Linq-provider should work with true/false and the final Hql2Sql > > translator will do the replacement. > > On Sun, Apr 24, 2011 at 6:19 PM, Patrick Earl <[email protected]> wrote: > >> > >> On Sun, Apr 24, 2011 at 5:02 AM, Harald Mueller > <[email protected]> > >> wrote: > >> > Maybe I need to stress the following once more: What we try here, is > to > >> > "put 3-valued logic ('SQL logic') over navigational expressions > ('Linq > >> > expressions')". So it is a *new semantics* for Linq expressions. As I > have > >> > pointed out repeatedly, I personally would have liked to "force" > >> > Linq2Objects logic into NHib.Linq expressions. However, we agreed > that we > >> > want "simple implementations" by way of using SQL logic as much as > possible. > >> > But when we do this, let's do it in earnest! That means, above all, > clearly > >> > separating *expressions* and *conditions* in our analysis. Of course, > Linq > >> > expressions do not have this separation - so we need special rules to > >> > distinguish them. Right now, in the code, we loosely rule that > expressions > >> > with result type bool are conditions, unless they are leaf > expressions, in > >> > which case they are interpreted as conditions of the form expr == 1. > Let's > >> > stick to this at least for some more time. > >> > > >> > (This ruling does most certainly not work in cases like (a == b) != > (c < > >> > d), where a direct transformation is simply not allowed in SQL - and > >> > probably also in HQL. But such "cross-overs" between expressions and > >> > conditions are a different topic - right now, I just propose that we > do not > >> > support them). > >> > >> > >> Just a couple minor notes. It's more like expr == <true> since some > >> databases actually have a boolean type. Additionally, it should > >> ultimately be a dialect-specific transformation to decide how the SQL > >> for these booleans is ultimately generated. That work is avoided for > >> the time being. Additionally, (a==b) != (c<d) is actually a valid > >> expression in databases like PostgreSQL and SQLite. It is actually > >> rather unfortunate that MSSQL opted not to have a boolean type. Now > >> we need to perform crazy hacks like "case when x = y then 1 else 0" :( > >> I don't think it's unreasonable that Linq will actually transform > >> expressions like (a==b) != (c<d) into valid case statements at some > >> point. > >> > >> > >> > (e) expr <op> <constant(s)> (where <constant(s)> are not value-nulls) > >> > > >> > Old result: { mE -> n } for all joined mE's in expr. > >> > > >> > New result: > >> > - If an outer-joined mE makes the expression expr null (we have u in > the > >> > expression mapping), it makes the condition n. > >> > - If outer-joining that mE makes the expression not-null (we have v > in > >> > the expression), the condition can become t or f, but also n. The > latter > >> > happens if *another* member expression, when outer joined, makes the > >> > expression null. > >> > > >> > Concisely: > >> > { mE -> n } if { mE -> u } in expr > >> > { mE -> tnf } if { mE -> v } in expr > >> > >> > >> Wouldn't it be tf? > >> > >> > >> > Case (k): > >> > Constants: Constants do not contain any member expressions, so the > >> > mapping comes out empty. > >> > >> Much of this section you already discuss below, but I wrote this part > >> without reading your remaining comments. > >> > >> When determining the result of an operator, it's handy to have the > >> result of the constant around. I was considering three possible > >> values for expressions based on your original design: > >> > >> oj-null > >> value-null > >> value-not-null > >> > >> It would technically even be possible to propagate constants as far as > >> possible to optimize out known expression results. For example, 1+1 = > >> 2 could be T instead of TF. While we're ultimately only interested in > >> how to join the member expressions, there's significant intermediate > >> information available in the expressions. Providing a framework for > >> taking advantage of that information may be helpful. > >> > >> I've also been thinking about how to avoid accidental inner joins for > >> partially supported cases. I've an idea about wrapping > >> VisitExpression and ensuring that the visitor marks the result as > >> handled. Sadly there's no technique that can avoid errors in > >> development. :) > >> > >> > >> > Case (l) ["ell"]: > >> > Dot operator on complete expressions: (expr).P - this could be > something > >> > like (a.B ?? a.D).E or worse. I think we should not support such > expressions > >> > (i.e., we allow wrong results); or at least should not support inner > join > >> > optimization for them! In the latter case, we have to invest some > thought - > >> > we'd have to remove all those mappings. Here is a suggestion to solve > this > >> > easily: > >> > > >> > We replace all mapped values with the pessimistic assumption uv. > >> > >> > >> This is an interesting case. I wonder if the code produces joins for > >> this right now. > >> > >> > >> > Of course, we *could* implement that "possible expression value" > >> > concept. In the following, I use pairs <M,Z> as expression results, > where M > >> > is the mapping as above and Z is the set of all possible expression > values. > >> > The Z set can then be intersected with all mapping results to > possibly > >> > reduce the mappings. I do not give the complete formalism (which > requires > >> > all the case tables above to be rewritten to add those "possible > values"), > >> > but just an outline: > >> > >> > >> Ya, this is how it would need to be designed for maximum flexibility. > >> I've also got another stack design up my sleeves to eliminate the need > >> for the separate left/right traversals currently utilized. Basically > >> each expression node would push a single result onto the stack. In a > >> binary expression, it would pop two off and push one back on. > >> > >> > >> I'll be working on this this afternoon. I hope it comes out in a > >> concise manner. > >> > >> Thanks for all your great thoughts Harald! I especially liked the > >> (expr).P example. > >> > >> Patrick Earl > > > > > > > > -- > > Fabio Maulo > > > > -- Empfehlen Sie GMX DSL Ihren Freunden und Bekannten und wir belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.gmx.de
