Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
9941a0d6
提交
9941a0d6
authored
6 年前
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add flags to FIRST / LAST / NTH value functions
上级
35b50ffc
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
146 行增加
和
13 行删除
+146
-13
Parser.java
h2/src/main/org/h2/command/Parser.java
+28
-0
WindowFunction.java
h2/src/main/org/h2/expression/aggregate/WindowFunction.java
+68
-4
nth_value.sql
...c/test/org/h2/test/scripts/functions/window/nth_value.sql
+50
-9
没有找到文件。
h2/src/main/org/h2/command/Parser.java
浏览文件 @
9941a0d6
...
@@ -3283,10 +3283,38 @@ public class Parser {
...
@@ -3283,10 +3283,38 @@ public class Parser {
}
}
read
(
CLOSE_PAREN
);
read
(
CLOSE_PAREN
);
WindowFunction
function
=
new
WindowFunction
(
type
,
currentSelect
,
args
);
WindowFunction
function
=
new
WindowFunction
(
type
,
currentSelect
,
args
);
if
(
type
==
WindowFunctionType
.
NTH_VALUE
)
{
readFromFirstOrLast
(
function
);
}
switch
(
type
)
{
case
FIRST_VALUE:
case
LAST_VALUE:
case
NTH_VALUE:
readRespectOrIgnoreNulls
(
function
);
//$FALL-THROUGH$
default
:
// Avoid warning
}
readFilterAndOver
(
function
);
readFilterAndOver
(
function
);
return
function
;
return
function
;
}
}
private
void
readFromFirstOrLast
(
WindowFunction
function
)
{
if
(
readIf
(
FROM
)
&&
!
readIf
(
"FIRST"
))
{
read
(
"LAST"
);
function
.
setFromLast
(
true
);
}
}
private
void
readRespectOrIgnoreNulls
(
WindowFunction
function
)
{
if
(
readIf
(
"RESPECT"
))
{
read
(
"NULLS"
);
}
else
if
(
readIf
(
"IGNORE"
))
{
read
(
"NULLS"
);
function
.
setIgnoreNulls
(
true
);
}
}
private
Expression
readFunctionWithoutParameters
(
String
name
)
{
private
Expression
readFunctionWithoutParameters
(
String
name
)
{
if
(
database
.
isAllowBuiltinAliasOverride
())
{
if
(
database
.
isAllowBuiltinAliasOverride
())
{
FunctionAlias
functionAlias
=
database
.
getSchema
(
session
.
getCurrentSchemaName
()).
findFunction
(
name
);
FunctionAlias
functionAlias
=
database
.
getSchema
(
session
.
getCurrentSchemaName
()).
findFunction
(
name
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/aggregate/WindowFunction.java
浏览文件 @
9941a0d6
...
@@ -107,6 +107,10 @@ public class WindowFunction extends AbstractAggregate {
...
@@ -107,6 +107,10 @@ public class WindowFunction extends AbstractAggregate {
private
final
Expression
[]
args
;
private
final
Expression
[]
args
;
private
boolean
fromLast
;
private
boolean
ignoreNulls
;
/**
/**
* Returns number of arguments for the specified type.
* Returns number of arguments for the specified type.
*
*
...
@@ -126,6 +130,40 @@ public class WindowFunction extends AbstractAggregate {
...
@@ -126,6 +130,40 @@ public class WindowFunction extends AbstractAggregate {
}
}
}
}
private
static
Value
getNthValue
(
ArrayList
<
Value
[]>
ordered
,
int
currentRowNumber
,
int
number
,
boolean
fromLast
,
boolean
ignoreNulls
)
{
return
ignoreNulls
?
getNthValueIgnoreNulls
(
ordered
,
currentRowNumber
,
number
,
fromLast
)
:
ordered
.
get
(
fromLast
?
currentRowNumber
-
number
:
number
)[
0
];
}
private
static
Value
getNthValueIgnoreNulls
(
ArrayList
<
Value
[]>
ordered
,
int
currentRowNumber
,
int
number
,
boolean
fromLast
)
{
Value
v
=
ValueNull
.
INSTANCE
;
int
cnt
=
0
;
if
(
fromLast
)
{
for
(
int
i
=
currentRowNumber
;
i
>=
0
;
i
--)
{
Value
t
=
ordered
.
get
(
i
)[
0
];
if
(
t
!=
ValueNull
.
INSTANCE
)
{
if
(
cnt
++
==
number
)
{
v
=
t
;
break
;
}
}
}
}
else
{
for
(
int
i
=
0
;
i
<=
currentRowNumber
;
i
++)
{
Value
t
=
ordered
.
get
(
i
)[
0
];
if
(
t
!=
ValueNull
.
INSTANCE
)
{
if
(
cnt
++
==
number
)
{
v
=
t
;
break
;
}
}
}
}
return
v
;
}
/**
/**
* Creates new instance of a window function.
* Creates new instance of a window function.
*
*
...
@@ -142,6 +180,26 @@ public class WindowFunction extends AbstractAggregate {
...
@@ -142,6 +180,26 @@ public class WindowFunction extends AbstractAggregate {
this
.
args
=
args
;
this
.
args
=
args
;
}
}
/**
* Sets FROM FIRST or FROM LAST clause value.
*
* @param fromLast
* whether FROM LAST clause was specified.
*/
public
void
setFromLast
(
boolean
fromLast
)
{
this
.
fromLast
=
fromLast
;
}
/**
* Sets RESPECT NULLS or IGNORE NULLS clause value.
*
* @param ignoreNulls
* whether IGNORE NULLS clause was specified
*/
public
void
setIgnoreNulls
(
boolean
ignoreNulls
)
{
this
.
ignoreNulls
=
ignoreNulls
;
}
@Override
@Override
public
boolean
isAggregate
()
{
public
boolean
isAggregate
()
{
return
false
;
return
false
;
...
@@ -232,10 +290,10 @@ public class WindowFunction extends AbstractAggregate {
...
@@ -232,10 +290,10 @@ public class WindowFunction extends AbstractAggregate {
break
;
break
;
}
}
case
FIRST_VALUE:
case
FIRST_VALUE:
v
=
ordered
.
get
(
0
)[
0
]
;
v
=
getNthValue
(
ordered
,
i
,
0
,
false
,
ignoreNulls
)
;
break
;
break
;
case
LAST_VALUE:
case
LAST_VALUE:
v
=
row
[
0
]
;
v
=
getNthValue
(
ordered
,
i
,
0
,
true
,
ignoreNulls
)
;
break
;
break
;
case
NTH_VALUE:
{
case
NTH_VALUE:
{
int
n
=
row
[
1
].
getInt
();
int
n
=
row
[
1
].
getInt
();
...
@@ -243,10 +301,10 @@ public class WindowFunction extends AbstractAggregate {
...
@@ -243,10 +301,10 @@ public class WindowFunction extends AbstractAggregate {
throw
DbException
.
getInvalidValueException
(
"nth row"
,
n
);
throw
DbException
.
getInvalidValueException
(
"nth row"
,
n
);
}
}
n
--;
n
--;
if
(
n
<
0
||
n
>
i
)
{
if
(
n
>
i
)
{
v
=
ValueNull
.
INSTANCE
;
v
=
ValueNull
.
INSTANCE
;
}
else
{
}
else
{
v
=
ordered
.
get
(
n
)[
0
]
;
v
=
getNthValue
(
ordered
,
i
,
n
,
fromLast
,
ignoreNulls
)
;
}
}
break
;
break
;
}
}
...
@@ -423,6 +481,12 @@ public class WindowFunction extends AbstractAggregate {
...
@@ -423,6 +481,12 @@ public class WindowFunction extends AbstractAggregate {
builder
.
append
(
args
[
i
].
getSQL
());
builder
.
append
(
args
[
i
].
getSQL
());
}
}
builder
.
append
(
')'
);
builder
.
append
(
')'
);
if
(
fromLast
&&
type
==
WindowFunctionType
.
NTH_VALUE
)
{
builder
.
append
(
" FROM LAST"
);
}
if
(
ignoreNulls
&&
(
type
==
WindowFunctionType
.
FIRST_VALUE
||
type
==
WindowFunctionType
.
LAST_VALUE
))
{
builder
.
append
(
" IGNORE NULLS"
);
}
return
appendTailConditions
(
builder
).
toString
();
return
appendTailConditions
(
builder
).
toString
();
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/scripts/functions/window/nth_value.sql
浏览文件 @
9941a0d6
...
@@ -24,16 +24,57 @@ INSERT INTO TEST VALUES
...
@@ -24,16 +24,57 @@ INSERT INTO TEST VALUES
SELECT
*
,
SELECT
*
,
FIRST_VALUE
(
VALUE
)
OVER
(
ORDER
BY
ID
)
FIRST
,
FIRST_VALUE
(
VALUE
)
OVER
(
ORDER
BY
ID
)
FIRST
,
FIRST_VALUE
(
VALUE
)
RESPECT
NULLS
OVER
(
ORDER
BY
ID
)
FIRST_N
,
FIRST_VALUE
(
VALUE
)
IGNORE
NULLS
OVER
(
ORDER
BY
ID
)
FIRST_NN
,
LAST_VALUE
(
VALUE
)
OVER
(
ORDER
BY
ID
)
LAST
,
LAST_VALUE
(
VALUE
)
OVER
(
ORDER
BY
ID
)
LAST
,
NTH_VALUE
(
VALUE
,
2
)
OVER
(
ORDER
BY
ID
)
NTH
LAST_VALUE
(
VALUE
)
RESPECT
NULLS
OVER
(
ORDER
BY
ID
)
LAST_N
,
FROM
TEST
FETCH
FIRST
4
ROWS
ONLY
;
LAST_VALUE
(
VALUE
)
IGNORE
NULLS
OVER
(
ORDER
BY
ID
)
LAST_NN
>
ID
CATEGORY
VALUE
FIRST
LAST
NTH
FROM
TEST
FETCH
FIRST
6
ROWS
ONLY
;
>
-- -------- ----- ----- ---- ----
>
ID
CATEGORY
VALUE
FIRST
FIRST_N
FIRST_NN
LAST
LAST_N
LAST_NN
>
1
1
null
null
null
null
>
-- -------- ----- ----- ------- -------- ---- ------ -------
>
2
1
12
null
12
12
>
1
1
null
null
null
null
null
null
null
>
3
1
null
null
null
12
>
2
1
12
null
null
12
12
12
12
>
4
1
13
null
13
12
>
3
1
null
null
null
12
null
null
12
>
rows
(
ordered
):
4
>
4
1
13
null
null
12
13
13
13
>
5
1
null
null
null
12
null
null
13
>
6
1
13
null
null
12
13
13
13
>
rows
(
ordered
):
6
SELECT
*
,
FIRST_VALUE
(
VALUE
)
OVER
(
ORDER
BY
ID
)
FIRST
,
FIRST_VALUE
(
VALUE
)
RESPECT
NULLS
OVER
(
ORDER
BY
ID
)
FIRST_N
,
FIRST_VALUE
(
VALUE
)
IGNORE
NULLS
OVER
(
ORDER
BY
ID
)
FIRST_NN
,
LAST_VALUE
(
VALUE
)
OVER
(
ORDER
BY
ID
)
LAST
,
LAST_VALUE
(
VALUE
)
RESPECT
NULLS
OVER
(
ORDER
BY
ID
)
LAST_N
,
LAST_VALUE
(
VALUE
)
IGNORE
NULLS
OVER
(
ORDER
BY
ID
)
LAST_NN
FROM
TEST
WHERE
ID
>
1
FETCH
FIRST
3
ROWS
ONLY
;
>
ID
CATEGORY
VALUE
FIRST
FIRST_N
FIRST_NN
LAST
LAST_N
LAST_NN
>
-- -------- ----- ----- ------- -------- ---- ------ -------
>
2
1
12
12
12
12
12
12
12
>
3
1
null
12
12
12
null
null
12
>
4
1
13
12
12
12
13
13
13
>
rows
(
ordered
):
3
SELECT
*
,
NTH_VALUE
(
VALUE
,
2
)
OVER
(
ORDER
BY
ID
)
NTH
,
NTH_VALUE
(
VALUE
,
2
)
FROM
FIRST
OVER
(
ORDER
BY
ID
)
NTH_FF
,
NTH_VALUE
(
VALUE
,
2
)
FROM
LAST
OVER
(
ORDER
BY
ID
)
NTH_FL
,
NTH_VALUE
(
VALUE
,
2
)
RESPECT
NULLS
OVER
(
ORDER
BY
ID
)
NTH_N
,
NTH_VALUE
(
VALUE
,
2
)
FROM
FIRST
RESPECT
NULLS
OVER
(
ORDER
BY
ID
)
NTH_FF_N
,
NTH_VALUE
(
VALUE
,
2
)
FROM
LAST
RESPECT
NULLS
OVER
(
ORDER
BY
ID
)
NTH_FL_N
,
NTH_VALUE
(
VALUE
,
2
)
IGNORE
NULLS
OVER
(
ORDER
BY
ID
)
NTH_NN
,
NTH_VALUE
(
VALUE
,
2
)
FROM
FIRST
IGNORE
NULLS
OVER
(
ORDER
BY
ID
)
NTH_FF_NN
,
NTH_VALUE
(
VALUE
,
2
)
FROM
LAST
IGNORE
NULLS
OVER
(
ORDER
BY
ID
)
NTH_FL_NN
FROM
TEST
FETCH
FIRST
6
ROWS
ONLY
;
>
ID
CATEGORY
VALUE
NTH
NTH_FF
NTH_FL
NTH_N
NTH_FF_N
NTH_FL_N
NTH_NN
NTH_FF_NN
NTH_FL_NN
>
-- -------- ----- ---- ------ ------ ----- -------- -------- ------ --------- ---------
>
1
1
null
null
null
null
null
null
null
null
null
null
>
2
1
12
12
12
null
12
12
null
null
null
null
>
3
1
null
12
12
12
12
12
12
null
null
null
>
4
1
13
12
12
null
12
12
null
13
13
12
>
5
1
null
12
12
13
12
12
13
13
13
12
>
6
1
13
12
12
null
12
12
null
13
13
13
>
rows
(
ordered
):
6
SELECT
NTH_VALUE
(
VALUE
,
0
)
OVER
(
ORDER
BY
ID
)
FROM
TEST
;
SELECT
NTH_VALUE
(
VALUE
,
0
)
OVER
(
ORDER
BY
ID
)
FROM
TEST
;
>
exception
INVALID_VALUE_2
>
exception
INVALID_VALUE_2
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论