From 823012b29c673a326e2d1fe6cc8fd2b7fd6f65d3 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Tue, 16 Jul 2024 18:00:42 +0200 Subject: [PATCH] HHH-18359 Add a wrap parameter rendering mode for Informix --- .../sql/ast/SqlAstNodeRenderingMode.java | 9 +++++- .../sql/ast/spi/AbstractSqlAstTranslator.java | 30 +++++++++++++++---- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/SqlAstNodeRenderingMode.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/SqlAstNodeRenderingMode.java index 762401d5a4..bdf86ed095 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/SqlAstNodeRenderingMode.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/SqlAstNodeRenderingMode.java @@ -54,5 +54,12 @@ public enum SqlAstNodeRenderingMode { * such that it doesn't appear as plain parameter. * null literals will be wrapped in a cast. */ - NO_UNTYPED + NO_UNTYPED, + + /** + * Wrap all nested parameters with a database specific wrapping strategy, + * defaulting to wrapping via a subquery e.g. {@code (select ?)}. + * This is useful for certain databases that don't support parameters directly within certain functions, like Informix. + */ + WRAP_ALL_PARAMETERS } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java index d91c94c546..4bef3ba6ff 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java @@ -7053,6 +7053,9 @@ public abstract class AbstractSqlAstTranslator implemen renderExpressionAsLiteral( jdbcParameter, jdbcParameterBindings ); break; } + case WRAP_ALL_PARAMETERS: + renderWrappedParameter( jdbcParameter ); + break; case DEFAULT: default: { visitParameterAsParameter( jdbcParameter ); @@ -7073,6 +7076,21 @@ public abstract class AbstractSqlAstTranslator implemen renderParameterAsParameter( parameterBinders.size() + 1, jdbcParameter ); } + protected void renderWrappedParameter(JdbcParameter jdbcParameter) { + clauseStack.push( Clause.SELECT ); + + try { + appendSql( "(select " ); + + render( jdbcParameter, SqlAstNodeRenderingMode.DEFAULT ); + appendSql( getFromDualForSelectOnly() ); + appendSql( ')' ); + } + finally { + clauseStack.pop(); + } + } + /** * Renders a parameter marker for the given position * @param jdbcParameter @@ -7088,7 +7106,7 @@ public abstract class AbstractSqlAstTranslator implemen @Override public void render(SqlAstNode sqlAstNode, SqlAstNodeRenderingMode renderingMode) { SqlAstNodeRenderingMode original = this.parameterRenderingMode; - if ( original != SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS ) { + if ( original != SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS && original != SqlAstNodeRenderingMode.WRAP_ALL_PARAMETERS ) { this.parameterRenderingMode = renderingMode; } try { @@ -7101,7 +7119,7 @@ public abstract class AbstractSqlAstTranslator implemen protected void withParameterRenderingMode(SqlAstNodeRenderingMode renderingMode, Runnable runnable) { SqlAstNodeRenderingMode original = this.parameterRenderingMode; - if ( original != SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS ) { + if ( original != SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS && original != SqlAstNodeRenderingMode.WRAP_ALL_PARAMETERS ) { this.parameterRenderingMode = renderingMode; } try { @@ -7285,7 +7303,7 @@ public abstract class AbstractSqlAstTranslator implemen appendSql( "case" ); final SqlAstNodeRenderingMode original = this.parameterRenderingMode; for ( CaseSearchedExpression.WhenFragment whenFragment : caseSearchedExpression.getWhenFragments() ) { - if ( original != SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS ) { + if ( original != SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS && original != SqlAstNodeRenderingMode.WRAP_ALL_PARAMETERS ) { this.parameterRenderingMode = SqlAstNodeRenderingMode.DEFAULT; } appendSql( " when " ); @@ -7313,7 +7331,7 @@ public abstract class AbstractSqlAstTranslator implemen for ( int i = 0; i < caseNumber; i++ ) { final CaseSearchedExpression.WhenFragment whenFragment = whenFragments.get( i ); Predicate predicate = whenFragment.getPredicate(); - if ( original != SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS ) { + if ( original != SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS && original != SqlAstNodeRenderingMode.WRAP_ALL_PARAMETERS ) { this.parameterRenderingMode = SqlAstNodeRenderingMode.DEFAULT; } if ( i != 0 ) { @@ -7360,12 +7378,12 @@ public abstract class AbstractSqlAstTranslator implemen Consumer resultRenderer) { appendSql( "case " ); final SqlAstNodeRenderingMode original = this.parameterRenderingMode; - if ( original != SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS ) { + if ( original != SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS && original != SqlAstNodeRenderingMode.WRAP_ALL_PARAMETERS ) { this.parameterRenderingMode = SqlAstNodeRenderingMode.DEFAULT; } caseSimpleExpression.getFixture().accept( this ); for ( CaseSimpleExpression.WhenFragment whenFragment : caseSimpleExpression.getWhenFragments() ) { - if ( original != SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS ) { + if ( original != SqlAstNodeRenderingMode.INLINE_ALL_PARAMETERS && original != SqlAstNodeRenderingMode.WRAP_ALL_PARAMETERS ) { this.parameterRenderingMode = SqlAstNodeRenderingMode.DEFAULT; } appendSql( " when " );