[hibernate-commits] Hibernate SVN: r18821 - in core/trunk: core/src/main/java/org/hibernate/hql/ast/tree and 2 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Feb 17 13:49:39 EST 2010


Author: steve.ebersole at jboss.com
Date: 2010-02-17 13:49:38 -0500 (Wed, 17 Feb 2010)
New Revision: 18821

Added:
   core/trunk/core/src/main/java/org/hibernate/hql/ast/TypeDiscriminatorMetadata.java
   core/trunk/core/src/main/java/org/hibernate/persister/entity/DiscriminatorMetadata.java
   core/trunk/core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java
Modified:
   core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/FromElement.java
   core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/MethodNode.java
   core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
   core/trunk/core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java
   core/trunk/core/src/main/java/org/hibernate/persister/entity/Queryable.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java
Log:
HHH-4917 - Keyword TYPE not supported


Added: core/trunk/core/src/main/java/org/hibernate/hql/ast/TypeDiscriminatorMetadata.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/TypeDiscriminatorMetadata.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/TypeDiscriminatorMetadata.java	2010-02-17 18:49:38 UTC (rev 18821)
@@ -0,0 +1,49 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.hql.ast;
+
+import org.hibernate.type.Type;
+
+/**
+ * Essentially a wrapper around a {@link org.hibernate.persister.entity.DiscriminatorMetadata}
+ * and the proper sql alias to use.
+ *
+ * @author Steve Ebersole
+ */
+public interface TypeDiscriminatorMetadata {
+	/**
+	 * Get the sql fragment that is used to determine the actual discriminator value for a row.
+	 *
+	 * @return The fragment
+	 */
+	public String getSqlFragment();
+
+	/**
+	 * Get the type used to resolve the actual discriminator value resulting from
+	 * {@link #getSqlFragment} back into a {@link Class} reference.
+	 *
+	 * @return The resolution type.
+	 */
+	public Type getResolutionType();
+}
\ No newline at end of file

Modified: core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/FromElement.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/FromElement.java	2010-02-17 15:21:28 UTC (rev 18820)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/FromElement.java	2010-02-17 18:49:38 UTC (rev 18821)
@@ -29,6 +29,7 @@
 import java.util.ArrayList;
 
 import org.hibernate.QueryException;
+import org.hibernate.hql.ast.TypeDiscriminatorMetadata;
 import org.hibernate.param.ParameterSpecification;
 import org.hibernate.engine.JoinSequence;
 import org.hibernate.hql.QueryTranslator;
@@ -37,6 +38,7 @@
 import org.hibernate.hql.ast.util.ASTUtil;
 import org.hibernate.hql.ast.HqlSqlWalker;
 import org.hibernate.persister.collection.QueryableCollection;
+import org.hibernate.persister.entity.DiscriminatorMetadata;
 import org.hibernate.persister.entity.EntityPersister;
 import org.hibernate.persister.entity.PropertyMapping;
 import org.hibernate.persister.entity.Queryable;
@@ -429,6 +431,58 @@
 		return origin;
 	}
 
