Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
49c8f3f4
提交
49c8f3f4
authored
8月 19, 2008
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Column aliases can now be used in GROUP BY and HAVING.
上级
a7fbae73
隐藏空白字符变更
内嵌
并排
正在显示
14 个修改的文件
包含
248 行增加
和
45 行删除
+248
-45
changelog.html
h2/src/docsrc/html/changelog.html
+1
-1
links.html
h2/src/docsrc/html/links.html
+26
-0
Select.java
h2/src/main/org/h2/command/dml/Select.java
+52
-27
SelectListColumnResolver.java
h2/src/main/org/h2/command/dml/SelectListColumnResolver.java
+82
-0
Aggregate.java
h2/src/main/org/h2/expression/Aggregate.java
+9
-0
Expression.java
h2/src/main/org/h2/expression/Expression.java
+5
-1
ExpressionColumn.java
h2/src/main/org/h2/expression/ExpressionColumn.java
+2
-2
JavaAggregate.java
h2/src/main/org/h2/expression/JavaAggregate.java
+9
-0
Column.java
h2/src/main/org/h2/table/Column.java
+1
-1
ColumnResolver.java
h2/src/main/org/h2/table/ColumnResolver.java
+11
-0
SingleColumnResolver.java
h2/src/main/org/h2/table/SingleColumnResolver.java
+6
-0
TableFilter.java
h2/src/main/org/h2/table/TableFilter.java
+5
-0
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+0
-13
test.in.txt
h2/src/test/org/h2/test/test.in.txt
+39
-0
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
49c8f3f4
...
...
@@ -16,7 +16,7 @@ Change Log
<h1>
Change Log
</h1>
<h2>
Next Version (unreleased)
</h2>
<ul><li>
-
<ul><li>
Column aliases can now be used in GROUP BY and HAVING.
</li></ul>
<h2>
Version 1.0.77 (2008-08-16)
</h2>
...
...
h2/src/docsrc/html/links.html
浏览文件 @
49c8f3f4
...
...
@@ -65,6 +65,11 @@ Linux Package Manager</a><br />
<h2>
Products and Projects
</h2>
<p><a
href=
"http://www.axiomstack.com/"
>
Axiom Stack
</a><br
/>
A web framework that let's you write dynamic web applications with Zen-like simplicity.
</p>
<p><a
href=
"http://cayenne.apache.org/"
>
Apache Cayenne
</a><br
/>
Open source persistence framework providing object-relational mapping (ORM) and remoting services.
...
...
@@ -115,10 +120,20 @@ DbVisualizer</a><br />
Database tool.
</p>
<p><a
href=
"http://antilogics.com/epictetus.html"
>
Epictetus
</a><br
/>
Free cross platform database tool.
</p>
<p><a
href=
"http://executequery.org"
>
Execute Query
</a><br
/>
Database utility written in Java.
</p>
<p><a
href=
"http://fabric3.codehaus.org/"
>
Fabric3
</a><br
/>
Fabric3 is a project implementing a federated service network based on the Service Component Architecture specification (http://www.osoa.org).
</p>
<p><a
href=
"http://www.fluxcorp.com"
>
Flux
</a><br
/>
...
...
@@ -273,6 +288,12 @@ databases, ontology-based domain modeling, and management of the
distributed enterprise.
</p>
<p><a
href=
"http://www.ontoprise.de/"
>
Ontoprise OntoBroker
</a><br
/>
SemanticWeb-Middleware. It supports all W3C Semantic Web recommendations:
OWL, RDF, RDFS, SPARQL, and F-Logic.
</p>
<p><a
href=
"http://www.orionserver.com/"
>
Orion
</a><br
/>
J2EE Application Server.
...
...
@@ -293,6 +314,11 @@ Pickle</a><br />
Pickle is a Java library containing classes for persistence, concurrency, and logging.
</p>
<p><a
href=
"http://www.pimansoft.com"
>
Piman
</a><br
/>
Water treatment projects data management.
</p>
<p><a
href=
"http://www.polepos.org"
>
PolePosition
</a><br
/>
Open source database benchmark.
...
...
h2/src/main/org/h2/command/dml/Select.java
浏览文件 @
49c8f3f4
...
...
@@ -77,6 +77,7 @@ public class Select extends Query {
private
boolean
isPrepared
,
checkInit
;
private
boolean
sortUsingIndex
;
private
SortOrder
sort
;
private
int
currentGroupRowId
;
public
Select
(
Session
session
)
{
super
(
session
);
...
...
@@ -125,6 +126,10 @@ public class Select extends Query {
public
HashMap
getCurrentGroup
()
{
return
currentGroup
;
}
public
int
getCurrentGroupRowId
()
{
return
currentGroupRowId
;
}
public
void
setOrder
(
ObjectArray
order
)
{
orderList
=
order
;
...
...
@@ -168,6 +173,7 @@ public class Select extends Query {
previousKeyValues
=
keyValues
;
currentGroup
=
new
HashMap
();
}
currentGroupRowId
++;
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
if
(
groupByExpression
==
null
||
!
groupByExpression
[
i
])
{
...
...
@@ -194,22 +200,34 @@ public class Select extends Query {
Expression
expr
=
(
Expression
)
expressions
.
get
(
j
);
row
[
j
]
=
expr
.
getValue
(
session
);
}
if
(
havingIndex
>
0
)
{
if
(
isHavingNullOrFalse
(
row
))
{
return
;
}
row
=
keepOnlyDistinct
(
row
,
columnCount
);
result
.
addRow
(
row
);
}
private
Value
[]
keepOnlyDistinct
(
Value
[]
row
,
int
columnCount
)
{
if
(
columnCount
==
distinctColumnCount
)
{
return
row
;
}
// remove columns so that 'distinct' can filter duplicate rows
Value
[]
r2
=
new
Value
[
distinctColumnCount
];
ObjectUtils
.
arrayCopy
(
row
,
r2
,
distinctColumnCount
);
return
r2
;
}
private
boolean
isHavingNullOrFalse
(
Value
[]
row
)
throws
SQLException
{
if
(
havingIndex
>=
0
)
{
Value
v
=
row
[
havingIndex
];
if
(
v
==
ValueNull
.
INSTANCE
)
{
return
;
return
true
;
}
if
(!
Boolean
.
TRUE
.
equals
(
v
.
getBoolean
()))
{
return
;
return
true
;
}
}
if
(
columnCount
!=
distinctColumnCount
)
{
// remove columns so that 'distinct' can filter duplicate rows
Value
[]
r2
=
new
Value
[
distinctColumnCount
];
ObjectUtils
.
arrayCopy
(
row
,
r2
,
distinctColumnCount
);
row
=
r2
;
}
result
.
addRow
(
row
);
return
false
;
}
private
Index
getGroupSortedIndex
()
{
...
...
@@ -295,6 +313,7 @@ public class Select extends Query {
groups
.
put
(
key
,
values
);
}
currentGroup
=
values
;
currentGroupRowId
++;
int
len
=
columnCount
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
if
(
groupByExpression
==
null
||
!
groupByExpression
[
i
])
{
...
...
@@ -326,21 +345,10 @@ public class Select extends Query {
Expression
expr
=
(
Expression
)
expressions
.
get
(
j
);
row
[
j
]
=
expr
.
getValue
(
session
);
}
if
(
havingIndex
>
0
)
{
Value
v
=
row
[
havingIndex
];
if
(
v
==
ValueNull
.
INSTANCE
)
{
continue
;
}
if
(!
Boolean
.
TRUE
.
equals
(
v
.
getBoolean
()))
{
continue
;
}
}
if
(
columnCount
!=
distinctColumnCount
)
{
// remove columns so that 'distinct' can filter duplicate rows
Value
[]
r2
=
new
Value
[
distinctColumnCount
];
ObjectUtils
.
arrayCopy
(
row
,
r2
,
distinctColumnCount
);
row
=
r2
;
if
(
isHavingNullOrFalse
(
row
))
{
continue
;
}
row
=
keepOnlyDistinct
(
row
,
columnCount
);
result
.
addRow
(
row
);
}
}
...
...
@@ -604,7 +612,7 @@ public class Select extends Query {
ObjectArray
expressionSQL
;
if
(
orderList
!=
null
||
group
!=
null
)
{
expressionSQL
=
new
ObjectArray
();
for
(
int
i
=
0
;
i
<
expressions
.
size
()
;
i
++)
{
for
(
int
i
=
0
;
i
<
visibleColumnCount
;
i
++)
{
Expression
expr
=
(
Expression
)
expressions
.
get
(
i
);
expr
=
expr
.
getNonAliasExpression
();
String
sql
=
expr
.
getSQL
();
...
...
@@ -625,8 +633,10 @@ public class Select extends Query {
havingIndex
=
-
1
;
}
// first visible columns, then order by, then having,
// and group by at the end
// first the select list (visible columns),
// then 'ORDER BY' expressions,
// then 'HAVING' expressions,
// and 'GROUP BY' expressions at the end
if
(
group
!=
null
)
{
groupIndex
=
new
int
[
group
.
size
()];
for
(
int
i
=
0
;
i
<
group
.
size
();
i
++)
{
...
...
@@ -640,6 +650,16 @@ public class Select extends Query {
break
;
}
}
if
(
found
<
0
)
{
// special case: GROUP BY a column alias
for
(
int
j
=
0
;
j
<
expressionSQL
.
size
();
j
++)
{
Expression
e
=
(
Expression
)
expressions
.
get
(
j
);
if
(
sql
.
equals
(
e
.
getAlias
()))
{
found
=
j
;
break
;
}
}
}
if
(
found
<
0
)
{
int
index
=
expressions
.
size
();
groupIndex
[
i
]
=
index
;
...
...
@@ -665,6 +685,11 @@ public class Select extends Query {
condition
.
mapColumns
(
f
,
0
);
}
}
if
(
havingIndex
>=
0
)
{
Expression
expr
=
(
Expression
)
expressions
.
get
(
havingIndex
);
SelectListColumnResolver
res
=
new
SelectListColumnResolver
(
this
);
expr
.
mapColumns
(
res
,
0
);
}
checkInit
=
true
;
}
...
...
h2/src/main/org/h2/command/dml/SelectListColumnResolver.java
0 → 100644
浏览文件 @
49c8f3f4
/*
* Copyright 2004-2008 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
command
.
dml
;
import
java.sql.SQLException
;
import
org.h2.expression.Expression
;
import
org.h2.expression.ExpressionColumn
;
import
org.h2.table.Column
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.util.ObjectArray
;
import
org.h2.value.Value
;
/**
* This class represents a column resolver for the column list of a SELECT
* statement. It is used to resolve select column aliases in the HAVING clause.
* Example:
* <p>
* SELECT X/3 AS A, COUNT(*) FROM SYSTEM_RANGE(1, 10) GROUP BY A HAVING A>2;
* </p>
*
* @author Thomas Mueller
*/
public
class
SelectListColumnResolver
implements
ColumnResolver
{
private
Select
select
;
private
Expression
[]
expressions
;
private
Column
[]
columns
;
SelectListColumnResolver
(
Select
select
)
{
this
.
select
=
select
;
int
columnCount
=
select
.
getColumnCount
();
columns
=
new
Column
[
columnCount
];
expressions
=
new
Expression
[
columnCount
];
ObjectArray
columnList
=
select
.
getExpressions
();
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
Expression
expr
=
(
Expression
)
columnList
.
get
(
i
);
Column
column
=
new
Column
(
expr
.
getAlias
(),
Value
.
NULL
);
column
.
setTable
(
null
,
i
);
columns
[
i
]
=
column
;
expressions
[
i
]
=
expr
.
getNonAliasExpression
();
}
}
public
Column
[]
getColumns
()
{
return
columns
;
}
public
String
getSchemaName
()
{
return
null
;
}
public
Select
getSelect
()
{
return
select
;
}
public
Column
[]
getSystemColumns
()
{
return
null
;
}
public
String
getTableAlias
()
{
return
null
;
}
public
TableFilter
getTableFilter
()
{
return
null
;
}
public
Value
getValue
(
Column
column
)
throws
SQLException
{
return
null
;
}
public
Expression
optimize
(
ExpressionColumn
expressionColumn
,
Column
column
)
{
return
expressions
[
column
.
getColumnId
()];
}
}
h2/src/main/org/h2/expression/Aggregate.java
浏览文件 @
49c8f3f4
...
...
@@ -125,6 +125,7 @@ public class Aggregate extends Expression {
private
int
dataType
,
scale
;
private
long
precision
;
private
int
displaySize
;
private
int
lastGroupRowId
;
/**
* Create a new aggregate object.
...
...
@@ -222,6 +223,14 @@ public class Aggregate extends Expression {
// this is a different level (the enclosing query)
return
;
}
int
groupRowId
=
select
.
getCurrentGroupRowId
();
if
(
lastGroupRowId
==
groupRowId
)
{
// already visited
return
;
}
lastGroupRowId
=
groupRowId
;
AggregateData
data
=
(
AggregateData
)
group
.
get
(
this
);
if
(
data
==
null
)
{
data
=
new
AggregateData
(
type
);
...
...
h2/src/main/org/h2/expression/Expression.java
浏览文件 @
49c8f3f4
...
...
@@ -96,7 +96,11 @@ public abstract class Expression {
/**
* Update an aggregate value.
* This method is called at statement execution time once for each row.
* This method is called at statement execution time.
* It is usually called once for each row, but if the expression is used multiple
* times (for example in the column list, and as part of the HAVING expression)
* it is called multiple times - the row counter needs to be used to make sure
* the internal state is only updated once.
*
* @param session the session
*/
...
...
h2/src/main/org/h2/expression/ExpressionColumn.java
浏览文件 @
49c8f3f4
...
...
@@ -124,7 +124,7 @@ public class ExpressionColumn extends Expression {
}
throw
Message
.
getSQLException
(
ErrorCode
.
COLUMN_NOT_FOUND_1
,
name
);
}
return
this
;
return
resolver
.
optimize
(
this
,
column
)
;
}
public
void
updateAggregate
(
Session
session
)
throws
SQLException
{
...
...
@@ -218,7 +218,7 @@ public class ExpressionColumn extends Expression {
}
public
String
getAlias
()
{
return
column
.
getName
();
return
column
==
null
?
null
:
column
.
getName
();
}
public
boolean
isAutoIncrement
()
{
...
...
h2/src/main/org/h2/expression/JavaAggregate.java
浏览文件 @
49c8f3f4
...
...
@@ -35,6 +35,7 @@ public class JavaAggregate extends Expression {
private
int
[]
argTypes
;
private
int
dataType
;
private
Connection
userConnection
;
private
int
lastGroupRowId
;
public
JavaAggregate
(
UserAggregate
userAggregate
,
Expression
[]
args
,
Select
select
)
{
this
.
userAggregate
=
userAggregate
;
...
...
@@ -154,6 +155,14 @@ public class JavaAggregate extends Expression {
// this is a different level (the enclosing query)
return
;
}
int
groupRowId
=
select
.
getCurrentGroupRowId
();
if
(
lastGroupRowId
==
groupRowId
)
{
// already visited
return
;
}
lastGroupRowId
=
groupRowId
;
AggregateFunction
agg
=
(
AggregateFunction
)
group
.
get
(
this
);
if
(
agg
==
null
)
{
agg
=
getInstance
();
...
...
h2/src/main/org/h2/table/Column.java
浏览文件 @
49c8f3f4
...
...
@@ -172,7 +172,7 @@ public class Column {
* @param table the table
* @param columnId the column index
*/
void
setTable
(
Table
table
,
int
columnId
)
{
public
void
setTable
(
Table
table
,
int
columnId
)
{
this
.
table
=
table
;
this
.
columnId
=
columnId
;
}
...
...
h2/src/main/org/h2/table/ColumnResolver.java
浏览文件 @
49c8f3f4
...
...
@@ -9,6 +9,8 @@ package org.h2.table;
import
java.sql.SQLException
;
import
org.h2.command.dml.Select
;
import
org.h2.expression.Expression
;
import
org.h2.expression.ExpressionColumn
;
import
org.h2.value.Value
;
/**
...
...
@@ -67,4 +69,13 @@ public interface ColumnResolver {
*/
Select
getSelect
();
/**
* Get the expression that represents this column.
*
* @param expressionColumn the expression column
* @param column the column
* @return the optimized expression
*/
Expression
optimize
(
ExpressionColumn
expressionColumn
,
Column
column
);
}
h2/src/main/org/h2/table/SingleColumnResolver.java
浏览文件 @
49c8f3f4
...
...
@@ -7,6 +7,8 @@
package
org
.
h2
.
table
;
import
org.h2.command.dml.Select
;
import
org.h2.expression.Expression
;
import
org.h2.expression.ExpressionColumn
;
import
org.h2.value.Value
;
/**
...
...
@@ -54,4 +56,8 @@ public class SingleColumnResolver implements ColumnResolver {
return
null
;
}
public
Expression
optimize
(
ExpressionColumn
expressionColumn
,
Column
column
)
{
return
expressionColumn
;
}
}
h2/src/main/org/h2/table/TableFilter.java
浏览文件 @
49c8f3f4
...
...
@@ -15,6 +15,7 @@ import org.h2.engine.Right;
import
org.h2.engine.Session
;
import
org.h2.expression.ConditionAndOr
;
import
org.h2.expression.Expression
;
import
org.h2.expression.ExpressionColumn
;
import
org.h2.index.Cursor
;
import
org.h2.index.Index
;
import
org.h2.index.IndexCondition
;
...
...
@@ -696,4 +697,8 @@ public class TableFilter implements ColumnResolver {
this
.
alias
=
alias
;
}
public
Expression
optimize
(
ExpressionColumn
expressionColumn
,
Column
column
)
{
return
expressionColumn
;
}
}
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
49c8f3f4
...
...
@@ -272,19 +272,6 @@ java org.h2.test.TestAll timer
/*
drop table test;
create table test(id int);
insert into test values(null);
insert into test values(1);
select * from test where id not in (select id from test where 1=0);
select * from test where null not in (select id from test where 1=0);
select * from test where not (id in (select id from test where 1=0));
select * from test where not (null in (select id from test where 1=0));
HSQLDB, MySQL, H2: empty
PostgreSQL, Derby: 1; null
Support large updates (use the transaction log to undo).
H2 Console: support single file upload and directory download (optional)
...
...
h2/src/test/org/h2/test/test.in.txt
浏览文件 @
49c8f3f4
--- special grammar and test cases ---------------------------------------------------------------------------------------------
select x/3 as a, count(*) c from system_range(1, 10) group by a having c>2;
> A C
> - -
> 1 3
> 2 3
> rows: 2
create table test(id int);
> ok
insert into test values(1), (2);
> update count: 2
select id+1 as x, count(*) from test group by x;
> X COUNT(*)
> - --------
> 2 1
> 3 1
> rows: 2
select 1 as id, id as b, count(*) from test group by id;
> ID B COUNT(*)
> -- - --------
> 1 1 1
> 1 2 1
> rows: 2
select id+1 as x, count(*) from test group by -x;
> exception
select id+1 as x, count(*) from test group by x having x>2;
> exception
select id+1 as x, count(*) from test group by 1;
> exception
drop table test;
> ok
create table test(t0 timestamp(0), t1 timestamp(1), t4 timestamp(4));
> ok
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论