Author: steve.ebersole(a)jboss.com
Date: 2006-11-16 14:33:19 -0500 (Thu, 16 Nov 2006)
New Revision: 10825
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/FromElement.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/FromElementType.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util/JoinProcessor.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util/SessionFactoryHelper.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/Queryable.java
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/HQLTest.java
Log:
HHH-939 : special '.class' property reference from HQL for joined-subclass;
HHH-1631 : sub/super-classes property reference from HQL for joined-subclass
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-11-16
19:32:48 UTC (rev 10824)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java 2006-11-16
19:33:19 UTC (rev 10825)
@@ -138,6 +138,8 @@
// discover foreign key (id) properties.
lhs.resolve( true, true, null, this );
setFromElement( lhs.getFromElement() ); // The 'from element' that the
property is in.
+
+ checkSubclassOrSuperclassPropertyReference( lhs, propName );
}
public void resolveInFunctionCall(boolean generateJoin, boolean implicitJoin) throws
SemanticException {
@@ -222,7 +224,7 @@
return propertyType;
}
- private void dereferenceCollection(CollectionType collectionType, boolean implicitJoin,
boolean indexed, String classAlias, AST parent)
+ private void dereferenceCollection(CollectionType collectionType, boolean implicitJoin,
boolean indexed, String classAlias, AST parent)
throws SemanticException {
dereferenceType = DEREF_COLLECTION;
@@ -284,14 +286,6 @@
private void dereferenceEntity(EntityType entityType, boolean implicitJoin, String
classAlias, boolean generateJoin, AST parent) throws SemanticException {
checkForCorrelatedSubquery( "dereferenceEntity" );
- // If this is an entity inside a component reference, then generate the join.
-// if ( unresolvedComponent( generateJoin ) ) {
-// if ( log.isDebugEnabled() ) {
-// log.debug( "dereferenceEntity() : resolving unresolved component '" +
propertyPath + "' ... " );
-// }
-// dereferenceEntityJoin( classAlias, entityType, implicitJoin, parent );
-// return;
-// }
// Only join to the entity table if:
// 1) we were instructed to generate any needed joins (generateJoins==true)
@@ -324,19 +318,6 @@
}
- private boolean unresolvedComponent(boolean generateJoin) {
- AST c = getFirstChild();
- if ( generateJoin && isDotNode( c ) ) {
- DotNode dot = ( DotNode ) c;
- if ( dot.dereferenceType == DEREF_COMPONENT || dot.dereferenceType == DEREF_IDENTIFIER
) {
- if ( StringHelper.isNotEmpty( propertyPath ) ) {
- return true;
- }
- }
- }
- return false;
- }
-
private boolean isDotNode(AST n) {
return n != null && n.getType() == SqlTokenTypes.DOT;
}
@@ -445,26 +426,11 @@
return propertyType.isReferenceToPrimaryKey();
}
else {
- String keyPropertyName = getSessionFactoryHelper()
- .getIdentifierOrUniqueKeyPropertyName( propertyType );
- return keyPropertyName != null && keyPropertyName.equals( propertyName );
+ String keyPropertyName =
getSessionFactoryHelper().getIdentifierOrUniqueKeyPropertyName( propertyType );
+ return keyPropertyName != null && keyPropertyName.equals( propertyName )
&& propertyType.isReferenceToPrimaryKey();
}
}
-// private boolean isPrimaryKeyReference(String property, EntityType propertyType) {
-// boolean isIdShortcut = EntityPersister.ENTITY_ID.equals( property ) &&
-// propertyType.isReferenceToPrimaryKey();
-// return isIdShortcut;
-// }
-//
-// private boolean isNamedIdPropertyShortcut(EntityType propertyType, String property) {
-// final String idPropertyName = getSessionFactoryHelper()
-// .getIdentifierOrUniqueKeyPropertyName( propertyType );
-// boolean isNamedIdPropertyShortcut = idPropertyName != null &&
-// idPropertyName.equals( property );
-// return isNamedIdPropertyShortcut;
-// }
-
private void checkForCorrelatedSubquery(String methodName) {
if ( isCorrelatedSubselect() ) {
if ( log.isDebugEnabled() ) {
@@ -614,6 +580,12 @@
}
}
}
+
+ FromReferenceNode lhs = getLhs();
+ while ( lhs != null ) {
+ checkSubclassOrSuperclassPropertyReference( lhs, lhs.getNextSibling().getText() );
+ lhs = ( FromReferenceNode ) lhs.getFirstChild();
+ }
}
/**
@@ -626,4 +598,14 @@
dereferenceType = DEREF_JAVA_CONSTANT;
setResolved(); // Don't resolve the node again.
}
+
+ private boolean checkSubclassOrSuperclassPropertyReference(FromReferenceNode lhs, String
propertyName) {
+ if ( lhs != null && !( lhs instanceof IndexNode ) && lhs.getDataType()
!= null && ! lhs.getDataType().isComponentType() ) {
+ final FromElement source = lhs.getFromElement();
+ if ( source != null ) {
+ source.handlePropertyBeingDereferenced( propertyName );
+ }
+ }
+ return false;
+ }
}
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/FromElement.java
===================================================================
---
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/FromElement.java 2006-11-16
19:32:48 UTC (rev 10824)
+++
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/FromElement.java 2006-11-16
19:33:19 UTC (rev 10825)
@@ -7,6 +7,7 @@
import org.hibernate.QueryException;
import org.hibernate.engine.JoinSequence;
import org.hibernate.hql.QueryTranslator;
+import org.hibernate.hql.CollectionProperties;
import org.hibernate.hql.antlr.SqlTokenTypes;
import org.hibernate.hql.ast.util.ASTUtil;
import org.hibernate.hql.ast.HqlSqlWalker;
@@ -60,6 +61,8 @@
private boolean manyToMany = false;
private String withClauseFragment = null;
private String withClauseJoinAlias;
+ private boolean dereferencedBySuperclassProperty;
+ private boolean dereferencedBySubclassProperty;
public FromElement() {
}
@@ -258,6 +261,11 @@
}
public void setIncludeSubclasses(boolean includeSubclasses) {
+ if ( isDereferencedBySuperclassOrSubclassProperty() ) {
+ if ( !includeSubclasses && log.isTraceEnabled() ) {
+ log.trace( "attempt to disable subclass-inclusions", new Exception(
"stack-trace source" ) );
+ }
+ }
this.includeSubclasses = includeSubclasses;
}
@@ -265,6 +273,10 @@
return includeSubclasses;
}
+ public boolean isDereferencedBySuperclassOrSubclassProperty() {
+ return dereferencedBySubclassProperty || dereferencedBySuperclassProperty;
+ }
+
public String getIdentityColumn() {
checkInitialized();
String table = getTableAlias();
@@ -500,4 +512,33 @@
return getQueryable().hasCache();
}
}
+
+ public void handlePropertyBeingDereferenced(String propertyName) {
+ if ( getQueryableCollection() != null &&
CollectionProperties.isCollectionProperty( propertyName ) ) {
+ }
+ else {
+ Queryable persister = getQueryable();
+ if ( persister != null ) {
+ Queryable.Declarer propertyDeclarer = persister.getSubclassPropertyDeclarer(
propertyName );
+ if ( log.isTraceEnabled() ) {
+ log.trace( "handling property dereference [" + persister.getEntityName() +
" (" + getClassAlias() + ") -> " + propertyName + " (" +
propertyDeclarer + ")]" );
+ }
+ if ( propertyDeclarer == Queryable.Declarer.SUBCLASS ) {
+ dereferencedBySubclassProperty = true;
+ includeSubclasses = true;
+ }
+ else if ( propertyDeclarer == Queryable.Declarer.SUPERCLASS ) {
+ dereferencedBySuperclassProperty = true;
+ }
+ }
+ }
+ }
+
+ public boolean isDereferencedBySuperclassProperty() {
+ return dereferencedBySuperclassProperty;
+ }
+
+ public boolean isDereferencedBySubclassProperty() {
+ return dereferencedBySubclassProperty;
+ }
}
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/FromElementType.java
===================================================================
---
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/FromElementType.java 2006-11-16
19:32:48 UTC (rev 10824)
+++
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/FromElementType.java 2006-11-16
19:33:19 UTC (rev 10825)
@@ -38,7 +38,6 @@
private QueryableCollection queryableCollection;
private CollectionPropertyMapping collectionPropertyMapping;
private JoinSequence joinSequence;
-
private String collectionSuffix;
public FromElementType(FromElement fromElement, EntityPersister persister, EntityType
entityType) {
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util/JoinProcessor.java
===================================================================
---
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util/JoinProcessor.java 2006-11-16
19:32:48 UTC (rev 10824)
+++
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util/JoinProcessor.java 2006-11-16
19:33:19 UTC (rev 10825)
@@ -5,6 +5,7 @@
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Collections;
+import java.util.List;
import org.hibernate.AssertionFailure;
import org.hibernate.engine.JoinSequence;
@@ -13,6 +14,7 @@
import org.hibernate.hql.ast.tree.FromClause;
import org.hibernate.hql.ast.tree.FromElement;
import org.hibernate.hql.ast.tree.QueryNode;
+import org.hibernate.hql.ast.tree.DotNode;
import org.hibernate.sql.JoinFragment;
import org.hibernate.util.StringHelper;
@@ -26,7 +28,7 @@
* The join generating classes are complex, this encapsulates some of the
JoinSequence-related
* code.
*
- * @author josh Jul 22, 2004 7:33:42 AM
+ * @author Joshua Davis
*/
public class JoinProcessor implements SqlTokenTypes {
@@ -38,7 +40,7 @@
/**
* Constructs a new JoinProcessor.
*
- * @param astFactory The factory for AST node creation.
+ * @param astFactory The factory for AST node creation.
* @param queryTranslatorImpl The query translator.
*/
public JoinProcessor(ASTFactory astFactory, QueryTranslatorImpl queryTranslatorImpl) {
@@ -70,35 +72,51 @@
public void processJoins(QueryNode query, boolean inSubquery) {
final FromClause fromClause = query.getFromClause();
- // TODO : found it easiest to simply reorder the FromElements here into ascending
order
- // in terms of injecting them into the resulting sql ast in orders relative to those
- // expected by the old parser; this is definitely another of those "only needed
- // for regression purposes". The SyntheticAndFactory, then, simply injects them
as it
- // encounters them.
- ArrayList orderedFromElements = new ArrayList();
- ListIterator liter = fromClause.getFromElements().listIterator(
fromClause.getFromElements().size() );
- while ( liter.hasPrevious() ) {
- orderedFromElements.add( liter.previous() );
+ final List fromElements;
+ if ( DotNode.useThetaStyleImplicitJoins ) {
+ // for regression testing against output from the old parser...
+ // found it easiest to simply reorder the FromElements here into ascending order
+ // in terms of injecting them into the resulting sql ast in orders relative to those
+ // expected by the old parser; this is definitely another of those "only needed
+ // for regression purposes". The SyntheticAndFactory, then, simply injects them
as it
+ // encounters them.
+ fromElements = new ArrayList();
+ ListIterator liter = fromClause.getFromElements().listIterator(
fromClause.getFromElements().size() );
+ while ( liter.hasPrevious() ) {
+ fromElements.add( liter.previous() );
+ }
}
+ else {
+ fromElements = fromClause.getFromElements();
+ }
// Iterate through the alias,JoinSequence pairs and generate SQL token nodes.
- Iterator iter = orderedFromElements.iterator();
+ Iterator iter = fromElements.iterator();
while ( iter.hasNext() ) {
final FromElement fromElement = ( FromElement ) iter.next();
JoinSequence join = fromElement.getJoinSequence();
join.setSelector(
- new JoinSequence.Selector() {
- public boolean includeSubclasses(String alias) {
- boolean shallowQuery = queryTranslatorImpl.isShallowQuery();
- boolean containsTableAlias = fromClause.containsTableAlias( alias );
- boolean includeSubclasses = fromElement.isIncludeSubclasses();
- boolean subQuery = fromClause.isSubQuery();
- return includeSubclasses && containsTableAlias && !subQuery
&& !shallowQuery;
- }
- }
- );
+ new JoinSequence.Selector() {
+ public boolean includeSubclasses(String alias) {
+ // The uber-rule here is that we need to include subclass joins if
+ // the FromElement is in any way dereferenced by a property from
+ // the subclass table; otherwise we end up with column references
+ // qualified by a non-existent table reference in the resulting SQL...
+ boolean containsTableAlias = fromClause.containsTableAlias( alias );
+ if ( fromElement.isDereferencedBySubclassProperty() ) {
+ // TODO : or should we return 'containsTableAlias'??
+ log.trace( "forcing inclusion of extra joins [alias=" + alias + ",
containsTableAlias=" + containsTableAlias + "]" );
+ return true;
+ }
+ boolean shallowQuery = queryTranslatorImpl.isShallowQuery();
+ boolean includeSubclasses = fromElement.isIncludeSubclasses();
+ boolean subQuery = fromClause.isSubQuery();
+ return includeSubclasses && containsTableAlias && !subQuery
&& !shallowQuery;
+ }
+ }
+ );
addJoinNodes( query, join, fromElement, inSubquery );
- } // while
+ }
}
@@ -106,10 +124,10 @@
// Generate FROM and WHERE fragments for the from element.
JoinFragment joinFragment = join.toJoinFragment(
inSubquery ? Collections.EMPTY_MAP : queryTranslatorImpl.getEnabledFilters(),
- fromElement.useFromFragment(),
- fromElement.getWithClauseFragment(),
- fromElement.getWithClauseJoinAlias()
- );
+ fromElement.useFromFragment() ||
fromElement.isDereferencedBySuperclassOrSubclassProperty(),
+ fromElement.getWithClauseFragment(),
+ fromElement.getWithClauseJoinAlias()
+ );
String frag = joinFragment.toFromFragmentString();
String whereFrag = joinFragment.toWhereFragmentString();
@@ -126,7 +144,9 @@
// If there is a FROM fragment and the FROM element is an explicit, then add the from
part.
if ( fromElement.useFromFragment() /*&& StringHelper.isNotEmpty( frag )*/ ) {
String fromFragment = processFromFragment( frag, join );
- if ( log.isDebugEnabled() ) log.debug( "Using FROM fragment [" +
fromFragment + "]" );
+ if ( log.isDebugEnabled() ) {
+ log.debug( "Using FROM fragment [" + fromFragment + "]" );
+ }
fromElement.setText( fromFragment.trim() ); // Set the text of the fromElement.
}
andFactory.addWhereFragment( joinFragment, whereFrag, query, fromElement );
@@ -138,22 +158,6 @@
if ( fromFragment.startsWith( ", " ) ) {
fromFragment = fromFragment.substring( 2 );
}
- /*
- // *** BEGIN FROM FRAGMENT VOODOO ***
- // If there is more than one join, reverse the order of the tables in the FROM
fragment.
- if ( join.getJoinCount() > 1 && fromFragment.indexOf( ',' ) >= 0
) {
- String[] froms = StringHelper.split( ",", fromFragment );
- StringBuffer buf = new StringBuffer();
- for ( int i = froms.length - 1; i >= 0; i-- ) {
- buf.append( froms[i] );
- if ( i > 0 ) {
- buf.append( ", " );
- }
- }
- fromFragment = buf.toString();
- }
- // *** END OF FROM FRAGMENT VOODOO ***
- */
return fromFragment;
}
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util/SessionFactoryHelper.java
===================================================================
---
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util/SessionFactoryHelper.java 2006-11-16
19:32:48 UTC (rev 10824)
+++
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util/SessionFactoryHelper.java 2006-11-16
19:33:19 UTC (rev 10825)
@@ -379,12 +379,7 @@
}
}
- Type rtnType = sqlFunction.getReturnType( argumentType, sfi );
- if ( rtnType == null ) {
- throw new QueryException( "unable to determine function return type [" +
functionName + "]" );
- }
-
- return rtnType;
+ return sqlFunction.getReturnType( argumentType, sfi );
}
public String[][] generateColumnNames(Type[] sqlResultTypes) {
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
---
branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java 2006-11-16
19:32:48 UTC (rev 10824)
+++
branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java 2006-11-16
19:33:19 UTC (rev 10825)
@@ -1352,6 +1352,19 @@
return index==-1 ? 0 : getSubclassPropertyTableNumber(index);
}
+ public Declarer getSubclassPropertyDeclarer(String propertyPath) {
+ int tableIndex = getSubclassPropertyTableNumber( propertyPath );
+ if ( tableIndex == 0 ) {
+ return Declarer.CLASS;
+ }
+ else if ( isClassOrSuperclassTable( tableIndex ) ) {
+ return Declarer.SUPERCLASS;
+ }
+ else {
+ return Declarer.SUBCLASS;
+ }
+ }
+
protected String generateTableAlias(String rootAlias, int tableNumber) {
if ( tableNumber == 0 ) {
return rootAlias;
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java
===================================================================
---
branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java 2006-11-16
19:32:48 UTC (rev 10824)
+++
branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java 2006-11-16
19:33:19 UTC (rev 10825)
@@ -575,4 +575,12 @@
public String getRootTableName() {
return naturalOrderTableNames[0];
}
+
+ public Declarer getSubclassPropertyDeclarer(String propertyPath) {
+ if ( "class".equals( propertyPath ) ) {
+ // special case where we need to force incloude all subclass joins
+ return Declarer.SUBCLASS;
+ }
+ return super.getSubclassPropertyDeclarer( propertyPath );
+ }
}
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/Queryable.java
===================================================================
---
branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/Queryable.java 2006-11-16
19:32:48 UTC (rev 10824)
+++
branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/Queryable.java 2006-11-16
19:33:19 UTC (rev 10825)
@@ -102,6 +102,18 @@
public int getSubclassPropertyTableNumber(String propertyPath);
/**
+ * Determine whether the given property is declared by our
+ * mapped class, our super class, or one of our subclasses...
+ * <p/>
+ * Note: the method is called 'subclass property...' simply
+ * for consistency sake (e.g. {@link #getSubclassPropertyTableNumber}
+ *
+ * @param propertyPath The property name.
+ * @return The property declarer
+ */
+ public Declarer getSubclassPropertyDeclarer(String propertyPath);
+
+ /**
* Get the name of the table with the given index from the internal
* array.
*
@@ -126,4 +138,17 @@
* @return The alias used for "filter conditions" within the where clause.
*/
public String generateFilterConditionAlias(String rootAlias);
+
+ public static class Declarer {
+ public static final Declarer CLASS = new Declarer( "class" );
+ public static final Declarer SUBCLASS = new Declarer( "subclass" );
+ public static final Declarer SUPERCLASS = new Declarer( "superclass" );
+ private final String name;
+ public Declarer(String name) {
+ this.name = name;
+ }
+ public String toString() {
+ return name;
+ }
+ }
}
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-11-16
19:32:48 UTC (rev 10824)
+++
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-11-16
19:33:19 UTC (rev 10825)
@@ -80,7 +80,9 @@
"cid/Order.hbm.xml",
"cid/LineItem.hbm.xml",
"cid/Product.hbm.xml",
- "any/Properties.hbm.xml"
+ "any/Properties.hbm.xml",
+ "legacy/Commento.hbm.xml",
+ "legacy/Marelo.hbm.xml"
};
}
@@ -90,6 +92,52 @@
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
}
+ public void testNestedComponentIsNull() {
+ // (1) From MapTest originally...
+ // (2) Was then moved into HQLTest...
+ // (3) However, a bug fix to EntityType#getIdentifierOrUniqueKeyType (HHH-2138)
+ // caused the classic parser to suddenly start throwing exceptions on
+ // this query, apparently relying on the buggy behavior somehow; thus
+ // moved here to at least get some syntax checking...
+ new SyntaxChecker( "from Commento c where c.marelo.commento.mcompr is null"
).checkAll();
+ }
+
+ public void testSpecialClassPropertyReference() {
+ // this is a long standing bug in Hibernate when applied to joined-subclasses;
+ // see HHH-939 for details and history
+ new SyntaxChecker( "from Zoo zoo where zoo.class = PettingZoo" ).checkAll();
+ new SyntaxChecker( "select a.description from Animal a where a.class =
Mammal" ).checkAll();
+ new SyntaxChecker( "select a.class from Animal a" ).checkAll();
+ new SyntaxChecker( "from DomesticAnimal an where an.class = Dog"
).checkAll();
+ new SyntaxChecker( "from Animal an where an.class = Dog" ).checkAll();
+ }
+
+ public void testSubclassOrSuperclassPropertyReferenceInJoinedSubclass() {
+ // this is a long standing bug in Hibernate; see HHH-1631 for details and history
+ //
+ // (1) pregnant is defined as a property of the class (Mammal) itself
+ // (2) description is defined as a property of the superclass (Animal)
+ // (3) name is defined as a property of a particular subclass (Human)
+
+ new SyntaxChecker( "from Zoo z join z.mammals as m where m.name.first =
'John'" ).checkIterate();
+
+ new SyntaxChecker( "from Zoo z join z.mammals as m where m.pregnant = false"
).checkAll();
+ new SyntaxChecker( "select m.pregnant from Zoo z join z.mammals as m where
m.pregnant = false" ).checkAll();
+
+ new SyntaxChecker( "from Zoo z join z.mammals as m where m.description =
'tabby'" ).checkAll();
+ new SyntaxChecker( "select m.description from Zoo z join z.mammals as m where
m.description = 'tabby'" ).checkAll();
+
+ new SyntaxChecker( "from Zoo z join z.mammals as m where m.name.first =
'John'" ).checkAll();
+ new SyntaxChecker( "select m.name from Zoo z join z.mammals as m where
m.name.first = 'John'" ).checkAll();
+
+ new SyntaxChecker( "select m.pregnant from Zoo z join z.mammals as m"
).checkAll();
+ new SyntaxChecker( "select m.description from Zoo z join z.mammals as m"
).checkAll();
+ new SyntaxChecker( "select m.name from Zoo z join z.mammals as m"
).checkAll();
+
+ new SyntaxChecker( "from DomesticAnimal da join da.owner as o where o.nickName =
'Gavin'" ).checkAll();
+ new SyntaxChecker( "select da.father from DomesticAnimal da join da.owner as o
where o.nickName = 'Gavin'" ).checkAll();
+ }
+
public void testSimpleSelectWithLimitAndOffset() throws Exception {
if ( ! ( getDialect().supportsLimit() && getDialect().supportsLimitOffset() ) )
{
reportSkip( "dialect does not support offset and limit combo", "limit
and offset combination" );
@@ -1581,4 +1629,65 @@
session.close();
}
+ private interface QueryPreparer {
+ public void prepare(Query query);
+ }
+
+ private static final QueryPreparer DEFAULT_PREPARER = new QueryPreparer() {
+ public void prepare(Query query) {
+ }
+ };
+
+ private class SyntaxChecker {
+ private final String hql;
+ private final QueryPreparer preparer;
+
+ public SyntaxChecker(String hql) {
+ this( hql, DEFAULT_PREPARER );
+ }
+
+ public SyntaxChecker(String hql, QueryPreparer preparer) {
+ this.hql = hql;
+ this.preparer = preparer;
+ }
+
+ public void checkAll() {
+ checkList();
+ checkIterate();
+ checkScroll();
+ }
+
+ public SyntaxChecker checkList() {
+ Session s = openSession();
+ s.beginTransaction();
+ Query query = s.createQuery( hql );
+ preparer.prepare( query );
+ query.list();
+ s.getTransaction().commit();
+ s.close();
+ return this;
+ }
+
+ public SyntaxChecker checkScroll() {
+ Session s = openSession();
+ s.beginTransaction();
+ Query query = s.createQuery( hql );
+ preparer.prepare( query );
+ query.scroll();
+ s.getTransaction().commit();
+ s.close();
+ return this;
+ }
+
+ public SyntaxChecker checkIterate() {
+ Session s = openSession();
+ s.beginTransaction();
+ Query query = s.createQuery( hql );
+ preparer.prepare( query );
+ query.iterate();
+ s.getTransaction().commit();
+ s.close();
+ return this;
+ }
+ }
}
Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/HQLTest.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/HQLTest.java 2006-11-16
19:32:48 UTC (rev 10824)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/HQLTest.java 2006-11-16
19:33:19 UTC (rev 10825)
@@ -3,39 +3,37 @@
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import antlr.RecognitionException;
import junit.framework.Test;
import junit.framework.TestSuite;
-import org.hibernate.classic.Session;
-import org.hibernate.criterion.Projections;
+import org.hibernate.Hibernate;
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.engine.SessionFactoryImplementor;
+import org.hibernate.engine.query.HQLQueryPlan;
+import org.hibernate.engine.query.ReturnMetadata;
+import org.hibernate.hql.QueryTranslator;
+import org.hibernate.hql.QueryTranslatorFactory;
+import org.hibernate.hql.ast.ASTQueryTranslatorFactory;
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.
*
@@ -939,9 +937,19 @@
}
public void testClassName() throws Exception {
+ // The Zoo reference is OK; Zoo is discriminator-based;
+ // the old parser could handle these correctly
+ //
+ // However, the Animal one ares not; Animal is joined subclassing;
+ // the old parser does not handle thee correctly. The new parser
+ // previously did not handle them correctly in that same way. So they
+ // used to pass regression even though the output was bogus SQL...
+ //
+ // I have moved the Animal ones (plus duplicating the Zoo one)
+ // to ASTParserLoadingTest for syntax checking.
assertTranslation( "from Zoo zoo where zoo.class = PettingZoo" );
- assertTranslation( "from DomesticAnimal an where an.class = Dog" );
- assertTranslation( "from Animal an where an.class = Dog" );
+// assertTranslation( "from DomesticAnimal an where an.class = Dog" );
+// assertTranslation( "from Animal an where an.class = Dog" );
}
public void testSelectDialectFunction() throws Exception {
@@ -1008,11 +1016,6 @@
assertTranslation( "from Baz baz inner join baz.components comp where
comp.name='foo'" );
}
- public void testNestedComponentIsNull() {
- // From MapTest...
- assertTranslation( "from Commento c where c.marelo.commento.mcompr is null"
);
- }
-
public void testOneToOneJoinedFetch() throws Exception {
// From OneToOneTest.testOneToOneOnSubclass
assertTranslation( "from org.hibernate.test.onetoone.joined.Person p join fetch
p.address left join fetch p.mailingAddress" );