+	public static final String DISCRIMINATOR_PROPERTY_NAME = "class";
+	private TypeDiscriminatorMetadata typeDiscriminatorMetadata;
+
+	private static class TypeDiscriminatorMetadataImpl implements TypeDiscriminatorMetadata {
+		private final DiscriminatorMetadata persisterDiscriminatorMetadata;
+		private final String alias;
+
+		private TypeDiscriminatorMetadataImpl(
+				DiscriminatorMetadata persisterDiscriminatorMetadata,
+				String alias) {
+			this.persisterDiscriminatorMetadata = persisterDiscriminatorMetadata;
+			this.alias = alias;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public String getSqlFragment() {
+			return persisterDiscriminatorMetadata.getSqlFragment( alias );
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public Type getResolutionType() {
+			return persisterDiscriminatorMetadata.getResolutionType();
+		}
+	}
+
+	public TypeDiscriminatorMetadata getTypeDiscriminatorMetadata() {
+		if ( typeDiscriminatorMetadata == null ) {
+			typeDiscriminatorMetadata = buildTypeDiscriminatorMetadata();
+		}
+		return typeDiscriminatorMetadata;
+	}
+
+	private TypeDiscriminatorMetadata buildTypeDiscriminatorMetadata() {
+		final String aliasToUse = getTableAlias();
+		Queryable queryable = getQueryable();
+		if ( queryable == null ) {
+			QueryableCollection collection = getQueryableCollection();
+			if ( ! collection.getElementType().isEntityType() ) {
+				throw new QueryException( "type discrimination cannot be applied to value collection [" + collection.getRole() + "]" );
+			}
+			queryable = (Queryable) collection.getElementPersister();
+		}
+
+		handlePropertyBeingDereferenced( getDataType(), DISCRIMINATOR_PROPERTY_NAME );
+
+		return new TypeDiscriminatorMetadataImpl( queryable.getTypeDiscriminatorMetadata(), aliasToUse );
+	}
+
 	public Type getPropertyType(String propertyName, String propertyPath) {
 		return elementType.getPropertyType( propertyName, propertyPath );
 	}

Modified: core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/MethodNode.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/MethodNode.java	2010-02-17 15:21:28 UTC (rev 18820)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/MethodNode.java	2010-02-17 18:49:38 UTC (rev 18821)
@@ -29,6 +29,7 @@
 import org.hibernate.dialect.function.SQLFunction;
 import org.hibernate.hql.CollectionProperties;
 import org.hibernate.hql.antlr.SqlTokenTypes;
+import org.hibernate.hql.ast.TypeDiscriminatorMetadata;
 import org.hibernate.hql.ast.util.ASTUtil;
 import org.hibernate.hql.ast.util.ColumnHelper;
 import org.hibernate.persister.collection.CollectionPropertyNames;
@@ -83,13 +84,11 @@
 		}
 
 		FromReferenceNode pathAsFromReferenceNode = (FromReferenceNode) path;
-		FromElement typeFromElement = pathAsFromReferenceNode.getFromElement();
-		Type type = typeFromElement.getPropertyType( "class", "class" );
-		setDataType( type );
+		FromElement fromElement = pathAsFromReferenceNode.getFromElement();
+		TypeDiscriminatorMetadata typeDiscriminatorMetadata = fromElement.getTypeDiscriminatorMetadata();
 
-		String[] columns = typeFromElement.toColumns( typeFromElement.getTableAlias(), "class", inSelect );
-		setText( columns[0] );
-
+		setDataType( typeDiscriminatorMetadata.getResolutionType() );
+		setText( typeDiscriminatorMetadata.getSqlFragment() );
 		setType( SqlTokenTypes.SQL_TOKEN );
 	}
 
@@ -217,7 +216,6 @@
 	}
 
 	protected void prepareSelectColumns(String[] columns) {
-		return;
 	}
 
 	public FromElement getFromElement() {

Modified: core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java	2010-02-17 15:21:28 UTC (rev 18820)
+++ core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java	2010-02-17 18:49:38 UTC (rev 18821)
@@ -87,6 +87,7 @@
 import org.hibernate.mapping.Property;
 import org.hibernate.mapping.Selectable;
 import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.persister.entity.DiscriminatorMetadata;
 import org.hibernate.pretty.MessageHelper;
 import org.hibernate.property.BackrefPropertyAccessor;
 import org.hibernate.sql.Alias;
@@ -1500,6 +1501,27 @@
 		}
 	}
 
