[hibernate-commits] Hibernate SVN: r17874 - in core/trunk: core/src/main/java/org/hibernate/dialect and 1 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Oct 28 22:07:41 EDT 2009


Author: steve.ebersole at jboss.com
Date: 2009-10-28 22:07:40 -0400 (Wed, 28 Oct 2009)
New Revision: 17874

Modified:
   core/trunk/core/src/main/java/org/hibernate/criterion/AggregateProjection.java
   core/trunk/core/src/main/java/org/hibernate/criterion/AvgProjection.java
   core/trunk/core/src/main/java/org/hibernate/criterion/CountProjection.java
   core/trunk/core/src/main/java/org/hibernate/criterion/RowCountProjection.java
   core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/hql/CriteriaHQLAlignmentTest.java
Log:
HHH-1724 - Critieria needs to be aligned with new aggreation type rules


Modified: core/trunk/core/src/main/java/org/hibernate/criterion/AggregateProjection.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/criterion/AggregateProjection.java	2009-10-29 00:36:07 UTC (rev 17873)
+++ core/trunk/core/src/main/java/org/hibernate/criterion/AggregateProjection.java	2009-10-29 02:07:40 UTC (rev 17874)
@@ -1,10 +1,10 @@
 /*
  * Hibernate, Relational Persistence for Idiomatic Java
  *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
+ * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
+ * third-party contributors as indicated by either @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
@@ -20,48 +20,86 @@
  * Free Software Foundation, Inc.
  * 51 Franklin Street, Fifth Floor
  * Boston, MA  02110-1301  USA
- *
  */
 package org.hibernate.criterion;
 
+import java.util.Collections;
+import java.util.List;
+
 import org.hibernate.Criteria;
 import org.hibernate.HibernateException;
+import org.hibernate.dialect.function.SQLFunction;
 import org.hibernate.type.Type;
 
 /**
- * An aggregation
+ * Base class for standard aggregation functions.
  *
  * @author max
  */
 public class AggregateProjection extends SimpleProjection {
-
 	protected final String propertyName;
-	private final String aggregate;
+	private final String functionName;
 	
-	protected AggregateProjection(String aggregate, String propertyName) {
-		this.aggregate = aggregate;
+	protected AggregateProjection(String functionName, String propertyName) {
+		this.functionName = functionName;
 		this.propertyName = propertyName;
 	}
 
+	public String getFunctionName() {
+		return functionName;
+	}
+
+	public String getPropertyName() {
+		return propertyName;
+	}
+
 	public String toString() {
-		return aggregate + "(" + propertyName + ')';
+		return functionName + "(" + propertyName + ')';
 	}
 
-	public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) 
-	throws HibernateException {
-		return new Type[] { criteriaQuery.getType(criteria, propertyName) };
+	/**
+	 * {@inheritDoc}
+	 */
+	public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
+		return new Type[] {
+				getFunction( criteriaQuery ).getReturnType(
+						criteriaQuery.getType( criteria, getPropertyName() ),
+						criteriaQuery.getFactory()
+				)
+		};
 	}
 
-	public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) 
-	throws HibernateException {
-		return new StringBuffer()
-			.append(aggregate)
-			.append("(")
-			.append( criteriaQuery.getColumn(criteria, propertyName) )
-			.append(") as y")
-			.append(loc)
-			.append('_')
-			.toString();
+	/**
+	 * {@inheritDoc}
+	 */
+	public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery)
+			throws HibernateException {
+		final String functionFragment = getFunction( criteriaQuery ).render(
+				buildFunctionParameterList( criteria, criteriaQuery ),
+				criteriaQuery.getFactory()
+		);
+		return functionFragment + " as y" + loc + '_';
 	}
 
+	protected SQLFunction getFunction(CriteriaQuery criteriaQuery) {
+		return getFunction( getFunctionName(), criteriaQuery );
+	}
+
+	protected SQLFunction getFunction(String functionName, CriteriaQuery criteriaQuery) {
+		SQLFunction function = criteriaQuery.getFactory()
+				.getSqlFunctionRegistry()
+				.findSQLFunction( functionName );
+		if ( function == null ) {
+			throw new HibernateException( "Unable to locate mapping for function named [" + functionName + "]" );
+		}
+		return function;
+	}
+
+	protected List buildFunctionParameterList(Criteria criteria, CriteriaQuery criteriaQuery) {
+		return buildFunctionParameterList( criteriaQuery.getColumn( criteria, getPropertyName() ) );
+	}
+
+	protected List buildFunctionParameterList(String column) {
+		return Collections.singletonList( column );
+	}
 }

