Hi Tom,
I looked into the issue with queries selecting a JOIN or IN-clause
variable (e.g. "SELECT o FROM Customer c JOIN c.orders o" or "SELECT o
FROM Customer c, IN(c.orders) o").
I changed the code in LocalVariableNode to check whether it selects such
a variable. If so, I call addAttribute passing a new ExpressionBuilder
instance for the class returned by resolveClass instead of using the
default ExpressionBuilder for the ReportQuery. This seems to work.
Are the ExpressionBuilder instances cached somewhere? If yes I might
need to lookup the ExpressionBuilder instead of creating a new one.
Attached you find my latest changes. The jar includes all the changes,
but compared to the version of Fridays I only changed LocalVariableNode.
Thanks.
Regards Michael
> Hi Tom,
>
> thanks for your changes. I looks like you added my version of class
> ParseTree in your jar, but I was able to adapt the class following your
> changes in EJBQLParseTree.
>
> Attached you find my EJBQL compiler changes of today. Together with your
> changes a lot more queries work now. I also changed to always create a
> ReportQuery as you proposed in the other email.
>
> Please have a look at class SelectNode methods getReferenceClass,
> resolveClass and resolveBaseClass. I tried to always use the class of
> the first abstract schema in the FROM clause as the reference class.
> Then getReferenceClass would return this class, resolveClass would call
> getReferenceClass and resolveBaseClass would go away. But this runs into
> a SQLException at runtime for a EJBQL query selecting a JOIN variable:
> SELECT c FROM Order o JOIN o.customer c.
> The generated SQL uses the table name CMP3_CUSTOMER instead the defined
> table alias in the WHERE clause:
> SELECT t0.ORDER_ID, t0.SHIP_ADDR, t0.CREATION_DATE, t0.TOTAL_PRICE,
> t0.ORDER_VERSION, t0.QUANTITY, t0.ITEM_ID, t0.CUST_ID
> FROM CMP3_ORDER t0, CMP3_ORDER t1
> WHERE (CMP3_CUSTOMER.CUST_ID (+) = t1.CUST_ID)
> The problem is the table qualifier in the WHERE clause, it uses
> CMP3_CUSTOMER instead of t0.
>
> The version in the attachment implements the above behavior, but still
> has the old code in comments. Maybe you have an idea.
>
> Thanks!
>
> Regards Michael
>
>> Michael,
>>
>> I have made progress on this issue. My current solution makes use of
>> parts of the current framework that deal with parallel expression
>> builders. Specifically, GenerationContext holds a list of the
>> expressions we have built. I am testing some changes to
>> EJBQLParseTree that appear to help. Essentially, I use the same
>> GenerationContext for the whole query rather than rebuilding a new one
>> for each operation.
>>
>> I am attaching my changes to the classes you sent me yesterday. Some
>> more work may be needed, but I definitely get a better result. (two
>> classes are changed - ParseTree and EJBQLParseTree)
>>
>> -Tom
>>
>> Tom Ware wrote:
>>
>>> Michael,
>>>
>>> I am still looking at your code, but I have noticed an issue that
>>> may be causing your issue with multiple versions of the same table in
>>> the where clause when you are building queries.
>>>
>>> The constructor ExpressionBuilder(Class) is special, it creates a
>>> special parallel expression builder. Each time one of these is
>>> built, it will result in a new reference to the table it refers to in
>>> the where clause. Except in complex queries (for instance, certain
>>> subselect queries), you likely want to refer to the same table. To
>>> do that, use the same instance of the ExpressionBuilder. You may
>>> need to maintain a list of the expression builders you have created.
>>>
>>> I am still working on getting you answers to your questions, but
>>> wanted to send this information ASAP.
>>>
>>> -Tom
>>>
>>