+	private DiscriminatorMetadata discriminatorMetadata;
+
+	public DiscriminatorMetadata getTypeDiscriminatorMetadata() {
+		if ( discriminatorMetadata == null ) {
+			discriminatorMetadata = buildTypeDiscriminatorMetadata();
+		}
+		return discriminatorMetadata;
+	}
+
+	private DiscriminatorMetadata buildTypeDiscriminatorMetadata() {
+		return new DiscriminatorMetadata() {
+			public String getSqlFragment(String sqlQualificationAlias) {
+				return toColumns( sqlQualificationAlias, ENTITY_CLASS )[0];
+			}
+
+			public Type getResolutionType() {
+				return new DiscriminatorType( getDiscriminatorType(), AbstractEntityPersister.this );
+			}
+		};
+	}
+
 	protected String generateTableAlias(String rootAlias, int tableNumber) {
 		if ( tableNumber == 0 ) {
 			return rootAlias;

Added: core/trunk/core/src/main/java/org/hibernate/persister/entity/DiscriminatorMetadata.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/persister/entity/DiscriminatorMetadata.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/persister/entity/DiscriminatorMetadata.java	2010-02-17 18:49:38 UTC (rev 18821)
@@ -0,0 +1,52 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.persister.entity;
+
+import org.hibernate.type.Type;
+
+/**
+ * Provides the information needed to properly handle type discrimination
+ * in HQL queries, either by 'something.class' or 'type(something)' references.
+ *
+ * @author Steve Ebersole
+ */
+public interface DiscriminatorMetadata {
+	/**
+	 * Get the sql fragment that is used to determine the actual discriminator value for a row.
+	 *
+	 * @param sqlQualificationAlias The qualification alias to append to any columns references in
+	 * the generated fragment.
+	 *
+	 * @return The fragment
+	 */
+	public String getSqlFragment(String sqlQualificationAlias);
+
+	/**
+	 * Get the type used to resolve the actual discriminator value resulting from
+	 * {@link #getSqlFragment} back into a {@link Class} reference.
+	 *
+	 * @return The resolution type.
+	 */
+	public Type getResolutionType();
+}

Added: core/trunk/core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java	2010-02-17 18:49:38 UTC (rev 18821)
@@ -0,0 +1,160 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.persister.entity;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.dom4j.Node;
+
+import org.hibernate.EntityMode;
+import org.hibernate.HibernateException;
+import org.hibernate.MappingException;
+import org.hibernate.engine.Mapping;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.type.AbstractType;
+import org.hibernate.type.Type;
+import org.hibernate.util.ArrayHelper;
+import org.hibernate.util.EqualsHelper;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class DiscriminatorType extends AbstractType {
+	private final Type underlyingType;
+	private final Loadable persister;
+
+	public DiscriminatorType(Type underlyingType, Loadable persister) {
+		this.underlyingType = underlyingType;
+		this.persister = persister;
+	}
+
+	public Class getReturnedClass() {
+		return Class.class;
+	}
+
+	public String getName() {
+		return getClass().getName();
+	}
+
+	public boolean isMutable() {
+		return false;
+	}
+
+	public Object nullSafeGet(
+			ResultSet rs,
+			String[] names,
+			SessionImplementor session,
+			Object owner) throws HibernateException, SQLException {
+		return nullSafeGet( rs, names[0], session, owner );
+	}
+
+	public Object nullSafeGet(
+			ResultSet rs,
+			String name,
+			SessionImplementor session,
+			Object owner) throws HibernateException, SQLException {
+		final Object discriminatorValue = underlyingType.nullSafeGet( rs, name, session, owner );
+		final String entityName = persister.getSubclassForDiscriminatorValue( discriminatorValue );
+		if ( entityName == null ) {
+			throw new HibernateException( "Unable to resolve discriminator value [" + discriminatorValue + "] to entity name" );
+		}
+		if ( EntityMode.POJO.equals( session.getEntityMode() ) ) {
+			return session.getEntityPersister( entityName, null ).getMappedClass( session.getEntityMode() );
+		}
+		else {
+			return entityName;
+		}
+	}
+
+	public void nullSafeSet(
+			PreparedStatement st,
+			Object value,
+			int index,
+			boolean[] settable,
+			SessionImplementor session) throws HibernateException, SQLException {
+		nullSafeSet( st, value, index, session );
+	}
+
+	public void nullSafeSet(
+			PreparedStatement st,
+			Object value,
+			int index,
+			SessionImplementor session) throws HibernateException, SQLException {
+		throw new UnsupportedOperationException(
+				"At the moment this type is not the one actually used to map the discriminator."
+		);
+	}
+
+	public String toLoggableString(Object value, SessionFactoryImplementor factory) throws HibernateException {
+		return value == null ? "[null]" : value.toString();
+	}
+
+	public Object deepCopy(Object value, EntityMode entityMode, SessionFactoryImplementor factory)
+			throws HibernateException {
+		return value;
+	}
+
+	public Object replace(Object original, Object target, SessionImplementor session, Object owner, Map copyCache)
+			throws HibernateException {
+		return original;
+	}
+
+	public boolean[] toColumnNullness(Object value, Mapping mapping) {
+		return value == null
+				? ArrayHelper.FALSE
+				: ArrayHelper.TRUE;
+	}
+
+	public boolean isDirty(Object old, Object current, boolean[] checkable, SessionImplementor session)
+			throws HibernateException {
+		return EqualsHelper.equals( old, current );
+	}
+
+
+	// simple delegation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public int[] sqlTypes(Mapping mapping) throws MappingException {
+		return underlyingType.sqlTypes( mapping );
+	}
+
+	public int getColumnSpan(Mapping mapping) throws MappingException {
+		return underlyingType.getColumnSpan( mapping );
+	}
+
+	public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) throws HibernateException {
+	}
+
+	public Object fromXMLNode(Node xml, Mapping factory) throws HibernateException {
+		// todo : ???
+		return null;
+	}
+
+}

