EJB-447 : Implement JPA 2.0 criteria apis (completed aggregation function support)

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17247 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2009-08-06 17:55:14 +00:00
parent eb0396b1c6
commit 8465009b4b
7 changed files with 218 additions and 105 deletions

View File

@ -44,8 +44,7 @@ import org.hibernate.ejb.EntityManagerFactoryImpl;
import org.hibernate.ejb.criteria.expression.CompoundSelectionImpl; import org.hibernate.ejb.criteria.expression.CompoundSelectionImpl;
import org.hibernate.ejb.criteria.expression.ParameterExpressionImpl; import org.hibernate.ejb.criteria.expression.ParameterExpressionImpl;
import org.hibernate.ejb.criteria.expression.LiteralExpression; import org.hibernate.ejb.criteria.expression.LiteralExpression;
import org.hibernate.ejb.criteria.expression.function.AverageAggregrateFunction; import org.hibernate.ejb.criteria.expression.function.AggregationFunction;
import org.hibernate.ejb.criteria.expression.function.SumAggregateFunction;
import org.hibernate.ejb.criteria.predicate.BooleanExpressionPredicate; import org.hibernate.ejb.criteria.predicate.BooleanExpressionPredicate;
import org.hibernate.ejb.criteria.predicate.ExplicitTruthValueCheck; import org.hibernate.ejb.criteria.predicate.ExplicitTruthValueCheck;
import org.hibernate.ejb.criteria.predicate.TruthValue; import org.hibernate.ejb.criteria.predicate.TruthValue;
@ -550,63 +549,57 @@ public class QueryBuilderImpl implements QueryBuilder, Serializable {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <N extends Number> Expression<Double> avg(Expression<N> x) { public <N extends Number> AggregationFunction.AVG avg(Expression<N> x) {
return new AverageAggregrateFunction( this, x ); return new AggregationFunction.AVG( this, x );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <N extends Number> Expression<N> sum(Expression<N> x) { public <N extends Number> AggregationFunction.SUM<N> sum(Expression<N> x) {
return new SumAggregateFunction<N>( this, x ); return new AggregationFunction.SUM<N>( this, x );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <N extends Number> Expression<N> max(Expression<N> x) { public <N extends Number> AggregationFunction.MAX<N> max(Expression<N> x) {
// TODO : requires a MaxAggregrateFunction return new AggregationFunction.MAX<N>( this, x );
throw new UnsupportedOperationException( "Note yet implemented!" );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <N extends Number> Expression<N> min(Expression<N> x) { public <N extends Number> AggregationFunction.MIN<N> min(Expression<N> x) {
// TODO : requires a MaxAggregrateFunction return new AggregationFunction.MIN<N>( this, x );
throw new UnsupportedOperationException( "Note yet implemented!" );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <X extends Comparable<X>> Expression<X> greatest(Expression<X> x) { public <X extends Comparable<X>> Expression<X> greatest(Expression<X> x) {
// TODO : not exactly sure what this should be returning, same as #max ? return new AggregationFunction.GREATEST<X>( this, x );
throw new UnsupportedOperationException( "Note yet implemented!" );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <X extends Comparable<X>> Expression<X> least(Expression<X> x) { public <X extends Comparable<X>> Expression<X> least(Expression<X> x) {
// TODO : not exactly sure what this should be returning, same as #min ? return new AggregationFunction.LEAST<X>( this, x );
throw new UnsupportedOperationException( "Note yet implemented!" );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public Expression<Long> count(Expression<?> x) { public Expression<Long> count(Expression<?> x) {
// TODO : CountAggregateFunction return new AggregationFunction.COUNT( this, x, false );
throw new UnsupportedOperationException( "Note yet implemented!" );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public Expression<Long> countDistinct(Expression<?> x) { public Expression<Long> countDistinct(Expression<?> x) {
// TODO : CountDistinctAggregateFunction or CountAggregateFunction w/ distinct parameterization return new AggregationFunction.COUNT( this, x, true );
throw new UnsupportedOperationException( "Note yet implemented!" );
} }

View File

@ -0,0 +1,170 @@
package org.hibernate.ejb.criteria.expression.function;
import java.util.Collections;
import java.util.List;
import javax.persistence.criteria.Expression;
import org.hibernate.ejb.criteria.QueryBuilderImpl;
import org.hibernate.ejb.criteria.expression.LiteralExpression;
/**
* Models SQL aggregation functions (<tt>MIN</tt>, <tt>MAX</tt>, <tt>COUNT</tt>, etc).
*
* @author Steve Ebersole
*/
public class AggregationFunction<T> extends BasicFunctionExpression<T> {
private static final List<Expression<?>> NO_ARGS = Collections.emptyList();
/**
* Constructs an aggregation function with no arguments (<tt>COUNT(*)</tt> e.g.).
*
* @param queryBuilder The query builder instance.
* @param returnType The function return type.
* @param functionName The name of the function.
*/
public AggregationFunction(
QueryBuilderImpl queryBuilder,
Class<T> returnType,
String functionName) {
super( queryBuilder, returnType, functionName, NO_ARGS );
}
/**
* Constructs an aggregation function with a single literal argument.
*
* @param queryBuilder The query builder instance.
* @param returnType The function return type.
* @param functionName The name of the function.
* @param argument The literal argument
*/
public AggregationFunction(
QueryBuilderImpl queryBuilder,
Class<T> returnType,
String functionName,
Object argument) {
this( queryBuilder, returnType, functionName, new LiteralExpression( queryBuilder, argument ) );
}
/**
* Constructs an aggregation function with a single literal argument.
*
* @param queryBuilder The query builder instance.
* @param returnType The function return type.
* @param functionName The name of the function.
* @param argument The argument
*/
public AggregationFunction(
QueryBuilderImpl queryBuilder,
Class<T> returnType,
String functionName,
Expression<?> argument) {
super( queryBuilder, returnType, functionName, argument );
}
@Override
public boolean isAggregation() {
return true;
}
/**
* Implementation of a <tt>COUNT</tt> function providing convenience in construction.
* <p/>
* Parameterized as {@link Long} because thats what JPA states
* that the return from <tt>COUNT</tt> should be.
*/
public static class COUNT extends AggregationFunction<Long> {
public static final String NAME = "count";
private final boolean distinct;
public COUNT(QueryBuilderImpl queryBuilder, Expression<?> expression, boolean distinct) {
super( queryBuilder, Long.class, NAME , expression );
this.distinct = distinct;
}
public boolean isDistinct() {
return distinct;
}
}
/**
* Implementation of a <tt>AVG</tt> function providing convenience in construction.
* <p/>
* Parameterized as {@link Double} because thats what JPA states that the return from <tt>AVG</tt> should be.
*/
public static class AVG extends AggregationFunction<Double> {
public static final String NAME = "avg";
public AVG(QueryBuilderImpl queryBuilder, Expression<? extends Number> expression) {
super( queryBuilder, Double.class, NAME, expression );
}
}
/**
* Implementation of a <tt>SUM</tt> function providing convenience in construction.
* <p/>
* Parameterized as {@link Number N extends Number} because thats what JPA states
* that the return from <tt>SUM</tt> should be.
*/
public static class SUM<N extends Number> extends AggregationFunction<N> {
public static final String NAME = "sum";
public SUM(QueryBuilderImpl queryBuilder, Expression<N> expression) {
super( queryBuilder, expression.getJavaType(), NAME , expression);
}
}
/**
* Implementation of a <tt>MIN</tt> function providing convenience in construction.
* <p/>
* Parameterized as {@link Number N extends Number} because thats what JPA states
* that the return from <tt>MIN</tt> should be.
*/
public static class MIN<N extends Number> extends AggregationFunction<N> {
public static final String NAME = "min";
public MIN(QueryBuilderImpl queryBuilder, Expression<N> expression) {
super( queryBuilder, expression.getJavaType(), NAME , expression);
}
}
/**
* Implementation of a <tt>MAX</tt> function providing convenience in construction.
* <p/>
* Parameterized as {@link Number N extends Number} because thats what JPA states
* that the return from <tt>MAX</tt> should be.
*/
public static class MAX<N extends Number> extends AggregationFunction<N> {
public static final String NAME = "max";
public MAX(QueryBuilderImpl queryBuilder, Expression<N> expression) {
super( queryBuilder, expression.getJavaType(), NAME , expression);
}
}
/**
* Models the <tt>MIN</tt> function in terms of non-numeric expressions.
*
* @see MIN
*/
public static class LEAST<X extends Comparable<X>> extends AggregationFunction<X> {
public static final String NAME = "min";
public LEAST(QueryBuilderImpl queryBuilder, Expression<X> expression) {
super( queryBuilder, expression.getJavaType(), NAME , expression);
}
}
/**
* Models the <tt>MAX</tt> function in terms of non-numeric expressions.
*
* @see MAX
*/
public static class GREATEST<X extends Comparable<X>> extends AggregationFunction<X> {
public static final String NAME = "max";
public GREATEST(QueryBuilderImpl queryBuilder, Expression<X> expression) {
super( queryBuilder, expression.getJavaType(), NAME , expression);
}
}
}

View File

@ -1,42 +0,0 @@
/*
* Copyright (c) 2009, 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.
*
* 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.ejb.criteria.expression.function;
import javax.persistence.criteria.Expression;
import org.hibernate.ejb.criteria.QueryBuilderImpl;
/**
* Implementation of a <tt>AVG</tt> function providing convenience in construction.
* <p/>
* Parameterized as {@link Double} because thats what JPA states that the return
* from <tt>AVG</tt> should be.
*
* @author Steve Ebersole
*/
public class AverageAggregrateFunction extends BasicFunctionExpression<Double> {
public AverageAggregrateFunction(
QueryBuilderImpl queryBuilder,
Expression<? extends Number> expression) {
super( queryBuilder, Double.class, "avg", expression );
}
}

View File

@ -21,6 +21,7 @@
*/ */
package org.hibernate.ejb.criteria.expression.function; package org.hibernate.ejb.criteria.expression.function;
import java.util.ArrayList;
import org.hibernate.ejb.criteria.expression.*; import org.hibernate.ejb.criteria.expression.*;
import java.util.List; import java.util.List;
import java.util.Arrays; import java.util.Arrays;
@ -33,7 +34,7 @@ import org.hibernate.ejb.criteria.QueryBuilderImpl;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class BasicFunctionExpression<X> extends ExpressionImpl<X> implements Expression<X> { public class BasicFunctionExpression<X> extends ExpressionImpl<X> implements FunctionExpression<X> {
private final String functionName; private final String functionName;
private final List<Expression<?>> argumentExpressions; private final List<Expression<?>> argumentExpressions;
@ -57,10 +58,27 @@ public class BasicFunctionExpression<X> extends ExpressionImpl<X> implements Exp
this.argumentExpressions = Arrays.asList( argumentExpressions ); this.argumentExpressions = Arrays.asList( argumentExpressions );
} }
protected static List<Expression<?>> wrapAsLiterals(QueryBuilderImpl queryBuilder, Object... literalArguments) {
List<Expression<?>> arguments = new ArrayList<Expression<?>>( properSize( literalArguments.length) );
for ( Object o : literalArguments ) {
arguments.add( new LiteralExpression( queryBuilder, o ) );
}
return arguments;
}
protected static int properSize(int number) {
return number + (int)( number*.75 ) + 1;
}
public String getFunctionName() { public String getFunctionName() {
return functionName; return functionName;
} }
public boolean isAggregation() {
return false;
}
public List<Expression<?>> getArgumentExpressions() { public List<Expression<?>> getArgumentExpressions() {
return argumentExpressions; return argumentExpressions;
} }

View File

@ -49,6 +49,10 @@ public class CastFunction<T,Y> extends ExpressionImpl<T> implements FunctionExpr
return CAST_NAME; return CAST_NAME;
} }
public boolean isAggregation() {
return false;
}
public ExpressionImpl<Y> getCastSource() { public ExpressionImpl<Y> getCastSource() {
return castSource; return castSource;
} }

View File

@ -31,5 +31,17 @@ import javax.persistence.criteria.Expression;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface FunctionExpression<T> extends Expression<T> { public interface FunctionExpression<T> extends Expression<T> {
/**
* Retrieve the name of the function.
*
* @return The function name.
*/
public String getFunctionName(); public String getFunctionName();
/**
* Is this function a value aggregator (like a <tt>COUNT</tt> or <tt>MAX</tt> function e.g.)?
*
* @return True if this functions does aggregation.
*/
public boolean isAggregation();
} }

View File

@ -1,42 +0,0 @@
/*
* Copyright (c) 2009, 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.
*
* 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.ejb.criteria.expression.function;
import javax.persistence.criteria.Expression;
import org.hibernate.ejb.criteria.QueryBuilderImpl;
/**
* Implementation of a <tt>SUM</tt> function providing convenience in construction.
* <p/>
* Parameterized as {@link Number N extends Number} because thats what JPA states
* that the return from <tt>SUM</tt> should be.
*
* @author Steve Ebersole
*/
public class SumAggregateFunction<N extends Number> extends BasicFunctionExpression<N> {
public SumAggregateFunction(
QueryBuilderImpl queryBuilder,
Expression<N> expression) {
super( queryBuilder, expression.getJavaType(), "sum", expression );
}
}