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.CriteriaBuilderImpl;
import org.hibernate.query.criteria.internal.ParameterRegistry; import org.hibernate.query.criteria.internal.ParameterRegistry;
import org.hibernate.query.criteria.internal.ValueHandlerFactory; import org.hibernate.query.criteria.internal.ValueHandlerFactory;
import org.hibernate.query.criteria.internal.ValueHandlerFactory.ValueHandler;
import org.hibernate.query.criteria.internal.compile.RenderingContext; import org.hibernate.query.criteria.internal.compile.RenderingContext;
/** /**
@ -20,6 +21,7 @@ import org.hibernate.query.criteria.internal.compile.RenderingContext;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class LiteralExpression<T> extends ExpressionImpl<T> implements Serializable { public class LiteralExpression<T> extends ExpressionImpl<T> implements Serializable {
private Object literal; private Object literal;
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
@ -41,33 +43,40 @@ public class LiteralExpression<T> extends ExpressionImpl<T> implements Serializa
return (T) literal; return (T) literal;
} }
@Override
public void registerParameters(ParameterRegistry registry) { public void registerParameters(ParameterRegistry registry) {
// nothing to do // nothing to do
} }
@SuppressWarnings({ "unchecked" }) @Override
public String render(RenderingContext renderingContext) { 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() ) { switch ( renderingContext.getClauseStack().getCurrent() ) {
case SELECT: { case SELECT: {
return renderProjection(); return renderProjection( renderingContext );
} }
case GROUP: { case GROUP: {
// technically a literal in the group-by clause // technically a literal in the group-by clause
// would be a reference to the position of a selection // would be a reference to the position of a selection
// //
// but this is what the code used to do... // but this is what the code used to do...
return renderProjection(); return renderProjection( renderingContext );
} }
default: { default: {
return normalRender( renderingContext ); return normalRender( renderingContext, renderingContext.getCriteriaLiteralHandlingMode() );
} }
} }
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private String normalRender(RenderingContext renderingContext) { private String normalRender(RenderingContext renderingContext, LiteralHandlingMode literalHandlingMode) {
LiteralHandlingMode literalHandlingMode = renderingContext.getCriteriaLiteralHandlingMode();
switch ( literalHandlingMode ) { switch ( literalHandlingMode ) {
case AUTO: { case AUTO: {
if ( ValueHandlerFactory.isNumeric( literal ) ) { if ( ValueHandlerFactory.isNumeric( literal ) ) {
@ -86,6 +95,11 @@ public class LiteralExpression<T> extends ExpressionImpl<T> implements Serializa
literalValue = renderingContext.getDialect().inlineLiteral( (String) literal ); 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 ); return ValueHandlerFactory.determineAppropriateHandler( (Class) literal.getClass() ).render( literalValue );
} }
default: { 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 // some drivers/servers do not like parameters in the select clause
final ValueHandlerFactory.ValueHandler handler = final ValueHandlerFactory.ValueHandler handler =
ValueHandlerFactory.determineAppropriateHandler( literal.getClass() ); ValueHandlerFactory.determineAppropriateHandler( literal.getClass() );
if ( handler == null ) {
return normalRender( renderingContext, LiteralHandlingMode.BIND );
}
if ( ValueHandlerFactory.isCharacter( literal ) ) { if ( ValueHandlerFactory.isCharacter( literal ) ) {
return '\'' + handler.render( literal ) + '\''; return '\'' + handler.render( literal ) + '\'';
} }