📄 datatypedescriptor.java
字号:
/* Derby - Class org.apache.derby.iapi.types.DataTypeDescriptor Copyright 1999, 2004 The Apache Software Foundation or its licensors, as applicable. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */package org.apache.derby.iapi.types;import org.apache.derby.iapi.services.io.Formatable;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.services.loader.ClassFactory;import org.apache.derby.catalog.TypeDescriptor;import org.apache.derby.catalog.types.TypeDescriptorImpl;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.services.io.StoredFormatIds;import org.apache.derby.iapi.services.io.FormatIdUtil;import org.apache.derby.iapi.services.io.Formatable;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.types.RowLocation;import org.apache.derby.iapi.services.loader.ClassFactory;import org.apache.derby.iapi.services.loader.ClassInspector;import org.apache.derby.iapi.reference.SQLState;import java.io.ObjectOutput;import java.io.ObjectInput;import java.io.IOException;import java.sql.Types;/** * This is an implementation of DataTypeDescriptor from the generic language * datatype module interface. * * @author Jeff Lichtman * @version 1.0 */public final class DataTypeDescriptor implements TypeDescriptor, Formatable{ /******************************************************** ** ** This class implements Formatable. That means that it ** can write itself to and from a formatted stream. If ** you add more fields to this class, make sure that you ** also write/read them with the writeExternal()/readExternal() ** methods. ** ** If, inbetween releases, you add more fields to this class, ** then you should bump the version number emitted by the getTypeFormatId() ** method. ** ********************************************************/ /* ** Static creators */ /** * Get a descriptor that corresponds to a builtin JDBC type. * * @param jdbcType The int type of the JDBC type for which to get * a corresponding SQL DataTypeDescriptor * * @return A new DataTypeDescriptor that corresponds to the Java type. * A null return value means there is no corresponding SQL type */ public static DataTypeDescriptor getBuiltInDataTypeDescriptor ( int jdbcType ) { return DataTypeDescriptor.getBuiltInDataTypeDescriptor(jdbcType, true); } public static DataTypeDescriptor getBuiltInDataTypeDescriptor ( int jdbcType, int length ) { return DataTypeDescriptor.getBuiltInDataTypeDescriptor(jdbcType, true, length); } /** * Get a descriptor that corresponds to a builtin JDBC type. * * @param jdbcType The int type of the JDBC type for which to get * a corresponding SQL DataTypeDescriptor * @param isNullable TRUE means it could contain NULL, FALSE means * it definitely cannot contain NULL. * * @return A new DataTypeDescriptor that corresponds to the Java type. * A null return value means there is no corresponding SQL type */ public static DataTypeDescriptor getBuiltInDataTypeDescriptor ( int jdbcType, boolean isNullable ) { TypeId typeId = TypeId.getBuiltInTypeId(jdbcType); if (typeId == null) { return null; } return new DataTypeDescriptor(typeId, isNullable); } /** * Get a descriptor that corresponds to a builtin JDBC type. * * @param jdbcType The int type of the JDBC type for which to get * a corresponding SQL DataTypeDescriptor * @param isNullable TRUE means it could contain NULL, FALSE means * it definitely cannot contain NULL. * * @return A new DataTypeDescriptor that corresponds to the Java type. * A null return value means there is no corresponding SQL type */ public static DataTypeDescriptor getBuiltInDataTypeDescriptor ( int jdbcType, boolean isNullable, int maxLength ) { TypeId typeId = TypeId.getBuiltInTypeId(jdbcType); if (typeId == null) { return null; } return new DataTypeDescriptor(typeId, isNullable, maxLength); } /** * Get a DataTypeServices that corresponds to a builtin SQL type * * @param javaTypeName The name of the Java type for which to get * a corresponding SQL DataTypeDescriptor * * @return A new DataTypeDescriptor that corresponds to the Java type. * A null return value means there is no corresponding SQL type (only for 'char') */ public static DataTypeDescriptor getBuiltInDataTypeDescriptor ( String sqlTypeName ) { return new DataTypeDescriptor(TypeId.getBuiltInTypeId(sqlTypeName), true); } /** * Get a DataTypeServices that corresponds to a builtin SQL type * * @param javaTypeName The name of the Java type for which to get * a corresponding SQL DataTypeDescriptor * * @return A new DataTypeDescriptor that corresponds to the Java type. * A null return value means there is no corresponding SQL type (only for 'char') */ public static DataTypeDescriptor getBuiltInDataTypeDescriptor ( String sqlTypeName, int length ) { return new DataTypeDescriptor(TypeId.getBuiltInTypeId(sqlTypeName), true, length); } /** * Get a DataTypeServices that corresponds to a Java type * * @param javaTypeName The name of the Java type for which to get * a corresponding SQL DataTypeDescriptor * * @return A new DataTypeDescriptor that corresponds to the Java type. * A null return value means there is no corresponding SQL type (only for 'char') */ public static DataTypeDescriptor getSQLDataTypeDescriptor ( String javaTypeName ) { return DataTypeDescriptor.getSQLDataTypeDescriptor(javaTypeName, true); } /** * Get a DataTypeServices that corresponds to a Java type * * @param javaTypeName The name of the Java type for which to get * a corresponding SQL DataTypeDescriptor * @param isNullable TRUE means it could contain NULL, FALSE means * it definitely cannot contain NULL. * * @return A new DataTypeDescriptor that corresponds to the Java type. * A null return value means there is no corresponding SQL type (only for 'char') */ public static DataTypeDescriptor getSQLDataTypeDescriptor ( String javaTypeName, boolean isNullable ) { TypeId typeId = TypeId.getSQLTypeForJavaType(javaTypeName); if (typeId == null) { return null; } return new DataTypeDescriptor(typeId, isNullable); } /** * Get a DataTypeDescriptor that corresponds to a Java type * * @param javaTypeName The name of the Java type for which to get * a corresponding SQL DataTypeDescriptor * @param precision The number of decimal digits * @param scale The number of digits after the decimal point * @param isNullable TRUE means it could contain NULL, FALSE means * it definitely cannot contain NULL. * @param maximumWidth The maximum width of a data value * represented by this type. * * @return A new DataTypeDescriptor that corresponds to the Java type. * A null return value means there is no corresponding SQL type. */ public static DataTypeDescriptor getSQLDataTypeDescriptor ( String javaTypeName, int precision, int scale, boolean isNullable, int maximumWidth ) { TypeId typeId = TypeId.getSQLTypeForJavaType(javaTypeName); if (typeId == null) { return null; } return new DataTypeDescriptor(typeId, precision, scale, isNullable, maximumWidth); } /* ** Instance fields & methods */ private TypeDescriptorImpl typeDescriptor; private TypeId typeId; /** * Public niladic constructor. Needed for Formatable interface to work. * */ public DataTypeDescriptor() {} /** * Constructor for use with numeric types * * @param typeId The typeId of the type being described * @param precision The number of decimal digits. * @param scale The number of digits after the decimal point. * @param isNullable TRUE means it could contain NULL, FALSE means * it definitely cannot contain NULL. * @param maximumWidth The maximum number of bytes for this datatype */ public DataTypeDescriptor(TypeId typeId, int precision, int scale, boolean isNullable, int maximumWidth) { this.typeId = typeId; typeDescriptor = new TypeDescriptorImpl(typeId.getBaseTypeId(), precision, scale, isNullable, maximumWidth); } /** * Constructor for use with non-numeric types * * @param typeId The typeId of the type being described * @param isNullable TRUE means it could contain NULL, FALSE means * it definitely cannot contain NULL. * @param maximumWidth The maximum number of bytes for this datatype */ public DataTypeDescriptor(TypeId typeId, boolean isNullable, int maximumWidth) { this.typeId = typeId; typeDescriptor = new TypeDescriptorImpl(typeId.getBaseTypeId(), isNullable, maximumWidth); } public DataTypeDescriptor(TypeId typeId, boolean isNullable) { this.typeId = typeId; typeDescriptor = new TypeDescriptorImpl(typeId.getBaseTypeId(), typeId.getMaximumPrecision(), typeId.getMaximumScale(), isNullable, typeId.getMaximumMaximumWidth()); } public DataTypeDescriptor(DataTypeDescriptor source, boolean isNullable) { this.typeId = source.typeId; typeDescriptor = new TypeDescriptorImpl(source.typeDescriptor, source.getPrecision(), source.getScale(), isNullable, source.getMaximumWidth()); } /** * Constructor for internal uses only. * (This is useful when the precision and scale are potentially wider than * those in the source, like when determining the dominant data type.) * * @param source The DTSI to copy * @param precision The number of decimal digits. * @param scale The number of digits after the decimal point. * @param isNullable TRUE means it could contain NULL, FALSE means * it definitely cannot contain NULL. * @param maximumWidth The maximum number of bytes for this datatype */ public DataTypeDescriptor(DataTypeDescriptor source, int precision, int scale, boolean isNullable, int maximumWidth) { this.typeId = source.typeId; typeDescriptor = new TypeDescriptorImpl(source.typeDescriptor, precision, scale, isNullable, maximumWidth); } /** * Constructor for internal uses only * * @param source The DTSI to copy * @param isNullable TRUE means it could contain NULL, FALSE means * it definitely cannot contain NULL. * @param maximumWidth The maximum number of bytes for this datatype */ public DataTypeDescriptor(DataTypeDescriptor source, boolean isNullable, int maximumWidth) { this.typeId = source.typeId; typeDescriptor = new TypeDescriptorImpl(source.typeDescriptor, isNullable, maximumWidth); } /** * Constructor for use in reconstructing a DataTypeDescriptor from a * TypeDescriptorImpl and a TypeId * * @param source The TypeDescriptorImpl to construct this DTSI from */ public DataTypeDescriptor(TypeDescriptorImpl source, TypeId typeId) { typeDescriptor = source; this.typeId = typeId;; } /* DataTypeDescriptor Interface */ public DataValueDescriptor normalize(DataValueDescriptor source, DataValueDescriptor cachedDest) throws StandardException { if (SanityManager.DEBUG) { if (cachedDest != null) { if (!getTypeId().isUserDefinedTypeId()) { String t1 = getTypeName(); String t2 = cachedDest.getTypeName(); if (!t1.equals(t2)) { if (!(((t1.equals("DECIMAL") || t1.equals("NUMERIC")) && (t2.equals("DECIMAL") || t2.equals("NUMERIC"))) || (t1.startsWith("INT") && t2.startsWith("INT")))) //INT/INTEGER SanityManager.THROWASSERT( "Normalization of " + t2 + " being asked to convert to " + t1); } } } } if (source.isNull()) { if (!isNullable()) throw StandardException.newException(SQLState.LANG_NULL_INTO_NON_NULL,""); if (cachedDest == null) cachedDest = getNull(); else cachedDest.setToNull(); } else { if (cachedDest == null) cachedDest = getNull(); int jdbcId = getJDBCTypeId(); cachedDest.normalize(this, source); //doing the following check after normalize so that normalize method would get called on long varchs and long varbinary //Need normalize to be called on long varchar for bug 5592 where we need to enforce a lenght limit in db2 mode if ((jdbcId == Types.LONGVARCHAR) || (jdbcId == Types.LONGVARBINARY)) { // special case for possible streams if (source.getClass() == cachedDest.getClass()) return source; } } return cachedDest; } /** * Get the dominant type (DataTypeDescriptor) of the 2. * For variable length types, the resulting type will have the * biggest max length of the 2. * If either side is nullable, then the result will also be nullable. * * @param otherDTS DataTypeDescriptor to compare with. * @param cf A ClassFactory * * @return DataTypeDescriptor DTS for dominant type * * @exception StandardException Thrown on error */ public DataTypeDescriptor getDominantType(DataTypeDescriptor otherDTS, ClassFactory cf) throws StandardException { boolean nullable; TypeId thisType; TypeId otherType; DataTypeDescriptor higherType = null; DataTypeDescriptor lowerType = null; int maximumWidth; int precision = getPrecision(); int scale = getScale(); thisType = getTypeId(); otherType = otherDTS.getTypeId(); /* The result is nullable if either side is nullable */ nullable = isNullable() || otherDTS.isNullable(); /* ** The result will have the maximum width of both sides */ maximumWidth = (getMaximumWidth() > otherDTS.getMaximumWidth()) ? getMaximumWidth() : otherDTS.getMaximumWidth(); /* We need 2 separate methods of determining type dominance - 1 if both * types are system built-in types and the other if at least 1 is * a user type. (typePrecedence is meaningless for user types.) */ if (thisType.systemBuiltIn() && otherType.systemBuiltIn()) { TypeId higherTypeId; TypeId lowerTypeId; if (thisType.typePrecedence() > otherType.typePrecedence()) { higherType = this; lowerType = otherDTS; higherTypeId = thisType; lowerTypeId = otherType; } else { higherType = otherDTS; lowerType = this; higherTypeId = otherType; lowerTypeId = thisType; } //Following is checking if higher type argument is real and other argument is decimal/bigint/integer/smallint, //then result type should be double if (higherTypeId.isRealTypeId() && (!lowerTypeId.isRealTypeId()) && lowerTypeId.isNumericTypeId()) { higherType = DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.DOUBLE); higherTypeId = TypeId.getBuiltInTypeId(Types.DOUBLE); } /* ** If we have a DECIMAL/NUMERIC we have to do some ** extra work to make sure the resultant type can ** handle the maximum values for the two input ** types. We cannot just take the maximum for ** precision. E.g. we want something like: ** ** DEC(10,10) and DEC(3,0) => DEC(13,10) ** ** (var)char type needs some conversion handled later. */ if (higherTypeId.isDecimalTypeId() && (!lowerTypeId.isStringTypeId())) { precision = higherTypeId.getPrecision(this, otherDTS); if (precision > 31) precision = 31; //db2 silently does this and so do we scale = higherTypeId.getScale(this, otherDTS); /* maximumWidth needs to count possible leading '-' and * decimal point and leading '0' if scale > 0. See also * sqlgrammar.jj(exactNumericType). Beetle 3875 */ maximumWidth = (scale > 0) ? precision + 3 : precision + 1; } else if (thisType.typePrecedence() != otherType.typePrecedence()) { precision = higherType.getPrecision(); scale = higherType.getScale(); /* GROSS HACKS: * If we are doing an implicit (var)char->(var)bit conversion * then the maximum width for the (var)char as a (var)bit * is really 16 * its width as a (var)char. Adjust * maximumWidth accordingly. * If we are doing an implicit (var)char->decimal conversion * then we need to increment the decimal's precision by * 2 * the maximum width for the (var)char and the scale
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -