diff --git a/core/src/main/java/org/hibernate/dialect/Dialect.java b/core/src/main/java/org/hibernate/dialect/Dialect.java index f2b25ab3cf..24e4c96995 100644 --- a/core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/core/src/main/java/org/hibernate/dialect/Dialect.java @@ -2015,4 +2015,23 @@ public abstract class Dialect { public boolean supportsBindAsCallableArgument() { return true; } + + /** + * Does this dialect support `count(a,b)`? + * + * @return True if the database supports counting tuples; false otherwise. + */ + public boolean supportsTupleCounts() { + return false; + } + + /** + * Does this dialect support `count(distinct a,b)`? + * + * @return True if the database supports counting disintct tuples; false otherwise. + */ + public boolean supportsTupleDistinctCounts() { + // oddly most database in fact seem to, so true is the default. + return true; + } } diff --git a/core/src/main/java/org/hibernate/dialect/H2Dialect.java b/core/src/main/java/org/hibernate/dialect/H2Dialect.java index 874fbb9670..17bf0d8af3 100644 --- a/core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -305,4 +305,9 @@ public class H2Dialect extends Dialect { public boolean supportsLobValueChangePropogation() { return false; } + + @Override + public boolean supportsTupleDistinctCounts() { + return false; + } } diff --git a/core/src/main/java/org/hibernate/dialect/HSQLDialect.java b/core/src/main/java/org/hibernate/dialect/HSQLDialect.java index f5e9389f88..7c6774a132 100644 --- a/core/src/main/java/org/hibernate/dialect/HSQLDialect.java +++ b/core/src/main/java/org/hibernate/dialect/HSQLDialect.java @@ -331,4 +331,9 @@ public class HSQLDialect extends Dialect { public boolean supportsLobValueChangePropogation() { return false; } + + @Override + public boolean supportsTupleDistinctCounts() { + return false; + } } diff --git a/parent/pom.xml b/parent/pom.xml index 4f375fffcb..2be1aa87d7 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -598,7 +598,7 @@ org.hibernate.dialect.H2Dialect org.h2.Driver - jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1 + jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE sa diff --git a/testsuite/src/test/java/org/hibernate/test/compositeelement/CompositeElementTest.java b/testsuite/src/test/java/org/hibernate/test/compositeelement/CompositeElementTest.java index c101124527..6bbe18a0f6 100755 --- a/testsuite/src/test/java/org/hibernate/test/compositeelement/CompositeElementTest.java +++ b/testsuite/src/test/java/org/hibernate/test/compositeelement/CompositeElementTest.java @@ -90,6 +90,7 @@ public class CompositeElementTest extends FunctionalTestCase { public void testCustomColumnReadAndWrite() { final double HEIGHT_INCHES = 49; final double HEIGHT_CENTIMETERS = HEIGHT_INCHES * 2.54d; + Session s = openSession(); Transaction t = s.beginTransaction(); Child c = new Child( "Child One" ); @@ -99,8 +100,8 @@ public class CompositeElementTest extends FunctionalTestCase { c.setParent( p ); s.save( p ); s.flush(); - - // Test value conversion during insert + + // Test value conversion during insert Double heightViaSql = (Double)s.createSQLQuery("select height_centimeters from parentchild c where c.name='Child One'") .uniqueResult(); assertEquals(HEIGHT_CENTIMETERS, heightViaSql, 0.01d); diff --git a/testsuite/src/test/java/org/hibernate/test/criteria/CriteriaQueryTest.java b/testsuite/src/test/java/org/hibernate/test/criteria/CriteriaQueryTest.java index b136d296f5..e5c88c7edb 100755 --- a/testsuite/src/test/java/org/hibernate/test/criteria/CriteriaQueryTest.java +++ b/testsuite/src/test/java/org/hibernate/test/criteria/CriteriaQueryTest.java @@ -985,10 +985,18 @@ public class CriteriaQueryTest extends FunctionalTestCase { result = s.createCriteria( Student.class ) .setProjection( Projections.count( "cityState" ) ) .uniqueResult(); - fail( "expected SQLGrammarException" ); + if ( ! getDialect().supportsTupleCounts() ) { + fail( "expected SQLGrammarException" ); + } + assertEquals( 1, ( ( Long ) result ).longValue() ); } catch ( SQLGrammarException ex ) { - // expected + if ( ! getDialect().supportsTupleCounts() ) { + // expected + } + else { + throw ex; + } } finally { t.rollback(); @@ -999,13 +1007,18 @@ public class CriteriaQueryTest extends FunctionalTestCase { t = s.beginTransaction(); try { result = s.createCriteria( Student.class ) - .setProjection( Projections.countDistinct( "cityState" ) ) - .uniqueResult(); + .setProjection( Projections.countDistinct( "cityState" ) ) + .uniqueResult(); + if ( ! getDialect().supportsTupleDistinctCounts() ) { + fail( "expected SQLGrammarException" ); + } assertEquals( 1, ( ( Long ) result ).longValue() ); } catch ( SQLGrammarException ex ) { - // HSQLDB's cannot handle more than 1 argument in SELECT COUNT( DISTINCT ... ) ) - if ( ! ( getDialect() instanceof HSQLDialect ) ) { + if ( ! getDialect().supportsTupleDistinctCounts() ) { + // expected + } + else { throw ex; } } @@ -1276,11 +1289,16 @@ public class CriteriaQueryTest extends FunctionalTestCase { s = openSession(); t = s.beginTransaction(); try { - Object result = s.createCriteria( CourseMeeting.class).setProjection( Projections.countDistinct( "id" ) ).list(); + s.createCriteria( CourseMeeting.class).setProjection( Projections.countDistinct( "id" ) ).list(); + if ( ! getDialect().supportsTupleDistinctCounts() ) { + fail( "expected SQLGrammarException" ); + } } catch ( SQLGrammarException ex ) { - // HSQLDB's cannot handle more than 1 argument in SELECT COUNT( DISTINCT ... ) ) - if ( ! ( getDialect() instanceof HSQLDialect ) ) { + if ( ! getDialect().supportsTupleDistinctCounts() ) { + // expected + } + else { throw ex; } } diff --git a/testsuite/src/test/java/org/hibernate/test/hql/CriteriaHQLAlignmentTest.java b/testsuite/src/test/java/org/hibernate/test/hql/CriteriaHQLAlignmentTest.java index 9472e421a6..bd8664aadd 100644 --- a/testsuite/src/test/java/org/hibernate/test/hql/CriteriaHQLAlignmentTest.java +++ b/testsuite/src/test/java/org/hibernate/test/hql/CriteriaHQLAlignmentTest.java @@ -230,11 +230,16 @@ public class CriteriaHQLAlignmentTest extends QueryTranslatorTestCase { t = s.beginTransaction(); try { count = ( Long ) s.createQuery( "select count( distinct name ) from Human" ).uniqueResult(); + if ( ! getDialect().supportsTupleDistinctCounts() ) { + fail( "expected SQLGrammarException" ); + } assertEquals( 2, count.longValue() ); } catch ( SQLGrammarException ex ) { - // HSQLDB's cannot handle more than 1 argument in SELECT COUNT( DISTINCT ... ) ) - if ( ! ( getDialect() instanceof HSQLDialect ) ) { + if ( ! getDialect().supportsTupleDistinctCounts() ) { + // expected + } + else { throw ex; } } @@ -247,13 +252,18 @@ public class CriteriaHQLAlignmentTest extends QueryTranslatorTestCase { t = s.beginTransaction(); try { count = ( Long ) s.createCriteria( Human.class ) - .setProjection( Projections.count( "name" ).setDistinct() ) - .uniqueResult(); + .setProjection( Projections.count( "name" ).setDistinct() ) + .uniqueResult(); + if ( ! getDialect().supportsTupleDistinctCounts() ) { + fail( "expected SQLGrammarException" ); + } assertEquals( 2, count.longValue() ); } catch ( SQLGrammarException ex ) { - // HSQLDB's cannot handle more than 1 argument in SELECT COUNT( DISTINCT ... ) ) - if ( ! ( getDialect() instanceof HSQLDialect ) ) { + if ( ! getDialect().supportsTupleDistinctCounts() ) { + // expected + } + else { throw ex; } } @@ -278,10 +288,18 @@ public class CriteriaHQLAlignmentTest extends QueryTranslatorTestCase { t = s.beginTransaction(); try { count = ( Long ) s.createQuery( "select count( name ) from Human" ).uniqueResult(); - fail( "should have failed due to SQLGrammarException" ); + if ( ! getDialect().supportsTupleCounts() ) { + fail( "expected SQLGrammarException" ); + } + assertEquals( 1, count.longValue() ); } catch ( SQLGrammarException ex ) { - // expected + if ( ! getDialect().supportsTupleCounts() ) { + // expected + } + else { + throw ex; + } } finally { t.rollback(); @@ -292,12 +310,20 @@ public class CriteriaHQLAlignmentTest extends QueryTranslatorTestCase { t = s.beginTransaction(); try { count = ( Long ) s.createCriteria( Human.class ) - .setProjection( Projections.count( "name" ) ) - .uniqueResult(); - fail( "should have failed due to SQLGrammarException" ); + .setProjection( Projections.count( "name" ) ) + .uniqueResult(); + if ( ! getDialect().supportsTupleCounts() ) { + fail( "expected SQLGrammarException" ); + } + assertEquals( 1, count.longValue() ); } catch ( SQLGrammarException ex ) { - // expected + if ( ! getDialect().supportsTupleCounts() ) { + // expected + } + else { + throw ex; + } } finally { t.rollback(); diff --git a/testsuite/src/test/java/org/hibernate/test/hql/HQLTest.java b/testsuite/src/test/java/org/hibernate/test/hql/HQLTest.java index e4f584f46b..c297172122 100644 --- a/testsuite/src/test/java/org/hibernate/test/hql/HQLTest.java +++ b/testsuite/src/test/java/org/hibernate/test/hql/HQLTest.java @@ -14,6 +14,7 @@ import junit.framework.Test; import org.hibernate.Hibernate; import org.hibernate.QueryException; import org.hibernate.dialect.DB2Dialect; +import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.HSQLDialect; import org.hibernate.dialect.IngresDialect; import org.hibernate.dialect.MySQLDialect; @@ -726,9 +727,12 @@ public class HQLTest extends QueryTranslatorTestCase { public void testGroupByFunction() { if ( getDialect() instanceof Oracle8iDialect ) return; // the new hiearchy... if ( getDialect() instanceof PostgreSQLDialect ) return; - assertTranslation( "select count(*) from Human h group by year(h.birthdate)" ); + if ( ! H2Dialect.class.isInstance( getDialect() ) ) { + // H2 has no year function + assertTranslation( "select count(*) from Human h group by year(h.birthdate)" ); + assertTranslation( "select count(*) from Human h group by year(sysdate)" ); + } assertTranslation( "select count(*) from Human h group by trunc( sqrt(h.bodyWeight*4)/2 )" ); - assertTranslation( "select count(*) from Human h group by year(sysdate)" ); } diff --git a/testsuite/src/test/java/org/hibernate/test/hql/ScrollableCollectionFetchingTest.java b/testsuite/src/test/java/org/hibernate/test/hql/ScrollableCollectionFetchingTest.java index 28a2e4c1d4..2f21839cf0 100644 --- a/testsuite/src/test/java/org/hibernate/test/hql/ScrollableCollectionFetchingTest.java +++ b/testsuite/src/test/java/org/hibernate/test/hql/ScrollableCollectionFetchingTest.java @@ -53,16 +53,14 @@ public class ScrollableCollectionFetchingTest extends FunctionalTestCase { Session s = openSession(); Transaction txn = s.beginTransaction(); - assertTrue(s - .createQuery( "from Animal a left join fetch a.offspring where a.description like :desc order by a.id" ) - .setString( "desc", "root%" ) - .list() - .isEmpty() ); + final String query = "from Animal a left join fetch a.offspring where a.description like :desc order by a.id"; - ScrollableResults results = s - .createQuery( "from Animal a left join fetch a.offspring where a.description like :desc order by a.id" ) - .setString( "desc", "root%" ) - .scroll(); + // first, as a control, make sure there are no results + int size = s.createQuery( query ).setString( "desc", "root%" ).list().size(); + assertEquals( 0, size ); + + // now get the scrollable results + ScrollableResults results = s.createQuery( query ).setString( "desc", "root%" ).scroll(); assertFalse( results.isFirst() ); assertFalse( results.isLast() );