HHH-14204 Schema validator should be more forgiving of column type mismatches

This commit is contained in:
Gavin King 2020-09-02 22:18:42 +02:00 committed by Sanne Grinovero
parent 3846001907
commit f203bda5db
3 changed files with 36 additions and 4 deletions

View File

@ -259,6 +259,37 @@ public abstract class Dialect implements ConversionContext {
uniqueDelegate = new DefaultUniqueDelegate( this ); 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 <tt>System</tt> properties. * Get an instance of the dialect specified by the current <tt>System</tt> properties.
* @deprecated this static method will be removed. * @deprecated this static method will be removed.

View File

@ -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())); throw new HibernateException( "Missing column: " + col.getName() + " in " + Table.qualify( tableInfo.getCatalog(), tableInfo.getSchema(), tableInfo.getName()));
} }
else { else {
final boolean typesMatch = col.getSqlType( dialect, mapping ).toLowerCase(Locale.ROOT) final boolean typesMatch =
.startsWith( columnInfo.getTypeName().toLowerCase(Locale.ROOT) ) dialect.equivalentTypes( columnInfo.getTypeCode(), col.getSqlTypeCode( mapping ) )
|| columnInfo.getTypeCode() == col.getSqlTypeCode( mapping ); || col.getSqlType( dialect, mapping ).toLowerCase(Locale.ROOT)
.startsWith( columnInfo.getTypeName().toLowerCase(Locale.ROOT) );
if ( !typesMatch ) { if ( !typesMatch ) {
throw new HibernateException( throw new HibernateException(
"Wrong column type in " + "Wrong column type in " +

View File

@ -152,7 +152,7 @@ public abstract class AbstractSchemaValidator implements SchemaValidator {
Metadata metadata, Metadata metadata,
ExecutionOptions options, ExecutionOptions options,
Dialect dialect) { 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) ); || column.getSqlType( dialect, metadata ).toLowerCase(Locale.ROOT).startsWith( columnInformation.getTypeName().toLowerCase(Locale.ROOT) );
if ( !typesMatch ) { if ( !typesMatch ) {
throw new SchemaManagementException( throw new SchemaManagementException(