/* Copyright (c) 2001-2018, 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.
HsqlDateTime;
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;
import org.hsqldb.lib.
ArrayUtil;
/**
* Type subclass for various types of INTERVAL.<p>
*
* @author Fred Toussi (fredt@users dot sourceforge.net)
* @version 2.4.1
* @since 1.9.0
*/
public final class
IntervalType extends
DTIType {
public final boolean
defaultPrecision;
public final boolean
isYearMonth;
public static final
NumberType factorType =
NumberType.
getNumberType(
Types.
SQL_DECIMAL, 40,
maxFractionPrecision);
private
IntervalType(int
typeGroup, int
type, long
precision, int
scale,
int
startIntervalType, int
endIntervalType,
boolean
defaultPrecision) {
super(
typeGroup,
type,
precision,
scale,
startIntervalType,
endIntervalType);
if (
endIntervalType !=
Types.
SQL_INTERVAL_SECOND &&
scale != 0) {
throw
Error.
error(
ErrorCode.
X_22006);
}
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
Tokens.
T_YEAR;
case
Types.
SQL_INTERVAL_YEAR_TO_MONTH :
return "YEAR TO MONTH";
case
Types.
SQL_INTERVAL_MONTH :
return
Tokens.
T_MONTH;
case
Types.
SQL_INTERVAL_DAY :
return
Tokens.
T_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
Tokens.
T_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
Tokens.
T_MINUTE;
case
Types.
SQL_INTERVAL_MINUTE_TO_SECOND :
return "MINUTE TO SECOND";
case
Types.
SQL_INTERVAL_SECOND :
return
Tokens.
T_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
isIntervalYearMonthType() {
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
isIntervalDaySecondType() {
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 (
other == null) {
return this;
}
if (
other ==
SQL_ALL_TYPES) {
return this;
}
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.
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(
Session session,
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;
} else if (
other.
isIntervalType()) {
IntervalType otherType = (
IntervalType)
other;
if (
isYearMonth ==
otherType.
isYearMonth) {
return
isYearMonth ?
Type.
SQL_BIGINT
:
factorType;
}
}
break;
case
OpTypes.
ADD :
if (
other.
isDateTimeType()) {
return
other.
getCombinedType(
session, 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 : {
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.
compareToLongLimits((
BigDecimal)
a) != 0) {
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) {
if (
a instanceof
BigDecimal) {
nanos = (int)
NumberType.
scaledDecimal(
a,
DTIType.
maxFractionPrecision);
} else if (
a instanceof
Double) {
double
d = (
Double)
a;
d -= (double) ((long)
d);
nanos = (int) (
d * 1000000000d);
}
}
return new
IntervalSecondData(
value,
nanos, this);
}
default :
throw
Error.
error(
ErrorCode.
X_42561);
}
}
case
Types.
SQL_INTERVAL_YEAR : {
long
months = (((
IntervalMonthData)
a).
units / 12) * 12L;
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(
session,
a,
Type.
SQL_VARCHAR);
} else if (
a instanceof
Integer) {
return
convertToType(
session,
a,
Type.
SQL_INTEGER);
} else if (
a instanceof
Long) {
return
convertToType(
session,
a,
Type.
SQL_BIGINT);
} else if (
a instanceof
BigDecimal) {
return
convertToType(
session,
a,
Type.
SQL_DECIMAL);
} else {
throw
Error.
error(
ErrorCode.
X_42561);
}
}
public
Object convertJavaToSQL(
SessionInterface session,
Object a) {
Object o =
convertJavaTimeObject(
session,
a);
if (
o != null) {
return
o;
}
return
convertToDefaultType(
session,
a);
}
//#ifdef JAVA8
/*
Object convertJavaTimeObject(SessionInterface session, Object a) {
if (this.isIntervalYearMonthType()) {
if (a instanceof java.time.Period) {
java.time.Period v = (java.time.Period) a;
int months = v.getYears() * 12 + v.getMonths();
return new IntervalMonthData(months, this);
}
} else {
if (a instanceof java.time.Duration) {
java.time.Duration v = (java.time.Duration) a;
long second = v.getSeconds();
int nano = v.getNano();
return new IntervalSecondData(second, nano, this, true);
}
}
return null;
}
*/
//#else
TimestampData convertJavaTimeObject(
SessionInterface session,
Object a) {
return null;
}
//#endif JAVA8
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]);
if (
startPartIndex !=
endPartIndex) {
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
isIntervalYearMonthType()
==
otherType.
isIntervalYearMonthType();
}
public int
canMoveFrom(
Type otherType) {
if (
otherType == this) {
return 0;
}
if (
typeCode ==
otherType.
typeCode) {
return
scale >=
otherType.
scale ? 0
: -1;
}
if (!
otherType.
isIntervalType()) {
return -1;
}
if (
isYearMonth == ((
IntervalType)
otherType).
isYearMonth) {
if (
scale <
otherType.
scale) {
return -1;
}
if (
endPartIndex >= ((
IntervalType)
otherType).
endPartIndex) {
if (
precision >=
otherType.
precision) {
if (
startPartIndex
<= ((
IntervalType)
otherType).
startPartIndex) {
return 0;
}
}
return 1;
}
}
return -1;
}
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 boolean
isNegative(
Object a) {
if (
a instanceof
IntervalMonthData) {
return ((
IntervalMonthData)
a).
units < 0;
} else {
long
units = ((
IntervalSecondData)
a).
units;
if (
units < 0) {
return true;
} else if (
units == 0) {
return ((
IntervalSecondData)
a).
nanos < 0;
} else {
return false;
}
}
}
public
Object add(
Session session,
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(
Session session,
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(
session,
(
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
aSeconds = ((
TimeData)
a).
getSeconds();
long
bSeconds = ((
TimeData)
b).
getSeconds();
long
nanos = ((
TimeData)
a).
getNanos()
- ((
TimeData)
b).
getNanos();
return
subtract(
aSeconds,
bSeconds,
nanos);
} else if (
a instanceof
TimestampData
&&
b instanceof
TimestampData) {
long
aSeconds = ((
TimestampData)
a).
getSeconds();
long
bSeconds = ((
TimestampData)
b).
getSeconds();
long
nanos = ((
TimestampData)
a).
getNanos()
- ((
TimestampData)
b).
getNanos();
return
subtract(
aSeconds,
bSeconds,
nanos);
}
// fall through
default :
throw
Error.
runtimeError(
ErrorCode.
U_S0500, "IntervalType");
}
}
private
IntervalSecondData subtract(long
aSeconds, long
bSeconds,
long
nanos) {
if (
endIntervalType !=
Types.
SQL_INTERVAL_SECOND) {
aSeconds =
HsqlDateTime.
getTruncatedPart(
aSeconds * 1000,
endIntervalType)
/ 1000;
bSeconds =
HsqlDateTime.
getTruncatedPart(
bSeconds * 1000,
endIntervalType)
/ 1000;
nanos = 0;
}
return new
IntervalSecondData(
aSeconds -
bSeconds,
nanos, this, true);
}
public
Object multiply(
Object a,
Object b) {
return
multiplyOrDivide(
a,
b, false);
}
public
Object divide(
Session session,
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;
}
boolean
isNumberDiv =
b instanceof
Number;
if (
divide) {
if (
isNumberDiv) {
if (
NumberType.
isZero(
b)) {
throw
Error.
error(
ErrorCode.
X_22012);
}
} else {
if (
isYearMonth) {
if (((
IntervalMonthData)
b).
units == 0) {
throw
Error.
error(
ErrorCode.
X_22012);
}
} else {
if (((
IntervalSecondData)
b).
units == 0) {
throw
Error.
error(
ErrorCode.
X_22012);
}
}
}
}
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(null,
units,
factor)
: (
BigDecimal)
factorType.
multiply(
units,
factor);
if (
NumberType.
compareToLongLimits(
result) != 0) {
throw
Error.
error(
ErrorCode.
X_22015);
}
if (
isNumberDiv) {
if (
isYearMonth) {
return new
IntervalMonthData(
result.
longValue(), this);
}
int
nanos = (int)
NumberType.
scaledDecimal(
result,
DTIType.
maxFractionPrecision);
return new
IntervalSecondData(
result.
longValue(),
nanos, this,
true);
} else {
if (
isYearMonth) {
return
Long.
valueOf(
result.
longValue());
} else {
return
result;
}
}
}
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
||
fractionPrecision >
DTIType.
maxFractionPrecision) {
throw
Error.
error(
ErrorCode.
X_42592);
}
if (
startIndex ==
DTIType.
INTERVAL_SECOND_INDEX) {
if (
precision >
DTIType.
maxIntervalSecondPrecision) {
throw
Error.
error(
ErrorCode.
X_42592);
}
} else if (
precision >
DTIType.
maxIntervalPrecision) {
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;
} else if (
precision ==
DTIType.
maxIntervalPrecision) {
return
SQL_INTERVAL_YEAR_MAX_PRECISION;
}
break;
case
Types.
SQL_INTERVAL_YEAR_TO_MONTH :
if (
precision ==
DTIType.
defaultIntervalPrecision) {
return
SQL_INTERVAL_YEAR_TO_MONTH;
} else if (
precision ==
DTIType.
maxIntervalPrecision) {
return
SQL_INTERVAL_YEAR_TO_MONTH_MAX_PRECISION;
}
break;
case
Types.
SQL_INTERVAL_MONTH :
if (
precision ==
DTIType.
defaultIntervalPrecision) {
return
SQL_INTERVAL_MONTH;
} else if (
precision ==
DTIType.
maxIntervalPrecision) {
return
SQL_INTERVAL_MONTH_MAX_PRECISION;
}
break;
case
Types.
SQL_INTERVAL_DAY :
if (
precision ==
DTIType.
defaultIntervalPrecision) {
return
SQL_INTERVAL_DAY;
} else if (
precision ==
DTIType.
maxIntervalPrecision) {
return
SQL_INTERVAL_DAY_MAX_PRECISION;
}
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;
} else if (
precision ==
DTIType.
maxIntervalPrecision) {
return
SQL_INTERVAL_HOUR_MAX_PRECISION;
}
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;
} else if (
precision ==
DTIType.
maxIntervalPrecision) {
return
SQL_INTERVAL_MINUTE_MAX_PRECISION;
}
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");
}
public static int
getIntervalType(
String part) {
int
index =
ArrayUtil.
find(
Tokens.
SQL_INTERVAL_FIELD_NAMES,
part);
if (
index < 0) {
throw
Error.
error(
ErrorCode.
X_42562);
}
return
intervalParts[
index];
}
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 ((
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);
}
case
MILLISECOND :
return ((
IntervalSecondData)
interval).
nanos / 1000000;
case
MICROSECOND :
return ((
IntervalSecondData)
interval).
nanos / 1000;
case
NANOSECOND :
return ((
IntervalSecondData)
interval).
nanos;
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
convertToLongEndUnits(
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");
}
}
public double
convertToDoubleStartUnits(
Object interval) {
switch (
startIntervalType) {
case
Types.
SQL_INTERVAL_YEAR :
case
Types.
SQL_INTERVAL_MONTH :
double
months = ((
IntervalMonthData)
interval).
units;
return (
months /
DTIType.
yearToSecondFactors[
startPartIndex]);
case
Types.
SQL_INTERVAL_DAY :
case
Types.
SQL_INTERVAL_HOUR :
case
Types.
SQL_INTERVAL_MINUTE :
case
Types.
SQL_INTERVAL_SECOND : {
double
seconds = ((
IntervalSecondData)
interval).
units;
return (
seconds /
DTIType.
yearToSecondFactors[
startPartIndex]);
}
default :
throw
Error.
runtimeError(
ErrorCode.
U_S0500, "IntervalType");
}
}
public double
convertToDouble(
Object interval) {
if (this.
isIntervalYearMonthType()) {
double
months = ((
IntervalMonthData)
interval).
units;
return
months;
} else {
double
seconds = ((
IntervalSecondData)
interval).
units;
seconds += ((double) ((
IntervalSecondData)
interval).
nanos)
/
nanoScaleFactors[0];
return
seconds;
}
}
public
Object convertFromDouble(double
value) {
long
units = (long)
value;
if (this.
isIntervalYearMonthType()) {
return new
IntervalMonthData(
units);
} else {
int
nanos = (int) ((
value -
units) *
nanoScaleFactors[0]);
return new
IntervalSecondData(
units,
nanos);
}
}
public
CharacterType getCharacterType() {
CharacterType type =
CharacterType.
getCharacterType(
Types.
SQL_VARCHAR,
displaySize());
type.
nameString =
getNameString();
return
type;
}
public
Object getValue(long
units, int
nanos) {
if (this.
isIntervalYearMonthType()) {
return new
IntervalMonthData(
units, this);
} else {
return new
IntervalSecondData(
units,
nanos, this, true);
}
}
}