Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
4c2a4489
提交
4c2a4489
authored
6 年前
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Store window data in SelectGroups
上级
64ff1b54
显示空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
277 行增加
和
131 行删除
+277
-131
Select.java
h2/src/main/org/h2/command/dml/Select.java
+9
-19
SelectGroups.java
h2/src/main/org/h2/command/dml/SelectGroups.java
+194
-80
ExpressionColumn.java
h2/src/main/org/h2/expression/ExpressionColumn.java
+3
-3
Aggregate.java
h2/src/main/org/h2/expression/aggregate/Aggregate.java
+28
-18
JavaAggregate.java
h2/src/main/org/h2/expression/aggregate/JavaAggregate.java
+14
-11
Window.java
h2/src/main/org/h2/expression/aggregate/Window.java
+18
-0
array-agg.sql
...est/org/h2/test/scripts/functions/aggregate/array-agg.sql
+11
-0
没有找到文件。
h2/src/main/org/h2/command/dml/Select.java
浏览文件 @
4c2a4489
...
...
@@ -8,7 +8,6 @@ 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,7 +104,8 @@ public class Select extends Query {
SelectGroups
groupData
;
private
int
havingIndex
;
private
boolean
isGroupQuery
,
isGroupSortedQuery
;
boolean
isGroupQuery
;
private
boolean
isGroupSortedQuery
;
private
boolean
isWindowQuery
;
private
boolean
isForUpdate
,
isForUpdateMvcc
;
private
double
cost
;
...
...
@@ -177,8 +177,8 @@ public class Select extends Query {
return
group
;
}
public
SelectGroups
getGroupDataIfCurrent
(
boolean
forAggregate
)
{
return
groupData
!=
null
&&
(
forAggregate
||
!
isWindowQuery
)
&&
groupData
.
isCurrentGroup
(
)
?
groupData
:
null
;
public
SelectGroups
getGroupDataIfCurrent
(
boolean
window
)
{
return
groupData
!=
null
&&
(
window
||
groupData
.
isCurrentGroup
()
)
?
groupData
:
null
;
}
@Override
...
...
@@ -357,10 +357,9 @@ public class Select extends Query {
private
void
queryWindow
(
int
columnCount
,
LocalResult
result
,
long
offset
,
boolean
quickOffset
)
{
if
(
groupData
==
null
)
{
groupData
=
new
SelectGroups
(
session
,
expressions
,
groupIndex
);
groupData
=
SelectGroups
.
getInstance
(
session
,
expressions
,
isGroupQuery
,
groupIndex
);
}
groupData
.
reset
();
HashMap
<
ValueArray
,
ArrayList
<
Row
>>
rows
=
new
HashMap
<>();
try
{
int
rowNumber
=
0
;
setCurrentRowNumber
(
0
);
...
...
@@ -369,13 +368,7 @@ public class Select extends Query {
setCurrentRowNumber
(
rowNumber
+
1
);
if
(
isConditionMet
())
{
rowNumber
++;
ValueArray
key
=
groupData
.
nextSource
();
ArrayList
<
Row
>
groupRows
=
rows
.
get
(
key
);
if
(
groupRows
==
null
)
{
groupRows
=
Utils
.
newSmallArrayList
();
rows
.
put
(
key
,
groupRows
);
}
groupRows
.
add
(
topTableFilter
.
get
());
groupData
.
nextSource
();
updateAgg
(
columnCount
);
if
(
sampleSize
>
0
&&
rowNumber
>=
sampleSize
)
{
break
;
...
...
@@ -384,11 +377,8 @@ public class Select extends Query {
}
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
();
}
...
...
@@ -396,7 +386,7 @@ public class Select extends Query {
private
void
queryGroup
(
int
columnCount
,
LocalResult
result
,
long
offset
,
boolean
quickOffset
)
{
if
(
groupData
==
null
)
{
groupData
=
new
SelectGroups
(
session
,
expressions
,
groupIndex
);
groupData
=
SelectGroups
.
getInstance
(
session
,
expressions
,
isGroupQuery
,
groupIndex
);
}
groupData
.
reset
();
try
{
...
...
@@ -1654,7 +1644,7 @@ public class Select extends Query {
LazyResultGroupSorted
(
Expression
[]
expressions
,
int
columnCount
)
{
super
(
expressions
,
columnCount
);
if
(
groupData
==
null
)
{
groupData
=
new
SelectGroups
(
getSession
(),
Select
.
this
.
expressions
,
groupIndex
);
groupData
=
SelectGroups
.
getInstance
(
getSession
(),
Select
.
this
.
expressions
,
isGroupQuery
,
groupIndex
);
}
else
{
// TODO is this branch possible?
groupData
.
resetLazy
();
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/dml/SelectGroups.java
浏览文件 @
4c2a4489
...
...
@@ -24,7 +24,7 @@ import org.h2.value.ValueArray;
* Call sequence:
* </p>
* <ul>
* <li>{@link #reset()}
(not required before the first execution)
.</li>
* <li>{@link #reset()}.</li>
* <li>For each source row {@link #nextSource()} should be invoked.</li>
* <li>{@link #done()}.</li>
* <li>{@link #next()} is invoked inside a loop until it returns null.</li>
...
...
@@ -39,51 +39,179 @@ import org.h2.value.ValueArray;
* can have one or more rows.</li>
* </ul>
*/
public
final
class
SelectGroups
{
public
abstract
class
SelectGroups
{
private
final
Session
session
;
private
final
ArrayList
<
Expression
>
expressions
;
private
static
final
class
Grouped
extends
SelectGroups
{
private
final
int
[]
groupIndex
;
/**
* The array of current group-by expression data e.g. AggregateData.
*/
private
Object
[]
currentGroupByExprData
;
/**
* Maps an expression object to an index, to use in accessing the Object[]
* pointed to by groupByData.
*/
private
final
HashMap
<
Expression
,
Integer
>
exprToIndexInGroupByData
=
new
HashMap
<>();
/**
* Map of group-by key to group-by expression data e.g. AggregateData
*/
private
HashMap
<
ValueArray
,
Object
[]>
groupByData
;
/**
* Key into groupByData that produces currentGroupByExprData. Not used in
*
lazy mode.
* Key into groupByData that produces currentGroupByExprData. Not used
* in
lazy mode.
*/
private
ValueArray
currentGroupsKey
;
/**
* The id of the current group
.
* Cursor for {@link #next()} method
.
*/
private
int
currentGroupRowId
;
private
Iterator
<
Entry
<
ValueArray
,
Object
[]>>
cursor
;
/**
* The key for the default group.
*/
// Can be static, but TestClearReferences complains about it
private
ValueArray
defaultGroup
=
ValueArray
.
get
(
new
Value
[
0
]);
private
final
ValueArray
defaultGroup
=
ValueArray
.
get
(
new
Value
[
0
]);
Grouped
(
Session
session
,
ArrayList
<
Expression
>
expressions
,
int
[]
groupIndex
)
{
super
(
session
,
expressions
);
this
.
groupIndex
=
groupIndex
;
}
@Override
public
void
reset
()
{
super
.
reset
();
groupByData
=
new
HashMap
<>();
currentGroupsKey
=
null
;
cursor
=
null
;
}
@Override
public
void
nextSource
()
{
if
(
groupIndex
==
null
)
{
currentGroupsKey
=
defaultGroup
;
}
else
{
Value
[]
keyValues
=
new
Value
[
groupIndex
.
length
];
// update group
for
(
int
i
=
0
;
i
<
groupIndex
.
length
;
i
++)
{
int
idx
=
groupIndex
[
i
];
Expression
expr
=
expressions
.
get
(
idx
);
keyValues
[
i
]
=
expr
.
getValue
(
session
);
}
currentGroupsKey
=
ValueArray
.
get
(
keyValues
);
}
Object
[]
values
=
groupByData
.
get
(
currentGroupsKey
);
if
(
values
==
null
)
{
values
=
new
Object
[
Math
.
max
(
exprToIndexInGroupByData
.
size
(),
expressions
.
size
())];
groupByData
.
put
(
currentGroupsKey
,
values
);
}
currentGroupByExprData
=
values
;
currentGroupRowId
++;
}
@Override
void
updateCurrentGroupExprData
()
{
// this can be null in lazy mode
if
(
currentGroupsKey
!=
null
)
{
// since we changed the size of the array, update the object in
// the groups map
groupByData
.
put
(
currentGroupsKey
,
currentGroupByExprData
);
}
}
@Override
public
void
done
()
{
if
(
groupIndex
==
null
&&
groupByData
.
size
()
==
0
)
{
groupByData
.
put
(
defaultGroup
,
new
Object
[
Math
.
max
(
exprToIndexInGroupByData
.
size
(),
expressions
.
size
())]);
}
cursor
=
groupByData
.
entrySet
().
iterator
();
}
@Override
public
ValueArray
next
()
{
if
(
cursor
.
hasNext
())
{
Map
.
Entry
<
ValueArray
,
Object
[]>
entry
=
cursor
.
next
();
currentGroupByExprData
=
entry
.
getValue
();
return
entry
.
getKey
();
}
return
null
;
}
@Override
public
void
resetLazy
()
{
super
.
resetLazy
();
currentGroupsKey
=
null
;
}
}
private
static
final
class
Plain
extends
SelectGroups
{
private
ArrayList
<
Object
[]>
rows
;
/**
* Cursor for {@link #next()} method.
*/
private
Iterator
<
Entry
<
ValueArray
,
Object
[]>>
cursor
;
private
Iterator
<
Object
[]>
cursor
;
Plain
(
Session
session
,
ArrayList
<
Expression
>
expressions
)
{
super
(
session
,
expressions
);
}
@Override
public
void
reset
()
{
super
.
reset
();
rows
=
new
ArrayList
<>();
cursor
=
null
;
}
@Override
public
void
nextSource
()
{
Object
[]
values
=
new
Object
[
Math
.
max
(
exprToIndexInGroupByData
.
size
(),
expressions
.
size
())];
rows
.
add
(
values
);
currentGroupByExprData
=
values
;
currentGroupRowId
++;
}
@Override
void
updateCurrentGroupExprData
()
{
rows
.
set
(
rows
.
size
()
-
1
,
currentGroupByExprData
);
}
@Override
public
void
done
()
{
cursor
=
rows
.
iterator
();
}
@Override
public
ValueArray
next
()
{
if
(
cursor
.
hasNext
())
{
Object
[]
values
=
cursor
.
next
();
currentGroupByExprData
=
values
;
return
ValueArray
.
get
(
new
Value
[
0
]);
}
return
null
;
}
}
final
Session
session
;
final
ArrayList
<
Expression
>
expressions
;
/**
* The array of current group-by expression data e.g. AggregateData.
*/
Object
[]
currentGroupByExprData
;
/**
* Maps an expression object to an index, to use in accessing the Object[]
* pointed to by groupByData.
*/
final
HashMap
<
Expression
,
Integer
>
exprToIndexInGroupByData
=
new
HashMap
<>();
/**
* Maps an expression object to its data.
*/
private
final
HashMap
<
Expression
,
Object
>
windowData
=
new
HashMap
<>();
/**
* The id of the current group.
*/
int
currentGroupRowId
;
/**
* Creates new instance of grouped data.
...
...
@@ -92,13 +220,19 @@ public final class SelectGroups {
* the session
* @param expressions
* the expressions
* @param isGroupQuery
* is this query is a group query
* @param groupIndex
* the indexes of group expressions, or null
*/
public
SelectGroups
(
Session
session
,
ArrayList
<
Expression
>
expressions
,
int
[]
groupIndex
)
{
public
static
SelectGroups
getInstance
(
Session
session
,
ArrayList
<
Expression
>
expressions
,
boolean
isGroupQuery
,
int
[]
groupIndex
)
{
return
isGroupQuery
?
new
Grouped
(
session
,
expressions
,
groupIndex
)
:
new
Plain
(
session
,
expressions
);
}
SelectGroups
(
Session
session
,
ArrayList
<
Expression
>
expressions
)
{
this
.
session
=
session
;
this
.
expressions
=
expressions
;
this
.
groupIndex
=
groupIndex
;
}
/**
...
...
@@ -110,8 +244,17 @@ public final class SelectGroups {
/**
* Get the group-by data for the current group and the passed in expression.
*
* @param expr
* expression
* @param window
* true if expression is a window expression
* @return expression data or null
*/
public
Object
getCurrentGroupExprData
(
Expression
expr
)
{
public
Object
getCurrentGroupExprData
(
Expression
expr
,
boolean
window
)
{
if
(
window
)
{
return
windowData
.
get
(
expr
);
}
Integer
index
=
exprToIndexInGroupByData
.
get
(
expr
);
if
(
index
==
null
)
{
return
null
;
...
...
@@ -121,8 +264,20 @@ public final class SelectGroups {
/**
* Set the group-by data for the current group and the passed in expression.
*
* @param expr
* expression
* @param object
* expression data to set
* @param window
* true if expression is a window expression
*/
public
void
setCurrentGroupExprData
(
Expression
expr
,
Object
obj
)
{
public
void
setCurrentGroupExprData
(
Expression
expr
,
Object
obj
,
boolean
window
)
{
if
(
window
)
{
Object
old
=
windowData
.
put
(
expr
,
obj
);
assert
old
==
null
;
return
;
}
Integer
index
=
exprToIndexInGroupByData
.
get
(
expr
);
if
(
index
!=
null
)
{
assert
currentGroupByExprData
[
index
]
==
null
;
...
...
@@ -133,16 +288,13 @@ public final class SelectGroups {
exprToIndexInGroupByData
.
put
(
expr
,
index
);
if
(
index
>=
currentGroupByExprData
.
length
)
{
currentGroupByExprData
=
Arrays
.
copyOf
(
currentGroupByExprData
,
currentGroupByExprData
.
length
*
2
);
// this can be null in lazy mode
if
(
currentGroupsKey
!=
null
)
{
// since we changed the size of the array, update the object in
// the groups map
groupByData
.
put
(
currentGroupsKey
,
currentGroupByExprData
);
}
updateCurrentGroupExprData
();
}
currentGroupByExprData
[
index
]
=
obj
;
}
abstract
void
updateCurrentGroupExprData
();
/**
* Returns identity of the current row. Used by aggregates to check whether
* they already processed this row or not.
...
...
@@ -157,72 +309,34 @@ public final class SelectGroups {
* Resets this group data for reuse.
*/
public
void
reset
()
{
groupByData
=
new
HashMap
<>();
currentGroupByExprData
=
null
;
currentGroupsKey
=
null
;
exprToIndexInGroupByData
.
clear
();
cursor
=
null
;
windowData
.
clear
()
;
}
/**
* Invoked for each source row to evaluate group key and setup all necessary
* data for aggregates.
*
* @return key of the current group
*/
public
ValueArray
nextSource
()
{
if
(
groupIndex
==
null
)
{
currentGroupsKey
=
defaultGroup
;
}
else
{
Value
[]
keyValues
=
new
Value
[
groupIndex
.
length
];
// update group
for
(
int
i
=
0
;
i
<
groupIndex
.
length
;
i
++)
{
int
idx
=
groupIndex
[
i
];
Expression
expr
=
expressions
.
get
(
idx
);
keyValues
[
i
]
=
expr
.
getValue
(
session
);
}
currentGroupsKey
=
ValueArray
.
get
(
keyValues
);
}
Object
[]
values
=
groupByData
.
get
(
currentGroupsKey
);
if
(
values
==
null
)
{
values
=
new
Object
[
Math
.
max
(
exprToIndexInGroupByData
.
size
(),
expressions
.
size
())];
groupByData
.
put
(
currentGroupsKey
,
values
);
}
currentGroupByExprData
=
values
;
currentGroupRowId
++;
return
currentGroupsKey
;
}
public
abstract
void
nextSource
();
/**
* Invoked after all source rows are evaluated.
*/
public
void
done
()
{
if
(
groupIndex
==
null
&&
groupByData
.
size
()
==
0
)
{
groupByData
.
put
(
defaultGroup
,
new
Object
[
Math
.
max
(
exprToIndexInGroupByData
.
size
(),
expressions
.
size
())]);
}
cursor
=
groupByData
.
entrySet
().
iterator
();
}
public
abstract
void
done
();
/**
* Returns the key of the next group.
*
* @return the key of the next group, or null
*/
public
ValueArray
next
()
{
if
(
cursor
.
hasNext
())
{
Map
.
Entry
<
ValueArray
,
Object
[]>
entry
=
cursor
.
next
();
currentGroupByExprData
=
entry
.
getValue
();
return
entry
.
getKey
();
}
return
null
;
}
public
abstract
ValueArray
next
();
/**
* Resets this group data for reuse in lazy mode.
*/
public
void
resetLazy
()
{
currentGroupByExprData
=
null
;
currentGroupsKey
=
null
;
}
/**
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/ExpressionColumn.java
浏览文件 @
4c2a4489
...
...
@@ -164,9 +164,9 @@ public class ExpressionColumn extends Expression {
// this is a different level (the enclosing query)
return
;
}
Value
v
=
(
Value
)
groupData
.
getCurrentGroupExprData
(
this
);
Value
v
=
(
Value
)
groupData
.
getCurrentGroupExprData
(
this
,
false
);
if
(
v
==
null
)
{
groupData
.
setCurrentGroupExprData
(
this
,
now
);
groupData
.
setCurrentGroupExprData
(
this
,
now
,
false
);
}
else
{
if
(!
database
.
areEqual
(
now
,
v
))
{
throw
DbException
.
get
(
ErrorCode
.
MUST_GROUP_BY_COLUMN_1
,
getSQL
());
...
...
@@ -180,7 +180,7 @@ public class ExpressionColumn extends Expression {
if
(
select
!=
null
)
{
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
false
);
if
(
groupData
!=
null
)
{
Value
v
=
(
Value
)
groupData
.
getCurrentGroupExprData
(
this
);
Value
v
=
(
Value
)
groupData
.
getCurrentGroupExprData
(
this
,
false
);
if
(
v
!=
null
)
{
return
v
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/aggregate/Aggregate.java
浏览文件 @
4c2a4489
...
...
@@ -170,10 +170,14 @@ public class Aggregate extends AbstractAggregate {
/**
* Create a new aggregate object.
*
* @param type the aggregate type
* @param on the aggregated expression
* @param select the select statement
* @param distinct if distinct is used
* @param type
* the aggregate type
* @param on
* the aggregated expression
* @param select
* the select statement
* @param distinct
* if distinct is used
*/
public
Aggregate
(
AggregateType
type
,
Expression
on
,
Select
select
,
boolean
distinct
)
{
this
.
type
=
type
;
...
...
@@ -229,8 +233,10 @@ public class Aggregate extends AbstractAggregate {
* Get the aggregate type for this name, or -1 if no aggregate has been
* found.
*
* @param name the aggregate function name
* @return null if no aggregate function has been found, or the aggregate type
* @param name
* the aggregate function name
* @return null if no aggregate function has been found, or the aggregate
* type
*/
public
static
AggregateType
getAggregateType
(
String
name
)
{
return
AGGREGATES
.
get
(
name
);
...
...
@@ -239,7 +245,8 @@ public class Aggregate extends AbstractAggregate {
/**
* Set the order for ARRAY_AGG() or GROUP_CONCAT() aggregate.
*
* @param orderByList the order by list
* @param orderByList
* the order by list
*/
public
void
setOrderByList
(
ArrayList
<
SelectOrderBy
>
orderByList
)
{
this
.
orderByList
=
orderByList
;
...
...
@@ -248,7 +255,8 @@ public class Aggregate extends AbstractAggregate {
/**
* Set the separator for the GROUP_CONCAT() aggregate.
*
* @param separator the separator expression
* @param separator
* the separator expression
*/
public
void
setGroupConcatSeparator
(
Expression
separator
)
{
this
.
groupConcatSeparator
=
separator
;
...
...
@@ -286,7 +294,7 @@ public class Aggregate extends AbstractAggregate {
// if (on != null) {
// on.updateAggregate();
// }
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
true
);
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
over
!=
null
);
if
(
groupData
==
null
)
{
// this is a different level (the enclosing query)
return
;
...
...
@@ -299,6 +307,9 @@ public class Aggregate extends AbstractAggregate {
}
lastGroupRowId
=
groupRowId
;
if
(
over
!=
null
)
{
over
.
updateAggregate
(
session
);
}
if
(
filterCondition
!=
null
)
{
if
(!
filterCondition
.
getBooleanValue
(
session
))
{
return
;
...
...
@@ -366,7 +377,7 @@ public class Aggregate extends AbstractAggregate {
DbException
.
throwInternalError
(
"type="
+
type
);
}
}
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
true
);
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
over
!=
null
);
if
(
groupData
==
null
)
{
throw
DbException
.
get
(
ErrorCode
.
INVALID_USE_OF_AGGREGATE_FUNCTION_1
,
getSQL
());
}
...
...
@@ -381,8 +392,7 @@ public class Aggregate extends AbstractAggregate {
sortWithOrderBy
(
array
);
}
StatementBuilder
buff
=
new
StatementBuilder
();
String
sep
=
groupConcatSeparator
==
null
?
","
:
groupConcatSeparator
.
getValue
(
session
).
getString
();
String
sep
=
groupConcatSeparator
==
null
?
","
:
groupConcatSeparator
.
getValue
(
session
).
getString
();
for
(
Value
val
:
array
)
{
String
s
;
if
(
val
.
getType
()
==
Value
.
ARRAY
)
{
...
...
@@ -431,10 +441,11 @@ public class Aggregate extends AbstractAggregate {
ValueArray
key
;
if
(
over
!=
null
&&
(
key
=
over
.
getCurrentKey
(
session
))
!=
null
)
{
@SuppressWarnings
(
"unchecked"
)
ValueHashMap
<
AggregateData
>
map
=
(
ValueHashMap
<
AggregateData
>)
groupData
.
getCurrentGroupExprData
(
this
);
ValueHashMap
<
AggregateData
>
map
=
(
ValueHashMap
<
AggregateData
>)
groupData
.
getCurrentGroupExprData
(
this
,
true
);
if
(
map
==
null
)
{
map
=
new
ValueHashMap
<>();
groupData
.
setCurrentGroupExprData
(
this
,
map
);
groupData
.
setCurrentGroupExprData
(
this
,
map
,
true
);
}
data
=
map
.
get
(
key
);
if
(
data
==
null
)
{
...
...
@@ -442,10 +453,10 @@ public class Aggregate extends AbstractAggregate {
map
.
put
(
key
,
data
);
}
}
else
{
data
=
(
AggregateData
)
groupData
.
getCurrentGroupExprData
(
this
);
data
=
(
AggregateData
)
groupData
.
getCurrentGroupExprData
(
this
,
over
!=
null
);
if
(
data
==
null
)
{
data
=
AggregateData
.
create
(
type
);
groupData
.
setCurrentGroupExprData
(
this
,
data
);
groupData
.
setCurrentGroupExprData
(
this
,
data
,
over
!=
null
);
}
}
return
data
;
...
...
@@ -766,8 +777,7 @@ public class Aggregate extends AbstractAggregate {
if
(
on
!=
null
&&
!
on
.
isEverything
(
visitor
))
{
return
false
;
}
if
(
groupConcatSeparator
!=
null
&&
!
groupConcatSeparator
.
isEverything
(
visitor
))
{
if
(
groupConcatSeparator
!=
null
&&
!
groupConcatSeparator
.
isEverything
(
visitor
))
{
return
false
;
}
if
(
orderByList
!=
null
)
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/aggregate/JavaAggregate.java
浏览文件 @
4c2a4489
...
...
@@ -160,7 +160,7 @@ public class JavaAggregate extends AbstractAggregate {
@Override
public
Value
getValue
(
Session
session
)
{
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
true
);
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
over
!=
null
);
if
(
groupData
==
null
)
{
throw
DbException
.
get
(
ErrorCode
.
INVALID_USE_OF_AGGREGATE_FUNCTION_1
,
getSQL
());
}
...
...
@@ -201,7 +201,7 @@ public class JavaAggregate extends AbstractAggregate {
@Override
public
void
updateAggregate
(
Session
session
)
{
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
true
);
SelectGroups
groupData
=
select
.
getGroupDataIfCurrent
(
over
!=
null
);
if
(
groupData
==
null
)
{
// this is a different level (the enclosing query)
return
;
...
...
@@ -214,6 +214,9 @@ public class JavaAggregate extends AbstractAggregate {
}
lastGroupRowId
=
groupRowId
;
if
(
over
!=
null
)
{
over
.
updateAggregate
(
session
);
}
if
(
filterCondition
!=
null
)
{
if
(!
filterCondition
.
getBooleanValue
(
session
))
{
return
;
...
...
@@ -253,13 +256,13 @@ public class JavaAggregate extends AbstractAggregate {
ValueArray
key
;
if
(
over
!=
null
&&
(
key
=
over
.
getCurrentKey
(
session
))
!=
null
)
{
@SuppressWarnings
(
"unchecked"
)
ValueHashMap
<
Aggregate
>
map
=
(
ValueHashMap
<
Aggregate
>)
groupData
.
getCurrentGroupExprData
(
this
);
ValueHashMap
<
Aggregate
>
map
=
(
ValueHashMap
<
Aggregate
>)
groupData
.
getCurrentGroupExprData
(
this
,
true
);
if
(
map
==
null
)
{
if
(
ifExists
)
{
return
null
;
}
map
=
new
ValueHashMap
<>();
groupData
.
setCurrentGroupExprData
(
this
,
map
);
groupData
.
setCurrentGroupExprData
(
this
,
map
,
true
);
}
data
=
map
.
get
(
key
);
if
(
data
==
null
)
{
...
...
@@ -270,13 +273,13 @@ public class JavaAggregate extends AbstractAggregate {
map
.
put
(
key
,
data
);
}
}
else
{
data
=
(
Aggregate
)
groupData
.
getCurrentGroupExprData
(
this
);
data
=
(
Aggregate
)
groupData
.
getCurrentGroupExprData
(
this
,
over
!=
null
);
if
(
data
==
null
)
{
if
(
ifExists
)
{
return
null
;
}
data
=
getInstance
();
groupData
.
setCurrentGroupExprData
(
this
,
data
);
groupData
.
setCurrentGroupExprData
(
this
,
data
,
over
!=
null
);
}
}
return
data
;
...
...
@@ -287,14 +290,14 @@ public class JavaAggregate extends AbstractAggregate {
ValueArray
key
;
if
(
over
!=
null
&&
(
key
=
over
.
getCurrentKey
(
session
))
!=
null
)
{
@SuppressWarnings
(
"unchecked"
)
ValueHashMap
<
AggregateDataCollecting
>
map
=
(
ValueHashMap
<
AggregateDataCollecting
>)
groupData
.
getCurrentGroupExprData
(
this
);
ValueHashMap
<
AggregateDataCollecting
>
map
=
(
ValueHashMap
<
AggregateDataCollecting
>)
groupData
.
getCurrentGroupExprData
(
this
,
true
);
if
(
map
==
null
)
{
if
(
ifExists
)
{
return
null
;
}
map
=
new
ValueHashMap
<>();
groupData
.
setCurrentGroupExprData
(
this
,
map
);
groupData
.
setCurrentGroupExprData
(
this
,
map
,
true
);
}
data
=
map
.
get
(
key
);
if
(
data
==
null
)
{
...
...
@@ -305,13 +308,13 @@ public class JavaAggregate extends AbstractAggregate {
map
.
put
(
key
,
data
);
}
}
else
{
data
=
(
AggregateDataCollecting
)
groupData
.
getCurrentGroupExprData
(
this
);
data
=
(
AggregateDataCollecting
)
groupData
.
getCurrentGroupExprData
(
this
,
over
!=
null
);
if
(
data
==
null
)
{
if
(
ifExists
)
{
return
null
;
}
data
=
new
AggregateDataCollecting
();
groupData
.
setCurrentGroupExprData
(
this
,
data
);
groupData
.
setCurrentGroupExprData
(
this
,
data
,
over
!=
null
);
}
}
return
data
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/aggregate/Window.java
浏览文件 @
4c2a4489
...
...
@@ -39,6 +39,7 @@ public final class Window {
* the column resolver
* @param level
* the subquery nesting level
* @see Expression#mapColumns(ColumnResolver, int)
*/
public
void
mapColumns
(
ColumnResolver
resolver
,
int
level
)
{
if
(
partitionBy
!=
null
)
{
...
...
@@ -56,6 +57,7 @@ public final class Window {
* the table filter
* @param value
* true if the table filter can return value
* @see Expression#setEvaluatable(TableFilter, boolean)
*/
public
void
setEvaluatable
(
TableFilter
tableFilter
,
boolean
value
)
{
if
(
partitionBy
!=
null
)
{
...
...
@@ -90,6 +92,7 @@ public final class Window {
* Returns SQL representation.
*
* @return SQL representation.
* @see Expression#getSQL()
*/
public
String
getSQL
()
{
if
(
partitionBy
==
null
)
{
...
...
@@ -105,6 +108,21 @@ public final class Window {
return
builder
.
append
(
')'
).
toString
();
}
/**
* Update an aggregate value.
*
* @param session
* the session
* @see Expression#updateAggregate(Session)
*/
public
void
updateAggregate
(
Session
session
)
{
if
(
partitionBy
!=
null
)
{
for
(
Expression
expr
:
partitionBy
)
{
expr
.
updateAggregate
(
session
);
}
}
}
@Override
public
String
toString
()
{
return
getSQL
();
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/scripts/functions/aggregate/array-agg.sql
浏览文件 @
4c2a4489
...
...
@@ -107,6 +107,17 @@ SELECT ARRAY_AGG(ID) OVER (PARTITION BY NAME), NAME FROM TEST;
>
(
4
,
5
,
6
)
c
>
rows
:
6
SELECT
ARRAY_AGG
(
ID
)
FILTER
(
WHERE
ID
<
3
OR
ID
>
4
)
OVER
(
PARTITION
BY
NAME
),
NAME
FROM
TEST
ORDER
BY
NAME
;
>
ARRAY_AGG
(
ID
)
FILTER
(
WHERE
((
ID
<
3
)
OR
(
ID
>
4
)))
OVER
(
PARTITION
BY
NAME
)
NAME
>
---------------------------------------------------------------------------- ----
>
(
1
,
2
)
a
>
(
1
,
2
)
a
>
null
b
>
(
5
,
6
)
c
>
(
5
,
6
)
c
>
(
5
,
6
)
c
>
rows
(
ordered
):
6
SELECT
ARRAY_AGG
(
SUM
(
ID
))
OVER
()
FROM
TEST
;
>
exception
FEATURE_NOT_SUPPORTED_1
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论