📄 sqlbinary.java
字号:
/* Derby - Class org.apache.derby.iapi.types.SQLBinary Copyright 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.reference.SQLState;import org.apache.derby.iapi.services.io.ArrayInputStream;import org.apache.derby.iapi.services.io.FormatableBitSet;import org.apache.derby.iapi.services.io.NewByteArrayInputStream;import org.apache.derby.iapi.types.DataTypeDescriptor;import org.apache.derby.iapi.types.DataValueDescriptor;import org.apache.derby.iapi.types.TypeId;import org.apache.derby.iapi.types.BitDataValue;import org.apache.derby.iapi.types.DataValueDescriptor;import org.apache.derby.iapi.types.ConcatableDataValue;import org.apache.derby.iapi.types.VariableSizeDataValue;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.services.io.FormatIdUtil;import org.apache.derby.iapi.services.io.StoredFormatIds;import org.apache.derby.iapi.services.io.StreamStorable;import org.apache.derby.iapi.services.io.FormatIdInputStream;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.types.BooleanDataValue;import org.apache.derby.iapi.types.StringDataValue;import org.apache.derby.iapi.types.NumberDataValue;import org.apache.derby.iapi.services.cache.ClassSize;import org.apache.derby.iapi.util.StringUtil;import org.apache.derby.iapi.types.SQLInteger;import java.io.ObjectOutput;import java.io.ObjectInput;import java.io.IOException;import java.io.InputStream;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.PreparedStatement;/** * SQLBinary satisfies the DataValueDescriptor * interfaces (i.e., DataType). It implements a String holder, * e.g. for storing a column value; it can be specified * when constructed to not allow nulls. Nullability cannot be changed * after construction. * <p> * Because DataType is a subclass of DataType, * SQLBit can play a role in either a DataType/Value * or a DataType/KeyRow, interchangeably. <P> Format : <encoded length><raw data> <BR> Length is encoded to support 5.x databases where the length was stored as the number of bits. The first bit of the first byte indicates if the format is an old (5.x) style or a new 8.1 style. 8.1 then uses the next two bits to indicate how the length is encoded. <BR> <encoded length> is one of N styles. <UL> <LI> (5.x format) 4 byte Java format integer value 0 - either <raw data> is 0 bytes/bits or an unknown number of bytes. <LI> (5.x format) 4 byte Java format integer value >0 (positive) - number of bits in <raw data>, number of bytes in <raw data> is the minimum number of bytes required to store the number of bits. <LI> (8.1 format) 1 byte encoded length (0 <= L <= 31) - number of bytes of <raw data> - encoded = 0x80 & L <LI> (8.1 format) 3 byte encoded length (32 <= L < 64k) - number of bytes of <raw data> - encoded = 0xA0 <L as Java format unsigned short> <LI> (8.1 format) 5 byte encoded length (64k <= L < 2G) - number of bytes of <raw data> - encoded = 0xC0 <L as Java format integer> <LI> (future) to be determined L >= 2G - encoded 0xE0 <encoding of L to be determined> (0xE0 is an esacape to allow any number of arbitary encodings in the future). </UL> */public abstract class SQLBinary extends DataType implements BitDataValue{ static final byte PAD = (byte) 0x20; private static final int BASE_MEMORY_USAGE = ClassSize.estimateBaseFromCatalog( SQLBinary.class); public int estimateMemoryUsage() { int sz = BASE_MEMORY_USAGE; if( null != dataValue) sz += dataValue.length; return sz; } // end of estimateMemoryUsage /* * object state */ byte[] dataValue; /* * stream state */ InputStream stream; /** Length of the stream in units relevant to the type, in this case bytes. */ int streamLength; /** no-arg constructor, required by Formattable. */ SQLBinary() { } SQLBinary(byte[] val) { dataValue = val; } public final void setValue(byte[] theValue) { dataValue = theValue; stream = null; streamLength = -1; } /** * Used by JDBC -- string should not contain * SQL92 formatting. * * @exception StandardException Thrown on error */ public final String getString() throws StandardException { if (getValue() == null) return null; else if (dataValue.length * 2 < 0) //if converted to hex, length exceeds max int { throw StandardException.newException(SQLState.LANG_STRING_TRUNCATION, getTypeName(), "", String.valueOf(Integer.MAX_VALUE)); } else { return org.apache.derby.iapi.util.StringUtil.toHexString(dataValue, 0, dataValue.length); } } /** * @exception StandardException Thrown on error */ public final InputStream getStream() { return (stream); } /** * * @exception StandardException Thrown on error */ public final byte[] getBytes() throws StandardException { return getValue(); } byte[] getValue() throws StandardException { try { if ((dataValue == null) && (stream != null)) { if (stream instanceof FormatIdInputStream) { readExternal((FormatIdInputStream) stream); } else if ( stream instanceof NewByteArrayInputStream ) { // this piece of code handles the case that a stream has been // opened on the bit value. the stream will have already called // readExternal() on the underlying FormatableBitSet. we just need to // retrieve the byte array from that stream. NewByteArrayInputStream nbais = (NewByteArrayInputStream) stream; dataValue = nbais.getData(); } else { readExternal(new FormatIdInputStream(stream)); } stream = null; streamLength = -1; } } catch (IOException ioe) { throw StandardException.newException(SQLState.LANG_STREAMING_COLUMN_I_O_EXCEPTION, ioe, getTypeName()); } return dataValue; } /** * length in bytes * * @exception StandardException Thrown on error */ public final int getLength() throws StandardException { if (stream != null) { if (streamLength != -1) return streamLength; } return (getBytes() == null) ? 0 : getBytes().length; } /* * Storable interface, implies Externalizable, TypedFormat */ /** * see if the Bit value is null. * @see org.apache.derby.iapi.services.io.Storable#isNull */ public final boolean isNull() { return (dataValue == null) && (stream == null); } /** Write the value out from the byte array (not called if null) using the 8.1 encoding. * @exception IOException io exception */ public final void writeExternal(ObjectOutput out) throws IOException { int len = dataValue.length; if (len <= 31) { out.write((byte) (0x80 | (len & 0xff))); } else if (len <= 0xFFFF) { out.write((byte) 0xA0); out.writeShort((short) len); } else { out.write((byte) 0xC0); out.writeInt(len); } out.write(dataValue, 0, dataValue.length); } /** * delegated to bit * * @exception IOException io exception * @exception ClassNotFoundException class not found */ public final void readExternal(ObjectInput in) throws IOException { // need to clear stream first, in case this object is reused, and // stream is set by previous use. Track 3794. stream = null; streamLength = -1; int len = SQLBinary.readBinaryLength(in); if (len != 0) { dataValue = new byte[len]; in.readFully(dataValue); } else { readFromStream((InputStream) in); } } public final void readExternalFromArray(ArrayInputStream in) throws IOException { // need to clear stream first, in case this object is reused, and // stream is set by previous use. Track 3794. stream = null; streamLength = -1; int len = SQLBinary.readBinaryLength(in); if (len != 0) { dataValue = new byte[len]; in.readFully(dataValue); } else { readFromStream(in); } } private static int readBinaryLength(ObjectInput in) throws IOException { int len = 0; int bl = in.read(); if (len < 0) throw new java.io.EOFException(); if ((bl & 0x80) != 0) { if (bl == 0xC0) { len = in.readInt(); } else if (bl == 0xA0) { len = in.readUnsignedShort(); } else { len = bl & 0x1F; } } else { // old length in bits int v2 = in.read(); int v3 = in.read(); int v4 = in.read(); if (v2 < 0 || v3 < 0 || v4 < 0) throw new java.io.EOFException(); int lenInBits = (((bl & 0xff) << 24) | ((v2 & 0xff) << 16) | ((v3 & 0xff) << 8) | (v4 & 0xff)); len = lenInBits / 8; if ((lenInBits % 8) != 0) len++; } return len; } private void readFromStream(InputStream in) throws IOException { dataValue = null; // allow gc of the old value before the new. byte[] tmpData = new byte[32 * 1024]; int off = 0; for (;;) { int len = in.read(tmpData, off, tmpData.length - off); if (len == -1) break; off += len; int available = in.available(); int extraSpace = available - (tmpData.length - off); if (extraSpace > 0) { // need to grow the array int size = tmpData.length * 2; if (extraSpace > tmpData.length) size += extraSpace; byte[] grow = new byte[size]; System.arraycopy(tmpData, 0, grow, 0, off); tmpData = grow; } } dataValue = new byte[off]; System.arraycopy(tmpData, 0, dataValue, 0, off); } /** * @see org.apache.derby.iapi.services.io.Storable#restoreToNull */ public final void restoreToNull() { dataValue = null; stream = null; streamLength = -1; } /** @exception StandardException thrown on error */ public final boolean compare(int op, DataValueDescriptor other, boolean orderedNulls, boolean unknownRV) throws StandardException { if (!orderedNulls) // nulls are unordered { if (SanityManager.DEBUG) { int otherTypeFormatId = other.getTypeFormatId(); if (!((StoredFormatIds.SQL_BIT_ID == otherTypeFormatId) || (StoredFormatIds.SQL_VARBIT_ID == otherTypeFormatId) || (StoredFormatIds.SQL_LONGVARBIT_ID == otherTypeFormatId) || (StoredFormatIds.SQL_CHAR_ID == otherTypeFormatId) || (StoredFormatIds.SQL_VARCHAR_ID == otherTypeFormatId) || (StoredFormatIds.SQL_LONGVARCHAR_ID == otherTypeFormatId) || ((StoredFormatIds.SQL_BLOB_ID == otherTypeFormatId) && (StoredFormatIds.SQL_BLOB_ID == getTypeFormatId())) )) SanityManager.THROWASSERT( "Some fool passed in a "+ other.getClass().getName() + ", " + otherTypeFormatId + " to SQLBinary.compare()"); } String otherString = other.getString(); if (this.getString() == null || otherString == null) return unknownRV; } /* Do the comparison */ return super.compare(op, other, orderedNulls, unknownRV); } /** @exception StandardException thrown on error */ public final int compare(DataValueDescriptor other) throws StandardException { /* Use compare method from dominant type, negating result * to reflect flipping of sides. */ if (typePrecedence() < other.typePrecedence()) { return - (other.compare(this)); } /* ** By convention, nulls sort High, and null == null */ if (this.isNull() || other.isNull()) { if (!isNull()) return -1; if (!other.isNull()) return 1; return 0; // both null } return SQLBinary.compare(getBytes(), other.getBytes()); } /* * CloneableObject interface */ /** From CloneableObject * Shallow clone a StreamStorable without objectifying. This is used to avoid * unnecessary objectifying of a stream object. The only difference of this method * from getClone is this method does not objectify a stream. beetle 4896 */ public final Object cloneObject() { if (stream == null) return getClone(); SQLBinary self = (SQLBinary) getNewNull(); self.setStream(stream); return self; } /* * DataValueDescriptor interface */ /** @see DataValueDescriptor#getClone */ public final DataValueDescriptor getClone() { try { DataValueDescriptor cloneDVD = getNewNull(); cloneDVD.setValue(getValue()); return cloneDVD; } catch (StandardException se) { if (SanityManager.DEBUG) SanityManager.THROWASSERT("Unexpected exception " + se); return null; } } /* * DataValueDescriptor interface */ /* * StreamStorable interface : */ public final InputStream returnStream() { return stream; } public final void setStream(InputStream newStream) { this.dataValue = null; this.stream = newStream; streamLength = -1; } public final void loadStream() throws StandardException { getValue(); } /* * class interface */ boolean objectNull(Object o) { if (o == null) { setToNull(); return true; } return false; } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -