hqltest.java

来自「好东西,hibernate-3.2.0,他是一开元的树杖hibernate-3.」· Java 代码 · 共 1,284 行 · 第 1/4 页

JAVA
1,284
字号
//$Id: HQLTest.java 10060 2006-06-28 02:53:39Z steve.ebersole@jboss.com $
package org.hibernate.test.hql;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.hibernate.classic.Session;
import org.hibernate.criterion.Projections;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.Oracle9Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.hql.ast.DetailedSemanticException;
import org.hibernate.hql.ast.QuerySyntaxException;
import org.hibernate.hql.ast.ASTQueryTranslatorFactory;
import org.hibernate.hql.ast.QueryTranslatorImpl;
import org.hibernate.hql.ast.tree.ConstructorNode;
import org.hibernate.hql.ast.tree.DotNode;
import org.hibernate.hql.ast.tree.IndexNode;
import org.hibernate.hql.ast.tree.SelectClause;
import org.hibernate.hql.QueryTranslatorFactory;
import org.hibernate.hql.QueryTranslator;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.query.HQLQueryPlan;
import org.hibernate.engine.query.ReturnMetadata;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;

import antlr.RecognitionException;

/**
 * Tests cases where the AST based query translator and the 'classic' query translator generate identical SQL.
 *
 * @author Gavin King
 */
public class HQLTest extends QueryTranslatorTestCase {

	public HQLTest(String x) {
		super( x );
		SelectClause.VERSION2_SQL = true;
	}

	protected boolean dropAfterFailure() {
		return false;
	}

	//FAILING TESTS:

	public void testManyToAnyReferences() {
		assertTranslation( "from PropertySet p where p.someSpecificProperty.id is not null" );
		assertTranslation( "from PropertySet p join p.generalProperties gp where gp.id is not null" );
	}

	public void testJoinFetchCollectionOfValues() {
		assertTranslation( "select h from Human as h join fetch h.nickNames" );
	}

	public void testCollectionJoinsInSubselect() {
		// caused by some goofiness in FromElementFactory that tries to
		// handle correlated subqueries (but fails miserably) even though this
		// is not a correlated subquery.  HHH-1248
		assertTranslation(
				"select a.id, a.description" +
				" from Animal a" +
				"       left join a.offspring" +
				" where a in (" +
				"       select a1 from Animal a1" +
				"           left join a1.offspring o" +
				"       where a1.id=1" +
		        ")"
		);
		assertTranslation(
				"select h.id, h.description" +
		        " from Human h" +
				"      left join h.friends" +
				" where h in (" +
				"      select h1" +
				"      from Human h1" +
				"          left join h1.friends f" +
				"      where h1.id=1" +
				")"
		);
	}

	public void testEmptyInListFailureExpected() {
		assertTranslation( "select a from Animal a where a.description in ()" );
	}

	public void testDateTimeArithmeticReturnTypesAndParameterGuessing() {
		QueryTranslatorImpl translator = createNewQueryTranslator( "select o.orderDate - o.orderDate from Order o" );
		assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
		assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
		translator = createNewQueryTranslator( "select o.orderDate + 2 from Order o" );
		assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
		assertEquals( "incorrect return type", Hibernate.CALENDAR_DATE, translator.getReturnTypes()[0] );
		translator = createNewQueryTranslator( "select o.orderDate -2 from Order o" );
		assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
		assertEquals( "incorrect return type", Hibernate.CALENDAR_DATE, translator.getReturnTypes()[0] );

		translator = createNewQueryTranslator( "from Order o where o.orderDate > ?" );
		assertEquals( "incorrect expected param type", Hibernate.CALENDAR_DATE, translator.getParameterTranslations().getOrdinalParameterExpectedType( 1 ) );

		translator = createNewQueryTranslator( "select o.orderDate + ? from Order o" );
		assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
		assertEquals( "incorrect return type", Hibernate.CALENDAR_DATE, translator.getReturnTypes()[0] );
		assertEquals( "incorrect expected param type", Hibernate.DOUBLE, translator.getParameterTranslations().getOrdinalParameterExpectedType( 1 ) );

	}

	public void testReturnMetadata() {
		HQLQueryPlan plan = createQueryPlan( "from Animal a" );
		check( plan.getReturnMetadata(), false, true );

		plan = createQueryPlan( "select a as animal from Animal a" );
		check( plan.getReturnMetadata(), false, false );

		plan = createQueryPlan( "from java.lang.Object" );
		check( plan.getReturnMetadata(), true, true );

		plan = createQueryPlan( "select o as entity from java.lang.Object o" );
		check( plan.getReturnMetadata(), true, false );
	}

