[hibernate-commits] Hibernate SVN: r10929 - in branches/Branch_3_2/Hibernate3: src/org/hibernate/hql/ast/tree test/org/hibernate/test/hql

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Dec 5 14:04:54 EST 2006


Author: steve.ebersole at jboss.com
Date: 2006-12-05 14:04:53 -0500 (Tue, 05 Dec 2006)
New Revision: 10929

Modified:
   branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/QueryTranslatorTestCase.java
Log:
HHH-2257 : implicit joins and shallow queries

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java	2006-12-05 19:00:32 UTC (rev 10928)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java	2006-12-05 19:04:53 UTC (rev 10929)
@@ -5,6 +5,7 @@
 import org.hibernate.engine.JoinSequence;
 import org.hibernate.hql.CollectionProperties;
 import org.hibernate.hql.antlr.SqlTokenTypes;
+import org.hibernate.hql.antlr.HqlSqlTokenTypes;
 import org.hibernate.hql.ast.util.ASTPrinter;
 import org.hibernate.hql.ast.util.ASTUtil;
 import org.hibernate.hql.ast.util.ColumnHelper;
@@ -286,26 +287,34 @@
 	private void dereferenceEntity(EntityType entityType, boolean implicitJoin, String classAlias, boolean generateJoin, AST parent) throws SemanticException {
 		checkForCorrelatedSubquery( "dereferenceEntity" );
 
-		// Only join to the entity table if:
-		//      1) we were instructed to generate any needed joins (generateJoins==true)
-		//    AND
-		//      2) EITHER:
-		//          A) our parent represents a further dereference of this entity to anything
-		//              other than the entity's id property
-		//        OR
-		//          B) this node is in any clause, other than the select clause (unless that
-		//              select clause is part of a scalar query :/ )
+		// two general cases we check here:
+		// 1) is our parent a DotNode as well?  If so, our property reference is
+		// 		being further de-referenced...
+		// 2) we were asked to generate any needed joins (generateJoins==true) *OR*
+		//		the current parser state indicates to use an INNER JOIN for implicit joins
+		//
+		// The "implicit join" portion of the second condition was done to account for
+		// situations like HHH-2257 to make sure that iterate() and list() return
+		// consistent results.  Previously the join would be skipped on "shallow queries"
+		// (aka, iterate()) for performance reasons, but that can lead to incorrect
+		// results since INNER JOINs do place extra restrications on the returned
+		// results.
 		DotNode parentAsDotNode = null;
 		String property = propertyName;
 		final boolean joinIsNeeded;
 
 		if ( isDotNode( parent ) ) {
+			// our parent is another dot node, meaning we are being further dereferenced.
+			// thus we need to generate a join unless the parent refers to the associated
+			// entity's PK (because 'our' table would know the FK).
 			parentAsDotNode = ( DotNode ) parent;
 			property = parentAsDotNode.propertyName;
 			joinIsNeeded = generateJoin && !isReferenceToPrimaryKey( parentAsDotNode.propertyName, entityType );
 		}
 		else {
-			joinIsNeeded = generateJoin && ( !getWalker().isInSelect() || !getWalker().isShallowQuery() );
+			// otherwise we need to generate the join if we were asked to, or
+			// if the current implicit join type is INNER JOINs
+			joinIsNeeded = generateJoin || getWalker().getImpliedJoinType() == JoinFragment.INNER_JOIN;
 		}
 
 		if ( joinIsNeeded ) {

Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java	2006-12-05 19:00:32 UTC (rev 10928)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java	2006-12-05 19:04:53 UTC (rev 10929)
@@ -76,6 +76,7 @@
 		return new String[] {
 				"hql/Animal.hbm.xml",
 				"hql/FooBarCopy.hbm.xml",
+				"hql/SimpleEntityWithAssociation.hbm.xml",
 				"batchfetch/ProductLine.hbm.xml",
 				"cid/Customer.hbm.xml",
 				"cid/Order.hbm.xml",
@@ -93,6 +94,94 @@
 		cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
 	}
 
+	public void testImplicitJoinsInDifferentClauses() {
+		// HHH-2257 :
+		// both the classic and ast translators output the same syntactically valid sql
+		// for all of these cases; the issue is that shallow (iterate) and
+		// non-shallow (list/scroll) queries return different results because the
+		// shallow skips the inner join which "weeds out" results from the non-shallow queries.
+		// The results were initially different depending upon the clause(s) in which the
+		// implicit join occurred
+		Session s = openSession();
+		s.beginTransaction();
+		SimpleEntityWithAssociation owner = new SimpleEntityWithAssociation( "owner" );
+		SimpleAssociatedEntity e1 = new SimpleAssociatedEntity( "thing one", owner );
+		SimpleAssociatedEntity e2 = new SimpleAssociatedEntity( "thing two" );
+		s.save( e1 );
+		s.save( e2 );
+		s.save( owner );
+		s.getTransaction().commit();
+		s.close();
+
+		checkCounts( "select e.owner from SimpleAssociatedEntity e", 1, "implicit-join in select clause" );
+		checkCounts( "select e.id, e.owner from SimpleAssociatedEntity e", 1, "implicit-join in select clause" );
+		checkCounts( "from SimpleAssociatedEntity e order by e.owner", 1, "implicit-join in order-by clause" );
+		checkCounts( "select e.owner.id, count(*) from SimpleAssociatedEntity e group by e.owner", 1, "implicit-join in select and group-by clauses" );
+
+	 	s = openSession();
+		s.beginTransaction();
+		s.delete( e1 );
+		s.delete( e2 );
+		s.delete( owner );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	private void checkCounts(String hql, int expected, String testCondition) {
+		Session s = openSession();
+		s.beginTransaction();
+		int count = determineCount( s.createQuery( hql ).list().iterator() );
+		assertEquals( "list() [" + testCondition + "]", expected, count );
+		count = determineCount( s.createQuery( hql ).iterate() );
+		assertEquals( "iterate() [" + testCondition + "]", expected, count );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testImplicitSelectEntityAssociationInShallowQuery() {
+		// HHH-2257 :
+		// both the classic and ast translators output the same syntactically valid sql.
+		// the issue is that shallow and non-shallow queries return different
+		// results because the shallow skips the inner join which "weeds out" results
+		// from the non-shallow queries...
+		Session s = openSession();
+		s.beginTransaction();
+		SimpleEntityWithAssociation owner = new SimpleEntityWithAssociation( "owner" );
+		SimpleAssociatedEntity e1 = new SimpleAssociatedEntity( "thing one", owner );
+		SimpleAssociatedEntity e2 = new SimpleAssociatedEntity( "thing two" );
+		s.save( e1 );
+		s.save( e2 );
+		s.save( owner );
+		s.getTransaction().commit();
+		s.close();
+
+	 	s = openSession();
+		s.beginTransaction();
+		int count = determineCount( s.createQuery( "select e.id, e.owner from SimpleAssociatedEntity e" ).list().iterator() );
+		assertEquals( 1, count ); // thing two would be removed from the result due to the inner join
+		count = determineCount( s.createQuery( "select e.id, e.owner from SimpleAssociatedEntity e" ).iterate() );
+		assertEquals( 1, count );
+		s.getTransaction().commit();
+		s.close();
+
+	 	s = openSession();
+		s.beginTransaction();
+		s.delete( e1 );
+		s.delete( e2 );
+		s.delete( owner );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	private int determineCount(Iterator iterator) {
+		int count = 0;
+		while( iterator.hasNext() ) {
+			count++;
+			iterator.next();
+		}
+		return count;
+	}
+
 	public void testNestedComponentIsNull() {
 		// (1) From MapTest originally...
 		// (2) Was then moved into HQLTest...

Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/QueryTranslatorTestCase.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/QueryTranslatorTestCase.java	2006-12-05 19:00:32 UTC (rev 10928)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/QueryTranslatorTestCase.java	2006-12-05 19:04:53 UTC (rev 10929)
@@ -498,6 +498,8 @@
 		return new String[] {
 				"hql/Animal.hbm.xml",
 				"hql/EntityWithCrazyCompositeKey.hbm.xml",
+				"hql/CrazyIdFieldNames.hbm.xml",
+				"hql/SimpleEntityWithAssociation.hbm.xml",
 				"batchfetch/ProductLine.hbm.xml",
 				"cid/Customer.hbm.xml",
 				"cid/Order.hbm.xml",
@@ -528,7 +530,6 @@
 				"legacy/UpDown.hbm.xml",
 				"compositeelement/Parent.hbm.xml",
 				"onetoone/joined/Person.hbm.xml",
-				"hql/CrazyIdFieldNames.hbm.xml",
 				"any/Properties.hbm.xml"
 		};
 	}




More information about the hibernate-commits mailing list