/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.core.types; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.SQLXML; import java.sql.Types; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import org.teiid.core.types.DataTypeManagerService.DefaultDataTypes; import org.teiid.designer.annotation.AnnotationUtils; import org.teiid.designer.runtime.version.spi.ITeiidServerVersion; import org.teiid.designer.runtime.version.spi.TeiidServerVersion; import org.teiid.designer.runtime.version.spi.TeiidServerVersion.Version; /** * <p> This is a helper class used to obtain SQL type information for java types. * The SQL type information is obtained from java.sql.Types class. The integers and * strings returned by methods in this class are based on constants in java.sql.Types. */ public final class JDBCSQLTypeInfo { public static class TypeInfo { String name; int maxDisplaySize; int defaultPrecision; String javaClassName; int[] jdbcTypes; private final ITeiidServerVersion minTeiidVersion; public TypeInfo(ITeiidServerVersion minTeiidVersion, int maxDisplaySize, int precision, String name, String javaClassName, int[] jdbcTypes) { super(); this.minTeiidVersion = minTeiidVersion; this.maxDisplaySize = maxDisplaySize; this.defaultPrecision = precision; this.name = name; this.javaClassName = javaClassName; this.jdbcTypes = jdbcTypes; } /** * @return minimum teiid version for this type info */ public ITeiidServerVersion getMinimumTeiidVersion() { return minTeiidVersion; } /** * @param teiidVersion * @return false if given version is less than min required version, true otherwise */ public boolean isApplicable(ITeiidServerVersion teiidVersion) { return ! minTeiidVersion.isGreaterThan(teiidVersion); } } // Prevent instantiation private JDBCSQLTypeInfo() {} public static final Integer DEFAULT_RADIX = 10; public static final Integer DEFAULT_SCALE = 0; // XML column constants public final static Integer XML_COLUMN_LENGTH = Integer.MAX_VALUE; private static Map<String, TypeInfo> NAME_TO_TYPEINFO = new LinkedHashMap<String, TypeInfo>(); private static Map<Integer, TypeInfo> TYPE_TO_TYPEINFO = new HashMap<Integer, TypeInfo>(); private static Map<String, TypeInfo> CLASSNAME_TO_TYPEINFO = new HashMap<String, TypeInfo>(); static { //note the order in which these are added matters. if there are multiple sql type mappings (e.g. biginteger and bigdecimal to numeric), the latter will be the primary addType(DataTypeManagerService.DefaultDataTypes.BIG_INTEGER, 20, 19, DataTypeManagerService.DefaultDataTypes.BIG_INTEGER.getId(), Types.NUMERIC); addType(new String[] {DataTypeManagerService.DefaultDataTypes.BIG_DECIMAL.getId(), "decimal"}, 22, 20, DataTypeManagerService.DefaultDataTypes.BIG_DECIMAL.getId(), Types.NUMERIC, Types.DECIMAL); //$NON-NLS-1$ addType(DataTypeManagerService.DefaultDataTypes.GEOMETRY, Integer.MAX_VALUE, Integer.MAX_VALUE, GeometryType.class.getName(), Types.BLOB, Types.LONGVARBINARY); addType(DataTypeManagerService.DefaultDataTypes.BLOB, Integer.MAX_VALUE, Integer.MAX_VALUE, Blob.class.getName(), Types.BLOB, Types.LONGVARBINARY); addType(DataTypeManagerService.DefaultDataTypes.BOOLEAN, 5, 1, DataTypeManagerService.DefaultDataTypes.BOOLEAN.getId(), Types.BIT, Types.BOOLEAN); addType(new String[] {DataTypeManagerService.DefaultDataTypes.BYTE.getId(), "tinyint"}, 4, 3, DataTypeManagerService.DefaultDataTypes.BYTE.getId(), Types.TINYINT); //$NON-NLS-1$ addType(DataTypeManagerService.DefaultDataTypes.CHAR, 1, 1, DataTypeManagerService.DefaultDataTypes.CHAR.getId(), Types.CHAR); addType(DataTypeManagerService.DefaultDataTypes.CLOB, Integer.MAX_VALUE, Integer.MAX_VALUE, Clob.class.getName(), Types.CLOB, Types.NCLOB, Types.LONGNVARCHAR, Types.LONGVARCHAR); addType(DataTypeManagerService.DefaultDataTypes.DATE, 10, 10, DataTypeManagerService.DefaultDataTypes.DATE.getId(), Types.DATE); addType(DataTypeManagerService.DefaultDataTypes.DOUBLE, 22, 20, DataTypeManagerService.DefaultDataTypes.DOUBLE.getId(), Types.DOUBLE, Types.FLOAT); addType(new String[] {DataTypeManagerService.DefaultDataTypes.FLOAT.getId(), "real"}, 22, 20, DataTypeManagerService.DefaultDataTypes.FLOAT.getId(), Types.REAL); //$NON-NLS-1$ addType(DataTypeManagerService.DefaultDataTypes.INTEGER, 11, 10, DataTypeManagerService.DefaultDataTypes.INTEGER.getId(), Types.INTEGER); addType(new String[] {DataTypeManagerService.DefaultDataTypes.LONG.getId(), "bigint"}, 20, 19, DataTypeManagerService.DefaultDataTypes.LONG.getId(), Types.BIGINT); //$NON-NLS-1$ addType(DataTypeManagerService.DefaultDataTypes.OBJECT, Integer.MAX_VALUE, Integer.MAX_VALUE, DataTypeManagerService.DefaultDataTypes.OBJECT.getId(), Types.JAVA_OBJECT); addType(new String[] {DataTypeManagerService.DefaultDataTypes.SHORT.getId(), "smallint"}, 6, 5, DataTypeManagerService.DefaultDataTypes.SHORT.getId(), Types.SMALLINT); //$NON-NLS-1$ addType(new String[] {DataTypeManagerService.DefaultDataTypes.STRING.getId(), "varchar"}, DataTypeManagerService.MAX_STRING_LENGTH, DataTypeManagerService.MAX_STRING_LENGTH, DataTypeManagerService.DefaultDataTypes.STRING.getId(), Types.VARCHAR, Types.NVARCHAR, Types.CHAR, Types.NCHAR); //$NON-NLS-1$ addType(DataTypeManagerService.DefaultDataTypes.TIME, 8, 8, DataTypeManagerService.DefaultDataTypes.TIME.getId(), Types.TIME); addType(DataTypeManagerService.DefaultDataTypes.TIMESTAMP, 29, 29, DataTypeManagerService.DefaultDataTypes.TIMESTAMP.getId(), Types.TIMESTAMP); addType(DataTypeManagerService.DefaultDataTypes.XML, Integer.MAX_VALUE, Integer.MAX_VALUE, SQLXML.class.getName(), Types.SQLXML); addType(DataTypeManagerService.DefaultDataTypes.NULL, 4, 1, null, Types.NULL); addType(DataTypeManagerService.DefaultDataTypes.VARBINARY, DataTypeManagerService.MAX_VARBINARY_BYTES, DataTypeManagerService.MAX_VARBINARY_BYTES, byte[].class.getName(), Types.VARBINARY, Types.BINARY); TypeInfo typeInfo = new TypeInfo(Version.TEIID_7_7.get(), Integer.MAX_VALUE, 0, "ARRAY", Array.class.getName(), new int[Types.ARRAY]); //$NON-NLS-1$ CLASSNAME_TO_TYPEINFO.put(Array.class.getName(), typeInfo); TYPE_TO_TYPEINFO.put(Types.ARRAY, typeInfo); } private static TypeInfo addType(DefaultDataTypes type, int maxDisplaySize, int precision, String javaClassName, int... sqlTypes) { ITeiidServerVersion minTeiidVersion = TeiidServerVersion.Version.TEIID_7_7.get(); // if (AnnotationUtils.hasAnnotation(type, Since.class)) { // Since since = AnnotationUtils.getAnnotation(type, Since.class); // minTeiidVersion = since.value().get(); // } return addType(minTeiidVersion, type.getId(), maxDisplaySize, precision, javaClassName, sqlTypes); } private static TypeInfo addType(ITeiidServerVersion minTeiidVersion, String typeName, int maxDisplaySize, int precision, String javaClassName, int... sqlTypes) { TypeInfo ti = new TypeInfo(minTeiidVersion, maxDisplaySize, precision, typeName, javaClassName, sqlTypes); NAME_TO_TYPEINFO.put(typeName, ti); if (javaClassName != null) { CLASSNAME_TO_TYPEINFO.put(javaClassName, ti); } for (int i : sqlTypes) { TYPE_TO_TYPEINFO.put(i, ti); } return ti; } private static void addType(ITeiidServerVersion minTeiidVersion, String[] typeNames, int maxDisplaySize, int precision, String javaClassName, int... sqlTypes) { TypeInfo ti = addType(minTeiidVersion, typeNames[0], maxDisplaySize, precision, javaClassName, sqlTypes); for (int i = 1; i < typeNames.length; i++) { NAME_TO_TYPEINFO.put(typeNames[i], ti); } } private static void addType(String[] typeNames, int maxDisplaySize, int precision, String javaClassName, int... sqlTypes) { addType(Version.TEIID_7_7.get(), typeNames, maxDisplaySize, precision, javaClassName, sqlTypes); } /** * This method is used to obtain a short indicating JDBC SQL type for any object. * The short values that give the type info are from java.sql.Types. * @param Name of the teiid type. * @return A short value representing SQL Type for the given java type. */ public static final int getSQLType(ITeiidServerVersion teiidVersion, String typeName) { if (typeName == null) { return Types.NULL; } TypeInfo sqlType = NAME_TO_TYPEINFO.get(typeName); if (sqlType == null) { if (DataTypeManagerService.isArrayType(typeName)) { return Types.ARRAY; } return Types.JAVA_OBJECT; } if (! sqlType.isApplicable(teiidVersion)) return Types.NULL; return sqlType.jdbcTypes[0]; } /** * Get sql Type from java class type name. This should not be called with runtime types * as Clob and Blob are represented by ClobType and BlobType respectively. * @param typeName * @return int */ public static final int getSQLTypeFromClass(ITeiidServerVersion teiidVersion, String className) { if (className == null) { return Types.NULL; } TypeInfo sqlType = CLASSNAME_TO_TYPEINFO.get(className); if (sqlType == null) { return Types.JAVA_OBJECT; } if (! sqlType.isApplicable(teiidVersion)) return Types.NULL; return sqlType.jdbcTypes[0]; } /** * This method is used to obtain a the java class name given an int value * indicating JDBC SQL type. The int values that give the type info are from * java.sql.Types. * @param int value giving the SQL type code. * @return A String representing the java class name for the given SQL Type. */ public static final String getJavaClassName(ITeiidServerVersion teiidVersion, int jdbcSQLType) { TypeInfo typeInfo = TYPE_TO_TYPEINFO.get(jdbcSQLType); if (typeInfo == null) { return DataTypeManagerService.DefaultDataTypes.OBJECT.getId(); } if (! typeInfo.isApplicable(teiidVersion)) return null; return typeInfo.javaClassName; } public static final String getTypeName(ITeiidServerVersion teiidVersion, int sqlType) { TypeInfo typeInfo = TYPE_TO_TYPEINFO.get(sqlType); if (typeInfo == null) { return DataTypeManagerService.DefaultDataTypes.OBJECT.getId(); } if (! typeInfo.isApplicable(teiidVersion)) return null; return typeInfo.name; } public static Set<String> getMMTypeNames() { return NAME_TO_TYPEINFO.keySet(); } public static Integer getMaxDisplaySize(ITeiidServerVersion teiidVersion, Class<?> dataTypeClass) { return getMaxDisplaySize(teiidVersion, DataTypeManagerService.getInstance(teiidVersion).getDataTypeName(dataTypeClass)); } public static Integer getMaxDisplaySize(ITeiidServerVersion teiidVersion, String typeName) { TypeInfo ti = NAME_TO_TYPEINFO.get(typeName); if (ti == null) { return null; } if (! ti.isApplicable(teiidVersion)) return null; return ti.maxDisplaySize; } public static Integer getDefaultPrecision(ITeiidServerVersion teiidVersion, Class<?> dataTypeClass) { return getDefaultPrecision(teiidVersion, DataTypeManagerService.getInstance(teiidVersion).getDataTypeName(dataTypeClass)); } public static Integer getDefaultPrecision(ITeiidServerVersion teiidVersion, String typeName) { TypeInfo ti = NAME_TO_TYPEINFO.get(typeName); if (ti == null) { return null; } if (! ti.isApplicable(teiidVersion)) return null; return ti.defaultPrecision; } }