mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-08 20:24:46 +00:00
HHH-17693 Fix typecheck assertions for converted properties
Also introduce a custom `DurationJdbcType`, mainly for validation purposes.
This commit is contained in:
parent
8a993f4057
commit
50e6cb62e2
@ -686,7 +686,7 @@ public void contributeType(CompositeUserType<?> type) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.INTERVAL_SECOND, SqlTypes.NUMERIC );
|
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.INTERVAL_SECOND, SqlTypes.DURATION );
|
||||||
}
|
}
|
||||||
|
|
||||||
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.INET, SqlTypes.VARBINARY );
|
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.INET, SqlTypes.VARBINARY );
|
||||||
|
@ -776,6 +776,7 @@ private void serializeBasicTo(
|
|||||||
case SqlTypes.DOUBLE:
|
case SqlTypes.DOUBLE:
|
||||||
case SqlTypes.DECIMAL:
|
case SqlTypes.DECIMAL:
|
||||||
case SqlTypes.NUMERIC:
|
case SqlTypes.NUMERIC:
|
||||||
|
case SqlTypes.DURATION:
|
||||||
jdbcJavaType.appendEncodedString(
|
jdbcJavaType.appendEncodedString(
|
||||||
appender,
|
appender,
|
||||||
jdbcJavaType.unwrap(
|
jdbcJavaType.unwrap(
|
||||||
|
@ -194,6 +194,7 @@ else if ( mappedType instanceof BasicType<?> ) {
|
|||||||
break;
|
break;
|
||||||
case SqlTypes.DECIMAL:
|
case SqlTypes.DECIMAL:
|
||||||
case SqlTypes.NUMERIC:
|
case SqlTypes.NUMERIC:
|
||||||
|
case SqlTypes.DURATION:
|
||||||
case SqlTypes.UUID:
|
case SqlTypes.UUID:
|
||||||
// These types need to be serialized as JSON string, but don't have a need for escaping
|
// These types need to be serialized as JSON string, but don't have a need for escaping
|
||||||
appender.append( '"' );
|
appender.append( '"' );
|
||||||
|
@ -564,6 +564,7 @@ private static void serializeValueTo(XMLAppender appender, SelectableMapping sel
|
|||||||
case SqlTypes.DOUBLE:
|
case SqlTypes.DOUBLE:
|
||||||
case SqlTypes.DECIMAL:
|
case SqlTypes.DECIMAL:
|
||||||
case SqlTypes.NUMERIC:
|
case SqlTypes.NUMERIC:
|
||||||
|
case SqlTypes.DURATION:
|
||||||
jdbcJavaType.appendEncodedString(
|
jdbcJavaType.appendEncodedString(
|
||||||
appender,
|
appender,
|
||||||
jdbcJavaType.unwrap(
|
jdbcJavaType.unwrap(
|
||||||
|
@ -546,7 +546,7 @@ public static synchronized int getPreferredSqlTypeCodeForDuration(StandardServic
|
|||||||
return explicitSetting;
|
return explicitSetting;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SqlTypes.NUMERIC;
|
return SqlTypes.DURATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Incubating
|
@Incubating
|
||||||
|
@ -507,39 +507,24 @@ private static boolean isNumberArray(SqmExpressible<?> expressible) {
|
|||||||
public static void assertString(SqmExpression<?> expression) {
|
public static void assertString(SqmExpression<?> expression) {
|
||||||
final SqmExpressible<?> nodeType = expression.getNodeType();
|
final SqmExpressible<?> nodeType = expression.getNodeType();
|
||||||
if ( nodeType != null ) {
|
if ( nodeType != null ) {
|
||||||
final Class<?> javaType = nodeType.getExpressibleJavaType().getJavaTypeClass();
|
final DomainType<?> domainType = nodeType.getSqmType();
|
||||||
if ( javaType != String.class && javaType != char[].class ) {
|
if ( !( domainType instanceof JdbcMapping ) || !( (JdbcMapping) domainType ).getJdbcType().isStringLike() ) {
|
||||||
throw new SemanticException(
|
throw new SemanticException(
|
||||||
"Operand of 'like' is of type '" + nodeType.getTypeName() +
|
"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) {
|
public static void assertDuration(SqmExpression<?> expression) {
|
||||||
final SqmExpressible<?> nodeType = expression.getNodeType();
|
final SqmExpressible<?> nodeType = expression.getNodeType();
|
||||||
if ( nodeType != null ) {
|
if ( nodeType != null ) {
|
||||||
final Class<?> javaType = nodeType.getExpressibleJavaType().getJavaTypeClass();
|
final DomainType<?> domainType = nodeType.getSqmType();
|
||||||
if ( !TemporalAmount.class.isAssignableFrom( javaType ) ) {
|
if ( !( domainType instanceof JdbcMapping ) || !( (JdbcMapping) domainType ).getJdbcType().isDuration() ) {
|
||||||
throw new SemanticException(
|
throw new SemanticException(
|
||||||
"Operand of 'by' is of type '" + nodeType.getTypeName() +
|
"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 static void assertDuration(SqmExpression<?> expression) {
|
|||||||
public static void assertNumeric(SqmExpression<?> expression, UnaryArithmeticOperator op) {
|
public static void assertNumeric(SqmExpression<?> expression, UnaryArithmeticOperator op) {
|
||||||
final SqmExpressible<?> nodeType = expression.getNodeType();
|
final SqmExpressible<?> nodeType = expression.getNodeType();
|
||||||
if ( nodeType != null ) {
|
if ( nodeType != null ) {
|
||||||
final Class<?> javaType = nodeType.getExpressibleJavaType().getJavaTypeClass();
|
final DomainType<?> domainType = nodeType.getSqmType();
|
||||||
if ( !Number.class.isAssignableFrom( javaType ) ) {
|
if ( !( domainType instanceof JdbcMapping ) || !( (JdbcMapping) domainType ).getJdbcType().isNumber() ) {
|
||||||
throw new SemanticException(
|
throw new SemanticException(
|
||||||
"Operand of " + op.getOperatorChar() + " is of type '" + nodeType.getTypeName() +
|
"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)"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -571,6 +571,13 @@ public class SqlTypes {
|
|||||||
*/
|
*/
|
||||||
public static final int ZONED_DATE_TIME = 3014;
|
public static final int ZONED_DATE_TIME = 3014;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
// Interval types
|
||||||
|
|
||||||
@ -854,6 +861,13 @@ public static boolean isIntervalType(int typeCode) {
|
|||||||
return typeCode == INTERVAL_SECOND;
|
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?
|
* Does the given typecode represent a SQL date or timestamp type?
|
||||||
* @param typeCode a JDBC type code from {@link Types}
|
* @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 @@ default boolean isInterval() {
|
|||||||
return isIntervalType( getDdlTypeCode() );
|
return isIntervalType( getDdlTypeCode() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default boolean isDuration() {
|
||||||
|
final int ddlTypeCode = getDefaultSqlTypeCode();
|
||||||
|
return isDurationType( ddlTypeCode )
|
||||||
|
|| isIntervalType( ddlTypeCode );
|
||||||
|
}
|
||||||
|
|
||||||
default CastType getCastType() {
|
default CastType getCastType() {
|
||||||
return getCastType( getDdlTypeCode() );
|
return getCastType( getDdlTypeCode() );
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
import org.hibernate.type.descriptor.jdbc.DateJdbcType;
|
import org.hibernate.type.descriptor.jdbc.DateJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.DecimalJdbcType;
|
import org.hibernate.type.descriptor.jdbc.DecimalJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.DoubleJdbcType;
|
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.FloatJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.InstantJdbcType;
|
import org.hibernate.type.descriptor.jdbc.InstantJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.IntegerJdbcType;
|
import org.hibernate.type.descriptor.jdbc.IntegerJdbcType;
|
||||||
@ -81,6 +82,7 @@ public static void prime(BaselineTarget target) {
|
|||||||
target.addDescriptor( TimestampWithTimeZoneJdbcType.INSTANCE );
|
target.addDescriptor( TimestampWithTimeZoneJdbcType.INSTANCE );
|
||||||
target.addDescriptor( TimeJdbcType.INSTANCE );
|
target.addDescriptor( TimeJdbcType.INSTANCE );
|
||||||
target.addDescriptor( TimeWithTimeZoneJdbcType.INSTANCE );
|
target.addDescriptor( TimeWithTimeZoneJdbcType.INSTANCE );
|
||||||
|
target.addDescriptor( DurationJdbcType.INSTANCE );
|
||||||
|
|
||||||
target.addDescriptor( BinaryJdbcType.INSTANCE );
|
target.addDescriptor( BinaryJdbcType.INSTANCE );
|
||||||
target.addDescriptor( VarbinaryJdbcType.INSTANCE );
|
target.addDescriptor( VarbinaryJdbcType.INSTANCE );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user