I am not crazy about breaking changes either, but I think we can slip this in as the _non_ default parser for a while. That would ensure that it wouldn't break anyone who didn't explicitly want that.
That will give us the immediate benefit of being able to build queries using the HQL, which will allow us to start working on the real Linq impl. On Wed, Apr 15, 2009 at 1:32 AM, Fabio Maulo <[email protected]> wrote: > I prefer to wait before introduce some breaking-changes for parser even if > is for legacy DB. > Why this query should not work ? > select count(*) from Bar as bar where '1' in (from g > in bar.Component.Glarch.ProxyArray.elements where g.Name='foo') > Who are sure that query was not ported from Hb in some moment ? > > IFAIK NHibernate.Test.Legacy was one of the first tests ported from Hb. > > 2009/4/14 Ayende Rahien <[email protected]> > > Steve, >> That is great job. >> Looking at the test results, I am fine with breaking all of them, except >> for: >> "from E e, A a where e.Reverse = a.Forward and a = ?" >> >> Looking at this, I am not sure _why_ this should generate a _parser_ >> error. >> From syntax perspective, it seems to be valid. >> >> My point of view is in two points: >> a) if we match Hibernate's behavior, we are good, because that is our >> spec, for most things >> b) we _can_ break backward compat in small ways. We are going to ship both >> parsers for at least a while, and give the user the configuration option to >> select one. That means that if a user is hit by a backward compat bug here, >> they can just revert to the old parser, and continue using that. That is an >> acceptable solution from my point of view. >> >> >> On Tue, Apr 14, 2009 at 10:16 PM, Steve <[email protected]> wrote: >> >>> >>> Hi Chaps, >>> >>> Finally, another update on the HQL AST parser work. I've had a few >>> other things on my plate the last couple of weeks, but managed to get >>> a few hours in on the parser. This post was coming out on Monday, but >>> I thought I'd better resync with the NHibernate trunk, and alas it >>> broke a couple of things. They are now fixed, so finally I think >>> we're nearly there. I've got a little bit of refactoring to do, and >>> sort out the error handling, but it's nothing major at all, and >>> doesn't stop me form getting onto the LINQ side of things at last. >>> There are a few tests that are failing which I could use your opinions >>> on whether the new behaviour is acceptable or not - these are listed >>> below. >>> >>> If anyone wants to test this, you should just be able to get the HQL >>> AST parser from the uNhAddins repository, build it and drop the binary >>> into the NHibernate.Tests\bin\Debug-2.0. Finally, add the following to >>> your config: >>> >>> <property >>> >>> name="query.factory_class">NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory, >>> ANTLR-HQL</property> >>> >>> One last thing, there's a change you´ll need to make to a minor change >>> to MultiQueryImpl.AggregateQueriesInformation() - change the foreach >>> from >>> foreach (QueryTranslator translator in queryTranslators) >>> to >>> foreach (IQueryTranslator translator in queryTranslators) >>> >>> and this line: >>> SqlCommandInfo commandInfo = translator.GetQueryStringAndTypes >>> (session, queryParameters); >>> to >>> SqlCommandInfo commandInfo = >>> translator.Loader.GetQueryStringAndTypes >>> (session, queryParameters); >>> >>> (I've sent a patch to Fabio, so hopefully this'll end up in the trunk >>> soon) >>> >>> That's the lot. I'm off to look at LINQ, and if you can let me know >>> how to handle the issues below, that would be cool. >>> >>> Cheers, >>> >>> Steve >>> >>> >>> ======================== >>> >>> TestCase 'NHibernate.Test.Hql.HQLFunctions.Cast' failed: >>> Expected: 1.29999995f >>> But was: 1.3d >>> >>> Z:\NHibernate\Trunk\nhibernate\src\NHibernate.Test\HQL\HQLFunctions.cs >>> (598,0): at NHibernate.Test.Hql.HQLFunctions.Cast() >>> >>> The query that is being executed here is "select cast(cast >>> (a.BodyWeight as string) as Double) from Animal a". The new parser is >>> returning 1.3 as a double, but the test is comparing the return value >>> with 1.3F (i.e., a single), and the vagaries of floating point math >>> causes failures when doing the comparisons. The old parser returned >>> Singles for this test, hence it worked. So the question is, should >>> the new parser be changed to return Singles, or should the test be >>> updated? >>> >>> ======================== >>> >>> Error: line 1:-1 no viable alternative at input 'is' >>> TestCase 'NHibernate.Test.Hql.HQLFunctions.Nullif' >>> failed: System.InvalidCastException : Unable to cast object of type >>> 'Antlr.Runtime.CommonErrorNode' to type >>> 'NHibernate.Hql.Ast.ANTLR.Tree.IASTNode'. >>> >>> Z:\uNhAddins\Trunk\ANTLR-HQL\ANTLR-HQL\Output\HqlParser.cs(5698,0): >>> at NHibernate.Hql.Ast.ANTLR.HqlParser.relationalExpression() >>> [middle of stack deleted for brevity] >>> >>> Z:\NHibernate\Trunk\nhibernate\src\NHibernate.Test\HQL\HQLFunctions.cs >>> (428,0): at NHibernate.Test.Hql.HQLFunctions.Nullif() >>> >>> The query here is "from Human h where nullif(h.NickName, '1e1') not is >>> null", and the new parser doesn't understand the "not is null" >>> construct. The behaviour here matches Hibernate, which also fails >>> with a query of this form. I for one don't like the syntax here, so >>> would be happy leaving it "broken". The user can obviously re-write >>> the query to get the required results (i.e., by using "is not null" >>> rather than the sucky "not is null"). Thoughts? BTW, ignore the >>> InvalidCastException that shows up in the error above, I've got to >>> sort out the error handling bit; it's not been high on the list, since >>> it's "just code" - nothing that is going to cause any issues :) >>> >>> ======================== >>> >>> failed: NHibernate.TypeMismatchException : left and right hand sides >>> of a binary logic operator were incompatibile >>> [NHibernate.DomainModel.A : NHibernate.DomainModel.E] >>> TearDown : System.Reflection.TargetInvocationException : Exception has >>> been thrown by the target of an invocation. >>> ----> NUnit.Framework.AssertionException : Test didn't clean up >>> after itself >>> >>> Z:\uNhAddins\Trunk\ANTLR-HQL\ANTLR-HQL\Tree\BinaryLogicOperatorNode.cs >>> (85,0): at >>> >>> NHibernate.Hql.Ast.ANTLR.Tree.BinaryLogicOperatorNode.MutateRowValueConstructorSyntaxesIfNecessary >>> (IType lhsType, IType rhsType) >>> [middle of stack deleted for brevity] >>> Z:\NHibernate\Trunk\nhibernate\src\NHibernate.Test\Legacy >>> \ABCProxyTest.cs(292,0): at >>> NHibernate.Test.Legacy.ABCProxyTest.OneToOne() >>> >>> The query here is "from E e, A a where e.Reverse = a.Forward and a >>> = ?". I think the new parser has this correct (I won't explain the >>> domain model here, it's probably easier if you just look at the >>> code). To back up my claim, Hibernate shows the same behaviour for >>> this test :) Take a look at the test and associated model, and let me >>> know what you think should happen. >>> >>> ======================== >>> >>> The following 4 are all from the Legacy test fixtures, and they all >>> fail in Hibernate in the same way. Since they are under legacy, I've >>> not spent much time looking at them. Are they things we need to >>> support in the new parser? >>> >>> TestCase 'NHibernate.Test.Legacy.FooBarTest.CollectionsInSelect' >>> failed: System.NullReferenceException : Object reference not set to an >>> instance of an object. >>> TearDown : System.Reflection.TargetInvocationException : Exception has >>> been thrown by the target of an invocation. >>> ----> NUnit.Framework.AssertionException : Test didn't clean up >>> after itself. session closed: False database cleaned: True connection >>> closed: True >>> >>> Z:\uNhAddins\Trunk\ANTLR-HQL\ANTLR-HQL\Tree\SelectExpressionList.cs >>> (30,0): at >>> >>> NHibernate.Hql.Ast.ANTLR.Tree.SelectExpressionList.CollectSelectExpressions >>> () >>> [middle of stack deleted for brevity] >>> Z:\NHibernate\Trunk\nhibernate\src\NHibernate.Test\Legacy >>> \FooBarTest.cs(2471,0): at >>> NHibernate.Test.Legacy.FooBarTest.CollectionsInSelect() >>> Query was "select count(*) from Bar as bar where '1' in (from g in >>> bar.Component.Glarch.ProxyArray.elements where g.Name='foo')" >>> >>> TestCase 'NHibernate.Test.Legacy.FooBarTest.Query' >>> failed: NHibernate.ADOException : could not execute query >>> [SQL: select bar0_.[foo_id] as foo1_517_, bar0_.Version as >>> Version517_, bar0_.foo as foo517_, bar0_.long_ as long5_517_, bar0_. >>> [@@##integer_ *] as column6_517_, bar0_.float_ as float7_517_, >>> bar0_.X as X517_, bar0_.date_ as date9_517_, bar0_.timestamp_ as >>> timestamp10_517_, bar0_.boolean_ as boolean11_517_, bar0_.bool_ as >>> bool12_517_, bar0_.null_ as null13_517_, bar0_.short_ as short14_517_, >>> bar0_.char_ as char15_517_, bar0_.zero_ as zero16_517_, bar0_.int_ as >>> int17_517_, bar0_.string_ as string18_517_, bar0_.byte_ as >>> byte19_517_, bar0_.YesNo as YesNo517_, bar0_.[stat...@###] as >>> status21_517_, bar0_.[localeayzabc1...@#$] as localea22_517_, >>> bar0_.first_name as first23_517_, bar0_.surname as surname517_, >>> bar0_.Dependent as Dependent517_, bar0_.count_ as count26_517_, >>> bar0_.name_ as name27_517_, bar0_.g__ as g28_517_, bar0_.cmpnt_null_ >>> as cmpnt29_517_, bar0_.subcount as subcount517_, bar0_.subname as >>> subname517_, bar0_.fee_sub as fee32_517_, bar0_.null_cmpnt_ as >>> null33_517_, bar0_.the_time as the34_517_, bar0_.Baz as Baz517_, >>> bar0_.bar_String as bar36_517_, bar0_.name_name as name37_517_, >>> bar0_.bar_count as bar38_517_, bar0_.Name as Name517_, bar0_.clazz as >>> clazz517_, bar0_.[gen_id] as gen41_517_, 2 * bar0_.int_ as formula37_ >>> from [foos] bar0_, StringDateMap stringdate2_ where bar0_. >>> [$foo_subclass^]='B' and bar0_.Baz=baz1_.baz_id and >>> baz1_.baz_id=stringdate2_.id_ and stringdate2_.map_key = 'now' and >>> (stringdate2_.map_value is not null)] >>> ----> System.Data.SqlClient.SqlException : The multi-part identifier >>> "baz1_.baz_id" could not be bound. >>> The multi-part identifier "baz1_.baz_id" could not be bound. >>> TearDown : System.Reflection.TargetInvocationException : Exception has >>> been thrown by the target of an invocation. >>> ----> NUnit.Framework.AssertionException : Test didn't clean up >>> after itself. session closed: False database cleaned: False connection >>> closed: True >>> Z:\NHibernate\Trunk\nhibernate\src\NHibernate\Loader\Loader.cs >>> (1661,0): at NHibernate.Loader.Loader.DoList(ISessionImplementor >>> session, QueryParameters queryParameters) >>> [middle of stack deleted for brevity] >>> Z:\NHibernate\Trunk\nhibernate\src\NHibernate.Test\Legacy >>> \FooBarTest.cs(855,0): at NHibernate.Test.Legacy.FooBarTest.Query() >>> Query was "select bar from Bar bar where bar.Baz.StringDateMap['now'] >>> is not null" >>> >>> TestCase 'NHibernate.Test.Legacy.MasterDetailTest.CollectionQuery' >>> failed: System.NullReferenceException : Object reference not set to an >>> instance of an object. >>> TearDown : System.Reflection.TargetInvocationException : Exception has >>> been thrown by the target of an invocation. >>> ----> NUnit.Framework.AssertionException : Test didn't clean up >>> after itself. session closed: False database cleaned: True connection >>> closed: True >>> >>> Z:\uNhAddins\Trunk\ANTLR-HQL\ANTLR-HQL\Tree\SelectExpressionList.cs >>> (30,0): at >>> >>> NHibernate.Hql.Ast.ANTLR.Tree.SelectExpressionList.CollectSelectExpressions >>> () >>> [middle of stack deleted for brevity] >>> Z:\NHibernate\Trunk\nhibernate\src\NHibernate.Test\Legacy >>> \MasterDetailTest.cs(371,0): at >>> NHibernate.Test.Legacy.MasterDetailTest.CollectionQuery() >>> Query was "FROM m IN CLASS Master WHERE NOT EXISTS ( FROM d in >>> m.Details.elements WHERE NOT d.I=5 )" >>> >>> TestCase 'NHibernate.Test.Legacy.MasterDetailTest.MasterDetail' >>> failed: NHibernate.QueryException : query specified join fetching, but >>> the owner of the fetched association was not present in the select >>> list [FromElement{explicit,not a collection join,fetch join,fetch non- >>> lazy >>> >>> properties,classAlias=,role=NHibernate.DomainModel.Master.Details,tableName=Detail,tableAlias=details1_,origin=Master >>> master0_,colums= >>> {master0_.master_key_column ,className=NHibernate.DomainModel.Detail}}] >>> [select m.id from NHibernate.DomainModel.Master m inner join fetch >>> m.Details] >>> TearDown : System.Reflection.TargetInvocationException : Exception has >>> been thrown by the target of an invocation. >>> ----> NUnit.Framework.AssertionException : Test didn't clean up >>> after itself. session closed: False database cleaned: False connection >>> closed: True >>> >>> Z:\uNhAddins\Trunk\ANTLR-HQL\ANTLR-HQL\Tree\SelectClause.cs(200,0): >>> at >>> NHibernate.Hql.Ast.ANTLR.Tree.SelectClause.InitializeExplicitSelectClause >>> (FromClause fromClause) >>> [middle of stack deleted for brevity] >>> Z:\NHibernate\Trunk\nhibernate\src\NHibernate.Test\Legacy >>> \MasterDetailTest.cs(465,0): at >>> NHibernate.Test.Legacy.MasterDetailTest.MasterDetail() >>> Query was: "select m.id from Master m inner join fetch m.Details" >>> >> >> > > > -- > Fabio Maulo >
