diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index 10ac712992..a85f50b337 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -259,6 +259,37 @@ public abstract class Dialect implements ConversionContext { uniqueDelegate = new DefaultUniqueDelegate( this ); } + /** + * Do the given JDBC type codes, as defined in {@link Types} represent + * essentially the same type in this dialect of SQL? The default + * implementation treats {@link Types#NUMERIC NUMERIC} and + * {@link Types#DECIMAL DECIMAL} as the same type, and + * {@link Types#FLOAT FLOAT}, {@link Types#REAL REAL}, and + * {@link Types#DOUBLE DOUBLE} as essentially the same type, since the + * ANSI SQL specification fails to meaningfully distinguish them. + * + * @param typeCode1 the first JDBC type code + * @param typeCode2 the second JDBC type code + * + * @return {@code true} if the two type codes are equivalent + */ + public boolean equivalentTypes(int typeCode1, int typeCode2) { + return typeCode1==typeCode2 + || isNumericOrDecimal(typeCode1) && isNumericOrDecimal(typeCode2) + || isFloatOrRealOrDouble(typeCode1) && isFloatOrRealOrDouble(typeCode2); + } + + private static boolean isNumericOrDecimal(int typeCode) { + return typeCode == Types.NUMERIC + || typeCode == Types.DECIMAL; + } + + private static boolean isFloatOrRealOrDouble(int typeCode) { + return typeCode == Types.FLOAT + || typeCode == Types.REAL + || typeCode == Types.DOUBLE; + } + /** * Get an instance of the dialect specified by the current System properties. * @deprecated this static method will be removed. diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java index 19b5ba57a2..50d132d9ea 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java @@ -420,9 +420,10 @@ public class Table implements RelationalModel, Serializable, Exportable { throw new HibernateException( "Missing column: " + col.getName() + " in " + Table.qualify( tableInfo.getCatalog(), tableInfo.getSchema(), tableInfo.getName())); } else { - final boolean typesMatch = col.getSqlType( dialect, mapping ).toLowerCase(Locale.ROOT) - .startsWith( columnInfo.getTypeName().toLowerCase(Locale.ROOT) ) - || columnInfo.getTypeCode() == col.getSqlTypeCode( mapping ); + final boolean typesMatch = + dialect.equivalentTypes( columnInfo.getTypeCode(), col.getSqlTypeCode( mapping ) ) + || col.getSqlType( dialect, mapping ).toLowerCase(Locale.ROOT) + .startsWith( columnInfo.getTypeName().toLowerCase(Locale.ROOT) ); if ( !typesMatch ) { throw new HibernateException( "Wrong column type in " + diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java index c9d0d5bfcf..b8abdec816 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java @@ -152,7 +152,7 @@ public abstract class AbstractSchemaValidator implements SchemaValidator { Metadata metadata, ExecutionOptions options, Dialect dialect) { - boolean typesMatch = column.getSqlTypeCode( metadata ) == columnInformation.getTypeCode() + boolean typesMatch = dialect.equivalentTypes( column.getSqlTypeCode( metadata ), columnInformation.getTypeCode() ) || column.getSqlType( dialect, metadata ).toLowerCase(Locale.ROOT).startsWith( columnInformation.getTypeName().toLowerCase(Locale.ROOT) ); if ( !typesMatch ) { throw new SchemaManagementException(