[hibernate-commits] Hibernate SVN: r19109 - in core/trunk: core/src/main/java/org/hibernate/criterion and 6 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Mar 24 14:24:40 EDT 2010


Author: stliu
Date: 2010-03-24 14:24:39 -0400 (Wed, 24 Mar 2010)
New Revision: 19109

Modified:
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java
   core/trunk/core/src/main/java/org/hibernate/criterion/InExpression.java
   core/trunk/core/src/main/java/org/hibernate/dialect/Oracle9iDialect.java
   core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/BinaryLogicOperatorNode.java
   core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/InLogicOperatorNode.java
   core/trunk/testing/src/main/java/org/hibernate/junit/functional/FunctionalTestCase.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/hql/HQLTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/unionsubclass2/UnionSubclassTest.java
Log:
HHH-4907  Support for tuple syntax in HQL/Criteria on databases which do not support tuple syntax

Modified: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java	2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java	2010-03-24 18:24:39 UTC (rev 19109)
@@ -11,6 +11,7 @@
 import org.hibernate.Criteria;
 import org.hibernate.criterion.Disjunction;
 import org.hibernate.criterion.Restrictions;
+import org.hibernate.junit.FailureExpected;
 import org.hibernate.junit.SkipForDialect;
 import org.hibernate.test.annotations.TestCase;
 
@@ -253,46 +254,12 @@
 		s.close();
 	}
 
-	@SkipForDialect(value=org.hibernate.dialect.HSQLDialect.class,
-			comment = "HSQLDB does not support ((..., ...),(..., ...))")
 	public void testQueryInAndComposite() {
 
 		Session s = openSession(  );
 		Transaction transaction = s.beginTransaction();
-
-		SomeEntity someEntity = new SomeEntity();
-		someEntity.setId( new SomeEntityId( ) );
-		someEntity.getId().setId( 1 );
-		someEntity.getId().setVersion( 11 );
-		someEntity.setProp( "aa" );
-		s.persist( someEntity );
-		someEntity = new SomeEntity();
-		someEntity.setId( new SomeEntityId( ) );
-		someEntity.getId().setId( 1 );
-		someEntity.getId().setVersion( 12 );
-		someEntity.setProp( "bb" );
-		s.persist( someEntity );
-		someEntity = new SomeEntity();
-		someEntity.setId( new SomeEntityId( ) );
-		someEntity.getId().setId( 10 );
-		someEntity.getId().setVersion( 21 );
-		someEntity.setProp( "cc1" );
-		s.persist( someEntity );
-		someEntity = new SomeEntity();
-		someEntity.setId( new SomeEntityId( ) );
-		someEntity.getId().setId( 10 );
-		someEntity.getId().setVersion( 22 );
-		someEntity.setProp( "cc2" );
-		s.persist( someEntity );
-		someEntity = new SomeEntity();
-		someEntity.setId( new SomeEntityId( ) );
-		someEntity.getId().setId( 10 );
-		someEntity.getId().setVersion( 23 );
-		someEntity.setProp( "cc3" );
-		s.persist( someEntity );
-
-		s.flush();
-
+		createData( s );
+        s.flush();
         List ids = new ArrayList<SomeEntityId>(2);
         ids.add( new SomeEntityId(1,12) );
         ids.add( new SomeEntityId(10,23) );
@@ -308,7 +275,60 @@
 		transaction.rollback();
 		s.close();
 	}
+    public void testQueryInAndCompositeWithHQL() {
+        Session s = openSession(  );
+        Transaction transaction = s.beginTransaction();
+        createData( s );
+        s.flush();
+        List ids = new ArrayList<SomeEntityId>(2);
+        ids.add( new SomeEntityId(1,12) );
+        ids.add( new SomeEntityId(10,23) );
+        ids.add( new SomeEntityId(10,22) );
+        Query query=s.createQuery( "from SomeEntity e where e.id in (:idList)" );
+        query.setParameterList( "idList", ids );
+        List list=query.list();
+        assertEquals( 3, list.size() );
+        transaction.rollback();
+        s.close();
+    }
 
