Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
0c17e600
提交
0c17e600
authored
9月 18, 2018
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add window frame exclusion clause implementation
上级
32d3ca3f
隐藏空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
315 行增加
和
95 行删除
+315
-95
help.csv
h2/src/docsrc/help/help.csv
+16
-8
Parser.java
h2/src/main/org/h2/command/Parser.java
+18
-2
AbstractAggregate.java
...c/main/org/h2/expression/aggregate/AbstractAggregate.java
+4
-3
Window.java
h2/src/main/org/h2/expression/aggregate/Window.java
+5
-2
WindowFrame.java
h2/src/main/org/h2/expression/aggregate/WindowFrame.java
+225
-74
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
+32
-2
nth_value.sql
...c/test/org/h2/test/scripts/functions/window/nth_value.sql
+11
-0
dictionary.txt
h2/src/tools/org/h2/build/doc/dictionary.txt
+1
-1
没有找到文件。
h2/src/docsrc/help/help.csv
浏览文件 @
0c17e600
...
@@ -2535,17 +2535,10 @@ SELECT * FROM (VALUES(1, 'Hello'), (2, 'World')) AS V;
...
@@ -2535,17 +2535,10 @@ SELECT * FROM (VALUES(1, 'Hello'), (2, 'World')) AS V;
"Other Grammar","Window specification","
"Other Grammar","Window specification","
([PARTITION BY expression [,...]] [ORDER BY order [,...]]
([PARTITION BY expression [,...]] [ORDER BY order [,...]]
[RANGE BETWEEN {
[windowFrame])
UNBOUNDED PRECEDING AND CURRENT ROW
|CURRENT ROW AND UNBOUNDED FOLLOWING
|UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
}])
","
","
A window specification for a window function or aggregate.
A window specification for a window function or aggregate.
Window frame clause (RANGE) is currently supported only in aggregates and
FIRST_VALUE(), LAST_VALUE(), and NTH_VALUE() window functions.
Window functions are currently experimental in H2 and should be used with caution.
Window functions are currently experimental in H2 and should be used with caution.
They also may require a lot of memory for large queries.
They also may require a lot of memory for large queries.
","
","
...
@@ -2553,6 +2546,21 @@ They also may require a lot of memory for large queries.
...
@@ -2553,6 +2546,21 @@ They also may require a lot of memory for large queries.
(ORDER BY ID)
(ORDER BY ID)
(PARTITION BY CATEGORY)
(PARTITION BY CATEGORY)
(PARTITION BY CATEGORY ORDER BY NAME, ID)
(PARTITION BY CATEGORY ORDER BY NAME, ID)
(ORDER BY Y RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE TIES)
"
"Other Grammar","Window frame","
[RANGE BETWEEN {
UNBOUNDED PRECEDING AND CURRENT ROW
|CURRENT ROW AND UNBOUNDED FOLLOWING
|UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
}]
[EXCLUDE {CURRENT ROW|GROUP|TIES|NO OTHERS}]
","
A window frame clause.
Is currently supported only in aggregates and FIRST_VALUE(), LAST_VALUE(), and NTH_VALUE() window functions.
","
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE GROUP
"
"
"Other Grammar","Term","
"Other Grammar","Term","
...
...
h2/src/main/org/h2/command/Parser.java
浏览文件 @
0c17e600
...
@@ -177,6 +177,7 @@ import org.h2.expression.aggregate.JavaAggregate;
...
@@ -177,6 +177,7 @@ import org.h2.expression.aggregate.JavaAggregate;
import
org.h2.expression.aggregate.Window
;
import
org.h2.expression.aggregate.Window
;
import
org.h2.expression.aggregate.WindowFrame
;
import
org.h2.expression.aggregate.WindowFrame
;
import
org.h2.expression.aggregate.WindowFrame.SimpleExtent
;
import
org.h2.expression.aggregate.WindowFrame.SimpleExtent
;
import
org.h2.expression.aggregate.WindowFrame.WindowFrameExclusion
;
import
org.h2.expression.aggregate.WindowFunction
;
import
org.h2.expression.aggregate.WindowFunction
;
import
org.h2.expression.aggregate.WindowFunction.WindowFunctionType
;
import
org.h2.expression.aggregate.WindowFunction.WindowFunctionType
;
import
org.h2.index.Index
;
import
org.h2.index.Index
;
...
@@ -3073,7 +3074,8 @@ public class Parser {
...
@@ -3073,7 +3074,8 @@ public class Parser {
frame
=
readWindowFrame
();
frame
=
readWindowFrame
();
break
;
break
;
default
:
default
:
frame
=
new
WindowFrame
(
SimpleExtent
.
RANGE_BETWEEN_UNBOUNDED_PRECEDING_AND_CURRENT_ROW
);
frame
=
new
WindowFrame
(
SimpleExtent
.
RANGE_BETWEEN_UNBOUNDED_PRECEDING_AND_CURRENT_ROW
,
WindowFrameExclusion
.
EXCLUDE_NO_OTHERS
);
}
}
}
else
{
}
else
{
frame
=
readWindowFrame
();
frame
=
readWindowFrame
();
...
@@ -3091,6 +3093,7 @@ public class Parser {
...
@@ -3091,6 +3093,7 @@ public class Parser {
private
WindowFrame
readWindowFrame
()
{
private
WindowFrame
readWindowFrame
()
{
SimpleExtent
extent
;
SimpleExtent
extent
;
WindowFrameExclusion
exclusion
=
WindowFrameExclusion
.
EXCLUDE_NO_OTHERS
;
if
(
readIf
(
"RANGE"
))
{
if
(
readIf
(
"RANGE"
))
{
read
(
"BETWEEN"
);
read
(
"BETWEEN"
);
if
(
readIf
(
"UNBOUNDED"
))
{
if
(
readIf
(
"UNBOUNDED"
))
{
...
@@ -3112,10 +3115,23 @@ public class Parser {
...
@@ -3112,10 +3115,23 @@ public class Parser {
read
(
"FOLLOWING"
);
read
(
"FOLLOWING"
);
extent
=
SimpleExtent
.
RANGE_BETWEEN_CURRENT_ROW_AND_UNBOUNDED_FOLLOWING
;
extent
=
SimpleExtent
.
RANGE_BETWEEN_CURRENT_ROW_AND_UNBOUNDED_FOLLOWING
;
}
}
if
(
readIf
(
"EXCLUDE"
))
{
if
(
readIf
(
"CURRENT"
))
{
read
(
"ROW"
);
exclusion
=
WindowFrameExclusion
.
EXCLUDE_CURRENT_ROW
;
}
else
if
(
readIf
(
GROUP
))
{
exclusion
=
WindowFrameExclusion
.
EXCLUDE_GROUP
;
}
else
if
(
readIf
(
"TIES"
))
{
exclusion
=
WindowFrameExclusion
.
EXCLUDE_TIES
;
}
else
{
read
(
"NO"
);
read
(
"OTHERS"
);
}
}
}
else
{
}
else
{
extent
=
SimpleExtent
.
RANGE_BETWEEN_UNBOUNDED_PRECEDING_AND_CURRENT_ROW
;
extent
=
SimpleExtent
.
RANGE_BETWEEN_UNBOUNDED_PRECEDING_AND_CURRENT_ROW
;
}
}
return
new
WindowFrame
(
extent
);
return
new
WindowFrame
(
extent
,
exclusion
);
}
}
private
AggregateType
getAggregateType
(
String
name
)
{
private
AggregateType
getAggregateType
(
String
name
)
{
...
...
h2/src/main/org/h2/expression/aggregate/AbstractAggregate.java
浏览文件 @
0c17e600
...
@@ -8,6 +8,7 @@ package org.h2.expression.aggregate;
...
@@ -8,6 +8,7 @@ package org.h2.expression.aggregate;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.dml.Select
;
import
org.h2.command.dml.Select
;
...
@@ -441,12 +442,12 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -441,12 +442,12 @@ public abstract class AbstractAggregate extends Expression {
result
.
put
(
row
[
rowIdColumn
].
getInt
(),
value
);
result
.
put
(
row
[
rowIdColumn
].
getInt
(),
value
);
}
}
}
else
{
}
else
{
// TODO optimize unordered aggregates
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
(
int
j
=
i
;
j
<
size
;
j
++)
{
for
(
Iterator
<
Value
[]>
iter
=
frame
.
iterator
(
ordered
,
getOverOrderBySort
(),
i
,
false
);
iter
updateFromExpressions
(
session
,
aggregateData
,
ordered
.
get
(
j
));
.
hasNext
();)
{
updateFromExpressions
(
session
,
aggregateData
,
iter
.
next
());
}
}
result
.
put
(
ordered
.
get
(
i
)[
rowIdColumn
].
getInt
(),
getAggregatedValue
(
session
,
aggregateData
));
result
.
put
(
ordered
.
get
(
i
)[
rowIdColumn
].
getInt
(),
getAggregatedValue
(
session
,
aggregateData
));
}
}
...
...
h2/src/main/org/h2/expression/aggregate/Window.java
浏览文件 @
0c17e600
...
@@ -36,7 +36,10 @@ public final class Window {
...
@@ -36,7 +36,10 @@ public final class Window {
*/
*/
static
void
appendOrderBy
(
StringBuilder
builder
,
ArrayList
<
SelectOrderBy
>
orderBy
)
{
static
void
appendOrderBy
(
StringBuilder
builder
,
ArrayList
<
SelectOrderBy
>
orderBy
)
{
if
(
orderBy
!=
null
&&
!
orderBy
.
isEmpty
())
{
if
(
orderBy
!=
null
&&
!
orderBy
.
isEmpty
())
{
builder
.
append
(
" ORDER BY "
);
if
(
builder
.
charAt
(
builder
.
length
()
-
1
)
!=
'('
)
{
builder
.
append
(
' '
);
}
builder
.
append
(
"ORDER BY "
);
for
(
int
i
=
0
;
i
<
orderBy
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
orderBy
.
size
();
i
++)
{
SelectOrderBy
o
=
orderBy
.
get
(
i
);
SelectOrderBy
o
=
orderBy
.
get
(
i
);
if
(
i
>
0
)
{
if
(
i
>
0
)
{
...
@@ -187,10 +190,10 @@ public final class Window {
...
@@ -187,10 +190,10 @@ public final class Window {
builder
.
append
(
StringUtils
.
unEnclose
(
partitionBy
.
get
(
i
).
getSQL
()));
builder
.
append
(
StringUtils
.
unEnclose
(
partitionBy
.
get
(
i
).
getSQL
()));
}
}
}
}
appendOrderBy
(
builder
,
orderBy
);
if
(!
frame
.
isDefault
())
{
if
(!
frame
.
isDefault
())
{
builder
.
append
(
' '
).
append
(
frame
.
getSQL
());
builder
.
append
(
' '
).
append
(
frame
.
getSQL
());
}
}
appendOrderBy
(
builder
,
orderBy
);
return
builder
.
append
(
')'
).
toString
();
return
builder
.
append
(
')'
).
toString
();
}
}
...
...
h2/src/main/org/h2/expression/aggregate/WindowFrame.java
浏览文件 @
0c17e600
...
@@ -6,10 +6,13 @@
...
@@ -6,10 +6,13 @@
package
org
.
h2
.
expression
.
aggregate
;
package
org
.
h2
.
expression
.
aggregate
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.BitSet
;
import
java.util.Collections
;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
java.util.NoSuchElementException
;
import
java.util.NoSuchElementException
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.result.SortOrder
;
import
org.h2.value.Value
;
import
org.h2.value.Value
;
/**
/**
...
@@ -59,16 +62,190 @@ public final class WindowFrame {
...
@@ -59,16 +62,190 @@ public final class WindowFrame {
}
}
/**
* Window frame exclusion clause.
*/
public
enum
WindowFrameExclusion
{
/**
* EXCLUDE CURRENT ROW exclusion clause.
*/
EXCLUDE_CURRENT_ROW
(
"EXCLUDE CURRENT ROW"
),
/**
* EXCLUDE GROUP exclusion clause.
*/
EXCLUDE_GROUP
(
"EXCLUDE GROUP"
),
/**
* EXCLUDE TIES exclusion clause.
*/
EXCLUDE_TIES
(
"EXCLUDE TIES"
),
/**
* EXCLUDE NO OTHERS exclusion clause.
*/
EXCLUDE_NO_OTHERS
(
"EXCLUDE NO OTHERS"
),
;
private
final
String
sql
;
private
WindowFrameExclusion
(
String
sql
)
{
this
.
sql
=
sql
;
}
/**
* Returns SQL representation.
*
* @return SQL representation.
* @see org.h2.expression.Expression#getSQL()
*/
public
String
getSQL
()
{
return
sql
;
}
}
private
abstract
class
Itr
implements
Iterator
<
Value
[]>
{
final
ArrayList
<
Value
[]>
orderedRows
;
Itr
(
ArrayList
<
Value
[]>
orderedRows
)
{
this
.
orderedRows
=
orderedRows
;
}
@Override
public
final
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
}
private
final
class
PlainItr
extends
Itr
{
private
final
int
endIndex
;
private
int
cursor
;
PlainItr
(
ArrayList
<
Value
[]>
orderedRows
,
int
startIndex
,
int
endIndex
)
{
super
(
orderedRows
);
this
.
endIndex
=
endIndex
;
cursor
=
startIndex
;
}
@Override
public
boolean
hasNext
()
{
return
cursor
<=
endIndex
;
}
@Override
public
Value
[]
next
()
{
if
(
cursor
>
endIndex
)
{
throw
new
NoSuchElementException
();
}
return
orderedRows
.
get
(
cursor
++);
}
}
private
final
class
PlainReverseItr
extends
Itr
{
private
final
int
startIndex
;
private
int
cursor
;
PlainReverseItr
(
ArrayList
<
Value
[]>
orderedRows
,
int
startIndex
,
int
endIndex
)
{
super
(
orderedRows
);
this
.
startIndex
=
startIndex
;
cursor
=
endIndex
;
}
@Override
public
boolean
hasNext
()
{
return
cursor
>=
startIndex
;
}
@Override
public
Value
[]
next
()
{
if
(
cursor
<
startIndex
)
{
throw
new
NoSuchElementException
();
}
return
orderedRows
.
get
(
cursor
--);
}
}
private
abstract
class
AbstractBitSetItr
extends
Itr
{
final
BitSet
set
;
int
cursor
;
AbstractBitSetItr
(
ArrayList
<
Value
[]>
orderedRows
,
BitSet
set
)
{
super
(
orderedRows
);
this
.
set
=
set
;
}
@Override
public
final
boolean
hasNext
()
{
return
cursor
>=
0
;
}
}
private
final
class
BitSetItr
extends
AbstractBitSetItr
{
BitSetItr
(
ArrayList
<
Value
[]>
orderedRows
,
BitSet
set
)
{
super
(
orderedRows
,
set
);
cursor
=
set
.
nextSetBit
(
0
);
}
@Override
public
Value
[]
next
()
{
if
(
cursor
<
0
)
{
throw
new
NoSuchElementException
();
}
Value
[]
result
=
orderedRows
.
get
(
cursor
);
cursor
=
set
.
nextSetBit
(
cursor
+
1
);
return
result
;
}
}
private
final
class
BitSetReverseItr
extends
AbstractBitSetItr
{
BitSetReverseItr
(
ArrayList
<
Value
[]>
orderedRows
,
BitSet
set
)
{
super
(
orderedRows
,
set
);
cursor
=
set
.
length
()
-
1
;
}
@Override
public
Value
[]
next
()
{
if
(
cursor
<
0
)
{
throw
new
NoSuchElementException
();
}
Value
[]
result
=
orderedRows
.
get
(
cursor
);
cursor
=
set
.
previousSetBit
(
cursor
-
1
);
return
result
;
}
}
private
final
SimpleExtent
extent
;
private
final
SimpleExtent
extent
;
private
final
WindowFrameExclusion
exclusion
;
/**
/**
* Creates new instance of window frame clause.
* Creates new instance of window frame clause.
*
*
* @param extent
* @param extent
* window frame extent
* window frame extent
* @param exclusion
* window frame exclusion
*/
*/
public
WindowFrame
(
SimpleExtent
extent
)
{
public
WindowFrame
(
SimpleExtent
extent
,
WindowFrameExclusion
exclusion
)
{
this
.
extent
=
extent
;
this
.
extent
=
extent
;
this
.
exclusion
=
exclusion
;
}
}
/**
/**
...
@@ -77,7 +254,8 @@ public final class WindowFrame {
...
@@ -77,7 +254,8 @@ public final class WindowFrame {
* @return whether window frame specification can be omitted
* @return whether window frame specification can be omitted
*/
*/
public
boolean
isDefault
()
{
public
boolean
isDefault
()
{
return
extent
==
SimpleExtent
.
RANGE_BETWEEN_UNBOUNDED_PRECEDING_AND_CURRENT_ROW
;
return
extent
==
SimpleExtent
.
RANGE_BETWEEN_UNBOUNDED_PRECEDING_AND_CURRENT_ROW
&&
exclusion
==
WindowFrameExclusion
.
EXCLUDE_NO_OTHERS
;
}
}
/**
/**
...
@@ -87,7 +265,8 @@ public final class WindowFrame {
...
@@ -87,7 +265,8 @@ public final class WindowFrame {
* @return whether window frame specification contains all rows in partition
* @return whether window frame specification contains all rows in partition
*/
*/
public
boolean
isFullPartition
()
{
public
boolean
isFullPartition
()
{
return
extent
==
SimpleExtent
.
RANGE_BETWEEN_UNBOUNDED_PRECEDING_AND_UNBOUNDED_FOLLOWING
;
return
extent
==
SimpleExtent
.
RANGE_BETWEEN_UNBOUNDED_PRECEDING_AND_UNBOUNDED_FOLLOWING
&&
exclusion
==
WindowFrameExclusion
.
EXCLUDE_NO_OTHERS
;
}
}
/**
/**
...
@@ -95,11 +274,16 @@ public final class WindowFrame {
...
@@ -95,11 +274,16 @@ public final class WindowFrame {
*
*
* @param orderedRows
* @param orderedRows
* ordered rows
* ordered rows
* @param sortOrder
* sort order
* @param currentRow
* @param currentRow
* index of the current row
* index of the current row
* @param reverse
* whether iterator should iterate in reverse order
* @return iterator
* @return iterator
*/
*/
public
Iterator
<
Value
[]>
iterator
(
final
ArrayList
<
Value
[]>
orderedRows
,
int
currentRow
)
{
public
Iterator
<
Value
[]>
iterator
(
ArrayList
<
Value
[]>
orderedRows
,
SortOrder
sortOrder
,
int
currentRow
,
boolean
reverse
)
{
int
size
=
orderedRows
.
size
();
int
size
=
orderedRows
.
size
();
final
int
startIndex
,
endIndex
;
final
int
startIndex
,
endIndex
;
switch
(
extent
)
{
switch
(
extent
)
{
...
@@ -118,82 +302,45 @@ public final class WindowFrame {
...
@@ -118,82 +302,45 @@ public final class WindowFrame {
default
:
default
:
throw
DbException
.
getUnsupportedException
(
"window frame extent ="
+
extent
);
throw
DbException
.
getUnsupportedException
(
"window frame extent ="
+
extent
);
}
}
return
new
Iterator
<
Value
[]>()
{
if
(
exclusion
!=
WindowFrameExclusion
.
EXCLUDE_NO_OTHERS
)
{
return
complexIterator
(
orderedRows
,
sortOrder
,
currentRow
,
startIndex
,
endIndex
,
reverse
);
private
int
cursor
=
startIndex
;
}
return
reverse
?
new
PlainReverseItr
(
orderedRows
,
startIndex
,
endIndex
)
@Override
:
new
PlainItr
(
orderedRows
,
startIndex
,
endIndex
);
public
boolean
hasNext
()
{
return
cursor
<=
endIndex
;
}
@Override
public
Value
[]
next
()
{
if
(
cursor
>
endIndex
)
{
throw
new
NoSuchElementException
();
}
return
orderedRows
.
get
(
cursor
++);
}
@Override
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
};
}
}
/**
private
Iterator
<
Value
[]>
complexIterator
(
ArrayList
<
Value
[]>
orderedRows
,
SortOrder
sortOrder
,
int
currentRow
,
* Returns iterator in descending order.
int
startIndex
,
int
endIndex
,
boolean
reverse
)
{
*
* @param orderedRows
* ordered rows
* @param currentRow
* index of the current row
* @return iterator in descending order
*/
public
Iterator
<
Value
[]>
reverseIterator
(
final
ArrayList
<
Value
[]>
orderedRows
,
int
currentRow
)
{
int
size
=
orderedRows
.
size
();
int
size
=
orderedRows
.
size
();
final
int
startIndex
,
endIndex
;
BitSet
set
=
new
BitSet
(
size
);
switch
(
extent
)
{
set
.
set
(
startIndex
,
endIndex
+
1
);
case
RANGE_BETWEEN_UNBOUNDED_PRECEDING_AND_CURRENT_ROW:
switch
(
exclusion
)
{
startIndex
=
0
;
case
EXCLUDE_CURRENT_ROW:
endIndex
=
currentRow
;
set
.
clear
(
currentRow
);
break
;
case
RANGE_BETWEEN_CURRENT_ROW_AND_UNBOUNDED_FOLLOWING:
startIndex
=
currentRow
;
endIndex
=
size
-
1
;
break
;
break
;
case
RANGE_BETWEEN_UNBOUNDED_PRECEDING_AND_UNBOUNDED_FOLLOWING:
case
EXCLUDE_GROUP:
startIndex
=
0
;
case
EXCLUDE_TIES:
{
endIndex
=
size
-
1
;
int
exStart
=
currentRow
;
break
;
Value
[]
row
=
orderedRows
.
get
(
currentRow
);
default
:
while
(
exStart
>
startIndex
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
exStart
-
1
))
==
0
)
{
throw
DbException
.
getUnsupportedException
(
"window frame extent ="
+
extent
);
exStart
--;
}
return
new
Iterator
<
Value
[]>()
{
private
int
cursor
=
endIndex
;
@Override
public
boolean
hasNext
()
{
return
cursor
>=
startIndex
;
}
}
int
exEnd
=
currentRow
;
@Override
while
(
exEnd
<
endIndex
&&
sortOrder
.
compare
(
row
,
orderedRows
.
get
(
exEnd
+
1
))
==
0
)
{
public
Value
[]
next
()
{
exEnd
++;
if
(
cursor
<
startIndex
)
{
throw
new
NoSuchElementException
();
}
return
orderedRows
.
get
(
cursor
--);
}
}
set
.
clear
(
exStart
,
exEnd
+
1
);
@Override
if
(
exclusion
==
WindowFrameExclusion
.
EXCLUDE_TIES
)
{
public
void
remove
()
{
set
.
set
(
currentRow
);
throw
new
UnsupportedOperationException
();
}
}
}
};
//$FALL-THROUGH$
default
:
}
if
(
set
.
isEmpty
())
{
return
Collections
.
emptyIterator
();
}
return
reverse
?
new
BitSetReverseItr
(
orderedRows
,
set
)
:
new
BitSetItr
(
orderedRows
,
set
);
}
}
/**
/**
...
@@ -203,7 +350,11 @@ public final class WindowFrame {
...
@@ -203,7 +350,11 @@ public final class WindowFrame {
* @see org.h2.expression.Expression#getSQL()
* @see org.h2.expression.Expression#getSQL()
*/
*/
public
String
getSQL
()
{
public
String
getSQL
()
{
return
extent
.
getSQL
();
String
sql
=
extent
.
getSQL
();
if
(
exclusion
!=
WindowFrameExclusion
.
EXCLUDE_NO_OTHERS
)
{
sql
=
sql
+
' '
+
exclusion
.
getSQL
();
}
return
sql
;
}
}
}
}
h2/src/main/org/h2/expression/aggregate/WindowFunction.java
浏览文件 @
0c17e600
...
@@ -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
,
i
),
0
,
ignoreNulls
);
v
=
getNthValue
(
frame
.
iterator
(
ordered
,
getOverOrderBySort
(),
i
,
false
),
0
,
ignoreNulls
);
break
;
break
;
}
}
case
LAST_VALUE:
case
LAST_VALUE:
v
=
getNthValue
(
frame
.
reverseIterator
(
ordered
,
i
),
0
,
ignoreNulls
);
v
=
getNthValue
(
frame
.
iterator
(
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
=
fr
omLast
?
frame
.
reverseIterator
(
ordered
,
i
)
:
frame
.
iterator
(
ordered
,
i
);
Iterator
<
Value
[]>
iter
=
fr
ame
.
iterator
(
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
浏览文件 @
0c17e600
...
@@ -233,8 +233,8 @@ SELECT
...
@@ -233,8 +233,8 @@ SELECT
>
rows
:
6
>
rows
:
6
SELECT
ARRAY_AGG
(
SUM
(
ID
))
OVER
(
ORDER
/**/
BY
ID
)
FROM
TEST
GROUP
BY
ID
;
SELECT
ARRAY_AGG
(
SUM
(
ID
))
OVER
(
ORDER
/**/
BY
ID
)
FROM
TEST
GROUP
BY
ID
;
>
ARRAY_AGG
(
SUM
(
ID
))
OVER
(
ORDER
BY
ID
)
>
ARRAY_AGG
(
SUM
(
ID
))
OVER
(
ORDER
BY
ID
)
>
-------------------------------------
-
>
-------------------------------------
>
(
1
)
>
(
1
)
>
(
1
,
2
)
>
(
1
,
2
)
>
(
1
,
2
,
3
)
>
(
1
,
2
,
3
)
...
@@ -245,3 +245,33 @@ SELECT ARRAY_AGG(SUM(ID)) OVER(ORDER /**/ BY ID) FROM TEST GROUP BY ID;
...
@@ -245,3 +245,33 @@ SELECT ARRAY_AGG(SUM(ID)) OVER(ORDER /**/ BY ID) FROM TEST GROUP BY ID;
DROP
TABLE
TEST
;
DROP
TABLE
TEST
;
>
ok
>
ok
CREATE
TABLE
TEST
(
ID
INT
,
G
INT
);
>
ok
INSERT
INTO
TEST
VALUES
(
1
,
1
),
(
2
,
2
),
(
3
,
2
),
(
4
,
2
),
(
5
,
3
);
>
update
count
:
5
SELECT
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
G
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
UNBOUNDED
FOLLOWING
)
D
,
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
G
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
UNBOUNDED
FOLLOWING
EXCLUDE
CURRENT
ROW
)
R
,
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
G
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
UNBOUNDED
FOLLOWING
EXCLUDE
GROUP
)
G
,
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
G
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
UNBOUNDED
FOLLOWING
EXCLUDE
TIES
)
T
,
ARRAY_AGG
(
ID
)
OVER
(
ORDER
BY
G
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
UNBOUNDED
FOLLOWING
EXCLUDE
NO
OTHERS
)
N
FROM
TEST
;
>
D
R
G
T
N
>
--------------- ------------ ------------ --------------- ---------------
>
(
1
,
2
,
3
,
4
,
5
)
(
2
,
3
,
4
,
5
)
(
2
,
3
,
4
,
5
)
(
1
,
2
,
3
,
4
,
5
)
(
1
,
2
,
3
,
4
,
5
)
>
(
1
,
2
,
3
,
4
,
5
)
(
1
,
3
,
4
,
5
)
(
1
,
5
)
(
1
,
2
,
5
)
(
1
,
2
,
3
,
4
,
5
)
>
(
1
,
2
,
3
,
4
,
5
)
(
1
,
2
,
4
,
5
)
(
1
,
5
)
(
1
,
3
,
5
)
(
1
,
2
,
3
,
4
,
5
)
>
(
1
,
2
,
3
,
4
,
5
)
(
1
,
2
,
3
,
5
)
(
1
,
5
)
(
1
,
4
,
5
)
(
1
,
2
,
3
,
4
,
5
)
>
(
1
,
2
,
3
,
4
,
5
)
(
1
,
2
,
3
,
4
)
(
1
,
2
,
3
,
4
)
(
1
,
2
,
3
,
4
,
5
)
(
1
,
2
,
3
,
4
,
5
)
>
rows
(
ordered
):
5
DROP
TABLE
TEST
;
>
ok
h2/src/test/org/h2/test/scripts/functions/window/nth_value.sql
浏览文件 @
0c17e600
...
@@ -135,5 +135,16 @@ SELECT *,
...
@@ -135,5 +135,16 @@ SELECT *,
>
13
4
null
41
null
null
>
13
4
null
41
null
null
>
rows
(
ordered
):
13
>
rows
(
ordered
):
13
SELECT
ID
,
CATEGORY
,
NTH_VALUE
(
CATEGORY
,
2
)
OVER
(
ORDER
BY
CATEGORY
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
CURRENT
ROW
)
C
,
NTH_VALUE
(
CATEGORY
,
2
)
OVER
(
ORDER
BY
CATEGORY
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
CURRENT
ROW
EXCLUDE
CURRENT
ROW
)
FROM
TEST
FETCH
FIRST
3
ROWS
ONLY
;
>
ID
CATEGORY
C
NTH_VALUE
(
CATEGORY
,
2
)
OVER
(
ORDER
BY
CATEGORY
RANGE
BETWEEN
UNBOUNDED
PRECEDING
AND
CURRENT
ROW
EXCLUDE
CURRENT
ROW
)
>
-- -------- ---- ---------------------------------------------------------------------------------------------------------------------
>
1
1
null
null
>
2
1
1
null
>
3
1
1
1
>
rows
(
ordered
):
3
DROP
TABLE
TEST
;
DROP
TABLE
TEST
;
>
ok
>
ok
h2/src/tools/org/h2/build/doc/dictionary.txt
浏览文件 @
0c17e600
...
@@ -796,4 +796,4 @@ interior envelopes multilinestring multipoint packed exterior normalization awkw
...
@@ -796,4 +796,4 @@ interior envelopes multilinestring multipoint packed exterior normalization awkw
xym normalizes coord setz xyzm geometrycollection multipolygon mixup rings polygons rejection finite
xym normalizes coord setz xyzm geometrycollection multipolygon mixup rings polygons rejection finite
pointzm pointz pointm dimensionality redefine forum measures
pointzm pointz pointm dimensionality redefine forum measures
mpg casted pzm mls constrained subtypes complains
mpg casted pzm mls constrained subtypes complains
ranks rno dro rko precede cume reopens preceding unbounded rightly
ranks rno dro rko precede cume reopens preceding unbounded rightly
itr
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论