Implement support for special parameter rendering through functions to support using certain Derby functions with parameters

This commit is contained in:
Christian Beikov 2021-02-23 20:01:06 +01:00
parent b6dc77280f
commit 003fddccb5
34 changed files with 372 additions and 145 deletions

View File

@ -40,6 +40,7 @@ import org.hibernate.procedure.spi.CallableStatementSupport;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
@ -814,7 +815,7 @@ public abstract class AbstractHANADialect extends Dialect {
CommonFunctionFactory.weekQuarter( queryEngine );
CommonFunctionFactory.daynameMonthname( queryEngine );
CommonFunctionFactory.lastDay( queryEngine );
CommonFunctionFactory.characterLength_length( queryEngine );
CommonFunctionFactory.characterLength_length( queryEngine, SqlAstNodeRenderingMode.DEFAULT );
CommonFunctionFactory.ascii( queryEngine );
CommonFunctionFactory.chr_char( queryEngine );
CommonFunctionFactory.addYearsMonthsDaysHoursMinutesSeconds( queryEngine );

View File

@ -11,7 +11,8 @@ import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.boot.TempTableDdlTransactionHandling;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.function.DerbyConcatEmulation;
import org.hibernate.dialect.function.DerbyLpadFunction;
import org.hibernate.dialect.function.DerbyRpadFunction;
import org.hibernate.dialect.function.IndividualLeastGreatestEmulation;
import org.hibernate.dialect.function.InsertSubstringOverlayEmulation;
import org.hibernate.dialect.identity.DB2IdentityColumnSupport;
@ -41,6 +42,7 @@ import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DerbyCaseFragment;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
@ -170,6 +172,7 @@ public class DerbyDialect extends Dialect {
public void initializeFunctionRegistry(QueryEngine queryEngine) {
super.initializeFunctionRegistry( queryEngine );
CommonFunctionFactory.concat_pipeOperator( queryEngine );
CommonFunctionFactory.cot( queryEngine );
CommonFunctionFactory.chr_char( queryEngine );
CommonFunctionFactory.degrees( queryEngine );
@ -187,7 +190,7 @@ public class DerbyDialect extends Dialect {
CommonFunctionFactory.stddevPopSamp( queryEngine );
CommonFunctionFactory.substring_substr( queryEngine );
CommonFunctionFactory.leftRight_substrLength( queryEngine );
CommonFunctionFactory.characterLength_length( queryEngine );
CommonFunctionFactory.characterLength_length( queryEngine, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
CommonFunctionFactory.power_expLn( queryEngine );
queryEngine.getSqmFunctionRegistry().patternDescriptorBuilder( "round", "floor(?1*1e?2+0.5)/1e?2")
@ -195,21 +198,9 @@ public class DerbyDialect extends Dialect {
.setInvariantType( StandardBasicTypes.DOUBLE )
.register();
queryEngine.getSqmFunctionRegistry().register( "concat", new DerbyConcatEmulation() );
//no way I can see to pad with anything other than spaces
// TODO: To support parameters, we have to inline the values
queryEngine.getSqmFunctionRegistry().patternDescriptorBuilder( "lpad", "case when length(?1)<?2 then substr(char('',?2)||?1,length(?1)+1) else ?1 end" )
.setInvariantType( StandardBasicTypes.STRING )
.setExactArgumentCount( 2 )
.setArgumentListSignature("(string, length)")
.register();
queryEngine.getSqmFunctionRegistry().patternDescriptorBuilder( "rpad", "case when length(?1)<?2 then substr(?1||char('',?2),1,?2) else ?1 end" )
.setInvariantType( StandardBasicTypes.STRING )
.setExactArgumentCount( 2 )
.setArgumentListSignature("(string, length)")
.register();
queryEngine.getSqmFunctionRegistry().register( "lpad", new DerbyLpadFunction() );
queryEngine.getSqmFunctionRegistry().register( "rpad", new DerbyRpadFunction() );
queryEngine.getSqmFunctionRegistry().register( "least", new IndividualLeastGreatestEmulation( true ) );
queryEngine.getSqmFunctionRegistry().register( "greatest", new IndividualLeastGreatestEmulation( false ) );
queryEngine.getSqmFunctionRegistry().register( "overlay", new InsertSubstringOverlayEmulation( true ) );

View File

@ -47,6 +47,7 @@ import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.*;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
@ -157,7 +158,7 @@ public class OracleDialect extends Dialect {
CommonFunctionFactory.rownumRowid( queryEngine );
CommonFunctionFactory.sysdate( queryEngine );
CommonFunctionFactory.systimestamp( queryEngine );
CommonFunctionFactory.characterLength_length( queryEngine );
CommonFunctionFactory.characterLength_length( queryEngine, SqlAstNodeRenderingMode.DEFAULT );
CommonFunctionFactory.addMonths( queryEngine );
CommonFunctionFactory.monthsBetween( queryEngine );
CommonFunctionFactory.everyAny_sumCaseCase( queryEngine );

View File

@ -178,6 +178,7 @@ public class SpannerDialect extends Dialect {
.register();
// String Functions
CommonFunctionFactory.concat_pipeOperator( queryEngine );
CommonFunctionFactory.trim2( queryEngine );
CommonFunctionFactory.reverse( queryEngine );
CommonFunctionFactory.repeat( queryEngine );

View File

@ -17,7 +17,8 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.CastTarget;
@ -52,7 +53,7 @@ public class CastFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
}
@Override
public void render(SqlAppender sqlAppender, List<SqlAstNode> arguments, SqlAstWalker walker) {
public void render(SqlAppender sqlAppender, List<SqlAstNode> arguments, SqlAstTranslator<?> walker) {
final Expression source = (Expression) arguments.get( 0 );
final JdbcMapping sourceMapping = ( (SqlExpressable) source.getExpressionType() ).getJdbcMapping();
final CastType sourceType = getCastType( sourceMapping );
@ -63,7 +64,7 @@ public class CastFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
String cast = dialect.castPattern( sourceType, targetType );
new PatternRenderer( cast ).render( sqlAppender, arguments, walker );
new PatternRenderer( cast, SqlAstNodeRenderingMode.DEFAULT ).render( sqlAppender, arguments, walker );
}
private CastType getCastType(JdbcMapping sourceMapping) {

View File

@ -7,6 +7,7 @@
package org.hibernate.dialect.function;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.type.StandardBasicTypes;
import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers.useArgType;
@ -1163,10 +1164,11 @@ public class CommonFunctionFactory {
/**
* Oracle-style
*/
public static void characterLength_length(QueryEngine queryEngine) {
public static void characterLength_length(QueryEngine queryEngine, SqlAstNodeRenderingMode argumentRenderingMode) {
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "length" )
.setInvariantType( StandardBasicTypes.INTEGER )
.setExactArgumentCount( 1 )
.setArgumentRenderingMode( argumentRenderingMode )
.register();
queryEngine.getSqmFunctionRegistry().registerAlternateKey( "character_length", "length" );
}

View File

@ -9,7 +9,7 @@ package org.hibernate.dialect.function;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.type.BasicType;
@ -37,7 +37,7 @@ public class CurrentFunction
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> arguments,
SqlAstWalker walker) {
SqlAstTranslator<?> walker) {
sqlAppender.appendSql(sql);
}

View File

@ -10,7 +10,7 @@ import org.hibernate.dialect.OracleDialect;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
@ -44,7 +44,7 @@ public class DB2FormatEmulation
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> arguments,
SqlAstWalker walker) {
SqlAstTranslator<?> walker) {
final Expression datetime = (Expression) arguments.get(0);
final boolean isTime = TypeConfiguration.getSqlTemporalType( datetime.getExpressionType() ) == TemporalType.TIME;
final Format format = (Format) arguments.get(1);

View File

@ -1,70 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.dialect.function;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.type.StandardBasicTypes;
import java.util.List;
/**
* Casts query parameters using the Derby varchar() function
* before concatenating them using the || operator.
*
* @author Steve Ebersole
* @author Christian Beikov
*/
public class DerbyConcatEmulation
extends AbstractSqmSelfRenderingFunctionDescriptor {
public DerbyConcatEmulation() {
super(
"concat",
StandardArgumentsValidators.min( 1 ),
StandardFunctionReturnTypeResolvers.invariant( StandardBasicTypes.STRING )
);
}
@Override
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> arguments,
SqlAstWalker walker) {
int numberOfArguments = arguments.size();
if ( numberOfArguments > 1 ) {
sqlAppender.appendSql("(");
}
for ( int i = 0; i < numberOfArguments; i++ ) {
SqlAstNode argument = arguments.get( i );
if ( i > 0 ) {
sqlAppender.appendSql("||");
}
boolean param = argument instanceof JdbcParameter;
if ( param ) {
sqlAppender.appendSql("cast(");
}
argument.accept(walker);
if ( param ) {
sqlAppender.appendSql(" as long varchar)");
}
}
if ( numberOfArguments > 1 ) {
sqlAppender.appendSql(")");
}
}
@Override
public String getArgumentListSignature() {
return "(string0[, string1[, ...]])";
}
}

View File

@ -0,0 +1,63 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.dialect.function;
import java.util.List;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.type.StandardBasicTypes;
/**
* A derby implementation for lpad.
*
* @author Christian Beikov
*/
public class DerbyLpadFunction
extends AbstractSqmSelfRenderingFunctionDescriptor {
public DerbyLpadFunction() {
super(
"lpad",
StandardArgumentsValidators.exactly( 2 ),
StandardFunctionReturnTypeResolvers.invariant( StandardBasicTypes.STRING )
);
}
@Override
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> arguments,
SqlAstTranslator<?> walker) {
final SqlAstNode string = arguments.get( 0 );
final SqlAstNode length = arguments.get( 1 );
sqlAppender.appendSql( "case when length(" );
walker.render( string, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
sqlAppender.appendSql( ")<" );
walker.render( length, SqlAstNodeRenderingMode.DEFAULT );
sqlAppender.appendSql( " then substr(char(''," );
// The char function for Derby always needs a literal value
walker.render( length, SqlAstNodeRenderingMode.INLINE_PARAMETERS );
sqlAppender.appendSql( ")||" );
walker.render( string, SqlAstNodeRenderingMode.DEFAULT );
sqlAppender.appendSql( ",length(" );
walker.render( string, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
sqlAppender.appendSql( ")+1) else " );
walker.render( string, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
sqlAppender.appendSql( " end" );
}
@Override
public String getArgumentListSignature() {
return "(string, length)";
}
}

View File

@ -0,0 +1,63 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.dialect.function;
import java.util.List;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.type.StandardBasicTypes;
/**
* A derby implementation for rpad.
*
* @author Christian Beikov
*/
public class DerbyRpadFunction
extends AbstractSqmSelfRenderingFunctionDescriptor {
public DerbyRpadFunction() {
super(
"rpad",
StandardArgumentsValidators.exactly( 2 ),
StandardFunctionReturnTypeResolvers.invariant( StandardBasicTypes.STRING )
);
}
@Override
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> arguments,
SqlAstTranslator<?> walker) {
final SqlAstNode string = arguments.get( 0 );
final SqlAstNode length = arguments.get( 1 );
sqlAppender.appendSql( "case when length(" );
walker.render( string, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
sqlAppender.appendSql( ")<" );
walker.render( length, SqlAstNodeRenderingMode.DEFAULT );
sqlAppender.appendSql( " then substr(" );
walker.render( string, SqlAstNodeRenderingMode.DEFAULT );
sqlAppender.appendSql( "||char(''," );
// The char function for Derby always needs a literal value
walker.render( length, SqlAstNodeRenderingMode.INLINE_PARAMETERS );
sqlAppender.appendSql( "),1," );
walker.render( length, SqlAstNodeRenderingMode.DEFAULT );
sqlAppender.appendSql( ") else " );
walker.render( string, SqlAstNodeRenderingMode.DEFAULT );
sqlAppender.appendSql( " end" );
}
@Override
public String getArgumentListSignature() {
return "(string, length)";
}
}

View File

@ -11,7 +11,7 @@ import java.util.List;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
@ -37,7 +37,7 @@ public class IndividualLeastGreatestEmulation
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> arguments,
SqlAstWalker walker) {
SqlAstTranslator<?> walker) {
final int numberOfArguments = arguments.size();
if ( numberOfArguments > 1 ) {
final int lastArgument = numberOfArguments - 1;

View File

@ -11,11 +11,9 @@ import java.util.List;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.type.StandardBasicTypes;
/**
*
@ -39,7 +37,7 @@ public class QuantifiedLeastGreatestEmulation
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> arguments,
SqlAstWalker walker) {
SqlAstTranslator<?> walker) {
final int numberOfArguments = arguments.size();
if ( numberOfArguments > 1 ) {
final int lastArgument = numberOfArguments - 1;

View File

@ -13,7 +13,7 @@ import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
@ -43,7 +43,7 @@ public class SQLServerFormatFunction extends AbstractSqmSelfRenderingFunctionDes
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> arguments,
SqlAstWalker walker) {
SqlAstTranslator<?> walker) {
final Expression datetime = (Expression) arguments.get(0);
final boolean isTime = TypeConfiguration.getSqlTemporalType( datetime.getExpressionType() ) == TemporalType.TIME;
final Format format = (Format) arguments.get(1);

View File

@ -13,7 +13,8 @@ import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.DurationUnit;
@ -45,7 +46,7 @@ public class TimestampaddFunction
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> arguments,
SqlAstWalker walker) {
SqlAstTranslator<?> walker) {
DurationUnit field = (DurationUnit) arguments.get(0);
Expression to = (Expression) arguments.get(2);
@ -55,7 +56,7 @@ public class TimestampaddFunction
TypeConfiguration.getSqlTemporalType( to.getExpressionType() )
);
new PatternRenderer( pattern ).render( sqlAppender, arguments, walker );
new PatternRenderer( pattern, SqlAstNodeRenderingMode.DEFAULT ).render( sqlAppender, arguments, walker );
}
// @Override

View File

@ -13,7 +13,8 @@ import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.DurationUnit;
@ -46,7 +47,7 @@ public class TimestampdiffFunction
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> arguments,
SqlAstWalker walker) {
SqlAstTranslator<?> walker) {
DurationUnit field = (DurationUnit) arguments.get(0);
Expression from = (Expression) arguments.get(1);
@ -58,7 +59,7 @@ public class TimestampdiffFunction
TypeConfiguration.getSqlTemporalType( to.getExpressionType() )
);
new PatternRenderer( pattern ).render( sqlAppender, arguments, walker );
new PatternRenderer( pattern, SqlAstNodeRenderingMode.DEFAULT ).render( sqlAppender, arguments, walker );
}
// @Override

View File

@ -12,7 +12,8 @@ import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescript
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
@ -40,14 +41,15 @@ public class TrimFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
}
@Override
public void render(SqlAppender sqlAppender, List<SqlAstNode> sqlAstArguments, SqlAstWalker walker) {
public void render(SqlAppender sqlAppender, List<SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) {
final TrimSpec specification = ( (TrimSpecification) sqlAstArguments.get( 0 ) ).getSpecification();
final Character trimCharacter = ( (QueryLiteral<Character>) sqlAstArguments.get( 1 ) ).getLiteralValue();
final Expression sourceExpr = (Expression) sqlAstArguments.get( 2 );
String trim = dialect.trimPattern( specification, trimCharacter );
new PatternRenderer( trim ).render( sqlAppender, Collections.singletonList( sourceExpr ), walker );
new PatternRenderer( trim, SqlAstNodeRenderingMode.DEFAULT )
.render( sqlAppender, Collections.singletonList( sourceExpr ), walker );
}
// @Override

View File

@ -11,7 +11,7 @@ import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.type.spi.TypeConfiguration;
@ -51,6 +51,6 @@ public abstract class AbstractSqmSelfRenderingFunctionDescriptor
public abstract void render(
SqlAppender sqlAppender,
List<SqlAstNode> sqlAstArguments,
SqlAstWalker walker);
SqlAstTranslator<?> walker);
}

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.query.sqm.function;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
@ -27,5 +28,5 @@ public interface FunctionRenderingSupport {
void render(
SqlAppender sqlAppender,
List<SqlAstNode> sqlAstArguments,
SqlAstWalker walker);
SqlAstTranslator<?> walker);
}

View File

@ -8,7 +8,8 @@ package org.hibernate.query.sqm.function;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
@ -29,13 +30,22 @@ public class NamedSqmFunctionDescriptor
private final String functionName;
private final boolean useParenthesesWhenNoArgs;
private final String argumentListSignature;
private final SqlAstNodeRenderingMode argumentRenderingMode;
public NamedSqmFunctionDescriptor(
String functionName,
boolean useParenthesesWhenNoArgs,
ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver) {
this( functionName, useParenthesesWhenNoArgs, argumentsValidator, returnTypeResolver, functionName, null );
this(
functionName,
useParenthesesWhenNoArgs,
argumentsValidator,
returnTypeResolver,
functionName,
null,
SqlAstNodeRenderingMode.DEFAULT
);
}
public NamedSqmFunctionDescriptor(
@ -44,12 +54,14 @@ public class NamedSqmFunctionDescriptor
ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver,
String name,
String argumentListSignature) {
String argumentListSignature,
SqlAstNodeRenderingMode argumentRenderingMode) {
super( name, argumentsValidator, returnTypeResolver );
this.functionName = functionName;
this.useParenthesesWhenNoArgs = useParenthesesWhenNoArgs;
this.argumentListSignature = argumentListSignature;
this.argumentRenderingMode = argumentRenderingMode;
}
/**
@ -75,7 +87,7 @@ public class NamedSqmFunctionDescriptor
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> sqlAstArguments,
SqlAstWalker walker) {
SqlAstTranslator<?> walker) {
final boolean useParens = useParenthesesWhenNoArgs || !sqlAstArguments.isEmpty();
sqlAppender.appendSql( functionName );
@ -88,7 +100,7 @@ public class NamedSqmFunctionDescriptor
if ( !firstPass ) {
sqlAppender.appendSql( ", " );
}
sqlAstArgument.accept(walker);
walker.render( sqlAstArgument, argumentRenderingMode );
firstPass = false;
}

View File

@ -10,7 +10,7 @@ import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
@ -69,7 +69,7 @@ public class PatternBasedSqmFunctionDescriptor
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> sqlAstArguments,
SqlAstWalker walker) {
SqlAstTranslator<?> walker) {
renderer.render( sqlAppender, sqlAstArguments, walker );
}

View File

@ -16,7 +16,7 @@ import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
@ -119,7 +119,7 @@ public class SelfRenderingFunctionSqlAstExpression
@Override
public void renderToSql(
SqlAppender sqlAppender,
SqlAstWalker walker,
SqlAstTranslator<?> walker,
SessionFactoryImplementor sessionFactory) {
renderer.render( sqlAppender, sqlAstArguments, walker );
}

View File

@ -9,6 +9,7 @@ package org.hibernate.query.sqm.produce.function;
import org.hibernate.query.sqm.function.NamedSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.type.BasicType;
/**
@ -26,6 +27,7 @@ public class NamedFunctionDescriptorBuilder {
private boolean useParenthesesWhenNoArgs = true;
private String argumentListSignature;
private SqlAstNodeRenderingMode argumentRenderingMode = SqlAstNodeRenderingMode.DEFAULT;
public NamedFunctionDescriptorBuilder(SqmFunctionRegistry registry, String registrationKey, String functionName) {
this.registry = registry;
@ -70,6 +72,11 @@ public class NamedFunctionDescriptorBuilder {
return this;
}
public NamedFunctionDescriptorBuilder setArgumentRenderingMode(SqlAstNodeRenderingMode argumentRenderingMode) {
this.argumentRenderingMode = argumentRenderingMode;
return this;
}
public SqmFunctionDescriptor register() {
return registry.register( registrationKey, descriptor() );
}
@ -81,7 +88,8 @@ public class NamedFunctionDescriptorBuilder {
argumentsValidator,
returnTypeResolver,
registrationKey,
argumentListSignature
argumentListSignature,
argumentRenderingMode
);
}
}

View File

@ -10,6 +10,7 @@ import org.hibernate.query.sqm.function.PatternBasedSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.type.BasicType;
/**
@ -23,6 +24,7 @@ public class PatternFunctionDescriptorBuilder {
private ArgumentsValidator argumentsValidator;
private FunctionReturnTypeResolver returnTypeResolver;
private SqlAstNodeRenderingMode argumentRenderingMode = SqlAstNodeRenderingMode.DEFAULT;
public PatternFunctionDescriptorBuilder(SqmFunctionRegistry registry, String registrationKey, String pattern) {
this.registry = registry;
@ -54,13 +56,18 @@ public class PatternFunctionDescriptorBuilder {
return this;
}
public PatternFunctionDescriptorBuilder setArgumentRenderingMode(SqlAstNodeRenderingMode argumentRenderingMode) {
this.argumentRenderingMode = argumentRenderingMode;
return this;
}
public SqmFunctionDescriptor register() {
return registry.register( registrationKey, descriptor() );
}
public SqmFunctionDescriptor descriptor() {
return new PatternBasedSqmFunctionDescriptor(
new PatternRenderer( pattern ),
new PatternRenderer( pattern, argumentRenderingMode ),
argumentsValidator,
returnTypeResolver,
registrationKey,

View File

@ -8,7 +8,8 @@ package org.hibernate.query.sqm.produce.function.internal;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
@ -29,13 +30,15 @@ public class PatternRenderer {
private final int[] paramIndexes;
private final int varargParam;
private final int maxParamIndex;
private final SqlAstNodeRenderingMode argumentRenderingMode;
/**
* Constructs a template renderer
*
* @param pattern The template
* @param argumentRenderingMode The rendering mode for arguments
*/
public PatternRenderer(String pattern) {
public PatternRenderer(String pattern, SqlAstNodeRenderingMode argumentRenderingMode) {
final Set<Integer> paramNumbers = new HashSet<>();
final List<String> chunkList = new ArrayList<>();
final List<Integer> paramList = new ArrayList<>();
@ -94,14 +97,16 @@ public class PatternRenderer {
chunkList.add( chunk.toString() );
}
varargParam = vararg;
maxParamIndex = max;
this.varargParam = vararg;
this.maxParamIndex = max;
chunks = chunkList.toArray( new String[chunkList.size()] );
paramIndexes = new int[paramList.size()];
this.chunks = chunkList.toArray( new String[chunkList.size()] );
int[] paramIndexes = new int[paramList.size()];
for ( i = 0; i < paramIndexes.length; ++i ) {
paramIndexes[i] = paramList.get( i );
}
this.paramIndexes = paramIndexes;
this.argumentRenderingMode = argumentRenderingMode;
}
public boolean hasVarargs() {
@ -115,15 +120,15 @@ public class PatternRenderer {
/**
* The rendering code.
*
* @param args The arguments to inject into the template
* @param sqlAppender
* @param args The arguments to inject into the template
* @return The rendered template with replacements
*/
@SuppressWarnings({ "UnusedDeclaration" })
public void render(
SqlAppender sqlAppender,
List<SqlAstNode> args,
SqlAstWalker walker) {
SqlAstTranslator<?> walker) {
final int numberOfArguments = args.size();
if ( numberOfArguments < maxParamIndex ) {
LOG.missingArguments( maxParamIndex, numberOfArguments );
@ -135,7 +140,7 @@ public class PatternRenderer {
final SqlAstNode arg = args.get( j );
if ( arg != null ) {
sqlAppender.appendSql( chunks[i] );
arg.accept( walker );
walker.render( arg, argumentRenderingMode );
}
}
}
@ -146,7 +151,7 @@ public class PatternRenderer {
sqlAppender.appendSql( chunks[i] );
}
if ( arg != null ) {
arg.accept( walker );
walker.render( arg, argumentRenderingMode );
}
}
else {

View File

@ -2280,13 +2280,14 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
@Override
public Expression visitFunction(SqmFunction sqmFunction) {
inferableTypeAccessStack.push( () -> null );
shallownessStack.push( Shallowness.FUNCTION );
try {
//noinspection unchecked
return sqmFunction.convertToSqlAst( this );
}
finally {
shallownessStack.pop();
inferableTypeAccessStack.pop();
}
}

View File

@ -0,0 +1,27 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.ast;
/**
* @author Christian Beikov
*/
public enum SqlAstNodeRenderingMode {
/**
* Render node as is.
*/
DEFAULT,
/**
* Render parameters as literals.
*/
INLINE_PARAMETERS,
/**
* Don't render plain parameters. Render it as literal or as expression.
*/
NO_PLAIN_PARAMETER
}

View File

@ -9,6 +9,7 @@ package org.hibernate.sql.ast;
import java.util.Set;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.exec.spi.JdbcOperation;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
@ -16,6 +17,12 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings;
* @author Steve Ebersole
*/
public interface SqlAstTranslator<T extends JdbcOperation> extends SqlAstWalker {
/**
* Renders the given SQL AST node with the given rendering mode.
*/
void render(SqlAstNode sqlAstNode, SqlAstNodeRenderingMode renderingMode);
/**
* Not the best spot for this. Its the table names collected while walking the SQL AST.
* Its ok here because the translator is consider a one-time-use. It just needs to be called

View File

@ -8,6 +8,8 @@ package org.hibernate.sql.ast.spi;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
@ -25,13 +27,19 @@ import org.hibernate.metamodel.mapping.ModelPartContainer;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.query.Limit;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlTreeCreationException;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.Literal;
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.insert.InsertStatement;
@ -54,6 +62,7 @@ import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.exec.spi.JdbcUpdate;
import org.hibernate.sql.results.jdbc.internal.JdbcValuesMappingProducerStandard;
import org.hibernate.type.IntegerType;
import org.hibernate.type.StringType;
import static org.hibernate.sql.ast.SqlTreePrinter.logSqlAst;
import static org.hibernate.sql.results.graph.DomainResultGraphPrinter.logDomainResultGraph;
@ -68,6 +77,8 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation>
private final Statement statement;
private final Set<String> affectedTableNames = new HashSet<>();
private boolean inlineParameters;
private Map<JdbcParameter, JdbcParameterBinding> appliedParameterBindings = Collections.emptyMap();
private JdbcParameterBindings jdbcParameterBindings;
private LockOptions lockOptions;
@ -90,6 +101,84 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation>
return affectedTableNames;
}
@Override
public void render(SqlAstNode sqlAstNode, SqlAstNodeRenderingMode renderingMode) {
switch ( renderingMode ) {
case NO_PLAIN_PARAMETER:
if ( sqlAstNode instanceof SqmParameterInterpretation ) {
sqlAstNode = ( (SqmParameterInterpretation) sqlAstNode ).getResolvedExpression();
}
if ( sqlAstNode instanceof JdbcParameter ) {
final JdbcMapping jdbcMapping = ( (JdbcParameter) sqlAstNode ).getExpressionType().getJdbcMappings()
.get( 0 );
// We try to avoid inlining parameters if possible which can be done by wrapping the parameter
// in an expression that is semantically unnecessary e.g. numeric + 0 or concat with an empty string
switch ( jdbcMapping.getSqlTypeDescriptor().getJdbcTypeCode() ) {
case Types.BIT:
case Types.SMALLINT:
case Types.TINYINT:
case Types.INTEGER:
case Types.BIGINT:
case Types.DOUBLE:
case Types.REAL:
case Types.FLOAT:
case Types.NUMERIC:
case Types.DECIMAL:
sqlAstNode.accept( this );
appendSql( "+0" );
break;
case Types.CHAR:
case Types.VARCHAR:
case Types.LONGVARCHAR:
case Types.NCHAR:
case Types.NVARCHAR:
case Types.LONGNVARCHAR:
final SqmFunctionDescriptor sqmFunctionDescriptor = getSessionFactory().getQueryEngine()
.getSqmFunctionRegistry()
.findFunctionDescriptor( "concat" );
if ( sqmFunctionDescriptor instanceof AbstractSqmSelfRenderingFunctionDescriptor ) {
final List<SqlAstNode> list = new ArrayList<>( 2 );
list.add( sqlAstNode );
list.add( new QueryLiteral<>( "", StringType.INSTANCE ) );
( (AbstractSqmSelfRenderingFunctionDescriptor) sqmFunctionDescriptor )
.render( this, list, this );
break;
}
default:
renderExpressionAsLiteral( (Expression) sqlAstNode, jdbcParameterBindings );
break;
}
}
else {
sqlAstNode.accept( this );
}
break;
case INLINE_PARAMETERS:
boolean inlineParameters = this.inlineParameters;
this.inlineParameters = true;
try {
sqlAstNode.accept( this );
}
finally {
this.inlineParameters = inlineParameters;
}
break;
case DEFAULT:
default:
sqlAstNode.accept( this );
}
}
@Override
public void visitParameter(JdbcParameter jdbcParameter) {
if ( inlineParameters ) {
renderExpressionAsLiteral( jdbcParameter, jdbcParameterBindings );
}
else {
super.visitParameter( jdbcParameter );
}
}
protected void addAppliedParameterBinding(JdbcParameter parameter, JdbcParameterBinding binding) {
if ( appliedParameterBindings.isEmpty() ) {
appliedParameterBindings = new IdentityHashMap<>();
@ -197,6 +286,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation>
protected void renderExpressionAsLiteral(Expression expression, JdbcParameterBindings jdbcParameterBindings) {
if ( expression instanceof Literal ) {
expression.accept( this );
return;
}
else if ( expression instanceof JdbcParameter ) {
if ( jdbcParameterBindings == null ) {
@ -204,6 +294,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation>
}
final JdbcParameter parameter = (JdbcParameter) expression;
renderAsLiteral( parameter, getParameterBindValue( parameter ) );
return;
}
throw new UnsupportedOperationException( "Can't render expression as literal: " + expression );
}

View File

@ -48,6 +48,7 @@ import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
import org.hibernate.query.sqm.tree.expression.Conversion;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.tree.MutationStatement;
import org.hibernate.sql.ast.tree.SqlAstNode;
@ -2721,12 +2722,20 @@ public abstract class AbstractSqlAstWalker implements SqlAstWalker, SqlAppender
@Override
public void visitSelfRenderingPredicate(SelfRenderingPredicate selfRenderingPredicate) {
// todo (6.0) render boolean expression as comparison predicate if necessary
selfRenderingPredicate.getSelfRenderingExpression().renderToSql( this, this, getSessionFactory() );
selfRenderingPredicate.getSelfRenderingExpression().renderToSql(
this,
(SqlAstTranslator<?>) this,
getSessionFactory()
);
}
@Override
public void visitSelfRenderingExpression(SelfRenderingExpression expression) {
expression.renderToSql( this, this, getSessionFactory() );
expression.renderToSql(
this,
(SqlAstTranslator<?>) this,
getSessionFactory()
);
}
// @Override

View File

@ -8,7 +8,7 @@ package org.hibernate.sql.ast.tree.expression;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
/**
@ -27,7 +27,7 @@ public class LiteralAsParameter<T> implements SelfRenderingExpression {
}
@Override
public void renderToSql(SqlAppender sqlAppender, SqlAstWalker walker, SessionFactoryImplementor sessionFactory) {
public void renderToSql(SqlAppender sqlAppender, SqlAstTranslator<?> walker, SessionFactoryImplementor sessionFactory) {
sqlAppender.appendSql( "?" );
}

View File

@ -7,6 +7,7 @@
package org.hibernate.sql.ast.tree.expression;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.SqlAstWalker;
@ -19,5 +20,5 @@ public interface SelfRenderingExpression extends Expression {
sqlTreeWalker.visitSelfRenderingExpression( this );
}
void renderToSql(SqlAppender sqlAppender, SqlAstWalker walker, SessionFactoryImplementor sessionFactory);
void renderToSql(SqlAppender sqlAppender, SqlAstTranslator<?> walker, SessionFactoryImplementor sessionFactory);
}

View File

@ -264,7 +264,6 @@ public class FunctionTests {
}
@Test
@SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby doesn't support a parameter in the 'length' function or the 'char' function which we render as emulation")
public void testOverlayFunctionParameters(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
@ -338,7 +337,6 @@ public class FunctionTests {
}
@Test
@SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby doesn't support a parameter in the 'length' function or the 'char' function which we render as emulation")
public void testPadFunctionParameters(SessionFactoryScope scope) {
scope.inTransaction(
session -> {

View File

@ -104,6 +104,11 @@ public class PreparedStatementSpyConnectionProvider extends ConnectionProviderDe
}
Connection connectionSpy = spy( connection, settingsForConnections );
try {
// Apache Derby is object identity sensitive and calling setAutoCommit on the spy causes issues
Mockito.doAnswer( invocation -> {
connection.setAutoCommit( invocation.getArgument( 0 ) );
return null;
}).when( connectionSpy ).setAutoCommit( Mockito.anyBoolean() );
Mockito.doAnswer( invocation -> {
PreparedStatement statement = (PreparedStatement) invocation.callRealMethod();
PreparedStatement statementSpy = spy( statement, settingsForStatements );