| /* Copyright (c) 2001-2010, The HSQL Development Group |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * Redistributions of source code must retain the above copyright notice, this |
| * list of conditions and the following disclaimer. |
| * |
| * Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * Neither the name of the HSQL Development Group nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, |
| * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| package org.hsqldb.types; |
| |
| import java.math.BigDecimal; |
| |
| import org.hsqldb.OpTypes; |
| import org.hsqldb.Session; |
| import org.hsqldb.SessionInterface; |
| import org.hsqldb.Tokens; |
| import org.hsqldb.error.Error; |
| import org.hsqldb.error.ErrorCode; |
| |
| /** |
| * Type subclass for various typs of INTERVAL.<p> |
| * |
| * @author Fred Toussi (fredt@users dot sourceforge.net) |
| * @version 1.9.0 |
| * @since 1.9.0 |
| */ |
| public final class IntervalType extends DTIType { |
| |
| public final boolean defaultPrecision; |
| public final boolean isYearMonth; |
| |
| private IntervalType(int typeGroup, int type, long precision, int scale, |
| int startIntervalType, int endIntervalType, |
| boolean defaultPrecision) { |
| |
| super(typeGroup, type, precision, scale, startIntervalType, |
| endIntervalType); |
| |
| switch (startIntervalType) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| case Types.SQL_INTERVAL_MONTH : |
| isYearMonth = true; |
| break; |
| |
| default : |
| isYearMonth = false; |
| break; |
| } |
| |
| this.defaultPrecision = defaultPrecision; |
| } |
| |
| public int displaySize() { |
| |
| switch (typeCode) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| return (int) precision + 1; |
| |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| return (int) precision + 4; |
| |
| case Types.SQL_INTERVAL_MONTH : |
| return (int) precision + 1; |
| |
| case Types.SQL_INTERVAL_DAY : |
| return (int) precision + 1; |
| |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| return (int) precision + 4; |
| |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| return (int) precision + 7; |
| |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| return (int) precision + 10 + (scale == 0 ? 0 |
| : scale + 1); |
| |
| case Types.SQL_INTERVAL_HOUR : |
| return (int) precision + 1; |
| |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| return (int) precision + 4; |
| |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| return (int) precision + 7 + (scale == 0 ? 0 |
| : scale + 1); |
| |
| case Types.SQL_INTERVAL_MINUTE : |
| return (int) precision + 1; |
| |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| return (int) precision + 4 + (scale == 0 ? 0 |
| : scale + 1); |
| |
| case Types.SQL_INTERVAL_SECOND : |
| return (int) precision + 1 + (scale == 0 ? 0 |
| : scale + 1); |
| |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| } |
| |
| public int getJDBCTypeCode() { |
| |
| // no JDBC number is available |
| return typeCode; |
| } |
| |
| public Class getJDBCClass() { |
| |
| switch (typeCode) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| case Types.SQL_INTERVAL_MONTH : |
| return IntervalMonthData.class; |
| |
| case Types.SQL_INTERVAL_DAY : |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| case Types.SQL_INTERVAL_HOUR : |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| case Types.SQL_INTERVAL_MINUTE : |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| case Types.SQL_INTERVAL_SECOND : |
| return org.hsqldb.types.IntervalSecondData.class; |
| |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| } |
| |
| public String getJDBCClassName() { |
| |
| switch (typeCode) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| case Types.SQL_INTERVAL_MONTH : |
| return IntervalMonthData.class.getName(); |
| |
| case Types.SQL_INTERVAL_DAY : |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| case Types.SQL_INTERVAL_HOUR : |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| case Types.SQL_INTERVAL_MINUTE : |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| case Types.SQL_INTERVAL_SECOND : |
| return org.hsqldb.types.IntervalSecondData.class.getName(); |
| |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| } |
| |
| public int getJDBCPrecision() { |
| return this.displaySize(); |
| } |
| |
| public int getSQLGenericTypeCode() { |
| return Types.SQL_INTERVAL; |
| } |
| |
| public String getNameString() { |
| return "INTERVAL " + getQualifier(typeCode); |
| } |
| |
| public static String getQualifier(int type) { |
| |
| switch (type) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| return "YEAR"; |
| |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| return "YEAR TO MONTH"; |
| |
| case Types.SQL_INTERVAL_MONTH : |
| return "MONTH"; |
| |
| case Types.SQL_INTERVAL_DAY : |
| return "DAY"; |
| |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| return "DAY TO HOUR"; |
| |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| return "DAY TO MINUTE"; |
| |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| return "DAY TO SECOND"; |
| |
| case Types.SQL_INTERVAL_HOUR : |
| return "HOUR"; |
| |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| return "HOUR TO MINUTE"; |
| |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| return "HOUR TO SECOND"; |
| |
| case Types.SQL_INTERVAL_MINUTE : |
| return "MINUTE"; |
| |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| return "MINUTE TO SECOND"; |
| |
| case Types.SQL_INTERVAL_SECOND : |
| return "SECOND"; |
| |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| } |
| |
| public String getDefinition() { |
| |
| if (precision == defaultIntervalPrecision |
| && (endIntervalType != Types.SQL_INTERVAL_SECOND |
| || scale == defaultIntervalFractionPrecision)) { |
| return getNameString(); |
| } |
| |
| StringBuffer sb = new StringBuffer(32); |
| |
| sb.append(Tokens.T_INTERVAL).append(' '); |
| sb.append(getQualifier(startIntervalType)); |
| |
| if (typeCode == Types.SQL_INTERVAL_SECOND) { |
| sb.append('('); |
| sb.append(precision); |
| |
| if (scale != defaultIntervalFractionPrecision) { |
| sb.append(','); |
| sb.append(scale); |
| } |
| |
| sb.append(')'); |
| |
| return sb.toString(); |
| } |
| |
| if (precision != defaultIntervalPrecision) { |
| sb.append('('); |
| sb.append(precision); |
| sb.append(')'); |
| } |
| |
| if (startIntervalType != endIntervalType) { |
| sb.append(' '); |
| sb.append(Tokens.T_TO); |
| sb.append(' '); |
| sb.append(Tokens.SQL_INTERVAL_FIELD_NAMES[endPartIndex]); |
| |
| if (endIntervalType == Types.SQL_INTERVAL_SECOND |
| && scale != defaultIntervalFractionPrecision) { |
| sb.append('('); |
| sb.append(scale); |
| sb.append(')'); |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| public boolean isIntervalType() { |
| return true; |
| } |
| |
| public boolean isYearMonthIntervalType() { |
| |
| switch (typeCode) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| case Types.SQL_INTERVAL_MONTH : |
| return true; |
| |
| default : |
| return false; |
| } |
| } |
| |
| public boolean isDaySecondIntervalType() { |
| |
| switch (typeCode) { |
| |
| case Types.SQL_INTERVAL_DAY : |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| case Types.SQL_INTERVAL_HOUR : |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| case Types.SQL_INTERVAL_MINUTE : |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| case Types.SQL_INTERVAL_SECOND : |
| return true; |
| |
| default : |
| return false; |
| } |
| } |
| |
| public boolean acceptsPrecision() { |
| return true; |
| } |
| |
| public boolean acceptsFractionalPrecision() { |
| return endIntervalType == Types.SQL_INTERVAL_SECOND; |
| } |
| |
| public Type getAggregateType(Type other) { |
| |
| if (typeCode == other.typeCode) { |
| if (precision >= other.precision && scale >= other.scale) { |
| return this; |
| } else if (precision <= other.precision && scale <= other.scale) { |
| return other; |
| } |
| } |
| |
| if (other == SQL_ALL_TYPES) { |
| return this; |
| } |
| |
| if (other.isCharacterType()) { |
| return other.getAggregateType(this); |
| } |
| |
| if (!other.isIntervalType()) { |
| throw Error.error(ErrorCode.X_42562); |
| } |
| |
| int startType = ((IntervalType) other).startIntervalType |
| > startIntervalType ? startIntervalType |
| : ((IntervalType) other) |
| .startIntervalType; |
| int endType = ((IntervalType) other).endIntervalType > endIntervalType |
| ? ((IntervalType) other).endIntervalType |
| : endIntervalType; |
| int newType = getCombinedIntervalType(startType, endType); |
| long newPrecision = precision > other.precision ? precision |
| : other.precision; |
| int newScale = scale > other.scale ? scale |
| : other.scale; |
| |
| try { |
| return getIntervalType(newType, startType, endType, newPrecision, |
| newScale, false); |
| } catch (RuntimeException e) { |
| throw Error.error(ErrorCode.X_42562); |
| } |
| } |
| |
| public Type getCombinedType(Type other, int operation) { |
| |
| switch (operation) { |
| |
| case OpTypes.MULTIPLY : |
| if (other.isNumberType()) { |
| return getIntervalType(this, maxIntervalPrecision, scale); |
| } |
| break; |
| |
| case OpTypes.DIVIDE : |
| if (other.isNumberType()) { |
| return this; |
| } |
| break; |
| |
| case OpTypes.ADD : |
| if (other.isDateTimeType()) { |
| return other.getCombinedType(this, operation); |
| } else if (other.isIntervalType()) { |
| IntervalType newType = |
| (IntervalType) getAggregateType(other); |
| |
| return getIntervalType(newType, maxIntervalPrecision, 0); |
| } |
| break; |
| |
| case OpTypes.SUBTRACT : |
| default : |
| return getAggregateType(other); |
| } |
| |
| throw Error.error(ErrorCode.X_42562); |
| } |
| |
| public int compare(Session session, Object a, Object b) { |
| |
| if (a == b) { |
| return 0; |
| } |
| |
| if (a == null) { |
| return -1; |
| } |
| |
| if (b == null) { |
| return 1; |
| } |
| |
| switch (typeCode) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| case Types.SQL_INTERVAL_MONTH : |
| return ((IntervalMonthData) a).compareTo( |
| (IntervalMonthData) b); |
| |
| case Types.SQL_INTERVAL_DAY : |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| case Types.SQL_INTERVAL_HOUR : |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| case Types.SQL_INTERVAL_MINUTE : |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| case Types.SQL_INTERVAL_SECOND : |
| return ((IntervalSecondData) a).compareTo( |
| (IntervalSecondData) b); |
| |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| } |
| |
| public Object convertToTypeLimits(SessionInterface session, Object a) { |
| |
| if (a == null) { |
| return null; |
| } |
| |
| if (a instanceof IntervalMonthData) { |
| IntervalMonthData im = (IntervalMonthData) a; |
| |
| if (im.units > getIntervalValueLimit()) { |
| throw Error.error(ErrorCode.X_22015); |
| } |
| } else if (a instanceof IntervalSecondData) { |
| IntervalSecondData is = (IntervalSecondData) a; |
| |
| if (is.units > getIntervalValueLimit()) { |
| throw Error.error(ErrorCode.X_22015); |
| } |
| |
| // int divisor = nanoScaleFactors[scale]; |
| // is.nanos = (is.nanos / divisor) * divisor; |
| } |
| |
| return a; |
| } |
| |
| public Object convertToType(SessionInterface session, Object a, |
| Type otherType) { |
| |
| if (a == null) { |
| return null; |
| } |
| |
| switch (otherType.typeCode) { |
| |
| case Types.SQL_CLOB : |
| a = a.toString(); |
| |
| // fall through |
| case Types.SQL_CHAR : |
| case Types.SQL_VARCHAR : |
| case Types.VARCHAR_IGNORECASE : { |
| return session.getScanner().convertToDatetimeInterval(session, |
| (String) a, this); |
| } |
| case Types.TINYINT : |
| case Types.SQL_SMALLINT : |
| case Types.SQL_INTEGER : |
| case Types.SQL_BIGINT : |
| case Types.SQL_REAL : |
| case Types.SQL_FLOAT : |
| case Types.SQL_DOUBLE : |
| case Types.SQL_NUMERIC : |
| case Types.SQL_DECIMAL : { |
| if (a instanceof BigDecimal) { |
| if (!NumberType.isInLongLimits((BigDecimal) a)) { |
| throw Error.error(ErrorCode.X_22015); |
| } |
| } |
| |
| long value = ((Number) a).longValue(); |
| |
| switch (this.endIntervalType) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| return IntervalMonthData.newIntervalYear(value, this); |
| |
| case Types.SQL_INTERVAL_MONTH : |
| return IntervalMonthData.newIntervalMonth(value, this); |
| |
| case Types.SQL_INTERVAL_DAY : |
| return IntervalSecondData.newIntervalDay(value, this); |
| |
| case Types.SQL_INTERVAL_HOUR : |
| return IntervalSecondData.newIntervalHour(value, this); |
| |
| case Types.SQL_INTERVAL_MINUTE : |
| return IntervalSecondData.newIntervalMinute(value, |
| this); |
| |
| case Types.SQL_INTERVAL_SECOND : { |
| int nanos = 0; |
| |
| if (scale > 0 && a instanceof BigDecimal) { |
| nanos = (int) NumberType.scaledDecimal( |
| a, DTIType.maxFractionPrecision); |
| } |
| |
| return new IntervalSecondData(value, nanos, this); |
| } |
| default : |
| throw Error.error(ErrorCode.X_42561); |
| } |
| } |
| case Types.SQL_INTERVAL_YEAR : { |
| long months = (((IntervalMonthData) a).units / 12) * 12; |
| |
| return new IntervalMonthData(months, this); |
| } |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| case Types.SQL_INTERVAL_MONTH : { |
| long months = ((IntervalMonthData) a).units; |
| |
| return new IntervalMonthData(months, this); |
| } |
| case Types.SQL_INTERVAL_DAY : { |
| long seconds = ((IntervalSecondData) a).units; |
| |
| seconds = (seconds / DTIType.yearToSecondFactors[2]) |
| * DTIType.yearToSecondFactors[2]; |
| |
| return new IntervalSecondData(seconds, 0, this); |
| } |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| case Types.SQL_INTERVAL_HOUR : |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| case Types.SQL_INTERVAL_MINUTE : { |
| long seconds = ((IntervalSecondData) a).units; |
| |
| seconds = (seconds / DTIType.yearToSecondFactors[endPartIndex]) |
| * DTIType.yearToSecondFactors[endPartIndex]; |
| |
| return new IntervalSecondData(seconds, 0, this); |
| } |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| case Types.SQL_INTERVAL_SECOND : { |
| long seconds = ((IntervalSecondData) a).units; |
| int nanos = ((IntervalSecondData) a).nanos; |
| |
| if (scale == 0) { |
| nanos = 0; |
| } else { |
| nanos = (nanos / (DTIType.nanoScaleFactors[scale])) |
| * (DTIType.nanoScaleFactors[scale]); |
| } |
| |
| return new IntervalSecondData(seconds, nanos, this); |
| } |
| default : |
| throw Error.error(ErrorCode.X_42561); |
| } |
| } |
| |
| public Object convertToDefaultType(SessionInterface session, Object a) { |
| |
| if (a == null) { |
| return null; |
| } |
| |
| if (a instanceof String) { |
| return convertToType(null, a, Type.SQL_VARCHAR); |
| } else { |
| throw Error.error(ErrorCode.X_42561); |
| } |
| } |
| |
| public String convertToString(Object a) { |
| |
| if (a == null) { |
| return null; |
| } |
| |
| switch (typeCode) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| case Types.SQL_INTERVAL_MONTH : |
| return intervalMonthToString(a); |
| |
| case Types.SQL_INTERVAL_DAY : |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| case Types.SQL_INTERVAL_HOUR : |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| case Types.SQL_INTERVAL_MINUTE : |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| case Types.SQL_INTERVAL_SECOND : |
| return intervalSecondToString(a); |
| |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| } |
| |
| public String convertToSQLString(Object a) { |
| |
| if (a == null) { |
| return Tokens.T_NULL; |
| } |
| |
| StringBuffer sb = new StringBuffer(32); |
| |
| sb.append(Tokens.T_INTERVAL).append(' '); |
| sb.append('\'').append(convertToString(a)).append('\'').append(' '); |
| sb.append(Tokens.SQL_INTERVAL_FIELD_NAMES[startPartIndex]); |
| sb.append(' '); |
| sb.append(Tokens.T_TO); |
| sb.append(' '); |
| sb.append(Tokens.SQL_INTERVAL_FIELD_NAMES[endPartIndex]); |
| |
| return sb.toString(); |
| } |
| |
| public boolean canConvertFrom(Type otherType) { |
| |
| if (otherType.typeCode == Types.SQL_ALL_TYPES) { |
| return true; |
| } |
| |
| if (otherType.isCharacterType()) { |
| return true; |
| } |
| |
| if (otherType.isNumberType()) { |
| return true; |
| } |
| |
| if (!otherType.isIntervalType()) { |
| return false; |
| } |
| |
| return !(isYearMonthIntervalType() |
| ^ ((IntervalType) otherType).isYearMonthIntervalType()); |
| } |
| |
| public int compareToTypeRange(Object o) { |
| |
| long max = precisionLimits[(int) precision]; |
| long units; |
| |
| if (o instanceof IntervalMonthData) { |
| units = ((IntervalMonthData) o).units; |
| } else if (o instanceof IntervalSecondData) { |
| units = ((IntervalSecondData) o).units; |
| } else { |
| return 0; |
| } |
| |
| if (units >= max) { |
| return 1; |
| } |
| |
| if (units < 0) { |
| if (-units >= max) { |
| return -1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| public Object absolute(Object a) { |
| |
| if (a == null) { |
| return null; |
| } |
| |
| if (a instanceof IntervalMonthData) { |
| if (((IntervalMonthData) a).units < 0) { |
| return negate(a); |
| } |
| } else { |
| if (((IntervalSecondData) a).units < 0 |
| || ((IntervalSecondData) a).nanos < 0) { |
| return negate(a); |
| } |
| } |
| |
| return a; |
| } |
| |
| public Object negate(Object a) { |
| |
| if (a == null) { |
| return null; |
| } |
| |
| if (a instanceof IntervalMonthData) { |
| long units = ((IntervalMonthData) a).units; |
| |
| return new IntervalMonthData(-units, this); |
| } else { |
| long units = ((IntervalSecondData) a).units; |
| int nanos = ((IntervalSecondData) a).nanos; |
| |
| return new IntervalSecondData(-units, -nanos, this, true); |
| } |
| } |
| |
| public Object add(Object a, Object b, Type otherType) { |
| |
| if (a == null || b == null) { |
| return null; |
| } |
| |
| switch (typeCode) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| case Types.SQL_INTERVAL_MONTH : |
| long months = ((IntervalMonthData) a).units |
| + ((IntervalMonthData) b).units; |
| |
| return new IntervalMonthData(months, this); |
| |
| case Types.SQL_INTERVAL_DAY : |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| case Types.SQL_INTERVAL_HOUR : |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| case Types.SQL_INTERVAL_MINUTE : |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| case Types.SQL_INTERVAL_SECOND : |
| long seconds = ((IntervalSecondData) a).units |
| + ((IntervalSecondData) b).units; |
| long nanos = ((IntervalSecondData) a).nanos |
| + ((IntervalSecondData) b).nanos; |
| |
| return new IntervalSecondData(seconds, nanos, this, true); |
| |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| } |
| |
| public Object subtract(Object a, Object b, Type otherType) { |
| |
| if (a == null || b == null) { |
| return null; |
| } |
| |
| switch (typeCode) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| case Types.SQL_INTERVAL_MONTH : |
| if (a instanceof IntervalMonthData |
| && b instanceof IntervalMonthData) { |
| long months = ((IntervalMonthData) a).units |
| - ((IntervalMonthData) b).units; |
| |
| return new IntervalMonthData(months, this); |
| } else if (a instanceof TimestampData |
| && b instanceof TimestampData) { |
| boolean isYear = typeCode == Types.SQL_INTERVAL_YEAR; |
| long months = |
| DateTimeType.subtractMonths((TimestampData) a, |
| (TimestampData) b, isYear); |
| |
| return new IntervalMonthData(months, this); |
| } |
| |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| case Types.SQL_INTERVAL_DAY : |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| case Types.SQL_INTERVAL_HOUR : |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| case Types.SQL_INTERVAL_MINUTE : |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| case Types.SQL_INTERVAL_SECOND : |
| if (a instanceof IntervalSecondData |
| && b instanceof IntervalSecondData) { |
| long seconds = ((IntervalSecondData) a).units |
| - ((IntervalSecondData) b).units; |
| long nanos = ((IntervalSecondData) a).nanos |
| - ((IntervalSecondData) b).nanos; |
| |
| return new IntervalSecondData(seconds, nanos, this, true); |
| } else if (a instanceof TimeData && b instanceof TimeData) { |
| long seconds = ((TimeData) a).getSeconds() |
| - ((TimeData) b).getSeconds(); |
| long nanos = ((TimeData) a).getNanos() |
| - ((TimeData) b).getNanos(); |
| |
| return new IntervalSecondData(seconds, nanos, this, true); |
| } else if (a instanceof TimestampData |
| && b instanceof TimestampData) { |
| long seconds = (((TimestampData) a).getSeconds() |
| - ((TimestampData) b).getSeconds()); |
| long nanos = ((TimestampData) a).getNanos() |
| - ((TimestampData) b).getNanos(); |
| |
| return new IntervalSecondData(seconds, nanos, this, true); |
| } |
| |
| // fall through |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| } |
| |
| public Object multiply(Object a, Object b) { |
| return multiplyOrDivide(a, b, false); |
| } |
| |
| public Object divide(Object a, Object b) { |
| return multiplyOrDivide(a, b, true); |
| } |
| |
| private Object multiplyOrDivide(Object a, Object b, boolean divide) { |
| |
| if (a == null || b == null) { |
| return null; |
| } |
| |
| if (a instanceof Number) { |
| Object temp = a; |
| |
| a = b; |
| b = temp; |
| } |
| |
| if (divide && NumberType.isZero(b)) { |
| throw Error.error(ErrorCode.X_22012); |
| } |
| |
| NumberType factorType = NumberType.getNumberType(Types.SQL_DECIMAL, |
| 40, maxFractionPrecision); |
| BigDecimal factor = (BigDecimal) factorType.convertToDefaultType(null, |
| b); |
| BigDecimal units; |
| |
| if (isYearMonth) { |
| units = BigDecimal.valueOf(((IntervalMonthData) a).units); |
| } else { |
| long value = |
| ((IntervalSecondData) a).units * DTIType.nanoScaleFactors[0] |
| + ((IntervalSecondData) a).nanos; |
| |
| units = BigDecimal.valueOf(value, 9); |
| } |
| |
| BigDecimal result = divide |
| ? (BigDecimal) factorType.divide(units, factor) |
| : (BigDecimal) factorType.multiply(units, factor); |
| |
| if (!NumberType.isInLongLimits(result)) { |
| throw Error.error(ErrorCode.X_22015); |
| } |
| |
| if (isYearMonth) { |
| return new IntervalMonthData(result.longValue(), this); |
| } |
| |
| int nanos = (int) NumberType.scaledDecimal(result, |
| DTIType.maxFractionPrecision); |
| |
| return new IntervalSecondData(result.longValue(), nanos, this, true); |
| } |
| |
| String intervalMonthToString(Object a) { |
| |
| StringBuffer sb = new StringBuffer(8); |
| long months = ((IntervalMonthData) a).units; |
| |
| if (months < 0) { |
| months = -months; |
| |
| sb.append('-'); |
| } |
| |
| for (int i = startPartIndex; i <= endPartIndex; i++) { |
| int factor = DTIType.yearToSecondFactors[i]; |
| long part = months / factor; |
| |
| if (i == startPartIndex) { |
| int zeros = (int) precision - getPrecisionExponent(part); |
| /* |
| for (int j = 0; j < zeros; j++) { |
| buffer.append('0'); |
| } |
| */ |
| } else if (part < 10) { |
| sb.append('0'); |
| } |
| |
| sb.append(part); |
| |
| months %= factor; |
| |
| if (i < endPartIndex) { |
| sb.append((char) DTIType.yearToSecondSeparators[i]); |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| String intervalSecondToString(Object a) { |
| |
| long seconds = ((IntervalSecondData) a).units; |
| int nanos = ((IntervalSecondData) a).nanos; |
| |
| return intervalSecondToString(seconds, nanos, false); |
| } |
| |
| public int precedenceDegree(Type other) { |
| |
| if (other.isIntervalType()) { |
| int otherIndex = ((IntervalType) other).endPartIndex; |
| |
| return otherIndex - endPartIndex; |
| } |
| |
| return Integer.MIN_VALUE; |
| } |
| |
| public int getStartIntervalType() { |
| return startIntervalType; |
| } |
| |
| public int getEndIntervalType() { |
| return endIntervalType; |
| } |
| |
| public static IntervalType newIntervalType(int type, long precision, |
| int fractionPrecision) { |
| |
| int startType = getStartIntervalType(type); |
| int endType = getEndIntervalType(type); |
| int group = startType > Types.SQL_INTERVAL_MONTH |
| ? Types.SQL_INTERVAL_SECOND |
| : Types.SQL_INTERVAL_MONTH; |
| |
| return new IntervalType(group, type, precision, fractionPrecision, |
| startType, endType, false); |
| } |
| |
| public static IntervalType getIntervalType(IntervalType type, |
| long precision, int fractionalPrecision) { |
| |
| if (type.precision >= precision && type.scale >= fractionalPrecision) { |
| return type; |
| } |
| |
| return getIntervalType(type.typeCode, precision, fractionalPrecision); |
| } |
| |
| public static IntervalType getIntervalType(int type, long precision, |
| int fractionPrecision) { |
| |
| int startType = getStartIntervalType(type); |
| int endType = getEndIntervalType(type); |
| |
| return getIntervalType(type, startType, endType, precision, |
| fractionPrecision, false); |
| } |
| |
| public static IntervalType getIntervalType(int startIndex, int endIndex, |
| long precision, int fractionPrecision) { |
| |
| boolean defaultPrecision = precision == -1; |
| |
| if (startIndex == -1 || endIndex == -1) { |
| throw Error.error(ErrorCode.X_22006); |
| } |
| |
| if (startIndex > endIndex) { |
| throw Error.error(ErrorCode.X_22006); |
| } |
| |
| if (startIndex <= DTIType.INTERVAL_MONTH_INDEX |
| && endIndex > DTIType.INTERVAL_MONTH_INDEX) { |
| throw Error.error(ErrorCode.X_22006); |
| } |
| |
| int startType = DTIType.intervalParts[startIndex]; |
| int endType = DTIType.intervalParts[endIndex]; |
| int type = DTIType.intervalTypes[startIndex][endIndex]; |
| |
| if (precision == 0 || precision > DTIType.maxIntervalPrecision |
| || fractionPrecision > DTIType.maxFractionPrecision) { |
| throw Error.error(ErrorCode.X_42592); |
| } |
| |
| if (precision == -1) { |
| precision = DTIType.defaultIntervalPrecision; |
| } |
| |
| if (fractionPrecision == -1) { |
| fractionPrecision = endType == Types.SQL_INTERVAL_SECOND |
| ? DTIType.defaultIntervalFractionPrecision |
| : 0; |
| } |
| |
| return getIntervalType(type, startType, endType, precision, |
| fractionPrecision, defaultPrecision); |
| } |
| |
| public static IntervalType getIntervalType(int type, int startType, |
| int endType, long precision, int fractionPrecision, |
| boolean defaultPrecision) { |
| |
| int group = startType > Types.SQL_INTERVAL_MONTH |
| ? Types.SQL_INTERVAL_SECOND |
| : Types.SQL_INTERVAL_MONTH; |
| |
| if (defaultPrecision) { |
| return new IntervalType(group, type, precision, fractionPrecision, |
| startType, endType, defaultPrecision); |
| } |
| |
| switch (type) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| if (precision == DTIType.defaultIntervalPrecision) { |
| return SQL_INTERVAL_YEAR; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| if (precision == DTIType.defaultIntervalPrecision) { |
| return SQL_INTERVAL_YEAR_TO_MONTH; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_MONTH : |
| if (precision == DTIType.defaultIntervalPrecision) { |
| return SQL_INTERVAL_MONTH; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_DAY : |
| if (precision == DTIType.defaultIntervalPrecision) { |
| return SQL_INTERVAL_DAY; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| if (precision == DTIType.defaultIntervalPrecision) { |
| return SQL_INTERVAL_DAY_TO_HOUR; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| if (precision == DTIType.defaultIntervalPrecision) { |
| return SQL_INTERVAL_DAY_TO_MINUTE; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| if (precision == DTIType.defaultIntervalPrecision |
| && fractionPrecision |
| == DTIType.defaultIntervalFractionPrecision) { |
| return SQL_INTERVAL_DAY_TO_SECOND; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_HOUR : |
| if (precision == DTIType.defaultIntervalPrecision) { |
| return SQL_INTERVAL_HOUR; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| if (precision == DTIType.defaultIntervalPrecision) { |
| return SQL_INTERVAL_HOUR_TO_MINUTE; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_MINUTE : |
| if (precision == DTIType.defaultIntervalPrecision) { |
| return SQL_INTERVAL_MINUTE; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| if (precision == DTIType.defaultIntervalPrecision |
| && fractionPrecision |
| == DTIType.defaultIntervalFractionPrecision) { |
| return SQL_INTERVAL_HOUR_TO_SECOND; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| if (precision == DTIType.defaultIntervalPrecision |
| && fractionPrecision |
| == DTIType.defaultIntervalFractionPrecision) { |
| return SQL_INTERVAL_MINUTE_TO_SECOND; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_SECOND : |
| if (precision == DTIType.defaultIntervalPrecision |
| && fractionPrecision |
| == DTIType.defaultIntervalFractionPrecision) { |
| return SQL_INTERVAL_SECOND; |
| } |
| break; |
| |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| |
| return new IntervalType(group, type, precision, fractionPrecision, |
| startType, endType, defaultPrecision); |
| } |
| |
| public static int getStartIntervalType(int type) { |
| |
| int startType; |
| |
| switch (type) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| startType = Types.SQL_INTERVAL_YEAR; |
| break; |
| |
| case Types.SQL_INTERVAL_MONTH : |
| startType = Types.SQL_INTERVAL_MONTH; |
| break; |
| |
| case Types.SQL_INTERVAL_DAY : |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| startType = Types.SQL_INTERVAL_DAY; |
| break; |
| |
| case Types.SQL_INTERVAL_HOUR : |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| startType = Types.SQL_INTERVAL_HOUR; |
| break; |
| |
| case Types.SQL_INTERVAL_MINUTE : |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| startType = Types.SQL_INTERVAL_MINUTE; |
| break; |
| |
| case Types.SQL_INTERVAL_SECOND : |
| startType = Types.SQL_INTERVAL_SECOND; |
| break; |
| |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| |
| return startType; |
| } |
| |
| public static int getEndIntervalType(int type) { |
| |
| int endType; |
| |
| switch (type) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| endType = Types.SQL_INTERVAL_YEAR; |
| break; |
| |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| endType = Types.SQL_INTERVAL_MONTH; |
| break; |
| |
| case Types.SQL_INTERVAL_MONTH : |
| endType = Types.SQL_INTERVAL_MONTH; |
| break; |
| |
| case Types.SQL_INTERVAL_DAY : |
| endType = Types.SQL_INTERVAL_DAY; |
| break; |
| |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| endType = Types.SQL_INTERVAL_HOUR; |
| break; |
| |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| endType = Types.SQL_INTERVAL_MINUTE; |
| break; |
| |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| endType = Types.SQL_INTERVAL_SECOND; |
| break; |
| |
| case Types.SQL_INTERVAL_HOUR : |
| endType = Types.SQL_INTERVAL_HOUR; |
| break; |
| |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| endType = Types.SQL_INTERVAL_MINUTE; |
| break; |
| |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| endType = Types.SQL_INTERVAL_SECOND; |
| break; |
| |
| case Types.SQL_INTERVAL_MINUTE : |
| endType = Types.SQL_INTERVAL_MINUTE; |
| break; |
| |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| endType = Types.SQL_INTERVAL_SECOND; |
| break; |
| |
| case Types.SQL_INTERVAL_SECOND : |
| endType = Types.SQL_INTERVAL_SECOND; |
| break; |
| |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| |
| return endType; |
| } |
| |
| public static Type getCombinedIntervalType(IntervalType type1, |
| IntervalType type2) { |
| |
| int startType = type2.startIntervalType > type1.startIntervalType |
| ? type1.startIntervalType |
| : type2.startIntervalType; |
| int endType = type2.endIntervalType > type1.endIntervalType |
| ? type2.endIntervalType |
| : type1.endIntervalType; |
| int type = getCombinedIntervalType(startType, endType); |
| long precision = type1.precision > type2.precision ? type1.precision |
| : type2.precision; |
| int fractionPrecision = type1.scale > type2.scale ? type1.scale |
| : type2.scale; |
| |
| return getIntervalType(type, startType, endType, precision, |
| fractionPrecision, false); |
| } |
| |
| public static int getCombinedIntervalType(int startType, int endType) { |
| |
| if (startType == endType) { |
| return startType; |
| } |
| |
| switch (startType) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| if (endType == Types.SQL_INTERVAL_MONTH) { |
| return Types.SQL_INTERVAL_YEAR_TO_MONTH; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_DAY : |
| switch (endType) { |
| |
| case Types.SQL_INTERVAL_HOUR : |
| return Types.SQL_INTERVAL_DAY_TO_HOUR; |
| |
| case Types.SQL_INTERVAL_MINUTE : |
| return Types.SQL_INTERVAL_DAY_TO_MINUTE; |
| |
| case Types.SQL_INTERVAL_SECOND : |
| return Types.SQL_INTERVAL_DAY_TO_SECOND; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_HOUR : |
| switch (endType) { |
| |
| case Types.SQL_INTERVAL_MINUTE : |
| return Types.SQL_INTERVAL_HOUR_TO_MINUTE; |
| |
| case Types.SQL_INTERVAL_SECOND : |
| return Types.SQL_INTERVAL_HOUR_TO_SECOND; |
| } |
| break; |
| |
| case Types.SQL_INTERVAL_MINUTE : |
| if (endType == Types.SQL_INTERVAL_SECOND) { |
| return Types.SQL_INTERVAL_MINUTE_TO_SECOND; |
| } |
| break; |
| |
| default : |
| } |
| |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| |
| long getIntervalValueLimit() { |
| |
| long limit; |
| |
| switch (typeCode) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| limit = DTIType.precisionLimits[(int) precision] * 12; |
| break; |
| |
| case Types.SQL_INTERVAL_YEAR_TO_MONTH : |
| limit = DTIType.precisionLimits[(int) precision] * 12; |
| limit += 12; |
| break; |
| |
| case Types.SQL_INTERVAL_MONTH : |
| limit = DTIType.precisionLimits[(int) precision]; |
| break; |
| |
| case Types.SQL_INTERVAL_DAY : |
| limit = DTIType.precisionLimits[(int) precision] * 24 * 60 |
| * 60; |
| break; |
| |
| case Types.SQL_INTERVAL_DAY_TO_HOUR : |
| limit = DTIType.precisionLimits[(int) precision] * 24 * 60 |
| * 60; |
| break; |
| |
| case Types.SQL_INTERVAL_DAY_TO_MINUTE : |
| limit = DTIType.precisionLimits[(int) precision] * 24 * 60 |
| * 60; |
| break; |
| |
| case Types.SQL_INTERVAL_DAY_TO_SECOND : |
| limit = DTIType.precisionLimits[(int) precision] * 24 * 60 |
| * 60; |
| break; |
| |
| case Types.SQL_INTERVAL_HOUR : |
| limit = DTIType.precisionLimits[(int) precision] * 60 * 60; |
| break; |
| |
| case Types.SQL_INTERVAL_HOUR_TO_MINUTE : |
| limit = DTIType.precisionLimits[(int) precision] * 60 * 60; |
| break; |
| |
| case Types.SQL_INTERVAL_HOUR_TO_SECOND : |
| limit = DTIType.precisionLimits[(int) precision] * 60 * 60; |
| break; |
| |
| case Types.SQL_INTERVAL_MINUTE : |
| limit = DTIType.precisionLimits[(int) precision] * 60; |
| break; |
| |
| case Types.SQL_INTERVAL_MINUTE_TO_SECOND : |
| limit = DTIType.precisionLimits[(int) precision] * 60; |
| break; |
| |
| case Types.SQL_INTERVAL_SECOND : |
| limit = DTIType.precisionLimits[(int) precision]; |
| break; |
| |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| |
| return limit; |
| } |
| |
| public int getPart(Session session, Object interval, int part) { |
| |
| long units; |
| |
| switch (part) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| return (int) (((IntervalMonthData) interval).units / 12); |
| |
| case Types.SQL_INTERVAL_MONTH : |
| units = ((IntervalMonthData) interval).units; |
| |
| return part == startIntervalType ? (int) units |
| : (int) (units % 12); |
| |
| case Types.SQL_INTERVAL_DAY : |
| return (int) (((IntervalSecondData) interval).units |
| / (24 * 60 * 60)); |
| |
| case Types.SQL_INTERVAL_HOUR : { |
| units = ((IntervalSecondData) interval).units / (60 * 60); |
| |
| return part == startIntervalType ? (int) units |
| : (int) (units % 24); |
| } |
| case Types.SQL_INTERVAL_MINUTE : { |
| units = ((IntervalSecondData) interval).units / 60; |
| |
| return part == startIntervalType ? (int) units |
| : (int) (units % 60); |
| } |
| case Types.SQL_INTERVAL_SECOND : { |
| units = ((IntervalSecondData) interval).units; |
| |
| return part == startIntervalType ? (int) units |
| : (int) (units % 60); |
| } |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| } |
| |
| public long getSeconds(Object interval) { |
| return ((IntervalSecondData) interval).units; |
| } |
| |
| public BigDecimal getSecondPart(Object interval) { |
| |
| long seconds = ((IntervalSecondData) interval).units; |
| |
| if (typeCode != Types.SQL_INTERVAL_SECOND) { |
| seconds %= 60; |
| } |
| |
| int nanos = ((IntervalSecondData) interval).nanos; |
| |
| return getSecondPart(seconds, nanos); |
| } |
| |
| public long convertToLong(Object interval) { |
| |
| switch (endIntervalType) { |
| |
| case Types.SQL_INTERVAL_YEAR : |
| case Types.SQL_INTERVAL_MONTH : |
| long months = ((IntervalMonthData) interval).units; |
| |
| return (months / DTIType.yearToSecondFactors[endPartIndex]); |
| |
| case Types.SQL_INTERVAL_DAY : |
| case Types.SQL_INTERVAL_HOUR : |
| case Types.SQL_INTERVAL_MINUTE : |
| case Types.SQL_INTERVAL_SECOND : { |
| long seconds = ((IntervalSecondData) interval).units; |
| |
| return (seconds / DTIType.yearToSecondFactors[endPartIndex]); |
| } |
| default : |
| throw Error.runtimeError(ErrorCode.U_S0500, "IntervalType"); |
| } |
| } |
| } |