📄 binarydecimal.java
字号:
/* Derby - Class org.apache.derby.iapi.types.BinaryDecimal Copyright 2005 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 java.io.IOException;import java.io.ObjectInput;import java.io.ObjectOutput;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Types;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.iapi.services.io.ArrayInputStream;import org.apache.derby.iapi.services.io.StoredFormatIds;import org.apache.derby.iapi.services.sanity.SanityManager;/** * SQL DECIMAL using raw data. Provides the basis for the * CDCDecimal implementation. * <P> * The on-disk format must match the SQLDecimal format so that * databases are portable across J2ME and J2SE environments. * <P> * The format of the byte array is defined by the return of the * java.math.BigInteger.toByteArray:, extracted here. * * Returns a byte array containing the two's-complement representation of this BigInteger. * The byte array will be in big-endian byte-order: the most significant byte is in the zeroth element. * * This is the format for DECIMAL even if BigINteger is not available, e.g. OSGi ee.minimum. */abstract class BinaryDecimal extends NumberDataType implements VariableSizeDataValue{ /** * An unscaled value of 1 in two's complement */ private static final byte[] ONE_2C = {(byte) 0x01}; /** * The unscaled value as a binary two's complement array. */ protected byte[] data2c; /** * The SQL scale, zero or positive, of the value */ protected int sqlScale; BinaryDecimal() { } /* ** Methods about the DECIMAL type itself. */ /** * DECIMAL implementation. * Use DECIMAL to indicate to self that another * passed in value is an instance of this type. */ public final int typeToBigDecimal() { return java.sql.Types.DECIMAL; } /** @see DataValueDescriptor#typePrecedence */ public final int typePrecedence() { return TypeId.DECIMAL_PRECEDENCE; } /* Return DECIMAL as the type name. * @see org.apache.derby.iapi.types.DataValueDescriptor#getTypeName() */ public final String getTypeName() { return TypeId.DECIMAL_NAME; } /** * Return my format identifier. * * @see org.apache.derby.iapi.services.io.TypedFormat#getTypeFormatId */ public final int getTypeFormatId() { return StoredFormatIds.SQL_DECIMAL_ID; } /* ** NULL handling. */ /** * see if the decimal value is null. */ public boolean isNull() { return data2c == null; } public void restoreToNull() { data2c = null; } /* Check the leftmost bit, if set the value is negative. * NULL values return false. * @see org.apache.derby.iapi.types.NumberDataType#isNegative() */ protected boolean isNegative() { return !isNull() && ((data2c[0] & 0x80) != 0); } /* ** Methods to convert values into this DECIMAL */ /** * Set the value from a long. */ public void setValue(long theValue) { byte[] rd = data2c; if (rd == null || rd.length < 8) rd = new byte[8]; rd[0] = (byte)(theValue >>> 56); rd[1] = (byte)(theValue >>> 48); rd[2] = (byte)(theValue >>> 40); rd[3] = (byte)(theValue >>> 32); rd[4] = (byte)(theValue >>> 24); rd[5] = (byte)(theValue >>> 16); rd[6] = (byte)(theValue >>> 8); rd[7] = (byte) theValue; if (SanityManager.DEBUG) { data2c = rd; sqlScale = 0; try { if (theValue != getLong()) SanityManager.THROWASSERT("BinaryDecimal invalid long conversion before reduce in " + theValue + " out " + getLong()); } catch (StandardException se) { SanityManager.THROWASSERT(se.toString()); } } data2c = BinaryDecimal.reduceBytes2c(rd, 0, 8); sqlScale = 0; if (SanityManager.DEBUG) { try { if (theValue != getLong()) SanityManager.THROWASSERT("BinaryDecimal invalid long conversion after reduce in " + theValue + " out " + getLong()); } catch (StandardException se) { SanityManager.THROWASSERT(se.toString()); } } } /** * Set the value from an int, just copy 'byte-by-byte' * from the int to a four byte array. Then reduce. * @see NumberDataValue#setValue */ public final void setValue(int theValue) { byte[] rd = data2c; if (rd == null || rd.length < 4) rd = new byte[4]; rd[0] = (byte)(theValue >>> 24); rd[1] = (byte)(theValue >>> 16); rd[2] = (byte)(theValue >>> 8); rd[3] = (byte) theValue; data2c = BinaryDecimal.reduceBytes2c(rd, 0, 4); sqlScale = 0; } /** * Set the value from a boolean */ public void setValue(boolean theValue) { int intValue = theValue ? 1 : 0; setValue(intValue); } /** * Convert from a double, normalize and then convert as a String. * * @exception StandardException Thrown on error */ public final void setValue(double theValue) throws StandardException { setCoreValue(NumberDataType.normalizeDOUBLE(theValue)); } /** * Convert from a float, normalize and then convert as a String. * */ public final void setValue(float theValue) throws StandardException { setCoreValue((double)NumberDataType.normalizeREAL(theValue)); } private void setCoreValue(double theValue) throws StandardException { setValue(Double.toString(theValue)); } /** Called when setting a DECIMAL value internally or from through a procedure or function. Handles long in addition to BigDecimal to handle identity being stored as a long but returned as a DECIMAL. */ public void setValue(Number theValue) throws StandardException { if (SanityManager.ASSERT) { if (theValue != null && !(theValue instanceof java.lang.Long)) SanityManager.THROWASSERT("BinaryDecimal.setValue(Number) passed a " + theValue.getClass()); } if (theValue == null) setToNull(); else setValue(theValue.longValue()); } /** * Set this DECIMAL value from another DataValueDescriptor */ protected void setFrom(DataValueDescriptor dvd) throws StandardException { switch (dvd.typeToBigDecimal()) { case Types.CHAR: case Types.DECIMAL: // TODO : direct copy setValue(dvd.getString()); break; case Types.BIGINT: setValue(dvd.getLong()); break; default: super.setFrom(dvd); } } /* ** Methods to get a value from this DECIMAL */ /** * Return a int from this value. * * @exception StandardException * this value is out of range for an int */ public final int getInt() throws StandardException { if (isNull()) return 0; try { long lv = getLong(); if ((lv >= Integer.MIN_VALUE) && (lv <= Integer.MAX_VALUE)) return (int) lv; } catch (StandardException se) { // out of range error but with incorrect messgae (BIGINT) // fall through to correct message } throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "INTEGER"); } /** * Return a byte from this value. * * @exception StandardException * this value is out of range for a short */ public final byte getByte() throws StandardException { if (isNull()) return (byte) 0; try { long lv = getLong(); if ((lv >= Byte.MIN_VALUE) && (lv <= Byte.MAX_VALUE)) return (byte) lv; } catch (StandardException se) { // out of range error but with incorrect messgae (BIGINT) // fall through to correct message } throw StandardException.newException( SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "TINYINT"); } /** * Return a short from this value. * @exception StandardException this value is out of range for a short */ public final short getShort() throws StandardException { if (isNull()) return (short)0; try { long lv = getLong(); if ((lv >= Short.MIN_VALUE) && (lv <= Short.MAX_VALUE)) return (short) lv; } catch (StandardException se) { // out of range error but with incorrect messgae (BIGINT) // fall through to correct message }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -