Source code: org/apache/derby/iapi/types/SQLBit.java
1 /*
2
3 Derby - Class org.apache.derby.iapi.types.SQLBit
4
5 Copyright 1999, 2004 The Apache Software Foundation or its licensors, as applicable.
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18
19 */
20
21 package org.apache.derby.iapi.types;
22
23 import org.apache.derby.iapi.reference.SQLState;
24
25 import org.apache.derby.iapi.services.io.ArrayInputStream;
26
27 import org.apache.derby.iapi.types.DataTypeDescriptor;
28 import org.apache.derby.iapi.types.DataValueDescriptor;
29 import org.apache.derby.iapi.types.TypeId;
30 import org.apache.derby.iapi.types.BitDataValue;
31 import org.apache.derby.iapi.types.DataValueDescriptor;
32 import org.apache.derby.iapi.types.ConcatableDataValue;
33 import org.apache.derby.iapi.types.VariableSizeDataValue;
34 import org.apache.derby.iapi.error.StandardException;
35
36 import org.apache.derby.iapi.services.io.FormatIdUtil;
37 import org.apache.derby.iapi.services.io.StoredFormatIds;
38 import org.apache.derby.iapi.services.io.StreamStorable;
39 import org.apache.derby.iapi.services.io.FormatIdInputStream;
40
41 import org.apache.derby.iapi.services.sanity.SanityManager;
42
43 import org.apache.derby.iapi.types.BooleanDataValue;
44 import org.apache.derby.iapi.types.StringDataValue;
45 import org.apache.derby.iapi.types.NumberDataValue;
46
47 import org.apache.derby.iapi.services.cache.ClassSize;
48 import org.apache.derby.iapi.util.StringUtil;
49
50 import org.apache.derby.iapi.types.SQLInteger;
51
52 import java.io.ObjectOutput;
53 import java.io.ObjectInput;
54 import java.io.IOException;
55 import java.io.InputStream;
56
57 import java.sql.ResultSet;
58 import java.sql.SQLException;
59
60 /**
61 * SQLBit satisfies the DataValueDescriptor
62 * interfaces (i.e., DataType). It implements a String holder,
63 * e.g. for storing a column value; it can be specified
64 * when constructed to not allow nulls. Nullability cannot be changed
65 * after construction.
66 * <p>
67 * Because DataType is a subclass of DataType,
68 * SQLBit can play a role in either a DataType/Value
69 * or a DataType/KeyRow, interchangeably.
70
71 <P>
72 Format : <encoded length><raw data>
73 <BR>
74 Length is encoded to support 5.x databases where the length was stored as the number of bits.
75 The first bit of the first byte indicates if the format is an old (5.x) style or a new 8.1 style.
76 8.1 then uses the next two bits to indicate how the length is encoded.
77 <BR>
78 <encoded length> is one of N styles.
79 <UL>
80 <LI> (5.x format) 4 byte Java format integer value 0 - either <raw data> is 0 bytes/bits or an unknown number of bytes.
81 <LI> (5.x format) 4 byte Java format integer value >0 (positive) - number of bits in <raw data>, number of bytes in <raw data>
82 is the minimum number of bytes required to store the number of bits.
83 <LI> (8.1 format) 1 byte encoded length (0 <= L <= 31) - number of bytes of <raw data> - encoded = 0x80 & L
84 <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>
85 <LI> (8.1 format) 5 byte encoded length (64k <= L < 2G) - number of bytes of <raw data> - encoded = 0xC0 <L as Java format integer>
86 <LI> (future) to be determined L >= 2G - encoded 0xE0 <encoding of L to be determined>
87 (0xE0 is an esacape to allow any number of arbitary encodings in the future).
88 </UL>
89 */
90 public class SQLBit
91 extends SQLBinary
92 {
93
94 /**
95 *
96 * @exception StandardException Thrown on error
97 */
98 public Object getObject() throws StandardException
99 {
100 return getBytes();
101 }
102
103
104 public String getTypeName()
105 {
106 return TypeId.BIT_NAME;
107 }
108
109 /*
110 * Storable interface, implies Externalizable, TypedFormat
111 */
112
113 /**
114 Return my format identifier.
115
116 @see org.apache.derby.iapi.services.io.TypedFormat#getTypeFormatId
117 */
118 public int getTypeFormatId()
119 {
120 return StoredFormatIds.SQL_BIT_ID;
121 }
122
123
124 /** @see DataValueDescriptor#getNewNull */
125 public DataValueDescriptor getNewNull()
126 {
127 return new SQLBit();
128 }
129
130 /**
131 * @see DataValueDescriptor#setValueFromResultSet
132 *
133 * @exception SQLException Thrown on error
134 */
135 public void setValueFromResultSet(ResultSet resultSet, int colNumber,
136 boolean isNullable)
137 throws SQLException
138 {
139 dataValue = resultSet.getBytes(colNumber);
140
141 if (isNullable && resultSet.wasNull())
142 {
143 setToNull();
144 }
145 }
146
147 /*
148 * DataValueDescriptor interface
149 */
150
151 /** @see DataValueDescriptor#typePrecedence */
152 public int typePrecedence()
153 {
154 return TypeId.BIT_PRECEDENCE;
155 }
156
157 /*
158 * constructors
159 */
160
161 /**
162 no-arg constructor, required by Formattable.
163 */
164 public SQLBit()
165 {
166 }
167
168 public SQLBit(byte[] val)
169 {
170 dataValue = val;
171 }
172
173
174 /**
175 * @see DataValueDescriptor#setValue
176 *
177 */
178 public final void setValue(Object theValue)
179 throws StandardException
180 {
181 if (theValue == null)
182 {
183 setToNull();
184 }
185 else if (theValue instanceof byte[])
186 {
187 ((SQLBinary) this).setValue((byte[])theValue);
188 }
189 else
190 {
191 throwLangSetMismatch(theValue);
192 }
193 }
194
195 /**
196 * Normalization method - this method may be called when putting
197 * a value into a SQLBit, for example, when inserting into a SQLBit
198 * column. See NormalizeResultSet in execution.
199 *
200 * @param desiredType The type to normalize the source column to
201 * @param source The value to normalize
202 *
203 * @exception StandardException Thrown for null into
204 * non-nullable column, and for
205 * truncation error
206 */
207
208 public void normalize(
209 DataTypeDescriptor desiredType,
210 DataValueDescriptor source)
211 throws StandardException
212 {
213 int desiredWidth = desiredType.getMaximumWidth();
214
215 ((SQLBinary) this).setValue(source.getBytes());
216 setWidth(desiredWidth, 0, true);
217 }
218
219 /**
220 * Set the width of the to the desired value. Used
221 * when CASTing. Ideally we'd recycle normalize(), but
222 * the behavior is different (we issue a warning instead
223 * of an error, and we aren't interested in nullability).
224 *
225 * @param desiredWidth the desired length
226 * @param desiredScale the desired scale (ignored)
227 * @param errorOnTrunc throw error on truncation
228 * @return this with the target width
229 *
230 * @exception StandardException Thrown on non-zero truncation
231 * if errorOnTrunc is true
232 */
233 public DataValueDescriptor setWidth(int desiredWidth,
234 int desiredScale, // Ignored
235 boolean errorOnTrunc)
236 throws StandardException
237 {
238 /*
239 ** If the input is NULL, nothing to do.
240 */
241 if (getValue() == null)
242 {
243 return this;
244 }
245
246 int sourceWidth = dataValue.length;
247
248 /*
249 ** If the input is shorter than the desired type,
250 ** then pad with blanks to the right length.
251 */
252 if (sourceWidth < desiredWidth)
253 {
254 byte[] actualData = new byte[desiredWidth];
255 System.arraycopy(dataValue, 0, actualData, 0, dataValue.length);
256 java.util.Arrays.fill(actualData, dataValue.length, actualData.length, SQLBinary.PAD);
257 dataValue = actualData;
258 }
259 /*
260 ** Truncation?
261 */
262 else if (sourceWidth > desiredWidth)
263 {
264 if (errorOnTrunc)
265 {
266 // error if truncating non pad characters.
267 for (int i = desiredWidth; i < dataValue.length; i++) {
268
269 if (dataValue[i] != SQLBinary.PAD)
270 throw StandardException.newException(SQLState.LANG_STRING_TRUNCATION, getTypeName(),
271 StringUtil.formatForPrint(this.toString()),
272 String.valueOf(desiredWidth));
273 }
274 }
275 //else
276 //{
277 // RESOLVE: when we have warnings, issue a warning if
278 // truncation of non-zero bits will occur
279 //}
280
281 /*
282 ** Truncate to the desired width.
283 */
284 byte[] shrunkData = new byte[desiredWidth];
285 System.arraycopy(dataValue, 0, shrunkData, 0, desiredWidth);
286 dataValue = shrunkData;
287
288 }
289 return this;
290 }
291
292
293
294
295
296 }