Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
0bed9d12
Unverified
提交
0bed9d12
authored
1月 15, 2019
作者:
Evgenij Ryazanov
提交者:
GitHub
1月 15, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1667 from katzyn/window
Detect NULL values and overflow in window frame bounds
上级
a092ef8b
de5f2b14
隐藏空白字符变更
内嵌
并排
正在显示
21 个修改的文件
包含
318 行增加
和
51 行删除
+318
-51
help.csv
h2/src/docsrc/help/help.csv
+1
-0
changelog.html
h2/src/docsrc/html/changelog.html
+4
-0
_messages_en.prop
h2/src/docsrc/textbase/_messages_en.prop
+1
-0
ErrorCode.java
h2/src/main/org/h2/api/ErrorCode.java
+9
-0
DataAnalysisOperation.java
...ain/org/h2/expression/analysis/DataAnalysisOperation.java
+24
-7
WindowFrame.java
h2/src/main/org/h2/expression/analysis/WindowFrame.java
+132
-38
WindowFrameBound.java
h2/src/main/org/h2/expression/analysis/WindowFrameBound.java
+9
-0
JdbcPreparedStatement.java
h2/src/main/org/h2/jdbc/JdbcPreparedStatement.java
+10
-5
_messages_cs.prop
h2/src/main/org/h2/res/_messages_cs.prop
+1
-0
_messages_de.prop
h2/src/main/org/h2/res/_messages_de.prop
+1
-0
_messages_en.prop
h2/src/main/org/h2/res/_messages_en.prop
+1
-0
_messages_es.prop
h2/src/main/org/h2/res/_messages_es.prop
+1
-0
_messages_fr.prop
h2/src/main/org/h2/res/_messages_fr.prop
+1
-0
_messages_ja.prop
h2/src/main/org/h2/res/_messages_ja.prop
+1
-0
_messages_pl.prop
h2/src/main/org/h2/res/_messages_pl.prop
+1
-0
_messages_pt_br.prop
h2/src/main/org/h2/res/_messages_pt_br.prop
+1
-0
_messages_ru.prop
h2/src/main/org/h2/res/_messages_ru.prop
+1
-0
_messages_sk.prop
h2/src/main/org/h2/res/_messages_sk.prop
+1
-0
_messages_zh_cn.prop
h2/src/main/org/h2/res/_messages_zh_cn.prop
+1
-0
array-agg.sql
...est/org/h2/test/scripts/functions/aggregate/array-agg.sql
+1
-1
window.sql
h2/src/test/org/h2/test/scripts/window.sql
+116
-0
没有找到文件。
h2/src/docsrc/help/help.csv
浏览文件 @
0bed9d12
...
...
@@ -5559,6 +5559,7 @@ OVER windowNameOrSpecification
","
Returns the ratio of a value to the sum of all values.
If argument is NULL or sum of all values is 0, then the value of function is NULL.
Window frame clause is not allowed for this function.
Window functions are currently experimental in H2 and should be used with caution.
They also may require a lot of memory for large queries.
...
...
h2/src/docsrc/html/changelog.html
浏览文件 @
0bed9d12
...
...
@@ -21,6 +21,10 @@ Change Log
<h2>
Next Version (unreleased)
</h2>
<ul>
<li>
Issue #1604: TestCrashAPI: PreparedStatement.getGeneratedKeys() is already closed
</li>
<li>
PR #1667: Detect NULL values and overflow in window frame bounds
</li>
<li>
PR #1664: Allow any expressions in window frames
</li>
<li>
Issue #1576: H2 Console should not display precision and scale for data types that don't have them
...
...
h2/src/docsrc/textbase/_messages_en.prop
浏览文件 @
0bed9d12
...
...
@@ -8,6 +8,7 @@
22004=Numeric value out of range: {0} in column {1}
22007=Cannot parse {0} constant {1}
22012=Division by zero: {0}
22013=Invalid PRECEDING or FOLLOWING size in window function: {0}
22018=Data conversion error converting {0}
22025=Error in LIKE ESCAPE: {0}
22030=Value not permitted for column {0}: {1}
...
...
h2/src/main/org/h2/api/ErrorCode.java
浏览文件 @
0bed9d12
...
...
@@ -133,6 +133,15 @@ public class ErrorCode {
*/
public
static
final
int
DIVISION_BY_ZERO_1
=
22012
;
/**
* The error with code <code>22013</code> is thrown when preceding or
* following size in a window function is null or negative. Example:
* <pre>
* FIRST_VALUE(N) OVER(ORDER BY N ROWS -1 PRECEDING)
* </pre>
*/
public
static
final
int
INVALID_PRECEDING_OR_FOLLOWING_1
=
22013
;
/**
* The error with code <code>22018</code> is thrown when
* trying to convert a value to a data type where the conversion is
...
...
h2/src/main/org/h2/expression/analysis/DataAnalysisOperation.java
浏览文件 @
0bed9d12
...
...
@@ -162,19 +162,31 @@ public abstract class DataAnalysisOperation extends Expression {
WindowFrame
frame
=
over
.
getWindowFrame
();
if
(
frame
!=
null
)
{
int
index
=
getNumExpressions
();
int
orderBySize
=
0
;
if
(
orderBy
!=
null
)
{
index
+=
orderBy
.
size
();
orderBySize
=
orderBy
.
size
();
index
+=
orderBySize
;
}
int
n
=
0
;
WindowFrameBound
bound
=
frame
.
getStarting
();
if
(
bound
.
isVariable
())
{
bound
.
setExpressionIndex
(
index
);
n
++;
if
(
bound
.
isParameterized
())
{
if
(
orderBySize
!=
1
)
{
throw
getSingleSortKeyException
();
}
if
(
bound
.
isVariable
())
{
bound
.
setExpressionIndex
(
index
);
n
++;
}
}
bound
=
frame
.
getFollowing
();
if
(
bound
!=
null
&&
bound
.
isVariable
())
{
bound
.
setExpressionIndex
(
index
+
n
);
n
++;
if
(
bound
!=
null
&&
bound
.
isParameterized
())
{
if
(
orderBySize
!=
1
)
{
throw
getSingleSortKeyException
();
}
if
(
bound
.
isVariable
())
{
bound
.
setExpressionIndex
(
index
+
n
);
n
++;
}
}
numFrameExpressions
=
n
;
}
...
...
@@ -182,6 +194,11 @@ public abstract class DataAnalysisOperation extends Expression {
return
this
;
}
private
DbException
getSingleSortKeyException
()
{
String
sql
=
getSQL
();
return
DbException
.
getSyntaxError
(
sql
,
sql
.
length
()
-
1
,
"exactly one sort key is required for RANGE units"
);
}
@Override
public
void
setEvaluatable
(
TableFilter
tableFilter
,
boolean
b
)
{
if
(
over
!=
null
)
{
...
...
h2/src/main/org/h2/expression/analysis/WindowFrame.java
浏览文件 @
0bed9d12
...
...
@@ -10,15 +10,17 @@ import java.util.Collections;
import
java.util.Iterator
;
import
java.util.NoSuchElementException
;
import
org.h2.api.ErrorCode
;
import
org.h2.engine.Session
;
import
org.h2.expression.BinaryOperation
;
import
org.h2.expression.Expression
;
import
org.h2.expression.BinaryOperation.OpType
;
import
org.h2.expression.Expression
;
import
org.h2.expression.ValueExpression
;
import
org.h2.message.DbException
;
import
org.h2.result.SortOrder
;
import
org.h2.table.ColumnResolver
;
import
org.h2.value.Value
;
import
org.h2.value.ValueNull
;
/**
* Window frame clause.
...
...
@@ -290,29 +292,94 @@ public final class WindowFrame {
private
static
int
getIntOffset
(
WindowFrameBound
bound
,
Value
[]
values
,
Session
session
)
{
Value
v
=
bound
.
isVariable
()
?
values
[
bound
.
getExpressionIndex
()]
:
bound
.
getValue
().
getValue
(
session
);
int
value
=
v
.
getInt
();
if
(
value
<
0
)
{
throw
DbException
.
get
InvalidValueException
(
"unsigned"
,
value
);
if
(
v
==
ValueNull
.
INSTANCE
||
v
alue
<
0
)
{
throw
DbException
.
get
(
ErrorCode
.
INVALID_PRECEDING_OR_FOLLOWING_1
,
v
.
getTraceSQL
()
);
}
return
value
;
}
/**
* Appends bound value to the current row and produces row for comparison
* operations.
*
* @param session
* the session
* @param orderedRows
* rows in partition
* @param sortOrder
* the sort order
* @param currentRow
* index of the current row
* @param bound
* window frame bound
* @param add
* false for PRECEDING, true for FOLLOWING
* @return row for comparison operations, or null if result is out of range
* and should be treated as UNLIMITED
*/
private
static
Value
[]
getCompareRow
(
Session
session
,
ArrayList
<
Value
[]>
orderedRows
,
SortOrder
sortOrder
,
int
currentRow
,
WindowFrameBound
bound
,
boolean
add
)
{
int
sortIndex
=
sortOrder
.
getQueryColumnIndexes
()[
0
];
OpType
opType
=
add
^
(
sortOrder
.
getSortTypes
()[
0
]
&
SortOrder
.
DESCENDING
)
!=
0
?
OpType
.
PLUS
:
OpType
.
MINUS
;
Value
[]
row
=
orderedRows
.
get
(
currentRow
);
Value
currentValue
=
row
[
sortIndex
];
int
type
=
currentValue
.
getType
();
Value
newValue
;
Value
range
=
getValueOffset
(
bound
,
orderedRows
.
get
(
currentRow
),
session
);
switch
(
type
)
{
case
Value
.
NULL
:
newValue
=
ValueNull
.
INSTANCE
;
break
;
case
Value
.
BYTE
:
case
Value
.
SHORT
:
case
Value
.
INT
:
case
Value
.
LONG
:
case
Value
.
DECIMAL
:
case
Value
.
DOUBLE
:
case
Value
.
FLOAT
:
case
Value
.
TIME
:
case
Value
.
DATE
:
case
Value
.
TIMESTAMP
:
case
Value
.
TIMESTAMP_TZ
:
case
Value
.
INTERVAL_YEAR
:
case
Value
.
INTERVAL_MONTH
:
case
Value
.
INTERVAL_DAY
:
case
Value
.
INTERVAL_HOUR
:
case
Value
.
INTERVAL_MINUTE
:
case
Value
.
INTERVAL_SECOND
:
case
Value
.
INTERVAL_YEAR_TO_MONTH
:
case
Value
.
INTERVAL_DAY_TO_HOUR
:
case
Value
.
INTERVAL_DAY_TO_MINUTE
:
case
Value
.
INTERVAL_DAY_TO_SECOND
:
case
Value
.
INTERVAL_HOUR_TO_MINUTE
:
case
Value
.
INTERVAL_HOUR_TO_SECOND
:
case
Value
.
INTERVAL_MINUTE_TO_SECOND
:
OpType
opType
=
add
^
(
sortOrder
.
getSortTypes
()[
0
]
&
SortOrder
.
DESCENDING
)
!=
0
?
OpType
.
PLUS
:
OpType
.
MINUS
;
try
{
newValue
=
new
BinaryOperation
(
opType
,
ValueExpression
.
get
(
currentValue
),
ValueExpression
.
get
(
range
))
.
optimize
(
session
).
getValue
(
session
).
convertTo
(
type
);
}
catch
(
DbException
ex
)
{
switch
(
ex
.
getErrorCode
())
{
case
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_1
:
case
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_2
:
return
null
;
}
throw
ex
;
}
break
;
default
:
throw
DbException
.
getInvalidValueException
(
"unsupported type of sort key for RANGE units"
,
currentValue
.
getTraceSQL
());
}
Value
[]
newRow
=
row
.
clone
();
newRow
[
sortIndex
]
=
new
BinaryOperation
(
opType
,
//
ValueExpression
.
get
(
row
[
sortIndex
]),
ValueExpression
.
get
(
getValueOffset
(
bound
,
orderedRows
.
get
(
currentRow
),
session
)))
//
.
optimize
(
session
).
getValue
(
session
);
newRow
[
sortIndex
]
=
newValue
;
return
newRow
;
}
private
static
Value
getValueOffset
(
WindowFrameBound
bound
,
Value
[]
values
,
Session
session
)
{
Value
value
=
bound
.
isVariable
()
?
values
[
bound
.
getExpressionIndex
()]
:
bound
.
getValue
().
getValue
(
session
);
if
(
value
.
getSignum
()
<
0
)
{
throw
DbException
.
get
InvalidValueException
(
"unsigned"
,
value
.
getTraceSQL
());
if
(
value
==
ValueNull
.
INSTANCE
||
value
.
getSignum
()
<
0
)
{
throw
DbException
.
get
(
ErrorCode
.
INVALID_PRECEDING_OR_FOLLOWING_1
,
value
.
getTraceSQL
());
}
return
value
;
}
...
...
@@ -544,6 +611,25 @@ public final class WindowFrame {
return
endIndex
;
}
/**
* Returns starting or ending index of a window frame.
*
* @param session
* the session
* @param orderedRows
* rows in partition
* @param sortOrder
* the sort order
* @param currentRow
* index of the current row
* @param bound
* window frame bound
* @param forFollowing
* false for start index, true for end index
* @return starting or ending index of a window frame (inclusive), can be 0
* or be equal to the number of rows if frame is not limited from
* that side
*/
private
int
getIndex
(
Session
session
,
ArrayList
<
Value
[]>
orderedRows
,
SortOrder
sortOrder
,
int
currentRow
,
WindowFrameBound
bound
,
boolean
forFollowing
)
{
int
size
=
orderedRows
.
size
();
...
...
@@ -587,26 +673,30 @@ public final class WindowFrame {
case
RANGE:
{
index
=
currentRow
;
Value
[]
row
=
getCompareRow
(
session
,
orderedRows
,
sortOrder
,
index
,
bound
,
false
);
index
=
Collections
.
binarySearch
(
orderedRows
,
row
,
sortOrder
);
if
(
index
>=
0
)
{
if
(!
forFollowing
)
{
while
(
index
>
0
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
index
-
1
))
==
0
)
{
index
--;
if
(
row
!=
null
)
{
index
=
Collections
.
binarySearch
(
orderedRows
,
row
,
sortOrder
);
if
(
index
>=
0
)
{
if
(!
forFollowing
)
{
while
(
index
>
0
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
index
-
1
))
==
0
)
{
index
--;
}
}
else
{
while
(
index
<
last
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
index
+
1
))
==
0
)
{
index
++;
}
}
}
else
{
while
(
index
<
last
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
index
+
1
))
==
0
)
{
index
++;
index
=
~
index
;
if
(!
forFollowing
)
{
if
(
index
==
0
)
{
index
=
-
1
;
}
}
else
{
index
--;
}
}
}
else
{
index
=
~
index
;
if
(!
forFollowing
)
{
if
(
index
==
0
)
{
index
=
-
1
;
}
}
else
{
index
--;
}
index
=
-
1
;
}
break
;
}
...
...
@@ -663,24 +753,28 @@ public final class WindowFrame {
case
RANGE:
{
index
=
currentRow
;
Value
[]
row
=
getCompareRow
(
session
,
orderedRows
,
sortOrder
,
index
,
bound
,
true
);
index
=
Collections
.
binarySearch
(
orderedRows
,
row
,
sortOrder
);
if
(
index
>=
0
)
{
if
(
forFollowing
)
{
while
(
index
<
last
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
index
+
1
))
==
0
)
{
index
++;
if
(
row
!=
null
)
{
index
=
Collections
.
binarySearch
(
orderedRows
,
row
,
sortOrder
);
if
(
index
>=
0
)
{
if
(
forFollowing
)
{
while
(
index
<
last
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
index
+
1
))
==
0
)
{
index
++;
}
}
else
{
while
(
index
>
0
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
index
-
1
))
==
0
)
{
index
--;
}
}
}
else
{
while
(
index
>
0
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
index
-
1
))
==
0
)
{
index
--;
index
=
~
index
;
if
(
forFollowing
)
{
if
(
index
!=
size
)
{
index
--;
}
}
}
}
else
{
index
=
~
index
;
if
(
forFollowing
)
{
if
(
index
!=
size
)
{
index
--;
}
}
index
=
size
;
}
break
;
}
...
...
h2/src/main/org/h2/expression/analysis/WindowFrameBound.java
浏览文件 @
0bed9d12
...
...
@@ -57,6 +57,15 @@ public class WindowFrameBound {
return
value
;
}
/**
* Returns whether bound is defined as n PRECEDING or n FOLLOWING.
*
* @return whether bound is defined as n PRECEDING or n FOLLOWING
*/
public
boolean
isParameterized
()
{
return
type
==
WindowFrameBoundType
.
PRECEDING
||
type
==
WindowFrameBoundType
.
FOLLOWING
;
}
/**
* Returns whether bound is defined with a variable. This method may be used
* only after {@link #optimize(Session)} invocation.
...
...
h2/src/main/org/h2/jdbc/JdbcPreparedStatement.java
浏览文件 @
0bed9d12
...
...
@@ -1309,12 +1309,17 @@ public class JdbcPreparedStatement extends JdbcStatement implements
@Override
public
ResultSet
getGeneratedKeys
()
throws
SQLException
{
if
(
batchIdentities
!=
null
)
{
int
id
=
getNextId
(
TraceObject
.
RESULT_SET
);
if
(
isDebugEnabled
())
{
debugCodeAssign
(
"ResultSet"
,
TraceObject
.
RESULT_SET
,
id
,
"getGeneratedKeys()"
);
try
{
int
id
=
getNextId
(
TraceObject
.
RESULT_SET
);
if
(
isDebugEnabled
())
{
debugCodeAssign
(
"ResultSet"
,
TraceObject
.
RESULT_SET
,
id
,
"getGeneratedKeys()"
);
}
checkClosed
();
generatedKeys
=
new
JdbcResultSet
(
conn
,
this
,
null
,
batchIdentities
.
getResult
(),
id
,
false
,
true
,
false
);
}
catch
(
Exception
e
)
{
throw
logAndConvert
(
e
);
}
checkClosed
();
generatedKeys
=
new
JdbcResultSet
(
conn
,
this
,
null
,
batchIdentities
.
getResult
(),
id
,
false
,
true
,
false
);
}
return
super
.
getGeneratedKeys
();
}
...
...
h2/src/main/org/h2/res/_messages_cs.prop
浏览文件 @
0bed9d12
...
...
@@ -8,6 +8,7 @@
22004=#Numeric value out of range: {0} in column {1}
22007=Nelze zpracovat konstantu {0} {1}
22012=Dělení nulou: {0}
22013=#Invalid PRECEDING or FOLLOWING size in window function: {0}
22018=Chyba při převodu dat {0}
22025=Chyba v LIKE escapování: {0}
22030=#Value not permitted for column {0}: {1}
...
...
h2/src/main/org/h2/res/_messages_de.prop
浏览文件 @
0bed9d12
...
...
@@ -8,6 +8,7 @@
22004=Numerischer Wert ausserhalb des Bereichs: {0} in Feld {1}
22007=Kann {0} {1} nicht umwandeln
22012=Division durch 0: {0}
22013=#Invalid PRECEDING or FOLLOWING size in window function: {0}
22018=Datenumwandlungsfehler beim Umwandeln von {0}
22025=Fehler in LIKE ESCAPE: {0}
22030=Wert nicht erlaubt für Feld {0}: {1}
...
...
h2/src/main/org/h2/res/_messages_en.prop
浏览文件 @
0bed9d12
...
...
@@ -8,6 +8,7 @@
22004=Numeric value out of range: {0} in column {1}
22007=Cannot parse {0} constant {1}
22012=Division by zero: {0}
22013=Invalid PRECEDING or FOLLOWING size in window function: {0}
22018=Data conversion error converting {0}
22025=Error in LIKE ESCAPE: {0}
22030=Value not permitted for column {0}: {1}
...
...
h2/src/main/org/h2/res/_messages_es.prop
浏览文件 @
0bed9d12
...
...
@@ -8,6 +8,7 @@
22004=#Numeric value out of range: {0} in column {1}
22007=Imposible interpretar la constante {0} {1}
22012=División por cero: {0}
22013=#Invalid PRECEDING or FOLLOWING size in window function: {0}
22018=Conversión de datos fallida, convirtiendo {0}
22025=Error en LIKE ESCAPE: {0}
22030=Valor no permitido para la columna {0}: {1}
...
...
h2/src/main/org/h2/res/_messages_fr.prop
浏览文件 @
0bed9d12
...
...
@@ -8,6 +8,7 @@
22004=#Numeric value out of range: {0} in column {1}
22007=Impossible d''analyser {0} constante {1}
22012=Division par zéro: {0}
22013=#Invalid PRECEDING or FOLLOWING size in window function: {0}
22018=Erreur lors de la conversion de données {0}
22025=Erreur dans LIKE ESCAPE: {0}
22030=Valeur non permise pour la colonne {0}: {1}
...
...
h2/src/main/org/h2/res/_messages_ja.prop
浏览文件 @
0bed9d12
...
...
@@ -8,6 +8,7 @@
22004=#Numeric value out of range: {0} in column {1}
22007={0} 定数 {1} を解析できません
22012=ゼロで除算しました: {0}
22013=#Invalid PRECEDING or FOLLOWING size in window function: {0}
22018=データ変換中にエラーが発生しました {0}
22025=LIKE ESCAPE にエラーがあります: {0}
22030=#Value not permitted for column {0}: {1}
...
...
h2/src/main/org/h2/res/_messages_pl.prop
浏览文件 @
0bed9d12
...
...
@@ -8,6 +8,7 @@
22004=#Numeric value out of range: {0} in column {1}
22007=Nie można odczytać {0} jako {1}
22012=Dzielenie przez zero: {0}
22013=#Invalid PRECEDING or FOLLOWING size in window function: {0}
22018=Błąd konwersji danych {0}
22025=Błąd w LIKE ESCAPE: {0}
22030=#Value not permitted for column {0}: {1}
...
...
h2/src/main/org/h2/res/_messages_pt_br.prop
浏览文件 @
0bed9d12
...
...
@@ -8,6 +8,7 @@
22004=#Numeric value out of range: {0} in column {1}
22007=Não é possível converter {1} para {0}
22012=Divisão por zero: {0}
22013=#Invalid PRECEDING or FOLLOWING size in window function: {0}
22018=Erro na conversão de dado, convertendo {0}
22025=Erro em LIKE ESCAPE: {0}
22030=#Value not permitted for column {0}: {1}
...
...
h2/src/main/org/h2/res/_messages_ru.prop
浏览文件 @
0bed9d12
...
...
@@ -8,6 +8,7 @@
22004=Численное значение вне допустимого диапазона: {0} в столбце {1}
22007=Невозможно преобразование строки {1} в тип {0}
22012=Деление на ноль: {0}
22013=Недопустимое значение PRECEDING или FOLLOWING в оконной функции: {0}
22018=Ошибка преобразования данных при конвертации {0}
22025=Ошибка в LIKE ESCAPE: {0}
22030=Недопустимое значение для столбца {0}: {1}
...
...
h2/src/main/org/h2/res/_messages_sk.prop
浏览文件 @
0bed9d12
...
...
@@ -8,6 +8,7 @@
22004=#Numeric value out of range: {0} in column {1}
22007=Nemožem rozobrať {0} konštantu {1}
22012=Delenie nulou: {0}
22013=#Invalid PRECEDING or FOLLOWING size in window function: {0}
22018=Chyba konverzie dát pre {0}
22025=Chyba v LIKE ESCAPE: {0}
22030=#Value not permitted for column {0}: {1}
...
...
h2/src/main/org/h2/res/_messages_zh_cn.prop
浏览文件 @
0bed9d12
...
...
@@ -8,6 +8,7 @@
22004=#Numeric value out of range: {0} in column {1}
22007=不能解析字段 {0} 的数值 :{1}
22012=除数为零: {0}
22013=#Invalid PRECEDING or FOLLOWING size in window function: {0}
22018=转换数据{0}期间出现转换错误
22025=LIKE ESCAPE(转义符)存在错误: {0}
22030=#Value not permitted for column {0}: {1}
...
...
h2/src/test/org/h2/test/scripts/functions/aggregate/array-agg.sql
浏览文件 @
0bed9d12
...
...
@@ -345,7 +345,7 @@ SELECT *,
>
rows
:
8
SELECT
*
,
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
VALUE
ROWS
-
1
PRECEDING
)
FROM
TEST
;
>
exception
INVALID_
VALUE_2
>
exception
INVALID_
PRECEDING_OR_FOLLOWING_1
SELECT
*
,
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
ID
ROWS
BETWEEN
2
PRECEDING
AND
1
PRECEDING
)
FROM
TEST
FETCH
FIRST
4
ROWS
ONLY
;
>
ID
VALUE
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
ID
ROWS
BETWEEN
2
PRECEDING
AND
1
PRECEDING
)
...
...
h2/src/test/org/h2/test/scripts/window.sql
浏览文件 @
0bed9d12
...
...
@@ -109,5 +109,121 @@ SELECT ROW_NUMBER() OVER (ORDER BY CATEGORY), SUM(ID) FROM TEST GROUP BY CATEGOR
>
1
12
>
rows
:
1
SELECT
SUM
(
ID
)
OVER
(
ORDER
BY
ID
ROWS
NULL
PRECEDING
)
P
FROM
TEST
;
>
exception
INVALID_PRECEDING_OR_FOLLOWING_1
SELECT
SUM
(
ID
)
OVER
(
ORDER
BY
ID
RANGE
NULL
PRECEDING
)
P
FROM
TEST
;
>
exception
INVALID_PRECEDING_OR_FOLLOWING_1
SELECT
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
V
NULLS
FIRST
RANGE
BETWEEN
1
PRECEDING
AND
UNBOUNDED
FOLLOWING
)
A
,
ID
,
V
FROM
VALUES
(
1
,
1
),
(
2
,
NULL
),
(
3
,
2
)
T
(
ID
,
V
)
ORDER
BY
V
NULLS
FIRST
;
>
A
ID
V
>
--------- -- ----
>
[
3
,
1
,
2
]
2
null
>
[
3
,
1
]
1
1
>
[
3
,
1
]
3
2
>
rows
(
ordered
):
3
SELECT
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
V
NULLS
LAST
RANGE
BETWEEN
1
PRECEDING
AND
UNBOUNDED
FOLLOWING
)
A
,
ID
,
V
FROM
VALUES
(
1
,
1
),
(
2
,
NULL
),
(
3
,
2
)
T
(
ID
,
V
)
ORDER
BY
V
NULLS
LAST
;
>
A
ID
V
>
--------- -- ----
>
[
2
,
3
,
1
]
1
1
>
[
2
,
3
,
1
]
3
2
>
[
2
]
2
null
>
rows
(
ordered
):
3
SELECT
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
V
NULLS
FIRST
RANGE
BETWEEN
1
FOLLOWING
AND
UNBOUNDED
FOLLOWING
)
A
,
ID
,
V
FROM
VALUES
(
1
,
1
),
(
2
,
NULL
),
(
3
,
2
)
T
(
ID
,
V
)
ORDER
BY
V
NULLS
FIRST
;
>
A
ID
V
>
--------- -- ----
>
[
3
,
1
,
2
]
2
null
>
[
3
]
1
1
>
null
3
2
>
rows
(
ordered
):
3
SELECT
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
V
NULLS
LAST
RANGE
BETWEEN
1
FOLLOWING
AND
UNBOUNDED
FOLLOWING
)
A
,
ID
,
V
FROM
VALUES
(
1
,
1
),
(
2
,
NULL
),
(
3
,
2
)
T
(
ID
,
V
)
ORDER
BY
V
NULLS
LAST
;
>
A
ID
V
>
------ -- ----
>
[
2
,
3
]
1
1
>
[
2
]
3
2
>
[
2
]
2
null
>
rows
(
ordered
):
3
SELECT
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
V
NULLS
FIRST
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
1
FOLLOWING
)
A
,
ID
,
V
FROM
VALUES
(
1
,
1
),
(
2
,
NULL
),
(
3
,
2
)
T
(
ID
,
V
)
ORDER
BY
V
NULLS
FIRST
;
>
A
ID
V
>
--------- -- ----
>
[
2
]
2
null
>
[
2
,
1
,
3
]
1
1
>
[
2
,
1
,
3
]
3
2
>
rows
(
ordered
):
3
SELECT
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
V
NULLS
LAST
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
1
FOLLOWING
)
A
,
ID
,
V
FROM
VALUES
(
1
,
1
),
(
2
,
NULL
),
(
3
,
2
)
T
(
ID
,
V
)
ORDER
BY
V
NULLS
LAST
;
>
A
ID
V
>
--------- -- ----
>
[
1
,
3
]
1
1
>
[
1
,
3
]
3
2
>
[
1
,
3
,
2
]
2
null
>
rows
(
ordered
):
3
SELECT
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
V
NULLS
FIRST
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
1
PRECEDING
)
A
,
ID
,
V
FROM
VALUES
(
1
,
1
),
(
2
,
NULL
),
(
3
,
2
)
T
(
ID
,
V
)
ORDER
BY
V
NULLS
FIRST
;
>
A
ID
V
>
------ -- ----
>
[
2
]
2
null
>
[
2
]
1
1
>
[
2
,
1
]
3
2
>
rows
(
ordered
):
3
SELECT
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
V
NULLS
LAST
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
1
PRECEDING
)
A
,
ID
,
V
FROM
VALUES
(
1
,
1
),
(
2
,
NULL
),
(
3
,
2
)
T
(
ID
,
V
)
ORDER
BY
V
NULLS
LAST
;
>
A
ID
V
>
--------- -- ----
>
null
1
1
>
[
1
]
3
2
>
[
1
,
3
,
2
]
2
null
>
rows
(
ordered
):
3
SELECT
SUM
(
V
)
OVER
(
ORDER
BY
V
RANGE
BETWEEN
1
PRECEDING
AND
1
FOLLOWING
)
FROM
VALUES
(
TRUE
)
T
(
V
);
>
exception
INVALID_VALUE_2
SELECT
SUM
(
ID
)
OVER
(
ORDER
BY
ID
RANGE
BETWEEN
10000000000
PRECEDING
AND
CURRENT
ROW
)
P
,
SUM
(
ID
)
OVER
(
ORDER
BY
ID
RANGE
BETWEEN
10000000001
PRECEDING
AND
10000000000
PRECEDING
)
P2
,
SUM
(
ID
)
OVER
(
ORDER
BY
ID
RANGE
BETWEEN
CURRENT
ROW
AND
2147483647
FOLLOWING
)
F
,
SUM
(
ID
)
OVER
(
ORDER
BY
ID
RANGE
BETWEEN
2147483647
FOLLOWING
AND
2147483648
FOLLOWING
)
F2
,
ID
FROM
TEST
ORDER
BY
ID
;
>
P
P2
F
F2
ID
>
-- ---- -- ---- --
>
1
null
63
null
1
>
3
null
62
null
2
>
7
null
60
null
4
>
15
null
56
null
8
>
31
null
48
null
16
>
63
null
32
null
32
>
rows
(
ordered
):
6
DROP
TABLE
TEST
;
>
ok
SELECT
ARRAY_AGG
(
T
)
OVER
(
ORDER
BY
T
RANGE
BETWEEN
INTERVAL
1
DAY
PRECEDING
AND
CURRENT
ROW
)
C
,
ARRAY_AGG
(
T
)
OVER
(
ORDER
BY
T
RANGE
BETWEEN
INTERVAL
2
HOUR
PRECEDING
AND
INTERVAL
1
HOUR
PRECEDING
)
P
,
T
FROM
VALUES
(
TIME
'00:00:00'
),
(
TIME
'01:30:00'
)
TEST
(
T
)
ORDER
BY
T
;
>
C
P
T
>
-------------------- ---------- --------
>
[
00
:
00
:
00
]
null
00
:
00
:
00
>
[
00
:
00
:
00
,
01
:
30
:
00
]
[
00
:
00
:
00
]
01
:
30
:
00
>
rows
(
ordered
):
2
SELECT
SUM
(
A
)
OVER
(
ORDER
BY
A
,
B
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
UNBOUNDED
FOLLOWING
)
S
FROM
VALUES
(
1
,
2
)
T
(
A
,
B
);
>>
1
SELECT
SUM
(
A
)
OVER
(
ORDER
BY
A
,
B
RANGE
BETWEEN
1
PRECEDING
AND
UNBOUNDED
FOLLOWING
)
S
FROM
VALUES
(
1
,
2
)
T
(
A
,
B
);
>
exception
SYNTAX_ERROR_2
SELECT
SUM
(
A
)
OVER
(
ORDER
BY
A
,
B
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
1
FOLLOWING
)
S
FROM
VALUES
(
1
,
2
)
T
(
A
,
B
);
>
exception
SYNTAX_ERROR_2
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论