	private void check(
			ReturnMetadata returnMetadata,
	        boolean expectingEmptyTypes,
	        boolean expectingEmptyAliases) {
		assertNotNull( "null return metadata", returnMetadata );
		assertNotNull( "null return metadata - types", returnMetadata );
		assertEquals( "unexpected return size", 1, returnMetadata.getReturnTypes().length );
		if ( expectingEmptyTypes ) {
			assertNull( "non-empty types", returnMetadata.getReturnTypes()[0] );
		}
		else {
			assertNotNull( "empty types", returnMetadata.getReturnTypes()[0] );
		}
		if ( expectingEmptyAliases ) {
			assertNull( "non-empty aliases", returnMetadata.getReturnAliases() );
		}
		else {
			assertNotNull( "empty aliases", returnMetadata.getReturnAliases() );
			assertNotNull( "empty aliases", returnMetadata.getReturnAliases()[0] );
		}
	}

	public void testImplicitJoinsAlongWithCartesianProduct() {
		DotNode.useThetaStyleImplicitJoins = true;
		assertTranslation( "select foo.foo from Foo foo, Foo foo2" );
		assertTranslation( "select foo.foo.foo from Foo foo, Foo foo2" );
		DotNode.useThetaStyleImplicitJoins = false;
	}

	public void testSubselectBetween() {
		assertTranslation("from Animal x where (select max(a.bodyWeight) from Animal a) between :min and :max");
		assertTranslation("from Animal x where (select max(a.description) from Animal a) like 'big%'");
		assertTranslation("from Animal x where (select max(a.bodyWeight) from Animal a) is not null");
		assertTranslation("from Animal x where exists (select max(a.bodyWeight) from Animal a)");
		assertTranslation("from Animal x where (select max(a.bodyWeight) from Animal a) in (1,2,3)");
	}
	
	public void testFetchOrderBy() {
		assertTranslation("from Animal a left outer join fetch a.offspring where a.mother.id = :mid order by a.description");
	}

	public void testCollectionOrderBy() {
		assertTranslation("from Animal a join a.offspring o order by a.description");
		assertTranslation("from Animal a join fetch a.offspring order by a.description");
		assertTranslation("from Animal a join fetch a.offspring o order by o.description");
		assertTranslation("from Animal a join a.offspring o order by a.description, o.description");
	}
	
	public void testExpressionWithParamInFunction() {
		assertTranslation("from Animal a where abs(a.bodyWeight-:param) < 2.0");
		assertTranslation("from Animal a where abs(:param - a.bodyWeight) < 2.0");
		assertTranslation("from Animal where abs(:x - :y) < 2.0");
		assertTranslation("from Animal where lower(upper(:foo)) like 'f%'");
		assertTranslation("from Animal a where abs(abs(a.bodyWeight - 1.0 + :param) * abs(length('ffobar')-3)) = 3.0");
		if ( getDialect() instanceof MySQLDialect ) return;
		assertTranslation("from Animal where lower(upper('foo') || upper(:bar)) like 'f%'");
		if ( getDialect() instanceof PostgreSQLDialect ) return;
		assertTranslation("from Animal where abs(cast(1 as float) - cast(:param as float)) = 1.0");
	}
	
	public void testCompositeKeysWithPropertyNamedId() {
		assertTranslation( "select e.id.id from EntityWithCrazyCompositeKey e" );
		assertTranslation( "select max(e.id.id) from EntityWithCrazyCompositeKey e" );
	}

	public void testMaxindexHqlFunctionInElementAccessorFailureExpected() {
		//TODO: broken SQL
		//      steve (2005.10.06) - this is perfect SQL, but fairly different from the old parser
		//              tested : HSQLDB (1.8), Oracle8i
		assertTranslation( "select c from ContainerX c where c.manyToMany[ maxindex(c.manyToMany) ].count = 2" );
		assertTranslation( "select c from Container c where c.manyToMany[ maxIndex(c.manyToMany) ].count = 2" );
	}

	public void testMultipleElementAccessorOperatorsFailureExpected() throws Exception {
		//TODO: broken SQL
		//      steve (2005.10.06) - Yes, this is all hosed ;)
		assertTranslation( "select c from ContainerX c where c.oneToMany[ c.manyToMany[0].count ].name = 's'" );
		assertTranslation( "select c from ContainerX c where c.manyToMany[ c.oneToMany[0].count ].name = 's'" );
	}

	/*public void testSelectMaxElements() throws Exception {
		//TODO: this is almost correct, but missing a select-clause column alias!
		assertTranslation("select max( elements(one.manies) ) from org.hibernate.test.legacy.One one");
	}*/

	public void testKeyManyToOneJoinFailureExpected() {
		//TODO: new parser generates unnecessary joins (though the query results are correct)
		assertTranslation( "from Order o left join fetch o.lineItems li left join fetch li.product p" );
		assertTranslation( "from Outer o where o.id.master.id.sup.dudu is not null" );
		assertTranslation( "from Outer o where o.id.master.id.sup.dudu is not null" );
	}

