From: <hib...@li...> - 2006-05-04 13:42:57
|
Author: max...@jb... Date: 2006-05-04 09:42:48 -0400 (Thu, 04 May 2006) New Revision: 9873 Modified: trunk/Hibernate3/src/org/hibernate/dialect/Dialect.java trunk/Hibernate3/test/org/hibernate/test/hql/Animal.hbm.xml trunk/Hibernate3/test/org/hibernate/test/hql/HQLTest.java trunk/Hibernate3/test/org/hibernate/test/hql/Human.java Log: HHH-1538 aggregations functions in EJBQL queries does not return the appropriate types Added HQLTest.testAggregationReturnType to test for the above statements. Consequence: COUNT changed from Hibernate.INTEGER to Hibernate.LONG MAX/MIN no changes AVG changed from being dependent on the field to only return Hibernate.DOUBLE SUM changed from always just return the type of the field to return according to the above rules. Stuff that falls besides these rules simply just return the underlying field/column type. e..g SUM(timestamp) will return timestamp; but will/should fail on the db Modified: trunk/Hibernate3/src/org/hibernate/dialect/Dialect.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/dialect/Dialect.java 2006-05-04 13:15:59 UTC (rev 9872) +++ trunk/Hibernate3/src/org/hibernate/dialect/Dialect.java 2006-05-04 13:42:48 UTC (rev 9873) @@ -65,7 +65,7 @@ static { STANDARD_AGGREGATE_FUNCTIONS.put( "count", new StandardSQLFunction("count") { public Type getReturnType(Type columnType, Mapping mapping) { - return Hibernate.INTEGER; + return Hibernate.LONG; } } ); @@ -80,18 +80,40 @@ } if ( sqlTypes.length != 1 ) throw new QueryException( "multi-column type in avg()" ); int sqlType = sqlTypes[0]; - if ( sqlType == Types.INTEGER || sqlType == Types.BIGINT || sqlType == Types.TINYINT ) { + /*pre H3.2 behavior if ( sqlType == Types.INTEGER || sqlType == Types.BIGINT || sqlType == Types.TINYINT ) { return Hibernate.FLOAT; } else { return columnType; - } + }*/ + return Hibernate.DOUBLE; } } ); STANDARD_AGGREGATE_FUNCTIONS.put( "max", new StandardSQLFunction("max") ); STANDARD_AGGREGATE_FUNCTIONS.put( "min", new StandardSQLFunction("min") ); - STANDARD_AGGREGATE_FUNCTIONS.put( "sum", new StandardSQLFunction("sum") ); + STANDARD_AGGREGATE_FUNCTIONS.put( "sum", new StandardSQLFunction("sum") { + public Type getReturnType(Type columnType, Mapping mapping) { + //pre H3.2 behavior: super.getReturnType(ct, m); + int[] sqlTypes; + try { + sqlTypes = columnType.sqlTypes( mapping ); + } + catch ( MappingException me ) { + throw new QueryException( me ); + } + if ( sqlTypes.length != 1 ) throw new QueryException( "multi-column type in sum()" ); + int sqlType = sqlTypes[0]; + if ( sqlType == Types.FLOAT || sqlType == Types.DOUBLE ) { + return Hibernate.DOUBLE; + } else if ( sqlType == Types.INTEGER || sqlType == Types.SMALLINT ) { + return Hibernate.LONG; + } + else { + return columnType; + } + } + }); } private final TypeNames typeNames = new TypeNames(); Modified: trunk/Hibernate3/test/org/hibernate/test/hql/Animal.hbm.xml =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/hql/Animal.hbm.xml 2006-05-04 13:15:59 UTC (rev 9872) +++ trunk/Hibernate3/test/org/hibernate/test/hql/Animal.hbm.xml 2006-05-04 13:42:48 UTC (rev 9873) @@ -48,6 +48,12 @@ </component> <property name="nickName"/> <property name="height"/> + + <property name="intValue"/> + <property name="floatValue"/> + <property name="bigDecimalValue"/> + <property name="bigIntegerValue"/> + <bag name="friends"> <key column="human1"/> <many-to-many column="human2" class="Human"/> Modified: trunk/Hibernate3/test/org/hibernate/test/hql/HQLTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/hql/HQLTest.java 2006-05-04 13:15:59 UTC (rev 9872) +++ trunk/Hibernate3/test/org/hibernate/test/hql/HQLTest.java 2006-05-04 13:42:48 UTC (rev 9873) @@ -618,6 +618,7 @@ assertTranslation( "select count(*) from Human h group by year(sysdate)" ); } + public void testPolymorphism() throws Exception { HashMap replacements = new HashMap(); replacements.put( "false", "0" ); @@ -804,6 +805,64 @@ assertTranslation( "select count(all an.id) from Animal an" ); } + public void testAggregationReturnType() { + // EJB3: COUNT returns Long + QueryTranslatorImpl translator = createNewQueryTranslator( "select count(*) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] ); + + // MAX, MIN return the type of the state-field to which they are applied. + translator = createNewQueryTranslator( "select max(h.height) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] ); + + translator = createNewQueryTranslator( "select max(h.id) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] ); + + // AVG returns Double. + translator = createNewQueryTranslator( "select avg(h.height) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] ); + + translator = createNewQueryTranslator( "select avg(h.id) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] ); + + translator = createNewQueryTranslator( "select avg(h.bigIntegerValue) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] ); + + // SUM returns Long when applied to state-fields of integral types (other than BigInteger); + translator = createNewQueryTranslator( "select sum(h.id) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] ); + + translator = createNewQueryTranslator( "select sum(h.intValue) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] ); + + // SUM returns Double when applied to state-fields of floating point types; + translator = createNewQueryTranslator( "select sum(h.height) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] ); + + translator = createNewQueryTranslator( "select sum(h.floatValue) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] ); + + // SUM returns BigInteger when applied to state-fields of type BigInteger + translator = createNewQueryTranslator( "select sum(h.bigIntegerValue) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.BIG_INTEGER, translator.getReturnTypes()[0] ); + + // SUM and BigDecimal when applied to state-fields of type BigDecimal. + translator = createNewQueryTranslator( "select sum(h.bigDecimalValue) from Human h" ); + assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length ); + assertEquals( "incorrect return type", Hibernate.BIG_DECIMAL, translator.getReturnTypes()[0] ); + + } + public void testSelectProperty() throws Exception { assertTranslation( "select an.bodyWeight, mo.bodyWeight from Animal an inner join an.mother mo where an.bodyWeight < mo.bodyWeight" ); } Modified: trunk/Hibernate3/test/org/hibernate/test/hql/Human.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/hql/Human.java 2006-05-04 13:15:59 UTC (rev 9872) +++ trunk/Hibernate3/test/org/hibernate/test/hql/Human.java 2006-05-04 13:42:48 UTC (rev 9873) @@ -1,6 +1,8 @@ //$Id$ package org.hibernate.test.hql; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.Collection; import java.util.Map; import java.util.Set; @@ -15,6 +17,12 @@ private Collection pets; private Map family; private double height; + + private BigInteger bigIntegerValue; + private BigDecimal bigDecimalValue; + private int intValue; + private float floatValue; + private Set nickNames; private Map addresses; @@ -81,4 +89,38 @@ public void setAddresses(Map addresses) { this.addresses = addresses; } + + public BigDecimal getBigDecimalValue() { + return bigDecimalValue; + } + + public void setBigDecimalValue(BigDecimal bigDecimalValue) { + this.bigDecimalValue = bigDecimalValue; + } + + public BigInteger getBigIntegerValue() { + return bigIntegerValue; + } + + public void setBigIntegerValue(BigInteger bigIntegerValue) { + this.bigIntegerValue = bigIntegerValue; + } + + public float getFloatValue() { + return floatValue; + } + + public void setFloatValue(float floatValue) { + this.floatValue = floatValue; + } + + public int getIntValue() { + return intValue; + } + + public void setIntValue(int intValue) { + this.intValue = intValue; + } + + } |