From cbc79c2d61fc8c0d64dae90c61fe98990635c051 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Fri, 4 Apr 2014 16:00:45 -0500 Subject: [PATCH] HHH-9100 - Improve CAST function support (cherry picked from commit 137c2daf8171a9fb47df58cb119d23c10fddf105) --- hibernate-core/src/main/antlr/hql-sql.g | 2 +- hibernate-core/src/main/antlr/sql-gen.g | 12 +++-- .../dialect/function/CastFunction.java | 2 +- .../hql/internal/ast/SqlGenerator.java | 54 ++++++++++++------- 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/hibernate-core/src/main/antlr/hql-sql.g b/hibernate-core/src/main/antlr/hql-sql.g index bc0b7adec4..ca7b63225f 100644 --- a/hibernate-core/src/main/antlr/hql-sql.g +++ b/hibernate-core/src/main/antlr/hql-sql.g @@ -629,7 +629,7 @@ functionCall processFunction( #functionCall, inSelect ); inFunctionCall=false; } - | #(CAST {inFunctionCall=true;} expr pathAsIdent) { + | #(CAST {inFunctionCall=true;} exprOrSubquery pathAsIdent) { processCastFunction( #functionCall, inSelect ); inFunctionCall=false; } diff --git a/hibernate-core/src/main/antlr/sql-gen.g b/hibernate-core/src/main/antlr/sql-gen.g index 99726b8f11..6c932db174 100644 --- a/hibernate-core/src/main/antlr/sql-gen.g +++ b/hibernate-core/src/main/antlr/sql-gen.g @@ -92,8 +92,8 @@ options { out(")"); } - protected void commaBetweenParameters(String comma) { - out(comma); + protected void betweenFunctionArguments() { + out( ", " ); } protected void captureExpressionStart() { @@ -465,11 +465,15 @@ methodCall : #(m:METHOD_CALL i:METHOD_NAME { beginFunctionTemplate(m,i); } ( #(EXPR_LIST (arguments)? ) )? { endFunctionTemplate(m); } ) - | #( c:CAST { beginFunctionTemplate(c,c); } expr castTargetType { endFunctionTemplate(c); } ) + | #( c:CAST { beginFunctionTemplate(c,c); } castExpression {betweenFunctionArguments();} castTargetType { endFunctionTemplate(c); } ) ; arguments - : expr ( { commaBetweenParameters(", "); } expr )* + : expr ( { betweenFunctionArguments(); } expr )* + ; + +castExpression + : selectExpr ; castTargetType diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/CastFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/CastFunction.java index 7a0a1fbc9c..19f5c0c199 100755 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/CastFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/CastFunction.java @@ -60,7 +60,7 @@ public class CastFunction implements SQLFunction { @Override public String render(Type columnType, List args, SessionFactoryImplementor factory) throws QueryException { if ( args.size()!=2 ) { - throw new QueryException("cast() requires two arguments"); + throw new QueryException( "cast() requires two arguments; found : " + args.size() ); } final String type = (String) args.get( 1 ); final int[] sqlTypeCodes = factory.getTypeResolver().heuristicType( type ).sqlTypes( factory ); diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java index 26adf6da58..8749fa7f61 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java @@ -44,6 +44,7 @@ import org.hibernate.hql.internal.ast.util.ASTPrinter; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.param.ParameterSpecification; import org.hibernate.type.Type; @@ -145,8 +146,8 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter { } @Override - protected void commaBetweenParameters(String comma) { - writer.commaBetweenParameters( comma ); + protected void betweenFunctionArguments() { + writer.betweenFunctionArguments(); } @Override @@ -241,14 +242,7 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter { interface SqlWriter { void clause(String clause); - /** - * todo remove this hack - * The parameter is either ", " or " , ". This is needed to pass sql generating tests as the old - * sql generator uses " , " in the WHERE and ", " in SELECT. - * - * @param comma either " , " or ", " - */ - void commaBetweenParameters(String comma); + void betweenFunctionArguments(); } interface FunctionArgumentsCollectingWriter extends SqlWriter { @@ -274,7 +268,7 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter { } @Override - public void commaBetweenParameters(String comma) { + public void betweenFunctionArguments() { ++argInd; } @@ -288,20 +282,44 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter { * which catches function arguments. */ class CastFunctionArguments implements FunctionArgumentsCollectingWriter { - private final List args = new ArrayList( 3 ); + private String castExpression; + private String castTargetType; + + private boolean startedType; @Override public void clause(String clause) { - args.add( clause ); + if ( startedType ) { + if ( castTargetType == null ) { + castTargetType = clause; + } + else { + castTargetType += clause; + } + } + else { + if ( castExpression == null ) { + castExpression = clause; + } + else { + castExpression += clause; + } + } } @Override - public void commaBetweenParameters(String comma) { - // todo : should this be an exception? Its not likely to end well if this method is called here... + public void betweenFunctionArguments() { + if ( startedType ) { + throw new QueryException( "CAST function should only have 2 arguments" ); + } + startedType = true; } public List getArgs() { - return args; + List rtn = CollectionHelper.arrayList( 2 ); + rtn.add( castExpression ); + rtn.add( castTargetType ); + return rtn; } } @@ -315,8 +333,8 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter { } @Override - public void commaBetweenParameters(String comma) { - getStringBuilder().append( comma ); + public void betweenFunctionArguments() { + getStringBuilder().append( ", " ); } }