--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.iapi.types.SQLTinyint\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.services.sanity.SanityManager;\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
+\r
+import org.apache.derby.iapi.types.BooleanDataValue;\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.NumberDataValue;\r
+import org.apache.derby.iapi.types.TypeId;\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
+ * SQLTinyint satisfies the DataValueDescriptor\r
+ * interfaces (i.e., OrderableDataType). It implements a tinyint 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
+ * SQLTinyint 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
+ */\r
+public final class SQLTinyint\r
+ extends NumberDataType\r
+{\r
+\r
+ /*\r
+ * constants\r
+ */\r
+ static final int TINYINT_LENGTH = 1;\r
+\r
+ /*\r
+ * object state\r
+ */\r
+ private byte value;\r
+ private boolean isnull;\r
+\r
+ private static final int BASE_MEMORY_USAGE = ClassSize.estimateBaseFromCatalog( SQLTinyint.class);\r
+\r
+ public int estimateMemoryUsage()\r
+ {\r
+ return BASE_MEMORY_USAGE;\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 byte.\r
+ */\r
+ public SQLTinyint() \r
+ {\r
+ isnull = true;\r
+ }\r
+\r
+ public SQLTinyint(byte val)\r
+ {\r
+ value = val;\r
+ }\r
+\r
+ /* This constructor gets used for the getClone() method */\r
+ public SQLTinyint(byte val, boolean isnull)\r
+ {\r
+ value = val;\r
+ this.isnull = isnull;\r
+ }\r
+\r
+ //////////////////////////////////////////////////////////////\r
+ //\r
+ // DataValueDescriptor interface\r
+ // (mostly implemented in DataType)\r
+ //\r
+ //////////////////////////////////////////////////////////////\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getInt \r
+ */\r
+ public int getInt()\r
+ {\r
+ return (int) value;\r
+ }\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getByte \r
+ */\r
+ public byte getByte() \r
+ {\r
+ return value;\r
+ }\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getShort \r
+ */\r
+ public short getShort()\r
+ {\r
+ return (short) 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
+ /** \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
+ return (isNull()) ? \r
+ null:\r
+ Byte.toString(value);\r
+ }\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getLength \r
+ */\r
+ public int getLength()\r
+ {\r
+ return TINYINT_LENGTH;\r
+ }\r
+\r
+ /** \r
+ * @see DataValueDescriptor#getObject \r
+ */\r
+ public Object getObject() \r
+ {\r
+ return (isNull()) ?\r
+ null:\r
+ new Integer(value);\r
+ }\r
+\r
+ // this is for DataType's error generator\r
+ public String getTypeName()\r
+ {\r
+ return TypeId.TINYINT_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
+ {\r
+ return StoredFormatIds.SQL_TINYINT_ID;\r
+ }\r
+\r
+ /**\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.writeByte(value);\r
+ }\r
+\r
+ /** @see java.io.Externalizable#readExternal */\r
+ public void readExternal(ObjectInput in) throws IOException {\r
+\r
+ value = in.readByte();\r
+ isnull = false;\r
+ }\r
+ public void readExternalFromArray(ArrayInputStream in) throws IOException {\r
+\r
+ value = in.readByte();\r
+ isnull = false;\r
+ }\r
+\r
+\r
+ /**\r
+ * @see Storable#restoreToNull\r
+ *\r
+ */\r
+ public void restoreToNull()\r
+ {\r
+ value = 0;\r
+ isnull = true;\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
+ int thisValue, otherValue;\r
+\r
+ /* Do comparisons with ints to avoid overflow problems */\r
+ thisValue = this.getInt();\r
+ 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 SQLTinyint(value, isnull);\r
+ }\r
+\r
+ /**\r
+ * @see DataValueDescriptor#getNewNull\r
+ */\r
+ public DataValueDescriptor getNewNull()\r
+ {\r
+ return new SQLTinyint();\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
+ value = resultSet.getByte(colNumber);\r
+ isnull = (isNullable && resultSet.wasNull());\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.TINYINT);\r
+ return;\r
+ }\r
+\r
+ ps.setByte(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.updateByte(position, value);\r
+ }\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 = Byte.valueOf(theValue.trim()).byteValue();\r
+ } catch (NumberFormatException nfe) {\r
+ throw invalidFormat();\r
+ }\r
+ isnull = false;\r
+ }\r
+ }\r
+\r
+\r
+ public void setValue(byte theValue)\r
+ {\r
+ value = theValue;\r
+ isnull = false;\r
+ }\r
+\r
+ /**\r
+ @exception StandardException if outsideRangeForTinyint\r
+ */\r
+ public void setValue(short theValue) throws StandardException\r
+ {\r
+ if (theValue > Byte.MAX_VALUE || theValue < Byte.MIN_VALUE)\r
+ throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "TINYINT");\r
+ value = (byte)theValue;\r
+ isnull = false;\r
+ }\r
+\r
+ /**\r
+ @exception StandardException if outsideRangeForTinyint\r
+ */\r
+ public void setValue(int theValue) throws StandardException\r
+ {\r
+ if (theValue > Byte.MAX_VALUE || theValue < Byte.MIN_VALUE)\r
+ throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "TINYINT");\r
+ value = (byte)theValue;\r
+ isnull = false;\r
+ }\r
+\r
+ /**\r
+ @exception StandardException if outsideRangeForTinyint\r
+ */\r
+ public void setValue(long theValue) throws StandardException\r
+ {\r
+ if (theValue > Byte.MAX_VALUE || theValue < Byte.MIN_VALUE)\r
+ throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "TINYINT");\r
+ value = (byte)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 > Byte.MAX_VALUE || theValue < Byte.MIN_VALUE)\r
+ throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "TINYINT");\r
+\r
+ float floorValue = (float)Math.floor(theValue);\r
+\r
+ value = (byte)floorValue;\r
+ isnull = false;\r
+\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 > Byte.MAX_VALUE || theValue < Byte.MIN_VALUE)\r
+ throw outOfRange();\r
+\r
+ double floorValue = Math.floor(theValue);\r
+\r
+ value = (byte)floorValue;\r
+ isnull = false;\r
+ }\r
+\r
+ /**\r
+ * @see NumberDataValue#setValue\r
+ *\r
+ */\r
+ public void setValue(boolean theValue)\r
+ {\r
+ value = theValue?(byte)1:(byte)0;\r
+ isnull = false;\r
+ }\r
+\r
+ \r
+ protected void setFrom(DataValueDescriptor theValue) throws StandardException {\r
+\r
+ setValue(theValue.getByte());\r
+ }\r
+\r
+\r
+ /*\r
+ * DataValueDescriptor interface\r
+ */\r
+\r
+ /** @see DataValueDescriptor#typePrecedence */\r
+ public int typePrecedence()\r
+ {\r
+ return TypeId.TINYINT_PRECEDENCE;\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.getByte() == right.getByte());\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.getByte() != right.getByte());\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 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.getByte() < right.getByte());\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.getByte() > right.getByte());\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.getByte() <= right.getByte());\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.getByte() >= right.getByte());\r
+ }\r
+\r
+\r
+\r
+\r
+\r
+ /**\r
+ * This method implements the * operator for "tinyint * tinyint".\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 SQLTinyint 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 SQLTinyint();\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 product of 2 bytes is an int, so we check to see if the product\r
+ ** is in the range of values for a byte.\r
+ */\r
+ int product = left.getByte() * right.getByte();\r
+ result.setValue(product);\r
+ return result;\r
+ }\r
+\r
+\r
+ /**\r
+ mod(tinyint, tinyint)\r
+ */\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 SQLTinyint();\r
+ }\r
+\r
+ if (dividend.isNull() || divisor.isNull())\r
+ {\r
+ result.setToNull();\r
+ return result;\r
+ }\r
+\r
+ /* Catch divide by 0 */\r
+ byte byteDivisor = divisor.getByte();\r
+ if (byteDivisor == 0)\r
+ {\r
+ throw StandardException.newException(SQLState.LANG_DIVIDE_BY_ZERO);\r
+ }\r
+\r
+ result.setValue(dividend.getByte() % byteDivisor);\r
+ return result;\r
+ }\r
+ /**\r
+ * This method implements the unary minus operator for tinyint.\r
+ *\r
+ * @param result The result of a previous call to this method, null\r
+ * if not called yet\r
+ *\r
+ * @return A SQLTinyint 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 SQLTinyint();\r
+ }\r
+\r
+ if (this.isNull())\r
+ {\r
+ result.setToNull();\r
+ return result;\r
+ }\r
+\r
+ int operandValue = this.getByte();\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 Byte.toString(value);\r
+ }\r
+\r
+\r
+ /*\r
+ * Hash code\r
+ */\r
+ public int hashCode()\r
+ {\r
+ return (int) value;\r
+ }\r
+}\r