HHH-5212 - Alter SQLFunction contract to be more flexible
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@20097 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
fbe7d325e2
commit
217898d8aa
|
@ -72,9 +72,9 @@ public class AggregateProjection extends SimpleProjection {
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery)
|
public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||||
throws HibernateException {
|
|
||||||
final String functionFragment = getFunction( criteriaQuery ).render(
|
final String functionFragment = getFunction( criteriaQuery ).render(
|
||||||
|
criteriaQuery.getType( criteria, getPropertyName() ),
|
||||||
buildFunctionParameterList( criteria, criteriaQuery ),
|
buildFunctionParameterList( criteria, criteriaQuery ),
|
||||||
criteriaQuery.getFactory()
|
criteriaQuery.getFactory()
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* 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
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.criterion;
|
package org.hibernate.criterion;
|
||||||
|
|
||||||
|
@ -50,7 +49,7 @@ public class RowCountProjection extends SimpleProjection {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
|
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||||
return getFunction( criteriaQuery ).render( ARGS, criteriaQuery.getFactory() )
|
return getFunction( criteriaQuery ).render( null, ARGS, criteriaQuery.getFactory() )
|
||||||
+ " as y" + position + '_';
|
+ " as y" + position + '_';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,26 +32,28 @@ import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
|
||||||
import org.hibernate.QueryException;
|
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.function.AvgFunction;
|
|
||||||
import org.hibernate.dialect.function.CastFunction;
|
import org.hibernate.dialect.function.CastFunction;
|
||||||
import org.hibernate.dialect.function.SQLFunction;
|
import org.hibernate.dialect.function.SQLFunction;
|
||||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||||
|
import org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
import org.hibernate.dialect.lock.*;
|
import org.hibernate.dialect.lock.LockingStrategy;
|
||||||
import org.hibernate.engine.Mapping;
|
import org.hibernate.dialect.lock.OptimisticForceIncrementLockingStrategy;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.dialect.lock.OptimisticLockingStrategy;
|
||||||
|
import org.hibernate.dialect.lock.PessimisticForceIncrementLockingStrategy;
|
||||||
|
import org.hibernate.dialect.lock.PessimisticReadSelectLockingStrategy;
|
||||||
|
import org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy;
|
||||||
|
import org.hibernate.dialect.lock.SelectLockingStrategy;
|
||||||
import org.hibernate.exception.SQLExceptionConverter;
|
import org.hibernate.exception.SQLExceptionConverter;
|
||||||
import org.hibernate.exception.SQLStateConverter;
|
import org.hibernate.exception.SQLStateConverter;
|
||||||
import org.hibernate.exception.ViolatedConstraintNameExtracter;
|
import org.hibernate.exception.ViolatedConstraintNameExtracter;
|
||||||
|
@ -63,9 +65,8 @@ import org.hibernate.persister.entity.Lockable;
|
||||||
import org.hibernate.sql.ANSICaseFragment;
|
import org.hibernate.sql.ANSICaseFragment;
|
||||||
import org.hibernate.sql.ANSIJoinFragment;
|
import org.hibernate.sql.ANSIJoinFragment;
|
||||||
import org.hibernate.sql.CaseFragment;
|
import org.hibernate.sql.CaseFragment;
|
||||||
import org.hibernate.sql.JoinFragment;
|
|
||||||
import org.hibernate.sql.ForUpdateFragment;
|
import org.hibernate.sql.ForUpdateFragment;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.sql.JoinFragment;
|
||||||
import org.hibernate.util.ReflectHelper;
|
import org.hibernate.util.ReflectHelper;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
|
|
||||||
|
@ -93,110 +94,11 @@ public abstract class Dialect {
|
||||||
public static final String QUOTE = "`\"[";
|
public static final String QUOTE = "`\"[";
|
||||||
public static final String CLOSED_QUOTE = "`\"]";
|
public static final String CLOSED_QUOTE = "`\"]";
|
||||||
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
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 AvgFunction() );
|
|
||||||
|
|
||||||
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 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final TypeNames typeNames = new TypeNames();
|
private final TypeNames typeNames = new TypeNames();
|
||||||
private final TypeNames hibernateTypeNames = new TypeNames();
|
private final TypeNames hibernateTypeNames = new TypeNames();
|
||||||
|
|
||||||
private final Properties properties = new Properties();
|
private final Properties properties = new Properties();
|
||||||
private final Map sqlFunctions = new HashMap();
|
private final Map<String, SQLFunction> sqlFunctions = new HashMap<String, SQLFunction>();
|
||||||
private final Set sqlKeywords = new HashSet();
|
private final Set sqlKeywords = new HashSet();
|
||||||
|
|
||||||
|
|
||||||
|
@ -204,7 +106,7 @@ public abstract class Dialect {
|
||||||
|
|
||||||
protected Dialect() {
|
protected Dialect() {
|
||||||
log.info( "Using dialect: " + this );
|
log.info( "Using dialect: " + this );
|
||||||
sqlFunctions.putAll( STANDARD_AGGREGATE_FUNCTIONS );
|
StandardAnsiSqlAggregationFunctions.primeFunctionMap( sqlFunctions );
|
||||||
|
|
||||||
// standard sql92 functions (can be overridden by subclasses)
|
// standard sql92 functions (can be overridden by subclasses)
|
||||||
registerFunction( "substring", new SQLFunctionTemplate( Hibernate.STRING, "substring(?1, ?2, ?3)" ) );
|
registerFunction( "substring", new SQLFunctionTemplate( Hibernate.STRING, "substring(?1, ?2, ?3)" ) );
|
||||||
|
|
|
@ -43,13 +43,6 @@ import java.util.ArrayList;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractAnsiTrimEmulationFunction implements SQLFunction {
|
public abstract class AbstractAnsiTrimEmulationFunction implements SQLFunction {
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public final Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
|
||||||
return Hibernate.STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
@ -67,7 +60,14 @@ public abstract class AbstractAnsiTrimEmulationFunction implements SQLFunction {
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public final String render(List args, SessionFactoryImplementor factory) throws QueryException {
|
public final Type getReturnType(Type argumentType, Mapping mapping) throws QueryException {
|
||||||
|
return Hibernate.STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public final String render(Type argumentType, List args, SessionFactoryImplementor factory) throws QueryException {
|
||||||
// According to both the ANSI-SQL and JPA specs, trim takes a variable number of parameters between 1 and 4.
|
// According to both the ANSI-SQL and JPA specs, trim takes a variable number of parameters between 1 and 4.
|
||||||
// at least one paramer (trimSource) is required. From the SQL spec:
|
// at least one paramer (trimSource) is required. From the SQL spec:
|
||||||
//
|
//
|
||||||
|
@ -87,12 +87,12 @@ public abstract class AbstractAnsiTrimEmulationFunction implements SQLFunction {
|
||||||
if ( args.size() == 1 ) {
|
if ( args.size() == 1 ) {
|
||||||
// we have the form: trim(trimSource)
|
// we have the form: trim(trimSource)
|
||||||
// so we trim leading and trailing spaces
|
// so we trim leading and trailing spaces
|
||||||
return resolveBothSpaceTrimFunction().render( args, factory ); // EARLY EXIT!!!!
|
return resolveBothSpaceTrimFunction().render( argumentType, args, factory ); // EARLY EXIT!!!!
|
||||||
}
|
}
|
||||||
else if ( "from".equalsIgnoreCase( ( String ) args.get( 0 ) ) ) {
|
else if ( "from".equalsIgnoreCase( ( String ) args.get( 0 ) ) ) {
|
||||||
// we have the form: trim(from trimSource).
|
// we have the form: trim(from trimSource).
|
||||||
// This is functionally equivalent to trim(trimSource)
|
// This is functionally equivalent to trim(trimSource)
|
||||||
return resolveBothSpaceTrimFromFunction().render( args, factory ); // EARLY EXIT!!!!
|
return resolveBothSpaceTrimFromFunction().render( argumentType, args, factory ); // EARLY EXIT!!!!
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// otherwise, a trim-specification and/or a trim-character
|
// otherwise, a trim-specification and/or a trim-character
|
||||||
|
@ -145,24 +145,24 @@ public abstract class AbstractAnsiTrimEmulationFunction implements SQLFunction {
|
||||||
|
|
||||||
if ( trimCharacter.equals( "' '" ) ) {
|
if ( trimCharacter.equals( "' '" ) ) {
|
||||||
if ( leading && trailing ) {
|
if ( leading && trailing ) {
|
||||||
return resolveBothSpaceTrimFunction().render( argsToUse, factory );
|
return resolveBothSpaceTrimFunction().render( argumentType, argsToUse, factory );
|
||||||
}
|
}
|
||||||
else if ( leading ) {
|
else if ( leading ) {
|
||||||
return resolveLeadingSpaceTrimFunction().render( argsToUse, factory );
|
return resolveLeadingSpaceTrimFunction().render( argumentType, argsToUse, factory );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return resolveTrailingSpaceTrimFunction().render( argsToUse, factory );
|
return resolveTrailingSpaceTrimFunction().render( argumentType, argsToUse, factory );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( leading && trailing ) {
|
if ( leading && trailing ) {
|
||||||
return resolveBothTrimFunction().render( argsToUse, factory );
|
return resolveBothTrimFunction().render( argumentType, argsToUse, factory );
|
||||||
}
|
}
|
||||||
else if ( leading ) {
|
else if ( leading ) {
|
||||||
return resolveLeadingTrimFunction().render( argsToUse, factory );
|
return resolveLeadingTrimFunction().render( argumentType, argsToUse, factory );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return resolveTrailingTrimFunction().render( argsToUse, factory );
|
return resolveTrailingTrimFunction().render( argumentType, argsToUse, factory );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ package org.hibernate.dialect.function;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines support for rendering according to ANSI SQL <tt>TRIM<//tt> function specification.
|
* Defines support for rendering according to ANSI SQL <tt>TRIM</tt> function specification.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.dialect.function;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hibernate.MappingException;
|
|
||||||
import org.hibernate.QueryException;
|
|
||||||
import org.hibernate.engine.Mapping;
|
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
|
||||||
import org.hibernate.type.DoubleType;
|
|
||||||
import org.hibernate.type.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The basic JPA spec compliant definition po<tt>AVG</tt> aggregation function.
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class AvgFunction implements SQLFunction {
|
|
||||||
public final 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( "multiple-column type in avg()" );
|
|
||||||
}
|
|
||||||
return DoubleType.INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean hasArguments() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean hasParenthesesIfNoArguments() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String render(List args, SessionFactoryImplementor factory) throws QueryException {
|
|
||||||
return "avg(" + args.get( 0 ) + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String toString() {
|
|
||||||
return "avg";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,32 +23,29 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect.function;
|
package org.hibernate.dialect.function;
|
||||||
|
|
||||||
import java.util.List;
|
import java.sql.Types;
|
||||||
|
|
||||||
import org.hibernate.QueryException;
|
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some databases strictly return the type of the of the aggregation value for <tt>AVG</tt> which is
|
* Some databases strictly return the type of the of the aggregation value for <tt>AVG</tt> which is
|
||||||
* problematic in the case of averaging integers because the decimals will be dropped. The usual workaround
|
* problematic in the case of averaging integers because the decimals will be dropped. The usual workaround
|
||||||
* is to cast the integer argument as some form of double/decimal.
|
* is to cast the integer argument as some form of double/decimal.
|
||||||
* <p/>
|
|
||||||
* A downside to this approach is that we always wrap the avg() argument in a cast even though we may not need or want
|
|
||||||
* to. A more full-featured solution would be defining {@link SQLFunction} such that we render based on the first
|
|
||||||
* argument; essentially have {@link SQLFunction} describe the basic metadata about the function and merge the
|
|
||||||
* {@link SQLFunction#getReturnType} and {@link SQLFunction#render} methods into a
|
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class AvgWithArgumentCastFunction extends AvgFunction {
|
public class AvgWithArgumentCastFunction extends StandardAnsiSqlAggregationFunctions.AvgFunction {
|
||||||
private final TemplateRenderer renderer;
|
private final String castType;
|
||||||
|
|
||||||
public AvgWithArgumentCastFunction(String castType) {
|
public AvgWithArgumentCastFunction(String castType) {
|
||||||
renderer = new TemplateRenderer( "avg(cast(?1 as " + castType + "))" );
|
this.castType = castType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String render(List args, SessionFactoryImplementor factory) throws QueryException {
|
protected String renderArgument(String argument, int firstArgumentJdbcType) {
|
||||||
return renderer.render( args, factory );
|
if ( firstArgumentJdbcType == Types.DOUBLE || firstArgumentJdbcType == Types.FLOAT ) {
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "cast(" + argument + " as " + castType + ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* 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
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect.function;
|
package org.hibernate.dialect.function;
|
||||||
|
|
||||||
|
@ -30,7 +29,6 @@ import org.hibernate.QueryException;
|
||||||
import org.hibernate.engine.Mapping;
|
import org.hibernate.engine.Mapping;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
import org.hibernate.type.TypeFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ANSI-SQL style <tt>cast(foo as type)</tt> where the type is
|
* ANSI-SQL style <tt>cast(foo as type)</tt> where the type is
|
||||||
|
@ -38,11 +36,6 @@ import org.hibernate.type.TypeFactory;
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public class CastFunction implements SQLFunction {
|
public class CastFunction implements SQLFunction {
|
||||||
|
|
||||||
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
|
||||||
return columnType; //note there is a wierd implementation in the client side
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasArguments() {
|
public boolean hasArguments() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +44,11 @@ public class CastFunction implements SQLFunction {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String render(List args, SessionFactoryImplementor factory) throws QueryException {
|
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
||||||
|
return columnType; // this is really just a guess, unless the caller properly identifies the 'type' argument here
|
||||||
|
}
|
||||||
|
|
||||||
|
public String render(Type columnType, List args, SessionFactoryImplementor factory) throws QueryException {
|
||||||
if ( args.size()!=2 ) {
|
if ( args.size()!=2 ) {
|
||||||
throw new QueryException("cast() requires two arguments");
|
throw new QueryException("cast() requires two arguments");
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,11 +37,6 @@ import org.hibernate.type.Type;
|
||||||
* @author Nathan Moon
|
* @author Nathan Moon
|
||||||
*/
|
*/
|
||||||
public class CharIndexFunction implements SQLFunction {
|
public class CharIndexFunction implements SQLFunction {
|
||||||
|
|
||||||
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
|
||||||
return Hibernate.INTEGER;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasArguments() {
|
public boolean hasArguments() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +45,11 @@ public class CharIndexFunction implements SQLFunction {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String render(List args, SessionFactoryImplementor factory) throws QueryException {
|
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
||||||
|
return Hibernate.INTEGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String render(Type columnType, List args, SessionFactoryImplementor factory) throws QueryException {
|
||||||
boolean threeArgs = args.size() > 2;
|
boolean threeArgs = args.size() > 2;
|
||||||
Object pattern = args.get(0);
|
Object pattern = args.get(0);
|
||||||
Object string = args.get(1);
|
Object string = args.get(1);
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* 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
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect.function;
|
package org.hibernate.dialect.function;
|
||||||
|
|
||||||
|
@ -39,10 +38,6 @@ import org.hibernate.type.Type;
|
||||||
*/
|
*/
|
||||||
public class ConvertFunction implements SQLFunction {
|
public class ConvertFunction implements SQLFunction {
|
||||||
|
|
||||||
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
|
||||||
return Hibernate.STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasArguments() {
|
public boolean hasArguments() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +46,11 @@ public class ConvertFunction implements SQLFunction {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String render(List args, SessionFactoryImplementor factory) throws QueryException {
|
public Type getReturnType(Type firstArgumentType, Mapping mapping) throws QueryException {
|
||||||
|
return Hibernate.STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) throws QueryException {
|
||||||
if ( args.size() != 2 && args.size() != 3 ) {
|
if ( args.size() != 2 && args.size() != 3 ) {
|
||||||
throw new QueryException( "convert() requires two or three arguments" );
|
throw new QueryException( "convert() requires two or three arguments" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,15 +48,6 @@ import org.hibernate.type.Type;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class DerbyConcatFunction implements SQLFunction {
|
public class DerbyConcatFunction implements SQLFunction {
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
* <p/>
|
|
||||||
* Here we always return {@link Hibernate#STRING}.
|
|
||||||
*/
|
|
||||||
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
|
||||||
return Hibernate.STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@ -75,6 +66,15 @@ public class DerbyConcatFunction implements SQLFunction {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p/>
|
||||||
|
* Here we always return {@link Hibernate#STRING}.
|
||||||
|
*/
|
||||||
|
public Type getReturnType(Type argumentType, Mapping mapping) throws QueryException {
|
||||||
|
return Hibernate.STRING;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@ -82,10 +82,10 @@ public class DerbyConcatFunction implements SQLFunction {
|
||||||
* this method. The logic here says that if not all the incoming args are dynamic parameters
|
* this method. The logic here says that if not all the incoming args are dynamic parameters
|
||||||
* (i.e. <tt>?</tt>) then we simply use the Derby concat operator (<tt>||</tt>) on the unchanged
|
* (i.e. <tt>?</tt>) then we simply use the Derby concat operator (<tt>||</tt>) on the unchanged
|
||||||
* arg elements. However, if all the args are dynamic parameters, then we need to wrap the individual
|
* arg elements. However, if all the args are dynamic parameters, then we need to wrap the individual
|
||||||
* arg elements in <tt>cast</tt> function calls, use the concantenation operator on the <tt>cast</tt>
|
* arg elements in <tt>cast</tt> function calls, use the concatenation operator on the <tt>cast</tt>
|
||||||
* returns, and then wrap that whole thing in a call to the Derby <tt>varchar</tt> function.
|
* returns, and then wrap that whole thing in a call to the Derby <tt>varchar</tt> function.
|
||||||
*/
|
*/
|
||||||
public String render(List args, SessionFactoryImplementor factory) throws QueryException {
|
public String render(Type argumentType, List args, SessionFactoryImplementor factory) throws QueryException {
|
||||||
boolean areAllArgsParams = true;
|
boolean areAllArgsParams = true;
|
||||||
Iterator itr = args.iterator();
|
Iterator itr = args.iterator();
|
||||||
while ( itr.hasNext() ) {
|
while ( itr.hasNext() ) {
|
||||||
|
|
|
@ -51,10 +51,6 @@ public class NoArgSQLFunction implements SQLFunction {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
|
||||||
return returnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasArguments() {
|
public boolean hasArguments() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +59,11 @@ public class NoArgSQLFunction implements SQLFunction {
|
||||||
return hasParenthesesIfNoArguments;
|
return hasParenthesesIfNoArguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String render(List args, SessionFactoryImplementor factory) throws QueryException {
|
public Type getReturnType(Type argumentType, Mapping mapping) throws QueryException {
|
||||||
|
return returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String render(Type argumentType, List args, SessionFactoryImplementor factory) throws QueryException {
|
||||||
if ( args.size()>0 ) {
|
if ( args.size()>0 ) {
|
||||||
throw new QueryException("function takes no arguments: " + name);
|
throw new QueryException("function takes no arguments: " + name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,16 +32,11 @@ import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emulation of <tt>coalesce()</tt> on Oracle, using multiple
|
* Emulation of <tt>coalesce()</tt> on Oracle, using multiple <tt>nvl()</tt> calls
|
||||||
* <tt>nvl()</tt> calls
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public class NvlFunction implements SQLFunction {
|
public class NvlFunction implements SQLFunction {
|
||||||
|
|
||||||
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
|
||||||
return columnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasArguments() {
|
public boolean hasArguments() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -50,14 +45,20 @@ public class NvlFunction implements SQLFunction {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String render(List args, SessionFactoryImplementor factory) throws QueryException {
|
public Type getReturnType(Type argumentType, Mapping mapping) throws QueryException {
|
||||||
|
return argumentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String render(Type argumentType, List args, SessionFactoryImplementor factory) throws QueryException {
|
||||||
int lastIndex = args.size()-1;
|
int lastIndex = args.size()-1;
|
||||||
Object last = args.remove(lastIndex);
|
Object last = args.remove(lastIndex);
|
||||||
if ( lastIndex==0 ) return last.toString();
|
if ( lastIndex==0 ) {
|
||||||
|
return last.toString();
|
||||||
|
}
|
||||||
Object secondLast = args.get(lastIndex-1);
|
Object secondLast = args.get(lastIndex-1);
|
||||||
String nvl = "nvl(" + secondLast + ", " + last + ")";
|
String nvl = "nvl(" + secondLast + ", " + last + ")";
|
||||||
args.set(lastIndex-1, nvl);
|
args.set(lastIndex-1, nvl);
|
||||||
return render(args, factory);
|
return render( argumentType, args, factory );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* 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
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect.function;
|
package org.hibernate.dialect.function;
|
||||||
|
|
||||||
|
@ -37,11 +36,6 @@ import org.hibernate.type.Type;
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public class PositionSubstringFunction implements SQLFunction {
|
public class PositionSubstringFunction implements SQLFunction {
|
||||||
|
|
||||||
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
|
||||||
return Hibernate.INTEGER;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasArguments() {
|
public boolean hasArguments() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +44,11 @@ public class PositionSubstringFunction implements SQLFunction {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String render(List args, SessionFactoryImplementor factory) throws QueryException {
|
public Type getReturnType(Type firstArgumentType, Mapping mapping) throws QueryException {
|
||||||
|
return Hibernate.INTEGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) throws QueryException {
|
||||||
boolean threeArgs = args.size() > 2;
|
boolean threeArgs = args.size() > 2;
|
||||||
Object pattern = args.get(0);
|
Object pattern = args.get(0);
|
||||||
Object string = args.get(1);
|
Object string = args.get(1);
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* 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
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect.function;
|
package org.hibernate.dialect.function;
|
||||||
|
|
||||||
|
@ -40,6 +39,7 @@ import org.hibernate.type.Type;
|
||||||
* provide details required for processing of the function.
|
* provide details required for processing of the function.
|
||||||
*
|
*
|
||||||
* @author David Channon
|
* @author David Channon
|
||||||
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SQLFunction {
|
public interface SQLFunction {
|
||||||
/**
|
/**
|
||||||
|
@ -50,40 +50,41 @@ public interface SQLFunction {
|
||||||
public boolean hasArguments();
|
public boolean hasArguments();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If there are no arguments, are parens required?
|
* If there are no arguments, are parentheses required?
|
||||||
*
|
*
|
||||||
* @return True if a no-arg call of this function requires parentheses.
|
* @return True if a no-arg call of this function requires parentheses.
|
||||||
*/
|
*/
|
||||||
public boolean hasParenthesesIfNoArguments();
|
public boolean hasParenthesesIfNoArguments();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The return type of the function. May be either a concrete type which
|
* The return type of the function. May be either a concrete type which is preset, or variable depending upon
|
||||||
* is preset, or variable depending upon the type of the first function
|
* the type of the first function argument.
|
||||||
* argument.
|
* <p/>
|
||||||
|
* Note, the 'firstArgumentType' parameter should match the one passed into {@link #render}
|
||||||
*
|
*
|
||||||
* @param columnType the type of the first argument
|
* @param firstArgumentType The type of the first argument
|
||||||
* @param mapping The mapping source.
|
* @param mapping The mapping source.
|
||||||
*
|
*
|
||||||
* @return The type to be expected as a return.
|
* @return The type to be expected as a return.
|
||||||
*
|
*
|
||||||
* @throws org.hibernate.QueryException Indicates an issue resolving the return type.
|
* @throws org.hibernate.QueryException Indicates an issue resolving the return type.
|
||||||
*
|
|
||||||
* @deprecated See http://opensource.atlassian.com/projects/hibernate/browse/HHH-5212
|
|
||||||
*/
|
*/
|
||||||
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException;
|
public Type getReturnType(Type firstArgumentType, Mapping mapping) throws QueryException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the function call as SQL fragment.
|
* Render the function call as SQL fragment.
|
||||||
|
* <p/>
|
||||||
|
* Note, the 'firstArgumentType' parameter should match the one passed into {@link #getReturnType}
|
||||||
*
|
*
|
||||||
* @param args The function arguments
|
* @param firstArgumentType The type of the first argument
|
||||||
|
* @param arguments The function arguments
|
||||||
* @param factory The SessionFactory
|
* @param factory The SessionFactory
|
||||||
*
|
*
|
||||||
* @return The rendered function call
|
* @return The rendered function call
|
||||||
*
|
*
|
||||||
* @throws org.hibernate.QueryException Indicates a problem rendering the
|
* @throws org.hibernate.QueryException Indicates a problem rendering the
|
||||||
* function call.
|
* function call.
|
||||||
*
|
|
||||||
* @deprecated See http://opensource.atlassian.com/projects/hibernate/browse/HHH-5212
|
|
||||||
*/
|
*/
|
||||||
public String render(List args, SessionFactoryImplementor factory) throws QueryException;
|
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor factory) throws QueryException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,6 @@ import java.util.List;
|
||||||
* parameters with '?' followed by parameter's index (first index is 1).
|
* parameters with '?' followed by parameter's index (first index is 1).
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
|
* @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
|
||||||
* @version <tt>$Revision: 6608 $</tt>
|
|
||||||
*/
|
*/
|
||||||
public class SQLFunctionTemplate implements SQLFunction {
|
public class SQLFunctionTemplate implements SQLFunction {
|
||||||
private final Type type;
|
private final Type type;
|
||||||
|
@ -59,14 +58,14 @@ public class SQLFunctionTemplate implements SQLFunction {
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public String render(List args, SessionFactoryImplementor factory) {
|
public String render(Type argumentType, List args, SessionFactoryImplementor factory) {
|
||||||
return renderer.render( args, factory );
|
return renderer.render( args, factory );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
public Type getReturnType(Type argumentType, Mapping mapping) throws QueryException {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
/*
|
||||||
|
* 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.dialect.function;
|
||||||
|
|
||||||
|
import java.sql.Types;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.QueryException;
|
||||||
|
import org.hibernate.engine.Mapping;
|
||||||
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO : javadoc
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class StandardAnsiSqlAggregationFunctions {
|
||||||
|
/**
|
||||||
|
* Definition of a standard ANSI SQL compliant <tt>COUNT</tt> function
|
||||||
|
*/
|
||||||
|
public static class CountFunction extends StandardSQLFunction {
|
||||||
|
public static final CountFunction INSTANCE = new CountFunction();
|
||||||
|
|
||||||
|
public CountFunction() {
|
||||||
|
super( "count", Hibernate.LONG );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor factory) {
|
||||||
|
if ( arguments.size() > 1 ) {
|
||||||
|
if ( "distinct".equalsIgnoreCase( arguments.get( 0 ).toString() ) ) {
|
||||||
|
return renderCountDistinct( arguments );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.render( firstArgumentType, arguments, factory );
|
||||||
|
}
|
||||||
|
|
||||||
|
private String renderCountDistinct(List arguments) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
buffer.append( "count(distinct " );
|
||||||
|
String sep = "";
|
||||||
|
Iterator itr = arguments.iterator();
|
||||||
|
itr.next(); // intentionally skip first
|
||||||
|
while ( itr.hasNext() ) {
|
||||||
|
buffer.append( sep )
|
||||||
|
.append( itr.next() );
|
||||||
|
sep = ", ";
|
||||||
|
}
|
||||||
|
return buffer.append( ")" ).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Definition of a standard ANSI SQL compliant <tt>AVG</tt> function
|
||||||
|
*/
|
||||||
|
public static class AvgFunction extends StandardSQLFunction {
|
||||||
|
public static final AvgFunction INSTANCE = new AvgFunction();
|
||||||
|
|
||||||
|
public AvgFunction() {
|
||||||
|
super( "avg", Hibernate.DOUBLE );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor factory) throws QueryException {
|
||||||
|
int jdbcTypeCode = determineJdbcTypeCode( firstArgumentType, factory );
|
||||||
|
return render( jdbcTypeCode, arguments.get(0).toString(), factory );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final int determineJdbcTypeCode(Type firstArgumentType, SessionFactoryImplementor factory) throws QueryException {
|
||||||
|
try {
|
||||||
|
final int[] jdbcTypeCodes = firstArgumentType.sqlTypes( factory );
|
||||||
|
if ( jdbcTypeCodes.length != 1 ) {
|
||||||
|
throw new QueryException( "multiple-column type in avg()" );
|
||||||
|
}
|
||||||
|
return jdbcTypeCodes[0];
|
||||||
|
}
|
||||||
|
catch ( MappingException me ) {
|
||||||
|
throw new QueryException( me );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String render(int firstArgumentJdbcType, String argument, SessionFactoryImplementor factory) {
|
||||||
|
return "avg(" + renderArgument( argument, firstArgumentJdbcType ) + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String renderArgument(String argument, int firstArgumentJdbcType) {
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class MaxFunction extends StandardSQLFunction {
|
||||||
|
public static final MaxFunction INSTANCE = new MaxFunction();
|
||||||
|
|
||||||
|
public MaxFunction() {
|
||||||
|
super( "max" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MinFunction extends StandardSQLFunction {
|
||||||
|
public static final MinFunction INSTANCE = new MinFunction();
|
||||||
|
|
||||||
|
public MinFunction() {
|
||||||
|
super( "min" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class SumFunction extends StandardSQLFunction {
|
||||||
|
public static final SumFunction INSTANCE = new SumFunction();
|
||||||
|
|
||||||
|
public SumFunction() {
|
||||||
|
super( "sum" );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final int determineJdbcTypeCode(Type type, Mapping mapping) throws QueryException {
|
||||||
|
try {
|
||||||
|
final int[] jdbcTypeCodes = type.sqlTypes( mapping );
|
||||||
|
if ( jdbcTypeCodes.length != 1 ) {
|
||||||
|
throw new QueryException( "multiple-column type in sum()" );
|
||||||
|
}
|
||||||
|
return jdbcTypeCodes[0];
|
||||||
|
}
|
||||||
|
catch ( MappingException me ) {
|
||||||
|
throw new QueryException( me );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getReturnType(Type firstArgumentType, Mapping mapping) {
|
||||||
|
final int jdbcType = determineJdbcTypeCode( firstArgumentType, mapping );
|
||||||
|
|
||||||
|
// First allow the actual type to control the return value; the underlying sqltype could
|
||||||
|
// actually be different
|
||||||
|
if ( firstArgumentType == Hibernate.BIG_INTEGER ) {
|
||||||
|
return Hibernate.BIG_INTEGER;
|
||||||
|
}
|
||||||
|
else if ( firstArgumentType == Hibernate.BIG_DECIMAL ) {
|
||||||
|
return Hibernate.BIG_DECIMAL;
|
||||||
|
}
|
||||||
|
else if ( firstArgumentType == Hibernate.LONG
|
||||||
|
|| firstArgumentType == Hibernate.SHORT
|
||||||
|
|| firstArgumentType == Hibernate.INTEGER ) {
|
||||||
|
return Hibernate.LONG;
|
||||||
|
}
|
||||||
|
else if ( firstArgumentType == Hibernate.FLOAT || firstArgumentType == Hibernate.DOUBLE) {
|
||||||
|
return Hibernate.DOUBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally use the jdbcType if == on Hibernate types did not find a match.
|
||||||
|
//
|
||||||
|
// IMPL NOTE : we do not match on Types.NUMERIC because it could be either, so we fall-through to the
|
||||||
|
// first argument type
|
||||||
|
if ( jdbcType == Types.FLOAT
|
||||||
|
|| jdbcType == Types.DOUBLE
|
||||||
|
|| jdbcType == Types.DECIMAL
|
||||||
|
|| jdbcType == Types.REAL) {
|
||||||
|
return Hibernate.DOUBLE;
|
||||||
|
}
|
||||||
|
else if ( jdbcType == Types.BIGINT
|
||||||
|
|| jdbcType == Types.INTEGER
|
||||||
|
|| jdbcType == Types.SMALLINT
|
||||||
|
|| jdbcType == Types.TINYINT ) {
|
||||||
|
return Hibernate.LONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// as a last resort, return the type of the first argument
|
||||||
|
return firstArgumentType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void primeFunctionMap(Map<String, SQLFunction> functionMap) {
|
||||||
|
functionMap.put( AvgFunction.INSTANCE.getName(), AvgFunction.INSTANCE );
|
||||||
|
functionMap.put( CountFunction.INSTANCE.getName(), CountFunction.INSTANCE );
|
||||||
|
functionMap.put( MaxFunction.INSTANCE.getName(), MaxFunction.INSTANCE );
|
||||||
|
functionMap.put( MinFunction.INSTANCE.getName(), MinFunction.INSTANCE );
|
||||||
|
functionMap.put( SumFunction.INSTANCE.getName(), SumFunction.INSTANCE );
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,8 +45,8 @@ public class StandardJDBCEscapeFunction extends StandardSQLFunction {
|
||||||
super( name, typeValue );
|
super( name, typeValue );
|
||||||
}
|
}
|
||||||
|
|
||||||
public String render(List args, SessionFactoryImplementor factory) {
|
public String render(Type argumentType, List args, SessionFactoryImplementor factory) {
|
||||||
return "{fn " + super.render( args, factory ) + "}";
|
return "{fn " + super.render( argumentType, args, factory ) + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* 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
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect.function;
|
package org.hibernate.dialect.function;
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ import org.hibernate.type.Type;
|
||||||
*/
|
*/
|
||||||
public class StandardSQLFunction implements SQLFunction {
|
public class StandardSQLFunction implements SQLFunction {
|
||||||
private final String name;
|
private final String name;
|
||||||
private final Type type;
|
private final Type registeredType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a standard SQL function definition with a variable return type;
|
* Construct a standard SQL function definition with a variable return type;
|
||||||
|
@ -60,11 +59,11 @@ public class StandardSQLFunction implements SQLFunction {
|
||||||
* Construct a standard SQL function definition with a static return type.
|
* Construct a standard SQL function definition with a static return type.
|
||||||
*
|
*
|
||||||
* @param name The name of the function.
|
* @param name The name of the function.
|
||||||
* @param type The static return type.
|
* @param registeredType The static return type.
|
||||||
*/
|
*/
|
||||||
public StandardSQLFunction(String name, Type type) {
|
public StandardSQLFunction(String name, Type registeredType) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.type = type;
|
this.registeredType = registeredType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,16 +82,7 @@ public class StandardSQLFunction implements SQLFunction {
|
||||||
* not static.
|
* not static.
|
||||||
*/
|
*/
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return registeredType;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public Type getReturnType(Type columnType, Mapping mapping) {
|
|
||||||
// return the concrete type, or the underlying type if a concrete type
|
|
||||||
// was not specified
|
|
||||||
return type == null ? columnType : type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -112,12 +102,19 @@ public class StandardSQLFunction implements SQLFunction {
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public String render(List args, SessionFactoryImplementor factory) {
|
public Type getReturnType(Type firstArgumentType, Mapping mapping) {
|
||||||
|
return registeredType == null ? firstArgumentType : registeredType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor sessionFactory) {
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
buf.append( name ).append( '(' );
|
buf.append( name ).append( '(' );
|
||||||
for ( int i = 0; i < args.size(); i++ ) {
|
for ( int i = 0; i < arguments.size(); i++ ) {
|
||||||
buf.append( args.get( i ) );
|
buf.append( arguments.get( i ) );
|
||||||
if ( i < args.size() - 1 ) {
|
if ( i < arguments.size() - 1 ) {
|
||||||
buf.append( ", " );
|
buf.append( ", " );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,4 +124,5 @@ public class StandardSQLFunction implements SQLFunction {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,10 +37,6 @@ import org.hibernate.type.Type;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public abstract class TrimFunctionTemplate implements SQLFunction {
|
public abstract class TrimFunctionTemplate implements SQLFunction {
|
||||||
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
|
||||||
return Hibernate.STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasArguments() {
|
public boolean hasArguments() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +45,11 @@ public abstract class TrimFunctionTemplate implements SQLFunction {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String render(List args, SessionFactoryImplementor factory) throws QueryException {
|
public Type getReturnType(Type firstArgument, Mapping mapping) throws QueryException {
|
||||||
|
return Hibernate.STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String render(Type firstArgument, List args, SessionFactoryImplementor factory) throws QueryException {
|
||||||
final Options options = new Options();
|
final Options options = new Options();
|
||||||
final String trimSource;
|
final String trimSource;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* 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
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect.function;
|
package org.hibernate.dialect.function;
|
||||||
|
|
||||||
|
@ -32,8 +31,7 @@ import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support for slightly more general templating than {@link StandardSQLFunction},
|
* Support for slightly more general templating than {@link StandardSQLFunction}, with an unlimited number of arguments.
|
||||||
* with an unlimited number of arguments.
|
|
||||||
*
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
|
@ -41,20 +39,20 @@ public class VarArgsSQLFunction implements SQLFunction {
|
||||||
private final String begin;
|
private final String begin;
|
||||||
private final String sep;
|
private final String sep;
|
||||||
private final String end;
|
private final String end;
|
||||||
private final Type type;
|
private final Type registeredType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a VarArgsSQLFunction instance with a 'static' return type. An example of a 'static'
|
* Constructs a VarArgsSQLFunction instance with a 'static' return type. An example of a 'static'
|
||||||
* return type would be something like an <tt>UPPER</tt> function which is always returning
|
* return type would be something like an <tt>UPPER</tt> function which is always returning
|
||||||
* a SQL VARCHAR and thus a string type.
|
* a SQL VARCHAR and thus a string type.
|
||||||
*
|
*
|
||||||
* @param type The return type.
|
* @param registeredType The return type.
|
||||||
* @param begin The beginning of the function templating.
|
* @param begin The beginning of the function templating.
|
||||||
* @param sep The separator for each individual function argument.
|
* @param sep The separator for each individual function argument.
|
||||||
* @param end The end of the function templating.
|
* @param end The end of the function templating.
|
||||||
*/
|
*/
|
||||||
public VarArgsSQLFunction(Type type, String begin, String sep, String end) {
|
public VarArgsSQLFunction(Type registeredType, String begin, String sep, String end) {
|
||||||
this.type = type;
|
this.registeredType = registeredType;
|
||||||
this.begin = begin;
|
this.begin = begin;
|
||||||
this.sep = sep;
|
this.sep = sep;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
|
@ -70,19 +68,12 @@ public class VarArgsSQLFunction implements SQLFunction {
|
||||||
* @param sep The separator for each individual function argument.
|
* @param sep The separator for each individual function argument.
|
||||||
* @param end The end of the function templating.
|
* @param end The end of the function templating.
|
||||||
*
|
*
|
||||||
* @see #getReturnType Specifically, the 'columnType' argument is the 'dynamic' type.
|
* @see #getReturnType Specifically, the 'firstArgumentType' argument is the 'dynamic' type.
|
||||||
*/
|
*/
|
||||||
public VarArgsSQLFunction(String begin, String sep, String end) {
|
public VarArgsSQLFunction(String begin, String sep, String end) {
|
||||||
this( null, begin, sep, end );
|
this( null, begin, sep, end );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
|
|
||||||
return type == null ? columnType : type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@ -104,11 +95,15 @@ public class VarArgsSQLFunction implements SQLFunction {
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public String render(List args, SessionFactoryImplementor factory) throws QueryException {
|
public Type getReturnType(Type firstArgumentType, Mapping mapping) throws QueryException {
|
||||||
|
return registeredType == null ? firstArgumentType : registeredType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor factory) {
|
||||||
StringBuffer buf = new StringBuffer().append( begin );
|
StringBuffer buf = new StringBuffer().append( begin );
|
||||||
for ( int i = 0; i < args.size(); i++ ) {
|
for ( int i = 0; i < arguments.size(); i++ ) {
|
||||||
buf.append( transformArgument( ( String ) args.get( i ) ) );
|
buf.append( transformArgument( ( String ) arguments.get( i ) ) );
|
||||||
if ( i < args.size() - 1 ) {
|
if ( i < arguments.size() - 1 ) {
|
||||||
buf.append( sep );
|
buf.append( sep );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,8 +111,8 @@ public class VarArgsSQLFunction implements SQLFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called from {@link #render} to allow applying a change or transformation to each individual
|
* Called from {@link #render} to allow applying a change or transformation
|
||||||
* argument.
|
* to each individual argument.
|
||||||
*
|
*
|
||||||
* @param argument The argument being processed.
|
* @param argument The argument being processed.
|
||||||
* @return The transformed argument; may be the same, though should never be null.
|
* @return The transformed argument; may be the same, though should never be null.
|
||||||
|
|
|
@ -33,6 +33,8 @@ import antlr.RecognitionException;
|
||||||
import antlr.collections.AST;
|
import antlr.collections.AST;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.hql.ast.tree.FunctionNode;
|
import org.hibernate.hql.ast.tree.FunctionNode;
|
||||||
|
import org.hibernate.hql.ast.tree.SqlNode;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
import org.hibernate.param.ParameterSpecification;
|
import org.hibernate.param.ParameterSpecification;
|
||||||
import org.hibernate.dialect.function.SQLFunction;
|
import org.hibernate.dialect.function.SQLFunction;
|
||||||
|
@ -202,10 +204,11 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter {
|
||||||
super.endFunctionTemplate( node );
|
super.endFunctionTemplate( node );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
final Type functionType = functionNode.getFirstArgumentType();
|
||||||
// this function has a registered SQLFunction -> redirect output and catch the arguments
|
// this function has a registered SQLFunction -> redirect output and catch the arguments
|
||||||
FunctionArguments functionArguments = ( FunctionArguments ) writer;
|
FunctionArguments functionArguments = ( FunctionArguments ) writer;
|
||||||
writer = outputStack.removeFirst();
|
writer = outputStack.removeFirst();
|
||||||
out( sqlFunction.render( functionArguments.getArgs(), sessionFactory ) );
|
out( sqlFunction.render( functionType, functionArguments.getArgs(), sessionFactory ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.hibernate.hql.ast.util.ColumnHelper;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
import antlr.SemanticException;
|
import antlr.SemanticException;
|
||||||
|
import antlr.collections.AST;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -62,6 +63,20 @@ public class AggregateNode extends AbstractSelectExpression implements SelectExp
|
||||||
return sqlFunction;
|
return sqlFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type getFirstArgumentType() {
|
||||||
|
AST argument = getFirstChild();
|
||||||
|
while ( argument != null ) {
|
||||||
|
if ( argument instanceof SqlNode ) {
|
||||||
|
final Type type = ( (SqlNode) argument ).getDataType();
|
||||||
|
if ( type != null ) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
argument = argument.getNextSibling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public Type getDataType() {
|
public Type getDataType() {
|
||||||
// Get the function return value type, based on the type of the first argument.
|
// Get the function return value type, based on the type of the first argument.
|
||||||
return getSessionFactoryHelper().findFunctionReturnType( getText(), resolveFunction(), getFirstChild() );
|
return getSessionFactoryHelper().findFunctionReturnType( getText(), resolveFunction(), getFirstChild() );
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
package org.hibernate.hql.ast.tree;
|
package org.hibernate.hql.ast.tree;
|
||||||
|
|
||||||
import org.hibernate.dialect.function.SQLFunction;
|
import org.hibernate.dialect.function.SQLFunction;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identifies a node which models a SQL function.
|
* Identifies a node which models a SQL function.
|
||||||
|
@ -32,4 +33,5 @@ import org.hibernate.dialect.function.SQLFunction;
|
||||||
*/
|
*/
|
||||||
public interface FunctionNode {
|
public interface FunctionNode {
|
||||||
public SQLFunction getSQLFunction();
|
public SQLFunction getSQLFunction();
|
||||||
|
public Type getFirstArgumentType();
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,7 +291,10 @@ public class IdentNode extends FromReferenceNode implements SelectExpression {
|
||||||
return fe.getDataType();
|
return fe.getDataType();
|
||||||
}
|
}
|
||||||
SQLFunction sf = getWalker().getSessionFactoryHelper().findSQLFunction( getText() );
|
SQLFunction sf = getWalker().getSessionFactoryHelper().findSQLFunction( getText() );
|
||||||
return sf == null ? null : sf.getReturnType( null, null );
|
if ( sf != null ) {
|
||||||
|
return sf.getReturnType( null, getWalker().getSessionFactoryHelper().getFactory() );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setScalarColumnText(int i) throws SemanticException {
|
public void setScalarColumnText(int i) throws SemanticException {
|
||||||
|
|
|
@ -96,6 +96,20 @@ public class MethodNode extends AbstractSelectExpression implements SelectExpres
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type getFirstArgumentType() {
|
||||||
|
AST argument = getFirstChild();
|
||||||
|
while ( argument != null ) {
|
||||||
|
if ( argument instanceof SqlNode ) {
|
||||||
|
final Type type = ( (SqlNode) argument ).getDataType();
|
||||||
|
if ( type != null ) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
argument = argument.getNextSibling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void dialectFunction(AST exprList) {
|
private void dialectFunction(AST exprList) {
|
||||||
function = getSessionFactoryHelper().findSQLFunction( methodName );
|
function = getSessionFactoryHelper().findSQLFunction( methodName );
|
||||||
if ( function != null ) {
|
if ( function != null ) {
|
||||||
|
|
|
@ -46,7 +46,6 @@ import org.hibernate.type.AssociationType;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
import org.hibernate.type.EntityType;
|
import org.hibernate.type.EntityType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
import org.hibernate.type.TypeFactory;
|
|
||||||
|
|
||||||
import antlr.SemanticException;
|
import antlr.SemanticException;
|
||||||
import antlr.collections.AST;
|
import antlr.collections.AST;
|
||||||
|
|
|
@ -142,9 +142,14 @@ public class SelectParser implements Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( COUNT_MODIFIERS.contains( lctoken ) ) {
|
else if ( COUNT_MODIFIERS.contains( lctoken ) ) {
|
||||||
if ( !ready || !aggregate ) throw new QueryException( token + " only allowed inside aggregate function in SELECT" );
|
if ( !ready || !aggregate ) {
|
||||||
|
throw new QueryException( token + " only allowed inside aggregate function in SELECT" );
|
||||||
|
}
|
||||||
q.appendScalarSelectToken( token );
|
q.appendScalarSelectToken( token );
|
||||||
if ( "*".equals( token ) ) q.addSelectScalar( getFunction( "count", q ).getReturnType( Hibernate.LONG, q.getFactory() ) ); //special case
|
if ( "*".equals( token ) ) {
|
||||||
|
// special case
|
||||||
|
q.addSelectScalar( getFunction( "count", q ).getReturnType( Hibernate.LONG, q.getFactory() ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ( getFunction( lctoken, q ) != null && token.equals( q.unalias( token ) ) ) {
|
else if ( getFunction( lctoken, q ) != null && token.equals( q.unalias( token ) ) ) {
|
||||||
// the name of an SQL function
|
// the name of an SQL function
|
||||||
|
|
|
@ -137,7 +137,7 @@ public class OrderByFragmentParser extends GeneratedOrderByFragmentParser {
|
||||||
expressions.add( child.getText() );
|
expressions.add( child.getText() );
|
||||||
child = child.getNextSibling();
|
child = child.getNextSibling();
|
||||||
}
|
}
|
||||||
final String text = function.render( expressions, context.getSessionFactory() );
|
final String text = function.render( null, expressions, context.getSessionFactory() );
|
||||||
return getASTFactory().create( OrderByTemplateTokenTypes.IDENT, text );
|
return getASTFactory().create( OrderByTemplateTokenTypes.IDENT, text );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class ComponentTest extends FunctionalTestCase {
|
||||||
else {
|
else {
|
||||||
List args = new ArrayList();
|
List args = new ArrayList();
|
||||||
args.add( "dob" );
|
args.add( "dob" );
|
||||||
f.setFormula( yearFunction.render( args, null ) );
|
f.setFormula( yearFunction.render( Hibernate.INTEGER, args, null ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.util.ArrayList;
|
||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.cfg.Mappings;
|
import org.hibernate.cfg.Mappings;
|
||||||
|
@ -40,7 +41,7 @@ public class CompositeElementTest extends FunctionalTestCase {
|
||||||
if ( lengthFunction != null ) {
|
if ( lengthFunction != null ) {
|
||||||
ArrayList args = new ArrayList();
|
ArrayList args = new ArrayList();
|
||||||
args.add( "bio" );
|
args.add( "bio" );
|
||||||
f.setFormula( lengthFunction.render( args, null ) );
|
f.setFormula( lengthFunction.render( Hibernate.INTEGER, args, null ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* 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
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
@ -23,8 +23,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.dialect.function;
|
package org.hibernate.test.dialect.function;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
@ -48,22 +48,22 @@ public class AnsiTrimEmulationFunctionTest extends TestCase {
|
||||||
final String expectedPostTrimSuffix = ",' ','-'),'${space}$',' ')";
|
final String expectedPostTrimSuffix = ",' ','-'),'${space}$',' ')";
|
||||||
|
|
||||||
// -> trim(LEADING '-' FROM a.column)
|
// -> trim(LEADING '-' FROM a.column)
|
||||||
String rendered = function.render( argList( "LEADING", "'-'", "FROM", trimSource ), null );
|
String rendered = function.render( null, argList( "LEADING", "'-'", "FROM", trimSource ), null );
|
||||||
String expected = expectedPostTrimPrefix + "ltrim(" + expectedTrimPrep + ")" + expectedPostTrimSuffix;
|
String expected = expectedPostTrimPrefix + "ltrim(" + expectedTrimPrep + ")" + expectedPostTrimSuffix;
|
||||||
assertEquals( expected, rendered );
|
assertEquals( expected, rendered );
|
||||||
|
|
||||||
// -> trim(TRAILING '-' FROM a.column)
|
// -> trim(TRAILING '-' FROM a.column)
|
||||||
rendered = function.render( argList( "TRAILING", "'-'", "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "TRAILING", "'-'", "FROM", trimSource ), null );
|
||||||
expected = expectedPostTrimPrefix + "rtrim(" + expectedTrimPrep + ")" + expectedPostTrimSuffix;
|
expected = expectedPostTrimPrefix + "rtrim(" + expectedTrimPrep + ")" + expectedPostTrimSuffix;
|
||||||
assertEquals( expected, rendered );
|
assertEquals( expected, rendered );
|
||||||
|
|
||||||
// -> trim(BOTH '-' FROM a.column)
|
// -> trim(BOTH '-' FROM a.column)
|
||||||
rendered = function.render( argList( "BOTH", "'-'", "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "BOTH", "'-'", "FROM", trimSource ), null );
|
||||||
expected = expectedPostTrimPrefix + "ltrim(rtrim(" + expectedTrimPrep + "))" + expectedPostTrimSuffix;
|
expected = expectedPostTrimPrefix + "ltrim(rtrim(" + expectedTrimPrep + "))" + expectedPostTrimSuffix;
|
||||||
assertEquals( expected, rendered );
|
assertEquals( expected, rendered );
|
||||||
|
|
||||||
// -> trim('-' FROM a.column)
|
// -> trim('-' FROM a.column)
|
||||||
rendered = function.render( argList( "'-'", "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "'-'", "FROM", trimSource ), null );
|
||||||
expected = expectedPostTrimPrefix + "ltrim(rtrim(" + expectedTrimPrep + "))" + expectedPostTrimSuffix;
|
expected = expectedPostTrimPrefix + "ltrim(rtrim(" + expectedTrimPrep + "))" + expectedPostTrimSuffix;
|
||||||
assertEquals( expected, rendered );
|
assertEquals( expected, rendered );
|
||||||
}
|
}
|
||||||
|
@ -82,88 +82,62 @@ public class AnsiTrimEmulationFunctionTest extends TestCase {
|
||||||
final String expectedPostTrimSuffix = ",' ','-'),'${space}$',' ')";
|
final String expectedPostTrimSuffix = ",' ','-'),'${space}$',' ')";
|
||||||
|
|
||||||
// -> trim(LEADING '-' FROM a.column)
|
// -> trim(LEADING '-' FROM a.column)
|
||||||
String rendered = function.render( argList( "LEADING", "'-'", "FROM", trimSource ), null );
|
String rendered = function.render( null, argList( "LEADING", "'-'", "FROM", trimSource ), null );
|
||||||
String expected = expectedPostTrimPrefix + "ltrim(" + expectedTrimPrep + ")" + expectedPostTrimSuffix;
|
String expected = expectedPostTrimPrefix + "ltrim(" + expectedTrimPrep + ")" + expectedPostTrimSuffix;
|
||||||
assertEquals( expected, rendered );
|
assertEquals( expected, rendered );
|
||||||
|
|
||||||
// -> trim(TRAILING '-' FROM a.column)
|
// -> trim(TRAILING '-' FROM a.column)
|
||||||
rendered = function.render( argList( "TRAILING", "'-'", "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "TRAILING", "'-'", "FROM", trimSource ), null );
|
||||||
expected = expectedPostTrimPrefix + "rtrim(" + expectedTrimPrep + ")" + expectedPostTrimSuffix;
|
expected = expectedPostTrimPrefix + "rtrim(" + expectedTrimPrep + ")" + expectedPostTrimSuffix;
|
||||||
assertEquals( expected, rendered );
|
assertEquals( expected, rendered );
|
||||||
|
|
||||||
// -> trim(BOTH '-' FROM a.column)
|
// -> trim(BOTH '-' FROM a.column)
|
||||||
rendered = function.render( argList( "BOTH", "'-'", "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "BOTH", "'-'", "FROM", trimSource ), null );
|
||||||
expected = expectedPostTrimPrefix + "ltrim(rtrim(" + expectedTrimPrep + "))" + expectedPostTrimSuffix;
|
expected = expectedPostTrimPrefix + "ltrim(rtrim(" + expectedTrimPrep + "))" + expectedPostTrimSuffix;
|
||||||
assertEquals( expected, rendered );
|
assertEquals( expected, rendered );
|
||||||
|
|
||||||
// -> trim('-' FROM a.column)
|
// -> trim('-' FROM a.column)
|
||||||
rendered = function.render( argList( "'-'", "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "'-'", "FROM", trimSource ), null );
|
||||||
expected = expectedPostTrimPrefix + "ltrim(rtrim(" + expectedTrimPrep + "))" + expectedPostTrimSuffix;
|
expected = expectedPostTrimPrefix + "ltrim(rtrim(" + expectedTrimPrep + "))" + expectedPostTrimSuffix;
|
||||||
assertEquals( expected, rendered );
|
assertEquals( expected, rendered );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void performBasicSpaceTrimmingTests(AnsiTrimEmulationFunction function) {
|
private void performBasicSpaceTrimmingTests(AnsiTrimEmulationFunction function) {
|
||||||
// -> trim(a.column)
|
// -> trim(a.column)
|
||||||
String rendered = function.render( argList( trimSource ), null );
|
String rendered = function.render( null, argList( trimSource ), null );
|
||||||
assertEquals( "ltrim(rtrim(a.column))", rendered );
|
assertEquals( "ltrim(rtrim(a.column))", rendered );
|
||||||
|
|
||||||
// -> trim(FROM a.column)
|
// -> trim(FROM a.column)
|
||||||
rendered = function.render( argList( "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "FROM", trimSource ), null );
|
||||||
assertEquals( "ltrim(rtrim(a.column))", rendered );
|
assertEquals( "ltrim(rtrim(a.column))", rendered );
|
||||||
|
|
||||||
// -> trim(BOTH FROM a.column)
|
// -> trim(BOTH FROM a.column)
|
||||||
rendered = function.render( argList( "BOTH", "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "BOTH", "FROM", trimSource ), null );
|
||||||
assertEquals( "ltrim(rtrim(a.column))", rendered );
|
assertEquals( "ltrim(rtrim(a.column))", rendered );
|
||||||
|
|
||||||
// -> trim(BOTH ' ' FROM a.column)
|
// -> trim(BOTH ' ' FROM a.column)
|
||||||
rendered = function.render( argList( "BOTH", "' '", "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "BOTH", "' '", "FROM", trimSource ), null );
|
||||||
assertEquals( "ltrim(rtrim(a.column))", rendered );
|
assertEquals( "ltrim(rtrim(a.column))", rendered );
|
||||||
|
|
||||||
// -> trim(LEADING FROM a.column)
|
// -> trim(LEADING FROM a.column)
|
||||||
rendered = function.render( argList( "LEADING", "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "LEADING", "FROM", trimSource ), null );
|
||||||
assertEquals( "ltrim(a.column)", rendered );
|
assertEquals( "ltrim(a.column)", rendered );
|
||||||
|
|
||||||
// -> trim(LEADING ' ' FROM a.column)
|
// -> trim(LEADING ' ' FROM a.column)
|
||||||
rendered = function.render( argList( "LEADING", "' '", "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "LEADING", "' '", "FROM", trimSource ), null );
|
||||||
assertEquals( "ltrim(a.column)", rendered );
|
assertEquals( "ltrim(a.column)", rendered );
|
||||||
|
|
||||||
// -> trim(TRAILING FROM a.column)
|
// -> trim(TRAILING FROM a.column)
|
||||||
rendered = function.render( argList( "TRAILING", "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "TRAILING", "FROM", trimSource ), null );
|
||||||
assertEquals( "rtrim(a.column)", rendered );
|
assertEquals( "rtrim(a.column)", rendered );
|
||||||
|
|
||||||
// -> trim(TRAILING ' ' FROM a.column)
|
// -> trim(TRAILING ' ' FROM a.column)
|
||||||
rendered = function.render( argList( "TRAILING", "' '", "FROM", trimSource ), null );
|
rendered = function.render( null, argList( "TRAILING", "' '", "FROM", trimSource ), null );
|
||||||
assertEquals( "rtrim(a.column)", rendered );
|
assertEquals( "rtrim(a.column)", rendered );
|
||||||
}
|
}
|
||||||
|
|
||||||
private List argList(String arg) {
|
private List argList(String... args) {
|
||||||
ArrayList args = new ArrayList();
|
return Arrays.asList( args );
|
||||||
args.add( arg );
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List argList(String arg1, String arg2) {
|
|
||||||
ArrayList args = new ArrayList();
|
|
||||||
args.add( arg1 );
|
|
||||||
args.add( arg2 );
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List argList(String arg1, String arg2, String arg3) {
|
|
||||||
ArrayList args = new ArrayList();
|
|
||||||
args.add( arg1 );
|
|
||||||
args.add( arg2 );
|
|
||||||
args.add( arg3 );
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List argList(String arg1, String arg2, String arg3, String arg4) {
|
|
||||||
ArrayList args = new ArrayList();
|
|
||||||
args.add( arg1 );
|
|
||||||
args.add( arg2 );
|
|
||||||
args.add( arg3 );
|
|
||||||
args.add( arg4 );
|
|
||||||
return args;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -682,7 +682,7 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
assertTranslation( "from Animal an where an.bodyWeight > abs(3*5)" );
|
assertTranslation( "from Animal an where an.bodyWeight > abs(3*5)" );
|
||||||
SQLFunction concat = getSessionFactoryImplementor().getSqlFunctionRegistry().findSQLFunction( "concat");
|
SQLFunction concat = getSessionFactoryImplementor().getSqlFunctionRegistry().findSQLFunction( "concat");
|
||||||
List list = new ArrayList(); list.add("'fat'"); list.add("'skinny'");
|
List list = new ArrayList(); list.add("'fat'"); list.add("'skinny'");
|
||||||
assertTranslation( "from Animal an where an.description = " + concat.render(list, getSessionFactoryImplementor()) );
|
assertTranslation( "from Animal an where an.description = " + concat.render(Hibernate.STRING, list, getSessionFactoryImplementor()) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNotOrWhereClause() {
|
public void testNotOrWhereClause() {
|
||||||
|
|
Loading…
Reference in New Issue