Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
9e5d9644
提交
9e5d9644
authored
2月 18, 2018
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into generated_keys
上级
0581dbd0
8556fd23
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
30 个修改的文件
包含
1116 行增加
和
644 行删除
+1116
-644
help.csv
h2/src/docsrc/help/help.csv
+39
-5
Constraint.java
h2/src/main/org/h2/constraint/Constraint.java
+0
-1
AggregateDataMedian.java
h2/src/main/org/h2/expression/AggregateDataMedian.java
+2
-1
Function.java
h2/src/main/org/h2/expression/Function.java
+96
-74
IndexCursor.java
h2/src/main/org/h2/index/IndexCursor.java
+3
-4
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+22
-20
DataReader.java
h2/src/main/org/h2/store/DataReader.java
+1
-1
MetaTable.java
h2/src/main/org/h2/table/MetaTable.java
+1
-1
ChangeFileEncryption.java
h2/src/main/org/h2/tools/ChangeFileEncryption.java
+2
-1
DateTimeUtils.java
h2/src/main/org/h2/util/DateTimeUtils.java
+41
-39
ToChar.java
h2/src/main/org/h2/util/ToChar.java
+180
-106
ToDateParser.java
h2/src/main/org/h2/util/ToDateParser.java
+202
-42
ToDateTokenizer.java
h2/src/main/org/h2/util/ToDateTokenizer.java
+82
-111
Transfer.java
h2/src/main/org/h2/value/Transfer.java
+1
-17
ValueLobDb.java
h2/src/main/org/h2/value/ValueLobDb.java
+10
-0
ValueTimestampTimeZone.java
h2/src/main/org/h2/value/ValueTimestampTimeZone.java
+24
-42
TestBase.java
h2/src/test/org/h2/test/TestBase.java
+66
-10
TestFunctions.java
h2/src/test/org/h2/test/db/TestFunctions.java
+92
-70
TestOutOfMemory.java
h2/src/test/org/h2/test/db/TestOutOfMemory.java
+88
-60
TestLobApi.java
h2/src/test/org/h2/test/jdbc/TestLobApi.java
+27
-4
TestScript.java
h2/src/test/org/h2/test/scripts/TestScript.java
+1
-1
dateadd.sql
...est/org/h2/test/scripts/functions/timeanddate/dateadd.sql
+12
-0
datediff.sql
...st/org/h2/test/scripts/functions/timeanddate/datediff.sql
+16
-0
extract.sql
...est/org/h2/test/scripts/functions/timeanddate/extract.sql
+14
-0
TestMVStoreBenchmark.java
h2/src/test/org/h2/test/store/TestMVStoreBenchmark.java
+0
-8
TestFuzzOptimizations.java
h2/src/test/org/h2/test/synth/TestFuzzOptimizations.java
+22
-17
TestClearReferences.java
h2/src/test/org/h2/test/unit/TestClearReferences.java
+3
-0
TestDateTimeUtils.java
h2/src/test/org/h2/test/unit/TestDateTimeUtils.java
+58
-4
TestTimeStampWithTimeZone.java
h2/src/test/org/h2/test/unit/TestTimeStampWithTimeZone.java
+9
-3
dictionary.txt
h2/src/tools/org/h2/build/doc/dictionary.txt
+2
-2
没有找到文件。
h2/src/docsrc/help/help.csv
浏览文件 @
9e5d9644
...
...
@@ -2300,9 +2300,9 @@ Each table has a pseudo-column named ""_ROWID_"" that contains the unique row id
"
"Other Grammar","Time","
TIME 'hh:mm:ss'
TIME 'hh:mm:ss
[.nnnnnnnnn]
'
","
A time literal. A value is between
plus and minus 2 million hours
A time literal. A value is between
0:00:00 and 23:59:59.999999999
and has nanosecond resolution.
","
TIME '23:59:59'
...
...
@@ -2318,6 +2318,19 @@ minimum and maximum years are 0001 and 9999.
TIMESTAMP '2005-12-31 23:59:59'
"
"Other Grammar","Timestamp with time zone","
TIMESTAMP 'yyyy-MM-dd hh:mm:ss[.nnnnnnnnn]
[Z | { - | + } timeZoneOffsetString | timeZoneNameString ]'
","
A timestamp with time zone literal.
If name of time zone is specified it will be converted to time zone offset.
","
TIMESTAMP WITH TIME ZONE '2005-12-31 23:59:59Z'
TIMESTAMP WITH TIME ZONE '2005-12-31 23:59:59-10:00'
TIMESTAMP WITH TIME ZONE '2005-12-31 23:59:59.123+05'
TIMESTAMP WITH TIME ZONE '2005-12-31 23:59:59.123456789 Europe/London'
"
"Other Grammar","Value","
string | dollarQuotedString | numeric | date | time | timestamp | boolean | bytes | array | null
","
...
...
@@ -3671,7 +3684,7 @@ CURRENT_TIMESTAMP()
Adds units to a date-time value. The string indicates the unit.
Use negative values to subtract units.
addIntLong may be a long value when manipulating milliseconds,
otherwise it'
s range is restricted to int.
microseconds, or nanoseconds otherwise it
s range is restricted to int.
The same units as in the EXTRACT function are supported.
This method returns a value with the same type as specified value if unit is compatible with this value.
If specified unit is a HOUR, MINUTE, SECOND, MILLISECOND, etc and value is a DATE value DATEADD returns combined TIMESTAMP.
...
...
@@ -3727,11 +3740,13 @@ DAY_OF_YEAR(CREATED)
"Functions (Time and Date)","EXTRACT","
EXTRACT ( { YEAR | YY | MONTH | MM | QUARTER | WEEK | ISO_WEEK
| DAY | DD | DAY_OF_YEAR | DOY
| HOUR | HH | MINUTE | MI | SECOND | SS | MILLISECOND | MS }
| HOUR | HH | MINUTE | MI | SECOND | SS | EPOCH
| MILLISECOND | MS | MICROSECOND | MCS | NANOSECOND | NS }
FROM timestamp )
","
Returns a specific value from a timestamps.
This method returns an int.
This method returns a numeric value with EPOCH unit and
an int for all other time units.
","
EXTRACT(SECOND FROM CURRENT_TIMESTAMP)
"
...
...
@@ -3820,6 +3835,17 @@ This method uses the current system locale.
WEEK(CREATED)
"
"Functions (Time and Date)","ISO_WEEK","
ISO_WEEK(timestamp)
","
Returns the week (1-53) from a timestamp.
This method uses the ISO definition when
first week of year should have at least four days
and week is started with Monday.
","
ISO_WEEK(CREATED)
"
"Functions (Time and Date)","YEAR","
YEAR(timestamp)
","
...
...
@@ -3828,6 +3854,14 @@ Returns the year from a timestamp.
YEAR(CREATED)
"
"Functions (Time and Date)","ISO_YEAR","
ISO_YEAR(timestamp)
","
Returns the ISO week year from a timestamp.
","
ISO_YEAR(CREATED)
"
"Functions (System)","ARRAY_GET","
ARRAY_GET(arrayExpression, indexExpression)
","
...
...
h2/src/main/org/h2/constraint/Constraint.java
浏览文件 @
9e5d9644
...
...
@@ -10,7 +10,6 @@ import org.h2.engine.DbObject;
import
org.h2.engine.Session
;
import
org.h2.expression.ExpressionVisitor
;
import
org.h2.index.Index
;
import
org.h2.message.DbException
;
import
org.h2.message.Trace
;
import
org.h2.result.Row
;
import
org.h2.schema.Schema
;
...
...
h2/src/main/org/h2/expression/AggregateDataMedian.java
浏览文件 @
9e5d9644
...
...
@@ -224,7 +224,8 @@ class AggregateDataMedian extends AggregateData {
case
Value
.
DOUBLE
:
return
ValueDouble
.
get
((
v0
.
getFloat
()
+
v1
.
getDouble
())
/
2
);
case
Value
.
TIME
:
{
return
ValueTime
.
fromMillis
((
v0
.
getTime
().
getTime
()
+
v1
.
getTime
().
getTime
())
/
2
);
ValueTime
t0
=
(
ValueTime
)
v0
.
convertTo
(
Value
.
TIME
),
t1
=
(
ValueTime
)
v1
.
convertTo
(
Value
.
TIME
);
return
ValueTime
.
fromNanos
((
t0
.
getNanos
()
+
t1
.
getNanos
())
/
2
);
}
case
Value
.
DATE
:
{
ValueDate
d0
=
(
ValueDate
)
v0
.
convertTo
(
Value
.
DATE
),
d1
=
(
ValueDate
)
v1
.
convertTo
(
Value
.
DATE
);
...
...
h2/src/main/org/h2/expression/Function.java
浏览文件 @
9e5d9644
差异被折叠。
点击展开。
h2/src/main/org/h2/index/IndexCursor.java
浏览文件 @
9e5d9644
...
...
@@ -148,6 +148,9 @@ public class IndexCursor implements Cursor {
}
}
}
if
(
inColumn
!=
null
)
{
start
=
table
.
getTemplateRow
();
}
}
/**
...
...
@@ -326,7 +329,6 @@ public class IndexCursor implements Cursor {
while
(
inResult
.
next
())
{
Value
v
=
inResult
.
currentRow
()[
0
];
if
(
v
!=
ValueNull
.
INSTANCE
)
{
v
=
inColumn
.
convert
(
v
);
if
(
inResultTested
==
null
)
{
inResultTested
=
new
HashSet
<>();
}
...
...
@@ -342,9 +344,6 @@ public class IndexCursor implements Cursor {
private
void
find
(
Value
v
)
{
v
=
inColumn
.
convert
(
v
);
int
id
=
inColumn
.
getColumnId
();
if
(
start
==
null
)
{
start
=
table
.
getTemplateRow
();
}
start
.
setValue
(
id
,
v
);
cursor
=
index
.
find
(
tableFilter
,
start
,
start
);
}
...
...
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
9e5d9644
...
...
@@ -2450,27 +2450,27 @@ public final class MVStore {
* needed.
*/
void
writeInBackground
()
{
if
(
closed
)
{
return
;
}
try
{
if
(
closed
)
{
return
;
}
// could also commit when there are many unsaved pages,
// but according to a test it doesn't really help
// could also commit when there are many unsaved pages,
// but according to a test it doesn't really help
long
time
=
getTimeSinceCreation
();
if
(
time
<=
lastCommitTime
+
autoCommitDelay
)
{
return
;
}
if
(
hasUnsavedChanges
())
{
try
{
commitAndSave
();
}
catch
(
Throwable
e
)
{
handleException
(
e
);
long
time
=
getTimeSinceCreation
();
if
(
time
<=
lastCommitTime
+
autoCommitDelay
)
{
return
;
}
}
if
(
autoCompactFillRate
>
0
)
{
try
{
if
(
hasUnsavedChanges
())
{
try
{
commitAndSave
();
}
catch
(
Throwable
e
)
{
handleException
(
e
);
return
;
}
}
if
(
autoCompactFillRate
>
0
)
{
// whether there were file read or write operations since
// the last time
boolean
fileOps
;
...
...
@@ -2486,9 +2486,9 @@ public final class MVStore {
// in the bookkeeping?
compact
(
fillRate
,
autoCommitMemory
);
autoCompactLastFileOpCount
=
fileStore
.
getWriteCount
()
+
fileStore
.
getReadCount
();
}
catch
(
Throwable
e
)
{
handleException
(
e
);
}
}
catch
(
Throwable
e
)
{
handleException
(
e
);
}
}
...
...
@@ -2497,7 +2497,9 @@ public final class MVStore {
try
{
backgroundExceptionHandler
.
uncaughtException
(
null
,
ex
);
}
catch
(
Throwable
ignore
)
{
ex
.
addSuppressed
(
ignore
);
if
(
ex
!=
ignore
)
{
// OOME may be the same
ex
.
addSuppressed
(
ignore
);
}
}
}
}
...
...
h2/src/main/org/h2/store/DataReader.java
浏览文件 @
9e5d9644
...
...
@@ -171,7 +171,7 @@ public class DataReader extends Reader {
int
i
=
0
;
try
{
for
(;
i
<
len
;
i
++)
{
buff
[
i
]
=
readChar
();
buff
[
off
+
i
]
=
readChar
();
}
return
len
;
}
catch
(
EOFException
e
)
{
...
...
h2/src/main/org/h2/table/MetaTable.java
浏览文件 @
9e5d9644
...
...
@@ -1615,7 +1615,7 @@ public class MetaTable extends Table {
if
(
constraintType
==
Constraint
.
Type
.
CHECK
)
{
checkExpression
=
((
ConstraintCheck
)
constraint
).
getExpression
().
getSQL
();
}
else
if
(
constraintType
==
Constraint
.
Type
.
UNIQUE
||
constraintType
==
Constraint
.
Type
.
PRIMARY_KEY
)
{
constraintType
==
Constraint
.
Type
.
PRIMARY_KEY
)
{
indexColumns
=
((
ConstraintUnique
)
constraint
).
getColumns
();
}
else
if
(
constraintType
==
Constraint
.
Type
.
REFERENTIAL
)
{
indexColumns
=
((
ConstraintReferential
)
constraint
).
getColumns
();
...
...
h2/src/main/org/h2/tools/ChangeFileEncryption.java
浏览文件 @
9e5d9644
...
...
@@ -224,7 +224,8 @@ public class ChangeFileEncryption extends Tool {
try
(
FileChannel
fileIn
=
getFileChannel
(
fileName
,
"r"
,
decryptKey
)){
try
(
InputStream
inStream
=
new
FileChannelInputStream
(
fileIn
,
true
))
{
FileUtils
.
delete
(
temp
);
try
(
OutputStream
outStream
=
new
FileChannelOutputStream
(
getFileChannel
(
temp
,
"rw"
,
encryptKey
),
true
))
{
try
(
OutputStream
outStream
=
new
FileChannelOutputStream
(
getFileChannel
(
temp
,
"rw"
,
encryptKey
),
true
))
{
byte
[]
buffer
=
new
byte
[
4
*
1024
];
long
remaining
=
fileIn
.
size
();
long
total
=
remaining
;
...
...
h2/src/main/org/h2/util/DateTimeUtils.java
浏览文件 @
9e5d9644
...
...
@@ -36,7 +36,7 @@ public class DateTimeUtils {
* The number of milliseconds per day.
*/
public
static
final
long
MILLIS_PER_DAY
=
24
*
60
*
60
*
1000L
;
/**
* The number of seconds per day.
*/
...
...
@@ -85,6 +85,11 @@ public class DateTimeUtils {
private
static
final
ThreadLocal
<
GregorianCalendar
>
CACHED_CALENDAR_NON_DEFAULT_TIMEZONE
=
new
ThreadLocal
<>();
/**
* Cached local time zone.
*/
private
static
volatile
TimeZone
timeZone
;
/**
* Observed JVM behaviour is that if the timezone of the host computer is
* changed while the JVM is running, the zone offset does not change but
...
...
@@ -100,12 +105,26 @@ public class DateTimeUtils {
// utility class
}
/**
* Returns local time zone.
*
* @return local time zone
*/
private
static
TimeZone
getTimeZone
()
{
TimeZone
tz
=
timeZone
;
if
(
tz
==
null
)
{
timeZone
=
tz
=
TimeZone
.
getDefault
();
}
return
tz
;
}
/**
* Reset the cached calendar for default timezone, for example after
* changing the default timezone.
*/
public
static
void
resetCalendar
()
{
CACHED_CALENDAR
.
remove
();
timeZone
=
null
;
zoneOffsetMillis
=
DateTimeUtils
.
createGregorianCalendar
().
get
(
Calendar
.
ZONE_OFFSET
);
}
...
...
@@ -628,20 +647,6 @@ public class DateTimeUtils {
return
ValueTimestamp
.
fromDateValueAndNanos
(
dateValue
,
timeNanos
);
}
/**
* Get the year (positive or negative) from a calendar.
*
* @param calendar the calendar
* @return the year
*/
private
static
int
getYear
(
Calendar
calendar
)
{
int
year
=
calendar
.
get
(
Calendar
.
YEAR
);
if
(
calendar
.
get
(
Calendar
.
ERA
)
==
GregorianCalendar
.
BC
)
{
year
=
1
-
year
;
}
return
year
;
}
/**
* Get the number of milliseconds since 1970-01-01 in the local timezone,
* but without daylight saving time into account.
...
...
@@ -921,19 +926,6 @@ public class DateTimeUtils {
return
new
Date
(
millis
);
}
/**
* Convert an encoded date value to millis, using the supplied timezone.
*
* @param tz the timezone
* @param dateValue the date value
* @return the date
*/
public
static
long
convertDateValueToMillis
(
TimeZone
tz
,
long
dateValue
)
{
return
getMillis
(
tz
,
yearFromDateValue
(
dateValue
),
monthFromDateValue
(
dateValue
),
dayFromDateValue
(
dateValue
),
0
,
0
,
0
,
0
);
}
/**
* Convert an encoded date-time value to millis, using the supplied timezone.
*
...
...
@@ -1070,9 +1062,13 @@ public class DateTimeUtils {
* @return the date value
*/
public
static
long
dateValueFromDate
(
long
ms
)
{
Calendar
cal
=
getCalendar
();
cal
.
setTimeInMillis
(
ms
);
return
dateValueFromCalendar
(
cal
);
ms
+=
getTimeZone
().
getOffset
(
ms
);
long
absoluteDay
=
ms
/
MILLIS_PER_DAY
;
// Round toward negative infinity
if
(
ms
<
0
&&
(
absoluteDay
*
MILLIS_PER_DAY
!=
ms
))
{
absoluteDay
--;
}
return
dateValueFromAbsoluteDay
(
absoluteDay
);
}
/**
...
...
@@ -1082,10 +1078,12 @@ public class DateTimeUtils {
* @return the date value
*/
private
static
long
dateValueFromCalendar
(
Calendar
cal
)
{
int
year
,
month
,
day
;
year
=
getYear
(
cal
);
month
=
cal
.
get
(
Calendar
.
MONTH
)
+
1
;
day
=
cal
.
get
(
Calendar
.
DAY_OF_MONTH
);
int
year
=
cal
.
get
(
Calendar
.
YEAR
);
if
(
cal
.
get
(
Calendar
.
ERA
)
==
GregorianCalendar
.
BC
)
{
year
=
1
-
year
;
}
int
month
=
cal
.
get
(
Calendar
.
MONTH
)
+
1
;
int
day
=
cal
.
get
(
Calendar
.
DAY_OF_MONTH
);
return
((
long
)
year
<<
SHIFT_YEAR
)
|
(
month
<<
SHIFT_MONTH
)
|
day
;
}
...
...
@@ -1097,9 +1095,13 @@ public class DateTimeUtils {
* @return the nanoseconds
*/
public
static
long
nanosFromDate
(
long
ms
)
{
Calendar
cal
=
getCalendar
();
cal
.
setTimeInMillis
(
ms
);
return
nanosFromCalendar
(
cal
);
ms
+=
getTimeZone
().
getOffset
(
ms
);
long
absoluteDay
=
ms
/
MILLIS_PER_DAY
;
// Round toward negative infinity
if
(
ms
<
0
&&
(
absoluteDay
*
MILLIS_PER_DAY
!=
ms
))
{
absoluteDay
--;
}
return
(
ms
-
absoluteDay
*
MILLIS_PER_DAY
)
*
1_000_000
;
}
/**
...
...
@@ -1154,7 +1156,7 @@ public class DateTimeUtils {
m
+=
12
;
}
long
a
=
((
y
*
2922L
)
>>
3
)
+
DAYS_OFFSET
[
m
-
3
]
+
d
-
719484
;
if
(
y
<=
1582
&&
((
y
<
1582
)
||
(
m
*
100
+
d
<
10
0
5
)))
{
if
(
y
<=
1582
&&
((
y
<
1582
)
||
(
m
*
100
+
d
<
10
1
5
)))
{
// Julian calendar (cutover at 1582-10-04 / 1582-10-15)
a
+=
13
;
}
else
if
(
y
<
1901
||
y
>
2099
)
{
...
...
h2/src/main/org/h2/util/ToChar.java
浏览文件 @
9e5d9644
差异被折叠。
点击展开。
h2/src/main/org/h2/util/ToDateParser.java
浏览文件 @
9e5d9644
...
...
@@ -7,9 +7,13 @@ package org.h2.util;
import
static
java
.
lang
.
String
.
format
;
import
java.sql.Timestamp
;
import
java.util.Calendar
;
import
java.util.GregorianCalendar
;
import
java.util.List
;
import
java.util.TimeZone
;
import
org.h2.value.ValueTimestamp
;
import
org.h2.value.ValueTimestampTimeZone
;
/**
* Emulates Oracle's TO_DATE function.<br>
...
...
@@ -21,8 +25,29 @@ public class ToDateParser {
private
final
ConfigParam
functionName
;
private
String
inputStr
;
private
String
formatStr
;
private
final
Calendar
resultCalendar
=
DateTimeUtils
.
createGregorianCalendar
();
private
Integer
nanos
;
private
boolean
doyValid
=
false
,
absoluteDayValid
=
false
,
hour12Valid
=
false
,
timeZoneHMValid
=
false
;
private
boolean
bc
;
private
long
absoluteDay
;
private
int
year
,
month
,
day
=
1
;
private
int
dayOfYear
;
private
int
hour
,
minute
,
second
,
nanos
;
private
int
hour12
;
boolean
isAM
=
true
;
private
TimeZone
timeZone
;
private
int
timeZoneHour
,
timeZoneMinute
;
private
int
currentYear
,
currentMonth
;
/**
* @param input the input date with the date-time info
...
...
@@ -31,20 +56,6 @@ public class ToDateParser {
* code)
*/
private
ToDateParser
(
ConfigParam
functionName
,
String
input
,
String
format
)
{
// reset calendar - default oracle behaviour
resultCalendar
.
set
(
Calendar
.
YEAR
,
1970
);
resultCalendar
.
set
(
Calendar
.
MONTH
,
DateTimeUtils
.
createGregorianCalendar
().
get
(
Calendar
.
MONTH
));
resultCalendar
.
clear
(
Calendar
.
DAY_OF_YEAR
);
resultCalendar
.
clear
(
Calendar
.
DAY_OF_WEEK
);
resultCalendar
.
clear
(
Calendar
.
DAY_OF_WEEK_IN_MONTH
);
resultCalendar
.
set
(
Calendar
.
DAY_OF_MONTH
,
1
);
resultCalendar
.
set
(
Calendar
.
HOUR
,
0
);
resultCalendar
.
set
(
Calendar
.
HOUR_OF_DAY
,
0
);
resultCalendar
.
set
(
Calendar
.
MINUTE
,
0
);
resultCalendar
.
set
(
Calendar
.
SECOND
,
0
);
resultCalendar
.
set
(
Calendar
.
MILLISECOND
,
0
);
resultCalendar
.
set
(
Calendar
.
AM_PM
,
Calendar
.
AM
);
this
.
functionName
=
functionName
;
inputStr
=
input
.
trim
();
// Keep a copy
...
...
@@ -59,30 +70,65 @@ public class ToDateParser {
unmodifiedFormatStr
=
formatStr
;
}
private
static
ToDateParser
get
DateParser
(
String
input
,
String
format
)
{
ToDateParser
result
=
new
ToDateParser
(
ConfigParam
.
TO_DATE
,
input
,
format
);
private
static
ToDateParser
get
TimestampParser
(
ConfigParam
param
,
String
input
,
String
format
)
{
ToDateParser
result
=
new
ToDateParser
(
param
,
input
,
format
);
parse
(
result
);
return
result
;
}
private
static
ToDateParser
getTimestampParser
(
String
input
,
String
format
)
{
ToDateParser
result
=
new
ToDateParser
(
ConfigParam
.
TO_TIMESTAMP
,
input
,
format
);
parse
(
result
);
return
result
;
}
private
Timestamp
getResultingTimestamp
()
{
Calendar
cal
=
(
Calendar
)
getResultCalendar
().
clone
();
int
nanosToSet
=
nanos
==
null
?
cal
.
get
(
Calendar
.
MILLISECOND
)
*
1000000
:
nanos
.
intValue
();
cal
.
set
(
Calendar
.
MILLISECOND
,
0
);
Timestamp
ts
=
new
Timestamp
(
cal
.
getTimeInMillis
());
ts
.
setNanos
(
nanosToSet
);
return
ts
;
private
ValueTimestamp
getResultingValue
()
{
long
dateValue
;
if
(
absoluteDayValid
)
{
dateValue
=
DateTimeUtils
.
dateValueFromAbsoluteDay
(
absoluteDay
);
}
else
{
int
year
=
this
.
year
;
if
(
year
==
0
)
{
year
=
getCurrentYear
();
}
if
(
bc
)
{
year
=
1
-
year
;
}
if
(
doyValid
)
{
dateValue
=
DateTimeUtils
.
dateValueFromAbsoluteDay
(
DateTimeUtils
.
absoluteDayFromDateValue
(
DateTimeUtils
.
dateValue
(
year
,
1
,
1
))
+
dayOfYear
-
1
);
}
else
{
int
month
=
this
.
month
;
if
(
month
==
0
)
{
// Oracle uses current month as default
month
=
getCurrentMonth
();
}
dateValue
=
DateTimeUtils
.
dateValue
(
year
,
month
,
day
);
}
}
int
hour
;
if
(
hour12Valid
)
{
hour
=
hour12
%
12
;
if
(!
isAM
)
{
hour
+=
12
;
}
}
else
{
hour
=
this
.
hour
;
}
long
timeNanos
=
((((
hour
*
60
)
+
minute
)
*
60
)
+
second
)
*
1_000_000_000L
+
nanos
;
return
ValueTimestamp
.
fromDateValueAndNanos
(
dateValue
,
timeNanos
);
}
Calendar
getResultCalendar
()
{
return
resultCalendar
;
private
ValueTimestampTimeZone
getResultingValueWithTimeZone
()
{
ValueTimestamp
ts
=
getResultingValue
();
long
dateValue
=
ts
.
getDateValue
();
short
offset
;
if
(
timeZoneHMValid
)
{
offset
=
(
short
)
(
timeZoneHour
*
60
+
((
timeZoneHour
>=
0
)
?
timeZoneMinute
:
-
timeZoneMinute
));
}
else
{
TimeZone
timeZone
=
this
.
timeZone
;
if
(
timeZone
==
null
)
{
timeZone
=
TimeZone
.
getDefault
();
}
long
millis
=
DateTimeUtils
.
convertDateTimeValueToMillis
(
timeZone
,
dateValue
,
nanos
/
1000000
);
offset
=
(
short
)
(
timeZone
.
getOffset
(
millis
)
/
1000
/
60
);
}
return
ValueTimestampTimeZone
.
fromDateValueAndNanos
(
dateValue
,
ts
.
getTimeNanos
(),
offset
);
}
String
getInputStr
()
{
...
...
@@ -97,10 +143,111 @@ public class ToDateParser {
return
functionName
.
name
();
}
private
void
queryCurrentYearAndMonth
()
{
GregorianCalendar
gc
=
DateTimeUtils
.
getCalendar
();
gc
.
setTimeInMillis
(
System
.
currentTimeMillis
());
currentYear
=
gc
.
get
(
Calendar
.
YEAR
);
currentMonth
=
gc
.
get
(
Calendar
.
MONTH
)
+
1
;
}
int
getCurrentYear
()
{
if
(
currentYear
==
0
)
{
queryCurrentYearAndMonth
();
}
return
currentYear
;
}
int
getCurrentMonth
()
{
if
(
currentMonth
==
0
)
{
queryCurrentYearAndMonth
();
}
return
currentMonth
;
}
void
setAbsoluteDay
(
int
absoluteDay
)
{
doyValid
=
false
;
absoluteDayValid
=
true
;
this
.
absoluteDay
=
absoluteDay
;
}
void
setBC
(
boolean
bc
)
{
doyValid
=
false
;
absoluteDayValid
=
false
;
this
.
bc
=
bc
;
}
void
setYear
(
int
year
)
{
doyValid
=
false
;
absoluteDayValid
=
false
;
this
.
year
=
year
;
}
void
setMonth
(
int
month
)
{
doyValid
=
false
;
absoluteDayValid
=
false
;
this
.
month
=
month
;
if
(
year
==
0
)
{
year
=
1970
;
}
}
void
setDay
(
int
day
)
{
doyValid
=
false
;
absoluteDayValid
=
false
;
this
.
day
=
day
;
if
(
year
==
0
)
{
year
=
1970
;
}
}
void
setDayOfYear
(
int
dayOfYear
)
{
doyValid
=
true
;
absoluteDayValid
=
false
;
this
.
dayOfYear
=
dayOfYear
;
}
void
setHour
(
int
hour
)
{
hour12Valid
=
false
;
this
.
hour
=
hour
;
}
void
setMinute
(
int
minute
)
{
this
.
minute
=
minute
;
}
void
setSecord
(
int
second
)
{
this
.
second
=
second
;
}
void
setNanos
(
int
nanos
)
{
this
.
nanos
=
nanos
;
}
void
setAmPm
(
boolean
isAM
)
{
hour12Valid
=
true
;
this
.
isAM
=
isAM
;
}
void
setHour12
(
int
hour12
)
{
hour12Valid
=
true
;
this
.
hour12
=
hour12
;
}
void
setTimeZone
(
TimeZone
timeZone
)
{
timeZoneHMValid
=
false
;
this
.
timeZone
=
timeZone
;
}
void
setTimeZoneHour
(
int
timeZoneHour
)
{
timeZoneHMValid
=
true
;
this
.
timeZoneHour
=
timeZoneHour
;
}
void
setTimeZoneMinute
(
int
timeZoneMinute
)
{
timeZoneHMValid
=
true
;
this
.
timeZoneMinute
=
timeZoneMinute
;
}
private
boolean
hasToParseData
()
{
return
formatStr
.
length
()
>
0
;
}
...
...
@@ -180,9 +327,21 @@ public class ToDateParser {
* @param format the format
* @return the timestamp
*/
public
static
Timestamp
toTimestamp
(
String
input
,
String
format
)
{
ToDateParser
parser
=
getTimestampParser
(
input
,
format
);
return
parser
.
getResultingTimestamp
();
public
static
ValueTimestamp
toTimestamp
(
String
input
,
String
format
)
{
ToDateParser
parser
=
getTimestampParser
(
ConfigParam
.
TO_TIMESTAMP
,
input
,
format
);
return
parser
.
getResultingValue
();
}
/**
* Parse a string as a timestamp with the given format.
*
* @param input the input
* @param format the format
* @return the timestamp
*/
public
static
ValueTimestampTimeZone
toTimestampTz
(
String
input
,
String
format
)
{
ToDateParser
parser
=
getTimestampParser
(
ConfigParam
.
TO_TIMESTAMP_TZ
,
input
,
format
);
return
parser
.
getResultingValueWithTimeZone
();
}
/**
...
...
@@ -192,9 +351,9 @@ public class ToDateParser {
* @param format the format
* @return the date as a timestamp
*/
public
static
Timestamp
toDate
(
String
input
,
String
format
)
{
ToDateParser
parser
=
get
DateParser
(
input
,
format
);
return
parser
.
getResulting
Timestamp
();
public
static
Value
Timestamp
toDate
(
String
input
,
String
format
)
{
ToDateParser
parser
=
get
TimestampParser
(
ConfigParam
.
TO_DATE
,
input
,
format
);
return
parser
.
getResulting
Value
();
}
/**
...
...
@@ -202,7 +361,8 @@ public class ToDateParser {
*/
private
enum
ConfigParam
{
TO_DATE
(
"DD MON YYYY"
),
TO_TIMESTAMP
(
"DD MON YYYY HH:MI:SS"
);
TO_TIMESTAMP
(
"DD MON YYYY HH:MI:SS"
),
TO_TIMESTAMP_TZ
(
"DD MON YYYY HH:MI:SS TZR"
);
private
final
String
defaultFormatStr
;
ConfigParam
(
String
defaultFormatStr
)
{
...
...
h2/src/main/org/h2/util/ToDateTokenizer.java
浏览文件 @
9e5d9644
差异被折叠。
点击展开。
h2/src/main/org/h2/value/Transfer.java
浏览文件 @
9e5d9644
...
...
@@ -14,7 +14,6 @@ import java.io.Reader;
import
java.math.BigDecimal
;
import
java.net.InetAddress
;
import
java.net.Socket
;
import
java.nio.charset.StandardCharsets
;
import
java.sql.ResultSet
;
import
java.sql.ResultSetMetaData
;
import
java.sql.SQLException
;
...
...
@@ -463,10 +462,6 @@ public class Transfer {
throw
DbException
.
get
(
ErrorCode
.
CONNECTION_BROKEN_1
,
"length="
+
length
);
}
if
(
length
>
Integer
.
MAX_VALUE
)
{
throw
DbException
.
get
(
ErrorCode
.
CONNECTION_BROKEN_1
,
"length="
+
length
);
}
writeLong
(
length
);
Reader
reader
=
v
.
getReader
();
Data
.
copyString
(
reader
,
out
);
...
...
@@ -652,21 +647,10 @@ public class Transfer {
return
ValueLobDb
.
create
(
Value
.
CLOB
,
session
.
getDataHandler
(),
tableId
,
id
,
hmac
,
precision
);
}
if
(
length
<
0
||
length
>
Integer
.
MAX_VALUE
)
{
if
(
length
<
0
)
{
throw
DbException
.
get
(
ErrorCode
.
CONNECTION_BROKEN_1
,
"length="
+
length
);
}
DataReader
reader
=
new
DataReader
(
in
);
int
len
=
(
int
)
length
;
char
[]
buff
=
new
char
[
len
];
IOUtils
.
readFully
(
reader
,
buff
,
len
);
int
magic
=
readInt
();
if
(
magic
!=
LOB_MAGIC
)
{
throw
DbException
.
get
(
ErrorCode
.
CONNECTION_BROKEN_1
,
"magic="
+
magic
);
}
byte
[]
small
=
new
String
(
buff
).
getBytes
(
StandardCharsets
.
UTF_8
);
return
ValueLobDb
.
createSmallLob
(
Value
.
CLOB
,
small
,
length
);
}
Value
v
=
session
.
getDataHandler
().
getLobStorage
().
createClob
(
new
DataReader
(
in
),
length
);
...
...
h2/src/main/org/h2/value/ValueLobDb.java
浏览文件 @
9e5d9644
...
...
@@ -26,6 +26,7 @@ import org.h2.store.FileStoreInputStream;
import
org.h2.store.FileStoreOutputStream
;
import
org.h2.store.LobStorageFrontend
;
import
org.h2.store.LobStorageInterface
;
import
org.h2.store.RangeReader
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.util.IOUtils
;
import
org.h2.util.MathUtils
;
...
...
@@ -544,6 +545,15 @@ public class ValueLobDb extends Value implements Value.ValueClob,
*/
public
static
ValueLobDb
createTempClob
(
Reader
in
,
long
length
,
DataHandler
handler
)
{
if
(
length
>=
0
)
{
// Otherwise BufferedReader may try to read more data than needed and that
// blocks the network level
try
{
in
=
new
RangeReader
(
in
,
0
,
length
);
}
catch
(
IOException
e
)
{
throw
DbException
.
convert
(
e
);
}
}
BufferedReader
reader
;
if
(
in
instanceof
BufferedReader
)
{
reader
=
(
BufferedReader
)
in
;
...
...
h2/src/main/org/h2/value/ValueTimestampTimeZone.java
浏览文件 @
9e5d9644
...
...
@@ -9,8 +9,6 @@ import java.math.BigDecimal;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.sql.Timestamp
;
import
java.util.SimpleTimeZone
;
import
java.util.TimeZone
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.TimestampWithTimeZone
;
import
org.h2.message.DbException
;
...
...
@@ -148,19 +146,6 @@ public class ValueTimestampTimeZone extends Value {
return
timeZoneOffsetMins
;
}
/**
* Returns compatible offset-based time zone with no DST schedule.
*
* @return compatible offset-based time zone
*/
public
TimeZone
getTimeZone
()
{
int
offset
=
timeZoneOffsetMins
;
if
(
offset
==
0
)
{
return
DateTimeUtils
.
UTC
;
}
return
new
SimpleTimeZone
(
offset
*
60000
,
Integer
.
toString
(
offset
));
}
@Override
public
Timestamp
getTimestamp
()
{
throw
new
UnsupportedOperationException
(
"unimplemented"
);
...
...
@@ -219,34 +204,31 @@ public class ValueTimestampTimeZone extends Value {
@Override
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueTimestampTimeZone
t
=
(
ValueTimestampTimeZone
)
o
;
//
We are pretending that the dateValue is in UTC because that gives us
// a
stable sort even if the DST database changes.
// convert to minutes and add timezone offset
long
a
=
DateTimeUtils
.
convertDateValueToMillis
(
DateTimeUtils
.
UTC
,
dateValue
)
/
(
1000L
*
60L
)
;
long
ma
=
timeNanos
/
(
1000L
*
1000L
*
1000L
*
60L
);
a
+=
ma
;
a
-=
timeZoneOffsetMins
;
// convert to minutes and add timezone offset
long
b
=
DateTimeUtils
.
convertDateValueToMillis
(
DateTimeUtils
.
UTC
,
t
.
dateValue
)
/
(
1000L
*
60L
)
;
long
mb
=
t
.
timeNanos
/
(
1000L
*
1000L
*
1000L
*
60L
)
;
b
+=
mb
;
b
-=
t
.
timeZoneOffsetMins
;
// compare date
int
c
=
Long
.
compare
(
a
,
b
);
if
(
c
!=
0
)
{
return
c
;
//
Maximum time zone offset is +/-18 hours so difference in days between local
// a
nd UTC cannot be more than one day
long
daysA
=
DateTimeUtils
.
absoluteDayFromDateValue
(
dateValue
);
long
timeA
=
timeNanos
-
timeZoneOffsetMins
*
60_000_000_000L
;
if
(
timeA
<
0
)
{
timeA
+=
DateTimeUtils
.
NANOS_PER_DAY
;
daysA
--
;
}
else
if
(
timeA
>=
DateTimeUtils
.
NANOS_PER_DAY
)
{
timeA
-=
DateTimeUtils
.
NANOS_PER_DAY
;
daysA
++
;
}
long
daysB
=
DateTimeUtils
.
absoluteDayFromDateValue
(
t
.
dateValue
);
long
timeB
=
t
.
timeNanos
-
t
.
timeZoneOffsetMins
*
60_000_000_000L
;
if
(
timeB
<
0
)
{
timeB
+=
DateTimeUtils
.
NANOS_PER_DAY
;
daysB
--
;
}
else
if
(
timeB
>=
DateTimeUtils
.
NANOS_PER_DAY
)
{
timeB
-=
DateTimeUtils
.
NANOS_PER_DAY
;
daysB
++;
}
int
c
mp
=
Long
.
compare
(
daysA
,
daysB
);
if
(
c
mp
!=
0
)
{
return
c
mp
;
}
// compare time
long
na
=
timeNanos
-
(
ma
*
1000L
*
1000L
*
1000L
*
60L
);
long
nb
=
t
.
timeNanos
-
(
mb
*
1000L
*
1000L
*
1000L
*
60L
);
return
Long
.
compare
(
na
,
nb
);
return
Long
.
compare
(
timeA
,
timeB
);
}
@Override
...
...
h2/src/test/org/h2/test/TestBase.java
浏览文件 @
9e5d9644
...
...
@@ -6,6 +6,7 @@
package
org
.
h2
.
test
;
import
java.io.ByteArrayInputStream
;
import
java.io.File
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.io.InputStream
;
...
...
@@ -30,7 +31,9 @@ import java.sql.Types;
import
java.text.DateFormat
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.SimpleTimeZone
;
import
java.util.concurrent.TimeUnit
;
...
...
@@ -40,6 +43,7 @@ import org.h2.store.fs.FilePath;
import
org.h2.store.fs.FileUtils
;
import
org.h2.test.utils.ProxyCodeGenerator
;
import
org.h2.test.utils.ResultVerifier
;
import
org.h2.test.utils.SelfDestructor
;
import
org.h2.tools.DeleteDbFiles
;
/**
...
...
@@ -466,16 +470,16 @@ public abstract class TestBase {
throw
new
AssertionError
(
string
);
}
/**
* Log an error message.
*
* @param s the message
*/
public
static
void
logErrorMessage
(
String
s
)
{
System
.
out
.
flush
();
System
.
err
.
println
(
"ERROR: "
+
s
+
"------------------------------"
);
logThrowable
(
s
,
null
);
}
/**
* Log an error message.
*
* @param s the message
*/
public
static
void
logErrorMessage
(
String
s
)
{
System
.
out
.
flush
();
System
.
err
.
println
(
"ERROR: "
+
s
+
"------------------------------"
);
logThrowable
(
s
,
null
);
}
/**
* Log an error message.
...
...
@@ -1444,6 +1448,16 @@ public abstract class TestBase {
return
System
.
getProperty
(
"java.class.path"
);
}
/**
* Get the path to a java executable of the current process
*
* @return the path to java
*/
private
String
getJVM
()
{
return
System
.
getProperty
(
"java.home"
)
+
File
.
separatorChar
+
"bin"
+
File
.
separator
+
"java"
;
}
/**
* Use up almost all memory.
*
...
...
@@ -1687,4 +1701,46 @@ public abstract class TestBase {
return
getClass
().
getSimpleName
();
}
public
ProcessBuilder
buildChild
(
String
name
,
Class
<?
extends
TestBase
>
childClass
,
String
...
jvmArgs
)
{
List
<
String
>
args
=
new
ArrayList
<>(
16
);
args
.
add
(
getJVM
());
Collections
.
addAll
(
args
,
jvmArgs
);
Collections
.
addAll
(
args
,
"-cp"
,
getClassPath
(),
SelfDestructor
.
getPropertyString
(
1
),
childClass
.
getName
(),
"-url"
,
getURL
(
name
,
true
),
"-user"
,
getUser
(),
"-password"
,
getPassword
());
ProcessBuilder
processBuilder
=
new
ProcessBuilder
()
// .redirectError(ProcessBuilder.Redirect.INHERIT)
.
redirectErrorStream
(
true
)
.
redirectOutput
(
ProcessBuilder
.
Redirect
.
INHERIT
)
.
command
(
args
);
return
processBuilder
;
}
public
abstract
static
class
Child
extends
TestBase
{
private
String
url
;
private
String
user
;
private
String
password
;
public
Child
(
String
...
args
)
{
for
(
int
i
=
0
;
i
<
args
.
length
;
i
++)
{
if
(
"-url"
.
equals
(
args
[
i
]))
{
url
=
args
[++
i
];
}
else
if
(
"-user"
.
equals
(
args
[
i
]))
{
user
=
args
[++
i
];
}
else
if
(
"-password"
.
equals
(
args
[
i
]))
{
password
=
args
[++
i
];
}
SelfDestructor
.
startCountdown
(
60
);
}
}
public
Connection
getConnection
()
throws
SQLException
{
return
getConnection
(
url
,
user
,
password
);
}
}
}
h2/src/test/org/h2/test/db/TestFunctions.java
浏览文件 @
9e5d9644
差异被折叠。
点击展开。
h2/src/test/org/h2/test/db/TestOutOfMemory.java
浏览文件 @
9e5d9644
...
...
@@ -15,7 +15,6 @@ import java.util.Map;
import
java.util.Random
;
import
java.util.concurrent.atomic.AtomicReference
;
import
org.h2.api.ErrorCode
;
import
org.h2.message.DbException
;
import
org.h2.mvstore.MVStore
;
import
org.h2.store.fs.FilePath
;
import
org.h2.store.fs.FilePathMem
;
...
...
@@ -28,6 +27,8 @@ import org.h2.test.TestBase;
*/
public
class
TestOutOfMemory
extends
TestBase
{
private
static
final
String
DB_NAME
=
"outOfMemory"
;
/**
* Run just this test.
*
...
...
@@ -38,16 +39,18 @@ public class TestOutOfMemory extends TestBase {
}
@Override
public
void
test
()
throws
SQLException
,
Interrupted
Exception
{
public
void
test
()
throws
Exception
{
if
(
config
.
vmlens
)
{
// running out of memory will cause the vmlens agent to stop working
return
;
}
try
{
System
.
gc
();
testMVStoreUsingInMemoryFileSystem
();
System
.
gc
();
testDatabaseUsingInMemoryFileSystem
();
if
(!
config
.
travis
)
{
System
.
gc
();
testMVStoreUsingInMemoryFileSystem
();
System
.
gc
();
testDatabaseUsingInMemoryFileSystem
();
}
System
.
gc
();
testUpdateWhenNearlyOutOfMemory
();
}
finally
{
...
...
@@ -147,67 +150,92 @@ public class TestOutOfMemory extends TestBase {
}
}
private
void
testUpdateWhenNearlyOutOfMemory
()
throws
SQLException
,
Interrupted
Exception
{
private
void
testUpdateWhenNearlyOutOfMemory
()
throws
Exception
{
if
(
config
.
memory
)
{
return
;
}
recoverAfterOOM
();
deleteDb
(
"outOfMemory"
);
Connection
conn
=
getConnection
(
"outOfMemory;MAX_OPERATION_MEMORY=1000000"
);
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"drop all objects"
);
stat
.
execute
(
"create table stuff (id int, text varchar as space(100) || id)"
);
stat
.
execute
(
"insert into stuff(id) select x from system_range(1, 3000)"
);
PreparedStatement
prep
=
conn
.
prepareStatement
(
"update stuff set text = text || space(1000) || id"
);
prep
.
execute
();
stat
.
execute
(
"checkpoint"
);
eatMemory
(
80
);
try
{
try
{
prep
.
execute
();
fail
();
}
catch
(
DbException
ex
)
{
freeMemory
();
assertTrue
(
ErrorCode
.
OUT_OF_MEMORY
==
ex
.
getErrorCode
()
||
ErrorCode
.
GENERAL_ERROR_1
==
ex
.
getErrorCode
());
}
catch
(
SQLException
ex
)
{
freeMemory
();
assertTrue
(
ErrorCode
.
OUT_OF_MEMORY
==
ex
.
getErrorCode
()
||
ErrorCode
.
GENERAL_ERROR_1
==
ex
.
getErrorCode
());
}
recoverAfterOOM
();
try
{
conn
.
close
();
fail
();
}
catch
(
DbException
ex
)
{
freeMemory
();
assertEquals
(
ErrorCode
.
DATABASE_IS_CLOSED
,
ex
.
getErrorCode
());
}
catch
(
SQLException
ex
)
{
freeMemory
();
assertEquals
(
ErrorCode
.
DATABASE_IS_CLOSED
,
ex
.
getErrorCode
());
deleteDb
(
DB_NAME
);
ProcessBuilder
processBuilder
=
buildChild
(
DB_NAME
+
";MAX_OPERATION_MEMORY=1000000"
,
MyChild
.
class
,
"-XX:+UseParallelGC"
,
// "-XX:+UseG1GC",
"-Xmx128m"
);
//*
processBuilder
.
start
().
waitFor
();
/*/
List<String> args = processBuilder.command();
for (Iterator<String> iter = args.iterator(); iter.hasNext(); ) {
String arg = iter.next();
if(arg.equals(MyChild.class.getName())) {
iter.remove();
break;
}
freeMemory
();
conn
=
null
;
conn
=
getConnection
(
"outOfMemory"
);
stat
=
conn
.
createStatement
();
ResultSet
rs
=
stat
.
executeQuery
(
"select count(*) from stuff"
);
rs
.
next
();
iter.remove();
}
MyChild.main(args.toArray(new String[0]));
//*/
try
(
Connection
conn
=
getConnection
(
DB_NAME
))
{
Statement
stat
=
conn
.
createStatement
();
ResultSet
rs
=
stat
.
executeQuery
(
"SELECT count(*) FROM stuff"
);
assertTrue
(
rs
.
next
());
assertEquals
(
3000
,
rs
.
getInt
(
1
));
}
catch
(
OutOfMemoryError
e
)
{
freeMemory
();
// out of memory not detected
throw
new
AssertionError
(
"Out of memory not detected"
,
e
);
}
finally
{
freeMemory
();
if
(
conn
!=
null
)
{
try
{
conn
.
close
();
}
catch
(
SQLException
e
)
{
// out of memory will / may close the database
assertKnownException
(
e
);
}
rs
=
stat
.
executeQuery
(
"SELECT * FROM stuff WHERE id = 3000"
);
assertTrue
(
rs
.
next
());
String
text
=
rs
.
getString
(
2
);
assertFalse
(
rs
.
wasNull
());
assertEquals
(
1004
,
text
.
length
());
// TODO: there are intermittent failures here
// where number is about 1000 short of expected value.
// This indicates a real problem - durability failure
// and need to be looked at.
rs
=
stat
.
executeQuery
(
"SELECT sum(length(text)) FROM stuff"
);
assertTrue
(
rs
.
next
());
int
totalSize
=
rs
.
getInt
(
1
);
if
(
3010893
>
totalSize
)
{
TestBase
.
logErrorMessage
(
"Durability failure - expected: 3010893, actual: "
+
totalSize
);
}
}
finally
{
deleteDb
(
DB_NAME
);
}
deleteDb
(
"outOfMemory"
);
}
public
static
final
class
MyChild
extends
TestBase
.
Child
{
public
static
void
main
(
String
...
args
)
throws
Exception
{
new
MyChild
(
args
).
init
().
test
();
}
private
MyChild
(
String
...
args
)
{
super
(
args
);
}
@Override
public
void
test
()
{
try
(
Connection
conn
=
getConnection
())
{
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"DROP ALL OBJECTS"
);
stat
.
execute
(
"CREATE TABLE stuff (id INT, text VARCHAR)"
);
stat
.
execute
(
"INSERT INTO stuff(id) SELECT x FROM system_range(1, 3000)"
);
PreparedStatement
prep
=
conn
.
prepareStatement
(
"UPDATE stuff SET text = IFNULL(text,'') || space(1000) || id"
);
prep
.
execute
();
stat
.
execute
(
"CHECKPOINT"
);
ResultSet
rs
=
stat
.
executeQuery
(
"SELECT sum(length(text)) FROM stuff"
);
assertTrue
(
rs
.
next
());
assertEquals
(
3010893
,
rs
.
getInt
(
1
));
eatMemory
(
80
);
prep
.
execute
();
fail
();
}
catch
(
SQLException
ignore
)
{
}
finally
{
freeMemory
();
}
}
}
}
h2/src/test/org/h2/test/jdbc/TestLobApi.java
浏览文件 @
9e5d9644
...
...
@@ -119,7 +119,20 @@ public class TestLobApi extends TestBase {
prep
.
setString
(
1
,
""
);
prep
.
setBytes
(
2
,
new
byte
[
0
]);
prep
.
execute
();
Random
r
=
new
Random
(
1
);
char
[]
charsSmall
=
new
char
[
20
];
for
(
int
i
=
0
;
i
<
charsSmall
.
length
;
i
++)
{
charsSmall
[
i
]
=
(
char
)
r
.
nextInt
(
10000
);
}
String
dSmall
=
new
String
(
charsSmall
);
prep
.
setCharacterStream
(
1
,
new
StringReader
(
dSmall
),
-
1
);
byte
[]
bytesSmall
=
new
byte
[
20
];
r
.
nextBytes
(
bytesSmall
);
prep
.
setBinaryStream
(
2
,
new
ByteArrayInputStream
(
bytesSmall
),
-
1
);
prep
.
execute
();
char
[]
chars
=
new
char
[
100000
];
for
(
int
i
=
0
;
i
<
chars
.
length
;
i
++)
{
chars
[
i
]
=
(
char
)
r
.
nextInt
(
10000
);
...
...
@@ -130,6 +143,7 @@ public class TestLobApi extends TestBase {
r
.
nextBytes
(
bytes
);
prep
.
setBinaryStream
(
2
,
new
ByteArrayInputStream
(
bytes
),
-
1
);
prep
.
execute
();
conn
.
setAutoCommit
(
false
);
ResultSet
rs
=
stat
.
executeQuery
(
"select * from test order by id"
);
rs
.
next
();
...
...
@@ -138,18 +152,27 @@ public class TestLobApi extends TestBase {
rs
.
next
();
Clob
c2
=
rs
.
getClob
(
2
);
Blob
b2
=
rs
.
getBlob
(
3
);
rs
.
next
();
Clob
c3
=
rs
.
getClob
(
2
);
Blob
b3
=
rs
.
getBlob
(
3
);
assertFalse
(
rs
.
next
());
// now close
rs
.
close
();
// but the LOBs must stay open
assertEquals
(
0
,
c1
.
length
());
assertEquals
(
0
,
b1
.
length
());
assertEquals
(
chars
.
length
,
c2
.
length
());
assertEquals
(
bytes
.
length
,
b2
.
length
());
assertEquals
(
""
,
c1
.
getSubString
(
1
,
0
));
assertEquals
(
new
byte
[
0
],
b1
.
getBytes
(
1
,
0
));
assertEquals
(
d
,
c2
.
getSubString
(
1
,
(
int
)
c2
.
length
()));
assertEquals
(
bytes
,
b2
.
getBytes
(
1
,
(
int
)
b2
.
length
()));
assertEquals
(
charsSmall
.
length
,
c2
.
length
());
assertEquals
(
bytesSmall
.
length
,
b2
.
length
());
assertEquals
(
dSmall
,
c2
.
getSubString
(
1
,
(
int
)
c2
.
length
()));
assertEquals
(
bytesSmall
,
b2
.
getBytes
(
1
,
(
int
)
b2
.
length
()));
assertEquals
(
chars
.
length
,
c3
.
length
());
assertEquals
(
bytes
.
length
,
b3
.
length
());
assertEquals
(
d
,
c3
.
getSubString
(
1
,
(
int
)
c3
.
length
()));
assertEquals
(
bytes
,
b3
.
getBytes
(
1
,
(
int
)
b3
.
length
()));
stat
.
execute
(
"drop table test"
);
conn
.
close
();
}
...
...
h2/src/test/org/h2/test/scripts/TestScript.java
浏览文件 @
9e5d9644
...
...
@@ -92,7 +92,7 @@ public class TestScript extends TestBase {
}
else
{
decimal2
=
"decimal_numeric"
;
}
for
(
String
s
:
new
String
[]
{
"array"
,
"bigint"
,
"binary"
,
"blob"
,
"boolean"
,
"char"
,
"clob"
,
"date"
,
"decimal"
,
decimal2
,
"double"
,
"enum"
,
"geometry"
,
"identity"
,
"int"
,
"other"
,
"real"
,
"smallint"
,
...
...
h2/src/test/org/h2/test/scripts/functions/timeanddate/dateadd.sql
浏览文件 @
9e5d9644
...
...
@@ -105,6 +105,18 @@ call dateadd('MS', 1, TIMESTAMP '2001-02-03 04:05:06.789001');
>
2001
-
02
-
03
04
:
05
:
06
.
790001
>
rows
:
1
SELECT
DATEADD
(
'MICROSECOND'
,
1
,
TIME
'10:00:01'
),
DATEADD
(
'MCS'
,
1
,
TIMESTAMP
'2010-10-20 10:00:01.1'
);
>
TIME
'10:00:01.000001'
TIMESTAMP
'2010-10-20 10:00:01.100001'
>
---------------------- --------------------------------------
>
10
:
00
:
01
.
000001
2010
-
10
-
20
10
:
00
:
01
.
100001
>
rows
:
1
SELECT
DATEADD
(
'NANOSECOND'
,
1
,
TIME
'10:00:01'
),
DATEADD
(
'NS'
,
1
,
TIMESTAMP
'2010-10-20 10:00:01.1'
);
>
TIME
'10:00:01.000000001'
TIMESTAMP
'2010-10-20 10:00:01.100000001'
>
------------------------- -----------------------------------------
>
10
:
00
:
01
.
000000001
2010
-
10
-
20
10
:
00
:
01
.
100000001
>
rows
:
1
SELECT
DATEADD
(
'HOUR'
,
1
,
DATE
'2010-01-20'
);
>
TIMESTAMP
'2010-01-20 01:00:00.0'
>
---------------------------------
...
...
h2/src/test/org/h2/test/scripts/functions/timeanddate/datediff.sql
浏览文件 @
9e5d9644
...
...
@@ -159,6 +159,22 @@ call datediff('MS', TIMESTAMP '1900-01-01 00:00:01.000', TIMESTAMP '2008-01-01 0
>
3408134399000
>
rows
:
1
SELECT
DATEDIFF
(
'MICROSECOND'
,
'2006-01-01 00:00:00.0000000'
,
'2006-01-01 00:00:00.123456789'
),
DATEDIFF
(
'MCS'
,
'2006-01-01 00:00:00.0000000'
,
'2006-01-01 00:00:00.123456789'
),
DATEDIFF
(
'MCS'
,
'2006-01-01 00:00:00.0000000'
,
'2006-01-02 00:00:00.123456789'
);
>
123456
123456
86400123456
>
------ ------ -----------
>
123456
123456
86400123456
>
rows
:
1
SELECT
DATEDIFF
(
'NANOSECOND'
,
'2006-01-01 00:00:00.0000000'
,
'2006-01-01 00:00:00.123456789'
),
DATEDIFF
(
'NS'
,
'2006-01-01 00:00:00.0000000'
,
'2006-01-01 00:00:00.123456789'
),
DATEDIFF
(
'NS'
,
'2006-01-01 00:00:00.0000000'
,
'2006-01-02 00:00:00.123456789'
);
>
123456789
123456789
86400123456789
>
--------- --------- --------------
>
123456789
123456789
86400123456789
>
rows
:
1
SELECT
DATEDIFF
(
'WEEK'
,
DATE
'2018-02-02'
,
DATE
'2018-02-03'
),
DATEDIFF
(
'ISO_WEEK'
,
DATE
'2018-02-02'
,
DATE
'2018-02-03'
);
>
0
0
>
-
-
...
...
h2/src/test/org/h2/test/scripts/functions/timeanddate/extract.sql
浏览文件 @
9e5d9644
...
...
@@ -3,6 +3,20 @@
-- Initial Developer: H2 Group
--
SELECT
EXTRACT
(
MICROSECOND
FROM
TIME
'10:00:00.123456789'
),
EXTRACT
(
MCS
FROM
TIMESTAMP
'2015-01-01 11:22:33.987654321'
);
>
123456
987654
>
------ ------
>
123456
987654
>
rows
:
1
SELECT
EXTRACT
(
NANOSECOND
FROM
TIME
'10:00:00.123456789'
),
EXTRACT
(
NS
FROM
TIMESTAMP
'2015-01-01 11:22:33.987654321'
);
>
123456789
987654321
>
--------- ---------
>
123456789
987654321
>
rows
:
1
select
EXTRACT
(
EPOCH
from
time
'00:00:00'
);
>
0
...
...
h2/src/test/org/h2/test/store/TestMVStoreBenchmark.java
浏览文件 @
9e5d9644
...
...
@@ -124,14 +124,6 @@ public class TestMVStoreBenchmark extends TestBase {
}
static
long
getMemory
()
{
try
{
LinkedList
<
byte
[]>
list
=
new
LinkedList
<>();
while
(
true
)
{
list
.
add
(
new
byte
[
1024
]);
}
}
catch
(
OutOfMemoryError
e
)
{
// ok
}
for
(
int
i
=
0
;
i
<
16
;
i
++)
{
System
.
gc
();
try
{
...
...
h2/src/test/org/h2/test/synth/TestFuzzOptimizations.java
浏览文件 @
9e5d9644
...
...
@@ -10,6 +10,7 @@ import java.sql.PreparedStatement;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Random
;
...
...
@@ -107,33 +108,37 @@ public class TestFuzzOptimizations extends TestBase {
ArrayList
<
String
>
params
=
New
.
arrayList
();
String
condition
=
getRandomCondition
(
random
,
params
,
columns
,
compares
,
values
);
// System.out.println(condition + " " + params);
PreparedStatement
prep0
=
conn
.
prepareStatement
(
"select * from test0 where "
+
condition
+
" order by 1, 2, 3"
);
PreparedStatement
prep1
=
conn
.
prepareStatement
(
"select * from test1 where "
+
condition
+
" order by 1, 2, 3"
);
for
(
int
j
=
0
;
j
<
params
.
size
();
j
++)
{
prep0
.
setString
(
j
+
1
,
params
.
get
(
j
));
prep1
.
setString
(
j
+
1
,
params
.
get
(
j
));
}
ResultSet
rs0
=
prep0
.
executeQuery
();
ResultSet
rs1
=
prep1
.
executeQuery
();
assertEquals
(
"seed: "
+
seed
+
" "
+
condition
,
rs0
,
rs1
);
String
message
=
"seed: "
+
seed
+
" "
+
condition
;
executeAndCompare
(
condition
,
params
,
message
);
if
(
params
.
size
()
>
0
)
{
for
(
int
j
=
0
;
j
<
params
.
size
();
j
++)
{
String
value
=
values
[
random
.
nextInt
(
values
.
length
-
2
)];
params
.
set
(
j
,
value
);
prep0
.
setString
(
j
+
1
,
value
);
prep1
.
setString
(
j
+
1
,
value
);
}
assertEquals
(
"seed: "
+
seed
+
" "
+
condition
,
rs0
,
rs1
);
executeAndCompare
(
condition
,
params
,
message
);
}
}
executeAndCompare
(
"a >=0 and b in(?, 2) and a in(1, ?, null)"
,
Arrays
.
asList
(
"10"
,
"2"
),
"seed=-6191135606105920350L"
);
db
.
execute
(
"drop table test0, test1"
);
}
private
void
executeAndCompare
(
String
condition
,
List
<
String
>
params
,
String
message
)
throws
SQLException
{
PreparedStatement
prep0
=
conn
.
prepareStatement
(
"select * from test0 where "
+
condition
+
" order by 1, 2, 3"
);
PreparedStatement
prep1
=
conn
.
prepareStatement
(
"select * from test1 where "
+
condition
+
" order by 1, 2, 3"
);
for
(
int
j
=
0
;
j
<
params
.
size
();
j
++)
{
prep0
.
setString
(
j
+
1
,
params
.
get
(
j
));
prep1
.
setString
(
j
+
1
,
params
.
get
(
j
));
}
ResultSet
rs0
=
prep0
.
executeQuery
();
ResultSet
rs1
=
prep1
.
executeQuery
();
assertEquals
(
message
,
rs0
,
rs1
);
}
private
String
getRandomCondition
(
Random
random
,
ArrayList
<
String
>
params
,
String
[]
columns
,
String
[]
compares
,
String
[]
values
)
{
int
comp
=
1
+
random
.
nextInt
(
4
);
...
...
h2/src/test/org/h2/test/unit/TestClearReferences.java
浏览文件 @
9e5d9644
...
...
@@ -26,6 +26,7 @@ public class TestClearReferences extends TestBase {
"org.h2.compress.CompressLZF.cachedHashTable"
,
"org.h2.engine.DbSettings.defaultSettings"
,
"org.h2.engine.SessionRemote.sessionFactory"
,
"org.h2.expression.Function.MONTHS_AND_WEEKS"
,
"org.h2.jdbcx.JdbcDataSourceFactory.cachedTraceSystem"
,
"org.h2.store.RecoverTester.instance"
,
"org.h2.store.fs.FilePath.defaultProvider"
,
...
...
@@ -36,6 +37,7 @@ public class TestClearReferences extends TestBase {
"org.h2.tools.CompressTool.cachedBuffer"
,
"org.h2.util.CloseWatcher.queue"
,
"org.h2.util.CloseWatcher.refs"
,
"org.h2.util.DateTimeUtils.timeZone"
,
"org.h2.util.MathUtils.cachedSecureRandom"
,
"org.h2.util.NetUtils.cachedLocalAddress"
,
"org.h2.util.StringUtils.softCache"
,
...
...
@@ -43,6 +45,7 @@ public class TestClearReferences extends TestBase {
"org.h2.util.JdbcUtils.allowedClassNamePrefixes"
,
"org.h2.util.JdbcUtils.userClassFactories"
,
"org.h2.util.Task.counter"
,
"org.h2.util.ToChar.NAMES"
,
"org.h2.value.CompareMode.lastUsed"
,
"org.h2.value.Value.softCache"
,
};
...
...
h2/src/test/org/h2/test/unit/TestDateTimeUtils.java
浏览文件 @
9e5d9644
...
...
@@ -5,13 +5,16 @@
*/
package
org
.
h2
.
test
.
unit
;
import
static
org
.
h2
.
util
.
DateTimeUtils
.
dateValue
;
import
java.sql.Timestamp
;
import
java.util.Calendar
;
import
java.util.GregorianCalendar
;
import
java.util.TimeZone
;
import
org.h2.test.TestBase
;
import
org.h2.util.DateTimeUtils
;
import
static
org
.
h2
.
util
.
DateTimeUtils
.
dateValue
;
import
org.h2.value.ValueTimestamp
;
/**
* Unit tests for the DateTimeUtils class
...
...
@@ -21,9 +24,18 @@ public class TestDateTimeUtils extends TestBase {
/**
* Run just this test.
*
* @param a ignored
* @param a
* if {@code "testUtc2Value"} only {@link #testUTC2Value(boolean)}
* will be executed with all time zones (slow). Otherwise all tests
* in this test unit will be executed with local time zone.
*/
public
static
void
main
(
String
...
a
)
throws
Exception
{
if
(
a
.
length
==
1
)
{
if
(
"testUtc2Value"
.
equals
(
a
[
0
]))
{
new
TestDateTimeUtils
().
testUTC2Value
(
true
);
return
;
}
}
TestBase
.
createCaller
().
init
().
test
();
}
...
...
@@ -33,6 +45,7 @@ public class TestDateTimeUtils extends TestBase {
testDayOfWeek
();
testWeekOfYear
();
testDateValueFromDenormalizedDate
();
testUTC2Value
(
false
);
}
private
void
testParseTimeNanosDB2Format
()
{
...
...
@@ -44,7 +57,7 @@ public class TestDateTimeUtils extends TestBase {
}
/**
* Test for {@link DateTimeUtils#getSundayDayOfWeek()} and
* Test for {@link DateTimeUtils#getSundayDayOfWeek(
long
)} and
* {@link DateTimeUtils#getIsoDayOfWeek(long)}.
*/
private
void
testDayOfWeek
()
{
...
...
@@ -106,4 +119,45 @@ public class TestDateTimeUtils extends TestBase {
assertEquals
(
dateValue
(-
100
,
2
,
29
),
DateTimeUtils
.
dateValueFromDenormalizedDate
(-
100
,
2
,
30
));
}
private
void
testUTC2Value
(
boolean
allTimeZones
)
{
TimeZone
def
=
TimeZone
.
getDefault
();
GregorianCalendar
gc
=
new
GregorianCalendar
();
if
(
allTimeZones
)
{
try
{
for
(
String
id
:
TimeZone
.
getAvailableIDs
())
{
System
.
out
.
println
(
id
);
TimeZone
tz
=
TimeZone
.
getTimeZone
(
id
);
TimeZone
.
setDefault
(
tz
);
DateTimeUtils
.
resetCalendar
();
testUTC2ValueImpl
(
tz
,
gc
);
}
}
finally
{
TimeZone
.
setDefault
(
def
);
DateTimeUtils
.
resetCalendar
();
}
}
else
{
testUTC2ValueImpl
(
def
,
gc
);
}
}
private
void
testUTC2ValueImpl
(
TimeZone
tz
,
GregorianCalendar
gc
)
{
gc
.
setTimeZone
(
tz
);
gc
.
set
(
Calendar
.
MILLISECOND
,
0
);
long
absoluteStart
=
DateTimeUtils
.
absoluteDayFromDateValue
(
DateTimeUtils
.
dateValue
(
1950
,
01
,
01
));
long
absoluteEnd
=
DateTimeUtils
.
absoluteDayFromDateValue
(
DateTimeUtils
.
dateValue
(
2050
,
01
,
01
));
for
(
long
i
=
absoluteStart
;
i
<
absoluteEnd
;
i
++)
{
long
dateValue
=
DateTimeUtils
.
dateValueFromAbsoluteDay
(
i
);
int
year
=
DateTimeUtils
.
yearFromDateValue
(
dateValue
);
int
month
=
DateTimeUtils
.
monthFromDateValue
(
dateValue
);
int
day
=
DateTimeUtils
.
dayFromDateValue
(
dateValue
);
for
(
int
j
=
0
;
j
<
48
;
j
++)
{
gc
.
set
(
year
,
month
-
1
,
day
,
j
/
2
,
(
j
&
1
)
*
30
,
0
);
long
timeMillis
=
gc
.
getTimeInMillis
();
ValueTimestamp
ts
=
DateTimeUtils
.
convertTimestamp
(
new
Timestamp
(
timeMillis
),
gc
);
assertEquals
(
ts
.
getDateValue
(),
DateTimeUtils
.
dateValueFromDate
(
timeMillis
));
assertEquals
(
ts
.
getTimeNanos
(),
DateTimeUtils
.
nanosFromDate
(
timeMillis
));
}
}
}
}
h2/src/test/org/h2/test/unit/TestTimeStampWithTimeZone.java
浏览文件 @
9e5d9644
...
...
@@ -126,21 +126,27 @@ public class TestTimeStampWithTimeZone extends TestBase {
ValueTimestampTimeZone
a
=
ValueTimestampTimeZone
.
parse
(
"1970-01-01 12:00:00.00+00:15"
);
ValueTimestampTimeZone
b
=
ValueTimestampTimeZone
.
parse
(
"1970-01-01 12:00:01.00+01:15"
);
int
c
=
a
.
compareTo
(
b
,
null
);
assertEquals
(
c
,
1
);
assertEquals
(
1
,
c
);
c
=
b
.
compareTo
(
a
,
null
);
assertEquals
(-
1
,
c
);
}
private
void
test3
()
{
ValueTimestampTimeZone
a
=
ValueTimestampTimeZone
.
parse
(
"1970-01-02 00:00:02.00+01:15"
);
ValueTimestampTimeZone
b
=
ValueTimestampTimeZone
.
parse
(
"1970-01-01 23:00:01.00+00:15"
);
int
c
=
a
.
compareTo
(
b
,
null
);
assertEquals
(
c
,
1
);
assertEquals
(
1
,
c
);
c
=
b
.
compareTo
(
a
,
null
);
assertEquals
(-
1
,
c
);
}
private
void
test4
()
{
ValueTimestampTimeZone
a
=
ValueTimestampTimeZone
.
parse
(
"1970-01-02 00:00:01.00+01:15"
);
ValueTimestampTimeZone
b
=
ValueTimestampTimeZone
.
parse
(
"1970-01-01 23:00:01.00+00:15"
);
int
c
=
a
.
compareTo
(
b
,
null
);
assertEquals
(
c
,
0
);
assertEquals
(
0
,
c
);
c
=
b
.
compareTo
(
a
,
null
);
assertEquals
(
0
,
c
);
}
private
void
test5
()
throws
SQLException
{
...
...
h2/src/tools/org/h2/build/doc/dictionary.txt
浏览文件 @
9e5d9644
...
...
@@ -764,5 +764,5 @@ mdy destfile hclf forbids spellchecking selfdestruct expects accident jacocoagen
jacoco xdata invokes sourcefiles classfiles duplication crypto stacktraces prt directions handled overly asm hardcoded
interpolated thead
die weekdiff osx subprocess dow proleptic
die weekdiff osx subprocess dow proleptic
microsecond microseconds divisible cmp denormalized suppressed saturated mcs
london
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论