From 20ce0d2001fe8e3c3775561567e38b123d526673 Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Mon, 8 Jan 2024 09:41:38 +0100 Subject: [PATCH] HBX-2716 - Remove floating point types from types advertised to support precision & scale Signed-off-by: Koen Aers --- .../java/org/hibernate/cfg/JDBCBinder.java | 4 +- .../cfg/reveng/BasicColumnProcessor.java | 7 +- .../DefaultReverseEngineeringStrategy.java | 5 +- .../cfg/reveng/JDBCToHibernateTypeHelper.java | 199 ------------------ .../cfg/reveng/OverrideRepository.java | 3 +- .../utils/JdbcToHibernateTypeHelper.java | 34 +-- .../detector/SchemaByMetaDataDetector.java | 4 +- 7 files changed, 34 insertions(+), 222 deletions(-) delete mode 100644 main/src/main/java/org/hibernate/cfg/reveng/JDBCToHibernateTypeHelper.java diff --git a/main/src/main/java/org/hibernate/cfg/JDBCBinder.java b/main/src/main/java/org/hibernate/cfg/JDBCBinder.java index 1cdf89f0f9..7422b5a4e8 100644 --- a/main/src/main/java/org/hibernate/cfg/JDBCBinder.java +++ b/main/src/main/java/org/hibernate/cfg/JDBCBinder.java @@ -28,11 +28,11 @@ import org.hibernate.cfg.reveng.AssociationInfo; import org.hibernate.cfg.reveng.DatabaseCollector; import org.hibernate.cfg.reveng.JDBCReader; -import org.hibernate.cfg.reveng.JDBCToHibernateTypeHelper; import org.hibernate.cfg.reveng.MappingsDatabaseCollector; import org.hibernate.cfg.reveng.RevEngUtils; import org.hibernate.cfg.reveng.ReverseEngineeringStrategy; import org.hibernate.cfg.reveng.TableIdentifier; +import org.hibernate.cfg.reveng.utils.JdbcToHibernateTypeHelper; import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.spi.Mapping; @@ -935,7 +935,7 @@ private String guessAndAlignType(Table table, Column column, Mapping mapping, bo } private String typeCodeName(int sqlTypeCode) { - return sqlTypeCode + "(" + JDBCToHibernateTypeHelper.getJDBCTypeName(sqlTypeCode) + ")"; + return sqlTypeCode + "(" + JdbcToHibernateTypeHelper.getJDBCTypeName(sqlTypeCode) + ")"; } /** diff --git a/main/src/main/java/org/hibernate/cfg/reveng/BasicColumnProcessor.java b/main/src/main/java/org/hibernate/cfg/reveng/BasicColumnProcessor.java index e3a87fd0cd..ab274d98e9 100644 --- a/main/src/main/java/org/hibernate/cfg/reveng/BasicColumnProcessor.java +++ b/main/src/main/java/org/hibernate/cfg/reveng/BasicColumnProcessor.java @@ -7,6 +7,7 @@ import org.hibernate.JDBCException; import org.hibernate.cfg.JDBCBinderException; import org.hibernate.cfg.reveng.dialect.MetaDataDialect; +import org.hibernate.cfg.reveng.utils.JdbcToHibernateTypeHelper; import org.hibernate.mapping.Column; import org.hibernate.mapping.Table; import org.hibernate.tool.util.TableNameQualifier; @@ -82,15 +83,15 @@ public static void processBasicColumns( column.setComment(comment); column.setSqlTypeCode(new Integer(sqlType) ); if(intBounds(size) ) { - if(JDBCToHibernateTypeHelper.typeHasLength(sqlType) ) { + if(JdbcToHibernateTypeHelper.typeHasLength(sqlType) ) { column.setLength(size); } - if(JDBCToHibernateTypeHelper.typeHasScaleAndPrecision(sqlType) ) { + if(JdbcToHibernateTypeHelper.typeHasPrecision(sqlType) ) { column.setPrecision(size); } } if(intBounds(decimalDigits) ) { - if(JDBCToHibernateTypeHelper.typeHasScaleAndPrecision(sqlType) ) { + if(JdbcToHibernateTypeHelper.typeHasScale(sqlType) ) { column.setScale(decimalDigits); } } diff --git a/main/src/main/java/org/hibernate/cfg/reveng/DefaultReverseEngineeringStrategy.java b/main/src/main/java/org/hibernate/cfg/reveng/DefaultReverseEngineeringStrategy.java index fb4718468b..b5d5959afd 100644 --- a/main/src/main/java/org/hibernate/cfg/reveng/DefaultReverseEngineeringStrategy.java +++ b/main/src/main/java/org/hibernate/cfg/reveng/DefaultReverseEngineeringStrategy.java @@ -10,6 +10,7 @@ import java.util.Properties; import java.util.Set; +import org.hibernate.cfg.reveng.utils.JdbcToHibernateTypeHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.mapping.Column; import org.hibernate.mapping.ForeignKey; @@ -106,11 +107,11 @@ public String foreignKeyToEntityName(String keyname, TableIdentifier fromTable, } public String columnToHibernateTypeName(TableIdentifier table, String columnName, int sqlType, int length, int precision, int scale, boolean nullable, boolean generatedIdentifier) { - String preferredHibernateType = JDBCToHibernateTypeHelper.getPreferredHibernateType(sqlType, length, precision, scale, nullable, generatedIdentifier); + String preferredHibernateType = JdbcToHibernateTypeHelper.getPreferredHibernateType(sqlType, length, precision, scale, nullable, generatedIdentifier); String location = ""; if(log.isDebugEnabled()) { - String info = " t:" + JDBCToHibernateTypeHelper.getJDBCTypeName( sqlType ) + " l:" + length + " p:" + precision + " s:" + scale + " n:" + nullable + " id:" + generatedIdentifier; + String info = " t:" + JdbcToHibernateTypeHelper.getJDBCTypeName( sqlType ) + " l:" + length + " p:" + precision + " s:" + scale + " n:" + nullable + " id:" + generatedIdentifier; if(table!=null) { location = TableNameQualifier.qualify(table.getCatalog(), table.getSchema(), table.getName() ) + "." + columnName + info; } else { diff --git a/main/src/main/java/org/hibernate/cfg/reveng/JDBCToHibernateTypeHelper.java b/main/src/main/java/org/hibernate/cfg/reveng/JDBCToHibernateTypeHelper.java deleted file mode 100644 index f921e1187f..0000000000 --- a/main/src/main/java/org/hibernate/cfg/reveng/JDBCToHibernateTypeHelper.java +++ /dev/null @@ -1,199 +0,0 @@ -package org.hibernate.cfg.reveng; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.sql.SQLException; -import java.sql.Types; -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.MappingException; - - -/** - * Utility class for mapping between sqltypes and hibernate type names. - * - * @author max (based on parts from Sql2Java from Middlegen) - * - */ -public final class JDBCToHibernateTypeHelper { - - private JDBCToHibernateTypeHelper() { - - } - - /** The Map containing the preferred conversion type values. */ - private static final Map PREFERRED_HIBERNATETYPE_FOR_SQLTYPE = new HashMap(); - - static { - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.TINYINT), new String[] { "byte", Byte.class.getName()} ); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.SMALLINT), new String[] { "short", Short.class.getName()} ); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.INTEGER), new String[] { "int", Integer.class.getName()} ); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.BIGINT), new String[] { "long", Long.class.getName()} ); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.REAL), new String[] { "float", Float.class.getName()} ); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.FLOAT), new String[] { "double", Double.class.getName()} ); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.DOUBLE), new String[] { "double", Double.class.getName()}); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.DECIMAL), new String[] { "big_decimal", "big_decimal" }); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.NUMERIC), new String[] { "big_decimal", "big_decimal" }); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.BIT), new String[] { "boolean", Boolean.class.getName()}); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.BOOLEAN), new String[] { "boolean", Boolean.class.getName()}); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.CHAR), new String[] { "char", Character.class.getName()}); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.VARCHAR), new String[] { "string", "string" }); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.LONGVARCHAR), new String[] { "string", "string" }); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.BINARY), new String[] { "binary", "binary" }); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.VARBINARY), new String[] { "binary", "binary" }); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.LONGVARBINARY), new String[] { "binary", "binary" }); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.DATE), new String[] { "date", "date" }); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.TIME), new String[] { "time", "time" }); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.TIMESTAMP), new String[] { "timestamp", "timestamp" }); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.CLOB), new String[] { "clob", "clob" }); - PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.BLOB), new String[] { "blob", "blob" }); - - //Hibernate does not have any built-in Type for these: - //preferredJavaTypeForSqlType.put(new Integer(Types.ARRAY), "java.sql.Array"); - //preferredJavaTypeForSqlType.put(new Integer(Types.REF), "java.sql.Ref"); - //preferredJavaTypeForSqlType.put(new Integer(Types.STRUCT), "java.lang.Object"); - //preferredJavaTypeForSqlType.put(new Integer(Types.JAVA_OBJECT), "java.lang.Object"); - } - - /* (non-Javadoc) - * @see org.hibernate.cfg.JDBCTypeToHibernateTypesStrategy#getPreferredHibernateType(int, int, int, int) - */ - public static String getPreferredHibernateType(int sqlType, int size, int precision, int scale, boolean nullable, boolean generatedIdentifier) { - boolean returnNullable = nullable || generatedIdentifier; - if ( (sqlType == Types.DECIMAL || sqlType == Types.NUMERIC) && scale <= 0) { // <= - if (precision == 1) { - // NUMERIC(1) is a often used idiom for storing boolean thus providing it out of the box. - return returnNullable?Boolean.class.getName():"boolean"; - } - else if (precision < 3) { - return returnNullable?Byte.class.getName():"byte"; - } - else if (precision < 5) { - return returnNullable?Short.class.getName():"short"; - } - else if (precision < 10) { - return returnNullable?Integer.class.getName():"int"; - } - else if (precision < 19) { - return returnNullable?Long.class.getName():"long"; - } - else { - return "big_integer"; - } - } - - if ( sqlType == Types.CHAR && size>1 ) { - return "string"; - } - - String[] result = (String[]) PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.get(new Integer(sqlType) ); - - if(result==null) { - return null; - } else if(returnNullable) { - return result[1]; - } else { - return result[0]; - } - } - - static Map jdbcTypes; // Name to value - static Map jdbcTypeValues; // value to Name - - public static String[] getJDBCTypes() { - checkTypes(); - - return (String[]) jdbcTypes.keySet().toArray(new String[jdbcTypes.size()]); - } - - public static int getJDBCType(String value) { - checkTypes(); - - Integer number = (Integer) jdbcTypes.get(value); - - if(number==null) { - try { - return Integer.parseInt(value); - } - catch (NumberFormatException nfe) { - throw new MappingException("jdbc-type: " + value + " is not a known JDBC Type nor a valid number"); - } - } - else { - return number.intValue(); - } - } - - private static void checkTypes() { - if(jdbcTypes==null) { - jdbcTypes = new HashMap(); - Field[] fields = Types.class.getFields(); - for (int i = 0; i < fields.length; i++) { - Field field = fields[i]; - if(Modifier.isStatic(field.getModifiers() ) ) { - try { - jdbcTypes.put(field.getName(), (Integer)field.get(Types.class) ); - } - catch (IllegalArgumentException e) { - // ignore - } - catch (IllegalAccessException e) { - // ignore - } - } - } - } - } - - public static String getJDBCTypeName(int value) { - if(jdbcTypeValues==null) { - jdbcTypeValues = new HashMap(); - Field[] fields = Types.class.getFields(); - for (int i = 0; i < fields.length; i++) { - Field field = fields[i]; - if(Modifier.isStatic(field.getModifiers() ) ) { - try { - jdbcTypeValues.put((Integer)field.get(Types.class), field.getName() ); - } - catch (IllegalArgumentException e) { - // ignore - } - catch (IllegalAccessException e) { - // ignore - } - } - } - } - - String name = (String) jdbcTypeValues.get(new Integer(value) ); - - if(name!=null) { - return name; - } - else { - return ""+value; - } - } - - /** - * @param table - * @param schema - * @param catalog - * @throws SQLException - */ - - // scale and precision have numeric column - public static boolean typeHasScaleAndPrecision(int sqlType) { - return (sqlType == Types.DECIMAL || sqlType == Types.NUMERIC - || sqlType == Types.REAL || sqlType == Types.FLOAT || sqlType == Types.DOUBLE); - } - - // length is for string column - public static boolean typeHasLength(int sqlType) { - return (sqlType == Types.CHAR || sqlType == Types.DATE - || sqlType == Types.LONGVARCHAR || sqlType == Types.TIME || sqlType == Types.TIMESTAMP - || sqlType == Types.VARCHAR ); - } -} - diff --git a/main/src/main/java/org/hibernate/cfg/reveng/OverrideRepository.java b/main/src/main/java/org/hibernate/cfg/reveng/OverrideRepository.java index b729a6637e..0642536209 100644 --- a/main/src/main/java/org/hibernate/cfg/reveng/OverrideRepository.java +++ b/main/src/main/java/org/hibernate/cfg/reveng/OverrideRepository.java @@ -20,6 +20,7 @@ import org.apache.commons.collections4.MapIterator; import org.apache.commons.collections4.MultiValuedMap; import org.hibernate.MappingException; +import org.hibernate.cfg.reveng.utils.JdbcToHibernateTypeHelper; import org.hibernate.cfg.reveng.utils.MetaAttributeHelper; import org.hibernate.cfg.reveng.utils.MetaAttributeHelper.SimpleMetaAttribute; import org.hibernate.internal.util.StringHelper; @@ -318,7 +319,7 @@ public List getSchemaSelections() { public String columnToHibernateTypeName(TableIdentifier table, String columnName, int sqlType, int length, int precision, int scale, boolean nullable, boolean generatedIdentifier) { String result = null; String location = ""; - String info = " t:" + JDBCToHibernateTypeHelper.getJDBCTypeName( sqlType ) + " l:" + length + " p:" + precision + " s:" + scale + " n:" + nullable + " id:" + generatedIdentifier; + String info = " t:" + JdbcToHibernateTypeHelper.getJDBCTypeName( sqlType ) + " l:" + length + " p:" + precision + " s:" + scale + " n:" + nullable + " id:" + generatedIdentifier; if(table!=null) { location = TableNameQualifier.qualify(table.getCatalog(), table.getSchema(), table.getName() ) + "." + columnName; } else { diff --git a/main/src/main/java/org/hibernate/cfg/reveng/utils/JdbcToHibernateTypeHelper.java b/main/src/main/java/org/hibernate/cfg/reveng/utils/JdbcToHibernateTypeHelper.java index cca86a6029..0d03569032 100644 --- a/main/src/main/java/org/hibernate/cfg/reveng/utils/JdbcToHibernateTypeHelper.java +++ b/main/src/main/java/org/hibernate/cfg/reveng/utils/JdbcToHibernateTypeHelper.java @@ -183,17 +183,25 @@ public static String getJDBCTypeName(int value) { * @throws SQLException */ - // scale and precision have numeric column - public static boolean typeHasScaleAndPrecision(int sqlType) { - return (sqlType == Types.DECIMAL || sqlType == Types.NUMERIC - || sqlType == Types.REAL || sqlType == Types.FLOAT || sqlType == Types.DOUBLE); - } - - // length is for string column - public static boolean typeHasLength(int sqlType) { - return (sqlType == Types.CHAR || sqlType == Types.DATE - || sqlType == Types.LONGVARCHAR || sqlType == Types.TIME || sqlType == Types.TIMESTAMP - || sqlType == Types.VARCHAR ); - } -} + // scale is for non floating point numeric columns + public static boolean typeHasScale(int sqlType) { + return (sqlType == Types.DECIMAL || sqlType == Types.NUMERIC); + } + + // precision is for numeric columns + public static boolean typeHasPrecision(int sqlType) { + return (sqlType == Types.DECIMAL || sqlType == Types.NUMERIC + || sqlType == Types.REAL || sqlType == Types.FLOAT || sqlType == Types.DOUBLE); + } + public static boolean typeHasScaleAndPrecision(int sqlType) { + return typeHasScale(sqlType) && typeHasPrecision(sqlType); + } + + // length is for string columns + public static boolean typeHasLength(int sqlType) { + return (sqlType == Types.CHAR || sqlType == Types.DATE + || sqlType == Types.LONGVARCHAR || sqlType == Types.TIME || sqlType == Types.TIMESTAMP + || sqlType == Types.VARCHAR ); + } +} diff --git a/main/src/main/java/org/hibernate/tool/hbmlint/detector/SchemaByMetaDataDetector.java b/main/src/main/java/org/hibernate/tool/hbmlint/detector/SchemaByMetaDataDetector.java index a1eee037a5..dee75fade1 100644 --- a/main/src/main/java/org/hibernate/tool/hbmlint/detector/SchemaByMetaDataDetector.java +++ b/main/src/main/java/org/hibernate/tool/hbmlint/detector/SchemaByMetaDataDetector.java @@ -16,8 +16,8 @@ import org.hibernate.cfg.reveng.DefaultDatabaseCollector; import org.hibernate.cfg.reveng.DefaultReverseEngineeringStrategy; import org.hibernate.cfg.reveng.JDBCReader; -import org.hibernate.cfg.reveng.JDBCToHibernateTypeHelper; import org.hibernate.cfg.reveng.SchemaSelection; +import org.hibernate.cfg.reveng.utils.JdbcToHibernateTypeHelper; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.spi.Mapping; @@ -201,7 +201,7 @@ public void visit( pc.reportIssue( new Issue( "SCHEMA_COLUMN_TYPE_MISMATCH", Issue.NORMAL_PRIORITY, table(table) + " has a wrong column type for " + col.getName() + ", expected: " - + JDBCToHibernateTypeHelper.getJDBCTypeName(modelTypeCode) + " but was " + JDBCToHibernateTypeHelper.getJDBCTypeName(dbTypeCode) + " in db") ); + + JdbcToHibernateTypeHelper.getJDBCTypeName(modelTypeCode) + " but was " + JdbcToHibernateTypeHelper.getJDBCTypeName(dbTypeCode) + " in db") ); } } }