Modified: core/trunk/core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java	2010-02-17 15:21:28 UTC (rev 18820)
+++ core/trunk/core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java	2010-02-17 18:49:38 UTC (rev 18821)
@@ -49,6 +49,7 @@
 import org.hibernate.mapping.Table;
 import org.hibernate.sql.CaseFragment;
 import org.hibernate.sql.SelectFragment;
+import org.hibernate.type.AbstractType;
 import org.hibernate.type.Type;
 import org.hibernate.util.ArrayHelper;
 

Modified: core/trunk/core/src/main/java/org/hibernate/persister/entity/Queryable.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/persister/entity/Queryable.java	2010-02-17 15:21:28 UTC (rev 18820)
+++ core/trunk/core/src/main/java/org/hibernate/persister/entity/Queryable.java	2010-02-17 18:49:38 UTC (rev 18821)
@@ -24,6 +24,7 @@
  */
 package org.hibernate.persister.entity;
 
+import org.hibernate.persister.entity.DiscriminatorMetadata;
 import org.hibernate.sql.SelectFragment;
 
 /**
@@ -165,6 +166,14 @@
 	 */
 	public String generateFilterConditionAlias(String rootAlias);
 
+	/**
+	 * Retrieve the information needed to properly deal with this entity's discriminator
+	 * in a query.
+	 *
+	 * @return The entity discriminator metadata
+	 */
+	public DiscriminatorMetadata getTypeDiscriminatorMetadata();
+
 	public static class Declarer {
 		public static final Declarer CLASS = new Declarer( "class" );
 		public static final Declarer SUBCLASS = new Declarer( "subclass" );

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-02-17 15:21:28 UTC (rev 18820)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java	2010-02-17 18:49:38 UTC (rev 18821)
@@ -38,6 +38,7 @@
 import org.hibernate.hql.ast.ASTQueryTranslatorFactory;
 import org.hibernate.junit.functional.FunctionalTestCase;
 import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.persister.entity.DiscriminatorType;
 import org.hibernate.stat.QueryStatistics;
 import org.hibernate.test.any.IntegerPropertyValue;
 import org.hibernate.test.any.PropertySet;
@@ -111,11 +112,27 @@
 		Session s = openSession();
 		s.beginTransaction();
 
+		///////////////////////////////////////////////////////////////
+		// where clause
 		// control
 		s.createQuery( "from Animal a where a.class = Dog" ).list();
-
+        // test
 		s.createQuery( "from Animal a where type(a) = Dog" ).list();
 
+		///////////////////////////////////////////////////////////////
+		// select clause (at some point we should unify these)
+		// control
+		Query query = s.createQuery( "select a.class from Animal a where a.class = Dog" );
+		query.list(); // checks syntax
+		assertEquals( 1, query.getReturnTypes().length );
+		assertEquals( Integer.class, query.getReturnTypes()[0].getReturnedClass() ); // always integer for joined
+        // test
+		query = s.createQuery( "select type(a) from Animal a where type(a) = Dog" );
+		query.list(); // checks syntax
+		assertEquals( 1, query.getReturnTypes().length );
+		assertEquals( DiscriminatorType.class, query.getReturnTypes()[0].getClass() );
+		assertEquals( Class.class, query.getReturnTypes()[0].getReturnedClass() );
+
 		s.getTransaction().commit();
 		s.close();
 	}



More information about the hibernate-commits mailing list