Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
2170322c
提交
2170322c
authored
9月 18, 2018
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement remaming types of window frames
上级
88807617
隐藏空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
218 行增加
和
49 行删除
+218
-49
help.csv
h2/src/docsrc/help/help.csv
+24
-5
Parser.java
h2/src/main/org/h2/command/Parser.java
+16
-6
AbstractAggregate.java
...c/main/org/h2/expression/aggregate/AbstractAggregate.java
+1
-1
Window.java
h2/src/main/org/h2/expression/aggregate/Window.java
+1
-1
WindowFrame.java
h2/src/main/org/h2/expression/aggregate/WindowFrame.java
+127
-25
WindowFrameBound.java
...rc/main/org/h2/expression/aggregate/WindowFrameBound.java
+5
-8
WindowFunction.java
h2/src/main/org/h2/expression/aggregate/WindowFunction.java
+3
-3
array-agg.sql
...est/org/h2/test/scripts/functions/aggregate/array-agg.sql
+41
-0
没有找到文件。
h2/src/docsrc/help/help.csv
浏览文件 @
2170322c
...
@@ -2550,11 +2550,8 @@ They also may require a lot of memory for large queries.
...
@@ -2550,11 +2550,8 @@ They also may require a lot of memory for large queries.
"
"
"Other Grammar","Window frame","
"Other Grammar","Window frame","
[RANGE BETWEEN {
ROWS|RANGE|GROUP
UNBOUNDED PRECEDING AND CURRENT ROW
{windowFramePreceding|BETWEEN windowFramePreceding AND windowFrameFollowing}
|CURRENT ROW AND UNBOUNDED FOLLOWING
|UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
}]
[EXCLUDE {CURRENT ROW|GROUP|TIES|NO OTHERS}]
[EXCLUDE {CURRENT ROW|GROUP|TIES|NO OTHERS}]
","
","
A window frame clause.
A window frame clause.
...
@@ -2563,6 +2560,28 @@ Is currently supported only in aggregates and FIRST_VALUE(), LAST_VALUE(), and N
...
@@ -2563,6 +2560,28 @@ Is currently supported only in aggregates and FIRST_VALUE(), LAST_VALUE(), and N
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE GROUP
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE GROUP
"
"
"Other Grammar","Window frame preceding","
UNBOUNDED PRECEDING|value PRECEDING|CURRENT ROW
","
A window frame preceding clause.
If value is specified it should be non-negative value or parameter.
","
UNBOUNDED PRECEDING
1 PRECEDING
CURRENT ROW
"
"Other Grammar","Window frame following","
UNBOUNDED FOLLOWING|value FOLLOWING|CURRENT ROW
","
A window frame following clause.
If value is specified it should be non-negative value or parameter.
","
UNBOUNDED FOLLOWING
1 FOLLOWING
CURRENT ROW
"
"Other Grammar","Term","
"Other Grammar","Term","
value
value
| columnName
| columnName
...
...
h2/src/main/org/h2/command/Parser.java
浏览文件 @
2170322c
...
@@ -3132,13 +3132,13 @@ public class Parser {
...
@@ -3132,13 +3132,13 @@ public class Parser {
private
WindowFrameBound
readWindowFrameStarting
()
{
private
WindowFrameBound
readWindowFrameStarting
()
{
if
(
readIf
(
"UNBOUNDED"
))
{
if
(
readIf
(
"UNBOUNDED"
))
{
read
(
"PRECEDING"
);
read
(
"PRECEDING"
);
return
new
WindowFrameBound
(
WindowFrameBoundType
.
UNBOUNDED
,
0
);
return
new
WindowFrameBound
(
WindowFrameBoundType
.
UNBOUNDED
,
null
);
}
}
if
(
readIf
(
"CURRENT"
))
{
if
(
readIf
(
"CURRENT"
))
{
read
(
"ROW"
);
read
(
"ROW"
);
return
new
WindowFrameBound
(
WindowFrameBoundType
.
CURRENT_ROW
,
0
);
return
new
WindowFrameBound
(
WindowFrameBoundType
.
CURRENT_ROW
,
null
);
}
}
int
value
=
readNonNegativeInt
();
Expression
value
=
readValueOrParameter
();
read
(
"PRECEDING"
);
read
(
"PRECEDING"
);
return
new
WindowFrameBound
(
WindowFrameBoundType
.
VALUE
,
value
);
return
new
WindowFrameBound
(
WindowFrameBoundType
.
VALUE
,
value
);
}
}
...
@@ -3146,17 +3146,27 @@ public class Parser {
...
@@ -3146,17 +3146,27 @@ public class Parser {
private
WindowFrameBound
readWindowFrameFollowing
()
{
private
WindowFrameBound
readWindowFrameFollowing
()
{
if
(
readIf
(
"UNBOUNDED"
))
{
if
(
readIf
(
"UNBOUNDED"
))
{
read
(
"FOLLOWING"
);
read
(
"FOLLOWING"
);
return
new
WindowFrameBound
(
WindowFrameBoundType
.
UNBOUNDED
,
0
);
return
new
WindowFrameBound
(
WindowFrameBoundType
.
UNBOUNDED
,
null
);
}
}
if
(
readIf
(
"CURRENT"
))
{
if
(
readIf
(
"CURRENT"
))
{
read
(
"ROW"
);
read
(
"ROW"
);
return
new
WindowFrameBound
(
WindowFrameBoundType
.
CURRENT_ROW
,
0
);
return
new
WindowFrameBound
(
WindowFrameBoundType
.
CURRENT_ROW
,
null
);
}
}
int
value
=
readNonNegativeInt
();
Expression
value
=
readValueOrParameter
();
read
(
"FOLLOWING"
);
read
(
"FOLLOWING"
);
return
new
WindowFrameBound
(
WindowFrameBoundType
.
VALUE
,
value
);
return
new
WindowFrameBound
(
WindowFrameBoundType
.
VALUE
,
value
);
}
}
private
Expression
readValueOrParameter
()
{
int
index
=
parseIndex
;
Expression
value
=
readExpression
();
if
(!(
value
instanceof
ValueExpression
)
&&
!(
value
instanceof
Parameter
))
{
parseIndex
=
index
;
throw
getSyntaxError
();
}
return
value
;
}
private
AggregateType
getAggregateType
(
String
name
)
{
private
AggregateType
getAggregateType
(
String
name
)
{
if
(!
identifiersToUpper
)
{
if
(!
identifiersToUpper
)
{
// if not yet converted to uppercase, do it now
// if not yet converted to uppercase, do it now
...
...
h2/src/main/org/h2/expression/aggregate/AbstractAggregate.java
浏览文件 @
2170322c
...
@@ -445,7 +445,7 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -445,7 +445,7 @@ public abstract class AbstractAggregate extends Expression {
int
size
=
ordered
.
size
();
int
size
=
ordered
.
size
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
Object
aggregateData
=
createAggregateData
();
Object
aggregateData
=
createAggregateData
();
for
(
Iterator
<
Value
[]>
iter
=
frame
.
iterator
(
ordered
,
getOverOrderBySort
(),
i
,
false
);
iter
for
(
Iterator
<
Value
[]>
iter
=
frame
.
iterator
(
session
,
ordered
,
getOverOrderBySort
(),
i
,
false
);
iter
.
hasNext
();)
{
.
hasNext
();)
{
updateFromExpressions
(
session
,
aggregateData
,
iter
.
next
());
updateFromExpressions
(
session
,
aggregateData
,
iter
.
next
());
}
}
...
...
h2/src/main/org/h2/expression/aggregate/Window.java
浏览文件 @
2170322c
...
@@ -66,7 +66,7 @@ public final class Window {
...
@@ -66,7 +66,7 @@ public final class Window {
this
.
partitionBy
=
partitionBy
;
this
.
partitionBy
=
partitionBy
;
this
.
orderBy
=
orderBy
;
this
.
orderBy
=
orderBy
;
if
(
frame
==
null
)
{
if
(
frame
==
null
)
{
frame
=
new
WindowFrame
(
WindowFrameUnits
.
RANGE
,
new
WindowFrameBound
(
WindowFrameBoundType
.
UNBOUNDED
,
0
),
frame
=
new
WindowFrame
(
WindowFrameUnits
.
RANGE
,
new
WindowFrameBound
(
WindowFrameBoundType
.
UNBOUNDED
,
null
),
null
,
WindowFrameExclusion
.
EXCLUDE_NO_OTHERS
);
null
,
WindowFrameExclusion
.
EXCLUDE_NO_OTHERS
);
}
}
this
.
frame
=
frame
;
this
.
frame
=
frame
;
...
...
h2/src/main/org/h2/expression/aggregate/WindowFrame.java
浏览文件 @
2170322c
...
@@ -11,6 +11,10 @@ import java.util.Collections;
...
@@ -11,6 +11,10 @@ import java.util.Collections;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
java.util.NoSuchElementException
;
import
java.util.NoSuchElementException
;
import
org.h2.engine.Session
;
import
org.h2.expression.BinaryOperation
;
import
org.h2.expression.BinaryOperation.OpType
;
import
org.h2.expression.ValueExpression
;
import
org.h2.expression.aggregate.WindowFrameBound.WindowFrameBoundType
;
import
org.h2.expression.aggregate.WindowFrameBound.WindowFrameBoundType
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.result.SortOrder
;
import
org.h2.result.SortOrder
;
...
@@ -154,6 +158,54 @@ public final class WindowFrame {
...
@@ -154,6 +158,54 @@ public final class WindowFrame {
private
final
WindowFrameExclusion
exclusion
;
private
final
WindowFrameExclusion
exclusion
;
private
static
int
toGroupStart
(
ArrayList
<
Value
[]>
orderedRows
,
SortOrder
sortOrder
,
int
offset
,
int
minOffset
)
{
Value
[]
row
=
orderedRows
.
get
(
offset
);
while
(
offset
>
minOffset
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
offset
-
1
))
==
0
)
{
offset
--;
}
return
offset
;
}
private
static
int
toGroupEnd
(
ArrayList
<
Value
[]>
orderedRows
,
SortOrder
sortOrder
,
int
offset
,
int
maxOffset
)
{
Value
[]
row
=
orderedRows
.
get
(
offset
);
while
(
offset
<
maxOffset
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
offset
+
1
))
==
0
)
{
offset
++;
}
return
offset
;
}
private
static
int
getIntOffset
(
WindowFrameBound
bound
,
Session
session
)
{
int
value
=
bound
.
getValue
().
getValue
(
session
).
getInt
();
if
(
value
<
0
)
{
throw
DbException
.
getInvalidValueException
(
"unsigned"
,
value
);
}
return
value
;
}
private
static
Value
plus
(
Session
session
,
ArrayList
<
Value
[]>
orderedRows
,
int
currentRow
,
WindowFrameBound
bound
,
int
index
)
{
return
new
BinaryOperation
(
OpType
.
PLUS
,
//
ValueExpression
.
get
(
orderedRows
.
get
(
currentRow
)[
index
]),
ValueExpression
.
get
(
getValueOffset
(
bound
,
session
)))
//
.
optimize
(
session
).
getValue
(
session
);
}
private
static
Value
minus
(
Session
session
,
ArrayList
<
Value
[]>
orderedRows
,
int
currentRow
,
WindowFrameBound
bound
,
int
index
)
{
return
new
BinaryOperation
(
OpType
.
MINUS
,
//
ValueExpression
.
get
(
orderedRows
.
get
(
currentRow
)[
index
]),
ValueExpression
.
get
(
getValueOffset
(
bound
,
session
)))
//
.
optimize
(
session
).
getValue
(
session
);
}
private
static
Value
getValueOffset
(
WindowFrameBound
bound
,
Session
session
)
{
Value
value
=
bound
.
getValue
().
getValue
(
session
);
if
(
value
.
getSignum
()
<
0
)
{
throw
DbException
.
getInvalidValueException
(
"unsigned"
,
value
.
getTraceSQL
());
}
return
value
;
}
/**
/**
* Creates new instance of window frame clause.
* Creates new instance of window frame clause.
*
*
...
@@ -202,6 +254,8 @@ public final class WindowFrame {
...
@@ -202,6 +254,8 @@ public final class WindowFrame {
/**
/**
* Returns iterator.
* Returns iterator.
*
*
* @param session
* the session
* @param orderedRows
* @param orderedRows
* ordered rows
* ordered rows
* @param sortOrder
* @param sortOrder
...
@@ -210,13 +264,15 @@ public final class WindowFrame {
...
@@ -210,13 +264,15 @@ public final class WindowFrame {
* index of the current row
* index of the current row
* @param reverse
* @param reverse
* whether iterator should iterate in reverse order
* whether iterator should iterate in reverse order
*
* @return iterator
* @return iterator
*/
*/
public
Iterator
<
Value
[]>
iterator
(
ArrayList
<
Value
[]>
orderedRows
,
SortOrder
sortOrder
,
int
currentRow
,
public
Iterator
<
Value
[]>
iterator
(
Session
session
,
ArrayList
<
Value
[]>
orderedRows
,
SortOrder
sortOrder
,
boolean
reverse
)
{
int
currentRow
,
boolean
reverse
)
{
int
size
=
orderedRows
.
size
();
int
size
=
orderedRows
.
size
();
final
int
startIndex
;
WindowFrameBound
bound
=
starting
;
switch
(
starting
.
getType
())
{
int
startIndex
;
switch
(
bound
.
getType
())
{
case
UNBOUNDED:
case
UNBOUNDED:
startIndex
=
0
;
startIndex
=
0
;
break
;
break
;
...
@@ -226,26 +282,53 @@ public final class WindowFrame {
...
@@ -226,26 +282,53 @@ public final class WindowFrame {
case
VALUE:
case
VALUE:
switch
(
units
)
{
switch
(
units
)
{
case
ROWS:
{
case
ROWS:
{
int
value
=
starting
.
getValue
(
);
int
value
=
getIntOffset
(
bound
,
session
);
startIndex
=
value
>
currentRow
?
0
:
currentRow
-
value
;
startIndex
=
value
>
currentRow
?
0
:
currentRow
-
value
;
break
;
break
;
}
}
case
GROUPS:
{
int
value
=
getIntOffset
(
bound
,
session
);
startIndex
=
toGroupStart
(
orderedRows
,
sortOrder
,
currentRow
,
0
);
while
(
value
>
0
&&
startIndex
>
0
)
{
value
--;
startIndex
=
toGroupStart
(
orderedRows
,
sortOrder
,
startIndex
-
1
,
0
);
}
break
;
}
case
RANGE:
{
startIndex
=
currentRow
;
int
index
=
sortOrder
.
getQueryColumnIndexes
()[
0
];
if
((
sortOrder
.
getSortTypes
()[
0
]
&
SortOrder
.
DESCENDING
)
!=
0
)
{
Value
c
=
plus
(
session
,
orderedRows
,
currentRow
,
bound
,
index
);
while
(
startIndex
>
0
&&
session
.
getDatabase
().
compare
(
c
,
orderedRows
.
get
(
startIndex
-
1
)[
index
])
>=
0
)
{
startIndex
--;
}
}
else
{
Value
c
=
minus
(
session
,
orderedRows
,
currentRow
,
bound
,
index
);
while
(
startIndex
>
0
&&
session
.
getDatabase
().
compare
(
c
,
orderedRows
.
get
(
startIndex
-
1
)[
index
])
<=
0
)
{
startIndex
--;
}
}
break
;
}
default
:
default
:
// TODO
throw
DbException
.
getUnsupportedException
(
"units="
+
units
);
throw
DbException
.
getUnsupportedException
(
"units="
+
units
);
}
}
break
;
break
;
default
:
default
:
throw
DbException
.
getUnsupportedException
(
"window frame bound type="
+
starting
.
getType
());
throw
DbException
.
getUnsupportedException
(
"window frame bound type="
+
bound
.
getType
());
}
}
bound
=
following
;
int
endIndex
;
int
endIndex
;
if
(
following
==
null
)
{
if
(
bound
==
null
)
{
endIndex
=
currentRow
;
endIndex
=
currentRow
;
}
else
{
}
else
{
switch
(
following
.
getType
())
{
int
last
=
size
-
1
;
switch
(
bound
.
getType
())
{
case
UNBOUNDED:
case
UNBOUNDED:
endIndex
=
size
-
1
;
endIndex
=
last
;
break
;
break
;
case
CURRENT_ROW:
case
CURRENT_ROW:
endIndex
=
currentRow
;
endIndex
=
currentRow
;
...
@@ -253,18 +336,44 @@ public final class WindowFrame {
...
@@ -253,18 +336,44 @@ public final class WindowFrame {
case
VALUE:
case
VALUE:
switch
(
units
)
{
switch
(
units
)
{
case
ROWS:
{
case
ROWS:
{
int
value
=
following
.
getValue
();
int
value
=
getIntOffset
(
bound
,
session
);
int
rem
=
size
-
currentRow
-
1
;
int
rem
=
last
-
currentRow
;
endIndex
=
value
>
rem
?
size
-
1
:
currentRow
+
value
;
endIndex
=
value
>
rem
?
last
:
currentRow
+
value
;
break
;
}
case
GROUPS:
{
int
value
=
getIntOffset
(
bound
,
session
);
endIndex
=
toGroupEnd
(
orderedRows
,
sortOrder
,
currentRow
,
last
);
while
(
value
>
0
&&
endIndex
<
last
)
{
value
--;
endIndex
=
toGroupEnd
(
orderedRows
,
sortOrder
,
endIndex
+
1
,
last
);
}
break
;
}
case
RANGE:
{
endIndex
=
currentRow
;
int
index
=
sortOrder
.
getQueryColumnIndexes
()[
0
];
if
((
sortOrder
.
getSortTypes
()[
0
]
&
SortOrder
.
DESCENDING
)
!=
0
)
{
Value
c
=
minus
(
session
,
orderedRows
,
currentRow
,
bound
,
index
);
while
(
endIndex
<
last
&&
session
.
getDatabase
().
compare
(
c
,
orderedRows
.
get
(
endIndex
+
1
)[
index
])
<=
0
)
{
endIndex
++;
}
}
else
{
Value
c
=
plus
(
session
,
orderedRows
,
currentRow
,
bound
,
index
);
while
(
endIndex
<
last
&&
session
.
getDatabase
().
compare
(
c
,
orderedRows
.
get
(
endIndex
+
1
)[
index
])
>=
0
)
{
endIndex
++;
}
}
break
;
break
;
}
}
default
:
default
:
// TODO
throw
DbException
.
getUnsupportedException
(
"units="
+
units
);
throw
DbException
.
getUnsupportedException
(
"units="
+
units
);
}
}
break
;
break
;
default
:
default
:
throw
DbException
.
getUnsupportedException
(
"window frame bound type="
+
following
.
getType
());
throw
DbException
.
getUnsupportedException
(
"window frame bound type="
+
bound
.
getType
());
}
}
}
}
if
(
exclusion
!=
WindowFrameExclusion
.
EXCLUDE_NO_OTHERS
)
{
if
(
exclusion
!=
WindowFrameExclusion
.
EXCLUDE_NO_OTHERS
)
{
...
@@ -285,15 +394,8 @@ public final class WindowFrame {
...
@@ -285,15 +394,8 @@ public final class WindowFrame {
break
;
break
;
case
EXCLUDE_GROUP:
case
EXCLUDE_GROUP:
case
EXCLUDE_TIES:
{
case
EXCLUDE_TIES:
{
int
exStart
=
currentRow
;
int
exStart
=
toGroupStart
(
orderedRows
,
sortOrder
,
currentRow
,
startIndex
);
Value
[]
row
=
orderedRows
.
get
(
currentRow
);
int
exEnd
=
toGroupEnd
(
orderedRows
,
sortOrder
,
currentRow
,
endIndex
);
while
(
exStart
>
startIndex
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
exStart
-
1
))
==
0
)
{
exStart
--;
}
int
exEnd
=
currentRow
;
while
(
exEnd
<
endIndex
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
exEnd
+
1
))
==
0
)
{
exEnd
++;
}
set
.
clear
(
exStart
,
exEnd
+
1
);
set
.
clear
(
exStart
,
exEnd
+
1
);
if
(
exclusion
==
WindowFrameExclusion
.
EXCLUDE_TIES
)
{
if
(
exclusion
==
WindowFrameExclusion
.
EXCLUDE_TIES
)
{
set
.
set
(
currentRow
);
set
.
set
(
currentRow
);
...
...
h2/src/main/org/h2/expression/aggregate/WindowFrameBound.java
浏览文件 @
2170322c
...
@@ -37,7 +37,7 @@ public class WindowFrameBound {
...
@@ -37,7 +37,7 @@ public class WindowFrameBound {
private
final
WindowFrameBoundType
type
;
private
final
WindowFrameBoundType
type
;
private
final
int
value
;
private
final
Expression
value
;
/**
/**
* Creates new instance of window frame bound.
* Creates new instance of window frame bound.
...
@@ -47,15 +47,12 @@ public class WindowFrameBound {
...
@@ -47,15 +47,12 @@ public class WindowFrameBound {
* @param value
* @param value
* bound value, if any
* bound value, if any
*/
*/
public
WindowFrameBound
(
WindowFrameBoundType
type
,
int
value
)
{
public
WindowFrameBound
(
WindowFrameBoundType
type
,
Expression
value
)
{
this
.
type
=
type
;
this
.
type
=
type
;
if
(
type
==
WindowFrameBoundType
.
VALUE
)
{
if
(
type
==
WindowFrameBoundType
.
VALUE
)
{
if
(
value
<
0
)
{
throw
DbException
.
getInvalidValueException
(
"unsigned"
,
value
);
}
this
.
value
=
value
;
this
.
value
=
value
;
}
else
{
}
else
{
this
.
value
=
0
;
this
.
value
=
null
;
}
}
}
}
...
@@ -73,7 +70,7 @@ public class WindowFrameBound {
...
@@ -73,7 +70,7 @@ public class WindowFrameBound {
*
*
* @return the value
* @return the value
*/
*/
public
int
getValue
()
{
public
Expression
getValue
()
{
return
value
;
return
value
;
}
}
...
@@ -93,7 +90,7 @@ public class WindowFrameBound {
...
@@ -93,7 +90,7 @@ public class WindowFrameBound {
case
CURRENT_ROW:
case
CURRENT_ROW:
return
"CURRENT ROW"
;
return
"CURRENT ROW"
;
case
VALUE:
case
VALUE:
return
value
+
(
following
?
" FOLLOWING"
:
" PRECEDING"
);
return
value
.
getSQL
()
+
(
following
?
" FOLLOWING"
:
" PRECEDING"
);
default
:
default
:
throw
DbException
.
throwInternalError
(
"type="
+
type
);
throw
DbException
.
throwInternalError
(
"type="
+
type
);
}
}
...
...
h2/src/main/org/h2/expression/aggregate/WindowFunction.java
浏览文件 @
2170322c
...
@@ -321,11 +321,11 @@ public class WindowFunction extends AbstractAggregate {
...
@@ -321,11 +321,11 @@ public class WindowFunction extends AbstractAggregate {
Value
v
;
Value
v
;
switch
(
type
)
{
switch
(
type
)
{
case
FIRST_VALUE:
{
case
FIRST_VALUE:
{
v
=
getNthValue
(
frame
.
iterator
(
ordered
,
getOverOrderBySort
(),
i
,
false
),
0
,
ignoreNulls
);
v
=
getNthValue
(
frame
.
iterator
(
session
,
ordered
,
getOverOrderBySort
(),
i
,
false
),
0
,
ignoreNulls
);
break
;
break
;
}
}
case
LAST_VALUE:
case
LAST_VALUE:
v
=
getNthValue
(
frame
.
iterator
(
ordered
,
getOverOrderBySort
(),
i
,
true
),
0
,
ignoreNulls
);
v
=
getNthValue
(
frame
.
iterator
(
session
,
ordered
,
getOverOrderBySort
(),
i
,
true
),
0
,
ignoreNulls
);
break
;
break
;
case
NTH_VALUE:
{
case
NTH_VALUE:
{
int
n
=
row
[
1
].
getInt
();
int
n
=
row
[
1
].
getInt
();
...
@@ -333,7 +333,7 @@ public class WindowFunction extends AbstractAggregate {
...
@@ -333,7 +333,7 @@ public class WindowFunction extends AbstractAggregate {
throw
DbException
.
getInvalidValueException
(
"nth row"
,
n
);
throw
DbException
.
getInvalidValueException
(
"nth row"
,
n
);
}
}
n
--;
n
--;
Iterator
<
Value
[]>
iter
=
frame
.
iterator
(
ordered
,
getOverOrderBySort
(),
i
,
fromLast
);
Iterator
<
Value
[]>
iter
=
frame
.
iterator
(
session
,
ordered
,
getOverOrderBySort
(),
i
,
fromLast
);
v
=
getNthValue
(
iter
,
n
,
ignoreNulls
);
v
=
getNthValue
(
iter
,
n
,
ignoreNulls
);
break
;
break
;
}
}
...
...
h2/src/test/org/h2/test/scripts/functions/aggregate/array-agg.sql
浏览文件 @
2170322c
...
@@ -275,3 +275,44 @@ SELECT
...
@@ -275,3 +275,44 @@ SELECT
DROP
TABLE
TEST
;
DROP
TABLE
TEST
;
>
ok
>
ok
CREATE
TABLE
TEST
(
ID
INT
,
VALUE
INT
);
>
ok
INSERT
INTO
TEST
VALUES
(
1
,
1
),
(
2
,
1
),
(
3
,
5
),
(
4
,
8
),
(
5
,
8
),
(
6
,
8
),
(
7
,
9
),
(
8
,
9
);
>
update
count
:
8
SELECT
*
,
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
VALUE
ROWS
BETWEEN
1
PRECEDING
AND
1
FOLLOWING
)
R_ID
,
ARRAY_AGG
(
VALUE
)
OVER
(
ORDER
BY
VALUE
ROWS
BETWEEN
1
PRECEDING
AND
1
FOLLOWING
)
R_V
,
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
VALUE
RANGE
BETWEEN
1
PRECEDING
AND
1
FOLLOWING
)
V_ID
,
ARRAY_AGG
(
VALUE
)
OVER
(
ORDER
BY
VALUE
RANGE
BETWEEN
1
PRECEDING
AND
1
FOLLOWING
)
V_V
,
ARRAY_AGG
(
VALUE
)
OVER
(
ORDER
BY
VALUE
DESC
RANGE
BETWEEN
1
PRECEDING
AND
1
FOLLOWING
)
V_V_R
,
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
VALUE
GROUPS
BETWEEN
1
PRECEDING
AND
1
FOLLOWING
)
G_ID
,
ARRAY_AGG
(
VALUE
)
OVER
(
ORDER
BY
VALUE
GROUPS
BETWEEN
1
PRECEDING
AND
1
FOLLOWING
)
G_V
FROM
TEST
;
>
ID
VALUE
R_ID
R_V
V_ID
V_V
V_V_R
G_ID
G_V
>
-- ----- --------- --------- --------------- --------------- --------------- ------------------ ------------------
>
1
1
(
1
,
2
)
(
1
,
1
)
(
1
,
2
)
(
1
,
1
)
(
1
,
1
)
(
1
,
2
,
3
)
(
1
,
1
,
5
)
>
2
1
(
1
,
2
,
3
)
(
1
,
1
,
5
)
(
1
,
2
)
(
1
,
1
)
(
1
,
1
)
(
1
,
2
,
3
)
(
1
,
1
,
5
)
>
3
5
(
2
,
3
,
4
)
(
1
,
5
,
8
)
(
3
)
(
5
)
(
5
)
(
1
,
2
,
3
,
4
,
5
,
6
)
(
1
,
1
,
5
,
8
,
8
,
8
)
>
4
8
(
3
,
4
,
5
)
(
5
,
8
,
8
)
(
4
,
5
,
6
,
7
,
8
)
(
8
,
8
,
8
,
9
,
9
)
(
9
,
9
,
8
,
8
,
8
)
(
3
,
4
,
5
,
6
,
7
,
8
)
(
5
,
8
,
8
,
8
,
9
,
9
)
>
5
8
(
4
,
5
,
6
)
(
8
,
8
,
8
)
(
4
,
5
,
6
,
7
,
8
)
(
8
,
8
,
8
,
9
,
9
)
(
9
,
9
,
8
,
8
,
8
)
(
3
,
4
,
5
,
6
,
7
,
8
)
(
5
,
8
,
8
,
8
,
9
,
9
)
>
6
8
(
5
,
6
,
7
)
(
8
,
8
,
9
)
(
4
,
5
,
6
,
7
,
8
)
(
8
,
8
,
8
,
9
,
9
)
(
9
,
9
,
8
,
8
,
8
)
(
3
,
4
,
5
,
6
,
7
,
8
)
(
5
,
8
,
8
,
8
,
9
,
9
)
>
7
9
(
6
,
7
,
8
)
(
8
,
9
,
9
)
(
4
,
5
,
6
,
7
,
8
)
(
8
,
8
,
8
,
9
,
9
)
(
9
,
9
,
8
,
8
,
8
)
(
4
,
5
,
6
,
7
,
8
)
(
8
,
8
,
8
,
9
,
9
)
>
8
9
(
7
,
8
)
(
9
,
9
)
(
4
,
5
,
6
,
7
,
8
)
(
8
,
8
,
8
,
9
,
9
)
(
9
,
9
,
8
,
8
,
8
)
(
4
,
5
,
6
,
7
,
8
)
(
8
,
8
,
8
,
9
,
9
)
>
rows
(
ordered
):
8
SELECT
*
,
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
VALUE
ROWS
-
1
PRECEDING
)
FROM
TEST
;
>
exception
INVALID_VALUE_2
DROP
TABLE
TEST
;
>
ok
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论