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