HHH-13016 HHH-13199 Force parameter binding for enum literals

Currently, we don't have a way to properly handle enum literals so get back to
using parameter binding, which was used before in the "case when" case
due to a bug fixed in HHH-13001.

Note that this forces the usage of enum literals even at the root of the
select clause.
This commit is contained in:
Guillaume Smet 2019-01-17 13:19:25 +01:00
parent 9c72384e1f
commit 624403e65c
1 changed files with 27 additions and 8 deletions

View File

@ -12,6 +12,7 @@ import org.hibernate.query.criteria.LiteralHandlingMode;
import org.hibernate.query.criteria.internal.CriteriaBuilderImpl;
import org.hibernate.query.criteria.internal.ParameterRegistry;
import org.hibernate.query.criteria.internal.ValueHandlerFactory;
import org.hibernate.query.criteria.internal.ValueHandlerFactory.ValueHandler;
import org.hibernate.query.criteria.internal.compile.RenderingContext;
/**
@ -20,6 +21,7 @@ import org.hibernate.query.criteria.internal.compile.RenderingContext;
* @author Steve Ebersole
*/
public class LiteralExpression<T> extends ExpressionImpl<T> implements Serializable {
private Object literal;
@SuppressWarnings({ "unchecked" })
@ -41,33 +43,40 @@ public class LiteralExpression<T> extends ExpressionImpl<T> implements Serializa
return (T) literal;
}
@Override
public void registerParameters(ParameterRegistry registry) {
// nothing to do
}
@SuppressWarnings({ "unchecked" })
@Override
public String render(RenderingContext renderingContext) {
// In the case of literals, we currently do not have an easy way to get the value.
// That would require some significant infrastructure changes.
// For now, we force the normalRender() code path for enums which means we will
// always use parameter binding for enum literals.
if ( literal instanceof Enum ) {
return normalRender( renderingContext, LiteralHandlingMode.BIND );
}
switch ( renderingContext.getClauseStack().getCurrent() ) {
case SELECT: {
return renderProjection();
return renderProjection( renderingContext );
}
case GROUP: {
// technically a literal in the group-by clause
// would be a reference to the position of a selection
//
// but this is what the code used to do...
return renderProjection();
return renderProjection( renderingContext );
}
default: {
return normalRender( renderingContext );
return normalRender( renderingContext, renderingContext.getCriteriaLiteralHandlingMode() );
}
}
}
@SuppressWarnings("unchecked")
private String normalRender(RenderingContext renderingContext) {
LiteralHandlingMode literalHandlingMode = renderingContext.getCriteriaLiteralHandlingMode();
private String normalRender(RenderingContext renderingContext, LiteralHandlingMode literalHandlingMode) {
switch ( literalHandlingMode ) {
case AUTO: {
if ( ValueHandlerFactory.isNumeric( literal ) ) {
@ -86,6 +95,11 @@ public class LiteralExpression<T> extends ExpressionImpl<T> implements Serializa
literalValue = renderingContext.getDialect().inlineLiteral( (String) literal );
}
ValueHandler valueHandler = ValueHandlerFactory.determineAppropriateHandler( (Class) literal.getClass() );
if ( valueHandler == null ) {
return bindLiteral( renderingContext );
}
return ValueHandlerFactory.determineAppropriateHandler( (Class) literal.getClass() ).render( literalValue );
}
default: {
@ -94,10 +108,15 @@ public class LiteralExpression<T> extends ExpressionImpl<T> implements Serializa
}
}
private String renderProjection() {
private String renderProjection(RenderingContext renderingContext) {
// some drivers/servers do not like parameters in the select clause
final ValueHandlerFactory.ValueHandler handler =
ValueHandlerFactory.determineAppropriateHandler( literal.getClass() );
if ( handler == null ) {
return normalRender( renderingContext, LiteralHandlingMode.BIND );
}
if ( ValueHandlerFactory.isCharacter( literal ) ) {
return '\'' + handler.render( literal ) + '\'';
}