persistence@glassfish.java.net

Re: EJBQL aggregates return type

From: Tom Ware <tom.ware_at_oracle.com>
Date: Wed, 30 Nov 2005 15:51:20 -0500

Hi Michael,

  Comment inline.

Michael Bouschen wrote:

>Hi Tom, hi Gordon,
>
>attached you find changes that make use of addCount and addAverage
>taking a result type argument. It also fixes a bug that the
>generateExpression method in AggregateNode and CountNode does not add
>the aggregate function to the returned expression.
>
>With these changes the query "SELECT COUNT(o.orderId) FROM Order o"
>returns the expected Long instance. It still returns a BigDecimal for
>the following queries:
> SELECT COUNT(o) FROM Order o
> SELECT COUNT(o.customer) FROM Order o
>The SQL for these queries uses a COUNT(*):
> SELECT COUNT(*) FROM CMP3_ORDER
> SELECT COUNT(*) FROM CMP3_CUSTOMER t0, CMP3_ORDER t1
> WHERE (t0.CUST_ID = t1.CUST_ID)
>But the SQL for the EJBQL query accessing a state field in the COUNT
>expression is: "SELECT COUNT(ORDER_ID) FROM ...". Maybe this makes a
>difference for the return type.
>
>
It looks like we have a bug in the report query code here. I'll add it
to our bug list.

>I tried another experiment using the following EJBQL:
> SELECT COUNT(o), COUNT(c) FROM Customer c JOIN c.orders o
>The generated SQL uses two COUNT(*) in the SELECT clause:
> SELECT COUNT(*), COUNT(*) FROM CMP3_ORDER t0, CMP3_CUSTOMER t1
> WHERE (t0.CUST_ID = t1.CUST_ID)
>I'm really not sure what the correct SQL should look like. I thought we
>could do a COUNT on the primary key columns instead of the COUNT(*), but
>this would not work in case of multiple primary key columns.
>
>
That's a really good test case. I think counting the primary key columns
should be fine. For multiple primary key columns we can just pick one
of them (since they are primary keys, none of them will be null).

>I checked the spec about the return type of a SUM aggregate:
>"SUM returns Long when applied to state-fields of integral types (other
>than BigInteger); Double when applied to state-fields of floating point
>types; BigInteger when applied to state-fields of type BigInteger; and
>BigDecimal when applied to state-fields of type BigDecimal."
>We could add a similar API addSum taking a return type to the
>ReportQuery, but then the AggregateNode need to checks the type of the
>aggregate argument being an integral type, etc. Does an Expression
>instance provide any type information I can check?
>
>
We can easily add the method that includes type for SUM in report
query. To get the type, you will have to look at the session stored in
the GenerationContext. That session has a project with a table of
descriptors. Those descriptors have the mappings. You can look up the
mapping for an attribute. The 'attribute' classification on each
mapping holds the type. There is likely more information you need to
get this going, so let me know what you need me to do some leg work on
and I will do it.

-Tom

>Regards Michael
>
>
>
>
>
>