--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.iapi.types.SQLSmallint\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.iapi.types;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.services.io.ArrayInputStream;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.TypeId;\r
+import org.apache.derby.iapi.types.NumberDataValue;\r
+import org.apache.derby.iapi.types.BooleanDataValue;\r
+\r
+import org.apache.derby.iapi.services.io.StoredFormatIds;\r
+import org.apache.derby.iapi.services.io.Storable;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.services.cache.ClassSize;\r
+\r
+import org.apache.derby.iapi.types.NumberDataType;\r
+import org.apache.derby.iapi.types.SQLBoolean;\r
+\r
+import java.io.ObjectOutput;\r
+import java.io.ObjectInput;\r
+import java.io.IOException;\r
+\r
+import java.sql.ResultSet;\r
+import java.sql.PreparedStatement;\r
+import java.sql.SQLException;\r
+\r
+/**\r
+ * SQLSmallint satisfies the DataValueDescriptor\r
+ * interfaces (i.e., OrderableDataType). It implements a smallint column, \r
+ * e.g. for storing a column value; it can be specified\r
+ * when constructed to not allow nulls. Nullability cannot be changed\r
+ * after construction, as it affects the storage size and mechanism.\r
+ * <p>\r
+ * Because OrderableDataType is a subtype of ValueColumn,\r
+ * SQLSmallint can play a role in either a ValueColumn/Row\r
+ * or a OrderableDataType/Row, interchangeably.\r
+ * <p>\r
+ * We assume the store has a flag for nullness of the value,\r
+ * and simply return a 0-length array for the stored form\r
+ * when the value is null.\r
+ * <p>\r
+ * PERFORMANCE: There are likely alot of performance improvements\r
+ * possible for this implementation -- it new's Short\r
+ * more than it probably wants to.\r
+ */\r
+public final class SQLSmallint\r
+ extends NumberDataType\r
+{\r
+ /*\r
+ * DataValueDescriptor interface\r
+ * (mostly implemented in DataType)\r
+ */\r
+\r
+\r
+ // JDBC is lax in what it permits and what it\r
+ // returns, so we are similarly lax\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getInt \r
+ */\r
+ public int getInt()\r
+ {\r
+ return (int) value;\r
+ }\r
+\r
+ /** \r
+ * @exception StandardException thrown on failure to convert\r
+ * @see DataValueDescriptor#getByte \r
+ */\r
+ public byte getByte() throws StandardException\r
+ {\r
+ if (value > Byte.MAX_VALUE || value < Byte.MIN_VALUE)\r
+ throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "TINYINT");\r
+ return (byte) value;\r
+ }\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getShort \r
+ */\r
+ public short getShort()\r
+ {\r
+ return value;\r
+ }\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getLong \r
+ */\r
+ public long getLong()\r
+ {\r
+ return (long) value;\r
+ }\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getFloat \r
+ */\r
+ public float getFloat()\r
+ {\r
+ return (float) value;\r
+ }\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getDouble \r
+ */\r
+ public double getDouble()\r
+ {\r
+ return (double) value;\r
+ }\r
+\r
+ // for lack of a specification: 0 or null is false,\r
+ // all else is true\r
+ /** \r
+ * @see DataValueDescriptor#getBoolean \r
+ */\r
+ public boolean getBoolean()\r
+ {\r
+ return (value != 0);\r
+ }\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getString \r
+ */\r
+ public String getString()\r
+ {\r
+ if (isNull())\r
+ return null;\r
+ else\r
+ return Short.toString(value);\r
+ }\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getLength \r
+ */\r
+ public int getLength()\r
+ {\r
+ return SMALLINT_LENGTH;\r
+ }\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getObject \r
+ */\r
+ public Object getObject() \r
+ {\r
+ if (isNull())\r
+ return null;\r
+ else\r
+ return new Integer(value);\r
+ }\r
+\r
+ // this is for DataType's error generator\r
+ public String getTypeName()\r
+ {\r
+ return TypeId.SMALLINT_NAME;\r
+ }\r
+\r
+ /*\r
+ * Storable interface, implies Externalizable, TypedFormat\r
+ */\r
+\r
+\r
+ /**\r
+ Return my format identifier.\r
+\r
+ @see org.apache.derby.iapi.services.io.TypedFormat#getTypeFormatId\r
+ */\r
+ public int getTypeFormatId() {\r
+ return StoredFormatIds.SQL_SMALLINT_ID;\r
+ }\r
+\r
+ /**\r
+ * always false for non-nullable columns\r
+ @see Storable#isNull\r
+ */\r
+ public boolean isNull()\r
+ {\r
+ return isnull;\r
+ }\r
+\r
+ public void writeExternal(ObjectOutput out) throws IOException {\r
+\r
+ // never called when value is null\r
+ if (SanityManager.DEBUG)\r
+ SanityManager.ASSERT(! isNull());\r
+\r
+ out.writeShort(value);\r
+ }\r
+\r
+ /** @see java.io.Externalizable#readExternal */\r
+ public void readExternalFromArray(ArrayInputStream in) throws IOException {\r
+\r
+ value = in.readShort();\r
+ isnull = false;\r
+ }\r
+ public void readExternal(ObjectInput in) throws IOException {\r
+\r
+ value = in.readShort();\r
+ isnull = false;\r
+ }\r
+\r
+ /**\r
+ * @see Storable#restoreToNull\r
+ *\r
+ */\r
+ public void restoreToNull()\r
+ {\r
+ value = 0;\r
+ isnull = true;\r
+ }\r
+\r
+\r
+ /** @exception StandardException Thrown on error */\r
+ protected int typeCompare(DataValueDescriptor arg) throws StandardException\r
+ {\r
+ /* neither are null, get the value */\r
+\r
+ /* Do comparisons with ints to avoid overflow problems */\r
+ int thisValue = this.getInt();\r
+ int otherValue = arg.getInt();\r
+ if (thisValue == otherValue)\r
+ return 0;\r
+ else if (thisValue > otherValue)\r
+ return 1;\r
+ else\r
+ return -1;\r
+ }\r
+\r
+ /*\r
+ * DataValueDescriptor interface\r
+ */\r
+\r
+ /** @see DataValueDescriptor#getClone */\r
+ public DataValueDescriptor getClone()\r
+ {\r
+ return new SQLSmallint(value, isnull);\r
+ }\r
+\r
+ /**\r
+ * @see DataValueDescriptor#getNewNull\r
+ */\r
+ public DataValueDescriptor getNewNull()\r
+ {\r
+ return new SQLSmallint();\r
+ }\r
+\r
+ /** \r
+ * @see DataValueDescriptor#setValueFromResultSet \r
+ *\r
+ * @exception SQLException Thrown on error\r
+ */\r
+ public void setValueFromResultSet(ResultSet resultSet, int colNumber,\r
+ boolean isNullable)\r
+ throws SQLException\r
+ {\r
+ try {\r
+ value = resultSet.getShort(colNumber);\r
+ isnull = (isNullable && resultSet.wasNull());\r
+ } catch (SQLException selq) {\r
+ int i = resultSet.getInt(colNumber);\r
+ value = (short) i;\r
+ isnull = false;\r
+\r
+ }\r
+ }\r
+ /**\r
+ Set the value into a PreparedStatement.\r
+\r
+ @exception SQLException Error setting value in PreparedStatement\r
+ */\r
+ public final void setInto(PreparedStatement ps, int position) throws SQLException {\r
+\r
+ if (isNull()) {\r
+ ps.setNull(position, java.sql.Types.SMALLINT);\r
+ return;\r
+ }\r
+\r
+ ps.setShort(position, value);\r
+ }\r
+ /**\r
+ Set this value into a ResultSet for a subsequent ResultSet.insertRow\r
+ or ResultSet.updateRow. This method will only be called for non-null values.\r
+\r
+ @exception SQLException thrown by the ResultSet object\r
+ @exception StandardException thrown by me accessing my value.\r
+ */\r
+ public final void setInto(ResultSet rs, int position) throws SQLException, StandardException {\r
+ rs.updateShort(position, value);\r
+ }\r
+\r
+\r
+ /*\r
+ * class interface\r
+ */\r
+\r
+ /*\r
+ * constructors\r
+ */\r
+\r
+ /**\r
+ No-arg constructor, required by Formattable.\r
+ // This constructor also gets used when we are\r
+ // allocating space for a short.\r
+ */\r
+ public SQLSmallint() \r
+ {\r
+ isnull = true;\r
+ }\r
+\r
+ public SQLSmallint(short val)\r
+ {\r
+ value = val;\r
+ }\r
+\r
+ /* This constructor gets used for the getClone() method */\r
+ public SQLSmallint(short val, boolean isnull)\r
+ {\r
+ value = val;\r
+ this.isnull = isnull;\r
+ }\r
+\r
+ /**\r
+ @exception StandardException thrown if string not accepted\r
+ */\r
+ public void setValue(String theValue)\r
+ throws StandardException\r
+ {\r
+ if (theValue == null)\r
+ {\r
+ value = 0;\r
+ isnull = true;\r
+ }\r
+ else\r
+ {\r
+ try {\r
+ value = Short.valueOf(theValue.trim()).shortValue();\r
+ } catch (NumberFormatException nfe) {\r
+ throw invalidFormat();\r
+ }\r
+ isnull = false;\r
+ }\r
+\r
+ }\r
+\r
+ public void setValue(short theValue)\r
+ {\r
+ value = theValue;\r
+ isnull = false;\r
+ }\r
+\r
+ public void setValue(byte theValue)\r
+ {\r
+ value = theValue;\r
+ isnull = false;\r
+ }\r
+\r
+ /**\r
+ @exception StandardException if outsideRangeForSmallint\r
+ */\r
+ public void setValue(int theValue) throws StandardException\r
+ {\r
+ if (theValue > Short.MAX_VALUE || theValue < Short.MIN_VALUE)\r
+ throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "SMALLINT");\r
+ value = (short)theValue;\r
+ isnull = false;\r
+ }\r
+\r
+ /**\r
+ @exception StandardException if outsideRangeForSmallint\r
+ */\r
+ public void setValue(long theValue) throws StandardException\r
+ {\r
+ if (theValue > Short.MAX_VALUE || theValue < Short.MIN_VALUE)\r
+ throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "SMALLINT");\r
+ value = (short)theValue;\r
+ isnull = false;\r
+ }\r
+\r
+ /**\r
+ * @see NumberDataValue#setValue\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public void setValue(float theValue) throws StandardException\r
+ {\r
+ theValue = NumberDataType.normalizeREAL(theValue);\r
+\r
+ if (theValue > Short.MAX_VALUE || theValue < Short.MIN_VALUE)\r
+ throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "SMALLINT");\r
+\r
+ float floorValue = (float)Math.floor(theValue);\r
+\r
+ value = (short)floorValue;\r
+ isnull = false;\r
+ }\r
+\r
+ /**\r
+ * @see NumberDataValue#setValue\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public void setValue(double theValue) throws StandardException\r
+ {\r
+ theValue = NumberDataType.normalizeDOUBLE(theValue);\r
+\r
+ if (theValue > Short.MAX_VALUE || theValue < Short.MIN_VALUE)\r
+ throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "SMALLINT");\r
+\r
+ double floorValue = Math.floor(theValue);\r
+\r
+ value = (short)floorValue;\r
+ isnull = false;\r
+ }\r
+\r
+ /**\r
+ * @see NumberDataValue#setValue\r
+ *\r
+ */\r
+ public void setValue(boolean theValue)\r
+ {\r
+ value = theValue?(short)1:(short)0;\r
+ isnull = false;\r
+ }\r
+\r
+ protected void setFrom(DataValueDescriptor theValue) throws StandardException {\r
+\r
+ setValue(theValue.getShort());\r
+ }\r
+\r
+ /*\r
+ * DataValueDescriptor interface\r
+ */\r
+\r
+ /** @see DataValueDescriptor#typePrecedence */\r
+ public int typePrecedence()\r
+ {\r
+ return TypeId.SMALLINT_PRECEDENCE;\r
+ }\r
+\r
+\r
+ /*\r
+ ** SQL Operators\r
+ */\r
+\r
+ /**\r
+ * The = operator as called from the language module, as opposed to\r
+ * the storage module.\r
+ *\r
+ * @param left The value on the left side of the =\r
+ * @param right The value on the right side of the =\r
+ *\r
+ * @return A SQL boolean value telling whether the two parameters are equal\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+\r
+ public BooleanDataValue equals(DataValueDescriptor left,\r
+ DataValueDescriptor right)\r
+ throws StandardException\r
+ {\r
+ return SQLBoolean.truthValue(left,\r
+ right,\r
+ left.getShort() == right.getShort());\r
+ }\r
+\r
+ /**\r
+ * The <> operator as called from the language module, as opposed to\r
+ * the storage module.\r
+ *\r
+ * @param left The value on the left side of the <>\r
+ * @param right The value on the right side of the <>\r
+ *\r
+ * @return A SQL boolean value telling whether the two parameters\r
+ * are not equal\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+\r
+ public BooleanDataValue notEquals(DataValueDescriptor left,\r
+ DataValueDescriptor right)\r
+ throws StandardException\r
+ {\r
+ return SQLBoolean.truthValue(left,\r
+ right,\r
+ left.getShort() != right.getShort());\r
+ }\r
+\r
+ /**\r
+ * The < operator as called from the language module, as opposed to\r
+ * the storage module.\r
+ *\r
+ * @param left The value on the left side of the <\r
+ * @param right The value on the right side of the <\r
+ * is not.\r
+ *\r
+ * @return A SQL boolean value telling whether the first operand is less\r
+ * than the second operand\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+\r
+ public BooleanDataValue lessThan(DataValueDescriptor left,\r
+ DataValueDescriptor right)\r
+ throws StandardException\r
+ {\r
+ return SQLBoolean.truthValue(left,\r
+ right,\r
+ left.getShort() < right.getShort());\r
+ }\r
+\r
+ /**\r
+ * The > operator as called from the language module, as opposed to\r
+ * the storage module.\r
+ *\r
+ * @param left The value on the left side of the >\r
+ * @param right The value on the right side of the >\r
+ *\r
+ * @return A SQL boolean value telling whether the first operand is greater\r
+ * than the second operand\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+\r
+ public BooleanDataValue greaterThan(DataValueDescriptor left,\r
+ DataValueDescriptor right)\r
+ throws StandardException\r
+ {\r
+ return SQLBoolean.truthValue(left,\r
+ right,\r
+ left.getShort() > right.getShort());\r
+ }\r
+\r
+ /**\r
+ * The <= operator as called from the language module, as opposed to\r
+ * the storage module.\r
+ *\r
+ * @param left The value on the left side of the <=\r
+ * @param right The value on the right side of the <=\r
+ *\r
+ * @return A SQL boolean value telling whether the first operand is less\r
+ * than or equal to the second operand\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+\r
+ public BooleanDataValue lessOrEquals(DataValueDescriptor left,\r
+ DataValueDescriptor right)\r
+ throws StandardException\r
+ {\r
+ return SQLBoolean.truthValue(left,\r
+ right,\r
+ left.getShort() <= right.getShort());\r
+ }\r
+\r
+ /**\r
+ * The >= operator as called from the language module, as opposed to\r
+ * the storage module.\r
+ *\r
+ * @param left The value on the left side of the >=\r
+ * @param right The value on the right side of the >=\r
+ *\r
+ * @return A SQL boolean value telling whether the first operand is greater\r
+ * than or equal to the second operand\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+\r
+ public BooleanDataValue greaterOrEquals(DataValueDescriptor left,\r
+ DataValueDescriptor right)\r
+ throws StandardException\r
+ {\r
+ return SQLBoolean.truthValue(left,\r
+ right,\r
+ left.getShort() >= right.getShort());\r
+ }\r
+\r
+\r
+\r
+\r
+ /**\r
+ * This method implements the * operator for "smallint * smallint".\r
+ *\r
+ * @param left The first value to be multiplied\r
+ * @param right The second value to be multiplied\r
+ * @param result The result of a previous call to this method, null\r
+ * if not called yet\r
+ *\r
+ * @return A SQLSmallint containing the result of the multiplication\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+\r
+ public NumberDataValue times(NumberDataValue left,\r
+ NumberDataValue right,\r
+ NumberDataValue result)\r
+ throws StandardException\r
+ {\r
+ if (result == null)\r
+ {\r
+ result = new SQLSmallint();\r
+ }\r
+\r
+ if (left.isNull() || right.isNull())\r
+ {\r
+ result.setToNull();\r
+ return result;\r
+ }\r
+\r
+ /*\r
+ ** Java does not check for overflow with integral types. We have to\r
+ ** check the result ourselves.\r
+ **\r
+ The setValue(int) will perform the overflow check.\r
+ */\r
+ int product = left.getShort() * right.getShort();\r
+ result.setValue(product);\r
+ return result;\r
+ }\r
+\r
+\r
+ /**\r
+ mod(smallint, smallint)\r
+ */\r
+ public NumberDataValue mod(NumberDataValue dividend,\r
+ NumberDataValue divisor,\r
+ NumberDataValue result)\r
+ throws StandardException\r
+ {\r
+ if (result == null)\r
+ {\r
+ result = new SQLSmallint();\r
+ }\r
+\r
+ if (dividend.isNull() || divisor.isNull())\r
+ {\r
+ result.setToNull();\r
+ return result;\r
+ }\r
+\r
+ /* Catch divide by 0 */\r
+ short shortDivisor = divisor.getShort();\r
+ if (shortDivisor == 0)\r
+ {\r
+ throw StandardException.newException(SQLState.LANG_DIVIDE_BY_ZERO);\r
+ }\r
+\r
+ result.setValue(dividend.getShort() % shortDivisor);\r
+ return result;\r
+ }\r
+ /**\r
+ * This method implements the unary minus operator for smallint.\r
+ *\r
+ * @param result The result of a previous call to this method, null\r
+ * if not called yet\r
+ *\r
+ * @return A SQLSmalllint containing the result of the division\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+\r
+ public NumberDataValue minus(NumberDataValue result)\r
+ throws StandardException\r
+ {\r
+ if (result == null)\r
+ {\r
+ result = new SQLSmallint();\r
+ }\r
+\r
+ if (this.isNull())\r
+ {\r
+ result.setToNull();\r
+ return result;\r
+ }\r
+\r
+ int operandValue = this.getShort();\r
+\r
+ result.setValue(-operandValue);\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ * This method implements the isNegative method.\r
+ *\r
+ * @return A boolean. If this.value is negative, return true.\r
+ * For positive values or null, return false.\r
+ */\r
+\r
+ protected boolean isNegative()\r
+ {\r
+ return !isNull() && value < 0;\r
+ }\r
+\r
+ /*\r
+ * String display of value\r
+ */\r
+\r
+ public String toString()\r
+ {\r
+ if (isNull())\r
+ return "NULL";\r
+ else\r
+ return Short.toString(value);\r
+ }\r
+\r
+ /*\r
+ * Hash code\r
+ */\r
+ public int hashCode()\r
+ {\r
+ return (int) value;\r
+ }\r
+\r
+ /*\r
+ * useful constants...\r
+ */\r
+ static final int SMALLINT_LENGTH = 2;\r
+\r
+ private static final int BASE_MEMORY_USAGE = ClassSize.estimateBaseFromCatalog( SQLSmallint.class);\r
+\r
+ public int estimateMemoryUsage()\r
+ {\r
+ return BASE_MEMORY_USAGE;\r
+ }\r
+\r
+ /*\r
+ * object state\r
+ */\r
+ private short value;\r
+ private boolean isnull;\r
+}\r