persistence@glassfish.java.net

EJBQL aggregates return type

From: Michael Bouschen <Michael.Bouschen_at_Sun.COM>
Date: Wed, 30 Nov 2005 20:48:09 +0100

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.

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.

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?

Regards Michael