001: /*
002:
003: Derby - Class org.apache.derby.iapi.types.SQLInteger
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.iapi.types;
023:
024: import org.apache.derby.iapi.services.io.ArrayInputStream;
025:
026: import org.apache.derby.iapi.types.DataValueDescriptor;
027: import org.apache.derby.iapi.types.TypeId;
028: import org.apache.derby.iapi.types.NumberDataValue;
029: import org.apache.derby.iapi.types.BooleanDataValue;
030: import org.apache.derby.iapi.reference.SQLState;
031:
032: import org.apache.derby.iapi.services.io.StoredFormatIds;
033: import org.apache.derby.iapi.services.io.Storable;
034:
035: import org.apache.derby.iapi.error.StandardException;
036: import org.apache.derby.iapi.services.sanity.SanityManager;
037:
038: import org.apache.derby.iapi.services.cache.ClassSize;
039:
040: import org.apache.derby.iapi.types.NumberDataType;
041: import org.apache.derby.iapi.types.SQLBoolean;
042:
043: import java.io.ObjectOutput;
044: import java.io.ObjectInput;
045: import java.io.IOException;
046:
047: import java.sql.ResultSet;
048: import java.sql.PreparedStatement;
049: import java.sql.SQLException;
050:
051: /**
052: * SQLInteger satisfies the DataValueDescriptor
053: * interfaces (i.e., OrderableDataType). It implements an integer column,
054: * e.g. for * storing a column value; it can be specified
055: * when constructed to not allow nulls. Nullability cannot be changed
056: * after construction, as it affects the storage size and mechanism.
057: * <p>
058: * Because OrderableDataType is a subtype of DataType,
059: * SQLInteger can play a role in either a DataType/Row
060: * or a OrderableDataType/Row, interchangeably.
061: * <p>
062: * We assume the store has a flag for nullness of the value,
063: * and simply return a 0-length array for the stored form
064: * when the value is null.
065: * <p>
066: * PERFORMANCE: There are likely alot of performance improvements
067: * possible for this implementation -- it new's Integer
068: * more than it probably wants to.
069: */
070: public final class SQLInteger extends NumberDataType {
071: /*
072: * DataValueDescriptor interface
073: * (mostly implemented in DataType)
074: */
075:
076: // JDBC is lax in what it permits and what it
077: // returns, so we are similarly lax
078: // @see DataValueDescriptor
079: public int getInt() {
080: /* This value is 0 if the SQLInteger is null */
081: return value;
082: }
083:
084: /**
085: * @exception StandardException thrown on failure to convert
086: */
087: public byte getByte() throws StandardException {
088: if (value > Byte.MAX_VALUE || value < Byte.MIN_VALUE)
089: throw StandardException
090: .newException(
091: SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
092: "TINYINT");
093: return (byte) value;
094: }
095:
096: /**
097: * @exception StandardException thrown on failure to convert
098: */
099: public short getShort() throws StandardException {
100: if (value > Short.MAX_VALUE || value < Short.MIN_VALUE)
101: throw StandardException.newException(
102: SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
103: "SMALLINT");
104: return (short) value;
105: }
106:
107: public long getLong() {
108: return (long) value;
109: }
110:
111: public float getFloat() {
112: return (float) value;
113: }
114:
115: public double getDouble() {
116: return (double) value;
117: }
118:
119: // for lack of a specification: 0 or null is false,
120: // all else is true
121: public boolean getBoolean() {
122: return (value != 0);
123: }
124:
125: public String getString() {
126: if (isNull())
127: return null;
128: else
129: return Integer.toString(value);
130: }
131:
132: public Object getObject() {
133: if (isNull())
134: return null;
135: else
136: return new Integer(value);
137: }
138:
139: public int getLength() {
140: return INTEGER_LENGTH;
141: }
142:
143: // this is for DataType's error generator
144: public String getTypeName() {
145: return TypeId.INTEGER_NAME;
146: }
147:
148: /*
149: * Storable interface, implies Externalizable, TypedFormat
150: */
151:
152: /**
153: Return my format identifier.
154:
155: @see org.apache.derby.iapi.services.io.TypedFormat#getTypeFormatId
156: */
157: public int getTypeFormatId() {
158: return StoredFormatIds.SQL_INTEGER_ID;
159: }
160:
161: /*
162: * see if the integer value is null.
163: */
164: /** @see Storable#isNull */
165: public boolean isNull() {
166: return isnull;
167: }
168:
169: public void writeExternal(ObjectOutput out) throws IOException {
170:
171: // never called when value is null
172: if (SanityManager.DEBUG)
173: SanityManager.ASSERT(!isNull());
174:
175: out.writeInt(value);
176: }
177:
178: /** @see java.io.Externalizable#readExternal */
179: public final void readExternal(ObjectInput in) throws IOException {
180:
181: value = in.readInt();
182: isnull = false;
183: }
184:
185: public final void readExternalFromArray(ArrayInputStream in)
186: throws IOException {
187:
188: value = in.readInt();
189: isnull = false;
190: }
191:
192: /**
193: * @see Storable#restoreToNull
194: *
195: */
196:
197: public void restoreToNull() {
198: value = 0;
199: isnull = true;
200: }
201:
202: /** @exception StandardException Thrown on error */
203: protected int typeCompare(DataValueDescriptor arg)
204: throws StandardException {
205: /* neither are null, get the value */
206:
207: int this Value = this .getInt();
208:
209: int otherValue = arg.getInt();
210:
211: if (this Value == otherValue)
212: return 0;
213: else if (this Value > otherValue)
214: return 1;
215: else
216: return -1;
217: }
218:
219: /*
220: * DataValueDescriptor interface
221: */
222:
223: /** @see DataValueDescriptor#getClone */
224: public DataValueDescriptor getClone() {
225: SQLInteger nsi = new SQLInteger(value);
226:
227: nsi.isnull = isnull;
228: return nsi;
229: }
230:
231: /**
232: * @see DataValueDescriptor#getNewNull
233: */
234: public DataValueDescriptor getNewNull() {
235: return new SQLInteger();
236: }
237:
238: /**
239: * @see DataValueDescriptor#setValueFromResultSet
240: *
241: * @exception SQLException Thrown on error
242: */
243: public void setValueFromResultSet(ResultSet resultSet,
244: int colNumber, boolean isNullable) throws SQLException {
245: if ((value = resultSet.getInt(colNumber)) == 0)
246: isnull = (isNullable && resultSet.wasNull());
247: else
248: isnull = false;
249: }
250:
251: /**
252: Set the value into a PreparedStatement.
253:
254: @exception SQLException Error setting value in PreparedStatement
255: */
256: public final void setInto(PreparedStatement ps, int position)
257: throws SQLException {
258:
259: if (isNull()) {
260: ps.setNull(position, java.sql.Types.INTEGER);
261: return;
262: }
263:
264: ps.setInt(position, value);
265: }
266:
267: /**
268: Set this value into a ResultSet for a subsequent ResultSet.insertRow
269: or ResultSet.updateRow. This method will only be called for non-null values.
270:
271: @exception SQLException thrown by the ResultSet object
272: */
273: public final void setInto(ResultSet rs, int position)
274: throws SQLException {
275: rs.updateInt(position, value);
276: }
277:
278: /*
279: * class interface
280: */
281:
282: /*
283: * constructors
284: */
285:
286: /** no-arg constructor, required by Formattable */
287: // This constructor also gets used when we are
288: // allocating space for an integer.
289: public SQLInteger() {
290: isnull = true;
291: }
292:
293: public SQLInteger(int val) {
294: value = val;
295: }
296:
297: public SQLInteger(char val) {
298: value = val;
299: }
300:
301: public SQLInteger(Integer obj) {
302: if (isnull = (obj == null))
303: ;
304: else
305: value = obj.intValue();
306: }
307:
308: /**
309: @exception StandardException thrown if string not accepted
310: */
311: public void setValue(String theValue) throws StandardException {
312: if (theValue == null) {
313: value = 0;
314: isnull = true;
315: } else {
316: try {
317: value = Integer.valueOf(theValue.trim()).intValue();
318: } catch (NumberFormatException nfe) {
319: throw invalidFormat();
320: }
321: isnull = false;
322: }
323: }
324:
325: public void setValue(int theValue) {
326: value = theValue;
327: isnull = false;
328: }
329:
330: /**
331: @exception StandardException thrown on overflow
332: */
333: public void setValue(long theValue) throws StandardException {
334: if (theValue > Integer.MAX_VALUE
335: || theValue < Integer.MIN_VALUE) {
336: throw outOfRange();
337: }
338:
339: value = (int) theValue;
340: isnull = false;
341: }
342:
343: /**
344: * @see NumberDataValue#setValue
345: *
346: * @exception StandardException Thrown on error
347: */
348: public void setValue(float theValue) throws StandardException {
349: theValue = NumberDataType.normalizeREAL(theValue);
350:
351: if (theValue > Integer.MAX_VALUE
352: || theValue < Integer.MIN_VALUE)
353: throw outOfRange();
354:
355: float floorValue = (float) Math.floor(theValue);
356:
357: value = (int) floorValue;
358: isnull = false;
359: }
360:
361: /**
362: * @see NumberDataValue#setValue
363: *
364: * @exception StandardException Thrown on error
365: */
366: public void setValue(double theValue) throws StandardException {
367: theValue = NumberDataType.normalizeDOUBLE(theValue);
368:
369: if (theValue > Integer.MAX_VALUE
370: || theValue < Integer.MIN_VALUE)
371: throw outOfRange();
372:
373: double floorValue = Math.floor(theValue);
374:
375: value = (int) floorValue;
376: isnull = false;
377: }
378:
379: public void setValue(boolean theValue) {
380: value = theValue ? 1 : 0;
381: isnull = false;
382: }
383:
384: protected void setFrom(DataValueDescriptor theValue)
385: throws StandardException {
386:
387: setValue(theValue.getInt());
388: }
389:
390: /*
391: * DataValueDescriptor interface
392: */
393:
394: /** @see DataValueDescriptor#typePrecedence */
395: public int typePrecedence() {
396: return TypeId.INT_PRECEDENCE;
397: }
398:
399: /*
400: ** SQL Operators
401: */
402:
403: /**
404: * The = operator as called from the language module, as opposed to
405: * the storage module.
406: *
407: * @param left The value on the left side of the =
408: * @param right The value on the right side of the =
409: *
410: * @return A SQL boolean value telling whether the two parameters are equal
411: *
412: * @exception StandardException Thrown on error
413: */
414:
415: public BooleanDataValue equals(DataValueDescriptor left,
416: DataValueDescriptor right) throws StandardException {
417: return SQLBoolean.truthValue(left, right,
418: left.getInt() == right.getInt());
419: }
420:
421: /**
422: * The <> operator as called from the language module, as opposed to
423: * the storage module.
424: *
425: * @param left The value on the left side of the <>
426: * @param right The value on the right side of the <>
427: *
428: * @return A SQL boolean value telling whether the two parameters
429: * are not equal
430: *
431: * @exception StandardException Thrown on error
432: */
433:
434: public BooleanDataValue notEquals(DataValueDescriptor left,
435: DataValueDescriptor right) throws StandardException {
436: return SQLBoolean.truthValue(left, right,
437: left.getInt() != right.getInt());
438: }
439:
440: /**
441: * The < operator as called from the language module, as opposed to
442: * the storage module.
443: *
444: * @param left The value on the left side of the <
445: * @param right The value on the right side of the <
446: *
447: * @return A SQL boolean value telling whether the first operand is less
448: * than the second operand
449: *
450: * @exception StandardException Thrown on error
451: */
452:
453: public BooleanDataValue lessThan(DataValueDescriptor left,
454: DataValueDescriptor right) throws StandardException {
455: return SQLBoolean.truthValue(left, right, left.getInt() < right
456: .getInt());
457: }
458:
459: /**
460: * The > operator as called from the language module, as opposed to
461: * the storage module.
462: *
463: * @param left The value on the left side of the >
464: * @param right The value on the right side of the >
465: *
466: * @return A SQL boolean value telling whether the first operand is greater
467: * than the second operand
468: *
469: * @exception StandardException Thrown on error
470: */
471:
472: public BooleanDataValue greaterThan(DataValueDescriptor left,
473: DataValueDescriptor right) throws StandardException {
474: return SQLBoolean.truthValue(left, right, left.getInt() > right
475: .getInt());
476: }
477:
478: /**
479: * The <= operator as called from the language module, as opposed to
480: * the storage module.
481: *
482: * @param left The value on the left side of the <=
483: * @param right The value on the right side of the <=
484: *
485: * @return A SQL boolean value telling whether the first operand is less
486: * than or equal to the second operand
487: *
488: * @exception StandardException Thrown on error
489: */
490:
491: public BooleanDataValue lessOrEquals(DataValueDescriptor left,
492: DataValueDescriptor right) throws StandardException {
493: return SQLBoolean.truthValue(left, right,
494: left.getInt() <= right.getInt());
495: }
496:
497: /**
498: * The >= operator as called from the language module, as opposed to
499: * the storage module.
500: *
501: * @param left The value on the left side of the >=
502: * @param right The value on the right side of the >=
503: *
504: * @return A SQL boolean value telling whether the first operand is greater
505: * than or equal to the second operand
506: *
507: * @exception StandardException Thrown on error
508: */
509:
510: public BooleanDataValue greaterOrEquals(DataValueDescriptor left,
511: DataValueDescriptor right) throws StandardException {
512: return SQLBoolean.truthValue(left, right,
513: left.getInt() >= right.getInt());
514: }
515:
516: /**
517: * This method implements the * operator for "int * int".
518: *
519: * @param left The first value to be multiplied
520: * @param right The second value to be multiplied
521: * @param result The result of a previous call to this method, null
522: * if not called yet
523: *
524: * @return A SQLInteger containing the result of the multiplication
525: *
526: * @exception StandardException Thrown on error
527: */
528:
529: public NumberDataValue times(NumberDataValue left,
530: NumberDataValue right, NumberDataValue result)
531: throws StandardException {
532: if (result == null) {
533: result = new SQLInteger();
534: }
535:
536: if (left.isNull() || right.isNull()) {
537: result.setToNull();
538: return result;
539: }
540:
541: /*
542: ** Java does not check for overflow with integral types. We have to
543: ** check the result ourselves.
544: **
545: ** We can't use sign checking tricks like we do for '+' and '-' since
546: ** the product of 2 integers can wrap around multiple times. So, we
547: ** do long arithmetic and then verify that the result is within the
548: ** range of an int, throwing an error if it isn't.
549: */
550: long tempResult = left.getLong() * right.getLong();
551:
552: result.setValue(tempResult);
553: return result;
554: }
555:
556: /**
557: mod(int, int)
558: */
559: public NumberDataValue mod(NumberDataValue dividend,
560: NumberDataValue divisor, NumberDataValue result)
561: throws StandardException {
562: if (result == null) {
563: result = new SQLInteger();
564: }
565:
566: if (dividend.isNull() || divisor.isNull()) {
567: result.setToNull();
568: return result;
569: }
570:
571: /* Catch divide by 0 */
572: int intDivisor = divisor.getInt();
573: if (intDivisor == 0) {
574: throw StandardException
575: .newException(SQLState.LANG_DIVIDE_BY_ZERO);
576: }
577:
578: result.setValue(dividend.getInt() % intDivisor);
579: return result;
580: }
581:
582: /**
583: * This method implements the unary minus operator for int.
584: *
585: * @param result The result of a previous call to this method, null
586: * if not called yet
587: *
588: * @return A SQLInteger containing the result of the division
589: *
590: * @exception StandardException Thrown on error
591: */
592:
593: public NumberDataValue minus(NumberDataValue result)
594: throws StandardException {
595: int operandValue;
596:
597: if (result == null) {
598: result = new SQLInteger();
599: }
600:
601: if (this .isNull()) {
602: result.setToNull();
603: return result;
604: }
605:
606: operandValue = this .getInt();
607:
608: /*
609: ** In two's complement arithmetic, the minimum value for a number
610: ** can't be negated, since there is no representation for its
611: ** positive value. For integers, the minimum value is -2147483648,
612: ** and the maximum value is 2147483647.
613: */
614: if (operandValue == Integer.MIN_VALUE) {
615: throw outOfRange();
616: }
617:
618: result.setValue(-operandValue);
619: return result;
620: }
621:
622: /**
623: * This method implements the isNegative method.
624: *
625: * @return A boolean. If this.value is negative, return true.
626: * For positive values or null, return false.
627: */
628:
629: protected boolean isNegative() {
630: return !isNull() && value < 0;
631: }
632:
633: /*
634: * String display of value
635: */
636:
637: public String toString() {
638: if (isNull())
639: return "NULL";
640: else
641: return Integer.toString(value);
642: }
643:
644: /*
645: * Hash code
646: */
647: public int hashCode() {
648: return value;
649: }
650:
651: /*
652: * useful constants...
653: */
654: static final int INTEGER_LENGTH = 4; // must match the number of bytes written by DataOutput.writeInt()
655:
656: private static final int BASE_MEMORY_USAGE = ClassSize
657: .estimateBaseFromCatalog(SQLInteger.class);
658:
659: public int estimateMemoryUsage() {
660: return BASE_MEMORY_USAGE;
661: }
662:
663: /*
664: * object state
665: */
666: private int value;
667: private boolean isnull;
668: }
|