Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
0661149e
Unverified
提交
0661149e
authored
8月 23, 2018
作者:
Evgenij Ryazanov
提交者:
GitHub
8月 23, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1392 from katzyn/misc
Some refactoring and assorted minor optimizations
上级
ac05e08c
9df1d17c
隐藏空白字符变更
内嵌
并排
正在显示
23 个修改的文件
包含
1070 行增加
和
970 行删除
+1070
-970
Interval.java
h2/src/main/org/h2/api/Interval.java
+9
-9
Parser.java
h2/src/main/org/h2/command/Parser.java
+2
-2
Query.java
h2/src/main/org/h2/command/dml/Query.java
+38
-10
Select.java
h2/src/main/org/h2/command/dml/Select.java
+0
-29
SelectUnion.java
h2/src/main/org/h2/command/dml/SelectUnion.java
+0
-31
AggregateDataMedian.java
h2/src/main/org/h2/expression/AggregateDataMedian.java
+4
-3
Function.java
h2/src/main/org/h2/expression/Function.java
+16
-12
IntervalOperation.java
h2/src/main/org/h2/expression/IntervalOperation.java
+17
-14
Parameter.java
h2/src/main/org/h2/expression/Parameter.java
+2
-2
ValueDataType.java
h2/src/main/org/h2/mvstore/db/ValueDataType.java
+4
-4
Sequence.java
h2/src/main/org/h2/schema/Sequence.java
+4
-8
Data.java
h2/src/main/org/h2/store/Data.java
+4
-4
DateTimeFunctions.java
h2/src/main/org/h2/util/DateTimeFunctions.java
+10
-10
DateTimeUtils.java
h2/src/main/org/h2/util/DateTimeUtils.java
+2
-791
IntervalUtils.java
h2/src/main/org/h2/util/IntervalUtils.java
+851
-0
LocalDateTimeUtils.java
h2/src/main/org/h2/util/LocalDateTimeUtils.java
+1
-1
Value.java
h2/src/main/org/h2/value/Value.java
+9
-8
ValueDouble.java
h2/src/main/org/h2/value/ValueDouble.java
+18
-10
ValueFloat.java
h2/src/main/org/h2/value/ValueFloat.java
+21
-13
ValueInterval.java
h2/src/main/org/h2/value/ValueInterval.java
+7
-6
TestScript.java
h2/src/test/org/h2/test/scripts/TestScript.java
+1
-1
createSequence.sql
h2/src/test/org/h2/test/scripts/ddl/createSequence.sql
+47
-0
TestDateTimeUtils.java
h2/src/test/org/h2/test/unit/TestDateTimeUtils.java
+3
-2
没有找到文件。
h2/src/main/org/h2/api/Interval.java
浏览文件 @
0661149e
...
...
@@ -9,7 +9,7 @@ import static org.h2.util.DateTimeUtils.NANOS_PER_MINUTE;
import
static
org
.
h2
.
util
.
DateTimeUtils
.
NANOS_PER_SECOND
;
import
org.h2.message.DbException
;
import
org.h2.util.
DateTime
Utils
;
import
org.h2.util.
Interval
Utils
;
/**
* INTERVAL representation for result sets.
...
...
@@ -471,7 +471,7 @@ public final class Interval {
public
Interval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
this
.
qualifier
=
qualifier
;
try
{
this
.
negative
=
DateTime
Utils
.
validateInterval
(
qualifier
,
negative
,
leading
,
remaining
);
this
.
negative
=
Interval
Utils
.
validateInterval
(
qualifier
,
negative
,
leading
,
remaining
);
}
catch
(
DbException
e
)
{
throw
new
IllegalArgumentException
();
}
...
...
@@ -523,7 +523,7 @@ public final class Interval {
* @return years, or 0
*/
public
long
getYears
()
{
return
DateTime
Utils
.
yearsFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
return
Interval
Utils
.
yearsFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
}
/**
...
...
@@ -532,7 +532,7 @@ public final class Interval {
* @return months, or 0
*/
public
long
getMonths
()
{
return
DateTime
Utils
.
monthsFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
return
Interval
Utils
.
monthsFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
}
/**
...
...
@@ -541,7 +541,7 @@ public final class Interval {
* @return days, or 0
*/
public
long
getDays
()
{
return
DateTime
Utils
.
daysFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
return
Interval
Utils
.
daysFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
}
/**
...
...
@@ -550,7 +550,7 @@ public final class Interval {
* @return hours, or 0
*/
public
long
getHours
()
{
return
DateTime
Utils
.
hoursFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
return
Interval
Utils
.
hoursFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
}
/**
...
...
@@ -559,7 +559,7 @@ public final class Interval {
* @return minutes, or 0
*/
public
long
getMinutes
()
{
return
DateTime
Utils
.
minutesFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
return
Interval
Utils
.
minutesFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
}
/**
...
...
@@ -599,7 +599,7 @@ public final class Interval {
* @return nanoseconds (including seconds), or 0
*/
public
long
getSecondsAndNanos
()
{
return
DateTime
Utils
.
nanosFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
return
Interval
Utils
.
nanosFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
}
@Override
...
...
@@ -628,7 +628,7 @@ public final class Interval {
@Override
public
String
toString
()
{
return
DateTime
Utils
.
intervalToString
(
qualifier
,
negative
,
leading
,
remaining
);
return
Interval
Utils
.
intervalToString
(
qualifier
,
negative
,
leading
,
remaining
);
}
}
h2/src/main/org/h2/command/Parser.java
浏览文件 @
0661149e
...
...
@@ -189,7 +189,7 @@ import org.h2.table.TableFilter;
import
org.h2.table.TableFilter.TableFilterVisitor
;
import
org.h2.table.TableView
;
import
org.h2.util.DateTimeFunctions
;
import
org.h2.util.
DateTime
Utils
;
import
org.h2.util.
Interval
Utils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.ParserUtil
;
import
org.h2.util.StatementBuilder
;
...
...
@@ -3691,7 +3691,7 @@ public class Parser {
qualifier
=
IntervalQualifier
.
SECOND
;
}
try
{
return
ValueExpression
.
get
(
DateTime
Utils
.
parseInterval
(
qualifier
,
negative
,
s
));
return
ValueExpression
.
get
(
Interval
Utils
.
parseInterval
(
qualifier
,
negative
,
s
));
}
catch
(
Exception
e
)
{
throw
DbException
.
get
(
ErrorCode
.
INVALID_DATETIME_CONSTANT_2
,
e
,
"INTERVAL"
,
s
);
}
...
...
h2/src/main/org/h2/command/dml/Query.java
浏览文件 @
0661149e
...
...
@@ -10,6 +10,7 @@ import java.util.HashSet;
import
java.util.List
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.CommandInterface
;
import
org.h2.command.Prepared
;
import
org.h2.engine.Database
;
import
org.h2.engine.Mode.ModeEnum
;
...
...
@@ -39,40 +40,56 @@ import org.h2.value.ValueNull;
*/
public
abstract
class
Query
extends
Prepared
{
/**
* The column list, including invisible expressions such as order by expressions.
*/
ArrayList
<
Expression
>
expressions
;
/**
* Array of expressions.
*
* @see #expressions
*/
Expression
[]
expressionArray
;
ArrayList
<
SelectOrderBy
>
orderList
;
SortOrder
sort
;
/**
* The limit expression as specified in the LIMIT or TOP clause.
*/
protected
Expression
limitExpr
;
Expression
limitExpr
;
/**
* Whether limit expression specifies percentage of rows.
*/
protected
boolean
fetchPercent
;
boolean
fetchPercent
;
/**
* Whether tied rows should be included in result too.
*/
protected
boolean
withTies
;
boolean
withTies
;
/**
* The offset expression as specified in the LIMIT .. OFFSET clause.
*/
protected
Expression
offsetExpr
;
Expression
offsetExpr
;
/**
* The sample size expression as specified in the SAMPLE_SIZE clause.
*/
protected
Expression
sampleSizeExpr
;
Expression
sampleSizeExpr
;
/**
* Whether the result must only contain distinct rows.
*/
protected
boolean
distinct
;
boolean
distinct
;
/**
* Whether the result needs to support random access.
*/
protected
boolean
randomAccessResult
;
boolean
randomAccessResult
;
private
boolean
noCache
;
private
int
lastLimit
;
...
...
@@ -144,7 +161,9 @@ public abstract class Query extends Prepared {
*
* @return the list of expressions
*/
public
abstract
ArrayList
<
Expression
>
getExpressions
();
public
ArrayList
<
Expression
>
getExpressions
()
{
return
expressions
;
}
/**
* Calculate the cost to execute this query.
...
...
@@ -178,14 +197,18 @@ public abstract class Query extends Prepared {
*
* @param order the order by list
*/
public
abstract
void
setOrder
(
ArrayList
<
SelectOrderBy
>
order
);
public
void
setOrder
(
ArrayList
<
SelectOrderBy
>
order
)
{
orderList
=
order
;
}
/**
* Whether the query has an order.
*
* @return true if it has
*/
public
abstract
boolean
hasOrder
();
public
boolean
hasOrder
()
{
return
orderList
!=
null
||
sort
!=
null
;
}
/**
* Set the 'for update' flag.
...
...
@@ -600,6 +623,11 @@ public abstract class Query extends Prepared {
return
new
SortOrder
(
session
.
getDatabase
(),
index
,
sortType
,
orderList
);
}
@Override
public
int
getType
()
{
return
CommandInterface
.
SELECT
;
}
public
void
setOffset
(
Expression
offset
)
{
this
.
offsetExpr
=
offset
;
}
...
...
h2/src/main/org/h2/command/dml/Select.java
浏览文件 @
0661149e
...
...
@@ -13,7 +13,6 @@ import java.util.HashSet;
import
java.util.Map
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.Trigger
;
import
org.h2.command.CommandInterface
;
import
org.h2.command.Parser
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Database
;
...
...
@@ -76,12 +75,6 @@ public class Select extends Query {
private
final
ArrayList
<
TableFilter
>
filters
=
Utils
.
newSmallArrayList
();
private
final
ArrayList
<
TableFilter
>
topFilters
=
Utils
.
newSmallArrayList
();
/**
* The column list, including synthetic columns (columns not shown in the
* result).
*/
ArrayList
<
Expression
>
expressions
;
private
Expression
[]
expressionArray
;
private
Expression
having
;
private
Expression
condition
;
...
...
@@ -98,7 +91,6 @@ public class Select extends Query {
private
int
[]
distinctIndexes
;
private
int
distinctColumnCount
;
private
ArrayList
<
SelectOrderBy
>
orderList
;
private
ArrayList
<
Expression
>
group
;
/**
...
...
@@ -136,7 +128,6 @@ public class Select extends Query {
private
boolean
isQuickAggregateQuery
,
isDistinctQuery
;
private
boolean
isPrepared
,
checkInit
;
private
boolean
sortUsingIndex
;
private
SortOrder
sort
;
/**
* The id of the current group.
...
...
@@ -245,16 +236,6 @@ public class Select extends Query {
return
currentGroupRowId
;
}
@Override
public
void
setOrder
(
ArrayList
<
SelectOrderBy
>
order
)
{
orderList
=
order
;
}
@Override
public
boolean
hasOrder
()
{
return
orderList
!=
null
||
sort
!=
null
;
}
@Override
public
void
setDistinct
()
{
if
(
distinctExpressions
!=
null
)
{
...
...
@@ -1452,11 +1433,6 @@ public class Select extends Query {
return
topTableFilter
;
}
@Override
public
ArrayList
<
Expression
>
getExpressions
()
{
return
expressions
;
}
@Override
public
void
setForUpdate
(
boolean
b
)
{
this
.
isForUpdate
=
b
;
...
...
@@ -1617,11 +1593,6 @@ public class Select extends Query {
return
!
isForUpdate
;
}
@Override
public
int
getType
()
{
return
CommandInterface
.
SELECT
;
}
@Override
public
boolean
allowGlobalConditions
()
{
return
offsetExpr
==
null
&&
(
limitExpr
==
null
||
sort
==
null
);
...
...
h2/src/main/org/h2/command/dml/SelectUnion.java
浏览文件 @
0661149e
...
...
@@ -9,7 +9,6 @@ import java.util.ArrayList;
import
java.util.HashSet
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.CommandInterface
;
import
org.h2.engine.Mode
;
import
org.h2.engine.Session
;
import
org.h2.engine.SysProperties
;
...
...
@@ -23,7 +22,6 @@ import org.h2.result.LazyResult;
import
org.h2.result.LocalResult
;
import
org.h2.result.ResultInterface
;
import
org.h2.result.ResultTarget
;
import
org.h2.result.SortOrder
;
import
org.h2.table.Column
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.Table
;
...
...
@@ -73,10 +71,6 @@ public class SelectUnion extends Query {
*/
final
Query
right
;
private
ArrayList
<
Expression
>
expressions
;
private
Expression
[]
expressionArray
;
private
ArrayList
<
SelectOrderBy
>
orderList
;
private
SortOrder
sort
;
private
boolean
isPrepared
,
checkInit
;
private
boolean
isForUpdate
;
...
...
@@ -110,21 +104,6 @@ public class SelectUnion extends Query {
return
right
;
}
@Override
public
void
setSQL
(
String
sql
)
{
this
.
sqlStatement
=
sql
;
}
@Override
public
void
setOrder
(
ArrayList
<
SelectOrderBy
>
order
)
{
orderList
=
order
;
}
@Override
public
boolean
hasOrder
()
{
return
orderList
!=
null
||
sort
!=
null
;
}
@Override
public
void
setDistinctIfPossible
()
{
setDistinct
();
...
...
@@ -376,11 +355,6 @@ public class SelectUnion extends Query {
return
set
;
}
@Override
public
ArrayList
<
Expression
>
getExpressions
()
{
return
expressions
;
}
@Override
public
void
setForUpdate
(
boolean
forUpdate
)
{
left
.
setForUpdate
(
forUpdate
);
...
...
@@ -484,11 +458,6 @@ public class SelectUnion extends Query {
right
.
fireBeforeSelectTriggers
();
}
@Override
public
int
getType
()
{
return
CommandInterface
.
SELECT
;
}
@Override
public
boolean
allowGlobalConditions
()
{
return
left
.
allowGlobalConditions
()
&&
right
.
allowGlobalConditions
();
...
...
h2/src/main/org/h2/expression/AggregateDataMedian.java
浏览文件 @
0661149e
...
...
@@ -23,6 +23,7 @@ import org.h2.table.IndexColumn;
import
org.h2.table.Table
;
import
org.h2.table.TableFilter
;
import
org.h2.util.DateTimeUtils
;
import
org.h2.util.IntervalUtils
;
import
org.h2.value.CompareMode
;
import
org.h2.value.Value
;
import
org.h2.value.ValueDate
;
...
...
@@ -261,9 +262,9 @@ class AggregateDataMedian extends AggregateDataCollecting {
case
Value
.
INTERVAL_HOUR_TO_MINUTE
:
case
Value
.
INTERVAL_HOUR_TO_SECOND
:
case
Value
.
INTERVAL_MINUTE_TO_SECOND
:
return
DateTime
Utils
.
intervalFromAbsolute
(
IntervalQualifier
.
valueOf
(
dataType
-
Value
.
INTERVAL_YEAR
),
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
v0
)
.
add
(
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
v1
)).
shiftRight
(
1
));
return
Interval
Utils
.
intervalFromAbsolute
(
IntervalQualifier
.
valueOf
(
dataType
-
Value
.
INTERVAL_YEAR
),
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
v0
)
.
add
(
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
v1
)).
shiftRight
(
1
));
default
:
// Just return first
return
v0
.
convertTo
(
dataType
);
...
...
h2/src/main/org/h2/expression/Function.java
浏览文件 @
0661149e
...
...
@@ -2324,20 +2324,24 @@ public class Function extends Expression implements FunctionCall {
d
=
displaySize
;
break
;
case
TRUNCATE:
t
=
p0
.
getType
();
s
=
p0
.
getScale
();
p
=
p0
.
getPrecision
();
d
=
p0
.
getDisplaySize
();
if
(
t
==
Value
.
NULL
)
{
t
=
Value
.
INT
;
p
=
ValueInt
.
PRECISION
;
d
=
ValueInt
.
DISPLAY_SIZE
;
switch
(
p0
.
getType
())
{
case
Value
.
STRING
:
case
Value
.
DATE
:
case
Value
.
TIMESTAMP
:
t
=
Value
.
TIMESTAMP
;
p
=
d
=
ValueTimestamp
.
DEFAULT_PRECISION
;
s
=
0
;
break
;
case
Value
.
TIMESTAMP_TZ
:
t
=
Value
.
TIMESTAMP
;
p
=
d
=
ValueTimestampTimeZone
.
DEFAULT_PRECISION
;
s
=
0
;
}
else
if
(
t
==
Value
.
TIMESTAMP
)
{
t
=
Value
.
DATE
;
p
=
ValueDate
.
PRECISION
;
break
;
default
:
t
=
Value
.
DOUBLE
;
s
=
0
;
d
=
ValueDate
.
PRECISION
;
p
=
ValueDouble
.
PRECISION
;
d
=
ValueDouble
.
DISPLAY_SIZE
;
}
break
;
case
ABS:
...
...
h2/src/main/org/h2/expression/IntervalOperation.java
浏览文件 @
0661149e
...
...
@@ -5,6 +5,8 @@
*/
package
org
.
h2
.
expression
;
import
static
org
.
h2
.
util
.
IntervalUtils
.
NANOS_PER_DAY_BI
;
import
java.math.BigDecimal
;
import
java.math.BigInteger
;
...
...
@@ -16,6 +18,7 @@ import org.h2.table.ColumnResolver;
import
org.h2.table.TableFilter
;
import
org.h2.util.DateTimeFunctions
;
import
org.h2.util.DateTimeUtils
;
import
org.h2.util.IntervalUtils
;
import
org.h2.value.DataType
;
import
org.h2.value.Value
;
import
org.h2.value.ValueDate
;
...
...
@@ -131,9 +134,9 @@ public class IntervalOperation extends Expression {
switch
(
opType
)
{
case
INTERVAL_PLUS_INTERVAL:
case
INTERVAL_MINUS_INTERVAL:
{
BigInteger
a1
=
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
l
);
BigInteger
a2
=
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
r
);
return
DateTime
Utils
.
intervalFromAbsolute
(
BigInteger
a1
=
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
l
);
BigInteger
a2
=
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
r
);
return
Interval
Utils
.
intervalFromAbsolute
(
IntervalQualifier
.
valueOf
(
Value
.
getHigherOrder
(
lType
,
rType
)
-
Value
.
INTERVAL_YEAR
),
opType
==
IntervalOpType
.
INTERVAL_PLUS_INTERVAL
?
a1
.
add
(
a2
)
:
a1
.
subtract
(
a2
));
}
...
...
@@ -142,9 +145,9 @@ public class IntervalOperation extends Expression {
return
getDateTimeWithInterval
(
l
,
r
,
lType
,
rType
);
case
INTERVAL_MULTIPLY_NUMERIC:
case
INTERVAL_DIVIDE_NUMERIC:
{
BigDecimal
a1
=
new
BigDecimal
(
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
l
));
BigDecimal
a1
=
new
BigDecimal
(
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
l
));
BigDecimal
a2
=
r
.
getBigDecimal
();
return
DateTime
Utils
.
intervalFromAbsolute
(
IntervalQualifier
.
valueOf
(
lType
-
Value
.
INTERVAL_YEAR
),
return
Interval
Utils
.
intervalFromAbsolute
(
IntervalQualifier
.
valueOf
(
lType
-
Value
.
INTERVAL_YEAR
),
(
opType
==
IntervalOpType
.
INTERVAL_MULTIPLY_NUMERIC
?
a1
.
multiply
(
a2
)
:
a1
.
divide
(
a2
))
.
toBigInteger
());
}
...
...
@@ -168,9 +171,9 @@ public class IntervalOperation extends Expression {
}
else
{
long
[]
a
=
DateTimeUtils
.
dateAndTimeFromValue
(
l
);
long
[]
b
=
DateTimeUtils
.
dateAndTimeFromValue
(
r
);
BigInteger
bi1
=
BigInteger
.
valueOf
(
a
[
0
]).
multiply
(
BigInteger
.
valueOf
(
DateTimeUtils
.
NANOS_PER_DAY
)
)
BigInteger
bi1
=
BigInteger
.
valueOf
(
a
[
0
]).
multiply
(
NANOS_PER_DAY_BI
)
.
add
(
BigInteger
.
valueOf
(
a
[
1
]));
BigInteger
bi2
=
BigInteger
.
valueOf
(
b
[
0
]).
multiply
(
BigInteger
.
valueOf
(
DateTimeUtils
.
NANOS_PER_DAY
)
)
BigInteger
bi2
=
BigInteger
.
valueOf
(
b
[
0
]).
multiply
(
NANOS_PER_DAY_BI
)
.
add
(
BigInteger
.
valueOf
(
b
[
1
]));
BigInteger
diff
=
bi1
.
subtract
(
bi2
);
if
(
lType
==
Value
.
TIMESTAMP_TZ
||
rType
==
Value
.
TIMESTAMP_TZ
)
{
...
...
@@ -179,7 +182,7 @@ public class IntervalOperation extends Expression {
diff
=
diff
.
add
(
BigInteger
.
valueOf
((((
ValueTimestampTimeZone
)
r
).
getTimeZoneOffsetMins
()
-
((
ValueTimestampTimeZone
)
l
).
getTimeZoneOffsetMins
())
*
60_000_000_000L
));
}
return
DateTime
Utils
.
intervalFromAbsolute
(
IntervalQualifier
.
DAY_TO_SECOND
,
diff
);
return
Interval
Utils
.
intervalFromAbsolute
(
IntervalQualifier
.
DAY_TO_SECOND
,
diff
);
}
}
throw
DbException
.
throwInternalError
(
"type="
+
opType
);
...
...
@@ -192,9 +195,9 @@ public class IntervalOperation extends Expression {
throw
DbException
.
throwInternalError
(
"type="
+
rType
);
}
BigInteger
a1
=
BigInteger
.
valueOf
(((
ValueTime
)
l
).
getNanos
());
BigInteger
a2
=
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
r
);
BigInteger
a2
=
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
r
);
BigInteger
n
=
opType
==
IntervalOpType
.
DATETIME_PLUS_INTERVAL
?
a1
.
add
(
a2
)
:
a1
.
subtract
(
a2
);
if
(
n
.
signum
()
<
0
||
n
.
compareTo
(
BigInteger
.
valueOf
(
DateTimeUtils
.
NANOS_PER_DAY
)
)
>=
0
)
{
if
(
n
.
signum
()
<
0
||
n
.
compareTo
(
NANOS_PER_DAY_BI
)
>=
0
)
{
throw
DbException
.
get
(
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_1
,
n
.
toString
());
}
return
ValueTime
.
fromNanos
(
n
.
longValue
());
...
...
@@ -203,24 +206,24 @@ public class IntervalOperation extends Expression {
case
Value
.
TIMESTAMP
:
case
Value
.
TIMESTAMP_TZ
:
if
(
DataType
.
isYearMonthIntervalType
(
rType
))
{
long
m
=
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
r
).
longValue
();
long
m
=
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
r
).
longValue
();
if
(
opType
==
IntervalOpType
.
DATETIME_MINUS_INTERVAL
)
{
m
=
-
m
;
}
return
DateTimeFunctions
.
dateadd
(
"MONTH"
,
m
,
l
);
}
else
{
BigInteger
a2
=
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
r
);
BigInteger
a2
=
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
r
);
if
(
lType
==
Value
.
DATE
)
{
BigInteger
a1
=
BigInteger
.
valueOf
(
DateTimeUtils
.
absoluteDayFromDateValue
(((
ValueDate
)
l
).
getDateValue
()));
a2
=
a2
.
divide
(
BigInteger
.
valueOf
(
DateTimeUtils
.
NANOS_PER_DAY
)
);
a2
=
a2
.
divide
(
NANOS_PER_DAY_BI
);
BigInteger
n
=
opType
==
IntervalOpType
.
DATETIME_PLUS_INTERVAL
?
a1
.
add
(
a2
)
:
a1
.
subtract
(
a2
);
return
ValueDate
.
fromDateValue
(
DateTimeUtils
.
dateValueFromAbsoluteDay
(
n
.
longValue
()));
}
else
{
long
[]
a
=
DateTimeUtils
.
dateAndTimeFromValue
(
l
);
long
absoluteDay
=
DateTimeUtils
.
absoluteDayFromDateValue
(
a
[
0
]);
long
timeNanos
=
a
[
1
];
BigInteger
[]
dr
=
a2
.
divideAndRemainder
(
BigInteger
.
valueOf
(
DateTimeUtils
.
NANOS_PER_DAY
)
);
BigInteger
[]
dr
=
a2
.
divideAndRemainder
(
NANOS_PER_DAY_BI
);
if
(
opType
==
IntervalOpType
.
DATETIME_PLUS_INTERVAL
)
{
absoluteDay
+=
dr
[
0
].
longValue
();
timeNanos
+=
dr
[
1
].
longValue
();
...
...
h2/src/main/org/h2/expression/Parameter.java
浏览文件 @
0661149e
...
...
@@ -85,8 +85,8 @@ public class Parameter extends Expression implements ParameterInterface {
@Override
public
Expression
optimize
(
Session
session
)
{
if
(
session
.
getDatabase
().
getMode
().
treatEmptyStringsAsNull
)
{
if
(
value
instanceof
ValueString
)
{
value
=
Value
String
.
get
(
value
.
getString
(),
true
)
;
if
(
value
instanceof
ValueString
&&
value
.
getString
().
isEmpty
()
)
{
value
=
Value
Null
.
INSTANCE
;
}
}
return
this
;
...
...
h2/src/main/org/h2/mvstore/db/ValueDataType.java
浏览文件 @
0661149e
...
...
@@ -589,13 +589,13 @@ public class ValueDataType implements DataType {
ordinal
<
5
?
0
:
readVarLong
(
buff
));
}
case
FLOAT_0_1:
return
ValueFloat
.
get
(
0
)
;
return
ValueFloat
.
ZERO
;
case
FLOAT_0_1
+
1
:
return
ValueFloat
.
get
(
1
)
;
return
ValueFloat
.
ONE
;
case
DOUBLE_0_1:
return
ValueDouble
.
get
(
0
)
;
return
ValueDouble
.
ZERO
;
case
DOUBLE_0_1
+
1
:
return
ValueDouble
.
get
(
1
)
;
return
ValueDouble
.
ONE
;
case
Value
.
DOUBLE
:
return
ValueDouble
.
get
(
Double
.
longBitsToDouble
(
Long
.
reverse
(
readVarLong
(
buff
))));
...
...
h2/src/main/org/h2/schema/Sequence.java
浏览文件 @
0661149e
...
...
@@ -5,7 +5,6 @@
*/
package
org
.
h2
.
schema
;
import
java.math.BigInteger
;
import
org.h2.api.ErrorCode
;
import
org.h2.engine.DbObject
;
import
org.h2.engine.Session
;
...
...
@@ -139,17 +138,14 @@ public class Sequence extends SchemaObjectBase {
* @param maxValue the prospective max value
* @param increment the prospective increment
*/
private
static
boolean
isValid
(
long
value
,
long
minValue
,
long
maxValue
,
long
increment
)
{
private
static
boolean
isValid
(
long
value
,
long
minValue
,
long
maxValue
,
long
increment
)
{
return
minValue
<=
value
&&
maxValue
>=
value
&&
maxValue
>
minValue
&&
increment
!=
0
&&
// Math.abs(increment) < maxValue - minValue
// use BigInteger to avoid overflows when maxValue and minValue
// are really big
BigInteger
.
valueOf
(
increment
).
abs
().
compareTo
(
BigInteger
.
valueOf
(
maxValue
).
subtract
(
BigInteger
.
valueOf
(
minValue
)))
<
0
;
// Math.abs(increment) <= maxValue - minValue
// Can use Long.compareUnsigned() on Java 8
Math
.
abs
(
increment
)
+
Long
.
MIN_VALUE
<=
maxValue
-
minValue
+
Long
.
MIN_VALUE
;
}
private
static
long
getDefaultMinValue
(
Long
startValue
,
long
increment
)
{
...
...
h2/src/main/org/h2/store/Data.java
浏览文件 @
0661149e
...
...
@@ -809,13 +809,13 @@ public class Data {
case
Value
.
STRING_FIXED
:
return
ValueStringFixed
.
get
(
readString
());
case
FLOAT_0_1:
return
ValueFloat
.
get
(
0
)
;
return
ValueFloat
.
ZERO
;
case
FLOAT_0_1
+
1
:
return
ValueFloat
.
get
(
1
)
;
return
ValueFloat
.
ONE
;
case
DOUBLE_0_1:
return
ValueDouble
.
get
(
0
)
;
return
ValueDouble
.
ZERO
;
case
DOUBLE_0_1
+
1
:
return
ValueDouble
.
get
(
1
)
;
return
ValueDouble
.
ONE
;
case
Value
.
DOUBLE
:
return
ValueDouble
.
get
(
Double
.
longBitsToDouble
(
Long
.
reverse
(
readVarLong
())));
...
...
h2/src/main/org/h2/util/DateTimeFunctions.java
浏览文件 @
0661149e
...
...
@@ -355,7 +355,7 @@ public final class DateTimeFunctions {
bd
=
bd
.
negate
();
}
}
else
{
bd
=
new
BigDecimal
(
DateTime
Utils
.
intervalToAbsolute
(
interval
))
bd
=
new
BigDecimal
(
Interval
Utils
.
intervalToAbsolute
(
interval
))
.
divide
(
BigDecimal
.
valueOf
(
NANOS_PER_SECOND
));
}
return
ValueDecimal
.
get
(
bd
);
...
...
@@ -634,33 +634,33 @@ public final class DateTimeFunctions {
long
v
;
switch
(
field
)
{
case
YEAR:
v
=
DateTime
Utils
.
yearsFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
v
=
Interval
Utils
.
yearsFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
break
;
case
MONTH:
v
=
DateTime
Utils
.
monthsFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
v
=
Interval
Utils
.
monthsFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
break
;
case
DAY_OF_MONTH:
case
DAY_OF_WEEK:
case
DAY_OF_YEAR:
v
=
DateTime
Utils
.
daysFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
v
=
Interval
Utils
.
daysFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
break
;
case
HOUR:
v
=
DateTime
Utils
.
hoursFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
v
=
Interval
Utils
.
hoursFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
break
;
case
MINUTE:
v
=
DateTime
Utils
.
minutesFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
v
=
Interval
Utils
.
minutesFromInterval
(
qualifier
,
negative
,
leading
,
remaining
);
break
;
case
SECOND:
v
=
DateTime
Utils
.
nanosFromInterval
(
qualifier
,
negative
,
leading
,
remaining
)
/
NANOS_PER_SECOND
;
v
=
Interval
Utils
.
nanosFromInterval
(
qualifier
,
negative
,
leading
,
remaining
)
/
NANOS_PER_SECOND
;
break
;
case
MILLISECOND:
v
=
DateTime
Utils
.
nanosFromInterval
(
qualifier
,
negative
,
leading
,
remaining
)
/
1_000_000
%
1_000
;
v
=
Interval
Utils
.
nanosFromInterval
(
qualifier
,
negative
,
leading
,
remaining
)
/
1_000_000
%
1_000
;
break
;
case
MICROSECOND:
v
=
DateTime
Utils
.
nanosFromInterval
(
qualifier
,
negative
,
leading
,
remaining
)
/
1_000
%
1_000_000
;
v
=
Interval
Utils
.
nanosFromInterval
(
qualifier
,
negative
,
leading
,
remaining
)
/
1_000
%
1_000_000
;
break
;
case
NANOSECOND:
v
=
DateTime
Utils
.
nanosFromInterval
(
qualifier
,
negative
,
leading
,
remaining
)
%
NANOS_PER_SECOND
;
v
=
Interval
Utils
.
nanosFromInterval
(
qualifier
,
negative
,
leading
,
remaining
)
%
NANOS_PER_SECOND
;
break
;
default
:
throw
DbException
.
getUnsupportedException
(
"getDatePart("
+
date
+
", "
+
field
+
')'
);
...
...
h2/src/main/org/h2/util/DateTimeUtils.java
浏览文件 @
0661149e
...
...
@@ -6,20 +6,15 @@
*/
package
org
.
h2
.
util
;
import
java.math.BigInteger
;
import
java.sql.Date
;
import
java.sql.Time
;
import
java.sql.Timestamp
;
import
java.util.Calendar
;
import
java.util.GregorianCalendar
;
import
java.util.TimeZone
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.IntervalQualifier
;
import
org.h2.engine.Mode
;
import
org.h2.message.DbException
;
import
org.h2.value.Value
;
import
org.h2.value.ValueDate
;
import
org.h2.value.ValueInterval
;
import
org.h2.value.ValueNull
;
import
org.h2.value.ValueTime
;
import
org.h2.value.ValueTimestamp
;
...
...
@@ -461,7 +456,7 @@ public class DateTimeUtils {
return
((((
hour
*
60L
)
+
minute
)
*
60
)
+
second
)
*
NANOS_PER_SECOND
+
nanos
;
}
private
static
int
parseNanos
(
String
s
,
int
start
,
int
end
)
{
static
int
parseNanos
(
String
s
,
int
start
,
int
end
)
{
if
(
start
>=
end
)
{
throw
new
IllegalArgumentException
(
s
);
}
...
...
@@ -1480,7 +1475,7 @@ public class DateTimeUtils {
}
}
private
static
void
stripTrailingZeroes
(
StringBuilder
buff
)
{
static
void
stripTrailingZeroes
(
StringBuilder
buff
)
{
int
i
=
buff
.
length
()
-
1
;
if
(
buff
.
charAt
(
i
)
==
'0'
)
{
while
(
buff
.
charAt
(--
i
)
==
'0'
)
{
...
...
@@ -1555,414 +1550,6 @@ public class DateTimeUtils {
return
b
.
toString
();
}
/**
* Parses the specified string as {@code INTERVAL} value.
*
* @param qualifier the default qualifier to use if string does not have one
* @param s the string with type information to parse
* @return the interval value.
* Type of value can be different from the specified qualifier.
*/
public
static
ValueInterval
parseFormattedInterval
(
IntervalQualifier
qualifier
,
String
s
)
{
int
i
=
0
;
i
=
skipWS
(
s
,
i
);
if
(!
s
.
regionMatches
(
true
,
i
,
"INTERVAL"
,
0
,
8
))
{
return
parseInterval
(
qualifier
,
false
,
s
);
}
i
=
skipWS
(
s
,
i
+
8
);
boolean
negative
=
false
;
char
ch
=
s
.
charAt
(
i
);
if
(
ch
==
'-'
)
{
negative
=
true
;
i
=
skipWS
(
s
,
i
+
1
);
ch
=
s
.
charAt
(
i
);
}
else
if
(
ch
==
'+'
)
{
i
=
skipWS
(
s
,
i
+
1
);
ch
=
s
.
charAt
(
i
);
}
if
(
ch
!=
'\''
)
{
throw
new
IllegalArgumentException
(
s
);
}
int
start
=
++
i
;
int
l
=
s
.
length
();
for
(;;)
{
if
(
i
==
l
)
{
throw
new
IllegalArgumentException
(
s
);
}
if
(
s
.
charAt
(
i
)
==
'\''
)
{
break
;
}
i
++;
}
String
v
=
s
.
substring
(
start
,
i
);
i
=
skipWS
(
s
,
i
+
1
);
if
(
s
.
regionMatches
(
true
,
i
,
"YEAR"
,
0
,
4
))
{
i
+=
4
;
int
j
=
skipWSEnd
(
s
,
i
);
if
(
j
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
YEAR
,
negative
,
v
);
}
if
(
j
>
i
&&
s
.
regionMatches
(
true
,
j
,
"TO"
,
0
,
2
))
{
j
+=
2
;
i
=
skipWS
(
s
,
j
);
if
(
i
>
j
&&
s
.
regionMatches
(
true
,
i
,
"MONTH"
,
0
,
5
))
{
if
(
skipWSEnd
(
s
,
i
+
5
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
YEAR_TO_MONTH
,
negative
,
v
);
}
}
}
}
else
if
(
s
.
regionMatches
(
true
,
i
,
"MONTH"
,
0
,
5
))
{
if
(
skipWSEnd
(
s
,
i
+
5
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
MONTH
,
negative
,
v
);
}
}
if
(
s
.
regionMatches
(
true
,
i
,
"DAY"
,
0
,
3
))
{
i
+=
3
;
int
j
=
skipWSEnd
(
s
,
i
);
if
(
j
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
DAY
,
negative
,
v
);
}
if
(
j
>
i
&&
s
.
regionMatches
(
true
,
j
,
"TO"
,
0
,
2
))
{
j
+=
2
;
i
=
skipWS
(
s
,
j
);
if
(
i
>
j
)
{
if
(
s
.
regionMatches
(
true
,
i
,
"HOUR"
,
0
,
4
))
{
if
(
skipWSEnd
(
s
,
i
+
4
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
DAY_TO_HOUR
,
negative
,
v
);
}
}
else
if
(
s
.
regionMatches
(
true
,
i
,
"MINUTE"
,
0
,
6
))
{
if
(
skipWSEnd
(
s
,
i
+
6
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
DAY_TO_MINUTE
,
negative
,
v
);
}
}
else
if
(
s
.
regionMatches
(
true
,
i
,
"SECOND"
,
0
,
6
))
{
if
(
skipWSEnd
(
s
,
i
+
6
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
DAY_TO_SECOND
,
negative
,
v
);
}
}
}
}
}
if
(
s
.
regionMatches
(
true
,
i
,
"HOUR"
,
0
,
4
))
{
i
+=
4
;
int
j
=
skipWSEnd
(
s
,
i
);
if
(
j
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
HOUR
,
negative
,
v
);
}
if
(
j
>
i
&&
s
.
regionMatches
(
true
,
j
,
"TO"
,
0
,
2
))
{
j
+=
2
;
i
=
skipWS
(
s
,
j
);
if
(
i
>
j
)
{
if
(
s
.
regionMatches
(
true
,
i
,
"MINUTE"
,
0
,
6
))
{
if
(
skipWSEnd
(
s
,
i
+
6
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
HOUR_TO_MINUTE
,
negative
,
v
);
}
}
else
if
(
s
.
regionMatches
(
true
,
i
,
"SECOND"
,
0
,
6
))
{
if
(
skipWSEnd
(
s
,
i
+
6
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
HOUR_TO_SECOND
,
negative
,
v
);
}
}
}
}
}
if
(
s
.
regionMatches
(
true
,
i
,
"MINUTE"
,
0
,
6
))
{
i
+=
6
;
int
j
=
skipWSEnd
(
s
,
i
);
if
(
j
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
MINUTE
,
negative
,
v
);
}
if
(
j
>
i
&&
s
.
regionMatches
(
true
,
j
,
"TO"
,
0
,
2
))
{
j
+=
2
;
i
=
skipWS
(
s
,
j
);
if
(
i
>
j
&&
s
.
regionMatches
(
true
,
i
,
"SECOND"
,
0
,
6
))
{
if
(
skipWSEnd
(
s
,
i
+
6
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
MINUTE_TO_SECOND
,
negative
,
v
);
}
}
}
}
if
(
s
.
regionMatches
(
true
,
i
,
"SECOND"
,
0
,
6
))
{
if
(
skipWSEnd
(
s
,
i
+
6
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
SECOND
,
negative
,
v
);
}
}
throw
new
IllegalArgumentException
(
s
);
}
private
static
int
skipWS
(
String
s
,
int
i
)
{
for
(
int
l
=
s
.
length
();
;
i
++)
{
if
(
i
==
l
)
{
throw
new
IllegalArgumentException
(
s
);
}
if
(!
Character
.
isWhitespace
(
s
.
charAt
(
i
)))
{
return
i
;
}
}
}
private
static
int
skipWSEnd
(
String
s
,
int
i
)
{
for
(
int
l
=
s
.
length
();
;
i
++)
{
if
(
i
==
l
)
{
return
i
;
}
if
(!
Character
.
isWhitespace
(
s
.
charAt
(
i
)))
{
return
i
;
}
}
}
/**
* Parses the specified string as {@code INTERVAL} value.
*
* @param qualifier the qualifier of interval
* @param negative whether the interval is negative
* @param s the string to parse
* @return the interval value
*/
public
static
ValueInterval
parseInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
String
s
)
{
long
leading
,
remaining
;
switch
(
qualifier
)
{
case
YEAR:
case
MONTH:
case
DAY:
case
HOUR:
case
MINUTE:
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
break
;
case
SECOND:
{
int
dot
=
s
.
indexOf
(
'.'
);
if
(
dot
<
0
)
{
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
}
else
{
leading
=
parseIntervalLeading
(
s
,
0
,
dot
,
negative
);
remaining
=
parseNanos
(
s
,
dot
+
1
,
s
.
length
());
}
break
;
}
case
YEAR_TO_MONTH:
return
parseInterval2
(
qualifier
,
s
,
'-'
,
11
,
negative
);
case
DAY_TO_HOUR:
return
parseInterval2
(
qualifier
,
s
,
' '
,
23
,
negative
);
case
DAY_TO_MINUTE:
{
int
space
=
s
.
indexOf
(
' '
);
if
(
space
<
0
)
{
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
}
else
{
leading
=
parseIntervalLeading
(
s
,
0
,
space
,
negative
);
int
colon
=
s
.
indexOf
(
':'
,
space
+
1
);
if
(
colon
<
0
)
{
remaining
=
parseIntervalRemaining
(
s
,
space
+
1
,
s
.
length
(),
23
)
*
60
;
}
else
{
remaining
=
parseIntervalRemaining
(
s
,
space
+
1
,
colon
,
23
)
*
60
+
parseIntervalRemaining
(
s
,
colon
+
1
,
s
.
length
(),
59
);
}
}
break
;
}
case
DAY_TO_SECOND:
{
int
space
=
s
.
indexOf
(
' '
);
if
(
space
<
0
)
{
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
}
else
{
leading
=
parseIntervalLeading
(
s
,
0
,
space
,
negative
);
int
colon
=
s
.
indexOf
(
':'
,
space
+
1
);
if
(
colon
<
0
)
{
remaining
=
parseIntervalRemaining
(
s
,
space
+
1
,
s
.
length
(),
23
)
*
NANOS_PER_HOUR
;
}
else
{
int
colon2
=
s
.
indexOf
(
':'
,
colon
+
1
);
if
(
colon2
<
0
)
{
remaining
=
parseIntervalRemaining
(
s
,
space
+
1
,
colon
,
23
)
*
NANOS_PER_HOUR
+
parseIntervalRemaining
(
s
,
colon
+
1
,
s
.
length
(),
59
)
*
NANOS_PER_MINUTE
;
}
else
{
remaining
=
parseIntervalRemaining
(
s
,
space
+
1
,
colon
,
23
)
*
NANOS_PER_HOUR
+
parseIntervalRemaining
(
s
,
colon
+
1
,
colon2
,
59
)
*
NANOS_PER_MINUTE
+
parseIntervalRemainingSeconds
(
s
,
colon2
+
1
);
}
}
}
break
;
}
case
HOUR_TO_MINUTE:
return
parseInterval2
(
qualifier
,
s
,
':'
,
59
,
negative
);
case
HOUR_TO_SECOND:
{
int
colon
=
s
.
indexOf
(
':'
);
if
(
colon
<
0
)
{
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
}
else
{
leading
=
parseIntervalLeading
(
s
,
0
,
colon
,
negative
);
int
colon2
=
s
.
indexOf
(
':'
,
colon
+
1
);
if
(
colon2
<
0
)
{
remaining
=
parseIntervalRemaining
(
s
,
colon
+
1
,
s
.
length
(),
59
)
*
NANOS_PER_MINUTE
;
}
else
{
remaining
=
parseIntervalRemaining
(
s
,
colon
+
1
,
colon2
,
59
)
*
NANOS_PER_MINUTE
+
parseIntervalRemainingSeconds
(
s
,
colon2
+
1
);
}
}
break
;
}
case
MINUTE_TO_SECOND:
{
int
dash
=
s
.
indexOf
(
':'
);
if
(
dash
<
0
)
{
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
}
else
{
leading
=
parseIntervalLeading
(
s
,
0
,
dash
,
negative
);
remaining
=
parseIntervalRemainingSeconds
(
s
,
dash
+
1
);
}
break
;
}
default
:
throw
new
IllegalArgumentException
();
}
negative
=
leading
<
0
;
if
(
negative
)
{
if
(
leading
!=
Long
.
MIN_VALUE
)
{
leading
=
-
leading
;
}
else
{
leading
=
0
;
}
}
return
ValueInterval
.
from
(
qualifier
,
negative
,
leading
,
remaining
);
}
static
ValueInterval
parseInterval2
(
IntervalQualifier
qualifier
,
String
s
,
char
ch
,
int
max
,
boolean
negative
)
{
long
leading
;
long
remaining
;
int
dash
=
s
.
indexOf
(
ch
,
1
);
if
(
dash
<
0
)
{
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
}
else
{
leading
=
parseIntervalLeading
(
s
,
0
,
dash
,
negative
);
remaining
=
parseIntervalRemaining
(
s
,
dash
+
1
,
s
.
length
(),
max
);
}
negative
=
leading
<
0
;
if
(
negative
)
{
if
(
leading
!=
Long
.
MIN_VALUE
)
{
leading
=
-
leading
;
}
else
{
leading
=
0
;
}
}
return
ValueInterval
.
from
(
qualifier
,
negative
,
leading
,
remaining
);
}
private
static
long
parseIntervalLeading
(
String
s
,
int
start
,
int
end
,
boolean
negative
)
{
long
leading
=
Long
.
parseLong
(
s
.
substring
(
start
,
end
));
if
(
leading
==
0
)
{
return
negative
^
s
.
charAt
(
start
)
==
'-'
?
Long
.
MIN_VALUE
:
0
;
}
return
negative
?
-
leading
:
leading
;
}
private
static
long
parseIntervalRemaining
(
String
s
,
int
start
,
int
end
,
int
max
)
{
int
v
=
StringUtils
.
parseUInt31
(
s
,
start
,
end
);
if
(
v
>
max
)
{
throw
new
IllegalArgumentException
(
s
);
}
return
v
;
}
private
static
long
parseIntervalRemainingSeconds
(
String
s
,
int
start
)
{
int
seconds
,
nanos
;
int
dot
=
s
.
indexOf
(
'.'
,
start
+
1
);
if
(
dot
<
0
)
{
seconds
=
StringUtils
.
parseUInt31
(
s
,
start
,
s
.
length
());
nanos
=
0
;
}
else
{
seconds
=
StringUtils
.
parseUInt31
(
s
,
start
,
dot
);
nanos
=
parseNanos
(
s
,
dot
+
1
,
s
.
length
());
}
if
(
seconds
>
59
)
{
throw
new
IllegalArgumentException
(
s
);
}
return
seconds
*
NANOS_PER_SECOND
+
nanos
;
}
/**
* Formats interval as a string.
*
* @param qualifier qualifier of the interval
* @param negative whether interval is negative
* @param leading the value of leading field
* @param remaining the value of all remaining fields
* @return string representation of the specified interval
*/
public
static
String
intervalToString
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
StringBuilder
buff
=
new
StringBuilder
().
append
(
"INTERVAL "
);
buff
.
append
(
'\''
);
if
(
negative
)
{
buff
.
append
(
'-'
);
}
switch
(
qualifier
)
{
case
YEAR:
case
MONTH:
case
DAY:
case
HOUR:
case
MINUTE:
buff
.
append
(
leading
);
break
;
case
SECOND:
buff
.
append
(
leading
);
appendNanos
(
buff
,
remaining
);
break
;
case
YEAR_TO_MONTH:
buff
.
append
(
leading
).
append
(
'-'
).
append
(
remaining
);
break
;
case
DAY_TO_HOUR:
buff
.
append
(
leading
).
append
(
' '
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
);
break
;
case
DAY_TO_MINUTE:
buff
.
append
(
leading
).
append
(
' '
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
/
60
);
buff
.
append
(
':'
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
%
60
);
break
;
case
DAY_TO_SECOND:
{
long
nanos
=
remaining
%
NANOS_PER_MINUTE
;
remaining
/=
NANOS_PER_MINUTE
;
buff
.
append
(
leading
).
append
(
' '
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
/
60
);
buff
.
append
(
':'
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
%
60
);
buff
.
append
(
':'
);
appendSecondsWithNanos
(
buff
,
nanos
);
break
;
}
case
HOUR_TO_MINUTE:
buff
.
append
(
leading
).
append
(
':'
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
);
break
;
case
HOUR_TO_SECOND:
buff
.
append
(
leading
).
append
(
':'
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
/
NANOS_PER_MINUTE
);
buff
.
append
(
':'
);
appendSecondsWithNanos
(
buff
,
remaining
%
NANOS_PER_MINUTE
);
break
;
case
MINUTE_TO_SECOND:
buff
.
append
(
leading
).
append
(
':'
);
appendSecondsWithNanos
(
buff
,
remaining
);
break
;
}
buff
.
append
(
"' "
).
append
(
qualifier
);
return
buff
.
toString
();
}
private
static
void
appendSecondsWithNanos
(
StringBuilder
buff
,
long
nanos
)
{
StringUtils
.
appendZeroPadded
(
buff
,
2
,
nanos
/
NANOS_PER_SECOND
);
appendNanos
(
buff
,
nanos
%
NANOS_PER_SECOND
);
}
private
static
void
appendNanos
(
StringBuilder
buff
,
long
nanos
)
{
if
(
nanos
>
0
)
{
buff
.
append
(
'.'
);
StringUtils
.
appendZeroPadded
(
buff
,
9
,
nanos
);
stripTrailingZeroes
(
buff
);
}
}
/**
* Converts scale of nanoseconds.
*
...
...
@@ -1982,380 +1569,4 @@ public class DateTimeUtils {
return
nanosOfDay
-
mod
;
}
/**
* Converts interval value to an absolute value.
*
* @param interval the interval value
* @return absolute value in months for year-month intervals,
* in nanoseconds for day-time intervals
*/
public
static
BigInteger
intervalToAbsolute
(
ValueInterval
interval
)
{
BigInteger
r
;
switch
(
interval
.
getQualifier
())
{
case
YEAR:
r
=
BigInteger
.
valueOf
(
interval
.
getLeading
()).
multiply
(
BigInteger
.
valueOf
(
12
));
break
;
case
MONTH:
r
=
BigInteger
.
valueOf
(
interval
.
getLeading
());
break
;
case
DAY:
r
=
BigInteger
.
valueOf
(
interval
.
getLeading
()).
multiply
(
BigInteger
.
valueOf
(
NANOS_PER_DAY
));
break
;
case
HOUR:
r
=
BigInteger
.
valueOf
(
interval
.
getLeading
()).
multiply
(
BigInteger
.
valueOf
(
NANOS_PER_HOUR
));
break
;
case
MINUTE:
r
=
BigInteger
.
valueOf
(
interval
.
getLeading
()).
multiply
(
BigInteger
.
valueOf
(
NANOS_PER_MINUTE
));
break
;
case
SECOND:
r
=
intervalToAbsolute
(
interval
,
NANOS_PER_SECOND
);
break
;
case
YEAR_TO_MONTH:
r
=
intervalToAbsolute
(
interval
,
12
);
break
;
case
DAY_TO_HOUR:
r
=
intervalToAbsolute
(
interval
,
24
,
NANOS_PER_HOUR
);
break
;
case
DAY_TO_MINUTE:
r
=
intervalToAbsolute
(
interval
,
24
*
60
,
NANOS_PER_MINUTE
);
break
;
case
DAY_TO_SECOND:
r
=
intervalToAbsolute
(
interval
,
NANOS_PER_DAY
);
break
;
case
HOUR_TO_MINUTE:
r
=
intervalToAbsolute
(
interval
,
60
,
NANOS_PER_MINUTE
);
break
;
case
HOUR_TO_SECOND:
r
=
intervalToAbsolute
(
interval
,
NANOS_PER_HOUR
);
break
;
case
MINUTE_TO_SECOND:
r
=
intervalToAbsolute
(
interval
,
NANOS_PER_MINUTE
);
break
;
default
:
throw
new
IllegalArgumentException
();
}
return
interval
.
isNegative
()
?
r
.
negate
()
:
r
;
}
private
static
BigInteger
intervalToAbsolute
(
ValueInterval
interval
,
long
multiplier
,
long
totalMultiplier
)
{
return
intervalToAbsolute
(
interval
,
multiplier
).
multiply
(
BigInteger
.
valueOf
(
totalMultiplier
));
}
private
static
BigInteger
intervalToAbsolute
(
ValueInterval
interval
,
long
multiplier
)
{
return
BigInteger
.
valueOf
(
interval
.
getLeading
()).
multiply
(
BigInteger
.
valueOf
(
multiplier
))
.
add
(
BigInteger
.
valueOf
(
interval
.
getRemaining
()));
}
/**
* Converts absolute value to an interval value.
*
* @param qualifier the qualifier of interval
* @param absolute absolute value in months for year-month intervals,
* in nanoseconds for day-time intervals
* @return the interval value
*/
public
static
ValueInterval
intervalFromAbsolute
(
IntervalQualifier
qualifier
,
BigInteger
absolute
)
{
switch
(
qualifier
)
{
case
YEAR:
return
ValueInterval
.
from
(
qualifier
,
absolute
.
signum
()
<
0
,
leadingExact
(
absolute
.
divide
(
BigInteger
.
valueOf
(
12
))),
0
);
case
MONTH:
return
ValueInterval
.
from
(
qualifier
,
absolute
.
signum
()
<
0
,
leadingExact
(
absolute
),
0
);
case
DAY:
return
ValueInterval
.
from
(
qualifier
,
absolute
.
signum
()
<
0
,
leadingExact
(
absolute
.
divide
(
BigInteger
.
valueOf
(
NANOS_PER_DAY
))),
0
);
case
HOUR:
return
ValueInterval
.
from
(
qualifier
,
absolute
.
signum
()
<
0
,
leadingExact
(
absolute
.
divide
(
BigInteger
.
valueOf
(
NANOS_PER_HOUR
))),
0
);
case
MINUTE:
return
ValueInterval
.
from
(
qualifier
,
absolute
.
signum
()
<
0
,
leadingExact
(
absolute
.
divide
(
BigInteger
.
valueOf
(
NANOS_PER_MINUTE
))),
0
);
case
SECOND:
return
intervalFromAbsolute
(
qualifier
,
absolute
,
NANOS_PER_SECOND
);
case
YEAR_TO_MONTH:
return
intervalFromAbsolute
(
qualifier
,
absolute
,
12
);
case
DAY_TO_HOUR:
return
intervalFromAbsolute
(
qualifier
,
absolute
.
divide
(
BigInteger
.
valueOf
(
NANOS_PER_HOUR
)),
24
);
case
DAY_TO_MINUTE:
return
intervalFromAbsolute
(
qualifier
,
absolute
.
divide
(
BigInteger
.
valueOf
(
NANOS_PER_MINUTE
)),
24
*
60
);
case
DAY_TO_SECOND:
return
intervalFromAbsolute
(
qualifier
,
absolute
,
NANOS_PER_DAY
);
case
HOUR_TO_MINUTE:
return
intervalFromAbsolute
(
qualifier
,
absolute
.
divide
(
BigInteger
.
valueOf
(
NANOS_PER_MINUTE
)),
60
);
case
HOUR_TO_SECOND:
return
intervalFromAbsolute
(
qualifier
,
absolute
,
NANOS_PER_HOUR
);
case
MINUTE_TO_SECOND:
return
intervalFromAbsolute
(
qualifier
,
absolute
,
NANOS_PER_MINUTE
);
default
:
throw
new
IllegalArgumentException
();
}
}
private
static
ValueInterval
intervalFromAbsolute
(
IntervalQualifier
qualifier
,
BigInteger
absolute
,
long
divisor
)
{
BigInteger
[]
dr
=
absolute
.
divideAndRemainder
(
BigInteger
.
valueOf
(
divisor
));
return
ValueInterval
.
from
(
qualifier
,
absolute
.
signum
()
<
0
,
leadingExact
(
dr
[
0
]),
Math
.
abs
(
dr
[
1
].
longValue
()));
}
private
static
long
leadingExact
(
BigInteger
absolute
)
{
if
(
absolute
.
compareTo
(
BigInteger
.
valueOf
(
999_999_999_999_999_999L
))
>
0
||
absolute
.
compareTo
(
BigInteger
.
valueOf
(-
999_999_999_999_999_999L
))
<
0
)
{
throw
DbException
.
get
(
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_1
,
absolute
.
toString
());
}
return
Math
.
abs
(
absolute
.
longValue
());
}
/**
* Ensures that all fields in interval are valid.
*
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return fixed value of negative field
*/
public
static
boolean
validateInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
if
(
qualifier
==
null
)
{
throw
new
NullPointerException
();
}
if
(
leading
==
0L
&&
remaining
==
0L
)
{
return
false
;
}
// Upper bound for remaining value (exclusive)
long
bound
;
switch
(
qualifier
)
{
case
YEAR:
case
MONTH:
case
DAY:
case
HOUR:
case
MINUTE:
bound
=
1
;
break
;
case
SECOND:
bound
=
NANOS_PER_SECOND
;
break
;
case
YEAR_TO_MONTH:
bound
=
12
;
break
;
case
DAY_TO_HOUR:
bound
=
24
;
break
;
case
DAY_TO_MINUTE:
bound
=
24
*
60
;
break
;
case
DAY_TO_SECOND:
bound
=
NANOS_PER_DAY
;
break
;
case
HOUR_TO_MINUTE:
bound
=
60
;
break
;
case
HOUR_TO_SECOND:
bound
=
NANOS_PER_HOUR
;
break
;
case
MINUTE_TO_SECOND:
bound
=
NANOS_PER_MINUTE
;
break
;
default
:
throw
DbException
.
getInvalidValueException
(
"interval"
,
qualifier
);
}
if
(
leading
<
0L
||
leading
>=
1_000_000_000_000_000_000L
)
{
throw
DbException
.
getInvalidValueException
(
"interval"
,
Long
.
toString
(
leading
));
}
if
(
remaining
<
0L
||
remaining
>=
bound
)
{
throw
DbException
.
getInvalidValueException
(
"interval"
,
Long
.
toString
(
remaining
));
}
return
negative
;
}
/**
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return years, or 0
*/
public
static
long
yearsFromInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
if
(
qualifier
==
IntervalQualifier
.
YEAR
||
qualifier
==
IntervalQualifier
.
YEAR_TO_MONTH
)
{
long
v
=
leading
;
if
(
negative
)
{
v
=
-
v
;
}
return
v
;
}
else
{
return
0
;
}
}
/**
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return months, or 0
*/
public
static
long
monthsFromInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
long
v
;
if
(
qualifier
==
IntervalQualifier
.
MONTH
)
{
v
=
leading
;
}
else
if
(
qualifier
==
IntervalQualifier
.
YEAR_TO_MONTH
){
v
=
remaining
;
}
else
{
return
0
;
}
if
(
negative
)
{
v
=
-
v
;
}
return
v
;
}
/**
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return months, or 0
*/
public
static
long
daysFromInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
switch
(
qualifier
)
{
case
DAY:
case
DAY_TO_HOUR:
case
DAY_TO_MINUTE:
case
DAY_TO_SECOND:
long
v
=
leading
;
if
(
negative
)
{
v
=
-
v
;
}
return
v
;
default
:
return
0
;
}
}
/**
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return hours, or 0
*/
public
static
long
hoursFromInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
long
v
;
switch
(
qualifier
)
{
case
HOUR:
case
HOUR_TO_MINUTE:
case
HOUR_TO_SECOND:
v
=
leading
;
break
;
case
DAY_TO_HOUR:
v
=
remaining
;
break
;
case
DAY_TO_MINUTE:
v
=
remaining
/
60
;
break
;
case
DAY_TO_SECOND:
v
=
remaining
/
NANOS_PER_HOUR
;
break
;
default
:
return
0
;
}
if
(
negative
)
{
v
=
-
v
;
}
return
v
;
}
/**
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return minutes, or 0
*/
public
static
long
minutesFromInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
long
v
;
switch
(
qualifier
)
{
case
MINUTE:
case
MINUTE_TO_SECOND:
v
=
leading
;
break
;
case
DAY_TO_MINUTE:
v
=
remaining
%
60
;
break
;
case
DAY_TO_SECOND:
v
=
remaining
/
NANOS_PER_MINUTE
%
60
;
break
;
case
HOUR_TO_MINUTE:
v
=
remaining
;
break
;
case
HOUR_TO_SECOND:
v
=
remaining
/
NANOS_PER_MINUTE
;
break
;
default
:
return
0
;
}
if
(
negative
)
{
v
=
-
v
;
}
return
v
;
}
/**
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return nanoseconds, or 0
*/
public
static
long
nanosFromInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
long
v
;
switch
(
qualifier
)
{
case
SECOND:
v
=
leading
*
NANOS_PER_SECOND
+
remaining
;
break
;
case
DAY_TO_SECOND:
case
HOUR_TO_SECOND:
v
=
remaining
%
NANOS_PER_MINUTE
;
break
;
case
MINUTE_TO_SECOND:
v
=
remaining
;
break
;
default
:
return
0
;
}
if
(
negative
)
{
v
=
-
v
;
}
return
v
;
}
}
h2/src/main/org/h2/util/IntervalUtils.java
0 → 100644
浏览文件 @
0661149e
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
util
;
import
static
org
.
h2
.
util
.
DateTimeUtils
.
NANOS_PER_DAY
;
import
static
org
.
h2
.
util
.
DateTimeUtils
.
NANOS_PER_HOUR
;
import
static
org
.
h2
.
util
.
DateTimeUtils
.
NANOS_PER_MINUTE
;
import
static
org
.
h2
.
util
.
DateTimeUtils
.
NANOS_PER_SECOND
;
import
java.math.BigInteger
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.IntervalQualifier
;
import
org.h2.message.DbException
;
import
org.h2.value.ValueInterval
;
/**
* This utility class contains interval conversion functions.
*/
public
class
IntervalUtils
{
private
static
final
BigInteger
NANOS_PER_SECOND_BI
=
BigInteger
.
valueOf
(
NANOS_PER_SECOND
);
private
static
final
BigInteger
NANOS_PER_MINUTE_BI
=
BigInteger
.
valueOf
(
NANOS_PER_MINUTE
);
private
static
final
BigInteger
NANOS_PER_HOUR_BI
=
BigInteger
.
valueOf
(
NANOS_PER_HOUR
);
/**
* The number of nanoseconds per day as BigInteger.
*/
public
static
final
BigInteger
NANOS_PER_DAY_BI
=
BigInteger
.
valueOf
(
NANOS_PER_DAY
);
private
static
final
BigInteger
MONTHS_PER_YEAR_BI
=
BigInteger
.
valueOf
(
12
);
private
static
final
BigInteger
HOURS_PER_DAY_BI
=
BigInteger
.
valueOf
(
24
);
private
static
final
BigInteger
MINUTES_PER_DAY_BI
=
BigInteger
.
valueOf
(
24
*
60
);
private
static
final
BigInteger
MINUTES_PER_HOUR_BI
=
BigInteger
.
valueOf
(
60
);
private
static
final
BigInteger
LEADING_MIN
=
BigInteger
.
valueOf
(-
999_999_999_999_999_999L
);
private
static
final
BigInteger
LEADING_MAX
=
BigInteger
.
valueOf
(
999_999_999_999_999_999L
);
private
IntervalUtils
()
{
// utility class
}
/**
* Parses the specified string as {@code INTERVAL} value.
*
* @param qualifier
* the default qualifier to use if string does not have one
* @param s
* the string with type information to parse
* @return the interval value. Type of value can be different from the
* specified qualifier.
*/
public
static
ValueInterval
parseFormattedInterval
(
IntervalQualifier
qualifier
,
String
s
)
{
int
i
=
0
;
i
=
skipWS
(
s
,
i
);
if
(!
s
.
regionMatches
(
true
,
i
,
"INTERVAL"
,
0
,
8
))
{
return
parseInterval
(
qualifier
,
false
,
s
);
}
i
=
skipWS
(
s
,
i
+
8
);
boolean
negative
=
false
;
char
ch
=
s
.
charAt
(
i
);
if
(
ch
==
'-'
)
{
negative
=
true
;
i
=
skipWS
(
s
,
i
+
1
);
ch
=
s
.
charAt
(
i
);
}
else
if
(
ch
==
'+'
)
{
i
=
skipWS
(
s
,
i
+
1
);
ch
=
s
.
charAt
(
i
);
}
if
(
ch
!=
'\''
)
{
throw
new
IllegalArgumentException
(
s
);
}
int
start
=
++
i
;
int
l
=
s
.
length
();
for
(;;)
{
if
(
i
==
l
)
{
throw
new
IllegalArgumentException
(
s
);
}
if
(
s
.
charAt
(
i
)
==
'\''
)
{
break
;
}
i
++;
}
String
v
=
s
.
substring
(
start
,
i
);
i
=
skipWS
(
s
,
i
+
1
);
if
(
s
.
regionMatches
(
true
,
i
,
"YEAR"
,
0
,
4
))
{
i
+=
4
;
int
j
=
skipWSEnd
(
s
,
i
);
if
(
j
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
YEAR
,
negative
,
v
);
}
if
(
j
>
i
&&
s
.
regionMatches
(
true
,
j
,
"TO"
,
0
,
2
))
{
j
+=
2
;
i
=
skipWS
(
s
,
j
);
if
(
i
>
j
&&
s
.
regionMatches
(
true
,
i
,
"MONTH"
,
0
,
5
))
{
if
(
skipWSEnd
(
s
,
i
+
5
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
YEAR_TO_MONTH
,
negative
,
v
);
}
}
}
}
else
if
(
s
.
regionMatches
(
true
,
i
,
"MONTH"
,
0
,
5
))
{
if
(
skipWSEnd
(
s
,
i
+
5
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
MONTH
,
negative
,
v
);
}
}
if
(
s
.
regionMatches
(
true
,
i
,
"DAY"
,
0
,
3
))
{
i
+=
3
;
int
j
=
skipWSEnd
(
s
,
i
);
if
(
j
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
DAY
,
negative
,
v
);
}
if
(
j
>
i
&&
s
.
regionMatches
(
true
,
j
,
"TO"
,
0
,
2
))
{
j
+=
2
;
i
=
skipWS
(
s
,
j
);
if
(
i
>
j
)
{
if
(
s
.
regionMatches
(
true
,
i
,
"HOUR"
,
0
,
4
))
{
if
(
skipWSEnd
(
s
,
i
+
4
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
DAY_TO_HOUR
,
negative
,
v
);
}
}
else
if
(
s
.
regionMatches
(
true
,
i
,
"MINUTE"
,
0
,
6
))
{
if
(
skipWSEnd
(
s
,
i
+
6
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
DAY_TO_MINUTE
,
negative
,
v
);
}
}
else
if
(
s
.
regionMatches
(
true
,
i
,
"SECOND"
,
0
,
6
))
{
if
(
skipWSEnd
(
s
,
i
+
6
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
DAY_TO_SECOND
,
negative
,
v
);
}
}
}
}
}
if
(
s
.
regionMatches
(
true
,
i
,
"HOUR"
,
0
,
4
))
{
i
+=
4
;
int
j
=
skipWSEnd
(
s
,
i
);
if
(
j
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
HOUR
,
negative
,
v
);
}
if
(
j
>
i
&&
s
.
regionMatches
(
true
,
j
,
"TO"
,
0
,
2
))
{
j
+=
2
;
i
=
skipWS
(
s
,
j
);
if
(
i
>
j
)
{
if
(
s
.
regionMatches
(
true
,
i
,
"MINUTE"
,
0
,
6
))
{
if
(
skipWSEnd
(
s
,
i
+
6
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
HOUR_TO_MINUTE
,
negative
,
v
);
}
}
else
if
(
s
.
regionMatches
(
true
,
i
,
"SECOND"
,
0
,
6
))
{
if
(
skipWSEnd
(
s
,
i
+
6
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
HOUR_TO_SECOND
,
negative
,
v
);
}
}
}
}
}
if
(
s
.
regionMatches
(
true
,
i
,
"MINUTE"
,
0
,
6
))
{
i
+=
6
;
int
j
=
skipWSEnd
(
s
,
i
);
if
(
j
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
MINUTE
,
negative
,
v
);
}
if
(
j
>
i
&&
s
.
regionMatches
(
true
,
j
,
"TO"
,
0
,
2
))
{
j
+=
2
;
i
=
skipWS
(
s
,
j
);
if
(
i
>
j
&&
s
.
regionMatches
(
true
,
i
,
"SECOND"
,
0
,
6
))
{
if
(
skipWSEnd
(
s
,
i
+
6
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
MINUTE_TO_SECOND
,
negative
,
v
);
}
}
}
}
if
(
s
.
regionMatches
(
true
,
i
,
"SECOND"
,
0
,
6
))
{
if
(
skipWSEnd
(
s
,
i
+
6
)
==
l
)
{
return
parseInterval
(
IntervalQualifier
.
SECOND
,
negative
,
v
);
}
}
throw
new
IllegalArgumentException
(
s
);
}
private
static
int
skipWS
(
String
s
,
int
i
)
{
for
(
int
l
=
s
.
length
();;
i
++)
{
if
(
i
==
l
)
{
throw
new
IllegalArgumentException
(
s
);
}
if
(!
Character
.
isWhitespace
(
s
.
charAt
(
i
)))
{
return
i
;
}
}
}
private
static
int
skipWSEnd
(
String
s
,
int
i
)
{
for
(
int
l
=
s
.
length
();;
i
++)
{
if
(
i
==
l
)
{
return
i
;
}
if
(!
Character
.
isWhitespace
(
s
.
charAt
(
i
)))
{
return
i
;
}
}
}
/**
* Parses the specified string as {@code INTERVAL} value.
*
* @param qualifier
* the qualifier of interval
* @param negative
* whether the interval is negative
* @param s
* the string to parse
* @return the interval value
*/
public
static
ValueInterval
parseInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
String
s
)
{
long
leading
,
remaining
;
switch
(
qualifier
)
{
case
YEAR:
case
MONTH:
case
DAY:
case
HOUR:
case
MINUTE:
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
break
;
case
SECOND:
{
int
dot
=
s
.
indexOf
(
'.'
);
if
(
dot
<
0
)
{
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
}
else
{
leading
=
parseIntervalLeading
(
s
,
0
,
dot
,
negative
);
remaining
=
DateTimeUtils
.
parseNanos
(
s
,
dot
+
1
,
s
.
length
());
}
break
;
}
case
YEAR_TO_MONTH:
return
parseInterval2
(
qualifier
,
s
,
'-'
,
11
,
negative
);
case
DAY_TO_HOUR:
return
parseInterval2
(
qualifier
,
s
,
' '
,
23
,
negative
);
case
DAY_TO_MINUTE:
{
int
space
=
s
.
indexOf
(
' '
);
if
(
space
<
0
)
{
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
}
else
{
leading
=
parseIntervalLeading
(
s
,
0
,
space
,
negative
);
int
colon
=
s
.
indexOf
(
':'
,
space
+
1
);
if
(
colon
<
0
)
{
remaining
=
parseIntervalRemaining
(
s
,
space
+
1
,
s
.
length
(),
23
)
*
60
;
}
else
{
remaining
=
parseIntervalRemaining
(
s
,
space
+
1
,
colon
,
23
)
*
60
+
parseIntervalRemaining
(
s
,
colon
+
1
,
s
.
length
(),
59
);
}
}
break
;
}
case
DAY_TO_SECOND:
{
int
space
=
s
.
indexOf
(
' '
);
if
(
space
<
0
)
{
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
}
else
{
leading
=
parseIntervalLeading
(
s
,
0
,
space
,
negative
);
int
colon
=
s
.
indexOf
(
':'
,
space
+
1
);
if
(
colon
<
0
)
{
remaining
=
parseIntervalRemaining
(
s
,
space
+
1
,
s
.
length
(),
23
)
*
NANOS_PER_HOUR
;
}
else
{
int
colon2
=
s
.
indexOf
(
':'
,
colon
+
1
);
if
(
colon2
<
0
)
{
remaining
=
parseIntervalRemaining
(
s
,
space
+
1
,
colon
,
23
)
*
NANOS_PER_HOUR
+
parseIntervalRemaining
(
s
,
colon
+
1
,
s
.
length
(),
59
)
*
NANOS_PER_MINUTE
;
}
else
{
remaining
=
parseIntervalRemaining
(
s
,
space
+
1
,
colon
,
23
)
*
NANOS_PER_HOUR
+
parseIntervalRemaining
(
s
,
colon
+
1
,
colon2
,
59
)
*
NANOS_PER_MINUTE
+
parseIntervalRemainingSeconds
(
s
,
colon2
+
1
);
}
}
}
break
;
}
case
HOUR_TO_MINUTE:
return
parseInterval2
(
qualifier
,
s
,
':'
,
59
,
negative
);
case
HOUR_TO_SECOND:
{
int
colon
=
s
.
indexOf
(
':'
);
if
(
colon
<
0
)
{
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
}
else
{
leading
=
parseIntervalLeading
(
s
,
0
,
colon
,
negative
);
int
colon2
=
s
.
indexOf
(
':'
,
colon
+
1
);
if
(
colon2
<
0
)
{
remaining
=
parseIntervalRemaining
(
s
,
colon
+
1
,
s
.
length
(),
59
)
*
NANOS_PER_MINUTE
;
}
else
{
remaining
=
parseIntervalRemaining
(
s
,
colon
+
1
,
colon2
,
59
)
*
NANOS_PER_MINUTE
+
parseIntervalRemainingSeconds
(
s
,
colon2
+
1
);
}
}
break
;
}
case
MINUTE_TO_SECOND:
{
int
dash
=
s
.
indexOf
(
':'
);
if
(
dash
<
0
)
{
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
}
else
{
leading
=
parseIntervalLeading
(
s
,
0
,
dash
,
negative
);
remaining
=
parseIntervalRemainingSeconds
(
s
,
dash
+
1
);
}
break
;
}
default
:
throw
new
IllegalArgumentException
();
}
negative
=
leading
<
0
;
if
(
negative
)
{
if
(
leading
!=
Long
.
MIN_VALUE
)
{
leading
=
-
leading
;
}
else
{
leading
=
0
;
}
}
return
ValueInterval
.
from
(
qualifier
,
negative
,
leading
,
remaining
);
}
static
ValueInterval
parseInterval2
(
IntervalQualifier
qualifier
,
String
s
,
char
ch
,
int
max
,
boolean
negative
)
{
long
leading
;
long
remaining
;
int
dash
=
s
.
indexOf
(
ch
,
1
);
if
(
dash
<
0
)
{
leading
=
parseIntervalLeading
(
s
,
0
,
s
.
length
(),
negative
);
remaining
=
0
;
}
else
{
leading
=
parseIntervalLeading
(
s
,
0
,
dash
,
negative
);
remaining
=
parseIntervalRemaining
(
s
,
dash
+
1
,
s
.
length
(),
max
);
}
negative
=
leading
<
0
;
if
(
negative
)
{
if
(
leading
!=
Long
.
MIN_VALUE
)
{
leading
=
-
leading
;
}
else
{
leading
=
0
;
}
}
return
ValueInterval
.
from
(
qualifier
,
negative
,
leading
,
remaining
);
}
private
static
long
parseIntervalLeading
(
String
s
,
int
start
,
int
end
,
boolean
negative
)
{
long
leading
=
Long
.
parseLong
(
s
.
substring
(
start
,
end
));
if
(
leading
==
0
)
{
return
negative
^
s
.
charAt
(
start
)
==
'-'
?
Long
.
MIN_VALUE
:
0
;
}
return
negative
?
-
leading
:
leading
;
}
private
static
long
parseIntervalRemaining
(
String
s
,
int
start
,
int
end
,
int
max
)
{
int
v
=
StringUtils
.
parseUInt31
(
s
,
start
,
end
);
if
(
v
>
max
)
{
throw
new
IllegalArgumentException
(
s
);
}
return
v
;
}
private
static
long
parseIntervalRemainingSeconds
(
String
s
,
int
start
)
{
int
seconds
,
nanos
;
int
dot
=
s
.
indexOf
(
'.'
,
start
+
1
);
if
(
dot
<
0
)
{
seconds
=
StringUtils
.
parseUInt31
(
s
,
start
,
s
.
length
());
nanos
=
0
;
}
else
{
seconds
=
StringUtils
.
parseUInt31
(
s
,
start
,
dot
);
nanos
=
DateTimeUtils
.
parseNanos
(
s
,
dot
+
1
,
s
.
length
());
}
if
(
seconds
>
59
)
{
throw
new
IllegalArgumentException
(
s
);
}
return
seconds
*
NANOS_PER_SECOND
+
nanos
;
}
/**
* Formats interval as a string.
*
* @param qualifier
* qualifier of the interval
* @param negative
* whether interval is negative
* @param leading
* the value of leading field
* @param remaining
* the value of all remaining fields
* @return string representation of the specified interval
*/
public
static
String
intervalToString
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
StringBuilder
buff
=
new
StringBuilder
().
append
(
"INTERVAL "
);
buff
.
append
(
'\''
);
if
(
negative
)
{
buff
.
append
(
'-'
);
}
switch
(
qualifier
)
{
case
YEAR:
case
MONTH:
case
DAY:
case
HOUR:
case
MINUTE:
buff
.
append
(
leading
);
break
;
case
SECOND:
buff
.
append
(
leading
);
appendNanos
(
buff
,
remaining
);
break
;
case
YEAR_TO_MONTH:
buff
.
append
(
leading
).
append
(
'-'
).
append
(
remaining
);
break
;
case
DAY_TO_HOUR:
buff
.
append
(
leading
).
append
(
' '
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
);
break
;
case
DAY_TO_MINUTE:
buff
.
append
(
leading
).
append
(
' '
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
/
60
);
buff
.
append
(
':'
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
%
60
);
break
;
case
DAY_TO_SECOND:
{
long
nanos
=
remaining
%
NANOS_PER_MINUTE
;
remaining
/=
NANOS_PER_MINUTE
;
buff
.
append
(
leading
).
append
(
' '
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
/
60
);
buff
.
append
(
':'
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
%
60
);
buff
.
append
(
':'
);
appendSecondsWithNanos
(
buff
,
nanos
);
break
;
}
case
HOUR_TO_MINUTE:
buff
.
append
(
leading
).
append
(
':'
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
);
break
;
case
HOUR_TO_SECOND:
buff
.
append
(
leading
).
append
(
':'
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
remaining
/
NANOS_PER_MINUTE
);
buff
.
append
(
':'
);
appendSecondsWithNanos
(
buff
,
remaining
%
NANOS_PER_MINUTE
);
break
;
case
MINUTE_TO_SECOND:
buff
.
append
(
leading
).
append
(
':'
);
appendSecondsWithNanos
(
buff
,
remaining
);
break
;
}
buff
.
append
(
"' "
).
append
(
qualifier
);
return
buff
.
toString
();
}
private
static
void
appendSecondsWithNanos
(
StringBuilder
buff
,
long
nanos
)
{
StringUtils
.
appendZeroPadded
(
buff
,
2
,
nanos
/
NANOS_PER_SECOND
);
appendNanos
(
buff
,
nanos
%
NANOS_PER_SECOND
);
}
private
static
void
appendNanos
(
StringBuilder
buff
,
long
nanos
)
{
if
(
nanos
>
0
)
{
buff
.
append
(
'.'
);
StringUtils
.
appendZeroPadded
(
buff
,
9
,
nanos
);
DateTimeUtils
.
stripTrailingZeroes
(
buff
);
}
}
/**
* Converts interval value to an absolute value.
*
* @param interval
* the interval value
* @return absolute value in months for year-month intervals, in nanoseconds
* for day-time intervals
*/
public
static
BigInteger
intervalToAbsolute
(
ValueInterval
interval
)
{
BigInteger
r
;
switch
(
interval
.
getQualifier
())
{
case
YEAR:
r
=
BigInteger
.
valueOf
(
interval
.
getLeading
()).
multiply
(
MONTHS_PER_YEAR_BI
);
break
;
case
MONTH:
r
=
BigInteger
.
valueOf
(
interval
.
getLeading
());
break
;
case
DAY:
r
=
BigInteger
.
valueOf
(
interval
.
getLeading
()).
multiply
(
NANOS_PER_DAY_BI
);
break
;
case
HOUR:
r
=
BigInteger
.
valueOf
(
interval
.
getLeading
()).
multiply
(
NANOS_PER_HOUR_BI
);
break
;
case
MINUTE:
r
=
BigInteger
.
valueOf
(
interval
.
getLeading
()).
multiply
(
NANOS_PER_MINUTE_BI
);
break
;
case
SECOND:
r
=
intervalToAbsolute
(
interval
,
NANOS_PER_SECOND_BI
);
break
;
case
YEAR_TO_MONTH:
r
=
intervalToAbsolute
(
interval
,
MONTHS_PER_YEAR_BI
);
break
;
case
DAY_TO_HOUR:
r
=
intervalToAbsolute
(
interval
,
HOURS_PER_DAY_BI
,
NANOS_PER_HOUR_BI
);
break
;
case
DAY_TO_MINUTE:
r
=
intervalToAbsolute
(
interval
,
MINUTES_PER_DAY_BI
,
NANOS_PER_MINUTE_BI
);
break
;
case
DAY_TO_SECOND:
r
=
intervalToAbsolute
(
interval
,
NANOS_PER_DAY_BI
);
break
;
case
HOUR_TO_MINUTE:
r
=
intervalToAbsolute
(
interval
,
MINUTES_PER_HOUR_BI
,
NANOS_PER_MINUTE_BI
);
break
;
case
HOUR_TO_SECOND:
r
=
intervalToAbsolute
(
interval
,
NANOS_PER_HOUR_BI
);
break
;
case
MINUTE_TO_SECOND:
r
=
intervalToAbsolute
(
interval
,
NANOS_PER_MINUTE_BI
);
break
;
default
:
throw
new
IllegalArgumentException
();
}
return
interval
.
isNegative
()
?
r
.
negate
()
:
r
;
}
private
static
BigInteger
intervalToAbsolute
(
ValueInterval
interval
,
BigInteger
multiplier
,
BigInteger
totalMultiplier
)
{
return
intervalToAbsolute
(
interval
,
multiplier
).
multiply
(
totalMultiplier
);
}
private
static
BigInteger
intervalToAbsolute
(
ValueInterval
interval
,
BigInteger
multiplier
)
{
return
BigInteger
.
valueOf
(
interval
.
getLeading
()).
multiply
(
multiplier
)
.
add
(
BigInteger
.
valueOf
(
interval
.
getRemaining
()));
}
/**
* Converts absolute value to an interval value.
*
* @param qualifier
* the qualifier of interval
* @param absolute
* absolute value in months for year-month intervals, in
* nanoseconds for day-time intervals
* @return the interval value
*/
public
static
ValueInterval
intervalFromAbsolute
(
IntervalQualifier
qualifier
,
BigInteger
absolute
)
{
switch
(
qualifier
)
{
case
YEAR:
return
ValueInterval
.
from
(
qualifier
,
absolute
.
signum
()
<
0
,
leadingExact
(
absolute
.
divide
(
MONTHS_PER_YEAR_BI
)),
0
);
case
MONTH:
return
ValueInterval
.
from
(
qualifier
,
absolute
.
signum
()
<
0
,
leadingExact
(
absolute
),
0
);
case
DAY:
return
ValueInterval
.
from
(
qualifier
,
absolute
.
signum
()
<
0
,
leadingExact
(
absolute
.
divide
(
NANOS_PER_DAY_BI
)),
0
);
case
HOUR:
return
ValueInterval
.
from
(
qualifier
,
absolute
.
signum
()
<
0
,
leadingExact
(
absolute
.
divide
(
NANOS_PER_HOUR_BI
)),
0
);
case
MINUTE:
return
ValueInterval
.
from
(
qualifier
,
absolute
.
signum
()
<
0
,
leadingExact
(
absolute
.
divide
(
NANOS_PER_MINUTE_BI
)),
0
);
case
SECOND:
return
intervalFromAbsolute
(
qualifier
,
absolute
,
NANOS_PER_SECOND_BI
);
case
YEAR_TO_MONTH:
return
intervalFromAbsolute
(
qualifier
,
absolute
,
MONTHS_PER_YEAR_BI
);
case
DAY_TO_HOUR:
return
intervalFromAbsolute
(
qualifier
,
absolute
.
divide
(
NANOS_PER_HOUR_BI
),
HOURS_PER_DAY_BI
);
case
DAY_TO_MINUTE:
return
intervalFromAbsolute
(
qualifier
,
absolute
.
divide
(
NANOS_PER_MINUTE_BI
),
MINUTES_PER_DAY_BI
);
case
DAY_TO_SECOND:
return
intervalFromAbsolute
(
qualifier
,
absolute
,
NANOS_PER_DAY_BI
);
case
HOUR_TO_MINUTE:
return
intervalFromAbsolute
(
qualifier
,
absolute
.
divide
(
NANOS_PER_MINUTE_BI
),
MINUTES_PER_HOUR_BI
);
case
HOUR_TO_SECOND:
return
intervalFromAbsolute
(
qualifier
,
absolute
,
NANOS_PER_HOUR_BI
);
case
MINUTE_TO_SECOND:
return
intervalFromAbsolute
(
qualifier
,
absolute
,
NANOS_PER_MINUTE_BI
);
default
:
throw
new
IllegalArgumentException
();
}
}
private
static
ValueInterval
intervalFromAbsolute
(
IntervalQualifier
qualifier
,
BigInteger
absolute
,
BigInteger
divisor
)
{
BigInteger
[]
dr
=
absolute
.
divideAndRemainder
(
divisor
);
return
ValueInterval
.
from
(
qualifier
,
absolute
.
signum
()
<
0
,
leadingExact
(
dr
[
0
]),
Math
.
abs
(
dr
[
1
].
longValue
()));
}
private
static
long
leadingExact
(
BigInteger
absolute
)
{
if
(
absolute
.
compareTo
(
LEADING_MAX
)
>
0
||
absolute
.
compareTo
(
LEADING_MIN
)
<
0
)
{
throw
DbException
.
get
(
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_1
,
absolute
.
toString
());
}
return
Math
.
abs
(
absolute
.
longValue
());
}
/**
* Ensures that all fields in interval are valid.
*
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return fixed value of negative field
*/
public
static
boolean
validateInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
if
(
qualifier
==
null
)
{
throw
new
NullPointerException
();
}
if
(
leading
==
0L
&&
remaining
==
0L
)
{
return
false
;
}
// Upper bound for remaining value (exclusive)
long
bound
;
switch
(
qualifier
)
{
case
YEAR:
case
MONTH:
case
DAY:
case
HOUR:
case
MINUTE:
bound
=
1
;
break
;
case
SECOND:
bound
=
NANOS_PER_SECOND
;
break
;
case
YEAR_TO_MONTH:
bound
=
12
;
break
;
case
DAY_TO_HOUR:
bound
=
24
;
break
;
case
DAY_TO_MINUTE:
bound
=
24
*
60
;
break
;
case
DAY_TO_SECOND:
bound
=
NANOS_PER_DAY
;
break
;
case
HOUR_TO_MINUTE:
bound
=
60
;
break
;
case
HOUR_TO_SECOND:
bound
=
NANOS_PER_HOUR
;
break
;
case
MINUTE_TO_SECOND:
bound
=
NANOS_PER_MINUTE
;
break
;
default
:
throw
DbException
.
getInvalidValueException
(
"interval"
,
qualifier
);
}
if
(
leading
<
0L
||
leading
>=
1_000_000_000_000_000_000L
)
{
throw
DbException
.
getInvalidValueException
(
"interval"
,
Long
.
toString
(
leading
));
}
if
(
remaining
<
0L
||
remaining
>=
bound
)
{
throw
DbException
.
getInvalidValueException
(
"interval"
,
Long
.
toString
(
remaining
));
}
return
negative
;
}
/**
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return years, or 0
*/
public
static
long
yearsFromInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
if
(
qualifier
==
IntervalQualifier
.
YEAR
||
qualifier
==
IntervalQualifier
.
YEAR_TO_MONTH
)
{
long
v
=
leading
;
if
(
negative
)
{
v
=
-
v
;
}
return
v
;
}
else
{
return
0
;
}
}
/**
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return months, or 0
*/
public
static
long
monthsFromInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
long
v
;
if
(
qualifier
==
IntervalQualifier
.
MONTH
)
{
v
=
leading
;
}
else
if
(
qualifier
==
IntervalQualifier
.
YEAR_TO_MONTH
)
{
v
=
remaining
;
}
else
{
return
0
;
}
if
(
negative
)
{
v
=
-
v
;
}
return
v
;
}
/**
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return months, or 0
*/
public
static
long
daysFromInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
switch
(
qualifier
)
{
case
DAY:
case
DAY_TO_HOUR:
case
DAY_TO_MINUTE:
case
DAY_TO_SECOND:
long
v
=
leading
;
if
(
negative
)
{
v
=
-
v
;
}
return
v
;
default
:
return
0
;
}
}
/**
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return hours, or 0
*/
public
static
long
hoursFromInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
long
v
;
switch
(
qualifier
)
{
case
HOUR:
case
HOUR_TO_MINUTE:
case
HOUR_TO_SECOND:
v
=
leading
;
break
;
case
DAY_TO_HOUR:
v
=
remaining
;
break
;
case
DAY_TO_MINUTE:
v
=
remaining
/
60
;
break
;
case
DAY_TO_SECOND:
v
=
remaining
/
NANOS_PER_HOUR
;
break
;
default
:
return
0
;
}
if
(
negative
)
{
v
=
-
v
;
}
return
v
;
}
/**
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return minutes, or 0
*/
public
static
long
minutesFromInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
long
v
;
switch
(
qualifier
)
{
case
MINUTE:
case
MINUTE_TO_SECOND:
v
=
leading
;
break
;
case
DAY_TO_MINUTE:
v
=
remaining
%
60
;
break
;
case
DAY_TO_SECOND:
v
=
remaining
/
NANOS_PER_MINUTE
%
60
;
break
;
case
HOUR_TO_MINUTE:
v
=
remaining
;
break
;
case
HOUR_TO_SECOND:
v
=
remaining
/
NANOS_PER_MINUTE
;
break
;
default
:
return
0
;
}
if
(
negative
)
{
v
=
-
v
;
}
return
v
;
}
/**
* @param qualifier
* qualifier
* @param negative
* whether interval is negative
* @param leading
* value of leading field
* @param remaining
* values of all remaining fields
* @return nanoseconds, or 0
*/
public
static
long
nanosFromInterval
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
long
v
;
switch
(
qualifier
)
{
case
SECOND:
v
=
leading
*
NANOS_PER_SECOND
+
remaining
;
break
;
case
DAY_TO_SECOND:
case
HOUR_TO_SECOND:
v
=
remaining
%
NANOS_PER_MINUTE
;
break
;
case
MINUTE_TO_SECOND:
v
=
remaining
;
break
;
default
:
return
0
;
}
if
(
negative
)
{
v
=
-
v
;
}
return
v
;
}
}
h2/src/main/org/h2/util/LocalDateTimeUtils.java
浏览文件 @
0661149e
...
...
@@ -397,7 +397,7 @@ public class LocalDateTimeUtils {
if
(
DataType
.
isYearMonthIntervalType
(
value
.
getType
()))
{
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
(
Throwable
)
null
,
value
.
getString
());
}
BigInteger
[]
dr
=
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
value
)
BigInteger
[]
dr
=
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
value
)
.
divideAndRemainder
(
BigInteger
.
valueOf
(
1_000_000_000
));
try
{
return
DURATION_OF_SECONDS
.
invoke
(
null
,
dr
[
0
].
longValue
(),
dr
[
1
].
longValue
());
...
...
h2/src/main/org/h2/value/Value.java
浏览文件 @
0661149e
...
...
@@ -28,6 +28,7 @@ import org.h2.store.DataHandler;
import
org.h2.tools.SimpleResultSet
;
import
org.h2.util.Bits
;
import
org.h2.util.DateTimeUtils
;
import
org.h2.util.IntervalUtils
;
import
org.h2.util.JdbcUtils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.StringUtils
;
...
...
@@ -963,7 +964,7 @@ public abstract class Value {
private
ValueDouble
convertToDouble
()
{
switch
(
getType
())
{
case
BOOLEAN:
return
ValueDouble
.
get
(
getBoolean
()
?
1
:
0
)
;
return
getBoolean
()
?
ValueDouble
.
ONE
:
ValueDouble
.
ZERO
;
case
BYTE:
case
SHORT:
case
INT:
...
...
@@ -984,7 +985,7 @@ public abstract class Value {
private
ValueFloat
convertToFloat
()
{
switch
(
getType
())
{
case
BOOLEAN:
return
ValueFloat
.
get
(
getBoolean
()
?
1
:
0
)
;
return
getBoolean
()
?
ValueFloat
.
ONE
:
ValueFloat
.
ZERO
;
case
BYTE:
case
SHORT:
case
INT:
...
...
@@ -1234,7 +1235,7 @@ public abstract class Value {
case
Value
.
STRING_FIXED
:
{
String
s
=
getString
();
try
{
return
(
ValueInterval
)
DateTime
Utils
return
(
ValueInterval
)
Interval
Utils
.
parseFormattedInterval
(
IntervalQualifier
.
valueOf
(
targetType
-
Value
.
INTERVAL_YEAR
),
s
)
.
convertTo
(
targetType
);
}
catch
(
Exception
e
)
{
...
...
@@ -1244,8 +1245,8 @@ public abstract class Value {
case
Value
.
INTERVAL_YEAR
:
case
Value
.
INTERVAL_MONTH
:
case
Value
.
INTERVAL_YEAR_TO_MONTH
:
return
DateTime
Utils
.
intervalFromAbsolute
(
IntervalQualifier
.
valueOf
(
targetType
-
Value
.
INTERVAL_YEAR
),
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
this
));
return
Interval
Utils
.
intervalFromAbsolute
(
IntervalQualifier
.
valueOf
(
targetType
-
Value
.
INTERVAL_YEAR
),
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
this
));
}
throw
getDataConversionError
(
targetType
);
}
...
...
@@ -1257,7 +1258,7 @@ public abstract class Value {
case
Value
.
STRING_FIXED
:
{
String
s
=
getString
();
try
{
return
(
ValueInterval
)
DateTime
Utils
return
(
ValueInterval
)
Interval
Utils
.
parseFormattedInterval
(
IntervalQualifier
.
valueOf
(
targetType
-
Value
.
INTERVAL_YEAR
),
s
)
.
convertTo
(
targetType
);
}
catch
(
Exception
e
)
{
...
...
@@ -1274,8 +1275,8 @@ public abstract class Value {
case
Value
.
INTERVAL_HOUR_TO_MINUTE
:
case
Value
.
INTERVAL_HOUR_TO_SECOND
:
case
Value
.
INTERVAL_MINUTE_TO_SECOND
:
return
DateTime
Utils
.
intervalFromAbsolute
(
IntervalQualifier
.
valueOf
(
targetType
-
Value
.
INTERVAL_YEAR
),
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
this
));
return
Interval
Utils
.
intervalFromAbsolute
(
IntervalQualifier
.
valueOf
(
targetType
-
Value
.
INTERVAL_YEAR
),
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
this
));
}
throw
getDataConversionError
(
targetType
);
}
...
...
h2/src/main/org/h2/value/ValueDouble.java
浏览文件 @
0661149e
...
...
@@ -28,12 +28,20 @@ public class ValueDouble extends Value {
public
static
final
int
DISPLAY_SIZE
=
24
;
/**
* Double.doubleToLongBits(0
.0
)
* Double.doubleToLongBits(0
d
)
*/
public
static
final
long
ZERO_BITS
=
Double
.
doubleToLongBits
(
0.0
);
public
static
final
long
ZERO_BITS
=
0L
;
/**
* The value 0.
*/
public
static
final
ValueDouble
ZERO
=
new
ValueDouble
(
0
d
);
/**
* The value 1.
*/
public
static
final
ValueDouble
ONE
=
new
ValueDouble
(
1
d
);
private
static
final
ValueDouble
ZERO
=
new
ValueDouble
(
0.0
);
private
static
final
ValueDouble
ONE
=
new
ValueDouble
(
1.0
);
private
static
final
ValueDouble
NAN
=
new
ValueDouble
(
Double
.
NaN
);
private
final
double
value
;
...
...
@@ -45,24 +53,24 @@ public class ValueDouble extends Value {
@Override
public
Value
add
(
Value
v
)
{
ValueDouble
v2
=
(
ValueDouble
)
v
;
return
ValueDouble
.
get
(
value
+
v2
.
value
);
return
get
(
value
+
v2
.
value
);
}
@Override
public
Value
subtract
(
Value
v
)
{
ValueDouble
v2
=
(
ValueDouble
)
v
;
return
ValueDouble
.
get
(
value
-
v2
.
value
);
return
get
(
value
-
v2
.
value
);
}
@Override
public
Value
negate
()
{
return
ValueDouble
.
get
(-
value
);
return
get
(-
value
);
}
@Override
public
Value
multiply
(
Value
v
)
{
ValueDouble
v2
=
(
ValueDouble
)
v
;
return
ValueDouble
.
get
(
value
*
v2
.
value
);
return
get
(
value
*
v2
.
value
);
}
@Override
...
...
@@ -71,7 +79,7 @@ public class ValueDouble extends Value {
if
(
v2
.
value
==
0.0
)
{
throw
DbException
.
get
(
ErrorCode
.
DIVISION_BY_ZERO_1
,
getSQL
());
}
return
ValueDouble
.
get
(
value
/
v2
.
value
);
return
get
(
value
/
v2
.
value
);
}
@Override
...
...
@@ -80,7 +88,7 @@ public class ValueDouble extends Value {
if
(
other
.
value
==
0
)
{
throw
DbException
.
get
(
ErrorCode
.
DIVISION_BY_ZERO_1
,
getSQL
());
}
return
ValueDouble
.
get
(
value
%
other
.
value
);
return
get
(
value
%
other
.
value
);
}
@Override
...
...
h2/src/main/org/h2/value/ValueFloat.java
浏览文件 @
0661149e
...
...
@@ -16,11 +16,6 @@ import org.h2.message.DbException;
*/
public
class
ValueFloat
extends
Value
{
/**
* Float.floatToIntBits(0.0F).
*/
public
static
final
int
ZERO_BITS
=
Float
.
floatToIntBits
(
0.0
F
);
/**
* The precision in digits.
*/
...
...
@@ -32,8 +27,21 @@ public class ValueFloat extends Value {
*/
static
final
int
DISPLAY_SIZE
=
15
;
private
static
final
ValueFloat
ZERO
=
new
ValueFloat
(
0.0
F
);
private
static
final
ValueFloat
ONE
=
new
ValueFloat
(
1.0
F
);
/**
* Float.floatToIntBits(0f).
*/
public
static
final
int
ZERO_BITS
=
0
;
/**
* The value 0.
*/
public
static
final
ValueFloat
ZERO
=
new
ValueFloat
(
0
f
);
/**
* The value 1.
*/
public
static
final
ValueFloat
ONE
=
new
ValueFloat
(
1
f
);
private
static
final
ValueFloat
NAN
=
new
ValueFloat
(
Float
.
NaN
);
private
final
float
value
;
...
...
@@ -45,24 +53,24 @@ public class ValueFloat extends Value {
@Override
public
Value
add
(
Value
v
)
{
ValueFloat
v2
=
(
ValueFloat
)
v
;
return
ValueFloat
.
get
(
value
+
v2
.
value
);
return
get
(
value
+
v2
.
value
);
}
@Override
public
Value
subtract
(
Value
v
)
{
ValueFloat
v2
=
(
ValueFloat
)
v
;
return
ValueFloat
.
get
(
value
-
v2
.
value
);
return
get
(
value
-
v2
.
value
);
}
@Override
public
Value
negate
()
{
return
ValueFloat
.
get
(-
value
);
return
get
(-
value
);
}
@Override
public
Value
multiply
(
Value
v
)
{
ValueFloat
v2
=
(
ValueFloat
)
v
;
return
ValueFloat
.
get
(
value
*
v2
.
value
);
return
get
(
value
*
v2
.
value
);
}
@Override
...
...
@@ -71,7 +79,7 @@ public class ValueFloat extends Value {
if
(
v2
.
value
==
0.0
)
{
throw
DbException
.
get
(
ErrorCode
.
DIVISION_BY_ZERO_1
,
getSQL
());
}
return
ValueFloat
.
get
(
value
/
v2
.
value
);
return
get
(
value
/
v2
.
value
);
}
@Override
...
...
@@ -80,7 +88,7 @@ public class ValueFloat extends Value {
if
(
other
.
value
==
0
)
{
throw
DbException
.
get
(
ErrorCode
.
DIVISION_BY_ZERO_1
,
getSQL
());
}
return
ValueFloat
.
get
(
value
%
other
.
value
);
return
get
(
value
%
other
.
value
);
}
@Override
...
...
h2/src/main/org/h2/value/ValueInterval.java
浏览文件 @
0661149e
...
...
@@ -12,6 +12,7 @@ import org.h2.api.Interval;
import
org.h2.api.IntervalQualifier
;
import
org.h2.message.DbException
;
import
org.h2.util.DateTimeUtils
;
import
org.h2.util.IntervalUtils
;
/**
* Implementation of the INTERVAL data type.
...
...
@@ -58,7 +59,7 @@ public class ValueInterval extends Value {
* @return interval value
*/
public
static
ValueInterval
from
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
)
{
negative
=
DateTime
Utils
.
validateInterval
(
qualifier
,
negative
,
leading
,
remaining
);
negative
=
Interval
Utils
.
validateInterval
(
qualifier
,
negative
,
leading
,
remaining
);
return
(
ValueInterval
)
Value
.
cache
(
new
ValueInterval
(
qualifier
.
ordinal
()
+
INTERVAL_YEAR
,
negative
,
leading
,
remaining
));
}
...
...
@@ -203,7 +204,7 @@ public class ValueInterval extends Value {
@Override
public
String
getString
()
{
return
DateTime
Utils
.
intervalToString
(
getQualifier
(),
negative
,
leading
,
remaining
);
return
Interval
Utils
.
intervalToString
(
getQualifier
(),
negative
,
leading
,
remaining
);
}
@Override
...
...
@@ -298,14 +299,14 @@ public class ValueInterval extends Value {
@Override
public
Value
add
(
Value
v
)
{
return
DateTime
Utils
.
intervalFromAbsolute
(
getQualifier
(),
DateTimeUtils
.
intervalToAbsolute
(
this
).
add
(
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
v
)));
return
Interval
Utils
.
intervalFromAbsolute
(
getQualifier
(),
IntervalUtils
.
intervalToAbsolute
(
this
).
add
(
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
v
)));
}
@Override
public
Value
subtract
(
Value
v
)
{
return
DateTime
Utils
.
intervalFromAbsolute
(
getQualifier
(),
DateTimeUtils
.
intervalToAbsolute
(
this
).
subtract
(
DateTime
Utils
.
intervalToAbsolute
((
ValueInterval
)
v
)));
return
Interval
Utils
.
intervalFromAbsolute
(
getQualifier
(),
IntervalUtils
.
intervalToAbsolute
(
this
).
subtract
(
Interval
Utils
.
intervalToAbsolute
((
ValueInterval
)
v
)));
}
@Override
...
...
h2/src/test/org/h2/test/scripts/TestScript.java
浏览文件 @
0661149e
...
...
@@ -125,7 +125,7 @@ public class TestScript extends TestDb {
testScript
(
"datatypes/"
+
s
+
".sql"
);
}
for
(
String
s
:
new
String
[]
{
"alterTableAdd"
,
"alterTableDropColumn"
,
"alterTableRename"
,
"createAlias"
,
"createSynonym"
,
"createTable"
,
"createTrigger"
,
"createView"
,
"createAlias"
,
"createS
equence"
,
"createS
ynonym"
,
"createTable"
,
"createTrigger"
,
"createView"
,
"dropDomain"
,
"dropIndex"
,
"dropSchema"
,
"truncateTable"
})
{
testScript
(
"ddl/"
+
s
+
".sql"
);
}
...
...
h2/src/test/org/h2/test/scripts/ddl/createSequence.sql
0 → 100644
浏览文件 @
0661149e
-- Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
CREATE
SEQUENCE
SEQ
START
WITH
0
INCREMENT
BY
1
MINVALUE
0
MAXVALUE
1
;
>
ok
DROP
SEQUENCE
SEQ
;
>
ok
CREATE
SEQUENCE
SEQ
START
WITH
0
INCREMENT
BY
1
MINVALUE
0
MAXVALUE
0
;
>
exception
SEQUENCE_ATTRIBUTES_INVALID
CREATE
SEQUENCE
SEQ
START
WITH
1
INCREMENT
BY
1
MINVALUE
1
MAXVALUE
0
;
>
exception
SEQUENCE_ATTRIBUTES_INVALID
CREATE
SEQUENCE
SEQ
START
WITH
0
INCREMENT
BY
0
MINVALUE
0
MAXVALUE
1
;
>
exception
SEQUENCE_ATTRIBUTES_INVALID
CREATE
SEQUENCE
SEQ
START
WITH
1
INCREMENT
BY
1
MINVALUE
2
MAXVALUE
10
;
>
exception
SEQUENCE_ATTRIBUTES_INVALID
CREATE
SEQUENCE
SEQ
START
WITH
20
INCREMENT
BY
1
MINVALUE
1
MAXVALUE
10
;
>
exception
SEQUENCE_ATTRIBUTES_INVALID
CREATE
SEQUENCE
SEQ
START
WITH
0
INCREMENT
BY
9223372036854775807
MINVALUE
-
9223372036854775808
MAXVALUE
9223372036854775807
;
>
ok
DROP
SEQUENCE
SEQ
;
>
ok
CREATE
SEQUENCE
SEQ
START
WITH
0
INCREMENT
BY
-
9223372036854775808
MINVALUE
-
9223372036854775808
MAXVALUE
9223372036854775807
;
>
ok
DROP
SEQUENCE
SEQ
;
>
ok
CREATE
SEQUENCE
SEQ
START
WITH
0
INCREMENT
BY
-
9223372036854775808
MINVALUE
-
1
MAXVALUE
9223372036854775807
;
>
ok
DROP
SEQUENCE
SEQ
;
>
ok
CREATE
SEQUENCE
SEQ
START
WITH
0
INCREMENT
BY
-
9223372036854775808
MINVALUE
0
MAXVALUE
9223372036854775807
;
>
exception
SEQUENCE_ATTRIBUTES_INVALID
h2/src/test/org/h2/test/unit/TestDateTimeUtils.java
浏览文件 @
0661149e
...
...
@@ -15,11 +15,12 @@ import java.util.TimeZone;
import
org.h2.api.IntervalQualifier
;
import
org.h2.test.TestBase
;
import
org.h2.util.DateTimeUtils
;
import
org.h2.util.IntervalUtils
;
import
org.h2.value.ValueInterval
;
import
org.h2.value.ValueTimestamp
;
/**
* Unit tests for the DateTimeUtils
class
* Unit tests for the DateTimeUtils
and IntervalUtils classes.
*/
public
class
TestDateTimeUtils
extends
TestBase
{
...
...
@@ -257,7 +258,7 @@ public class TestDateTimeUtils extends TestBase {
private
void
testParseIntervalImpl
(
IntervalQualifier
qualifier
,
boolean
negative
,
long
leading
,
long
remaining
,
String
s
,
String
full
)
{
ValueInterval
expected
=
ValueInterval
.
from
(
qualifier
,
negative
,
leading
,
remaining
);
assertEquals
(
expected
,
DateTime
Utils
.
parseInterval
(
qualifier
,
negative
,
s
));
assertEquals
(
expected
,
Interval
Utils
.
parseInterval
(
qualifier
,
negative
,
s
));
StringBuilder
b
=
new
StringBuilder
();
b
.
append
(
"INTERVAL "
).
append
(
'\''
);
if
(
negative
)
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论