Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
aee4cfaa
提交
aee4cfaa
authored
9月 14, 2018
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add partial support for OVER() without conditions to aggregate functions
上级
f6e1781a
显示空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
199 行增加
和
37 行删除
+199
-37
Parser.java
h2/src/main/org/h2/command/Parser.java
+24
-2
Select.java
h2/src/main/org/h2/command/dml/Select.java
+88
-28
SelectGroups.java
h2/src/main/org/h2/command/dml/SelectGroups.java
+4
-1
ExpressionColumn.java
h2/src/main/org/h2/expression/ExpressionColumn.java
+2
-2
Aggregate.java
h2/src/main/org/h2/expression/aggregate/Aggregate.java
+22
-2
JavaAggregate.java
h2/src/main/org/h2/expression/aggregate/JavaAggregate.java
+15
-2
Window.java
h2/src/main/org/h2/expression/aggregate/Window.java
+13
-0
array-agg.sql
...est/org/h2/test/scripts/functions/aggregate/array-agg.sql
+31
-0
没有找到文件。
h2/src/main/org/h2/command/Parser.java
浏览文件 @
aee4cfaa
...
...
@@ -173,6 +173,7 @@ import org.h2.expression.Wildcard;
import
org.h2.expression.aggregate.Aggregate
;
import
org.h2.expression.aggregate.Aggregate.AggregateType
;
import
org.h2.expression.aggregate.JavaAggregate
;
import
org.h2.expression.aggregate.Window
;
import
org.h2.index.Index
;
import
org.h2.message.DbException
;
import
org.h2.result.SortOrder
;
...
...
@@ -2883,7 +2884,6 @@ public class Parser {
if
(
currentSelect
==
null
)
{
throw
getSyntaxError
();
}
currentSelect
.
setGroupQuery
();
Aggregate
r
;
switch
(
aggregateType
)
{
case
COUNT:
...
...
@@ -2968,10 +2968,26 @@ public class Parser {
read
(
CLOSE_PAREN
);
if
(
r
!=
null
)
{
r
.
setFilterCondition
(
readFilterCondition
());
Window
over
=
readOver
();
if
(
over
!=
null
)
{
r
.
setOverCondition
(
over
);
currentSelect
.
setWindowQuery
();
}
else
{
currentSelect
.
setGroupQuery
();
}
}
return
r
;
}
private
Window
readOver
()
{
if
(
readIf
(
"OVER"
))
{
read
(
OPEN_PAREN
);
read
(
CLOSE_PAREN
);
return
new
Window
();
}
return
null
;
}
private
void
setModeAggOrder
(
Aggregate
r
,
Expression
expr
)
{
ArrayList
<
SelectOrderBy
>
orderList
=
new
ArrayList
<>(
1
);
SelectOrderBy
order
=
new
SelectOrderBy
();
...
...
@@ -3027,7 +3043,13 @@ public class Parser {
Expression
filterCondition
=
readFilterCondition
();
Expression
[]
list
=
params
.
toArray
(
new
Expression
[
0
]);
JavaAggregate
agg
=
new
JavaAggregate
(
aggregate
,
list
,
currentSelect
,
distinct
,
filterCondition
);
Window
over
=
readOver
();
if
(
over
!=
null
)
{
agg
.
setOverCondition
(
over
);
currentSelect
.
setWindowQuery
();
}
else
{
currentSelect
.
setGroupQuery
();
}
return
agg
;
}
...
...
h2/src/main/org/h2/command/dml/Select.java
浏览文件 @
aee4cfaa
...
...
@@ -8,6 +8,7 @@ package org.h2.command.dml;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.BitSet
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.Trigger
;
...
...
@@ -105,6 +106,7 @@ public class Select extends Query {
private
int
havingIndex
;
private
boolean
isGroupQuery
,
isGroupSortedQuery
;
private
boolean
isWindowQuery
;
private
boolean
isForUpdate
,
isForUpdateMvcc
;
private
double
cost
;
private
boolean
isQuickAggregateQuery
,
isDistinctQuery
;
...
...
@@ -160,6 +162,13 @@ public class Select extends Query {
isGroupQuery
=
true
;
}
/**
* Called if this query contains window functions.
*/
public
void
setWindowQuery
()
{
isWindowQuery
=
true
;
}
public
void
setGroupBy
(
ArrayList
<
Expression
>
group
)
{
this
.
group
=
group
;
}
...
...
@@ -168,8 +177,8 @@ public class Select extends Query {
return
group
;
}
public
SelectGroups
getGroupDataIfCurrent
()
{
return
groupData
!=
null
&&
groupData
.
isCurrentGroup
()
?
groupData
:
null
;
public
SelectGroups
getGroupDataIfCurrent
(
boolean
forAggregate
)
{
return
groupData
!=
null
&&
(
forAggregate
||
!
isWindowQuery
)
&&
groupData
.
isCurrentGroup
()
?
groupData
:
null
;
}
@Override
...
...
@@ -346,11 +355,12 @@ public class Select extends Query {
return
condition
==
null
||
condition
.
getBooleanValue
(
session
);
}
private
void
query
Group
(
int
columnCount
,
LocalResult
result
,
long
offset
,
boolean
quickOffset
)
{
private
void
query
Window
(
int
columnCount
,
LocalResult
result
,
long
offset
,
boolean
quickOffset
)
{
if
(
groupData
==
null
)
{
groupData
=
new
SelectGroups
(
session
,
expressions
,
groupIndex
);
}
groupData
.
reset
();
HashMap
<
ValueArray
,
ArrayList
<
Row
>>
rows
=
new
HashMap
<>();
try
{
int
rowNumber
=
0
;
setCurrentRowNumber
(
0
);
...
...
@@ -359,13 +369,46 @@ public class Select extends Query {
setCurrentRowNumber
(
rowNumber
+
1
);
if
(
isConditionMet
())
{
rowNumber
++;
groupData
.
nextSource
();
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
if
(
groupByExpression
==
null
||
!
groupByExpression
[
i
])
{
Expression
expr
=
expressions
.
get
(
i
);
expr
.
updateAggregate
(
session
);
ValueArray
key
=
groupData
.
nextSource
();
ArrayList
<
Row
>
groupRows
=
rows
.
get
(
key
);
if
(
groupRows
==
null
)
{
groupRows
=
Utils
.
newSmallArrayList
();
rows
.
put
(
key
,
groupRows
);
}
groupRows
.
add
(
topTableFilter
.
get
());
updateAgg
(
columnCount
);
if
(
sampleSize
>
0
&&
rowNumber
>=
sampleSize
)
{
break
;
}
}
}
groupData
.
done
();
for
(
ValueArray
currentGroupsKey
;
(
currentGroupsKey
=
groupData
.
next
())
!=
null
;)
{
for
(
Row
originalRow
:
rows
.
get
(
currentGroupsKey
))
{
topTableFilter
.
set
(
originalRow
);
offset
=
processGroupedRow
(
columnCount
,
result
,
offset
,
quickOffset
,
currentGroupsKey
);
}
}
}
finally
{
groupData
.
reset
();
}
}
private
void
queryGroup
(
int
columnCount
,
LocalResult
result
,
long
offset
,
boolean
quickOffset
)
{
if
(
groupData
==
null
)
{
groupData
=
new
SelectGroups
(
session
,
expressions
,
groupIndex
);
}
groupData
.
reset
();
try
{
int
rowNumber
=
0
;
setCurrentRowNumber
(
0
);
int
sampleSize
=
getSampleSizeValue
(
session
);
while
(
topTableFilter
.
next
())
{
setCurrentRowNumber
(
rowNumber
+
1
);
if
(
isConditionMet
())
{
rowNumber
++;
groupData
.
nextSource
();
updateAgg
(
columnCount
);
if
(
sampleSize
>
0
&&
rowNumber
>=
sampleSize
)
{
break
;
}
...
...
@@ -373,6 +416,24 @@ public class Select extends Query {
}
groupData
.
done
();
for
(
ValueArray
currentGroupsKey
;
(
currentGroupsKey
=
groupData
.
next
())
!=
null
;)
{
offset
=
processGroupedRow
(
columnCount
,
result
,
offset
,
quickOffset
,
currentGroupsKey
);
}
}
finally
{
groupData
.
reset
();
}
}
private
void
updateAgg
(
int
columnCount
)
{
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
if
(
groupByExpression
==
null
||
!
groupByExpression
[
i
])
{
Expression
expr
=
expressions
.
get
(
i
);
expr
.
updateAggregate
(
session
);
}
}
}
private
long
processGroupedRow
(
int
columnCount
,
LocalResult
result
,
long
offset
,
boolean
quickOffset
,
ValueArray
currentGroupsKey
)
{
Value
[]
keyValues
=
currentGroupsKey
.
getList
();
Value
[]
row
=
new
Value
[
columnCount
];
for
(
int
j
=
0
;
groupIndex
!=
null
&&
j
<
groupIndex
.
length
;
j
++)
{
...
...
@@ -386,18 +447,15 @@ public class Select extends Query {
row
[
j
]
=
expr
.
getValue
(
session
);
}
if
(
isHavingNullOrFalse
(
row
))
{
continue
;
return
offset
;
}
if
(
quickOffset
&&
offset
>
0
)
{
offset
--;
continue
;
return
offset
;
}
row
=
keepOnlyDistinct
(
row
,
columnCount
);
result
.
addRow
(
row
);
}
}
finally
{
groupData
.
reset
();
}
return
offset
;
}
/**
...
...
@@ -663,7 +721,7 @@ public class Select extends Query {
result
=
createLocalResult
(
result
);
result
.
setDistinct
(
distinctIndexes
);
}
if
(
isGroupQuery
&&
!
isGroupSortedQuery
)
{
if
(
is
WindowQuery
||
is
GroupQuery
&&
!
isGroupSortedQuery
)
{
result
=
createLocalResult
(
result
);
}
if
(!
lazy
&&
(
limitRows
>=
0
||
offset
>
0
))
{
...
...
@@ -697,6 +755,8 @@ public class Select extends Query {
try
{
if
(
isQuickAggregateQuery
)
{
queryQuick
(
columnCount
,
to
,
quickOffset
&&
offset
>
0
);
}
else
if
(
isWindowQuery
)
{
queryWindow
(
columnCount
,
result
,
offset
,
quickOffset
);
}
else
if
(
isGroupQuery
)
{
if
(
isGroupSortedQuery
)
{
lazyResult
=
queryGroupSorted
(
columnCount
,
to
,
offset
,
quickOffset
);
...
...
h2/src/main/org/h2/command/dml/SelectGroups.java
浏览文件 @
aee4cfaa
...
...
@@ -167,8 +167,10 @@ public final class SelectGroups {
/**
* Invoked for each source row to evaluate group key and setup all necessary
* data for aggregates.
*
* @return key of the current group
*/
public
void
nextSource
()
{
public
ValueArray
nextSource
()
{
if
(
groupIndex
==
null
)
{
currentGroupsKey
=
defaultGroup
;
}
else
{
...
...
@@ -188,6 +190,7 @@ public final class SelectGroups {
}
currentGroupByExprData
=
values
;
currentGroupRowId
++;
return
currentGroupsKey
;
}
/**
...
...
h2/src/main/org/h2/expression/ExpressionColumn.java
浏览文件 @
aee4cfaa
...
...
@@ -159,7 +159,7 @@ public class ExpressionColumn extends Expression {
if
(
select
==
null
)
{
throw
DbException
.
get
(
ErrorCode
.
MUST_GROUP_BY_COLUMN_1
,
getSQL
());
}
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
();
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
false
);
if
(
groupData
==
null
)
{
// this is a different level (the enclosing query)
return
;
...
...
@@ -178,7 +178,7 @@ public class ExpressionColumn extends Expression {
public
Value
getValue
(
Session
session
)
{
Select
select
=
columnResolver
.
getSelect
();
if
(
select
!=
null
)
{
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
();
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
false
);
if
(
groupData
!=
null
)
{
Value
v
=
(
Value
)
groupData
.
getCurrentGroupExprData
(
this
);
if
(
v
!=
null
)
{
...
...
h2/src/main/org/h2/expression/aggregate/Aggregate.java
浏览文件 @
aee4cfaa
...
...
@@ -168,6 +168,8 @@ public class Aggregate extends Expression {
private
Expression
filterCondition
;
private
Window
over
;
/**
* Create a new aggregate object.
*
...
...
@@ -264,6 +266,15 @@ public class Aggregate extends Expression {
this
.
filterCondition
=
filterCondition
;
}
/**
* Sets the OVER condition.
*
* @param over OVER condition
*/
public
void
setOverCondition
(
Window
over
)
{
this
.
over
=
over
;
}
private
SortOrder
initOrder
(
Session
session
)
{
int
size
=
orderByList
.
size
();
int
[]
index
=
new
int
[
size
];
...
...
@@ -296,7 +307,7 @@ public class Aggregate extends Expression {
// if (on != null) {
// on.updateAggregate();
// }
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
();
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
true
);
if
(
groupData
==
null
)
{
// this is a different level (the enclosing query)
return
;
...
...
@@ -380,7 +391,7 @@ public class Aggregate extends Expression {
DbException
.
throwInternalError
(
"type="
+
type
);
}
}
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
();
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
true
);
if
(
groupData
==
null
)
{
throw
DbException
.
get
(
ErrorCode
.
INVALID_USE_OF_AGGREGATE_FUNCTION_1
,
getSQL
());
}
...
...
@@ -624,6 +635,9 @@ public class Aggregate extends Expression {
if
(
filterCondition
!=
null
)
{
buff
.
append
(
" FILTER (WHERE "
).
append
(
filterCondition
.
getSQL
()).
append
(
')'
);
}
if
(
over
!=
null
)
{
buff
.
append
(
" OVER()"
);
}
return
buff
.
toString
();
}
...
...
@@ -645,6 +659,9 @@ public class Aggregate extends Expression {
if
(
filterCondition
!=
null
)
{
buff
.
append
(
" FILTER (WHERE "
).
append
(
filterCondition
.
getSQL
()).
append
(
')'
);
}
if
(
over
!=
null
)
{
buff
.
append
(
" OVER()"
);
}
return
buff
.
toString
();
}
...
...
@@ -723,6 +740,9 @@ public class Aggregate extends Expression {
if
(
filterCondition
!=
null
)
{
text
+=
" FILTER (WHERE "
+
filterCondition
.
getSQL
()
+
')'
;
}
if
(
over
!=
null
)
{
text
+=
" OVER()"
;
}
return
text
;
}
...
...
h2/src/main/org/h2/expression/aggregate/JavaAggregate.java
浏览文件 @
aee4cfaa
...
...
@@ -36,6 +36,7 @@ public class JavaAggregate extends Expression {
private
int
[]
argTypes
;
private
final
boolean
distinct
;
private
Expression
filterCondition
;
private
Window
over
;
private
int
dataType
;
private
Connection
userConnection
;
private
int
lastGroupRowId
;
...
...
@@ -49,6 +50,15 @@ public class JavaAggregate extends Expression {
this
.
filterCondition
=
filterCondition
;
}
/**
* Sets the OVER condition.
*
* @param over OVER condition
*/
public
void
setOverCondition
(
Window
over
)
{
this
.
over
=
over
;
}
@Override
public
int
getCost
()
{
int
cost
=
5
;
...
...
@@ -88,6 +98,9 @@ public class JavaAggregate extends Expression {
if
(
filterCondition
!=
null
)
{
buff
.
append
(
" FILTER (WHERE "
).
append
(
filterCondition
.
getSQL
()).
append
(
')'
);
}
if
(
over
!=
null
)
{
buff
.
append
(
" OVER()"
);
}
return
buff
.
toString
();
}
...
...
@@ -169,7 +182,7 @@ public class JavaAggregate extends Expression {
@Override
public
Value
getValue
(
Session
session
)
{
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
();
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
true
);
if
(
groupData
==
null
)
{
throw
DbException
.
get
(
ErrorCode
.
INVALID_USE_OF_AGGREGATE_FUNCTION_1
,
getSQL
());
}
...
...
@@ -210,7 +223,7 @@ public class JavaAggregate extends Expression {
@Override
public
void
updateAggregate
(
Session
session
)
{
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
();
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
true
);
if
(
groupData
==
null
)
{
// this is a different level (the enclosing query)
return
;
...
...
h2/src/main/org/h2/expression/aggregate/Window.java
0 → 100644
浏览文件 @
aee4cfaa
/*
* 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
.
aggregate
;
/**
* Window clause.
*/
public
final
class
Window
{
}
h2/src/test/org/h2/test/scripts/functions/aggregate/array-agg.sql
浏览文件 @
aee4cfaa
...
...
@@ -67,3 +67,34 @@ select array_agg(distinct v order by v desc) from test;
drop
table
test
;
>
ok
CREATE
TABLE
TEST
(
ID
INT
PRIMARY
KEY
,
NAME
VARCHAR
);
>
ok
INSERT
INTO
TEST
VALUES
(
1
,
'a'
),
(
2
,
'a'
),
(
3
,
'b'
),
(
4
,
'c'
),
(
5
,
'c'
),
(
6
,
'c'
);
>
update
count
:
6
SELECT
ARRAY_AGG
(
ID
),
NAME
FROM
TEST
;
>
exception
MUST_GROUP_BY_COLUMN_1
SELECT
ARRAY_AGG
(
ID
),
NAME
FROM
TEST
GROUP
BY
NAME
;
>
ARRAY_AGG
(
ID
)
NAME
>
------------- ----
>
(
1
,
2
)
a
>
(
3
)
b
>
(
4
,
5
,
6
)
c
>
rows
:
3
SELECT
ARRAY_AGG
(
ID
)
OVER
(),
NAME
FROM
TEST
;
>
ARRAY_AGG
(
ID
)
OVER
()
NAME
>
-------------------- ----
>
(
1
,
2
,
3
,
4
,
5
,
6
)
a
>
(
1
,
2
,
3
,
4
,
5
,
6
)
a
>
(
1
,
2
,
3
,
4
,
5
,
6
)
b
>
(
1
,
2
,
3
,
4
,
5
,
6
)
c
>
(
1
,
2
,
3
,
4
,
5
,
6
)
c
>
(
1
,
2
,
3
,
4
,
5
,
6
)
c
>
rows
:
6
DROP
TABLE
TEST
;
>
ok
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论