+
+	private void createData(Session s){
+        SomeEntity someEntity = new SomeEntity();
+        someEntity.setId( new SomeEntityId( ) );
+        someEntity.getId().setId( 1 );
+        someEntity.getId().setVersion( 11 );
+        someEntity.setProp( "aa" );
+        s.persist( someEntity );
+        
+        someEntity = new SomeEntity();
+        someEntity.setId( new SomeEntityId( ) );
+        someEntity.getId().setId( 1 );
+        someEntity.getId().setVersion( 12 );
+        someEntity.setProp( "bb" );
+        s.persist( someEntity );
+        
+        someEntity = new SomeEntity();
+        someEntity.setId( new SomeEntityId( ) );
+        someEntity.getId().setId( 10 );
+        someEntity.getId().setVersion( 21 );
+        someEntity.setProp( "cc1" );
+        s.persist( someEntity );
+        
+        someEntity = new SomeEntity();
+        someEntity.setId( new SomeEntityId( ) );
+        someEntity.getId().setId( 10 );
+        someEntity.getId().setVersion( 22 );
+        someEntity.setProp( "cc2" );
+        s.persist( someEntity );
+        
+        someEntity = new SomeEntity();
+        someEntity.setId( new SomeEntityId( ) );
+        someEntity.getId().setId( 10 );
+        someEntity.getId().setVersion( 23 );
+        someEntity.setProp( "cc3" );
+        s.persist( someEntity );
+	}
 	protected Class[] getAnnotatedClasses() {
 		return new Class[] {
 				Parent.class,

Modified: core/trunk/core/src/main/java/org/hibernate/criterion/InExpression.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/criterion/InExpression.java	2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/core/src/main/java/org/hibernate/criterion/InExpression.java	2010-03-24 18:24:39 UTC (rev 19109)
@@ -50,19 +50,35 @@
 		this.values = values;
 	}
 
-	public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
-	throws HibernateException {
-		String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName);
-		String singleValueParam = StringHelper.repeat( "?, ", columns.length-1 )  + "?";
-		if ( columns.length>1 ) singleValueParam = '(' + singleValueParam + ')';
-		String params = values.length>0 ?
-			StringHelper.repeat( singleValueParam + ", ", values.length-1 ) + singleValueParam :
-			"";
-		String cols = StringHelper.join(", ", columns);
-		if ( columns.length>1 ) cols = '(' + cols + ')';
-		return cols + " in (" + params + ')';
-	}
+    public String toSqlString( Criteria criteria, CriteriaQuery criteriaQuery )
+            throws HibernateException {
+        String[] columns = criteriaQuery.getColumnsUsingProjection(
+                criteria, propertyName );
+        if ( criteriaQuery.getFactory().getDialect()
+                .supportsRowValueConstructorSyntaxInInList() || columns.length<=1) {
 
+            String singleValueParam = StringHelper.repeat( "?, ",
+                    columns.length - 1 )
+                    + "?";
+            if ( columns.length > 1 )
+                singleValueParam = '(' + singleValueParam + ')';
+            String params = values.length > 0 ? StringHelper.repeat(
+                    singleValueParam + ", ", values.length - 1 )
+                    + singleValueParam : "";
+            String cols = StringHelper.join( ", ", columns );
+            if ( columns.length > 1 )
+                cols = '(' + cols + ')';
+            return cols + " in (" + params + ')';
+        } else {
+           String cols = " ( " + StringHelper.join( " = ? and ", columns ) + "= ? ) ";
+             cols = values.length > 0 ? StringHelper.repeat( cols
+                    + "or ", values.length - 1 )
+                    + cols : "";
+            cols = " ( " + cols + " ) ";
+            return cols;
+        }
+    }
+
 	public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) 
 	throws HibernateException {
 		ArrayList list = new ArrayList();

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/Oracle9iDialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/Oracle9iDialect.java	2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/Oracle9iDialect.java	2010-03-24 18:24:39 UTC (rev 19109)
@@ -127,5 +127,12 @@
 	public String getReadLockString(int timeout) {
 		return getWriteLockString( timeout );
 	}
+	/**
+	 * HHH-4907, I don't know if oracle 8 supports this syntax, so I'd think it is better add this 
+	 * method here. Reopen this issue if you found/know 8 supports it.
+	 */
+    public boolean supportsRowValueConstructorSyntaxInInList() {
+        return true;
+    }
 	
 }

