[hibernate-dev] Treat support

Christian Beikov christian.beikov at gmail.com
Tue Aug 23 08:08:20 EDT 2016


Hi Emond,

thanks for the list, I already linked some of the issues you opened. 
HHH-10561, HHH-10759, HHH-10767 and HHH-11062 are apparently bugs in the 
Criteria to HQL/JPQL rendering and I am trying to directly target the 
HQL/JPQL parts.

Regarding HHH-10768 see the comments on the issue.


Regards,

Christian

Am 23.08.2016 um 11:36 schrieb Emond Papegaaij:

> Hi Christian,
>
> In the past few months I've reported quite a few bugs on treat support in
> Hibernate. I think some of them are already covered by your tests, but not
> all. You might want to add those to your tests. These are the issues I've
> reported:
> https://hibernate.atlassian.net/browse/HHH-10561
> https://hibernate.atlassian.net/browse/HHH-10759
> https://hibernate.atlassian.net/browse/HHH-10767
> https://hibernate.atlassian.net/browse/HHH-10768
> https://hibernate.atlassian.net/browse/HHH-11062
>
> Best regards,
> Emond
>
> On dinsdag 23 augustus 2016 11:07:22 CEST Christian Beikov wrote:
>> Hi,
>>
>> so I finished my work on the testsuite
>> <https://github.com/beikov/jpa-treat-variations> for the treat operator.
>> I also started a forum topic for this discussion:
>> https://forum.hibernate.org/viewtopic.php?f=1&t=1043553
>> If anyone is interested, I also started a discussion in the EclipeLink
>> forum about that:
>> https://www.eclipse.org/forums/index.php/mn/msg/1080319/1/on/0/?SQ=5ddc74f60
>> 1d6750e4794121738a57076
>>
>> I hope we can all agree on an interpretation of how treat should work
>> and hopefully get a clarification into the spec. Or at least some TCK
>> tests, as it doesn't seem to assert anything useful right now.
>>
>> Regards,
>> Christian
>>
>> Am 09.08.2016 um 13:14 schrieb Christian Beikov:
>>> Hello again,
>>>
>>> I finished the first part of the test cases for root treats and
>>> many-to-one treats. I also tried to explain how I would expect treat
>>> to work and present a reduction/translation strategy to be able to
>>> reduce thinking just about the base cases.
>>> Could you comment on that?
>>> https://github.com/beikov/jpa-treat-variations/blob/master/src/test/java/j
>>> pa/test/TreatVariationsTest.java The tests show various problems with
>>> Hibernate as well as EclipseLink. I will add findings from Datanucleus as
>>> soon as the relation mapping for table per class is supported.
>>>
>>> Here is a collection of JIRAs for treat problems
>>>
>>>    * https://hibernate.atlassian.net/browse/HHH-10988
>>>    * https://hibernate.atlassian.net/browse/HHH-9345
>>>    * https://hibernate.atlassian.net/browse/HHH-9862
>>>    * https://hibernate.atlassian.net/browse/HHH-10768
>>>    * https://hibernate.atlassian.net/browse/HHH-9594
>>>
>>> The definition of the semantics according to JPA spec 4.4.9 are a bit
>>> strange as it does not distinguish between FROM and WHERE clause when
>>> mentioning filtering on the subtype.
>>> It specifically says "Use of the TREAT operator therefore also has the
>>> effect of filtering on the specified type (and its subtypes) as well
>>> as performing the downcast" and I think this is only relevant for
>>> treats in the FROM clause.
>>> Treats in the WHERE clause should not result in filtering. Depending
>>> on the join type which is used for the treat path, the result of the
>>> treat is either the subtype instance, or may be NULL in case of a left
>>> join.
>>> Since any comparison(except NULL aware operations) with NULL will
>>> eventually result in FALSE according to the SQL spec, the requirement
>>> for the treat operator in the WHERE clause to result in FALSE for
>>> instances that are not a subtype is also fulfilled.
>>> The section "... and in the case of a restriction, the associated
>>> predicate is false." didn't consider NULL aware operations so I think
>>> this is an oversight.
>>>
>>> Am 04.08.2016 um 15:52 schrieb Steve Ebersole:
>>>> Hey Christian,
>>>>
>>>> In general terms, one of the items on the docket for SQM is better
>>>> TREAT support; but there is a lot that goes into that statement.  One
>>>> aspect is what we support in the parser properly in terms of
>>>> recognition.  Another is how this translates into the generates SQL
>>>> query.  All of this is being looked at with SQM.
>>>>
>>>> Also, relatedly, better support for switching on/off JPQL-compliance
>>>> checking is a goal.
>>>>
>>>> <background>
>>>> TREAT is an explicit downcast operator.  It allows you to down cast a
>>>> type reference in order to reference one of its subclass attributes.
>>>> HQL actually supports implicit downcasting (subclass attribute
>>>> references).  In a way you can think of HQL as offering TREAT support
>>>> implicitly.
>>>> </background>
>>>>
>>>> With all that in mind, see my comments inline...
>>>>
>>>>
>>>> On Wed, Aug 3, 2016 at 9:43 PM Christian Beikov
>>>>
>>>> <christian.beikov at gmail.com <mailto:christian.beikov at gmail.com>> wrote:
>>>>        * Missing support for treated paths like "TREAT(...).property"
>>>>      
>>>>      in the
>>>>      
>>>>          parser. This is more or less workaroundable for non-root path
>>>>          treats. Since root paths can't be treat joined to my
>>>>      
>>>>      knowledge, some
>>>>      
>>>>          treated paths simple can't be used. Maybe in 90% of the cases
>>>>          hibernate will just resolve to the right property without needing
>>>>          the treat?
>>>>
>>>> I'm not sure what you mean by "root paths can't be treated".  You
>>>> mean literally the query root?  As in "MyEntity e" in "select e from
>>>> MyEntity e"?  If so, yes JPA does not allow for that to be TREAT'ed;
>>>> but really it makes no sense to allow TREAT there, if you step back
>>>> and look at it.  A query like "select e from TREAT(MyEntity as MySub)
>>>> e" makes no sense; its ultimately just the same as "select e from
>>>> MySub e".  Arguably I guess it *could* make some sense *if* MySub is
>>>> a sub MappedSuperclass since technically JPA also allows only
>>>> entities as query roots (HQL does not have this restriction).
>>>>
>>>> As discussed above, assuming that "someProp" is a persistent property
>>>> defined on MySub, this is a perfectly valid HQL: "select e.someProp
>>>> from MyEntity e".  It is not however valid JPQL; in JPQL you'd have
>>>> to say: "select treat( e as MySub).someProp from MyEntity e"
>>>>
>>>> All that said, the inability to dereference a TREAT'ed path (the
>>>> ".property" part) would be a bug, and tbh I am surprised that you say
>>>> this does not work with Hibernate. Which of your tests show this not
>>>> working?  Is there a related Jira?
>>>>
>>>>        * Missing support for a special case of treat join which apparently
>>>>        
>>>>          was overseen by the JPA spec which would be
>>>>      
>>>>      "TREAT(TREAT(rootPath AS
>>>>      
>>>>          Subtype).relation AS RelationSubtype)". Eclipselink not only
>>>>      
>>>>      allows
>>>>      
>>>>          this syntax but for inner joins also implements the appropriate
>>>>          logic. I am thinking that this might even work in hibernate
>>>>      
>>>>      without
>>>>      
>>>>          the inner treat, but would fail for attributes with same names.
>>>>
>>>> Do you mean specifically the nesting of TREAT operators?  Again, I am
>>>> surprised that this would not work.  Tests?  Jira?
>>>>
>>>>        * Joins for supertypes and conditions on discriminators are not
>>>>      
>>>>      aware
>>>>      
>>>>          of the join type actually used in the treated join => left join
>>>>          should cascade up the type hierarchy and discriminator checks
>>>>      
>>>>      should
>>>>      
>>>>          contain OR DTYPE IS NULL for left join semantics. If treats
>>>>      
>>>>      are in
>>>>      
>>>>          subconditions the DTYPE checks might even be wrong
>>>>
>>>> This "restriction" aspect is honestly Hibernate's biggest shortcoming
>>>> in its TREAT support. Hibernate's "SQL generation machinery" simply
>>>> was not built to support this.  At all.  I hacked together some
>>>> support for TREAT on top of that legacy "SQL generation machinery",
>>>> but it is very limited.
>>>>
>>>> This aspect is specifically what we have discussed in terms of TREAT
>>>> support improvements in SQM.  Keeping track of where the TREAT occurs
>>>> so that we can later know how to properly handle it, whether that
>>>> means we can skip parts of the inheritance join tree or maybe need to
>>>> render some extra WHERE-clause restrictions...
>>>>
>>>>        * Joins are generated for the whole hierarchy not only the
>>>>      
>>>>      types that
>>>>      
>>>>          are treated => this might seem to be "just" a performance
>>>>      
>>>>      problem,
>>>>      
>>>>          but IMO actually is a correctness problem as it makes a
>>>>      
>>>>      difference
>>>>      
>>>>          if you get e.g. 2 rows or 2 * TYPES rows especially for count
>>>>      
>>>>      queries.
>>>>
>>>> Generating the joins for the whole hierarchy is important for HQL's
>>>> implicit downcasting support. However, that said, there are attempts
>>>> to restrict that already in place.  IIRC this only works for TREATs
>>>> that occur in the FROM-clause specifically.  However, I thought that
>>>> other TREAT operations were still handled in terms of adding
>>>> restrictions when dictated.  So this might be specific to certain
>>>> circumstances.
>>>>
>>>> Again, which specific tests show this?  Jira?
>>>>
>>>> ----
>>>>
>>>> Some specifics of the plan...
>>>>
>>>> First, internally within the query AST I want to make sure that we
>>>> model *all* downcasts whether they are implicit or explicit.  In
>>>> other words, in terms of AST both of these queries would result in
>>>>
>>>> the same structure:
>>>>   1. select e.someProp from MyEntity
>>>>   2. select treat(e as MySub).someProp from MyEntity
>>>>
>>>> Secondly, we need to keep track of various pieces of information
>>>> pertaining to a downcast
>>>> (see
>>>> org.hibernate.sqm.query.from.Downcast/org.hibernate.sqm.query.from.Downc
>>>> astable).>>
>>>> This includes info like:
>>>>   1. The downcast "target"
>>>>   2. The context in which the downcast occurred
>>>>   3. Any/all contexts in which the downcast is used.
>>>>
>>>> The last 2 items there would specifically lead to:
>>>>    * Which specific inheritance joins are needed - and may indicate
>>>>    
>>>>      join type
>>>>    
>>>>    * Any extra restrictions we may need to add
>> _______________________________________________
>> hibernate-dev mailing list
>> hibernate-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>
> _______________________________________________
> hibernate-dev mailing list
> hibernate-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/hibernate-dev



More information about the hibernate-dev mailing list