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
