Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
fc67a911
Unverified
提交
fc67a911
authored
2月 06, 2018
作者:
ScaY
提交者:
GitHub
2月 06, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into scay-issue#832
上级
7fed46d6
0200afe4
隐藏空白字符变更
内嵌
并排
正在显示
17 个修改的文件
包含
1255 行增加
和
109 行删除
+1255
-109
help.csv
h2/src/docsrc/help/help.csv
+15
-2
Select.java
h2/src/main/org/h2/command/dml/Select.java
+1
-1
Aggregate.java
h2/src/main/org/h2/expression/Aggregate.java
+22
-3
AggregateData.java
h2/src/main/org/h2/expression/AggregateData.java
+2
-0
AggregateDataMedian.java
h2/src/main/org/h2/expression/AggregateDataMedian.java
+266
-0
Operation.java
h2/src/main/org/h2/expression/Operation.java
+8
-8
JdbcDataSource.java
h2/src/main/org/h2/jdbcx/JdbcDataSource.java
+13
-4
DateTimeUtils.java
h2/src/main/org/h2/util/DateTimeUtils.java
+65
-42
LocalDateTimeUtils.java
h2/src/main/org/h2/util/LocalDateTimeUtils.java
+67
-23
TestFunctions.java
h2/src/test/org/h2/test/db/TestFunctions.java
+16
-16
TestIndex.java
h2/src/test/org/h2/test/db/TestIndex.java
+2
-1
TestDataSource.java
h2/src/test/org/h2/test/jdbcx/TestDataSource.java
+20
-0
TestScript.java
h2/src/test/org/h2/test/scripts/TestScript.java
+1
-1
median.sql
...c/test/org/h2/test/scripts/functions/aggregate/median.sql
+736
-0
TestTools.java
h2/src/test/org/h2/test/unit/TestTools.java
+15
-3
TestValue.java
h2/src/test/org/h2/test/unit/TestValue.java
+3
-3
dictionary.txt
h2/src/tools/org/h2/build/doc/dictionary.txt
+3
-2
没有找到文件。
h2/src/docsrc/help/help.csv
浏览文件 @
fc67a911
...
...
@@ -498,7 +498,7 @@ qualified class name. The class must implement the interface
Admin rights are required to execute this command.
This command commits an open transaction in this connection.
","
CREATE AGGREGATE MEDIAN FOR ""com.acme.db.Median""
CREATE AGGREGATE
SIMPLE_
MEDIAN FOR ""com.acme.db.Median""
"
"Commands (DDL)","CREATE ALIAS","
...
...
@@ -821,7 +821,7 @@ Drops an existing user-defined aggregate function.
Admin rights are required to execute this command.
This command commits an open transaction in this connection.
","
DROP AGGREGATE MEDIAN
DROP AGGREGATE
SIMPLE_
MEDIAN
"
"Commands (DDL)","DROP ALIAS","
...
...
@@ -2801,6 +2801,19 @@ Aggregates are only allowed in select statements.
VAR_SAMP(X)
"
"Functions (Aggregate)","MEDIAN","
MEDIAN( [ DISTINCT ] value )
","
The value separating the higher half of a values from the lower half.
Returns the middle value or an interpolated value between two middle values if number of values is even.
Interpolation is only supported for numeric, date, and time data types.
NULL values are ignored in the calculation.
If no rows are selected, the result is NULL.
Aggregates are only allowed in select statements.
","
MEDIAN(X)
"
"Functions (Numeric)","ABS","
ABS ( { numeric } )
","
...
...
h2/src/main/org/h2/command/dml/Select.java
浏览文件 @
fc67a911
...
...
@@ -77,7 +77,7 @@ public class Select extends Query {
boolean
[]
groupByExpression
;
/**
* Th
h
e current group-by values.
* The current group-by values.
*/
HashMap
<
Expression
,
Object
>
currentGroup
;
...
...
h2/src/main/org/h2/expression/Aggregate.java
浏览文件 @
fc67a911
...
...
@@ -123,10 +123,15 @@ public class Aggregate extends Expression {
/**
* The aggregate type for HISTOGRAM(expression).
*/
HISTOGRAM
HISTOGRAM
,
/**
* The aggregate type for MEDIAN(expression).
*/
MEDIAN
}
private
static
final
HashMap
<
String
,
AggregateType
>
AGGREGATES
=
new
HashMap
<>(
2
4
);
private
static
final
HashMap
<
String
,
AggregateType
>
AGGREGATES
=
new
HashMap
<>(
2
5
);
private
final
AggregateType
type
;
private
final
Select
select
;
...
...
@@ -187,6 +192,7 @@ public class Aggregate extends Expression {
addAggregate
(
"HISTOGRAM"
,
AggregateType
.
HISTOGRAM
);
addAggregate
(
"BIT_OR"
,
AggregateType
.
BIT_OR
);
addAggregate
(
"BIT_AND"
,
AggregateType
.
BIT_AND
);
addAggregate
(
"MEDIAN"
,
AggregateType
.
MEDIAN
);
}
private
static
void
addAggregate
(
String
name
,
AggregateType
type
)
{
...
...
@@ -287,7 +293,7 @@ public class Aggregate extends Expression {
Table
table
=
select
.
getTopTableFilter
().
getTable
();
return
ValueLong
.
get
(
table
.
getRowCount
(
session
));
case
MIN:
case
MAX:
case
MAX:
{
boolean
first
=
type
==
AggregateType
.
MIN
;
Index
index
=
getMinMaxColumnIndex
();
int
sortType
=
index
.
getIndexColumns
()[
0
].
sortType
;
...
...
@@ -303,6 +309,10 @@ public class Aggregate extends Expression {
v
=
row
.
getValue
(
index
.
getColumns
()[
0
].
getColumnId
());
}
return
v
;
}
case
MEDIAN:
{
return
AggregateDataMedian
.
getFromIndex
(
session
,
on
,
dataType
);
}
default
:
DbException
.
throwInternalError
(
"type="
+
type
);
}
...
...
@@ -434,6 +444,7 @@ public class Aggregate extends Expression {
break
;
case
MIN:
case
MAX:
case
MEDIAN:
break
;
case
STDDEV_POP:
case
STDDEV_SAMP:
...
...
@@ -568,6 +579,9 @@ public class Aggregate extends Expression {
case
BIT_OR:
text
=
"BIT_OR"
;
break
;
case
MEDIAN:
text
=
"MEDIAN"
;
break
;
default
:
throw
DbException
.
throwInternalError
(
"type="
+
type
);
}
...
...
@@ -606,6 +620,11 @@ public class Aggregate extends Expression {
case
MAX:
Index
index
=
getMinMaxColumnIndex
();
return
index
!=
null
;
case
MEDIAN:
if
(
distinct
)
{
return
false
;
}
return
AggregateDataMedian
.
getMedianColumnIndex
(
on
)
!=
null
;
default
:
return
false
;
}
...
...
h2/src/main/org/h2/expression/AggregateData.java
浏览文件 @
fc67a911
...
...
@@ -31,6 +31,8 @@ abstract class AggregateData {
return
new
AggregateDataCount
();
}
else
if
(
aggregateType
==
AggregateType
.
HISTOGRAM
)
{
return
new
AggregateDataHistogram
();
}
else
if
(
aggregateType
==
AggregateType
.
MEDIAN
)
{
return
new
AggregateDataMedian
();
}
else
{
return
new
AggregateDataDefault
(
aggregateType
);
}
...
...
h2/src/main/org/h2/expression/AggregateDataMedian.java
0 → 100644
浏览文件 @
fc67a911
/*
* 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
.
expression
;
import
java.math.BigDecimal
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Comparator
;
import
java.util.HashSet
;
import
org.h2.engine.Database
;
import
org.h2.engine.Session
;
import
org.h2.index.Cursor
;
import
org.h2.index.Index
;
import
org.h2.result.SearchRow
;
import
org.h2.result.SortOrder
;
import
org.h2.table.Column
;
import
org.h2.table.IndexColumn
;
import
org.h2.table.Table
;
import
org.h2.table.TableFilter
;
import
org.h2.util.DateTimeUtils
;
import
org.h2.value.CompareMode
;
import
org.h2.value.Value
;
import
org.h2.value.ValueDate
;
import
org.h2.value.ValueDecimal
;
import
org.h2.value.ValueDouble
;
import
org.h2.value.ValueFloat
;
import
org.h2.value.ValueInt
;
import
org.h2.value.ValueLong
;
import
org.h2.value.ValueNull
;
import
org.h2.value.ValueTime
;
import
org.h2.value.ValueTimestamp
;
import
org.h2.value.ValueTimestampTimeZone
;
/**
* Data stored while calculating a MEDIAN aggregate.
*/
class
AggregateDataMedian
extends
AggregateData
{
private
Collection
<
Value
>
values
;
private
static
boolean
isNullsLast
(
Index
index
)
{
IndexColumn
ic
=
index
.
getIndexColumns
()[
0
];
int
sortType
=
ic
.
sortType
;
return
(
sortType
&
SortOrder
.
NULLS_LAST
)
!=
0
||
(
sortType
&
SortOrder
.
DESCENDING
)
!=
0
&&
(
sortType
&
SortOrder
.
NULLS_FIRST
)
==
0
;
}
static
Index
getMedianColumnIndex
(
Expression
on
)
{
if
(
on
instanceof
ExpressionColumn
)
{
ExpressionColumn
col
=
(
ExpressionColumn
)
on
;
Column
column
=
col
.
getColumn
();
TableFilter
filter
=
col
.
getTableFilter
();
if
(
filter
!=
null
)
{
Table
table
=
filter
.
getTable
();
ArrayList
<
Index
>
indexes
=
table
.
getIndexes
();
Index
result
=
null
;
if
(
indexes
!=
null
)
{
boolean
nullable
=
column
.
isNullable
();
for
(
int
i
=
1
,
size
=
indexes
.
size
();
i
<
size
;
i
++)
{
Index
index
=
indexes
.
get
(
i
);
if
(!
index
.
canFindNext
())
{
continue
;
}
if
(!
index
.
isFirstColumn
(
column
))
{
continue
;
}
if
(
result
==
null
||
result
.
getColumns
().
length
>
index
.
getColumns
().
length
// Prefer index without nulls last for nullable columns
||
nullable
&&
isNullsLast
(
result
)
&&
!
isNullsLast
(
index
))
{
result
=
index
;
}
}
}
return
result
;
}
}
return
null
;
}
static
Value
getFromIndex
(
Session
session
,
Expression
on
,
int
dataType
)
{
Index
index
=
getMedianColumnIndex
(
on
);
long
count
=
index
.
getRowCount
(
session
);
if
(
count
==
0
)
{
return
ValueNull
.
INSTANCE
;
}
Cursor
cursor
=
index
.
find
(
session
,
null
,
null
);
cursor
.
next
();
int
columnId
=
index
.
getColumns
()[
0
].
getColumnId
();
ExpressionColumn
expr
=
(
ExpressionColumn
)
on
;
if
(
expr
.
getColumn
().
isNullable
())
{
boolean
hasNulls
=
false
;
SearchRow
row
;
/*
* Try to skip nulls from the start first with the same cursor that will be used
* to read values.
*/
while
(
count
>
0
)
{
row
=
cursor
.
getSearchRow
();
if
(
row
==
null
)
{
return
ValueNull
.
INSTANCE
;
}
if
(
row
.
getValue
(
columnId
)
==
ValueNull
.
INSTANCE
)
{
count
--;
cursor
.
next
();
hasNulls
=
true
;
}
else
break
;
}
if
(
count
==
0
)
{
return
ValueNull
.
INSTANCE
;
}
/*
* If no nulls found and if index orders nulls last create a second cursor to
* count nulls at the end.
*/
if
(!
hasNulls
&&
isNullsLast
(
index
))
{
TableFilter
tableFilter
=
expr
.
getTableFilter
();
SearchRow
check
=
tableFilter
.
getTable
().
getTemplateSimpleRow
(
true
);
check
.
setValue
(
columnId
,
ValueNull
.
INSTANCE
);
Cursor
nullsCursor
=
index
.
find
(
session
,
check
,
check
);
while
(
nullsCursor
.
next
())
{
count
--;
}
if
(
count
<=
0
)
{
return
ValueNull
.
INSTANCE
;
}
}
}
long
skip
=
(
count
-
1
)
/
2
;
for
(
int
i
=
0
;
i
<
skip
;
i
++)
{
cursor
.
next
();
}
SearchRow
row
=
cursor
.
getSearchRow
();
if
(
row
==
null
)
{
return
ValueNull
.
INSTANCE
;
}
Value
v
=
row
.
getValue
(
columnId
);
if
(
v
==
ValueNull
.
INSTANCE
)
{
return
v
;
}
if
((
count
&
1
)
==
0
)
{
cursor
.
next
();
row
=
cursor
.
getSearchRow
();
if
(
row
==
null
)
{
return
v
;
}
Value
v2
=
row
.
getValue
(
columnId
);
if
(
v2
==
ValueNull
.
INSTANCE
)
{
return
v
;
}
return
getMedian
(
v
,
v2
,
dataType
,
session
.
getDatabase
().
getCompareMode
());
}
return
v
;
}
@Override
void
add
(
Database
database
,
int
dataType
,
boolean
distinct
,
Value
v
)
{
if
(
v
==
ValueNull
.
INSTANCE
)
{
return
;
}
Collection
<
Value
>
c
=
values
;
if
(
c
==
null
)
{
values
=
c
=
distinct
?
new
HashSet
<
Value
>()
:
new
ArrayList
<
Value
>();
}
c
.
add
(
v
);
}
@Override
Value
getValue
(
Database
database
,
int
dataType
,
boolean
distinct
)
{
Collection
<
Value
>
c
=
values
;
// Non-null collection cannot be empty here
if
(
c
==
null
)
{
return
ValueNull
.
INSTANCE
;
}
if
(
distinct
&&
c
instanceof
ArrayList
)
{
c
=
new
HashSet
<>(
c
);
}
Value
[]
a
=
c
.
toArray
(
new
Value
[
0
]);
final
CompareMode
mode
=
database
.
getCompareMode
();
Arrays
.
sort
(
a
,
new
Comparator
<
Value
>()
{
@Override
public
int
compare
(
Value
o1
,
Value
o2
)
{
return
o1
.
compareTo
(
o2
,
mode
);
}
});
int
len
=
a
.
length
;
int
idx
=
len
/
2
;
Value
v1
=
a
[
idx
];
if
((
len
&
1
)
==
1
)
{
return
v1
.
convertTo
(
dataType
);
}
return
getMedian
(
a
[
idx
-
1
],
v1
,
dataType
,
mode
);
}
static
Value
getMedian
(
Value
v0
,
Value
v1
,
int
dataType
,
CompareMode
mode
)
{
if
(
v0
.
compareTo
(
v1
,
mode
)
==
0
)
{
return
v0
.
convertTo
(
dataType
);
}
switch
(
dataType
)
{
case
Value
.
BYTE
:
case
Value
.
SHORT
:
case
Value
.
INT
:
return
ValueInt
.
get
((
v0
.
getInt
()
+
v1
.
getInt
())
/
2
).
convertTo
(
dataType
);
case
Value
.
LONG
:
return
ValueLong
.
get
((
v0
.
getLong
()
+
v1
.
getLong
())
/
2
);
case
Value
.
DECIMAL
:
return
ValueDecimal
.
get
(
v0
.
getBigDecimal
().
add
(
v1
.
getBigDecimal
()).
divide
(
BigDecimal
.
valueOf
(
2
)));
case
Value
.
FLOAT
:
return
ValueFloat
.
get
((
v0
.
getFloat
()
+
v1
.
getFloat
())
/
2
);
case
Value
.
DOUBLE
:
return
ValueDouble
.
get
((
v0
.
getFloat
()
+
v1
.
getDouble
())
/
2
);
case
Value
.
TIME
:
{
return
ValueTime
.
fromMillis
((
v0
.
getTime
().
getTime
()
+
v1
.
getTime
().
getTime
())
/
2
);
}
case
Value
.
DATE
:
{
ValueDate
d0
=
(
ValueDate
)
v0
.
convertTo
(
Value
.
DATE
),
d1
=
(
ValueDate
)
v1
.
convertTo
(
Value
.
DATE
);
return
ValueDate
.
fromDateValue
(
DateTimeUtils
.
dateValueFromAbsoluteDay
((
DateTimeUtils
.
absoluteDayFromDateValue
(
d0
.
getDateValue
())
+
DateTimeUtils
.
absoluteDayFromDateValue
(
d1
.
getDateValue
()))
/
2
));
}
case
Value
.
TIMESTAMP
:
{
ValueTimestamp
ts0
=
(
ValueTimestamp
)
v0
.
convertTo
(
Value
.
TIMESTAMP
),
ts1
=
(
ValueTimestamp
)
v1
.
convertTo
(
Value
.
TIMESTAMP
);
long
dateSum
=
DateTimeUtils
.
absoluteDayFromDateValue
(
ts0
.
getDateValue
())
+
DateTimeUtils
.
absoluteDayFromDateValue
(
ts1
.
getDateValue
());
long
nanos
=
(
ts0
.
getTimeNanos
()
+
ts1
.
getTimeNanos
())
/
2
;
if
((
dateSum
&
1
)
!=
0
)
{
nanos
+=
DateTimeUtils
.
NANOS_PER_DAY
/
2
;
if
(
nanos
>=
DateTimeUtils
.
NANOS_PER_DAY
)
{
nanos
-=
DateTimeUtils
.
NANOS_PER_DAY
;
dateSum
++;
}
}
return
ValueTimestamp
.
fromDateValueAndNanos
(
DateTimeUtils
.
dateValueFromAbsoluteDay
(
dateSum
/
2
),
nanos
);
}
case
Value
.
TIMESTAMP_TZ
:
{
ValueTimestampTimeZone
ts0
=
(
ValueTimestampTimeZone
)
v0
.
convertTo
(
Value
.
TIMESTAMP_TZ
),
ts1
=
(
ValueTimestampTimeZone
)
v1
.
convertTo
(
Value
.
TIMESTAMP_TZ
);
long
dateSum
=
DateTimeUtils
.
absoluteDayFromDateValue
(
ts0
.
getDateValue
())
+
DateTimeUtils
.
absoluteDayFromDateValue
(
ts1
.
getDateValue
());
long
nanos
=
(
ts0
.
getTimeNanos
()
+
ts1
.
getTimeNanos
())
/
2
;
int
offset
=
ts0
.
getTimeZoneOffsetMins
()
+
ts1
.
getTimeZoneOffsetMins
();
if
((
dateSum
&
1
)
!=
0
)
{
nanos
+=
DateTimeUtils
.
NANOS_PER_DAY
/
2
;
}
if
((
offset
&
1
)
!=
0
)
{
nanos
+=
30L
*
1000000000
;
}
if
(
nanos
>=
DateTimeUtils
.
NANOS_PER_DAY
)
{
nanos
-=
DateTimeUtils
.
NANOS_PER_DAY
;
dateSum
++;
}
return
ValueTimestampTimeZone
.
fromDateValueAndNanos
(
DateTimeUtils
.
dateValueFromAbsoluteDay
(
dateSum
/
2
),
nanos
,
(
short
)
(
offset
/
2
));
}
default
:
// Just return first
return
v0
.
convertTo
(
dataType
);
}
}
}
h2/src/main/org/h2/expression/Operation.java
浏览文件 @
fc67a911
...
...
@@ -27,38 +27,38 @@ public class Operation extends Expression {
* This operation represents a string concatenation as in
* 'Hello' || 'World'.
*/
CONCAT
,
CONCAT
,
/**
* This operation represents an addition as in 1 + 2.
*/
PLUS
,
PLUS
,
/**
* This operation represents a subtraction as in 2 - 1.
*/
MINUS
,
MINUS
,
/**
* This operation represents a multiplication as in 2 * 3.
*/
MULTIPLY
,
MULTIPLY
,
/**
* This operation represents a division as in 4 * 2.
*/
DIVIDE
,
DIVIDE
,
/**
* This operation represents a negation as in - ID.
*/
NEGATE
,
NEGATE
,
/**
* This operation represents a modulus as in 5 % 2.
*/
MODULUS
}
;
MODULUS
}
private
OpType
opType
;
private
Expression
left
,
right
;
...
...
h2/src/main/org/h2/jdbcx/JdbcDataSource.java
浏览文件 @
fc67a911
...
...
@@ -23,6 +23,7 @@ import javax.sql.XAConnection;
import
javax.sql.XADataSource
;
import
org.h2.Driver
;
import
org.h2.jdbc.JdbcConnection
;
import
org.h2.message.DbException
;
import
org.h2.message.TraceObject
;
import
org.h2.util.StringUtils
;
...
...
@@ -401,23 +402,31 @@ public class JdbcDataSource extends TraceObject implements XADataSource,
}
/**
*
[Not supported]
Return an object of this class if possible.
* Return an object of this class if possible.
*
* @param iface the class
*/
@Override
@SuppressWarnings
(
"unchecked"
)
public
<
T
>
T
unwrap
(
Class
<
T
>
iface
)
throws
SQLException
{
throw
unsupported
(
"unwrap"
);
try
{
if
(
isWrapperFor
(
iface
))
{
return
(
T
)
this
;
}
throw
DbException
.
getInvalidValueException
(
"iface"
,
iface
);
}
catch
(
Exception
e
)
{
throw
logAndConvert
(
e
);
}
}
/**
*
[Not supported]
Checks if unwrap can return an object of this class.
* Checks if unwrap can return an object of this class.
*
* @param iface the class
*/
@Override
public
boolean
isWrapperFor
(
Class
<?>
iface
)
throws
SQLException
{
throw
unsupported
(
"isWrapperFor"
);
return
iface
!=
null
&&
iface
.
isAssignableFrom
(
getClass
()
);
}
/**
...
...
h2/src/main/org/h2/util/DateTimeUtils.java
浏览文件 @
fc67a911
...
...
@@ -43,11 +43,19 @@ public class DateTimeUtils {
*/
public
static
final
TimeZone
UTC
=
TimeZone
.
getTimeZone
(
"UTC"
);
private
static
final
long
NANOS_PER_DAY
=
MILLIS_PER_DAY
*
1000000
;
/**
* The number of nanoseconds per day.
*/
public
static
final
long
NANOS_PER_DAY
=
MILLIS_PER_DAY
*
1000000
;
private
static
final
int
SHIFT_YEAR
=
9
;
private
static
final
int
SHIFT_MONTH
=
5
;
/**
* Date value for 1970-01-01.
*/
private
static
final
int
EPOCH_DATE_VALUE
=
(
1970
<<
SHIFT_YEAR
)
+
(
1
<<
SHIFT_MONTH
)
+
1
;
private
static
final
int
[]
NORMAL_DAYS_PER_MONTH
=
{
0
,
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
};
...
...
@@ -65,12 +73,12 @@ public class DateTimeUtils {
* have that problem, and while it is still a small memory leak, it is not a
* class loader memory leak.
*/
private
static
final
ThreadLocal
<
Calendar
>
CACHED_CALENDAR
=
new
ThreadLocal
<>();
private
static
final
ThreadLocal
<
Gregorian
Calendar
>
CACHED_CALENDAR
=
new
ThreadLocal
<>();
/**
* A cached instance of Calendar used when a timezone is specified.
*/
private
static
final
ThreadLocal
<
Calendar
>
CACHED_CALENDAR_NON_DEFAULT_TIMEZONE
=
private
static
final
ThreadLocal
<
Gregorian
Calendar
>
CACHED_CALENDAR_NON_DEFAULT_TIMEZONE
=
new
ThreadLocal
<>();
/**
...
...
@@ -102,8 +110,8 @@ public class DateTimeUtils {
*
* @return a calendar instance. A cached instance is returned where possible
*/
private
static
Calendar
getCalendar
()
{
Calendar
c
=
CACHED_CALENDAR
.
get
();
private
static
Gregorian
Calendar
getCalendar
()
{
Gregorian
Calendar
c
=
CACHED_CALENDAR
.
get
();
if
(
c
==
null
)
{
c
=
DateTimeUtils
.
createGregorianCalendar
();
CACHED_CALENDAR
.
set
(
c
);
...
...
@@ -118,8 +126,8 @@ public class DateTimeUtils {
* @param tz timezone for the calendar, is never null
* @return a calendar instance. A cached instance is returned where possible
*/
private
static
Calendar
getCalendar
(
TimeZone
tz
)
{
Calendar
c
=
CACHED_CALENDAR_NON_DEFAULT_TIMEZONE
.
get
();
private
static
Gregorian
Calendar
getCalendar
(
TimeZone
tz
)
{
Gregorian
Calendar
c
=
CACHED_CALENDAR_NON_DEFAULT_TIMEZONE
.
get
();
if
(
c
==
null
||
!
c
.
getTimeZone
().
equals
(
tz
))
{
c
=
DateTimeUtils
.
createGregorianCalendar
(
tz
);
CACHED_CALENDAR_NON_DEFAULT_TIMEZONE
.
set
(
c
);
...
...
@@ -137,7 +145,7 @@ public class DateTimeUtils {
*
* @return a new calendar instance.
*/
public
static
Calendar
createGregorianCalendar
()
{
public
static
Gregorian
Calendar
createGregorianCalendar
()
{
return
new
GregorianCalendar
();
}
...
...
@@ -151,7 +159,7 @@ public class DateTimeUtils {
* @param tz timezone for the calendar, is never null
* @return a new calendar instance.
*/
public
static
Calendar
createGregorianCalendar
(
TimeZone
tz
)
{
public
static
Gregorian
Calendar
createGregorianCalendar
(
TimeZone
tz
)
{
return
new
GregorianCalendar
(
tz
);
}
...
...
@@ -520,9 +528,15 @@ public class DateTimeUtils {
*/
public
static
long
getMillis
(
TimeZone
tz
,
int
year
,
int
month
,
int
day
,
int
hour
,
int
minute
,
int
second
,
int
millis
)
{
GregorianCalendar
c
;
if
(
tz
==
null
)
{
c
=
getCalendar
();
}
else
{
c
=
getCalendar
(
tz
);
}
c
.
setLenient
(
false
);
try
{
return
getTimeTry
(
false
,
tz
,
year
,
month
,
day
,
hour
,
minute
,
second
,
millis
);
return
convertToMillis
(
c
,
year
,
month
,
day
,
hour
,
minute
,
second
,
millis
);
}
catch
(
IllegalArgumentException
e
)
{
// special case: if the time simply doesn't exist because of
// daylight saving time changes, use the lenient version
...
...
@@ -531,12 +545,10 @@ public class DateTimeUtils {
if
(
hour
<
0
||
hour
>
23
)
{
throw
e
;
}
return
getTimeTry
(
true
,
tz
,
year
,
month
,
day
,
hour
,
minute
,
second
,
millis
);
}
else
if
(
message
.
indexOf
(
"DAY_OF_MONTH"
)
>
0
)
{
int
maxDay
;
if
(
month
==
2
)
{
maxDay
=
new
GregorianCalendar
()
.
isLeapYear
(
year
)
?
29
:
28
;
maxDay
=
c
.
isLeapYear
(
year
)
?
29
:
28
;
}
else
{
maxDay
=
30
+
((
month
+
(
month
>
7
?
1
:
0
))
&
1
);
}
...
...
@@ -547,27 +559,12 @@ public class DateTimeUtils {
// using the timezone Brasilia and others,
// for example for 2042-10-12 00:00:00.
hour
+=
6
;
return
getTimeTry
(
true
,
tz
,
year
,
month
,
day
,
hour
,
minute
,
second
,
millis
);
}
else
{
return
getTimeTry
(
true
,
tz
,
year
,
month
,
day
,
hour
,
minute
,
second
,
millis
);
}
c
.
setLenient
(
true
);
return
convertToMillis
(
c
,
year
,
month
,
day
,
hour
,
minute
,
second
,
millis
);
}
}
private
static
long
getTimeTry
(
boolean
lenient
,
TimeZone
tz
,
int
year
,
int
month
,
int
day
,
int
hour
,
int
minute
,
int
second
,
int
millis
)
{
Calendar
c
;
if
(
tz
==
null
)
{
c
=
getCalendar
();
}
else
{
c
=
getCalendar
(
tz
);
}
c
.
setLenient
(
lenient
);
return
convertToMillis
(
c
,
year
,
month
,
day
,
hour
,
minute
,
second
,
millis
);
}
private
static
long
convertToMillis
(
Calendar
cal
,
int
year
,
int
month
,
int
day
,
int
hour
,
int
minute
,
int
second
,
int
millis
)
{
if
(
year
<=
0
)
{
...
...
@@ -595,19 +592,45 @@ public class DateTimeUtils {
* @param field the field type
* @return the value
*/
public
static
long
getDatePart
(
Value
date
,
int
field
)
{
Calendar
c
=
valueToCalendar
(
date
);
if
(
field
==
Function
.
EPOCH
)
{
return
c
.
getTime
().
getTime
()
/
1000
;
}
if
(
field
==
Calendar
.
YEAR
)
{
return
getYear
(
c
);
public
static
int
getDatePart
(
Value
date
,
int
field
)
{
long
dateValue
=
EPOCH_DATE_VALUE
;
long
timeNanos
=
0
;
if
(
date
instanceof
ValueTimestamp
)
{
ValueTimestamp
v
=
(
ValueTimestamp
)
date
;
dateValue
=
v
.
getDateValue
();
timeNanos
=
v
.
getTimeNanos
();
}
else
if
(
date
instanceof
ValueDate
)
{
dateValue
=
((
ValueDate
)
date
).
getDateValue
();
}
else
if
(
date
instanceof
ValueTime
)
{
timeNanos
=
((
ValueTime
)
date
).
getNanos
();
}
else
if
(
date
instanceof
ValueTimestampTimeZone
)
{
ValueTimestampTimeZone
v
=
(
ValueTimestampTimeZone
)
date
;
dateValue
=
v
.
getDateValue
();
timeNanos
=
v
.
getTimeNanos
();
}
else
{
ValueTimestamp
v
=
(
ValueTimestamp
)
date
.
convertTo
(
Value
.
TIMESTAMP
);
date
=
v
;
// For valueToCalendar() to avoid second convertTo() call
dateValue
=
v
.
getDateValue
();
timeNanos
=
v
.
getTimeNanos
();
}
int
value
=
c
.
get
(
field
);
if
(
field
==
Calendar
.
MONTH
)
{
return
value
+
1
;
switch
(
field
)
{
case
Calendar
.
YEAR
:
return
yearFromDateValue
(
dateValue
);
case
Calendar
.
MONTH
:
return
monthFromDateValue
(
dateValue
);
case
Calendar
.
DAY_OF_MONTH
:
return
dayFromDateValue
(
dateValue
);
case
Calendar
.
HOUR_OF_DAY
:
return
(
int
)
(
timeNanos
/
3_600_000_000_000L
%
24
);
case
Calendar
.
MINUTE
:
return
(
int
)
(
timeNanos
/
60_000_000_000L
%
60
);
case
Calendar
.
SECOND
:
return
(
int
)
(
timeNanos
/
1_000_000_000
%
60
);
case
Calendar
.
MILLISECOND
:
return
(
int
)
(
timeNanos
/
1_000_000
%
1_000
);
}
return
value
;
return
value
ToCalendar
(
date
).
get
(
field
)
;
}
/**
...
...
h2/src/main/org/h2/util/LocalDateTimeUtils.java
浏览文件 @
fc67a911
...
...
@@ -12,7 +12,6 @@ import java.lang.reflect.Method;
import
java.sql.Timestamp
;
import
java.util.Arrays
;
import
java.util.concurrent.TimeUnit
;
import
org.h2.message.DbException
;
import
org.h2.value.Value
;
import
org.h2.value.ValueDate
;
...
...
@@ -61,58 +60,103 @@ public class LocalDateTimeUtils {
*/
public
static
final
Class
<?>
OFFSET_DATE_TIME
;
// Class<java.time.ZoneOffset>
/**
* {@code Class<java.time.ZoneOffset>} or {@code null}.
*/
private
static
final
Class
<?>
ZONE_OFFSET
;
// java.time.LocalTime#ofNanoOfDay()
/**
* {@code java.time.LocalTime#ofNanoOfDay()} or {@code null}.
*/
private
static
final
Method
LOCAL_TIME_OF_NANO
;
// java.time.LocalTime#toNanoOfDay()
/**
* {@code java.time.LocalTime#toNanoOfDay()} or {@code null}.
*/
private
static
final
Method
LOCAL_TIME_TO_NANO
;
// java.time.LocalDate#of(int, int, int)
/**
* {@code java.time.LocalDate#of(int, int, int)} or {@code null}.
*/
private
static
final
Method
LOCAL_DATE_OF_YEAR_MONTH_DAY
;
// java.time.LocalDate#parse(CharSequence)
/**
* {@code java.time.LocalDate#parse(CharSequence)} or {@code null}.
*/
private
static
final
Method
LOCAL_DATE_PARSE
;
// java.time.LocalDate#getYear()
/**
* {@code java.time.LocalDate#getYear()} or {@code null}.
*/
private
static
final
Method
LOCAL_DATE_GET_YEAR
;
// java.time.LocalDate#getMonthValue()
/**
* {@code java.time.LocalDate#getMonthValue()} or {@code null}.
*/
private
static
final
Method
LOCAL_DATE_GET_MONTH_VALUE
;
// java.time.LocalDate#getDayOfMonth()
/**
* {@code java.time.LocalDate#getDayOfMonth()} or {@code null}.
*/
private
static
final
Method
LOCAL_DATE_GET_DAY_OF_MONTH
;
// java.time.LocalDate#atStartOfDay()
/**
* {@code java.time.LocalDate#atStartOfDay()} or {@code null}.
*/
private
static
final
Method
LOCAL_DATE_AT_START_OF_DAY
;
// java.sql.Timestamp.from(java.time.Instant)
/**
* {@code java.sql.Timestamp.from(java.time.Instant)} or {@code null}.
*/
private
static
final
Method
TIMESTAMP_FROM
;
// java.sql.Timestamp.toInstant()
/**
* {@code java.sql.Timestamp.toInstant()} or {@code null}.
*/
private
static
final
Method
TIMESTAMP_TO_INSTANT
;
// java.time.LocalTime#parse(CharSequence)
/**
* {@code java.time.LocalTime#parse(CharSequence)} or {@code null}.
*/
private
static
final
Method
LOCAL_TIME_PARSE
;
// java.time.LocalDateTime#plusNanos(long)
/**
* {@code java.time.LocalDateTime#plusNanos(long)} or {@code null}.
*/
private
static
final
Method
LOCAL_DATE_TIME_PLUS_NANOS
;
// java.time.LocalDateTime#toLocalDate()
/**
* {@code java.time.LocalDateTime#toLocalDate()} or {@code null}.
*/
private
static
final
Method
LOCAL_DATE_TIME_TO_LOCAL_DATE
;
// java.time.LocalDateTime#toLocalTime()
/**
* {@code java.time.LocalDateTime#toLocalTime()} or {@code null}.
*/
private
static
final
Method
LOCAL_DATE_TIME_TO_LOCAL_TIME
;
// java.time.LocalDateTime#parse(CharSequence)
/**
* {@code java.time.LocalDateTime#parse(CharSequence)} or {@code null}.
*/
private
static
final
Method
LOCAL_DATE_TIME_PARSE
;
// java.time.ZoneOffset#ofTotalSeconds(int)
/**
* {@code java.time.ZoneOffset#ofTotalSeconds(int)} or {@code null}.
*/
private
static
final
Method
ZONE_OFFSET_OF_TOTAL_SECONDS
;
// java.time.OffsetDateTime#of(LocalDateTime, ZoneOffset)
/**
* {@code java.time.OffsetDateTime#of(LocalDateTime, ZoneOffset)} or
* {@code null}.
*/
private
static
final
Method
OFFSET_DATE_TIME_OF_LOCAL_DATE_TIME_ZONE_OFFSET
;
// java.time.OffsetDateTime#parse(CharSequence)
/**
* {@code java.time.OffsetDateTime#parse(CharSequence)} or {@code null}.
*/
private
static
final
Method
OFFSET_DATE_TIME_PARSE
;
// java.time.OffsetDateTime#toLocalDateTime()
/**
* {@code java.time.OffsetDateTime#toLocalDateTime()} or {@code null}.
*/
private
static
final
Method
OFFSET_DATE_TIME_TO_LOCAL_DATE_TIME
;
// java.time.OffsetDateTime#getOffset()
/**
* {@code java.time.OffsetDateTime#getOffset()} or {@code null}.
*/
private
static
final
Method
OFFSET_DATE_TIME_GET_OFFSET
;
// java.time.ZoneOffset#getTotalSeconds()
/**
* {@code java.time.ZoneOffset#getTotalSeconds()} or {@code null}.
*/
private
static
final
Method
ZONE_OFFSET_GET_TOTAL_SECONDS
;
private
static
final
boolean
IS_JAVA8_DATE_API_PRESENT
;
...
...
h2/src/test/org/h2/test/db/TestFunctions.java
浏览文件 @
fc67a911
...
...
@@ -740,12 +740,12 @@ public class TestFunctions extends TestBase implements AggregateFunction {
deleteDb
(
"functions"
);
Connection
conn
=
getConnection
(
"functions"
);
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"CREATE AGGREGATE MEDIAN FOR \""
+
stat
.
execute
(
"CREATE AGGREGATE
SIMPLE_
MEDIAN FOR \""
+
MedianStringType
.
class
.
getName
()
+
"\""
);
stat
.
execute
(
"CREATE AGGREGATE IF NOT EXISTS MEDIAN FOR \""
+
stat
.
execute
(
"CREATE AGGREGATE IF NOT EXISTS
SIMPLE_
MEDIAN FOR \""
+
MedianStringType
.
class
.
getName
()
+
"\""
);
ResultSet
rs
=
stat
.
executeQuery
(
"SELECT MEDIAN(X) FROM SYSTEM_RANGE(1, 9)"
);
"SELECT
SIMPLE_
MEDIAN(X) FROM SYSTEM_RANGE(1, 9)"
);
rs
.
next
();
assertEquals
(
"5"
,
rs
.
getString
(
1
));
conn
.
close
();
...
...
@@ -756,22 +756,22 @@ public class TestFunctions extends TestBase implements AggregateFunction {
conn
=
getConnection
(
"functions"
);
stat
=
conn
.
createStatement
();
stat
.
executeQuery
(
"SELECT MEDIAN(X) FROM SYSTEM_RANGE(1, 9)"
);
stat
.
executeQuery
(
"SELECT
SIMPLE_
MEDIAN(X) FROM SYSTEM_RANGE(1, 9)"
);
DatabaseMetaData
meta
=
conn
.
getMetaData
();
rs
=
meta
.
getProcedures
(
null
,
null
,
"MEDIAN"
);
rs
=
meta
.
getProcedures
(
null
,
null
,
"
SIMPLE_
MEDIAN"
);
assertTrue
(
rs
.
next
());
assertFalse
(
rs
.
next
());
rs
=
stat
.
executeQuery
(
"SCRIPT"
);
boolean
found
=
false
;
while
(
rs
.
next
())
{
String
sql
=
rs
.
getString
(
1
);
if
(
sql
.
contains
(
"MEDIAN"
))
{
if
(
sql
.
contains
(
"
SIMPLE_
MEDIAN"
))
{
found
=
true
;
}
}
assertTrue
(
found
);
stat
.
execute
(
"DROP AGGREGATE MEDIAN"
);
stat
.
execute
(
"DROP AGGREGATE IF EXISTS MEDIAN"
);
stat
.
execute
(
"DROP AGGREGATE
SIMPLE_
MEDIAN"
);
stat
.
execute
(
"DROP AGGREGATE IF EXISTS
SIMPLE_
MEDIAN"
);
conn
.
close
();
}
...
...
@@ -779,12 +779,12 @@ public class TestFunctions extends TestBase implements AggregateFunction {
deleteDb
(
"functions"
);
Connection
conn
=
getConnection
(
"functions"
);
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"CREATE AGGREGATE MEDIAN FOR \""
+
stat
.
execute
(
"CREATE AGGREGATE
SIMPLE_
MEDIAN FOR \""
+
MedianString
.
class
.
getName
()
+
"\""
);
stat
.
execute
(
"CREATE AGGREGATE IF NOT EXISTS MEDIAN FOR \""
+
stat
.
execute
(
"CREATE AGGREGATE IF NOT EXISTS
SIMPLE_
MEDIAN FOR \""
+
MedianString
.
class
.
getName
()
+
"\""
);
ResultSet
rs
=
stat
.
executeQuery
(
"SELECT MEDIAN(X) FROM SYSTEM_RANGE(1, 9)"
);
"SELECT
SIMPLE_
MEDIAN(X) FROM SYSTEM_RANGE(1, 9)"
);
rs
.
next
();
assertEquals
(
"5"
,
rs
.
getString
(
1
));
conn
.
close
();
...
...
@@ -795,22 +795,22 @@ public class TestFunctions extends TestBase implements AggregateFunction {
conn
=
getConnection
(
"functions"
);
stat
=
conn
.
createStatement
();
stat
.
executeQuery
(
"SELECT MEDIAN(X) FROM SYSTEM_RANGE(1, 9)"
);
stat
.
executeQuery
(
"SELECT
SIMPLE_
MEDIAN(X) FROM SYSTEM_RANGE(1, 9)"
);
DatabaseMetaData
meta
=
conn
.
getMetaData
();
rs
=
meta
.
getProcedures
(
null
,
null
,
"MEDIAN"
);
rs
=
meta
.
getProcedures
(
null
,
null
,
"
SIMPLE_
MEDIAN"
);
assertTrue
(
rs
.
next
());
assertFalse
(
rs
.
next
());
rs
=
stat
.
executeQuery
(
"SCRIPT"
);
boolean
found
=
false
;
while
(
rs
.
next
())
{
String
sql
=
rs
.
getString
(
1
);
if
(
sql
.
contains
(
"MEDIAN"
))
{
if
(
sql
.
contains
(
"
SIMPLE_
MEDIAN"
))
{
found
=
true
;
}
}
assertTrue
(
found
);
stat
.
execute
(
"DROP AGGREGATE MEDIAN"
);
stat
.
execute
(
"DROP AGGREGATE IF EXISTS MEDIAN"
);
stat
.
execute
(
"DROP AGGREGATE
SIMPLE_
MEDIAN"
);
stat
.
execute
(
"DROP AGGREGATE IF EXISTS
SIMPLE_
MEDIAN"
);
conn
.
close
();
}
...
...
h2/src/test/org/h2/test/db/TestIndex.java
浏览文件 @
fc67a911
...
...
@@ -262,7 +262,8 @@ public class TestIndex extends TestBase {
c
.
close
();
}
private
void
testConcurrentUpdateRun
(
ConcurrentUpdateThread
[]
threads
,
PreparedStatement
check
)
throws
SQLException
{
private
void
testConcurrentUpdateRun
(
ConcurrentUpdateThread
[]
threads
,
PreparedStatement
check
)
throws
SQLException
{
for
(
ConcurrentUpdateThread
t
:
threads
)
{
t
.
start
();
}
...
...
h2/src/test/org/h2/test/jdbcx/TestDataSource.java
浏览文件 @
fc67a911
...
...
@@ -15,9 +15,12 @@ import javax.naming.StringRefAddr;
import
javax.naming.spi.ObjectFactory
;
import
javax.sql.ConnectionEvent
;
import
javax.sql.ConnectionEventListener
;
import
javax.sql.DataSource
;
import
javax.sql.XAConnection
;
import
javax.transaction.xa.XAResource
;
import
javax.transaction.xa.Xid
;
import
org.h2.api.ErrorCode
;
import
org.h2.jdbcx.JdbcDataSource
;
import
org.h2.jdbcx.JdbcDataSourceFactory
;
import
org.h2.jdbcx.JdbcXAConnection
;
...
...
@@ -71,6 +74,7 @@ public class TestDataSource extends TestBase {
}
testDataSourceFactory
();
testDataSource
();
testUnwrap
();
testXAConnection
();
deleteDb
(
"dataSource"
);
}
...
...
@@ -190,4 +194,20 @@ public class TestDataSource extends TestBase {
conn
.
close
();
}
private
void
testUnwrap
()
throws
SQLException
{
JdbcDataSource
ds
=
new
JdbcDataSource
();
assertTrue
(
ds
.
isWrapperFor
(
Object
.
class
));
assertTrue
(
ds
.
isWrapperFor
(
DataSource
.
class
));
assertTrue
(
ds
.
isWrapperFor
(
JdbcDataSource
.
class
));
assertFalse
(
ds
.
isWrapperFor
(
String
.
class
));
assertTrue
(
ds
==
ds
.
unwrap
(
Object
.
class
));
assertTrue
(
ds
==
ds
.
unwrap
(
DataSource
.
class
));
try
{
ds
.
unwrap
(
String
.
class
);
fail
();
}
catch
(
SQLException
ex
)
{
assertEquals
(
ErrorCode
.
INVALID_VALUE_2
,
ex
.
getErrorCode
());
}
}
}
h2/src/test/org/h2/test/scripts/TestScript.java
浏览文件 @
fc67a911
...
...
@@ -99,7 +99,7 @@ public class TestScript extends TestBase {
testScript
(
"datatypes/"
+
s
+
".sql"
);
}
for
(
String
s
:
new
String
[]
{
"avg"
,
"bit-and"
,
"bit-or"
,
"count"
,
"group-concat"
,
"max"
,
"min"
,
"selectivity"
,
"stddev-pop"
,
"group-concat"
,
"max"
,
"m
edian"
,
"m
in"
,
"selectivity"
,
"stddev-pop"
,
"stddev-samp"
,
"sum"
,
"var-pop"
,
"var-samp"
})
{
testScript
(
"functions/aggregate/"
+
s
+
".sql"
);
}
...
...
h2/src/test/org/h2/test/scripts/functions/aggregate/median.sql
0 → 100644
浏览文件 @
fc67a911
-- 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
--
-- ASC
create
table
test
(
v
tinyint
);
>
ok
create
index
test_idx
on
test
(
v
asc
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
-- ASC NULLS FIRST
create
table
test
(
v
tinyint
);
>
ok
create
index
test_idx
on
test
(
v
asc
nulls
first
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
-- ASC NULLS LAST
create
table
test
(
v
tinyint
);
>
ok
create
index
test_idx
on
test
(
v
asc
nulls
last
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
-- DESC
create
table
test
(
v
tinyint
);
>
ok
create
index
test_idx
on
test
(
v
desc
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
-- DESC NULLS FIRST
create
table
test
(
v
tinyint
);
>
ok
create
index
test_idx
on
test
(
v
desc
nulls
first
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
-- DESC NULLS LAST
create
table
test
(
v
tinyint
);
>
ok
create
index
test_idx
on
test
(
v
desc
nulls
last
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
create
table
test
(
v
tinyint
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
create
table
test
(
v
smallint
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
create
table
test
(
v
int
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
create
table
test
(
v
bigint
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
create
table
test
(
v
real
);
>
ok
insert
into
test
values
(
2
),
(
2
),
(
1
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
2
.
0
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
2
.
0
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
1
.
5
insert
into
test
values
(
1
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
1
.
5
drop
table
test
;
>
ok
create
table
test
(
v
double
);
>
ok
insert
into
test
values
(
2
),
(
2
),
(
1
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
2
.
0
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
2
.
0
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
1
.
5
insert
into
test
values
(
1
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
1
.
5
drop
table
test
;
>
ok
create
table
test
(
v
numeric
(
1
));
>
ok
insert
into
test
values
(
2
),
(
2
),
(
1
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
2
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
2
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
1
.
5
insert
into
test
values
(
1
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
1
.
5
drop
table
test
;
>
ok
create
table
test
(
v
time
);
>
ok
insert
into
test
values
(
'20:00:00'
),
(
'20:00:00'
),
(
'10:00:00'
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
:
00
:
00
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
:
00
:
00
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
:
00
:
00
insert
into
test
values
(
'10:00:00'
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
:
00
:
00
drop
table
test
;
>
ok
create
table
test
(
v
date
);
>
ok
insert
into
test
values
(
'2000-01-20'
),
(
'2000-01-20'
),
(
'2000-01-10'
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
----------
>
2000
-
01
-
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
----------
>
2000
-
01
-
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
2000
-
01
-
15
insert
into
test
values
(
'2000-01-10'
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
----------
>
2000
-
01
-
15
drop
table
test
;
>
ok
create
table
test
(
v
timestamp
);
>
ok
insert
into
test
values
(
'2000-01-20 20:00:00'
),
(
'2000-01-20 20:00:00'
),
(
'2000-01-10 10:00:00'
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------------------
>
2000
-
01
-
20
20
:
00
:
00
.
0
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------------------
>
2000
-
01
-
20
20
:
00
:
00
.
0
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
---------------------
>
2000
-
01
-
15
15
:
00
:
00
.
0
insert
into
test
values
(
'2000-01-10 10:00:00'
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------------------
>
2000
-
01
-
15
15
:
00
:
00
.
0
delete
from
test
;
>
update
count
:
5
insert
into
test
values
(
'2000-01-20 20:00:00'
),
(
'2000-01-21 20:00:00'
);
>
update
count
:
2
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------------------
>
2000
-
01
-
21
08
:
00
:
00
.
0
drop
table
test
;
>
ok
create
table
test
(
v
timestamp
with
time
zone
);
>
ok
insert
into
test
values
(
'2000-01-20 20:00:00+04'
),
(
'2000-01-20 20:00:00+04'
),
(
'2000-01-10 10:00:00+02'
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
------------------------
>
2000
-
01
-
20
20
:
00
:
00
.
0
+
04
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
------------------------
>
2000
-
01
-
20
20
:
00
:
00
.
0
+
04
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------------
>
2000
-
01
-
15
15
:
00
:
00
.
0
+
03
insert
into
test
values
(
'2000-01-10 10:00:00+02'
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
------------------------
>
2000
-
01
-
15
15
:
00
:
00
.
0
+
03
delete
from
test
;
>
update
count
:
5
insert
into
test
values
(
'2000-01-20 20:00:00+10:15'
),
(
'2000-01-21 20:00:00-09'
);
>
update
count
:
2
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------------------------
>
2000
-
01
-
21
08
:
00
:
30
.
0
+
00
:
37
drop
table
test
;
>
ok
-- with group by
create
table
test
(
name
varchar
,
value
int
);
>
ok
insert
into
test
values
(
'Group 2A'
,
10
),
(
'Group 2A'
,
10
),
(
'Group 2A'
,
20
),
(
'Group 1X'
,
40
),
(
'Group 1X'
,
50
),
(
'Group 3B'
,
null
);
>
update
count
:
6
select
name
,
median
(
value
)
from
test
group
by
name
order
by
name
;
>
NAME
MEDIAN
(
VALUE
)
>
-------- -------------
>
Group
1
X
45
>
Group
2
A
10
>
Group
3
B
null
>
rows
(
ordered
):
3
drop
table
test
;
>
ok
-- with filter
create
table
test
(
v
int
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
where
v
<>
20
;
>
MEDIAN
(
V
)
>
---------
>
10
create
index
test_idx
on
test
(
v
asc
);
>
ok
select
median
(
v
)
from
test
where
v
<>
20
;
>
MEDIAN
(
V
)
>
---------
>
10
drop
table
test
;
>
ok
-- two-column index
create
table
test
(
v
int
,
v2
int
);
>
ok
create
index
test_idx
on
test
(
v
,
v2
);
>
ok
insert
into
test
values
(
20
,
1
),
(
10
,
2
),
(
20
,
3
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
drop
table
test
;
>
ok
-- not null column
create
table
test
(
v
int
not
null
);
>
ok
create
index
test_idx
on
test
(
v
desc
);
>
ok
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
null
insert
into
test
values
(
10
),
(
20
);
>
update
count
:
2
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
insert
into
test
values
(
20
),
(
10
),
(
20
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
drop
table
test
;
>
ok
h2/src/test/org/h2/test/unit/TestTools.java
浏览文件 @
fc67a911
...
...
@@ -139,7 +139,7 @@ public class TestTools extends TestBase {
c
.
runTool
(
"-web"
,
"-webPort"
,
"9002"
,
"-tool"
,
"-browser"
,
"-tcp"
,
"-tcpPort"
,
"9003"
,
"-pg"
,
"-pgPort"
,
"9004"
);
assertContains
(
lastUrl
,
":9002"
);
c
.
shutdown
(
);
shutdownConsole
(
c
);
// check if starting the browser works
c
.
runTool
(
"-web"
,
"-webPort"
,
"9002"
,
"-tool"
);
...
...
@@ -169,7 +169,7 @@ public class TestTools extends TestBase {
// ignore
}
c
.
shutdown
(
);
shutdownConsole
(
c
);
// trying to use the same port for two services should fail,
// but also stop the first service
...
...
@@ -184,7 +184,19 @@ public class TestTools extends TestBase {
}
else
{
System
.
clearProperty
(
SysProperties
.
H2_BROWSER
);
}
c
.
shutdown
();
shutdownConsole
(
c
);
}
}
private
static
void
shutdownConsole
(
Console
c
)
{
c
.
shutdown
();
if
(
Thread
.
currentThread
().
isInterrupted
())
{
// Clear interrupted state so test can continue its work safely
try
{
Thread
.
sleep
(
1
);
}
catch
(
InterruptedException
e
)
{
// Ignore
}
}
}
...
...
h2/src/test/org/h2/test/unit/TestValue.java
浏览文件 @
fc67a911
...
...
@@ -307,10 +307,10 @@ public class TestValue extends TestBase {
}
private
void
testTimestamp
()
{
ValueTimestamp
v
t
s
=
ValueTimestamp
.
parse
(
"2000-01-15 10:20:30.333222111"
);
ValueTimestamp
v
alueT
s
=
ValueTimestamp
.
parse
(
"2000-01-15 10:20:30.333222111"
);
Timestamp
ts
=
Timestamp
.
valueOf
(
"2000-01-15 10:20:30.333222111"
);
assertEquals
(
ts
.
toString
(),
v
t
s
.
getString
());
assertEquals
(
ts
,
v
t
s
.
getTimestamp
());
assertEquals
(
ts
.
toString
(),
v
alueT
s
.
getString
());
assertEquals
(
ts
,
v
alueT
s
.
getTimestamp
());
Calendar
c
=
Calendar
.
getInstance
(
TimeZone
.
getTimeZone
(
"Europe/Berlin"
));
c
.
set
(
2018
,
02
,
25
,
1
,
59
,
00
);
c
.
set
(
Calendar
.
MILLISECOND
,
123
);
...
...
h2/src/tools/org/h2/build/doc/dictionary.txt
浏览文件 @
fc67a911
...
...
@@ -760,5 +760,6 @@ zzbbzz cldr booleans maria enquotes mtc cbuf checksummed nreturn despite bbzz re
unconditionally coco aren eecccc decimals charsets zzbb lsb msb usecount outdir endian misleading precompiled
assorted reimplemented hangups confirmation predefined
mdy destfile hclf forbids spellchecking selfdestruct expects accident jacocoagent cli historic mitigate
jacoco xdata invokes sourcefiles classfiles duplication crypto stacktraces prt directions handled overly asm hardcoded
mdy destfile hclf forbids spellchecking selfdestruct expects accident jacocoagent cli historic mitigate
jacoco xdata invokes sourcefiles classfiles duplication crypto stacktraces prt directions handled overly asm hardcoded
interpolated thead
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论