HHH-18201 Configure NO_PLAIN_PARAMETER rendering mode for timestamps in timestampadd and -diff
This commit is contained in:
parent
edbece8125
commit
dba38f84fc
|
@ -1221,11 +1221,8 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
|||
|
||||
//timestampadd()/timestampdiff() delegated back to the Dialect itself
|
||||
//since there is a great variety of different ways to emulate them
|
||||
|
||||
functionContributions.getFunctionRegistry().register( "timestampadd",
|
||||
new TimestampaddFunction( this, typeConfiguration ) );
|
||||
functionContributions.getFunctionRegistry().register( "timestampdiff",
|
||||
new TimestampdiffFunction( this, typeConfiguration ) );
|
||||
//by default, we don't allow plain parameters for the timestamp argument as most database don't support this
|
||||
functionFactory.timestampaddAndDiff( this, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
|
||||
functionContributions.getFunctionRegistry().registerAlternateKey( "dateadd", "timestampadd" );
|
||||
functionContributions.getFunctionRegistry().registerAlternateKey( "datediff", "timestampdiff" );
|
||||
|
||||
|
|
|
@ -2381,6 +2381,29 @@ public class CommonFunctionFactory {
|
|||
.register();
|
||||
}
|
||||
|
||||
public void timestampaddAndDiff(Dialect dialect, SqlAstNodeRenderingMode timestampRenderingMode) {
|
||||
functionRegistry.register(
|
||||
"timestampadd",
|
||||
new TimestampaddFunction(
|
||||
dialect,
|
||||
typeConfiguration,
|
||||
SqlAstNodeRenderingMode.DEFAULT,
|
||||
SqlAstNodeRenderingMode.DEFAULT,
|
||||
timestampRenderingMode
|
||||
)
|
||||
);
|
||||
functionRegistry.register(
|
||||
"timestampdiff",
|
||||
new TimestampdiffFunction(
|
||||
dialect,
|
||||
typeConfiguration,
|
||||
SqlAstNodeRenderingMode.DEFAULT,
|
||||
timestampRenderingMode,
|
||||
timestampRenderingMode
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* MySQL style, returns the number of days between two dates
|
||||
*/
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
|||
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
|
||||
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;
|
||||
|
@ -47,8 +48,13 @@ public class TimestampaddFunction
|
|||
extends AbstractSqmSelfRenderingFunctionDescriptor {
|
||||
|
||||
private final Dialect dialect;
|
||||
private final SqlAstNodeRenderingMode[] renderingModes;
|
||||
|
||||
public TimestampaddFunction(Dialect dialect, TypeConfiguration typeConfiguration) {
|
||||
this( dialect, typeConfiguration, SqlAstNodeRenderingMode.DEFAULT );
|
||||
}
|
||||
|
||||
public TimestampaddFunction(Dialect dialect, TypeConfiguration typeConfiguration, SqlAstNodeRenderingMode... renderingModes) {
|
||||
super(
|
||||
"timestampadd",
|
||||
new ArgumentTypesValidator(
|
||||
|
@ -59,6 +65,7 @@ public class TimestampaddFunction
|
|||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TEMPORAL_UNIT, INTEGER, TEMPORAL )
|
||||
);
|
||||
this.dialect = dialect;
|
||||
this.renderingModes = renderingModes;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,7 +85,7 @@ public class TimestampaddFunction
|
|||
PatternRenderer patternRenderer(TemporalUnit unit, Expression interval, Expression to) {
|
||||
TemporalType temporalType = getSqlTemporalType( to.getExpressionType() );
|
||||
IntervalType intervalType = getSqlIntervalType( interval.getExpressionType().getSingleJdbcMapping() );
|
||||
return new PatternRenderer( dialect.timestampaddPattern( unit, temporalType, intervalType ) );
|
||||
return new PatternRenderer( dialect.timestampaddPattern( unit, temporalType, intervalType ), renderingModes );
|
||||
}
|
||||
|
||||
// @Override
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
|
|||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmDurationUnit;
|
||||
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;
|
||||
|
@ -56,8 +57,13 @@ public class TimestampdiffFunction
|
|||
extends AbstractSqmSelfRenderingFunctionDescriptor {
|
||||
|
||||
private final Dialect dialect;
|
||||
private final SqlAstNodeRenderingMode[] renderingModes;
|
||||
|
||||
public TimestampdiffFunction(Dialect dialect, TypeConfiguration typeConfiguration) {
|
||||
this( dialect, typeConfiguration, SqlAstNodeRenderingMode.DEFAULT );
|
||||
}
|
||||
|
||||
public TimestampdiffFunction(Dialect dialect, TypeConfiguration typeConfiguration, SqlAstNodeRenderingMode... renderingModes) {
|
||||
super(
|
||||
"timestampdiff",
|
||||
new ArgumentTypesValidator(
|
||||
|
@ -71,6 +77,7 @@ public class TimestampdiffFunction
|
|||
StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, TEMPORAL_UNIT, TEMPORAL, TEMPORAL )
|
||||
);
|
||||
this.dialect = dialect;
|
||||
this.renderingModes = renderingModes;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -90,7 +97,7 @@ public class TimestampdiffFunction
|
|||
private PatternRenderer patternRenderer(TemporalUnit unit, Expression from, Expression to) {
|
||||
TemporalType lhsTemporalType = getSqlTemporalType( from.getExpressionType() );
|
||||
TemporalType rhsTemporalType = getSqlTemporalType( to.getExpressionType() );
|
||||
return new PatternRenderer( dialect.timestampdiffPattern( unit, lhsTemporalType, rhsTemporalType ) );
|
||||
return new PatternRenderer( dialect.timestampdiffPattern( unit, lhsTemporalType, rhsTemporalType ), renderingModes );
|
||||
}
|
||||
|
||||
public SelfRenderingFunctionSqlAstExpression expression(
|
||||
|
|
|
@ -36,7 +36,7 @@ public class PatternRenderer {
|
|||
private final int[] paramIndexes;
|
||||
private final int varargParam;
|
||||
private final int maxParamIndex;
|
||||
private final SqlAstNodeRenderingMode argumentRenderingMode;
|
||||
private final SqlAstNodeRenderingMode[] argumentRenderingModes;
|
||||
|
||||
public PatternRenderer(String pattern) {
|
||||
this( pattern, SqlAstNodeRenderingMode.DEFAULT );
|
||||
|
@ -49,6 +49,16 @@ public class PatternRenderer {
|
|||
* @param argumentRenderingMode The rendering mode for arguments
|
||||
*/
|
||||
public PatternRenderer(String pattern, SqlAstNodeRenderingMode argumentRenderingMode) {
|
||||
this( pattern, new SqlAstNodeRenderingMode[] { argumentRenderingMode } );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a template renderer
|
||||
*
|
||||
* @param pattern The template
|
||||
* @param argumentRenderingModes The rendering modes for arguments
|
||||
*/
|
||||
public PatternRenderer(String pattern, SqlAstNodeRenderingMode[] argumentRenderingModes) {
|
||||
final Set<Integer> paramNumbers = new HashSet<>();
|
||||
final List<String> chunkList = new ArrayList<>();
|
||||
final List<Integer> paramList = new ArrayList<>();
|
||||
|
@ -116,7 +126,7 @@ public class PatternRenderer {
|
|||
paramIndexes[i] = paramList.get( i );
|
||||
}
|
||||
this.paramIndexes = paramIndexes;
|
||||
this.argumentRenderingMode = argumentRenderingMode;
|
||||
this.argumentRenderingModes = argumentRenderingModes;
|
||||
}
|
||||
|
||||
public boolean hasVarargs() {
|
||||
|
@ -185,6 +195,7 @@ public class PatternRenderer {
|
|||
|
||||
for ( int i = 0; i < chunks.length; i++ ) {
|
||||
if ( i == varargParam ) {
|
||||
final SqlAstNodeRenderingMode argumentRenderingMode = getArgumentRenderingMode(varargParam - 1);
|
||||
for ( int j = i; j < numberOfArguments; j++ ) {
|
||||
final SqlAstNode arg = args.get( j );
|
||||
if ( arg != null ) {
|
||||
|
@ -217,11 +228,11 @@ public class PatternRenderer {
|
|||
filter.accept( translator );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
sqlAppender.appendSql( " then " );
|
||||
translator.render( arg, argumentRenderingMode );
|
||||
translator.render( arg, getArgumentRenderingMode(index) );
|
||||
sqlAppender.appendSql( " else null end" );
|
||||
}
|
||||
else {
|
||||
translator.render( arg, argumentRenderingMode );
|
||||
translator.render( arg, getArgumentRenderingMode(index) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -233,10 +244,10 @@ public class PatternRenderer {
|
|||
if ( withinGroup != null && !withinGroup.isEmpty() ) {
|
||||
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
|
||||
sqlAppender.appendSql( " within group (order by" );
|
||||
translator.render( withinGroup.get( 0 ), argumentRenderingMode );
|
||||
translator.render( withinGroup.get( 0 ), getArgumentRenderingMode( 0 ) );
|
||||
for ( int i = 1; i < withinGroup.size(); i++ ) {
|
||||
sqlAppender.appendSql( SqlAppender.COMMA_SEPARATOR_CHAR );
|
||||
translator.render( withinGroup.get( 0 ), argumentRenderingMode );
|
||||
translator.render( withinGroup.get( 0 ), getArgumentRenderingMode( 0 ) );
|
||||
}
|
||||
sqlAppender.appendSql( ')' );
|
||||
translator.getCurrentClauseStack().pop();
|
||||
|
@ -267,4 +278,11 @@ public class PatternRenderer {
|
|||
translator.getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
private SqlAstNodeRenderingMode getArgumentRenderingMode(int index) {
|
||||
if ( index < argumentRenderingModes.length ) {
|
||||
return argumentRenderingModes[index];
|
||||
}
|
||||
return argumentRenderingModes[argumentRenderingModes.length - 1];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue