From 623ee20bb6834041a9467578f3c3e6beb9d271e3 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 21 Dec 2012 20:54:14 +0100 Subject: [PATCH] [#456] Add runtime support for PRECISION, SCALE, and LENGTH attributes - Renamed AbstractDataType to DefaultDataType, made it non-abstract - Removed [SQLDialect]DataType from DefaultDataType's type hierarchy --- .../java/org/jooq/util/JavaGenerator.java | 14 +- .../util/AbstractTypedElementDefinition.java | 8 +- .../jooq/util/DefaultDataTypeDefinition.java | 2 +- .../java/org/jooq/impl/AbstractDataType.java | 679 ------------------ .../java/org/jooq/impl/ArrayDataType.java | 2 +- .../java/org/jooq/impl/ConvertedDataType.java | 2 +- .../main/java/org/jooq/impl/DefaultArray.java | 2 +- .../org/jooq/impl/DefaultBindContext.java | 2 +- .../java/org/jooq/impl/DefaultDataType.java | 643 ++++++++++++++++- jOOQ/src/main/java/org/jooq/impl/Factory.java | 2 +- .../org/jooq/impl/MetaDataFieldProvider.java | 2 +- .../src/main/java/org/jooq/impl/MetaImpl.java | 2 +- .../main/java/org/jooq/impl/SQLDataType.java | 2 +- .../main/java/org/jooq/impl/UDTDataType.java | 2 +- jOOQ/src/main/java/org/jooq/impl/Val.java | 6 +- .../java/org/jooq/util/ase/ASEDataType.java | 101 ++- .../org/jooq/util/cubrid/CUBRIDDataType.java | 120 ++-- .../java/org/jooq/util/db2/DB2DataType.java | 91 +-- .../org/jooq/util/derby/DerbyDataType.java | 113 ++- .../jooq/util/firebird/FirebirdDataType.java | 92 ++- .../java/org/jooq/util/h2/H2DataType.java | 141 ++-- .../org/jooq/util/hsqldb/HSQLDBDataType.java | 103 ++- .../org/jooq/util/ingres/IngresDataType.java | 133 ++-- .../org/jooq/util/mysql/MySQLDataType.java | 109 ++- .../org/jooq/util/oracle/OracleDataType.java | 129 ++-- .../jooq/util/postgres/PostgresDataType.java | 142 ++-- .../org/jooq/util/sqlite/SQLiteDataType.java | 94 ++- .../util/sqlserver/SQLServerDataType.java | 95 ++- .../org/jooq/util/sybase/SybaseDataType.java | 102 ++- .../test/java/org/jooq/test/TestDataType.java | 4 +- 30 files changed, 1380 insertions(+), 1559 deletions(-) delete mode 100644 jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java diff --git a/jOOQ-codegen/src/main/java/org/jooq/util/JavaGenerator.java b/jOOQ-codegen/src/main/java/org/jooq/util/JavaGenerator.java index 57e2ab1833..ea902df0ec 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/util/JavaGenerator.java +++ b/jOOQ-codegen/src/main/java/org/jooq/util/JavaGenerator.java @@ -67,7 +67,7 @@ import org.jooq.UDT; import org.jooq.UDTField; import org.jooq.UniqueKey; import org.jooq.exception.SQLDialectNotSupportedException; -import org.jooq.impl.AbstractDataType; +import org.jooq.impl.DefaultDataType; import org.jooq.impl.AbstractKeys; import org.jooq.impl.AbstractRoutine; import org.jooq.impl.ArrayRecordImpl; @@ -2422,7 +2422,7 @@ public class JavaGenerator extends AbstractGenerator { // Try finding a basic standard SQL type according to the current dialect else { try { - Class clazz = AbstractDataType.getType(db.getDialect(), t, p, s); + Class clazz = DefaultDataType.getType(db.getDialect(), t, p, s); type = clazz.getCanonicalName(); if (clazz.getTypeParameters().length > 0) { @@ -2471,7 +2471,7 @@ public class JavaGenerator extends AbstractGenerator { sb.append("."); sb.append(db.getDialect().getName()); sb.append("DataType."); - sb.append(AbstractDataType.normalise(AbstractDataType.getDataType(db.getDialect(), String.class).getTypeName())); + sb.append(DefaultDataType.normalise(DefaultDataType.getDataType(db.getDialect(), String.class).getTypeName())); sb.append(".asEnumDataType("); sb.append(getStrategy().getFullJavaClassName(db.getEnum(schema, u))); sb.append(".class)"); @@ -2480,7 +2480,7 @@ public class JavaGenerator extends AbstractGenerator { DataType dataType = null; try { - dataType = AbstractDataType.getDataType(db.getDialect(), t, p, s); + dataType = DefaultDataType.getDataType(db.getDialect(), t, p, s); } // Mostly because of unsupported data types. Will be handled later. @@ -2494,7 +2494,7 @@ public class JavaGenerator extends AbstractGenerator { sb.append(SQLDataType.class.getCanonicalName()); sb.append("."); - sb.append(AbstractDataType.normalise(sqlDataType.getTypeName())); + sb.append(DefaultDataType.normalise(sqlDataType.getTypeName())); if (db.getConfiguredCustomType(u) != null) { sb.append(".asConvertedDataType(new "); @@ -2518,14 +2518,14 @@ public class JavaGenerator extends AbstractGenerator { try { String type1 = getType(db, schema, t, p, s, u, null); String type2 = getType(db, schema, t, 0, 0, u, null); - String typeName = AbstractDataType.normalise(t); + String typeName = DefaultDataType.normalise(t); // [#1298] Prevent compilation errors for missing types Reflect.on(typeClass).field(typeName); sb.append(typeName); if (!type1.equals(type2)) { - Class clazz = AbstractDataType.getType(db.getDialect(), t, p, s); + Class clazz = DefaultDataType.getType(db.getDialect(), t, p, s); sb.append(".asNumberDataType("); sb.append(clazz.getCanonicalName()); diff --git a/jOOQ-meta/src/main/java/org/jooq/util/AbstractTypedElementDefinition.java b/jOOQ-meta/src/main/java/org/jooq/util/AbstractTypedElementDefinition.java index d0c7cb4127..0bcf069749 100644 --- a/jOOQ-meta/src/main/java/org/jooq/util/AbstractTypedElementDefinition.java +++ b/jOOQ-meta/src/main/java/org/jooq/util/AbstractTypedElementDefinition.java @@ -42,7 +42,7 @@ import java.util.List; import org.jooq.DataType; import org.jooq.exception.SQLDialectNotSupportedException; -import org.jooq.impl.AbstractDataType; +import org.jooq.impl.DefaultDataType; import org.jooq.impl.SQLDataType; import org.jooq.tools.JooqLogger; import org.jooq.util.jaxb.ForcedType; @@ -108,7 +108,7 @@ abstract class AbstractTypedElementDefinition int s = definedType.getScale(); try { - forcedDataType = AbstractDataType.getDataType(db.getDialect(), forcedType.getName(), p, s); + forcedDataType = DefaultDataType.getDataType(db.getDialect(), forcedType.getName(), p, s); } catch (SQLDialectNotSupportedException ignore) {} // [#677] SQLDataType matches are actual type-rewrites @@ -127,12 +127,12 @@ abstract class AbstractTypedElementDefinition DataType dataType = null; try { - dataType = AbstractDataType.getDataType(db.getDialect(), definedType.getType(), 0, 0); + dataType = DefaultDataType.getDataType(db.getDialect(), definedType.getType(), 0, 0); } catch (SQLDialectNotSupportedException ignore) {} if (dataType != null) { if (dataType.getSQLType() == Types.DATE) { - DataType forcedDataType = AbstractDataType.getDataType(db.getDialect(), SQLDataType.TIMESTAMP.getTypeName(), 0, 0); + DataType forcedDataType = DefaultDataType.getDataType(db.getDialect(), SQLDataType.TIMESTAMP.getTypeName(), 0, 0); type = new DefaultDataTypeDefinition(db, getSchema(), forcedDataType.getTypeName(), 0, 0, 0); } } diff --git a/jOOQ-meta/src/main/java/org/jooq/util/DefaultDataTypeDefinition.java b/jOOQ-meta/src/main/java/org/jooq/util/DefaultDataTypeDefinition.java index 62cd92419f..8465b24bc2 100644 --- a/jOOQ-meta/src/main/java/org/jooq/util/DefaultDataTypeDefinition.java +++ b/jOOQ-meta/src/main/java/org/jooq/util/DefaultDataTypeDefinition.java @@ -36,7 +36,7 @@ package org.jooq.util; -import static org.jooq.impl.AbstractDataType.normalise; +import static org.jooq.impl.DefaultDataType.normalise; import org.jooq.SQLDialect; import org.jooq.util.oracle.OracleDataType; diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java deleted file mode 100644 index 08873560d1..0000000000 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java +++ /dev/null @@ -1,679 +0,0 @@ -/** - * Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com - * All rights reserved. - * - * This software is licensed to you under the Apache License, Version 2.0 - * (the "License"); You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * . Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * . Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * . Neither the name "jOOQ" nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -package org.jooq.impl; - -import static org.jooq.impl.SQLDataType.BLOB; -import static org.jooq.impl.SQLDataType.CLOB; -import static org.jooq.impl.SQLDataType.NCLOB; - -import java.lang.reflect.Array; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.jooq.ArrayRecord; -import org.jooq.Configuration; -import org.jooq.Converter; -import org.jooq.DataType; -import org.jooq.EnumType; -import org.jooq.Result; -import org.jooq.SQLDialect; -import org.jooq.UDTRecord; -import org.jooq.exception.SQLDialectNotSupportedException; -import org.jooq.tools.Convert; -import org.jooq.types.Interval; - -/** - * A common base class for data types. - *

- * This also acts as a static data type registry for jOOQ internally. - *

- * This type is for JOOQ INTERNAL USE only. Do not reference directly - * - * @author Lukas Eder - */ -@SuppressWarnings({"unchecked", "deprecation"}) -public abstract class AbstractDataType implements DataType { - - /** - * Generated UID - */ - private static final long serialVersionUID = 4155588654449505119L; - - /** - * A pattern for data type name normalisation - */ - private static final Pattern NORMALISE_PATTERN = Pattern.compile("\"|\\.|\\s|\\(\\w+(,\\w+)*\\)|(NOT\\s*NULL)?"); - - // ------------------------------------------------------------------------- - // Data type caches - // ------------------------------------------------------------------------- - - /** - * A cache for dialect-specific data types by normalised - */ - private static final Map>[] TYPES_BY_NAME; - - /** - * A cache for dialect-specific data types by Java type - */ - private static final Map, DataType>[] TYPES_BY_TYPE; - - /** - * A cache for dialect-specific data types by SQL DataTypes - */ - private static final Map, DataType>[] TYPES_BY_SQL_DATATYPE; - - /** - * A cache for SQL DataTypes by Java type - */ - private static final Map, DataType> SQL_DATATYPES_BY_TYPE; - - // ------------------------------------------------------------------------- - // Precisions - // ------------------------------------------------------------------------- - - /** - * The minimum decimal precision needed to represent a Java {@link Long} type - */ - private static final int LONG_PRECISION = String.valueOf(Long.MAX_VALUE).length(); - - /** - * The minimum decimal precision needed to represent a Java {@link Integer} type - */ - private static final int INTEGER_PRECISION = String.valueOf(Integer.MAX_VALUE).length(); - - /** - * The minimum decimal precision needed to represent a Java {@link Short} type - */ - private static final int SHORT_PRECISION = String.valueOf(Short.MAX_VALUE).length(); - - /** - * The minimum decimal precision needed to represent a Java {@link Byte} type - */ - private static final int BYTE_PRECISION = String.valueOf(Byte.MAX_VALUE).length(); - - // ------------------------------------------------------------------------- - // Data type attributes - // ------------------------------------------------------------------------- - - /** - * The SQL dialect associated with this data type - */ - private final SQLDialect dialect; - - /** - * The SQL DataType corresponding to this data type - */ - private final SQLDataType sqlDataType; - - /** - * The Java class corresponding to this data type - */ - private final Class type; - - /** - * The Java class corresponding to arrays of this data type - */ - private final Class arrayType; - - /** - * The type name used for casting to this type - */ - private final String castTypeName; - - /** - * The type name - */ - private final String typeName; - - static { - TYPES_BY_SQL_DATATYPE = new Map[SQLDialect.values().length]; - TYPES_BY_NAME = new Map[SQLDialect.values().length]; - TYPES_BY_TYPE = new Map[SQLDialect.values().length]; - - for (SQLDialect dialect : SQLDialect.values()) { - TYPES_BY_SQL_DATATYPE[dialect.ordinal()] = new LinkedHashMap, DataType>(); - TYPES_BY_NAME[dialect.ordinal()] = new LinkedHashMap>(); - TYPES_BY_TYPE[dialect.ordinal()] = new LinkedHashMap, DataType>(); - } - - SQL_DATATYPES_BY_TYPE = new LinkedHashMap, DataType>(); - } - - protected AbstractDataType(SQLDialect dialect, SQLDataType sqlDataType, Class type, String typeName) { - this(dialect, sqlDataType, type, typeName, typeName); - } - - protected AbstractDataType(SQLDialect dialect, SQLDataType sqlDataType, Class type, String typeName, String castTypeName) { - this.dialect = dialect; - - // [#858] SQLDataTypes should reference themselves for more convenience - this.sqlDataType = (SQLDataType) ((this instanceof SQLDataType) ? this : sqlDataType); - this.type = type; - this.typeName = typeName; - this.castTypeName = castTypeName; - this.arrayType = (Class) Array.newInstance(type, 0).getClass(); - - init(); - } - - private final void init() { - - // Dialect-specific data types - int ordinal = dialect == null ? SQLDialect.SQL99.ordinal() : dialect.ordinal(); - String normalised = AbstractDataType.normalise(typeName); - - if (TYPES_BY_NAME[ordinal].get(normalised) == null) { - TYPES_BY_NAME[ordinal].put(normalised, this); - } - - if (TYPES_BY_TYPE[ordinal].get(type) == null) { - TYPES_BY_TYPE[ordinal].put(type, this); - } - - if (TYPES_BY_SQL_DATATYPE[ordinal].get(sqlDataType) == null) { - TYPES_BY_SQL_DATATYPE[ordinal].put(sqlDataType, this); - } - - // Global data types - if (dialect == null) { - if (SQL_DATATYPES_BY_TYPE.get(type) == null) { - SQL_DATATYPES_BY_TYPE.put(type, this); - } - } - } - - @Override - public final SQLDataType getSQLDataType() { - return sqlDataType; - } - - @Override - public final DataType getDataType(Configuration configuration) { - - // If this is a SQLDataType find the most suited dialect-specific - // data type - if (getDialect() == null) { - DataType dataType = TYPES_BY_SQL_DATATYPE[configuration.getDialect().ordinal()].get(this); - - if (dataType != null) { - return (DataType) dataType; - } - } - - // If this is already the dialect's specific data type, return this - else if (getDialect() == configuration.getDialect()) { - return this; - } - - // If the SQL data type is not available stick with this data type - else if (getSQLDataType() == null) { - return this; - } - - // If this is another dialect's specific data type, recurse - else { - getSQLDataType().getDataType(configuration); - } - - return this; - } - - @Override - public /* final */ int getSQLType() { - // TODO [#1227] There is some confusion with these types, especially - // when it comes to byte[] which can be mapped to BLOB, BINARY, VARBINARY - - if (type == Blob.class) { - return Types.BLOB; - } - else if (type == Boolean.class) { - return Types.BOOLEAN; - } - else if (type == BigInteger.class) { - return Types.BIGINT; - } - else if (type == BigDecimal.class) { - return Types.DECIMAL; - } - else if (type == Byte.class) { - return Types.TINYINT; - } - else if (type == byte[].class) { - return Types.BLOB; - } - else if (type == Clob.class) { - return Types.CLOB; - } - else if (type == Date.class) { - return Types.DATE; - } - else if (type == Double.class) { - return Types.DOUBLE; - } - else if (type == Float.class) { - return Types.FLOAT; - } - else if (type == Integer.class) { - return Types.INTEGER; - } - else if (type == Long.class) { - return Types.BIGINT; - } - else if (type == Short.class) { - return Types.SMALLINT; - } - else if (type == String.class) { - return Types.VARCHAR; - } - else if (type == Time.class) { - return Types.TIME; - } - else if (type == Timestamp.class) { - return Types.TIMESTAMP; - } - - // The type byte[] is handled earlier. - else if (type.isArray()) { - return Types.ARRAY; - } - else if (ArrayRecord.class.isAssignableFrom(type)) { - return Types.ARRAY; - } - else if (EnumType.class.isAssignableFrom(type)) { - return Types.VARCHAR; - } - else if (UDTRecord.class.isAssignableFrom(type)) { - return Types.STRUCT; - } - else if (Result.class.isAssignableFrom(type)) { - switch (dialect) { - case ORACLE: - case H2: - return -10; // OracleTypes.CURSOR; - - case POSTGRES: - default: - return Types.OTHER; - } - } - else { - return Types.OTHER; - } - } - - @Override - public final Class getType() { - return type; - } - - @Override - public final Class getArrayType() { - return arrayType; - } - - @Override - public final String getTypeName() { - return typeName; - } - - @Override - public String getTypeName(Configuration configuration) { - return getDataType(configuration).getTypeName(); - } - - @Override - public final String getCastTypeName() { - return castTypeName; - } - - @Override - public /* final */ String getCastTypeName(Configuration configuration, int length) { - String result = getCastTypeName(configuration); - - if (length != 0) { - - // Remove existing length information, first - result = result.replaceAll("\\([^\\)]*\\)", ""); - result += "(" + length + ")"; - } - - return result; - } - - @Override - public /* final */ String getCastTypeName(Configuration configuration, int precision, int scale) { - String result = getCastTypeName(configuration); - - if (precision != 0) { - - // Remove existing precision / scale information, first - result = result.replaceAll("\\([^\\)]*\\)", ""); - - if (scale != 0) { - result += "(" + precision + ", " + scale + ")"; - } - else { - result += "(" + precision + ")"; - } - } - - return result; - } - - @Override - public String getCastTypeName(Configuration configuration) { - return getDataType(configuration).getCastTypeName(); - } - - @Override - public final DataType getArrayDataType() { - return new ArrayDataType(this); - } - - @Override - public final > DataType asArrayDataType(Class arrayDataType) { - return new DefaultDataType(dialect, arrayDataType, typeName, castTypeName); - } - - @Override - public final DataType asEnumDataType(Class enumDataType) { - return new DefaultDataType(dialect, enumDataType, typeName, castTypeName); - } - - @Override - public final DataType asConvertedDataType(Converter converter) { - return new ConvertedDataType(this, converter); - } - - @Override - public final SQLDialect getDialect() { - return dialect; - } - - @Override - public /* final */ T convert(Object object) { - - // [#1441] Avoid unneeded type conversions to improve performance - if (object == null) { - return null; - } - else if (object.getClass() == type) { - return (T) object; - } - else { - return Convert.convert(object, type); - } - } - - @Override - public final T[] convert(Object... objects) { - return (T[]) Convert.convertArray(objects, type); - } - - @Override - public final List convert(Collection objects) { - return Convert.convert(objects, type); - } - - public static DataType getDefaultDataType(String typeName) { - return new DefaultDataType(SQLDialect.SQL99, Object.class, typeName, typeName); - } - - public static DataType getDefaultDataType(SQLDialect dialect, String typeName) { - return new DefaultDataType(dialect, Object.class, typeName, typeName); - } - - public static DataType getDataType(SQLDialect dialect, String typeName) { - String normalised = AbstractDataType.normalise(typeName); - DataType result = TYPES_BY_NAME[dialect.ordinal()].get(normalised); - - // UDT data types and others are registered using SQL99 - if (result == null) { - result = TYPES_BY_NAME[SQLDialect.SQL99.ordinal()].get(normalised); - } - - if (result == null) { - // [#366] Don't log a warning here. The warning is logged when - // catching the exception in jOOQ-codegen - throw new SQLDialectNotSupportedException("Type " + typeName + " is not supported in dialect " + dialect, false); - } - - return result; - } - - public static DataType getDataType(SQLDialect dialect, Class type) { - - // Recurse for arrays - if (byte[].class != type && type.isArray()) { - return (DataType) getDataType(dialect, type.getComponentType()).getArrayDataType(); - } - - // Base types are registered statically - else { - DataType result = null; - - if (dialect != null) { - result = TYPES_BY_TYPE[dialect.ordinal()].get(type); - } - - if (result == null) { - - // jOOQ data types are handled here - if (EnumType.class.isAssignableFrom(type) || - UDTRecord.class.isAssignableFrom(type) || - ArrayRecord.class.isAssignableFrom(type)) { - - for (SQLDialect d : SQLDialect.values()) { - result = TYPES_BY_TYPE[d.ordinal()].get(type); - - if (result != null) { - break; - } - } - } - } - - if (result == null) { - if (SQL_DATATYPES_BY_TYPE.get(type) != null) { - return (DataType) SQL_DATATYPES_BY_TYPE.get(type); - } - - // All other data types are illegal - else { - throw new SQLDialectNotSupportedException("Type " + type + " is not supported in dialect " + dialect); - } - } - - return (DataType) result; - } - } - - @Override - public final boolean isNumeric() { - return Number.class.isAssignableFrom(type) && !isInterval(); - } - - @Override - public final boolean isString() { - return type == String.class; - } - - @Override - public final boolean isDateTime() { - return java.util.Date.class.isAssignableFrom(type); - } - - @Override - public final boolean isTemporal() { - return isDateTime() || isInterval(); - } - - @Override - public final boolean isInterval() { - return Interval.class.isAssignableFrom(type); - } - - @Override - public final boolean isLob() { - SQLDataType t = getSQLDataType(); - return (t == BLOB || t == CLOB || t == NCLOB); - } - - @Override - public final boolean isBinary() { - return type == byte[].class; - } - - @Override - public final boolean isArray() { - return ArrayRecord.class.isAssignableFrom(type) - || (!isBinary() && type.isArray()); - } - - // ------------------------------------------------------------------------ - // The Object API - // ------------------------------------------------------------------------ - - @Override - public String toString() { - return getClass().getSimpleName() + " [" + type + ", " + typeName + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((dialect == null) ? 0 : dialect.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + ((typeName == null) ? 0 : typeName.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - AbstractDataType other = (AbstractDataType) obj; - if (dialect != other.dialect) - return false; - if (type == null) { - if (other.type != null) - return false; - } - else if (!type.equals(other.type)) - return false; - if (typeName == null) { - if (other.typeName != null) - return false; - } - else if (!typeName.equals(other.typeName)) - return false; - return true; - } - - /** - * @return The type name without all special characters and white spaces - */ - public static String normalise(String typeName) { - return NORMALISE_PATTERN.matcher(typeName.toUpperCase()).replaceAll(""); - } - - /** - * Convert a type name (using precision and scale) into a Java class - */ - public static DataType getDataType(SQLDialect dialect, String t, int p, int s) throws SQLDialectNotSupportedException { - DataType result = AbstractDataType.getDataType(dialect, AbstractDataType.normalise(t)); - - if (result.getType() == BigDecimal.class) { - result = AbstractDataType.getDataType(dialect, getNumericClass(p, s)); - } - - return result; - } - - /** - * Convert a type name (using precision and scale) into a Java class - */ - public static Class getType(SQLDialect dialect, String t, int p, int s) throws SQLDialectNotSupportedException { - return getDataType(dialect, t, p, s).getType(); - } - - /** - * Get the most suitable Java class for a given precision and scale - */ - private static Class getNumericClass(int precision, int scale) { - - // Integer numbers - if (scale == 0 && precision != 0) { - if (precision < BYTE_PRECISION) { - return Byte.class; - } - if (precision < SHORT_PRECISION) { - return Short.class; - } - if (precision < INTEGER_PRECISION) { - return Integer.class; - } - if (precision < LONG_PRECISION) { - return Long.class; - } - - // Default integer number - return BigInteger.class; - } - - // Real numbers should not be represented as float or double - else { - return BigDecimal.class; - } - } -} diff --git a/jOOQ/src/main/java/org/jooq/impl/ArrayDataType.java b/jOOQ/src/main/java/org/jooq/impl/ArrayDataType.java index 9aa714bb16..ddcc78d7a3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ArrayDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/ArrayDataType.java @@ -43,7 +43,7 @@ import org.jooq.DataType; * * @author Lukas Eder */ -class ArrayDataType extends AbstractDataType { +class ArrayDataType extends DefaultDataType { /** * Generated UID diff --git a/jOOQ/src/main/java/org/jooq/impl/ConvertedDataType.java b/jOOQ/src/main/java/org/jooq/impl/ConvertedDataType.java index eb09e46143..ed8639f432 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ConvertedDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/ConvertedDataType.java @@ -44,7 +44,7 @@ import org.jooq.DataType; * * @author Lukas Eder */ -class ConvertedDataType extends AbstractDataType { +class ConvertedDataType extends DefaultDataType { /** * Generated UID diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultArray.java b/jOOQ/src/main/java/org/jooq/impl/DefaultArray.java index 6bb48dc40f..91965ca86f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultArray.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultArray.java @@ -56,7 +56,7 @@ class DefaultArray implements Array { @Override public String getBaseTypeName() { - return AbstractDataType.getDataType(dialect, type.getComponentType()).getTypeName(); + return DefaultDataType.getDataType(dialect, type.getComponentType()).getTypeName(); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java index b96d2ef04d..f5cd2b8a29 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java @@ -126,7 +126,7 @@ class DefaultBindContext extends AbstractBindContext { // Setting null onto a prepared statement is subtly different for every // SQL dialect. See the following section for details if (value == null) { - int sqlType = AbstractDataType.getDataType(dialect, type).getSQLType(); + int sqlType = DefaultDataType.getDataType(dialect, type).getSQLType(); // Oracle-style ARRAY types need to be bound with their type name if (ArrayRecord.class.isAssignableFrom(type)) { diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java b/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java index 5c6fa40df7..4efa22f232 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java @@ -35,22 +35,653 @@ */ package org.jooq.impl; +import static org.jooq.impl.SQLDataType.BLOB; +import static org.jooq.impl.SQLDataType.CLOB; +import static org.jooq.impl.SQLDataType.NCLOB; + +import java.lang.reflect.Array; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import org.jooq.ArrayRecord; +import org.jooq.Configuration; +import org.jooq.Converter; +import org.jooq.DataType; +import org.jooq.EnumType; +import org.jooq.Result; import org.jooq.SQLDialect; +import org.jooq.UDTRecord; +import org.jooq.exception.SQLDialectNotSupportedException; +import org.jooq.tools.Convert; +import org.jooq.types.Interval; /** - * A default data type for data types without any specific features or unknown - * data types. + * A common base class for data types. + *

+ * This also acts as a static data type registry for jOOQ internally. + *

+ * This type is for JOOQ INTERNAL USE only. Do not reference directly * * @author Lukas Eder */ -class DefaultDataType extends AbstractDataType { +@SuppressWarnings({"unchecked", "deprecation"}) +public class DefaultDataType implements DataType { /** * Generated UID */ - private static final long serialVersionUID = -2612295936942892367L; + private static final long serialVersionUID = 4155588654449505119L; - DefaultDataType(SQLDialect dialect, Class type, String typeName, String castTypeName) { - super(dialect, null, type, typeName, castTypeName); + /** + * A pattern for data type name normalisation + */ + private static final Pattern NORMALISE_PATTERN = Pattern.compile("\"|\\.|\\s|\\(\\w+(,\\w+)*\\)|(NOT\\s*NULL)?"); + + // ------------------------------------------------------------------------- + // Data type caches + // ------------------------------------------------------------------------- + + /** + * A cache for dialect-specific data types by normalised + */ + private static final Map>[] TYPES_BY_NAME; + + /** + * A cache for dialect-specific data types by Java type + */ + private static final Map, DataType>[] TYPES_BY_TYPE; + + /** + * A cache for dialect-specific data types by SQL DataTypes + */ + private static final Map, DataType>[] TYPES_BY_SQL_DATATYPE; + + /** + * A cache for SQL DataTypes by Java type + */ + private static final Map, DataType> SQL_DATATYPES_BY_TYPE; + + // ------------------------------------------------------------------------- + // Precisions + // ------------------------------------------------------------------------- + + /** + * The minimum decimal precision needed to represent a Java {@link Long} type + */ + private static final int LONG_PRECISION = String.valueOf(Long.MAX_VALUE).length(); + + /** + * The minimum decimal precision needed to represent a Java {@link Integer} type + */ + private static final int INTEGER_PRECISION = String.valueOf(Integer.MAX_VALUE).length(); + + /** + * The minimum decimal precision needed to represent a Java {@link Short} type + */ + private static final int SHORT_PRECISION = String.valueOf(Short.MAX_VALUE).length(); + + /** + * The minimum decimal precision needed to represent a Java {@link Byte} type + */ + private static final int BYTE_PRECISION = String.valueOf(Byte.MAX_VALUE).length(); + + // ------------------------------------------------------------------------- + // Data type attributes + // ------------------------------------------------------------------------- + + /** + * The SQL dialect associated with this data type + */ + private final SQLDialect dialect; + + /** + * The SQL DataType corresponding to this data type + */ + private final SQLDataType sqlDataType; + + /** + * The Java class corresponding to this data type + */ + private final Class type; + + /** + * The Java class corresponding to arrays of this data type + */ + private final Class arrayType; + + /** + * The type name used for casting to this type + */ + private final String castTypeName; + + /** + * The type name + */ + private final String typeName; + + static { + TYPES_BY_SQL_DATATYPE = new Map[SQLDialect.values().length]; + TYPES_BY_NAME = new Map[SQLDialect.values().length]; + TYPES_BY_TYPE = new Map[SQLDialect.values().length]; + + for (SQLDialect dialect : SQLDialect.values()) { + TYPES_BY_SQL_DATATYPE[dialect.ordinal()] = new LinkedHashMap, DataType>(); + TYPES_BY_NAME[dialect.ordinal()] = new LinkedHashMap>(); + TYPES_BY_TYPE[dialect.ordinal()] = new LinkedHashMap, DataType>(); + } + + SQL_DATATYPES_BY_TYPE = new LinkedHashMap, DataType>(); + } + + public DefaultDataType(SQLDialect dialect, SQLDataType sqlDataType, String typeName) { + this(dialect, sqlDataType, sqlDataType.getType(), typeName, typeName); + } + + public DefaultDataType(SQLDialect dialect, SQLDataType sqlDataType, String typeName, String castTypeName) { + this(dialect, sqlDataType, sqlDataType.getType(), typeName, castTypeName); + } + + public DefaultDataType(SQLDialect dialect, SQLDataType sqlDataType, Class type, String typeName) { + this(dialect, sqlDataType, type, typeName, typeName); + } + + public DefaultDataType(SQLDialect dialect, SQLDataType sqlDataType, Class type, String typeName, String castTypeName) { + this.dialect = dialect; + + // [#858] SQLDataTypes should reference themselves for more convenience + this.sqlDataType = (SQLDataType) ((this instanceof SQLDataType) ? this : sqlDataType); + this.type = type; + this.typeName = typeName; + this.castTypeName = castTypeName; + this.arrayType = (Class) Array.newInstance(type, 0).getClass(); + + init(); + } + + private final void init() { + + // Dialect-specific data types + int ordinal = dialect == null ? SQLDialect.SQL99.ordinal() : dialect.ordinal(); + String normalised = DefaultDataType.normalise(typeName); + + if (TYPES_BY_NAME[ordinal].get(normalised) == null) { + TYPES_BY_NAME[ordinal].put(normalised, this); + } + + if (TYPES_BY_TYPE[ordinal].get(type) == null) { + TYPES_BY_TYPE[ordinal].put(type, this); + } + + if (TYPES_BY_SQL_DATATYPE[ordinal].get(sqlDataType) == null) { + TYPES_BY_SQL_DATATYPE[ordinal].put(sqlDataType, this); + } + + // Global data types + if (dialect == null) { + if (SQL_DATATYPES_BY_TYPE.get(type) == null) { + SQL_DATATYPES_BY_TYPE.put(type, this); + } + } + } + + @Override + public final SQLDataType getSQLDataType() { + return sqlDataType; + } + + @Override + public final DataType getDataType(Configuration configuration) { + + // If this is a SQLDataType find the most suited dialect-specific + // data type + if (getDialect() == null) { + DataType dataType = TYPES_BY_SQL_DATATYPE[configuration.getDialect().ordinal()].get(this); + + if (dataType != null) { + return (DataType) dataType; + } + } + + // If this is already the dialect's specific data type, return this + else if (getDialect() == configuration.getDialect()) { + return this; + } + + // If the SQL data type is not available stick with this data type + else if (getSQLDataType() == null) { + return this; + } + + // If this is another dialect's specific data type, recurse + else { + getSQLDataType().getDataType(configuration); + } + + return this; + } + + @Override + public /* final */ int getSQLType() { + // TODO [#1227] There is some confusion with these types, especially + // when it comes to byte[] which can be mapped to BLOB, BINARY, VARBINARY + + if (type == Blob.class) { + return Types.BLOB; + } + else if (type == Boolean.class) { + return Types.BOOLEAN; + } + else if (type == BigInteger.class) { + return Types.BIGINT; + } + else if (type == BigDecimal.class) { + return Types.DECIMAL; + } + else if (type == Byte.class) { + return Types.TINYINT; + } + else if (type == byte[].class) { + return Types.BLOB; + } + else if (type == Clob.class) { + return Types.CLOB; + } + else if (type == Date.class) { + return Types.DATE; + } + else if (type == Double.class) { + return Types.DOUBLE; + } + else if (type == Float.class) { + return Types.FLOAT; + } + else if (type == Integer.class) { + return Types.INTEGER; + } + else if (type == Long.class) { + return Types.BIGINT; + } + else if (type == Short.class) { + return Types.SMALLINT; + } + else if (type == String.class) { + return Types.VARCHAR; + } + else if (type == Time.class) { + return Types.TIME; + } + else if (type == Timestamp.class) { + return Types.TIMESTAMP; + } + + // The type byte[] is handled earlier. + else if (type.isArray()) { + return Types.ARRAY; + } + else if (ArrayRecord.class.isAssignableFrom(type)) { + return Types.ARRAY; + } + else if (EnumType.class.isAssignableFrom(type)) { + return Types.VARCHAR; + } + else if (UDTRecord.class.isAssignableFrom(type)) { + return Types.STRUCT; + } + else if (Result.class.isAssignableFrom(type)) { + switch (dialect) { + case ORACLE: + case H2: + return -10; // OracleTypes.CURSOR; + + case POSTGRES: + default: + return Types.OTHER; + } + } + else { + return Types.OTHER; + } + } + + @Override + public final Class getType() { + return type; + } + + @Override + public final Class getArrayType() { + return arrayType; + } + + @Override + public final String getTypeName() { + return typeName; + } + + @Override + public String getTypeName(Configuration configuration) { + return getDataType(configuration).getTypeName(); + } + + @Override + public final String getCastTypeName() { + return castTypeName; + } + + @Override + public /* final */ String getCastTypeName(Configuration configuration, int length) { + String result = getCastTypeName(configuration); + + if (length != 0) { + + // Remove existing length information, first + result = result.replaceAll("\\([^\\)]*\\)", ""); + result += "(" + length + ")"; + } + + return result; + } + + @Override + public /* final */ String getCastTypeName(Configuration configuration, int precision, int scale) { + String result = getCastTypeName(configuration); + + if (precision != 0) { + + // Remove existing precision / scale information, first + result = result.replaceAll("\\([^\\)]*\\)", ""); + + if (scale != 0) { + result += "(" + precision + ", " + scale + ")"; + } + else { + result += "(" + precision + ")"; + } + } + + return result; + } + + @Override + public String getCastTypeName(Configuration configuration) { + return getDataType(configuration).getCastTypeName(); + } + + @Override + public final DataType getArrayDataType() { + return new ArrayDataType(this); + } + + @Override + public final > DataType asArrayDataType(Class arrayDataType) { + return new DefaultDataType(dialect, null, arrayDataType, typeName, castTypeName); + } + + @Override + public final DataType asEnumDataType(Class enumDataType) { + return new DefaultDataType(dialect, null, enumDataType, typeName, castTypeName); + } + + @Override + public final DataType asConvertedDataType(Converter converter) { + return new ConvertedDataType(this, converter); + } + + @Override + public final SQLDialect getDialect() { + return dialect; + } + + @Override + public /* final */ T convert(Object object) { + + // [#1441] Avoid unneeded type conversions to improve performance + if (object == null) { + return null; + } + else if (object.getClass() == type) { + return (T) object; + } + else { + return Convert.convert(object, type); + } + } + + @Override + public final T[] convert(Object... objects) { + return (T[]) Convert.convertArray(objects, type); + } + + @Override + public final List convert(Collection objects) { + return Convert.convert(objects, type); + } + + public static DataType getDefaultDataType(String typeName) { + return new DefaultDataType(SQLDialect.SQL99, null, Object.class, typeName, typeName); + } + + public static DataType getDefaultDataType(SQLDialect dialect, String typeName) { + return new DefaultDataType(dialect, null, Object.class, typeName, typeName); + } + + public static DataType getDataType(SQLDialect dialect, String typeName) { + String normalised = DefaultDataType.normalise(typeName); + DataType result = TYPES_BY_NAME[dialect.ordinal()].get(normalised); + + // UDT data types and others are registered using SQL99 + if (result == null) { + result = TYPES_BY_NAME[SQLDialect.SQL99.ordinal()].get(normalised); + } + + if (result == null) { + // [#366] Don't log a warning here. The warning is logged when + // catching the exception in jOOQ-codegen + throw new SQLDialectNotSupportedException("Type " + typeName + " is not supported in dialect " + dialect, false); + } + + return result; + } + + public static DataType getDataType(SQLDialect dialect, Class type) { + + // Recurse for arrays + if (byte[].class != type && type.isArray()) { + return (DataType) getDataType(dialect, type.getComponentType()).getArrayDataType(); + } + + // Base types are registered statically + else { + DataType result = null; + + if (dialect != null) { + result = TYPES_BY_TYPE[dialect.ordinal()].get(type); + } + + if (result == null) { + + // jOOQ data types are handled here + if (EnumType.class.isAssignableFrom(type) || + UDTRecord.class.isAssignableFrom(type) || + ArrayRecord.class.isAssignableFrom(type)) { + + for (SQLDialect d : SQLDialect.values()) { + result = TYPES_BY_TYPE[d.ordinal()].get(type); + + if (result != null) { + break; + } + } + } + } + + if (result == null) { + if (SQL_DATATYPES_BY_TYPE.get(type) != null) { + return (DataType) SQL_DATATYPES_BY_TYPE.get(type); + } + + // All other data types are illegal + else { + throw new SQLDialectNotSupportedException("Type " + type + " is not supported in dialect " + dialect); + } + } + + return (DataType) result; + } + } + + @Override + public final boolean isNumeric() { + return Number.class.isAssignableFrom(type) && !isInterval(); + } + + @Override + public final boolean isString() { + return type == String.class; + } + + @Override + public final boolean isDateTime() { + return java.util.Date.class.isAssignableFrom(type); + } + + @Override + public final boolean isTemporal() { + return isDateTime() || isInterval(); + } + + @Override + public final boolean isInterval() { + return Interval.class.isAssignableFrom(type); + } + + @Override + public final boolean isLob() { + SQLDataType t = getSQLDataType(); + return (t == BLOB || t == CLOB || t == NCLOB); + } + + @Override + public final boolean isBinary() { + return type == byte[].class; + } + + @Override + public final boolean isArray() { + return ArrayRecord.class.isAssignableFrom(type) + || (!isBinary() && type.isArray()); + } + + // ------------------------------------------------------------------------ + // The Object API + // ------------------------------------------------------------------------ + + @Override + public String toString() { + return getClass().getSimpleName() + " [" + type + ", " + typeName + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((dialect == null) ? 0 : dialect.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((typeName == null) ? 0 : typeName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DefaultDataType other = (DefaultDataType) obj; + if (dialect != other.dialect) + return false; + if (type == null) { + if (other.type != null) + return false; + } + else if (!type.equals(other.type)) + return false; + if (typeName == null) { + if (other.typeName != null) + return false; + } + else if (!typeName.equals(other.typeName)) + return false; + return true; + } + + /** + * @return The type name without all special characters and white spaces + */ + public static String normalise(String typeName) { + return NORMALISE_PATTERN.matcher(typeName.toUpperCase()).replaceAll(""); + } + + /** + * Convert a type name (using precision and scale) into a Java class + */ + public static DataType getDataType(SQLDialect dialect, String t, int p, int s) throws SQLDialectNotSupportedException { + DataType result = DefaultDataType.getDataType(dialect, DefaultDataType.normalise(t)); + + if (result.getType() == BigDecimal.class) { + result = DefaultDataType.getDataType(dialect, getNumericClass(p, s)); + } + + return result; + } + + /** + * Convert a type name (using precision and scale) into a Java class + */ + public static Class getType(SQLDialect dialect, String t, int p, int s) throws SQLDialectNotSupportedException { + return getDataType(dialect, t, p, s).getType(); + } + + /** + * Get the most suitable Java class for a given precision and scale + */ + private static Class getNumericClass(int precision, int scale) { + + // Integer numbers + if (scale == 0 && precision != 0) { + if (precision < BYTE_PRECISION) { + return Byte.class; + } + if (precision < SHORT_PRECISION) { + return Short.class; + } + if (precision < INTEGER_PRECISION) { + return Integer.class; + } + if (precision < LONG_PRECISION) { + return Long.class; + } + + // Default integer number + return BigInteger.class; + } + + // Real numbers should not be represented as float or double + else { + return BigDecimal.class; + } } } diff --git a/jOOQ/src/main/java/org/jooq/impl/Factory.java b/jOOQ/src/main/java/org/jooq/impl/Factory.java index 19b8266801..48d7216d28 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Factory.java +++ b/jOOQ/src/main/java/org/jooq/impl/Factory.java @@ -7652,7 +7652,7 @@ public class Factory { @SuppressWarnings("deprecation") @Support public static DataType getDataType(Class type) { - return AbstractDataType.getDataType(SQLDialect.SQL99, type); + return DefaultDataType.getDataType(SQLDialect.SQL99, type); } /** diff --git a/jOOQ/src/main/java/org/jooq/impl/MetaDataFieldProvider.java b/jOOQ/src/main/java/org/jooq/impl/MetaDataFieldProvider.java index 7db5a861a6..3ff66c5bde 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MetaDataFieldProvider.java +++ b/jOOQ/src/main/java/org/jooq/impl/MetaDataFieldProvider.java @@ -104,7 +104,7 @@ class MetaDataFieldProvider implements FieldProvider, Serializable { String type = meta.getColumnTypeName(i); try { - dataType = AbstractDataType.getDataType(configuration.getDialect(), type, precision, scale); + dataType = DefaultDataType.getDataType(configuration.getDialect(), type, precision, scale); } // [#650, #667] TODO This should not happen. All types diff --git a/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java b/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java index d46a370f40..0f0ad7d78b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java @@ -223,7 +223,7 @@ class MetaImpl implements Meta { // TODO: Exception handling should be moved inside SQLDataType DataType type = null; try { - type = AbstractDataType.getDataType(SQLDialect.SQL99, typeName, precision, scale); + type = DefaultDataType.getDataType(SQLDialect.SQL99, typeName, precision, scale); } catch (SQLDialectNotSupportedException e) { type = SQLDataType.OTHER; diff --git a/jOOQ/src/main/java/org/jooq/impl/SQLDataType.java b/jOOQ/src/main/java/org/jooq/impl/SQLDataType.java index b7d06980b3..e9b3fe2fe2 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SQLDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/SQLDataType.java @@ -79,7 +79,7 @@ import org.jooq.util.sybase.SybaseDataType; * * @author Lukas Eder */ -public final class SQLDataType extends AbstractDataType { +public final class SQLDataType extends DefaultDataType { /** * Generated UID diff --git a/jOOQ/src/main/java/org/jooq/impl/UDTDataType.java b/jOOQ/src/main/java/org/jooq/impl/UDTDataType.java index d235f53e02..1652ad663c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UDTDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/UDTDataType.java @@ -42,7 +42,7 @@ import org.jooq.UDTRecord; /** * @author Lukas Eder */ -class UDTDataType> extends AbstractDataType { +class UDTDataType> extends DefaultDataType { /** * Generated UID diff --git a/jOOQ/src/main/java/org/jooq/impl/Val.java b/jOOQ/src/main/java/org/jooq/impl/Val.java index f0ba24a2ab..84fedf901f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Val.java +++ b/jOOQ/src/main/java/org/jooq/impl/Val.java @@ -217,7 +217,7 @@ class Val extends AbstractField implements Param { // If the bind value is set, it can be used to derive the cast type if (value != null) { - toSQLCast(context, AbstractDataType.getDataType(dialect, value.getClass()), 0, 0); + toSQLCast(context, DefaultDataType.getDataType(dialect, value.getClass()), 0, 0); } // [#632] [#722] Current integration tests show that Ingres and @@ -229,7 +229,7 @@ class Val extends AbstractField implements Param { // Derby and DB2 must have a type associated with NULL. Use VARCHAR // as a workaround. That's probably not correct in all cases, though else { - toSQLCast(context, AbstractDataType.getDataType(dialect, String.class), 0, 0); + toSQLCast(context, DefaultDataType.getDataType(dialect, String.class), 0, 0); } } @@ -510,7 +510,7 @@ class Val extends AbstractField implements Param { if (type.isArray() && byte[].class != type) { context.sql(getBindVariable(context)); context.sql("::"); - context.keyword(AbstractDataType.getDataType(dialect, type).getCastTypeName(context)); + context.keyword(DefaultDataType.getDataType(dialect, type).getCastTypeName(context)); } // ... and also for enum types diff --git a/jOOQ/src/main/java/org/jooq/util/ase/ASEDataType.java b/jOOQ/src/main/java/org/jooq/util/ase/ASEDataType.java index 7495aa3b4e..35196ceb7d 100644 --- a/jOOQ/src/main/java/org/jooq/util/ase/ASEDataType.java +++ b/jOOQ/src/main/java/org/jooq/util/ase/ASEDataType.java @@ -36,8 +36,9 @@ import java.sql.Date; import java.sql.Time; import java.sql.Timestamp; +import org.jooq.DataType; import org.jooq.SQLDialect; -import org.jooq.impl.AbstractDataType; +import org.jooq.impl.DefaultDataType; import org.jooq.impl.SQLDataType; /** @@ -46,78 +47,70 @@ import org.jooq.impl.SQLDataType; * @see http://infocenter.sybase.com/help/topic/com.sybase.infocenter.dc36271.1550/html/blocks/X31825.htm * @author Lukas Eder */ -public class ASEDataType extends AbstractDataType { - - /** - * Generated UID - */ - private static final long serialVersionUID = -4442303192680774346L; +public class ASEDataType { // ------------------------------------------------------------------------- // Default SQL data types and synonyms thereof // ------------------------------------------------------------------------- - public static final ASEDataType TINYINT = new ASEDataType(SQLDataType.TINYINT, "tinyint"); - public static final ASEDataType SMALLINT = new ASEDataType(SQLDataType.SMALLINT, "smallint"); - public static final ASEDataType UNSIGNEDSMALLLINT = new ASEDataType(SQLDataType.SMALLINT, "unsigned smallint"); - public static final ASEDataType INT = new ASEDataType(SQLDataType.INTEGER, "int"); - public static final ASEDataType INTEGER = new ASEDataType(SQLDataType.INTEGER, "integer"); - public static final ASEDataType UNSIGNEDINT = new ASEDataType(SQLDataType.INTEGER, "unsigned int"); - public static final ASEDataType BIGINT = new ASEDataType(SQLDataType.BIGINT, "bigint"); - public static final ASEDataType UNSIGNEDBIGINT = new ASEDataType(SQLDataType.BIGINT, "unsigned bigint"); - public static final ASEDataType DOUBLE_PRECISION = new ASEDataType(SQLDataType.DOUBLE, "double precision"); - public static final ASEDataType FLOAT = new ASEDataType(SQLDataType.FLOAT, "float"); - public static final ASEDataType REAL = new ASEDataType(SQLDataType.REAL, "real"); - public static final ASEDataType DECIMAL = new ASEDataType(SQLDataType.DECIMAL, "decimal"); - public static final ASEDataType DEC = new ASEDataType(SQLDataType.DECIMAL, "dec"); - public static final ASEDataType NUMERIC = new ASEDataType(SQLDataType.NUMERIC, "numeric"); - public static final ASEDataType BIT = new ASEDataType(SQLDataType.BIT, "bit"); - public static final ASEDataType VARCHAR = new ASEDataType(SQLDataType.VARCHAR, "varchar"); - public static final ASEDataType CHAR = new ASEDataType(SQLDataType.CHAR, "char"); - public static final ASEDataType LONGVARCHAR = new ASEDataType(SQLDataType.LONGVARCHAR, "text"); - public static final ASEDataType NCHAR = new ASEDataType(SQLDataType.NCHAR, "nchar"); - public static final ASEDataType NVARCHAR = new ASEDataType(SQLDataType.NVARCHAR, "nvarchar"); - public static final ASEDataType TEXT = new ASEDataType(SQLDataType.CLOB, "text"); - public static final ASEDataType DATE = new ASEDataType(SQLDataType.DATE, "date"); - public static final ASEDataType