Modified: core/trunk/core/src/main/java/org/hibernate/criterion/AvgProjection.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/criterion/AvgProjection.java	2009-10-29 00:36:07 UTC (rev 17873)
+++ core/trunk/core/src/main/java/org/hibernate/criterion/AvgProjection.java	2009-10-29 02:07:40 UTC (rev 17874)
@@ -1,10 +1,10 @@
 /*
  * Hibernate, Relational Persistence for Idiomatic Java
  *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
+ * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
+ * third-party contributors as indicated by either @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
@@ -20,28 +20,16 @@
  * Free Software Foundation, Inc.
  * 51 Franklin Street, Fifth Floor
  * Boston, MA  02110-1301  USA
- *
  */
 package org.hibernate.criterion;
 
-import org.hibernate.Criteria;
-import org.hibernate.Hibernate;
-import org.hibernate.HibernateException;
-import org.hibernate.type.Type;
-
 /**
  * An avg() projection
  *
  * @author Gavin King
  */
 public class AvgProjection extends AggregateProjection {
-
 	public AvgProjection(String propertyName) {
 		super("avg", propertyName);
 	}
-	
-	public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery)
-	throws HibernateException {
-		return new Type[] { Hibernate.DOUBLE };
-	}
 }

Modified: core/trunk/core/src/main/java/org/hibernate/criterion/CountProjection.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/criterion/CountProjection.java	2009-10-29 00:36:07 UTC (rev 17873)
+++ core/trunk/core/src/main/java/org/hibernate/criterion/CountProjection.java	2009-10-29 02:07:40 UTC (rev 17874)
@@ -1,10 +1,10 @@
 /*
  * Hibernate, Relational Persistence for Idiomatic Java
  *
- * Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
+ * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
+ * third-party contributors as indicated by either @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
@@ -20,21 +20,14 @@
  * Free Software Foundation, Inc.
  * 51 Franklin Street, Fifth Floor
  * Boston, MA  02110-1301  USA
- *
  */
 package org.hibernate.criterion;
 
-import org.hibernate.Criteria;
-import org.hibernate.Hibernate;
-import org.hibernate.HibernateException;
-import org.hibernate.type.Type;
-
 /**
  * A count
  * @author Gavin King
  */
 public class CountProjection extends AggregateProjection {
-
 	private boolean distinct;
 
 	protected CountProjection(String prop) {
@@ -42,33 +35,16 @@
 	}
 
 	public String toString() {
-		if(distinct) {
+		if ( distinct ) {
 			return "distinct " + super.toString();
-		} else {
+		}
+		else {
 			return super.toString();
 		}
 	}
 
-	public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) 
-	throws HibernateException {
-		return new Type[] { Hibernate.INTEGER };
-	}
-
-	public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) 
-	throws HibernateException {
-		StringBuffer buf = new StringBuffer();
-		buf.append("count(");
-		if (distinct) buf.append("distinct ");
-		return buf.append( criteriaQuery.getColumn(criteria, propertyName) )
-			.append(") as y")
-			.append(position)
-			.append('_')
-			.toString();
-	}
-	
 	public CountProjection setDistinct() {
 		distinct = true;
 		return this;
 	}
-	
 }

Modified: core/trunk/core/src/main/java/org/hibernate/criterion/RowCountProjection.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/criterion/RowCountProjection.java	2009-10-29 00:36:07 UTC (rev 17873)
+++ core/trunk/core/src/main/java/org/hibernate/criterion/RowCountProjection.java	2009-10-29 02:07:40 UTC (rev 17874)
@@ -24,35 +24,43 @@
  */
 package org.hibernate.criterion;
 
+import java.util.List;
+
 import org.hibernate.Criteria;
-import org.hibernate.Hibernate;
 import org.hibernate.HibernateException;
+import org.hibernate.dialect.function.SQLFunction;
 import org.hibernate.type.Type;
 
 /**
  * A row count
+ *
  * @author Gavin King
  */
 public class RowCountProjection extends SimpleProjection {
+	private static List ARGS = java.util.Collections.singletonList( "*" );
 
-	protected RowCountProjection() {}
-
 	public String toString() {
 		return "count(*)";
 	}
 
-	public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) 
-	throws HibernateException {
-		return new Type[] { Hibernate.INTEGER };
+	public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
+		return new Type[] {
+				getFunction( criteriaQuery ).getReturnType( null, criteriaQuery.getFactory() )
+		};
 	}
 