Modified: core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/BinaryLogicOperatorNode.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/BinaryLogicOperatorNode.java	2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/BinaryLogicOperatorNode.java	2010-03-24 18:24:39 UTC (rev 19109)
@@ -75,7 +75,7 @@
 	}
 
 	protected final void mutateRowValueConstructorSyntaxesIfNecessary(Type lhsType, Type rhsType) {
-		// TODO : this really needs to be delayed unitl after we definitively know all node types
+		// TODO : this really needs to be delayed until after we definitively know all node types
 		// where this is currently a problem is parameters for which where we cannot unequivocally
 		// resolve an expected type
 		SessionFactoryImplementor sessionFactory = getSessionFactoryHelper().getFactory();
@@ -109,7 +109,7 @@
 	 * @param valueElements The number of elements in the row value constructor list.
 	 */
 	private void mutateRowValueConstructorSyntax(int valueElements) {
-		// mutation depends on the types of nodes invloved...
+		// mutation depends on the types of nodes involved...
 		int comparisonType = getType();
 		String comparisonText = getText();
 		setType( HqlSqlTokenTypes.AND );
@@ -127,8 +127,21 @@
 						? null
 						: ( ( ParameterNode ) getRightHandOperand() ).getHqlParameterSpecification();
 
-		AST container = this;
-		for ( int i = valueElements - 1; i > 0; i-- ) {
+		translate( valueElements, comparisonType, comparisonText,
+                lhsElementTexts, rhsElementTexts,
+                lhsEmbeddedCompositeParameterSpecification,
+                rhsEmbeddedCompositeParameterSpecification, this );
+	}
+	/**
+	 * 
+	 */
+    protected void translate( int valueElements, int comparisonType,
+            String comparisonText, String[] lhsElementTexts,
+            String[] rhsElementTexts,
+            ParameterSpecification lhsEmbeddedCompositeParameterSpecification,
+            ParameterSpecification rhsEmbeddedCompositeParameterSpecification,
+            AST container ) {
+        for ( int i = valueElements - 1; i > 0; i-- ) {
 			if ( i == 1 ) {
 				AST op1 = getASTFactory().create( comparisonType, comparisonText );
 				AST lhs1 = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, lhsElementTexts[0] );
@@ -165,9 +178,9 @@
 				container = newContainer;
 			}
 		}
-	}
+    }
 
