HHH-17693 Fix typecheck assertions for converted properties
Also introduce a custom `DurationJdbcType`, mainly for validation purposes.
This commit is contained in:
parent
658e9bc215
commit
6138c76c72
|
@ -686,7 +686,7 @@ public class MetadataBuildingProcess {
|
|||
);
|
||||
}
|
||||
else {
|
||||
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.INTERVAL_SECOND, SqlTypes.NUMERIC );
|
||||
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.INTERVAL_SECOND, SqlTypes.DURATION );
|
||||
}
|
||||
|
||||
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.INET, SqlTypes.VARBINARY );
|
||||
|
|
|
@ -776,6 +776,7 @@ public abstract class AbstractPostgreSQLStructJdbcType implements AggregateJdbcT
|
|||
case SqlTypes.DOUBLE:
|
||||
case SqlTypes.DECIMAL:
|
||||
case SqlTypes.NUMERIC:
|
||||
case SqlTypes.DURATION:
|
||||
jdbcJavaType.appendEncodedString(
|
||||
appender,
|
||||
jdbcJavaType.unwrap(
|
||||
|
|
|
@ -194,6 +194,7 @@ public class JsonHelper {
|
|||
break;
|
||||
case SqlTypes.DECIMAL:
|
||||
case SqlTypes.NUMERIC:
|
||||
case SqlTypes.DURATION:
|
||||
case SqlTypes.UUID:
|
||||
// These types need to be serialized as JSON string, but don't have a need for escaping
|
||||
appender.append( '"' );
|
||||
|
|
|
@ -564,6 +564,7 @@ public class XmlHelper {
|
|||
case SqlTypes.DOUBLE:
|
||||
case SqlTypes.DECIMAL:
|
||||
case SqlTypes.NUMERIC:
|
||||
case SqlTypes.DURATION:
|
||||
jdbcJavaType.appendEncodedString(
|
||||
appender,
|
||||
jdbcJavaType.unwrap(
|
||||
|
|
|
@ -546,7 +546,7 @@ public final class ConfigurationHelper {
|
|||
return explicitSetting;
|
||||
}
|
||||
|
||||
return SqlTypes.NUMERIC;
|
||||
return SqlTypes.DURATION;
|
||||
}
|
||||
|
||||
@Incubating
|
||||
|
|
|
@ -507,39 +507,24 @@ public class TypecheckUtil {
|
|||
public static void assertString(SqmExpression<?> expression) {
|
||||
final SqmExpressible<?> nodeType = expression.getNodeType();
|
||||
if ( nodeType != null ) {
|
||||
final Class<?> javaType = nodeType.getExpressibleJavaType().getJavaTypeClass();
|
||||
if ( javaType != String.class && javaType != char[].class ) {
|
||||
final DomainType<?> domainType = nodeType.getSqmType();
|
||||
if ( !( domainType instanceof JdbcMapping ) || !( (JdbcMapping) domainType ).getJdbcType().isStringLike() ) {
|
||||
throw new SemanticException(
|
||||
"Operand of 'like' is of type '" + nodeType.getTypeName() +
|
||||
"' which is not a string (it is not an instance of 'java.lang.String' or 'char[]')"
|
||||
"' which is not a string (its JDBC type code is not string-like)"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// public static void assertNumeric(SqmExpression<?> expression, BinaryArithmeticOperator op) {
|
||||
// final SqmExpressible<?> nodeType = expression.getNodeType();
|
||||
// if ( nodeType != null ) {
|
||||
// final Class<?> javaType = nodeType.getExpressibleJavaType().getJavaTypeClass();
|
||||
// if ( !Number.class.isAssignableFrom( javaType )
|
||||
// && !Temporal.class.isAssignableFrom( javaType )
|
||||
// && !TemporalAmount.class.isAssignableFrom( javaType )
|
||||
// && !java.util.Date.class.isAssignableFrom( javaType ) ) {
|
||||
// throw new SemanticException( "Operand of " + op.getOperatorSqlText()
|
||||
// + " is of type '" + nodeType.getTypeName() + "' which is not a numeric type"
|
||||
// + " (it is not an instance of 'java.lang.Number', 'java.time.Temporal', or 'java.time.TemporalAmount')" );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
public static void assertDuration(SqmExpression<?> expression) {
|
||||
final SqmExpressible<?> nodeType = expression.getNodeType();
|
||||
if ( nodeType != null ) {
|
||||
final Class<?> javaType = nodeType.getExpressibleJavaType().getJavaTypeClass();
|
||||
if ( !TemporalAmount.class.isAssignableFrom( javaType ) ) {
|
||||
final DomainType<?> domainType = nodeType.getSqmType();
|
||||
if ( !( domainType instanceof JdbcMapping ) || !( (JdbcMapping) domainType ).getJdbcType().isDuration() ) {
|
||||
throw new SemanticException(
|
||||
"Operand of 'by' is of type '" + nodeType.getTypeName() +
|
||||
"' which is not a duration (it is not an instance of 'java.time.TemporalAmount')"
|
||||
"' which is not a duration (its JDBC type code is not duration-like)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -548,11 +533,11 @@ public class TypecheckUtil {
|
|||
public static void assertNumeric(SqmExpression<?> expression, UnaryArithmeticOperator op) {
|
||||
final SqmExpressible<?> nodeType = expression.getNodeType();
|
||||
if ( nodeType != null ) {
|
||||
final Class<?> javaType = nodeType.getExpressibleJavaType().getJavaTypeClass();
|
||||
if ( !Number.class.isAssignableFrom( javaType ) ) {
|
||||
final DomainType<?> domainType = nodeType.getSqmType();
|
||||
if ( !( domainType instanceof JdbcMapping ) || !( (JdbcMapping) domainType ).getJdbcType().isNumber() ) {
|
||||
throw new SemanticException(
|
||||
"Operand of " + op.getOperatorChar() + " is of type '" + nodeType.getTypeName() +
|
||||
"' which is not a numeric type (it is not an instance of 'java.lang.Number')"
|
||||
"' which is not a numeric type (its JDBC type code is not numeric)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -498,6 +498,14 @@ public class SqlTypes {
|
|||
*/
|
||||
public static final int TIME_UTC = 3007;
|
||||
|
||||
/**
|
||||
* A type code representing a "virtual mapping" of {@linkplain java.time.Duration}.
|
||||
*
|
||||
* @see Types#NUMERIC
|
||||
* @see org.hibernate.type.descriptor.jdbc.DurationJdbcType
|
||||
*/
|
||||
public static final int DURATION = 3015;
|
||||
|
||||
// Interval types
|
||||
|
||||
/**
|
||||
|
@ -779,6 +787,13 @@ public class SqlTypes {
|
|||
return typeCode == INTERVAL_SECOND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the given typecode represent a {@code duration} type?
|
||||
*/
|
||||
public static boolean isDurationType(int typeCode) {
|
||||
return typeCode == DURATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the given typecode represent a SQL date or timestamp type?
|
||||
* @param typeCode a JDBC type code from {@link Types}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.type.descriptor.jdbc;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.time.Duration;
|
||||
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link java.time.Duration}.
|
||||
*
|
||||
* @author Marco Belladelli
|
||||
*/
|
||||
public class DurationJdbcType extends NumericJdbcType {
|
||||
public static final DurationJdbcType INSTANCE = new DurationJdbcType();
|
||||
|
||||
@Override
|
||||
public int getDdlTypeCode() {
|
||||
return Types.NUMERIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultSqlTypeCode() {
|
||||
return SqlTypes.DURATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return "DURATION";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DurationJdbcType";
|
||||
}
|
||||
}
|
|
@ -287,6 +287,12 @@ public interface JdbcType extends Serializable {
|
|||
return isIntervalType( getDdlTypeCode() );
|
||||
}
|
||||
|
||||
default boolean isDuration() {
|
||||
final int ddlTypeCode = getDefaultSqlTypeCode();
|
||||
return isDurationType( ddlTypeCode )
|
||||
|| isIntervalType( ddlTypeCode );
|
||||
}
|
||||
|
||||
default CastType getCastType() {
|
||||
return getCastType( getDdlTypeCode() );
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hibernate.type.descriptor.jdbc.ClobJdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.DateJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.DecimalJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.DoubleJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.DurationJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.FloatJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.IntegerJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
@ -66,6 +67,7 @@ public class JdbcTypeBaseline {
|
|||
target.addDescriptor( TimestampWithTimeZoneJdbcType.INSTANCE );
|
||||
target.addDescriptor( TimeJdbcType.INSTANCE );
|
||||
target.addDescriptor( TimeWithTimeZoneJdbcType.INSTANCE );
|
||||
target.addDescriptor( DurationJdbcType.INSTANCE );
|
||||
|
||||
target.addDescriptor( BinaryJdbcType.INSTANCE );
|
||||
target.addDescriptor( VarbinaryJdbcType.INSTANCE );
|
||||
|
|
Loading…
Reference in New Issue