Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
0661149e
Unverified
提交
0661149e
authored
6 年前
作者:
Evgenij Ryazanov
提交者:
GitHub
6 年前
浏览文件
操作
浏览文件
下载
差异文件
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
);
}
}
This diff is collapsed.
Click to expand it.
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
);
}
...
...
This diff is collapsed.
Click to expand it.
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
;
}
...
...
This diff is collapsed.
Click to expand it.
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
);
...
...
This diff is collapsed.
Click to expand it.
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
();
...
...
This diff is collapsed.
Click to expand it.
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
);
...
...
This diff is collapsed.
Click to expand it.
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:
...
...
This diff is collapsed.
Click to expand it.
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
();
...
...
This diff is collapsed.
Click to expand it.
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
;
...
...
This diff is collapsed.
Click to expand it.
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
))));
...
...
This diff is collapsed.
Click to expand it.
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
)
{
...
...
This diff is collapsed.
Click to expand it.
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
())));
...
...
This diff is collapsed.
Click to expand it.
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
+
')'
);
...
...
This diff is collapsed.
Click to expand it.
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
;
}
}
This diff is collapsed.
Click to expand it.
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
;
}
}
This diff is collapsed.
Click to expand it.
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
());
...
...
This diff is collapsed.
Click to expand it.
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
);
}
...
...
This diff is collapsed.
Click to expand it.
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
...
...
This diff is collapsed.
Click to expand it.
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
...
...
This diff is collapsed.
Click to expand it.
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
...
...
This diff is collapsed.
Click to expand it.
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"
);
}
...
...
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
)
{
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论