-	public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) 
-	throws HibernateException {
-		return new StringBuffer()
-			.append("count(*) as y")
-			.append(position)
-			.append('_')
-			.toString();
+	public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
+		return getFunction( criteriaQuery ).render( ARGS, criteriaQuery.getFactory() )
+				+ " as y" + position + '_';
 	}
 
+	protected SQLFunction getFunction(CriteriaQuery criteriaQuery) {
+		SQLFunction function = criteriaQuery.getFactory()
+				.getSqlFunctionRegistry()
+				.findSQLFunction( "count" );
+		if ( function == null ) {
+			throw new HibernateException( "Unable to locate count function mapping" );
+		}
+		return function;
+	}
 }

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java	2009-10-29 00:36:07 UTC (rev 17873)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java	2009-10-29 02:07:40 UTC (rev 17874)
@@ -33,6 +33,8 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.util.List;
+import java.util.Iterator;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -49,6 +51,7 @@
 import org.hibernate.dialect.lock.LockingStrategy;
 import org.hibernate.dialect.lock.SelectLockingStrategy;
 import org.hibernate.engine.Mapping;
+import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.exception.SQLExceptionConverter;
 import org.hibernate.exception.SQLStateConverter;
 import org.hibernate.exception.ViolatedConstraintNameExtracter;
@@ -94,71 +97,116 @@
 	// build the map of standard ANSI SQL aggregation functions ~~~~~~~~~~~~~~~
 
 	private static final Map STANDARD_AGGREGATE_FUNCTIONS = new HashMap();
+
 	static {
-		STANDARD_AGGREGATE_FUNCTIONS.put( "count", new StandardSQLFunction("count") {
-			public Type getReturnType(Type columnType, Mapping mapping) {
-				return Hibernate.LONG;
-			}
-		} );
+		STANDARD_AGGREGATE_FUNCTIONS.put(
+				"count",
+				new StandardSQLFunction("count") {
+					public Type getReturnType(Type columnType, Mapping mapping) {
+						return Hibernate.LONG;
+					}
+					public String render(List args, SessionFactoryImplementor factory) {
+						if ( args.size() > 1 ) {
+							if ( "distinct".equalsIgnoreCase( args.get( 0 ).toString() ) ) {
+								return renderCountDistinct( args );
+							}
+						}
+						return super.render( args, factory );
+					}
+					private String renderCountDistinct(List args) {
+						StringBuffer buffer = new StringBuffer();
+						buffer.append( "count(distinct " );
+						String sep = "";
+						Iterator itr = args.iterator();
+						itr.next(); // intentionally skip first
+						while ( itr.hasNext() ) {
+							buffer.append( sep )
+									.append( itr.next() );
+							sep = ", ";
+						}
+						return buffer.append( ")" ).toString();
+					}
+				}
+		);
 
-		STANDARD_AGGREGATE_FUNCTIONS.put( "avg", new StandardSQLFunction("avg") {
-			public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
-				int[] sqlTypes;
-				try {
-					sqlTypes = columnType.sqlTypes( mapping );
+		STANDARD_AGGREGATE_FUNCTIONS.put(
+				"avg",
+				new StandardSQLFunction("avg") {
+					public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
+						int[] sqlTypes;
+						try {
+							sqlTypes = columnType.sqlTypes( mapping );
+						}
+						catch ( MappingException me ) {
+							throw new QueryException( me );
+						}
+						if ( sqlTypes.length != 1 ) {
+							throw new QueryException( "multi-column type in avg()" );
+						}
+						return Hibernate.DOUBLE;
+					}
 				}
-				catch ( MappingException me ) {
-					throw new QueryException( me );
-				}
-				if ( sqlTypes.length != 1 ) throw new QueryException( "multi-column type in avg()" );
-				return Hibernate.DOUBLE;
-			}
-		} );
+		);
 
 		STANDARD_AGGREGATE_FUNCTIONS.put( "max", new StandardSQLFunction("max") );
 		STANDARD_AGGREGATE_FUNCTIONS.put( "min", new StandardSQLFunction("min") );
