Author: gbadner
Date: 2010-04-28 13:19:19 -0400 (Wed, 28 Apr 2010)
New Revision: 19317
Modified:
core/branches/Branch_3_5/core/src/main/java/org/hibernate/criterion/CountProjection.java
core/branches/Branch_3_5/parent/pom.xml
core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/criteria/CriteriaQueryTest.java
core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/hql/CriteriaHQLAlignmentTest.java
Log:
HHH-4957 HHH-3096 : Fix COUNT( DISTINCT ...) for single and multiple arguments
Modified:
core/branches/Branch_3_5/core/src/main/java/org/hibernate/criterion/CountProjection.java
===================================================================
---
core/branches/Branch_3_5/core/src/main/java/org/hibernate/criterion/CountProjection.java 2010-04-28
16:25:52 UTC (rev 19316)
+++
core/branches/Branch_3_5/core/src/main/java/org/hibernate/criterion/CountProjection.java 2010-04-28
17:19:19 UTC (rev 19317)
@@ -23,6 +23,14 @@
*/
package org.hibernate.criterion;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.hibernate.Criteria;
+import org.hibernate.QueryException;
+
/**
* A count
* @author Gavin King
@@ -43,6 +51,18 @@
}
}
+ protected List buildFunctionParameterList(Criteria criteria, CriteriaQuery
criteriaQuery) {
+ String cols[] = criteriaQuery.getColumns( propertyName, criteria );
+ return ( distinct ? buildCountDistinctParameterList( cols ) : Arrays.asList( cols ) );
+ }
+
+ private List buildCountDistinctParameterList(String[] cols) {
+ List params = new ArrayList( cols.length + 1 );
+ params.add( "distinct" );
+ params.addAll( Arrays.asList( cols ) );
+ return params;
+ }
+
public CountProjection setDistinct() {
distinct = true;
return this;
Modified: core/branches/Branch_3_5/parent/pom.xml
===================================================================
--- core/branches/Branch_3_5/parent/pom.xml 2010-04-28 16:25:52 UTC (rev 19316)
+++ core/branches/Branch_3_5/parent/pom.xml 2010-04-28 17:19:19 UTC (rev 19317)
@@ -953,6 +953,26 @@
</properties>
</profile>
+ <profile>
+ <id>mysql5-gbadner</id>
+ <dependencies>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>5.0.5</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <properties>
+
<db.dialect>org.hibernate.dialect.MySQL5InnoDBDialect</db.dialect>
+ <jdbc.driver>com.mysql.jdbc.Driver</jdbc.driver>
+ <jdbc.url>jdbc:mysql://localhost/test</jdbc.url>
+ <jdbc.user>root</jdbc.user>
+ <jdbc.pass></jdbc.pass>
+ <jdbc.isolation />
+ </properties>
+ </profile>
+
</profiles>
<properties>
Modified:
core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/criteria/CriteriaQueryTest.java
===================================================================
---
core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/criteria/CriteriaQueryTest.java 2010-04-28
16:25:52 UTC (rev 19316)
+++
core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/criteria/CriteriaQueryTest.java 2010-04-28
17:19:19 UTC (rev 19317)
@@ -27,6 +27,8 @@
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;
+import org.hibernate.dialect.HSQLDialect;
+import org.hibernate.exception.SQLGrammarException;
import org.hibernate.junit.functional.FunctionalTestCase;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
import org.hibernate.test.hql.Animal;
@@ -515,6 +517,16 @@
.uniqueResult();
assertEquals(count, new Long(2));
+ count = (Long) s.createCriteria(Enrolment.class)
+ .setProjection( Projections.countDistinct("studentNumber") )
+ .uniqueResult();
+ assertEquals(count, new Long(2));
+
+ count = (Long) s.createCriteria(Enrolment.class)
+ .setProjection( Projections.countDistinct("courseCode").as( "cnt"
) )
+ .uniqueResult();
+ assertEquals(count, new Long(1));
+
Object object = s.createCriteria(Enrolment.class)
.setProjection( Projections.projectionList()
.add( Projections.count("studentNumber") )
@@ -955,6 +967,15 @@
assertEquals( ( ( CityState ) result ).getCity(), "Odessa" );
assertEquals( ( ( CityState ) result ).getState(), "WA" );
+ result = s.createCriteria( Student.class )
+ .setProjection( Projections.count( "cityState.city" ) )
+ .uniqueResult();
+ assertEquals( 2, ( ( Long ) result ).longValue() );
+
+ result = s.createCriteria( Student.class )
+ .setProjection( Projections.countDistinct( "cityState.city" ) )
+ .uniqueResult();
+ assertEquals( 1, ( ( Long ) result ).longValue() );
t.commit();
s.close();
@@ -964,18 +985,37 @@
result = s.createCriteria( Student.class )
.setProjection( Projections.count( "cityState" ) )
.uniqueResult();
- fail( "should have failed with QueryException" );
+ fail( "expected SQLGrammarException" );
}
- catch ( QueryException ex ) {
- //expected
+ catch ( SQLGrammarException ex ) {
+ // expected
}
finally {
t.rollback();
+ s.close();
}
- s.close();
s = openSession();
t = s.beginTransaction();
+ try {
+ result = s.createCriteria( Student.class )
+ .setProjection( Projections.countDistinct( "cityState" ) )
+ .uniqueResult();
+ assertEquals( 1, ( ( Long ) result ).longValue() );
+ }
+ catch ( SQLGrammarException ex ) {
+ // HSQLDB's cannot handle more than 1 argument in SELECT COUNT( DISTINCT ... ) )
+ if ( ! ( getDialect() instanceof HSQLDialect ) ) {
+ throw ex;
+ }
+ }
+ finally {
+ t.rollback();
+ s.close();
+ }
+
+ s = openSession();
+ t = s.beginTransaction();
s.delete(gavin);
s.delete(xam);
s.delete(course);
@@ -1214,10 +1254,46 @@
course.getCourseMeetings().add( new CourseMeeting( course, "Monday", 1,
"1313 Mockingbird Lane" ) );
s.save(course);
s.flush();
-
+ s.clear();
List data = ( List ) s.createCriteria( CourseMeeting.class).setProjection(
Projections.id() ).list();
- t.rollback();
+ t.commit();
s.close();
+
+ s = openSession();
+ t = s.beginTransaction();
+ try {
+ s.createCriteria( CourseMeeting.class).setProjection( Projections.count(
"id" ) ).list();
+ fail( "should have thrown SQLGrammarException" );
+ }
+ catch ( SQLGrammarException ex ) {
+ // expected
+ }
+ finally {
+ t.rollback();
+ s.close();
+ }
+
+ s = openSession();
+ t = s.beginTransaction();
+ try {
+ Object result = s.createCriteria( CourseMeeting.class).setProjection(
Projections.countDistinct( "id" ) ).list();
+ }
+ catch ( SQLGrammarException ex ) {
+ // HSQLDB's cannot handle more than 1 argument in SELECT COUNT( DISTINCT ... ) )
+ if ( ! ( getDialect() instanceof HSQLDialect ) ) {
+ throw ex;
+ }
+ }
+ finally {
+ t.rollback();
+ s.close();
+ }
+
+ s = openSession();
+ t = s.beginTransaction();
+ s.delete( course );
+ t.commit();
+ s.close();
}
public void testProjectedCompositeIdWithAlias() {
Modified:
core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/hql/CriteriaHQLAlignmentTest.java
===================================================================
---
core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/hql/CriteriaHQLAlignmentTest.java 2010-04-28
16:25:52 UTC (rev 19316)
+++
core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/hql/CriteriaHQLAlignmentTest.java 2010-04-28
17:19:19 UTC (rev 19317)
@@ -8,6 +8,10 @@
import junit.framework.Test;
import org.hibernate.Hibernate;
+import org.hibernate.QueryException;
+import org.hibernate.Transaction;
+import org.hibernate.dialect.HSQLDialect;
+import org.hibernate.exception.SQLGrammarException;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
import org.hibernate.classic.Session;
import org.hibernate.criterion.Projections;
@@ -171,4 +175,140 @@
s.close();
}
+ public void testCountReturnValues() {
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ Human human1 = new Human();
+ human1.setName( new Name( "John", 'Q', "Public" ) );
+ human1.setNickName( "Johnny" );
+ s.save(human1);
+ Human human2 = new Human();
+ human2.setName( new Name( "John", 'A', "Doe" ) );
+ human2.setNickName( "Johnny" );
+ s.save( human2 );
+ Human human3 = new Human();
+ human3.setName( new Name( "John", 'A', "Doe" ) );
+ human3.setNickName( "Jack" );
+ s.save( human3 );
+ Human human4 = new Human();
+ human4.setName( new Name( "John", 'A', "Doe" ) );
+ s.save( human4 );
+ t.commit();
+ s.close();
+
+ s = openSession();
+ t = s.beginTransaction();
+
+ Long count = ( Long ) s.createQuery( "select count( * ) from Human"
).uniqueResult();
+ assertEquals( 4, count.longValue() );
+ s.clear();
+ count = ( Long ) s.createCriteria( Human.class )
+ .setProjection( Projections.rowCount() )
+ .uniqueResult();
+ assertEquals( 4, count.longValue() );
+ s.clear();
+
+ count = ( Long ) s.createQuery( "select count( nickName ) from Human"
).uniqueResult();
+ assertEquals( 3, count.longValue() );
+ s.clear();
+ count = ( Long ) s.createCriteria( Human.class )
+ .setProjection( Projections.count( "nickName" ) )
+ .uniqueResult();
+ assertEquals( 3, count.longValue() );
+ s.clear();
+
+ count = ( Long ) s.createQuery( "select count( distinct nickName ) from
Human" ).uniqueResult();
+ assertEquals( 2, count.longValue() );
+ s.clear();
+ count = ( Long ) s.createCriteria( Human.class )
+ .setProjection( Projections.count( "nickName" ).setDistinct() )
+ .uniqueResult();
+ assertEquals( 2, count.longValue() );
+ s.clear();
+
+ s = openSession();
+ t = s.beginTransaction();
+ try {
+ count = ( Long ) s.createQuery( "select count( distinct name ) from Human"
).uniqueResult();
+ assertEquals( 2, count.longValue() );
+ }
+ catch ( SQLGrammarException ex ) {
+ // HSQLDB's cannot handle more than 1 argument in SELECT COUNT( DISTINCT ... ) )
+ if ( ! ( getDialect() instanceof HSQLDialect ) ) {
+ throw ex;
+ }
+ }
+ finally {
+ t.rollback();
+ s.close();
+ }
+
+ s = openSession();
+ t = s.beginTransaction();
+ try {
+ count = ( Long ) s.createCriteria( Human.class )
+ .setProjection( Projections.count( "name" ).setDistinct() )
+ .uniqueResult();
+ assertEquals( 2, count.longValue() );
+ }
+ catch ( SQLGrammarException ex ) {
+ // HSQLDB's cannot handle more than 1 argument in SELECT COUNT( DISTINCT ... ) )
+ if ( ! ( getDialect() instanceof HSQLDialect ) ) {
+ throw ex;
+ }
+ }
+ finally {
+ t.rollback();
+ s.close();
+ }
+
+ s = openSession();
+ t = s.beginTransaction();
+ count = ( Long ) s.createQuery( "select count( distinct name.first ) from
Human" ).uniqueResult();
+ assertEquals( 1, count.longValue() );
+ s.clear();
+ count = ( Long ) s.createCriteria( Human.class )
+ .setProjection( Projections.count( "name.first" ).setDistinct() )
+ .uniqueResult();
+ assertEquals( 1, count.longValue() );
+ t.commit();
+ s.close();
+
+ s = openSession();
+ t = s.beginTransaction();
+ try {
+ count = ( Long ) s.createQuery( "select count( name ) from Human"
).uniqueResult();
+ fail( "should have failed due to SQLGrammarException" );
+ }
+ catch ( SQLGrammarException ex ) {
+ // expected
+ }
+ finally {
+ t.rollback();
+ s.close();
+ }
+
+ s = openSession();
+ t = s.beginTransaction();
+ try {
+ count = ( Long ) s.createCriteria( Human.class )
+ .setProjection( Projections.count( "name" ) )
+ .uniqueResult();
+ fail( "should have failed due to SQLGrammarException" );
+ }
+ catch ( SQLGrammarException ex ) {
+ // expected
+ }
+ finally {
+ t.rollback();
+ s.close();
+ }
+
+ s = openSession();
+ t = s.beginTransaction();
+ s.createQuery( "delete from Human" ).executeUpdate();
+ t.commit();
+ s.close();
+ }
+
}