-	private static String[] extractMutationTexts(Node operand, int count) {
+	protected static String[] extractMutationTexts(Node operand, int count) {
 		if ( operand instanceof ParameterNode ) {
 			String[] rtn = new String[count];
 			for ( int i = 0; i < count; i++ ) {

Modified: core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/InLogicOperatorNode.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/InLogicOperatorNode.java	2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/InLogicOperatorNode.java	2010-03-24 18:24:39 UTC (rev 19109)
@@ -24,8 +24,16 @@
  */
 package org.hibernate.hql.ast.tree;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import antlr.SemanticException;
 import antlr.collections.AST;
+
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.hql.antlr.HqlSqlTokenTypes;
+import org.hibernate.hql.antlr.HqlTokenTypes;
+import org.hibernate.param.ParameterSpecification;
 import org.hibernate.type.Type;
 
 /**
@@ -60,5 +68,109 @@
 				inListChild = inListChild.getNextSibling();
 			}
 		}
+		SessionFactoryImplementor sessionFactory = getSessionFactoryHelper().getFactory();
+		if ( sessionFactory.getDialect().supportsRowValueConstructorSyntaxInInList() )
+			return;
+        
+        Type lhsType = extractDataType( lhs );
+        if ( lhsType == null )
+            return;
+        int lhsColumnSpan = lhsType.getColumnSpan( sessionFactory );
+        Node rhsNode = (Node) inList.getFirstChild();
+        if ( !isNodeAcceptable( rhsNode ) )
+            return;
+        int rhsColumnSpan = 0;
+        if ( rhsNode.getType() == HqlTokenTypes.VECTOR_EXPR ) {
+            rhsColumnSpan = rhsNode.getNumberOfChildren();
+        } else {
+            Type rhsType = extractDataType( rhsNode );
+            if ( rhsType == null )
+                return;
+            rhsColumnSpan = rhsType.getColumnSpan( sessionFactory );
+        }
+		if ( lhsColumnSpan > 1 && rhsColumnSpan > 1 ) {
+			mutateRowValueConstructorSyntaxInInListSyntax( lhsColumnSpan, rhsColumnSpan );
+		}
 	}
+	
+	/**
+	 * this is possible for parameter lists and explicit lists. It is completely unreasonable for sub-queries.
+	 */
+    private boolean isNodeAcceptable( Node rhsNode ) {
+        return rhsNode instanceof LiteralNode
+                || rhsNode instanceof ParameterNode
+                || rhsNode.getType() == HqlTokenTypes.VECTOR_EXPR;
+    }
+    /**
+     * Mutate the subtree relating to a row-value-constructor in "in" list to instead use
+     * a series of ORen and ANDed predicates.  This allows multi-column type comparisons
+     * and explicit row-value-constructor in "in" list syntax even on databases which do
+     * not support row-value-constructor in "in" list.
+     * <p/>
+     * For example, here we'd mutate "... where (col1, col2) in ( ('val1', 'val2'), ('val3', 'val4') ) ..." to
+     * "... where (col1 = 'val1' and col2 = 'val2') or (col1 = 'val3' and val2 = 'val4') ..."
+     *
+     * @param lhsColumnSpan The number of elements in the row value constructor list.
+     */
+    private void mutateRowValueConstructorSyntaxInInListSyntax(
+            int lhsColumnSpan, int rhsColumnSpan ) {
+        String[] lhsElementTexts = extractMutationTexts( getLeftHandOperand(),
+                lhsColumnSpan );
+        Node rhsNode = (Node) getInList().getFirstChild();
+
+        ParameterSpecification lhsEmbeddedCompositeParameterSpecification = getLeftHandOperand() == null
+                || ( !ParameterNode.class.isInstance( getLeftHandOperand() ) ) ? null
+                : ( (ParameterNode) getLeftHandOperand() )
+                        .getHqlParameterSpecification();
+        /**
+         * only one element in "in" cluster, e.g.
+         * <code> where (a,b) in ( (1,2) ) </code> this will be mutated to
+         * <code>where a=1 and b=2 </code>
+         */
+        if ( rhsNode != null && rhsNode.getNextSibling() == null ) {
+            String[] rhsElementTexts = extractMutationTexts( rhsNode,
+                    rhsColumnSpan );
+            setType( HqlSqlTokenTypes.AND );
+            setText( "AND" );
+            ParameterSpecification rhsEmbeddedCompositeParameterSpecification = rhsNode == null
+                    || ( !ParameterNode.class.isInstance( rhsNode ) ) ? null
+                    : ( (ParameterNode) rhsNode )
+                            .getHqlParameterSpecification();
+            translate( lhsColumnSpan, HqlSqlTokenTypes.EQ, "=", lhsElementTexts,
+                    rhsElementTexts,
+                    lhsEmbeddedCompositeParameterSpecification,
+                    rhsEmbeddedCompositeParameterSpecification, this );
+        } else {
+            List andElementsNodeList = new ArrayList();
+            while ( rhsNode != null ) {
+                String[] rhsElementTexts = extractMutationTexts( rhsNode,
+                        rhsColumnSpan );
+                AST and = getASTFactory().create( HqlSqlTokenTypes.AND, "AND" );
+                ParameterSpecification rhsEmbeddedCompositeParameterSpecification = rhsNode == null
+                        || ( !ParameterNode.class.isInstance( rhsNode ) ) ? null
+                        : ( (ParameterNode) rhsNode )
+                                .getHqlParameterSpecification();
+                translate( lhsColumnSpan, HqlSqlTokenTypes.EQ, "=",
+                        lhsElementTexts, rhsElementTexts,
+                        lhsEmbeddedCompositeParameterSpecification,
+                        rhsEmbeddedCompositeParameterSpecification, and );
+                andElementsNodeList.add( and );
+                rhsNode = (Node) rhsNode.getNextSibling();
+            }
+            setType( HqlSqlTokenTypes.OR );
+            setText( "OR" );
+            AST curNode = this;
+            for ( int i = andElementsNodeList.size() - 1; i > 1; i-- ) {
+                AST or = getASTFactory().create( HqlSqlTokenTypes.OR, "OR" );
+                curNode.setFirstChild( or );
+                curNode = or;
+                AST and = (AST) andElementsNodeList.get( i );
+                or.setNextSibling( and );
+            }
+            AST node0 = (AST) andElementsNodeList.get( 0 );
+            AST node1 = (AST) andElementsNodeList.get( 1 );
+            node0.setNextSibling( node1 );
+            curNode.setFirstChild( node0 );
+        }
+    }
 }

Modified: core/trunk/testing/src/main/java/org/hibernate/junit/functional/FunctionalTestCase.java
===================================================================
--- core/trunk/testing/src/main/java/org/hibernate/junit/functional/FunctionalTestCase.java	2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/testing/src/main/java/org/hibernate/junit/functional/FunctionalTestCase.java	2010-03-24 18:24:39 UTC (rev 19109)
@@ -432,14 +432,6 @@
 		return false;
 	}
 
-	protected boolean supportsRowValueConstructorSyntaxInInList() {
-		if ( ! getDialect().supportsRowValueConstructorSyntaxInInList() ) {
-			reportSkip( "Dialect does not support 'tuple' syntax as part of an IN value list", "query support" );
-			return false;
-		}
-		return true;
-	}
-
 	protected boolean supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() {
 		if ( ! getDialect().supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() ) {
 			reportSkip( "Driver does not support 'position query' methods on forward-only cursors", "query support" );

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java	2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java	2010-03-24 18:24:39 UTC (rev 19109)
@@ -48,6 +48,7 @@
 import org.hibernate.test.cid.LineItem;
 import org.hibernate.test.cid.Order;
 import org.hibernate.test.cid.Product;
+import org.hibernate.test.cid.LineItem.Id;
 import org.hibernate.transform.DistinctRootEntityResultTransformer;
 import org.hibernate.transform.Transformers;
 import org.hibernate.type.ComponentType;
@@ -467,6 +468,48 @@
 		s.close();
 	}
 
+	public void testRowValueConstructorSyntaxInInList() {
+		Session s = openSession();
+		s.beginTransaction();
+		Product product = new Product();
+		product.setDescription( "My Product" );
+		product.setNumberAvailable( 10 );
+		product.setPrice( new BigDecimal( 123 ) );
+		product.setProductId( "4321" );
+		s.save( product );
+		
+
+		Customer customer = new Customer();
+		customer.setCustomerId( "123456789" );
+		customer.setName( "My customer" );
+		customer.setAddress( "somewhere" );
+		s.save( customer );
+
+		Order order = customer.generateNewOrder( new BigDecimal( 1234 ) );
+		s.save( order );
+
+		LineItem li = order.generateLineItem( product, 5 );
+		s.save( li );
+		product = new Product();
+		product.setDescription( "My Product" );
+		product.setNumberAvailable( 10 );
+		product.setPrice( new BigDecimal( 123 ) );
+		product.setProductId( "1234" );
+		s.save( product );
+		li = order.generateLineItem( product, 10 );
+		s.save( li );
+
+		s.flush();
+		Query query = s.createQuery( "from LineItem l where l.id in (:idList)" );
+		List list = new ArrayList();
+		list.add( new Id("123456789", order.getId().getOrderNumber(), "4321") );
+		list.add( new Id("123456789", order.getId().getOrderNumber(), "1234") );
+		query.setParameterList( "idList", list );
+		assertEquals( 2, query.list().size() );
+		s.getTransaction().commit();
+		s.close();
+		
+	}
 	private void checkCounts(String hql, int expected, String testCondition) {
 		Session s = openSession();
 		s.beginTransaction();

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/hql/HQLTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/hql/HQLTest.java	2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/hql/HQLTest.java	2010-03-24 18:24:39 UTC (rev 19109)
@@ -9,7 +9,6 @@
 import java.util.List;
 import java.util.Map;
 
-import antlr.RecognitionException;
 import junit.framework.Test;
 
 import org.hibernate.Hibernate;
@@ -30,6 +29,7 @@
 import org.hibernate.engine.query.ReturnMetadata;
 import org.hibernate.hql.QueryTranslator;
 import org.hibernate.hql.QueryTranslatorFactory;
+import org.hibernate.hql.antlr.HqlTokenTypes;
 import org.hibernate.hql.ast.ASTQueryTranslatorFactory;
 import org.hibernate.hql.ast.DetailedSemanticException;
 import org.hibernate.hql.ast.QuerySyntaxException;
@@ -39,9 +39,14 @@
 import org.hibernate.hql.ast.tree.DotNode;
 import org.hibernate.hql.ast.tree.FromReferenceNode;
 import org.hibernate.hql.ast.tree.IndexNode;
+import org.hibernate.hql.ast.tree.QueryNode;
 import org.hibernate.hql.ast.tree.SelectClause;
+import org.hibernate.hql.ast.util.ASTUtil;
 import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
 
+import antlr.RecognitionException;
+import antlr.collections.AST;
+
 /**
  * Tests cases where the AST based query translator and the 'classic' query translator generate identical SQL.
  *
@@ -94,7 +99,35 @@
 		assertTranslation( "from Animal a where a.offspring.description = 'xyz'" );
 		assertTranslation( "from Animal a where a.offspring.father.description = 'xyz'" );
 	}
+	
+    /**
+     * ClassicQueryTranslatorFactory does not support translate tuple with "in" syntax to "and/or" clause
+     */
+    public void testRowValueConstructorSyntaxInInListFailureExpected() {
+        assertTranslation( "from LineItem l where l.id in (:idList)" );
+    }
 
+    public void testRowValueConstructorSyntaxInInList() {
+    	if (!getDialect().supportsRowValueConstructorSyntaxInInList())
+    		return;
+		QueryTranslatorImpl translator = createNewQueryTranslator("from LineItem l where l.id in (?)");
+		assertInExist("'in' should be translated to 'and'", false, translator);
+		translator = createNewQueryTranslator("from LineItem l where l.id in (('a1',1,'b1'),('a2',2,'b2'))");
+		assertInExist("'in' should be translated to 'and'", false, translator);
+		translator = createNewQueryTranslator("from Animal a where a.id in (?)");
+		assertInExist("only translate tuple with 'in' syntax", true, translator);
+		translator = createNewQueryTranslator("from LineItem l where l.id in (select a1 from Animal a1 left join a1.offspring o where a1.id = 1)");
+		assertInExist("do not translate subqueries", true, translator);
+
+    }
+
+	private void assertInExist( String message, boolean expected, QueryTranslatorImpl translator ) {
+		AST ast = translator.getSqlAST().getWalker().getAST();
+		QueryNode queryNode = (QueryNode) ast;
+		AST inNode = ASTUtil.findTypeInChildren( queryNode, HqlTokenTypes.IN );
+		assertEquals( message, expected, inNode != null );
+	}
+    
 	public void testSubComponentReferences() {
 		assertTranslation( "select c.address.zip.code from ComponentContainer c" );
 		assertTranslation( "select c.address.zip from ComponentContainer c" );

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassTest.java	2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassTest.java	2010-03-24 18:24:39 UTC (rev 19109)
@@ -92,15 +92,12 @@
 		joe = (Customer) s.get( Customer.class, new Long( joe.getId() ) );
 
  		mark.setZip("30306");
-		assertEquals( s.createQuery("from Person p where p.address.zip = '30306'").list().size(), 1 );
+        assertEquals( s.createQuery("from Person p where p.address.zip = '30306'" ).list().size(),1 );
 
-		if ( supportsRowValueConstructorSyntaxInInList() ) {
-			s.createCriteria(Person.class).add(
-					Restrictions.in("address", new Address[] { mark.getAddress(), joe.getAddress() } )
-			).list();
-		}
+        s.createCriteria( Person.class ).add(
+                Restrictions.in( "address", new Address[] { mark.getAddress(), joe.getAddress() } ) ).list();
 
-		s.delete(mark);
+        s.delete(mark);
 		s.delete(joe);
 		s.delete(yomomma);
 		assertTrue( s.createQuery("from Person").list().isEmpty() );

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/unionsubclass2/UnionSubclassTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/unionsubclass2/UnionSubclassTest.java	2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/unionsubclass2/UnionSubclassTest.java	2010-03-24 18:24:39 UTC (rev 19109)
@@ -94,11 +94,9 @@
  		mark.setZip("30306");
 		assertEquals( s.createQuery("from Person p where p.address.zip = '30306'").list().size(), 1 );
 
-		if ( supportsRowValueConstructorSyntaxInInList() ) {
-			s.createCriteria(Person.class).add( 
-					Restrictions.in("address", new Address[] { mark.getAddress(), joe.getAddress() } ) 
-			).list();
-		}
+        s.createCriteria( Person.class ).add(
+                Restrictions.in( "address", new Address[] { mark.getAddress(),
+                        joe.getAddress() } ) ).list();
 		
 		s.delete(mark);
 		s.delete(joe);



More information about the hibernate-commits mailing list