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