HHH-18201 Handle SqmBinaryArithmetic in determineValueMapping
This commit is contained in:
parent
dba38f84fc
commit
cf0e4d4622
|
@ -9,6 +9,7 @@ package org.hibernate.dialect;
|
|||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.hibernate.boot.model.FunctionContributions;
|
||||
import org.hibernate.boot.model.TypeContributions;
|
||||
|
@ -510,7 +511,11 @@ public class DerbyDialect extends Dialect {
|
|||
case NATIVE:
|
||||
return "{fn timestampadd(sql_tsi_frac_second,mod(bigint(?2),1000000000),{fn timestampadd(sql_tsi_second,bigint((?2)/1000000000),?3)})}";
|
||||
default:
|
||||
return "{fn timestampadd(sql_tsi_?1,bigint(?2),?3)}";
|
||||
final String addExpression = "{fn timestampadd(sql_tsi_?1,bigint(?2),?3)}";
|
||||
// Since timestampadd will always produce a TIMESTAMP, we have to cast back to the intended type
|
||||
return temporalType == TemporalType.TIMESTAMP
|
||||
? addExpression
|
||||
: "cast(" + addExpression + " as " + temporalType.name().toLowerCase( Locale.ROOT ) + ")" ;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6010,6 +6010,21 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
);
|
||||
}
|
||||
|
||||
if ( sqmExpression instanceof SqmBinaryArithmetic<?> ) {
|
||||
final SqmBinaryArithmetic<?> binaryArithmetic = (SqmBinaryArithmetic<?>) sqmExpression;
|
||||
if ( binaryArithmetic.getNodeType() == null ) {
|
||||
final MappingModelExpressible<?> lhs = determineValueMapping( binaryArithmetic.getLeftHandOperand() );
|
||||
final MappingModelExpressible<?> rhs = determineValueMapping( binaryArithmetic.getRightHandOperand() );
|
||||
// This cast should be fine since the result of this will be a BasicType
|
||||
return (MappingModelExpressible<?>) getTypeConfiguration().resolveArithmeticType(
|
||||
// These casts should be safe, since the only JdbcMapping is BasicType
|
||||
// which also implements SqmExpressible
|
||||
lhs == null ? null : (SqmExpressible<?>) lhs.getSingleJdbcMapping(),
|
||||
rhs == null ? null : (SqmExpressible<?>) rhs.getSingleJdbcMapping()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
log.debugf( "Determining mapping-model type for generalized SqmExpression : %s", sqmExpression );
|
||||
final SqmExpressible<?> nodeType = sqmExpression.getNodeType();
|
||||
if ( nodeType == null ) {
|
||||
|
@ -6536,11 +6551,20 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
SqmExpression<?> leftOperand = expression.getLeftHandOperand();
|
||||
SqmExpression<?> rightOperand = expression.getRightHandOperand();
|
||||
|
||||
boolean durationToRight = isDuration( rightOperand.getNodeType() );
|
||||
TypeConfiguration typeConfiguration = getCreationContext().getMappingMetamodel().getTypeConfiguration();
|
||||
TemporalType temporalTypeToLeft = typeConfiguration.getSqlTemporalType( leftOperand.getNodeType() );
|
||||
TemporalType temporalTypeToRight = typeConfiguration.getSqlTemporalType( rightOperand.getNodeType() );
|
||||
boolean temporalTypeSomewhereToLeft = adjustedTimestamp != null || temporalTypeToLeft != null;
|
||||
// Need to infer the operand types here first to decide how to transform the expression
|
||||
final FromClauseIndex fromClauseIndex = fromClauseIndexStack.getCurrent();
|
||||
inferrableTypeAccessStack.push( () -> determineValueMapping( rightOperand, fromClauseIndex ) );
|
||||
final MappingModelExpressible<?> leftOperandType = determineValueMapping( leftOperand );
|
||||
inferrableTypeAccessStack.pop();
|
||||
inferrableTypeAccessStack.push( () -> determineValueMapping( leftOperand, fromClauseIndex ) );
|
||||
final MappingModelExpressible<?> rightOperandType = determineValueMapping( rightOperand );
|
||||
inferrableTypeAccessStack.pop();
|
||||
|
||||
final boolean durationToRight = isDuration( rightOperand.getNodeType() );
|
||||
final TypeConfiguration typeConfiguration = getCreationContext().getMappingMetamodel().getTypeConfiguration();
|
||||
final TemporalType temporalTypeToLeft = typeConfiguration.getSqlTemporalType( leftOperandType );
|
||||
final TemporalType temporalTypeToRight = typeConfiguration.getSqlTemporalType( rightOperandType );
|
||||
final boolean temporalTypeSomewhereToLeft = adjustedTimestamp != null || temporalTypeToLeft != null;
|
||||
|
||||
if ( temporalTypeToLeft != null && durationToRight ) {
|
||||
if ( adjustmentScale != null || negativeAdjustment ) {
|
||||
|
@ -6557,7 +6581,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
else {
|
||||
// Infer one operand type through the other
|
||||
final FromClauseIndex fromClauseIndex = fromClauseIndexStack.getCurrent();
|
||||
inferrableTypeAccessStack.push( () -> determineValueMapping( rightOperand, fromClauseIndex ) );
|
||||
final Expression lhs = toSqlExpression( leftOperand.accept( this ) );
|
||||
inferrableTypeAccessStack.pop();
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.time.LocalDate;
|
|||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
@ -49,6 +50,7 @@ import org.hibernate.internal.CoreMessageLogger;
|
|||
import org.hibernate.internal.SessionFactoryRegistry;
|
||||
import org.hibernate.jpa.spi.JpaCompliance;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressible;
|
||||
|
@ -821,6 +823,17 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
|
|||
if ( type instanceof BasicValuedMapping ) {
|
||||
return getSqlTemporalType( ( (BasicValuedMapping) type ).getJdbcMapping().getJdbcType() );
|
||||
}
|
||||
else if ( type instanceof EmbeddableValuedModelPart ) {
|
||||
// Handle the special embeddables for emulated offset/timezone handling
|
||||
final Class<?> javaTypeClass = ( (EmbeddableValuedModelPart) type ).getJavaType().getJavaTypeClass();
|
||||
if ( javaTypeClass == OffsetDateTime.class
|
||||
|| javaTypeClass == ZonedDateTime.class ) {
|
||||
return TemporalType.TIMESTAMP;
|
||||
}
|
||||
else if ( javaTypeClass == OffsetTime.class ) {
|
||||
return TemporalType.TIME;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue