Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
69b68c52
Unverified
提交
69b68c52
authored
9月 16, 2018
作者:
Evgenij Ryazanov
提交者:
GitHub
9月 16, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1451 from katzyn/aggregate
Add experimental support for aggregates with OVER (ORDER BY *)
上级
19820759
5d541a4e
显示空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
349 行增加
和
58 行删除
+349
-58
Parser.java
h2/src/main/org/h2/command/Parser.java
+6
-1
Select.java
h2/src/main/org/h2/command/dml/Select.java
+5
-0
SelectGroups.java
h2/src/main/org/h2/command/dml/SelectGroups.java
+9
-0
AbstractAggregate.java
...c/main/org/h2/expression/aggregate/AbstractAggregate.java
+115
-8
Aggregate.java
h2/src/main/org/h2/expression/aggregate/Aggregate.java
+53
-39
JavaAggregate.java
h2/src/main/org/h2/expression/aggregate/JavaAggregate.java
+24
-2
PartitionData.java
h2/src/main/org/h2/expression/aggregate/PartitionData.java
+26
-0
Window.java
h2/src/main/org/h2/expression/aggregate/Window.java
+64
-8
array-agg.sql
...est/org/h2/test/scripts/functions/aggregate/array-agg.sql
+47
-0
没有找到文件。
h2/src/main/org/h2/command/Parser.java
浏览文件 @
69b68c52
...
@@ -3050,8 +3050,13 @@ public class Parser {
...
@@ -3050,8 +3050,13 @@ public class Parser {
partitionBy
.
add
(
expr
);
partitionBy
.
add
(
expr
);
}
while
(
readIf
(
COMMA
));
}
while
(
readIf
(
COMMA
));
}
}
ArrayList
<
SelectOrderBy
>
orderBy
=
null
;
if
(
readIf
(
ORDER
))
{
read
(
"BY"
);
orderBy
=
parseSimpleOrderList
();
}
read
(
CLOSE_PAREN
);
read
(
CLOSE_PAREN
);
aggregate
.
setOverCondition
(
new
Window
(
partitionBy
));
aggregate
.
setOverCondition
(
new
Window
(
partitionBy
,
orderBy
));
currentSelect
.
setWindowQuery
();
currentSelect
.
setWindowQuery
();
}
else
{
}
else
{
currentSelect
.
setGroupQuery
();
currentSelect
.
setGroupQuery
();
...
...
h2/src/main/org/h2/command/dml/Select.java
浏览文件 @
69b68c52
...
@@ -366,8 +366,10 @@ public class Select extends Query {
...
@@ -366,8 +366,10 @@ public class Select extends Query {
groupData
=
SelectGroups
.
getInstance
(
session
,
expressions
,
isGroupQuery
,
groupIndex
);
groupData
=
SelectGroups
.
getInstance
(
session
,
expressions
,
isGroupQuery
,
groupIndex
);
}
}
groupData
.
reset
();
groupData
.
reset
();
groupData
.
resetCounter
();
try
{
try
{
gatherGroup
(
columnCount
,
true
);
gatherGroup
(
columnCount
,
true
);
groupData
.
resetCounter
();
processGroupResult
(
columnCount
,
result
,
offset
,
quickOffset
);
processGroupResult
(
columnCount
,
result
,
offset
,
quickOffset
);
}
finally
{
}
finally
{
groupData
.
reset
();
groupData
.
reset
();
...
@@ -379,12 +381,15 @@ public class Select extends Query {
...
@@ -379,12 +381,15 @@ public class Select extends Query {
groupData
=
SelectGroups
.
getInstance
(
session
,
expressions
,
isGroupQuery
,
groupIndex
);
groupData
=
SelectGroups
.
getInstance
(
session
,
expressions
,
isGroupQuery
,
groupIndex
);
}
}
groupData
.
reset
();
groupData
.
reset
();
groupData
.
resetCounter
();
try
{
try
{
gatherGroup
(
columnCount
,
false
);
gatherGroup
(
columnCount
,
false
);
groupData
.
resetCounter
();
while
(
groupData
.
next
()
!=
null
)
{
while
(
groupData
.
next
()
!=
null
)
{
updateAgg
(
columnCount
,
true
);
updateAgg
(
columnCount
,
true
);
}
}
groupData
.
done
();
groupData
.
done
();
groupData
.
resetCounter
();
try
{
try
{
isGroupWindowStage2
=
true
;
isGroupWindowStage2
=
true
;
processGroupResult
(
columnCount
,
result
,
offset
,
quickOffset
);
processGroupResult
(
columnCount
,
result
,
offset
,
quickOffset
);
...
...
h2/src/main/org/h2/command/dml/SelectGroups.java
浏览文件 @
69b68c52
...
@@ -183,6 +183,7 @@ public abstract class SelectGroups {
...
@@ -183,6 +183,7 @@ public abstract class SelectGroups {
if
(
cursor
.
hasNext
())
{
if
(
cursor
.
hasNext
())
{
Object
[]
values
=
cursor
.
next
();
Object
[]
values
=
cursor
.
next
();
currentGroupByExprData
=
values
;
currentGroupByExprData
=
values
;
currentGroupRowId
++;
return
ValueArray
.
get
(
new
Value
[
0
]);
return
ValueArray
.
get
(
new
Value
[
0
]);
}
}
return
null
;
return
null
;
...
@@ -315,6 +316,14 @@ public abstract class SelectGroups {
...
@@ -315,6 +316,14 @@ public abstract class SelectGroups {
windowData
.
clear
();
windowData
.
clear
();
}
}
/**
* Reset the row id counter.
*/
public
void
resetCounter
()
{
// TODO merge into reset() and done()
currentGroupRowId
=
0
;
}
/**
/**
* Invoked for each source row to evaluate group key and setup all necessary
* Invoked for each source row to evaluate group key and setup all necessary
* data for aggregates.
* data for aggregates.
...
...
h2/src/main/org/h2/expression/aggregate/AbstractAggregate.java
浏览文件 @
69b68c52
...
@@ -5,17 +5,24 @@
...
@@ -5,17 +5,24 @@
*/
*/
package
org
.
h2
.
expression
.
aggregate
;
package
org
.
h2
.
expression
.
aggregate
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.dml.Select
;
import
org.h2.command.dml.Select
;
import
org.h2.command.dml.SelectGroups
;
import
org.h2.command.dml.SelectGroups
;
import
org.h2.command.dml.SelectOrderBy
;
import
org.h2.engine.Session
;
import
org.h2.engine.Session
;
import
org.h2.expression.Expression
;
import
org.h2.expression.Expression
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.result.SortOrder
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.table.TableFilter
;
import
org.h2.util.ValueHashMap
;
import
org.h2.util.ValueHashMap
;
import
org.h2.value.Value
;
import
org.h2.value.Value
;
import
org.h2.value.ValueArray
;
import
org.h2.value.ValueArray
;
import
org.h2.value.ValueInt
;
/**
/**
* A base class for aggregates.
* A base class for aggregates.
...
@@ -30,8 +37,22 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -30,8 +37,22 @@ public abstract class AbstractAggregate extends Expression {
protected
Window
over
;
protected
Window
over
;
private
SortOrder
overOrderBySort
;
private
int
lastGroupRowId
;
private
int
lastGroupRowId
;
protected
static
SortOrder
createOrder
(
Session
session
,
ArrayList
<
SelectOrderBy
>
orderBy
,
int
offset
)
{
int
size
=
orderBy
.
size
();
int
[]
index
=
new
int
[
size
];
int
[]
sortType
=
new
int
[
size
];
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
SelectOrderBy
o
=
orderBy
.
get
(
i
);
index
[
i
]
=
i
+
offset
;
sortType
[
i
]
=
o
.
sortType
;
}
return
new
SortOrder
(
session
.
getDatabase
(),
index
,
sortType
,
null
);
}
AbstractAggregate
(
Select
select
,
boolean
distinct
)
{
AbstractAggregate
(
Select
select
,
boolean
distinct
)
{
this
.
select
=
select
;
this
.
select
=
select
;
this
.
distinct
=
distinct
;
this
.
distinct
=
distinct
;
...
@@ -67,6 +88,17 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -67,6 +88,17 @@ public abstract class AbstractAggregate extends Expression {
}
}
}
}
@Override
public
Expression
optimize
(
Session
session
)
{
if
(
over
!=
null
)
{
ArrayList
<
SelectOrderBy
>
orderBy
=
over
.
getOrderBy
();
if
(
orderBy
!=
null
)
{
overOrderBySort
=
createOrder
(
session
,
orderBy
,
getNumExpressions
());
}
}
return
this
;
}
@Override
@Override
public
void
setEvaluatable
(
TableFilter
tableFilter
,
boolean
b
)
{
public
void
setEvaluatable
(
TableFilter
tableFilter
,
boolean
b
)
{
if
(
filterCondition
!=
null
)
{
if
(
filterCondition
!=
null
)
{
...
@@ -116,7 +148,14 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -116,7 +148,14 @@ public abstract class AbstractAggregate extends Expression {
return
;
return
;
}
}
}
}
updateAggregate
(
session
,
getData
(
session
,
groupData
,
false
));
if
(
over
!=
null
)
{
ArrayList
<
SelectOrderBy
>
orderBy
=
over
.
getOrderBy
();
if
(
orderBy
!=
null
)
{
updateOrderedAggregate
(
session
,
groupData
,
groupRowId
,
orderBy
);
return
;
}
}
updateAggregate
(
session
,
getData
(
session
,
groupData
,
false
,
false
));
}
}
/**
/**
...
@@ -138,7 +177,36 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -138,7 +177,36 @@ public abstract class AbstractAggregate extends Expression {
*/
*/
protected
abstract
void
updateGroupAggregates
(
Session
session
);
protected
abstract
void
updateGroupAggregates
(
Session
session
);
protected
Object
getData
(
Session
session
,
SelectGroups
groupData
,
boolean
ifExists
)
{
/**
* Returns the number of expressions, excluding FILTER and OVER clauses.
*
* @return the number of expressions
*/
protected
abstract
int
getNumExpressions
();
/**
* Stores current values of expressions into the specified array.
*
* @param session
* the session
* @param array
* array to store values of expressions
*/
protected
abstract
void
rememberExpressions
(
Session
session
,
Value
[]
array
);
/**
* Updates the provided aggregate data from the remembered expressions.
*
* @param session
* the session
* @param aggregateData
* aggregate data
* @param array
* values of expressions
*/
protected
abstract
void
updateFromExpressions
(
Session
session
,
Object
aggregateData
,
Value
[]
array
);
protected
Object
getData
(
Session
session
,
SelectGroups
groupData
,
boolean
ifExists
,
boolean
forOrderBy
)
{
Object
data
;
Object
data
;
if
(
over
!=
null
)
{
if
(
over
!=
null
)
{
ValueArray
key
=
over
.
getCurrentKey
(
session
);
ValueArray
key
=
over
.
getCurrentKey
(
session
);
...
@@ -157,7 +225,7 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -157,7 +225,7 @@ public abstract class AbstractAggregate extends Expression {
if
(
ifExists
)
{
if
(
ifExists
)
{
return
null
;
return
null
;
}
}
data
=
createAggregateData
();
data
=
forOrderBy
?
new
ArrayList
<>()
:
createAggregateData
();
map
.
put
(
key
,
new
PartitionData
(
data
));
map
.
put
(
key
,
new
PartitionData
(
data
));
}
else
{
}
else
{
data
=
partition
.
getData
();
data
=
partition
.
getData
();
...
@@ -168,7 +236,7 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -168,7 +236,7 @@ public abstract class AbstractAggregate extends Expression {
if
(
ifExists
)
{
if
(
ifExists
)
{
return
null
;
return
null
;
}
}
data
=
createAggregateData
();
data
=
forOrderBy
?
new
ArrayList
<>()
:
createAggregateData
();
groupData
.
setCurrentGroupExprData
(
this
,
new
PartitionData
(
data
),
true
);
groupData
.
setCurrentGroupExprData
(
this
,
new
PartitionData
(
data
),
true
);
}
else
{
}
else
{
data
=
partition
.
getData
();
data
=
partition
.
getData
();
...
@@ -180,7 +248,7 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -180,7 +248,7 @@ public abstract class AbstractAggregate extends Expression {
if
(
ifExists
)
{
if
(
ifExists
)
{
return
null
;
return
null
;
}
}
data
=
createAggregateData
();
data
=
forOrderBy
?
new
ArrayList
<>()
:
createAggregateData
();
groupData
.
setCurrentGroupExprData
(
this
,
data
,
false
);
groupData
.
setCurrentGroupExprData
(
this
,
data
,
false
);
}
}
}
}
...
@@ -195,13 +263,14 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -195,13 +263,14 @@ public abstract class AbstractAggregate extends Expression {
if
(
groupData
==
null
)
{
if
(
groupData
==
null
)
{
throw
DbException
.
get
(
ErrorCode
.
INVALID_USE_OF_AGGREGATE_FUNCTION_1
,
getSQL
());
throw
DbException
.
get
(
ErrorCode
.
INVALID_USE_OF_AGGREGATE_FUNCTION_1
,
getSQL
());
}
}
return
over
==
null
?
getAggregatedValue
(
session
,
getData
(
session
,
groupData
,
true
))
return
over
==
null
?
getAggregatedValue
(
session
,
getData
(
session
,
groupData
,
true
,
false
))
:
getWindowResult
(
session
,
groupData
);
:
getWindowResult
(
session
,
groupData
);
}
}
private
Value
getWindowResult
(
Session
session
,
SelectGroups
groupData
)
{
private
Value
getWindowResult
(
Session
session
,
SelectGroups
groupData
)
{
PartitionData
partition
;
PartitionData
partition
;
Object
data
;
Object
data
;
boolean
forOrderBy
=
over
.
getOrderBy
()
!=
null
;
ValueArray
key
=
over
.
getCurrentKey
(
session
);
ValueArray
key
=
over
.
getCurrentKey
(
session
);
if
(
key
!=
null
)
{
if
(
key
!=
null
)
{
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
...
@@ -212,7 +281,7 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -212,7 +281,7 @@ public abstract class AbstractAggregate extends Expression {
}
}
partition
=
(
PartitionData
)
map
.
get
(
key
);
partition
=
(
PartitionData
)
map
.
get
(
key
);
if
(
partition
==
null
)
{
if
(
partition
==
null
)
{
data
=
createAggregateData
();
data
=
forOrderBy
?
new
ArrayList
<>()
:
createAggregateData
();
partition
=
new
PartitionData
(
data
);
partition
=
new
PartitionData
(
data
);
map
.
put
(
key
,
partition
);
map
.
put
(
key
,
partition
);
}
else
{
}
else
{
...
@@ -221,13 +290,16 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -221,13 +290,16 @@ public abstract class AbstractAggregate extends Expression {
}
else
{
}
else
{
partition
=
(
PartitionData
)
groupData
.
getCurrentGroupExprData
(
this
,
true
);
partition
=
(
PartitionData
)
groupData
.
getCurrentGroupExprData
(
this
,
true
);
if
(
partition
==
null
)
{
if
(
partition
==
null
)
{
data
=
createAggregateData
();
data
=
forOrderBy
?
new
ArrayList
<>()
:
createAggregateData
();
partition
=
new
PartitionData
(
data
);
partition
=
new
PartitionData
(
data
);
groupData
.
setCurrentGroupExprData
(
this
,
partition
,
true
);
groupData
.
setCurrentGroupExprData
(
this
,
partition
,
true
);
}
else
{
}
else
{
data
=
partition
.
getData
();
data
=
partition
.
getData
();
}
}
}
}
if
(
over
.
getOrderBy
()
!=
null
)
{
return
getOrderedResult
(
session
,
groupData
,
partition
,
data
);
}
Value
result
=
partition
.
getResult
();
Value
result
=
partition
.
getResult
();
if
(
result
==
null
)
{
if
(
result
==
null
)
{
result
=
getAggregatedValue
(
session
,
data
);
result
=
getAggregatedValue
(
session
,
data
);
...
@@ -238,6 +310,41 @@ public abstract class AbstractAggregate extends Expression {
...
@@ -238,6 +310,41 @@ public abstract class AbstractAggregate extends Expression {
protected
abstract
Value
getAggregatedValue
(
Session
session
,
Object
aggregateData
);
protected
abstract
Value
getAggregatedValue
(
Session
session
,
Object
aggregateData
);
private
void
updateOrderedAggregate
(
Session
session
,
SelectGroups
groupData
,
int
groupRowId
,
ArrayList
<
SelectOrderBy
>
orderBy
)
{
int
ne
=
getNumExpressions
();
int
size
=
orderBy
.
size
();
Value
[]
array
=
new
Value
[
ne
+
size
+
1
];
rememberExpressions
(
session
,
array
);
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
SelectOrderBy
o
=
orderBy
.
get
(
i
);
array
[
ne
++]
=
o
.
expression
.
getValue
(
session
);
}
array
[
ne
]
=
ValueInt
.
get
(
groupRowId
);
@SuppressWarnings
(
"unchecked"
)
ArrayList
<
Value
[]>
data
=
(
ArrayList
<
Value
[]>)
getData
(
session
,
groupData
,
false
,
true
);
data
.
add
(
array
);
return
;
}
private
Value
getOrderedResult
(
Session
session
,
SelectGroups
groupData
,
PartitionData
partition
,
Object
data
)
{
HashMap
<
Integer
,
Value
>
result
=
partition
.
getOrderedResult
();
if
(
result
==
null
)
{
result
=
new
HashMap
<>();
@SuppressWarnings
(
"unchecked"
)
ArrayList
<
Value
[]>
orderedData
=
(
ArrayList
<
Value
[]>)
data
;
int
ne
=
getNumExpressions
();
int
last
=
ne
+
over
.
getOrderBy
().
size
();
Collections
.
sort
(
orderedData
,
overOrderBySort
);
Object
aggregateData
=
createAggregateData
();
for
(
Value
[]
row
:
orderedData
)
{
updateFromExpressions
(
session
,
aggregateData
,
row
);
result
.
put
(
row
[
last
].
getInt
(),
getAggregatedValue
(
session
,
aggregateData
));
}
}
return
result
.
get
(
groupData
.
getCurrentGroupRowId
());
}
protected
StringBuilder
appendTailConditions
(
StringBuilder
builder
)
{
protected
StringBuilder
appendTailConditions
(
StringBuilder
builder
)
{
if
(
filterCondition
!=
null
)
{
if
(
filterCondition
!=
null
)
{
builder
.
append
(
" FILTER (WHERE "
).
append
(
filterCondition
.
getSQL
()).
append
(
')'
);
builder
.
append
(
" FILTER (WHERE "
).
append
(
filterCondition
.
getSQL
()).
append
(
')'
);
...
...
h2/src/main/org/h2/expression/aggregate/Aggregate.java
浏览文件 @
69b68c52
...
@@ -256,18 +256,6 @@ public class Aggregate extends AbstractAggregate {
...
@@ -256,18 +256,6 @@ public class Aggregate extends AbstractAggregate {
this
.
groupConcatSeparator
=
separator
;
this
.
groupConcatSeparator
=
separator
;
}
}
private
SortOrder
initOrder
(
Session
session
)
{
int
size
=
orderByList
.
size
();
int
[]
index
=
new
int
[
size
];
int
[]
sortType
=
new
int
[
size
];
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
SelectOrderBy
o
=
orderByList
.
get
(
i
);
index
[
i
]
=
i
+
1
;
sortType
[
i
]
=
o
.
sortType
;
}
return
new
SortOrder
(
session
.
getDatabase
(),
index
,
sortType
,
null
);
}
private
void
sortWithOrderBy
(
Value
[]
array
)
{
private
void
sortWithOrderBy
(
Value
[]
array
)
{
final
SortOrder
sortOrder
=
orderBySort
;
final
SortOrder
sortOrder
=
orderBySort
;
if
(
sortOrder
!=
null
)
{
if
(
sortOrder
!=
null
)
{
...
@@ -286,13 +274,17 @@ public class Aggregate extends AbstractAggregate {
...
@@ -286,13 +274,17 @@ public class Aggregate extends AbstractAggregate {
protected
void
updateAggregate
(
Session
session
,
Object
aggregateData
)
{
protected
void
updateAggregate
(
Session
session
,
Object
aggregateData
)
{
AggregateData
data
=
(
AggregateData
)
aggregateData
;
AggregateData
data
=
(
AggregateData
)
aggregateData
;
Value
v
=
on
==
null
?
null
:
on
.
getValue
(
session
);
Value
v
=
on
==
null
?
null
:
on
.
getValue
(
session
);
updateData
(
session
,
data
,
v
,
null
);
}
private
void
updateData
(
Session
session
,
AggregateData
data
,
Value
v
,
Value
[]
remembered
)
{
if
(
type
==
AggregateType
.
GROUP_CONCAT
)
{
if
(
type
==
AggregateType
.
GROUP_CONCAT
)
{
if
(
v
!=
ValueNull
.
INSTANCE
)
{
if
(
v
!=
ValueNull
.
INSTANCE
)
{
v
=
updateCollecting
(
session
,
v
.
convertTo
(
Value
.
STRING
));
v
=
updateCollecting
(
session
,
v
.
convertTo
(
Value
.
STRING
)
,
remembered
);
}
}
}
else
if
(
type
==
AggregateType
.
ARRAY_AGG
)
{
}
else
if
(
type
==
AggregateType
.
ARRAY_AGG
)
{
if
(
v
!=
ValueNull
.
INSTANCE
)
{
if
(
v
!=
ValueNull
.
INSTANCE
)
{
v
=
updateCollecting
(
session
,
v
);
v
=
updateCollecting
(
session
,
v
,
remembered
);
}
}
}
}
data
.
add
(
session
.
getDatabase
(),
dataType
,
distinct
,
v
);
data
.
add
(
session
.
getDatabase
(),
dataType
,
distinct
,
v
);
...
@@ -310,20 +302,55 @@ public class Aggregate extends AbstractAggregate {
...
@@ -310,20 +302,55 @@ public class Aggregate extends AbstractAggregate {
}
}
}
}
private
Value
updateCollecting
(
Session
session
,
Value
v
)
{
private
Value
updateCollecting
(
Session
session
,
Value
v
,
Value
[]
remembered
)
{
if
(
orderByList
!=
null
)
{
if
(
orderByList
!=
null
)
{
int
size
=
orderByList
.
size
();
int
size
=
orderByList
.
size
();
Value
[]
array
=
new
Value
[
1
+
size
];
Value
[]
array
=
new
Value
[
1
+
size
];
array
[
0
]
=
v
;
array
[
0
]
=
v
;
if
(
remembered
==
null
)
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
SelectOrderBy
o
=
orderByList
.
get
(
i
);
SelectOrderBy
o
=
orderByList
.
get
(
i
);
array
[
i
+
1
]
=
o
.
expression
.
getValue
(
session
);
array
[
i
+
1
]
=
o
.
expression
.
getValue
(
session
);
}
}
}
else
{
for
(
int
i
=
1
;
i
<=
size
;
i
++)
{
array
[
i
]
=
remembered
[
i
];
}
}
v
=
ValueArray
.
get
(
array
);
v
=
ValueArray
.
get
(
array
);
}
}
return
v
;
return
v
;
}
}
@Override
protected
int
getNumExpressions
()
{
int
n
=
on
!=
null
?
1
:
0
;
if
(
orderByList
!=
null
)
{
n
+=
orderByList
.
size
();
}
return
n
;
}
@Override
protected
void
rememberExpressions
(
Session
session
,
Value
[]
array
)
{
int
offset
=
0
;
if
(
on
!=
null
)
{
array
[
offset
++]
=
on
.
getValue
(
session
);
}
if
(
orderByList
!=
null
)
{
for
(
SelectOrderBy
o
:
orderByList
)
{
array
[
offset
++]
=
o
.
expression
.
getValue
(
session
);
}
}
}
@Override
protected
void
updateFromExpressions
(
Session
session
,
Object
aggregateData
,
Value
[]
array
)
{
AggregateData
data
=
(
AggregateData
)
aggregateData
;
Value
v
=
on
==
null
?
null
:
array
[
0
];
updateData
(
session
,
data
,
v
,
array
);
}
@Override
@Override
protected
Object
createAggregateData
()
{
protected
Object
createAggregateData
()
{
return
AggregateData
.
create
(
type
);
return
AggregateData
.
create
(
type
);
...
@@ -450,6 +477,7 @@ public class Aggregate extends AbstractAggregate {
...
@@ -450,6 +477,7 @@ public class Aggregate extends AbstractAggregate {
@Override
@Override
public
Expression
optimize
(
Session
session
)
{
public
Expression
optimize
(
Session
session
)
{
super
.
optimize
(
session
);
if
(
on
!=
null
)
{
if
(
on
!=
null
)
{
on
=
on
.
optimize
(
session
);
on
=
on
.
optimize
(
session
);
dataType
=
on
.
getType
();
dataType
=
on
.
getType
();
...
@@ -461,7 +489,7 @@ public class Aggregate extends AbstractAggregate {
...
@@ -461,7 +489,7 @@ public class Aggregate extends AbstractAggregate {
for
(
SelectOrderBy
o
:
orderByList
)
{
for
(
SelectOrderBy
o
:
orderByList
)
{
o
.
expression
=
o
.
expression
.
optimize
(
session
);
o
.
expression
=
o
.
expression
.
optimize
(
session
);
}
}
orderBySort
=
initOrder
(
session
);
orderBySort
=
createOrder
(
session
,
orderByList
,
1
);
}
}
if
(
groupConcatSeparator
!=
null
)
{
if
(
groupConcatSeparator
!=
null
)
{
groupConcatSeparator
=
groupConcatSeparator
.
optimize
(
session
);
groupConcatSeparator
=
groupConcatSeparator
.
optimize
(
session
);
...
@@ -583,42 +611,28 @@ public class Aggregate extends AbstractAggregate {
...
@@ -583,42 +611,28 @@ public class Aggregate extends AbstractAggregate {
}
}
private
String
getSQLGroupConcat
()
{
private
String
getSQLGroupConcat
()
{
St
atementBuilder
buff
=
new
Statement
Builder
(
"GROUP_CONCAT("
);
St
ringBuilder
buff
=
new
String
Builder
(
"GROUP_CONCAT("
);
if
(
distinct
)
{
if
(
distinct
)
{
buff
.
append
(
"DISTINCT "
);
buff
.
append
(
"DISTINCT "
);
}
}
buff
.
append
(
on
.
getSQL
());
buff
.
append
(
on
.
getSQL
());
if
(
orderByList
!=
null
)
{
Window
.
appendOrderBy
(
buff
,
orderByList
);
buff
.
append
(
" ORDER BY "
);
for
(
SelectOrderBy
o
:
orderByList
)
{
buff
.
appendExceptFirst
(
", "
);
buff
.
append
(
o
.
expression
.
getSQL
());
SortOrder
.
typeToString
(
buff
.
builder
(),
o
.
sortType
);
}
}
if
(
groupConcatSeparator
!=
null
)
{
if
(
groupConcatSeparator
!=
null
)
{
buff
.
append
(
" SEPARATOR "
).
append
(
groupConcatSeparator
.
getSQL
());
buff
.
append
(
" SEPARATOR "
).
append
(
groupConcatSeparator
.
getSQL
());
}
}
buff
.
append
(
')'
);
buff
.
append
(
')'
);
return
appendTailConditions
(
buff
.
builder
()
).
toString
();
return
appendTailConditions
(
buff
).
toString
();
}
}
private
String
getSQLArrayAggregate
()
{
private
String
getSQLArrayAggregate
()
{
St
atementBuilder
buff
=
new
Statement
Builder
(
"ARRAY_AGG("
);
St
ringBuilder
buff
=
new
String
Builder
(
"ARRAY_AGG("
);
if
(
distinct
)
{
if
(
distinct
)
{
buff
.
append
(
"DISTINCT "
);
buff
.
append
(
"DISTINCT "
);
}
}
buff
.
append
(
on
.
getSQL
());
buff
.
append
(
on
.
getSQL
());
if
(
orderByList
!=
null
)
{
Window
.
appendOrderBy
(
buff
,
orderByList
);
buff
.
append
(
" ORDER BY "
);
for
(
SelectOrderBy
o
:
orderByList
)
{
buff
.
appendExceptFirst
(
", "
);
buff
.
append
(
o
.
expression
.
getSQL
());
SortOrder
.
typeToString
(
buff
.
builder
(),
o
.
sortType
);
}
}
buff
.
append
(
')'
);
buff
.
append
(
')'
);
return
appendTailConditions
(
buff
.
builder
()
).
toString
();
return
appendTailConditions
(
buff
).
toString
();
}
}
@Override
@Override
...
...
h2/src/main/org/h2/expression/aggregate/JavaAggregate.java
浏览文件 @
69b68c52
...
@@ -116,6 +116,7 @@ public class JavaAggregate extends AbstractAggregate {
...
@@ -116,6 +116,7 @@ public class JavaAggregate extends AbstractAggregate {
@Override
@Override
public
Expression
optimize
(
Session
session
)
{
public
Expression
optimize
(
Session
session
)
{
super
.
optimize
(
session
);
userConnection
=
session
.
createConnection
(
false
);
userConnection
=
session
.
createConnection
(
false
);
int
len
=
args
.
length
;
int
len
=
args
.
length
;
argTypes
=
new
int
[
len
];
argTypes
=
new
int
[
len
];
...
@@ -194,13 +195,17 @@ public class JavaAggregate extends AbstractAggregate {
...
@@ -194,13 +195,17 @@ public class JavaAggregate extends AbstractAggregate {
@Override
@Override
protected
void
updateAggregate
(
Session
session
,
Object
aggregateData
)
{
protected
void
updateAggregate
(
Session
session
,
Object
aggregateData
)
{
updateData
(
session
,
aggregateData
,
null
);
}
private
void
updateData
(
Session
session
,
Object
aggregateData
,
Value
[]
remembered
)
{
try
{
try
{
if
(
distinct
)
{
if
(
distinct
)
{
AggregateDataCollecting
data
=
(
AggregateDataCollecting
)
aggregateData
;
AggregateDataCollecting
data
=
(
AggregateDataCollecting
)
aggregateData
;
Value
[]
argValues
=
new
Value
[
args
.
length
];
Value
[]
argValues
=
new
Value
[
args
.
length
];
Value
arg
=
null
;
Value
arg
=
null
;
for
(
int
i
=
0
,
len
=
args
.
length
;
i
<
len
;
i
++)
{
for
(
int
i
=
0
,
len
=
args
.
length
;
i
<
len
;
i
++)
{
arg
=
args
[
i
].
getValue
(
session
)
;
arg
=
remembered
==
null
?
args
[
i
].
getValue
(
session
)
:
remembered
[
i
]
;
arg
=
arg
.
convertTo
(
argTypes
[
i
]);
arg
=
arg
.
convertTo
(
argTypes
[
i
]);
argValues
[
i
]
=
arg
;
argValues
[
i
]
=
arg
;
}
}
...
@@ -210,7 +215,7 @@ public class JavaAggregate extends AbstractAggregate {
...
@@ -210,7 +215,7 @@ public class JavaAggregate extends AbstractAggregate {
Object
[]
argValues
=
new
Object
[
args
.
length
];
Object
[]
argValues
=
new
Object
[
args
.
length
];
Object
arg
=
null
;
Object
arg
=
null
;
for
(
int
i
=
0
,
len
=
args
.
length
;
i
<
len
;
i
++)
{
for
(
int
i
=
0
,
len
=
args
.
length
;
i
<
len
;
i
++)
{
Value
v
=
args
[
i
].
getValue
(
session
)
;
Value
v
=
remembered
==
null
?
args
[
i
].
getValue
(
session
)
:
remembered
[
i
]
;
v
=
v
.
convertTo
(
argTypes
[
i
]);
v
=
v
.
convertTo
(
argTypes
[
i
]);
arg
=
v
.
getObject
();
arg
=
v
.
getObject
();
argValues
[
i
]
=
arg
;
argValues
[
i
]
=
arg
;
...
@@ -229,6 +234,23 @@ public class JavaAggregate extends AbstractAggregate {
...
@@ -229,6 +234,23 @@ public class JavaAggregate extends AbstractAggregate {
}
}
}
}
@Override
protected
int
getNumExpressions
()
{
return
args
.
length
;
}
@Override
protected
void
rememberExpressions
(
Session
session
,
Value
[]
array
)
{
for
(
int
i
=
0
;
i
<
args
.
length
;
i
++)
{
array
[
i
]
=
args
[
i
].
getValue
(
session
);
}
}
@Override
protected
void
updateFromExpressions
(
Session
session
,
Object
aggregateData
,
Value
[]
array
)
{
updateData
(
session
,
aggregateData
,
array
);
}
@Override
@Override
protected
Object
createAggregateData
()
{
protected
Object
createAggregateData
()
{
return
distinct
?
new
AggregateDataCollecting
()
:
getInstance
();
return
distinct
?
new
AggregateDataCollecting
()
:
getInstance
();
...
...
h2/src/main/org/h2/expression/aggregate/PartitionData.java
浏览文件 @
69b68c52
...
@@ -5,6 +5,8 @@
...
@@ -5,6 +5,8 @@
*/
*/
package
org
.
h2
.
expression
.
aggregate
;
package
org
.
h2
.
expression
.
aggregate
;
import
java.util.HashMap
;
import
org.h2.value.Value
;
import
org.h2.value.Value
;
/**
/**
...
@@ -22,6 +24,11 @@ final class PartitionData {
...
@@ -22,6 +24,11 @@ final class PartitionData {
*/
*/
private
Value
result
;
private
Value
result
;
/**
* Evaluated ordered result.
*/
private
HashMap
<
Integer
,
Value
>
orderedResult
;
/**
/**
* Creates new instance of partition data.
* Creates new instance of partition data.
*
*
...
@@ -60,4 +67,23 @@ final class PartitionData {
...
@@ -60,4 +67,23 @@ final class PartitionData {
this
.
result
=
result
;
this
.
result
=
result
;
}
}
/**
* Returns the ordered result.
*
* @return the ordered result
*/
HashMap
<
Integer
,
Value
>
getOrderedResult
()
{
return
orderedResult
;
}
/**
* Sets the ordered result.
*
* @param orderedResult
* the ordered result to set
*/
void
setOrderedResult
(
HashMap
<
Integer
,
Value
>
orderedResult
)
{
this
.
orderedResult
=
orderedResult
;
}
}
}
h2/src/main/org/h2/expression/aggregate/Window.java
浏览文件 @
69b68c52
...
@@ -7,8 +7,10 @@ package org.h2.expression.aggregate;
...
@@ -7,8 +7,10 @@ package org.h2.expression.aggregate;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
org.h2.command.dml.SelectOrderBy
;
import
org.h2.engine.Session
;
import
org.h2.engine.Session
;
import
org.h2.expression.Expression
;
import
org.h2.expression.Expression
;
import
org.h2.result.SortOrder
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.table.TableFilter
;
import
org.h2.util.StringUtils
;
import
org.h2.util.StringUtils
;
...
@@ -22,14 +24,39 @@ public final class Window {
...
@@ -22,14 +24,39 @@ public final class Window {
private
final
ArrayList
<
Expression
>
partitionBy
;
private
final
ArrayList
<
Expression
>
partitionBy
;
private
final
ArrayList
<
SelectOrderBy
>
orderBy
;
/**
* @param builder
* string builder
* @param orderBy
* ORDER BY clause, or null
*/
static
void
appendOrderBy
(
StringBuilder
builder
,
ArrayList
<
SelectOrderBy
>
orderBy
)
{
if
(
orderBy
!=
null
)
{
builder
.
append
(
" ORDER BY "
);
for
(
int
i
=
0
;
i
<
orderBy
.
size
();
i
++)
{
SelectOrderBy
o
=
orderBy
.
get
(
i
);
if
(
i
>
0
)
{
builder
.
append
(
", "
);
}
builder
.
append
(
o
.
expression
.
getSQL
());
SortOrder
.
typeToString
(
builder
,
o
.
sortType
);
}
}
}
/**
/**
* Creates a new instance of window clause.
* Creates a new instance of window clause.
*
*
* @param partitionBy
* @param partitionBy
* PARTITION BY clause, or null
* PARTITION BY clause, or null
* @param orderBy
* ORDER BY clause, or null
*/
*/
public
Window
(
ArrayList
<
Expression
>
partitionBy
)
{
public
Window
(
ArrayList
<
Expression
>
partitionBy
,
ArrayList
<
SelectOrderBy
>
orderBy
)
{
this
.
partitionBy
=
partitionBy
;
this
.
partitionBy
=
partitionBy
;
this
.
orderBy
=
orderBy
;
}
}
/**
/**
...
@@ -47,6 +74,11 @@ public final class Window {
...
@@ -47,6 +74,11 @@ public final class Window {
e
.
mapColumns
(
resolver
,
level
);
e
.
mapColumns
(
resolver
,
level
);
}
}
}
}
if
(
orderBy
!=
null
)
{
for
(
SelectOrderBy
o
:
orderBy
)
{
o
.
expression
.
mapColumns
(
resolver
,
level
);
}
}
}
}
/**
/**
...
@@ -65,6 +97,20 @@ public final class Window {
...
@@ -65,6 +97,20 @@ public final class Window {
e
.
setEvaluatable
(
tableFilter
,
value
);
e
.
setEvaluatable
(
tableFilter
,
value
);
}
}
}
}
if
(
orderBy
!=
null
)
{
for
(
SelectOrderBy
o
:
orderBy
)
{
o
.
expression
.
setEvaluatable
(
tableFilter
,
value
);
}
}
}
/**
* Returns ORDER BY clause.
*
* @return ORDER BY clause, or null
*/
public
ArrayList
<
SelectOrderBy
>
getOrderBy
()
{
return
orderBy
;
}
}
/**
/**
...
@@ -95,16 +141,20 @@ public final class Window {
...
@@ -95,16 +141,20 @@ public final class Window {
* @see Expression#getSQL()
* @see Expression#getSQL()
*/
*/
public
String
getSQL
()
{
public
String
getSQL
()
{
if
(
partitionBy
==
null
)
{
if
(
partitionBy
==
null
&&
orderBy
==
null
)
{
return
"OVER ()"
;
return
"OVER ()"
;
}
}
StringBuilder
builder
=
new
StringBuilder
().
append
(
"OVER (PARTITION BY "
);
StringBuilder
builder
=
new
StringBuilder
().
append
(
"OVER ("
);
if
(
partitionBy
!=
null
)
{
builder
.
append
(
"PARTITION BY "
);
for
(
int
i
=
0
;
i
<
partitionBy
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
partitionBy
.
size
();
i
++)
{
if
(
i
>
0
)
{
if
(
i
>
0
)
{
builder
.
append
(
", "
);
builder
.
append
(
", "
);
}
}
builder
.
append
(
StringUtils
.
unEnclose
(
partitionBy
.
get
(
i
).
getSQL
()));
builder
.
append
(
StringUtils
.
unEnclose
(
partitionBy
.
get
(
i
).
getSQL
()));
}
}
}
appendOrderBy
(
builder
,
orderBy
);
return
builder
.
append
(
')'
).
toString
();
return
builder
.
append
(
')'
).
toString
();
}
}
...
@@ -113,7 +163,8 @@ public final class Window {
...
@@ -113,7 +163,8 @@ public final class Window {
*
*
* @param session
* @param session
* the session
* the session
* @param window true for window processing stage, false for group stage
* @param window
* true for window processing stage, false for group stage
* @see Expression#updateAggregate(Session, boolean)
* @see Expression#updateAggregate(Session, boolean)
*/
*/
public
void
updateAggregate
(
Session
session
,
boolean
window
)
{
public
void
updateAggregate
(
Session
session
,
boolean
window
)
{
...
@@ -122,6 +173,11 @@ public final class Window {
...
@@ -122,6 +173,11 @@ public final class Window {
expr
.
updateAggregate
(
session
,
window
);
expr
.
updateAggregate
(
session
,
window
);
}
}
}
}
if
(
orderBy
!=
null
)
{
for
(
SelectOrderBy
o
:
orderBy
)
{
o
.
expression
.
updateAggregate
(
session
,
false
);
}
}
}
}
@Override
@Override
...
...
h2/src/test/org/h2/test/scripts/functions/aggregate/array-agg.sql
浏览文件 @
69b68c52
...
@@ -196,5 +196,52 @@ SELECT ARRAY_AGG(ARRAY_AGG(ID ORDER BY ID)) FILTER (WHERE NAME > 'c') OVER () FR
...
@@ -196,5 +196,52 @@ SELECT ARRAY_AGG(ARRAY_AGG(ID ORDER BY ID)) FILTER (WHERE NAME > 'c') OVER () FR
SELECT
ARRAY_AGG
(
ID
)
OVER
()
FROM
TEST
GROUP
BY
NAME
;
SELECT
ARRAY_AGG
(
ID
)
OVER
()
FROM
TEST
GROUP
BY
NAME
;
>
exception
MUST_GROUP_BY_COLUMN_1
>
exception
MUST_GROUP_BY_COLUMN_1
SELECT
ARRAY_AGG
(
ID
)
OVER
(
PARTITION
BY
NAME
ORDER
/**/
BY
ID
),
NAME
FROM
TEST
;
>
ARRAY_AGG
(
ID
)
OVER
(
PARTITION
BY
NAME
ORDER
BY
ID
)
NAME
>
-------------------------------------------------- ----
>
(
1
)
a
>
(
1
,
2
)
a
>
(
3
)
b
>
(
4
)
c
>
(
4
,
5
)
c
>
(
4
,
5
,
6
)
c
>
rows
:
6
SELECT
ARRAY_AGG
(
ID
)
OVER
(
PARTITION
BY
NAME
ORDER
/**/
BY
ID
DESC
),
NAME
FROM
TEST
;
>
ARRAY_AGG
(
ID
)
OVER
(
PARTITION
BY
NAME
ORDER
BY
ID
DESC
)
NAME
>
------------------------------------------------------- ----
>
(
2
)
a
>
(
2
,
1
)
a
>
(
3
)
b
>
(
6
)
c
>
(
6
,
5
)
c
>
(
6
,
5
,
4
)
c
>
rows
:
6
SELECT
ARRAY_AGG
(
ID
ORDER
/**/
BY
ID
)
OVER
(
PARTITION
BY
NAME
ORDER
/**/
BY
ID
DESC
)
A
,
ARRAY_AGG
(
ID
)
OVER
(
PARTITION
BY
NAME
ORDER
/**/
BY
ID
DESC
)
D
,
NAME
FROM
TEST
;
>
A
D
NAME
>
--------- --------- ----
>
(
1
,
2
)
(
2
,
1
)
a
>
(
2
)
(
2
)
a
>
(
3
)
(
3
)
b
>
(
4
,
5
,
6
)
(
6
,
5
,
4
)
c
>
(
5
,
6
)
(
6
,
5
)
c
>
(
6
)
(
6
)
c
>
rows
:
6
SELECT
ARRAY_AGG
(
SUM
(
ID
))
OVER
(
ORDER
/**/
BY
ID
)
FROM
TEST
GROUP
BY
ID
;
>
ARRAY_AGG
(
SUM
(
ID
))
OVER
(
ORDER
BY
ID
)
>
--------------------------------------
>
(
1
)
>
(
1
,
2
)
>
(
1
,
2
,
3
)
>
(
1
,
2
,
3
,
4
)
>
(
1
,
2
,
3
,
4
,
5
)
>
(
1
,
2
,
3
,
4
,
5
,
6
)
>
rows
:
6
DROP
TABLE
TEST
;
DROP
TABLE
TEST
;
>
ok
>
ok
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论