	public void testDuplicateExplicitJoinFailureExpected() throws Exception {
		//very minor issue with select clause:
		assertTranslation( "from Animal a join a.mother m1 join a.mother m2" );
		assertTranslation( "from Zoo zoo join zoo.animals an join zoo.mammals m" );
		assertTranslation( "from Zoo zoo join zoo.mammals an join zoo.mammals m" );
	}

	// TESTS THAT FAIL ONLY ON DIALECTS WITH THETA-STYLE OUTERJOINS:

	public void testIndexWithExplicitJoin() throws Exception {
		//TODO: broken on dialects with theta-style outerjoins:
		//      steve (2005.10.06) - this works perfectly for me on Oracle8i
		assertTranslation( "from Zoo zoo join zoo.animals an where zoo.mammals[ index(an) ] = an" );
		assertTranslation( "from Zoo zoo join zoo.mammals dog where zoo.mammals[ index(dog) ] = dog" );
		assertTranslation( "from Zoo zoo join zoo.mammals dog where dog = zoo.mammals[ index(dog) ]" );
	}

	public void testOneToManyMapIndex() throws Exception {
		//TODO: this breaks on dialects with theta-style outerjoins:
		//      steve (2005.10.06) - this works perfectly for me on Oracle8i
		assertTranslation( "from Zoo zoo where zoo.mammals['dog'].description like '%black%'" );
		assertTranslation( "from Zoo zoo where zoo.mammals['dog'].father.description like '%black%'" );
		assertTranslation( "from Zoo zoo where zoo.mammals['dog'].father.id = 1234" );
		assertTranslation( "from Zoo zoo where zoo.animals['1234'].description like '%black%'" );
	}

	public void testExplicitJoinMapIndex() throws Exception {
		//TODO: this breaks on dialects with theta-style outerjoins:
		//      steve (2005.10.06) - this works perfectly for me on Oracle8i
		assertTranslation( "from Zoo zoo, Dog dog where zoo.mammals['dog'] = dog" );
		assertTranslation( "from Zoo zoo join zoo.mammals dog where zoo.mammals['dog'] = dog" );
	}

	public void testIndexFunction() throws Exception {
		// Instead of doing the pre-processor trick like the existing QueryTranslator, this
		// is handled by MethodNode.
		//      steve (2005.10.06) - this works perfectly for me on Oracle8i
		//TODO: broken on dialects with theta-style outerjoins:
		assertTranslation( "from Zoo zoo join zoo.mammals dog where index(dog) = 'dog'" );
		assertTranslation( "from Zoo zoo join zoo.animals an where index(an) = '1234'" );
	}

	public void testSelectCollectionOfValues() throws Exception {
		//TODO: broken on dialects with theta-style joins
		///old parser had a bug where the collection element was not included in return types!
		//      steve (2005.10.06) - this works perfectly for me on Oracle8i
		assertTranslation( "select baz, date from Baz baz join baz.stringDateMap date where index(date) = 'foo'" );
	}

	public void testCollectionOfValues() throws Exception {
		//old parser had a bug where the collection element was not returned!
		//TODO: broken on dialects with theta-style joins
		//      steve (2005.10.06) - this works perfectly for me on Oracle8i
		assertTranslation( "from Baz baz join baz.stringDateMap date where index(date) = 'foo'" );
	}

    public void testHHH719() throws Exception {
        assertTranslation("from Baz b order by org.bazco.SpecialFunction(b.id)");
        assertTranslation("from Baz b order by anypackage.anyFunction(b.id)");
    }


	//PASSING TESTS:

	public void testParameterListExpansion() {
		assertTranslation( "from Animal as animal where animal.id in (:idList_1, :idList_2)" );
	}

	public void testComponentManyToOneDereferenceShortcut() {
		assertTranslation( "from Zoo z where z.address.stateProvince.id is null" );
	}

	public void testNestedCollectionImplicitJoins() {
		// HHH-770
		assertTranslation( "select h.friends.offspring from Human h" );
	}

	public void testExplicitJoinsInSubquery() {
		// test for HHH-557,
		// TODO : this passes regardless because the only difference between the two sqls is one extra comma
		// (commas are eaten by the tokenizer during asserTranslation when building the token maps).
		assertTranslation(
		        "from org.hibernate.test.hql.Animal as animal " +
		        "where animal.id in (" +
		        "        select a.id " +
		        "        from org.hibernate.test.hql.Animal as a " +
		        "               left join a.mother as mo" +
		        ")"
		);
	}

	public void testImplicitJoinsInGroupBy() {
		assertTranslation(
		        "select o.mother.bodyWeight, count(distinct o) " +
		        "from Animal an " +
		        "   join an.offspring as o " +
		        "group by o.mother.bodyWeight" 
		);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?