-		STANDARD_AGGREGATE_FUNCTIONS.put( "sum", new StandardSQLFunction("sum") {
-			public Type getReturnType(Type columnType, Mapping mapping) {
-				//pre H3.2 behavior: super.getReturnType(ct, m);
-				int[] sqlTypes;
-				try {
-					sqlTypes = columnType.sqlTypes( mapping );
-				}
-				catch ( MappingException me ) {
-					throw new QueryException( me );
-				}
-				if ( sqlTypes.length != 1 ) throw new QueryException( "multi-column type in sum()" );
-				int sqlType = sqlTypes[0];
 
-				// First allow the actual type to control the return value. (the actual underlying sqltype could actually be different)
-				if ( columnType == Hibernate.BIG_INTEGER ) {
-					return Hibernate.BIG_INTEGER;
-				}
-				else if ( columnType == Hibernate.BIG_DECIMAL ) {
-					return Hibernate.BIG_DECIMAL;
-				}
-				else if ( columnType == Hibernate.LONG || columnType == Hibernate.SHORT || columnType == Hibernate.INTEGER) {
-					return Hibernate.LONG;
-				}
-				else if ( columnType == Hibernate.FLOAT || columnType == Hibernate.DOUBLE) {
-					return Hibernate.DOUBLE;
-				}
+		STANDARD_AGGREGATE_FUNCTIONS.put(
+				"sum",
+				new StandardSQLFunction("sum") {
+					public Type getReturnType(Type columnType, Mapping mapping) {
+						//pre H3.2 behavior: super.getReturnType(ct, m);
+						int[] sqlTypes;
+						try {
+							sqlTypes = columnType.sqlTypes( mapping );
+						}
+						catch ( MappingException me ) {
+							throw new QueryException( me );
+						}
+						if ( sqlTypes.length != 1 ) {
+							throw new QueryException( "multi-column type in sum()" );
+						}
+						int sqlType = sqlTypes[0];
 
-				// finally use the sqltype if == on Hibernate types did not find a match.
-				if ( sqlType == Types.NUMERIC ) {
-					return columnType; //because numeric can be anything
+						// First allow the actual type to control the return value; the underlying sqltype could
+						// actually be different
+						if ( columnType == Hibernate.BIG_INTEGER ) {
+							return Hibernate.BIG_INTEGER;
+						}
+						else if ( columnType == Hibernate.BIG_DECIMAL ) {
+							return Hibernate.BIG_DECIMAL;
+						}
+						else if ( columnType == Hibernate.LONG
+								|| columnType == Hibernate.SHORT
+								|| columnType == Hibernate.INTEGER ) {
+							return Hibernate.LONG;
+						}
+						else if ( columnType == Hibernate.FLOAT || columnType == Hibernate.DOUBLE)  {
+							return Hibernate.DOUBLE;
+						}
+
+						// finally use the sqltype if == on Hibernate types did not find a match.
+						if ( sqlType == Types.NUMERIC ) {
+							return columnType; //because numeric can be anything
+						}
+						else if ( sqlType == Types.FLOAT
+								|| sqlType == Types.DOUBLE
+								|| sqlType == Types.DECIMAL
+								|| sqlType == Types.REAL) {
+							return Hibernate.DOUBLE;
+						}
+						else if ( sqlType == Types.BIGINT
+								|| sqlType == Types.INTEGER
+								|| sqlType == Types.SMALLINT
+								|| sqlType == Types.TINYINT ) {
+							return Hibernate.LONG;
+						}
+						else {
+							return columnType;
+						}
+					}
 				}
-				else if ( sqlType == Types.FLOAT || sqlType == Types.DOUBLE || sqlType == Types.DECIMAL || sqlType == Types.REAL) {
-					return Hibernate.DOUBLE;
-				}
-				else if ( sqlType == Types.BIGINT || sqlType == Types.INTEGER || sqlType == Types.SMALLINT || sqlType == Types.TINYINT ) {
-					return Hibernate.LONG;
-				}
-				else {
-					return columnType;
-				}
-			}
-		});
+		);
 	}
 
 	private final TypeNames typeNames = new TypeNames();

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/hql/CriteriaHQLAlignmentTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/hql/CriteriaHQLAlignmentTest.java	2009-10-29 00:36:07 UTC (rev 17873)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/hql/CriteriaHQLAlignmentTest.java	2009-10-29 02:07:40 UTC (rev 17874)
@@ -113,7 +113,7 @@
 	}
 	
 	// HHH-1724 Align Criteria with HQL aggregation return types.
-	public void testCriteriaAggregationReturnTypeFailureExpected() {
+	public void testCriteriaAggregationReturnType() {
 		Session s = openSession();
 		Human human = new Human();
 		human.setBigIntegerValue( new BigInteger("42") );



More information about the hibernate-commits mailing list