Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
b983458d
提交
b983458d
authored
7 年前
作者:
Owner
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Issue#576 Add support for insert,update,merge,delete and create table statemets in WITH statement
上级
02e67c53
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
230 行增加
和
12 行删除
+230
-12
Parser.java
h2/src/main/org/h2/command/Parser.java
+68
-9
TestGeneralCommonTableQueries.java
...rc/test/org/h2/test/db/TestGeneralCommonTableQueries.java
+162
-3
没有找到文件。
h2/src/main/org/h2/command/Parser.java
浏览文件 @
b983458d
...
...
@@ -482,8 +482,8 @@ public class Parser {
break
;
case
'w'
:
case
'W'
:
if
(
isToken
(
"WITH"
))
{
c
=
parse
Select
();
if
(
readIf
(
"WITH"
))
{
c
=
parse
WithStatementOrQuery
();
}
break
;
case
';'
:
...
...
@@ -1758,6 +1758,21 @@ public class Parser {
return
command
;
}
private
Prepared
parseWithStatementOrQuery
()
{
int
paramIndex
=
parameters
.
size
();
Prepared
command
=
parseWith
();
ArrayList
<
Parameter
>
params
=
New
.
arrayList
();
for
(
int
i
=
paramIndex
,
size
=
parameters
.
size
();
i
<
size
;
i
++)
{
params
.
add
(
parameters
.
get
(
i
));
}
command
.
setParameterList
(
params
);
if
(
command
instanceof
Query
){
Query
query
=
(
Query
)
command
;
query
.
init
();
}
return
command
;
}
private
Query
parseSelectUnion
()
{
int
start
=
lastParseIndex
;
Query
command
=
parseSelectSub
();
...
...
@@ -1940,7 +1955,14 @@ public class Parser {
return
command
;
}
if
(
readIf
(
"WITH"
))
{
Query
query
=
parseWith
();
Query
query
=
null
;
try
{
query
=
(
Query
)
parseWith
();
}
catch
(
ClassCastException
e
){
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_1
,
"WITH statment supports only SELECT (query) in this context"
);
}
// recursive can not be lazy
query
.
setNeverLazy
(
true
);
return
query
;
...
...
@@ -4890,16 +4912,53 @@ public class Parser {
return
command
;
}
private
Query
parseWith
()
{
private
Prepared
parseWith
()
{
List
<
TableView
>
viewsCreated
=
new
ArrayList
<
TableView
>();
readIf
(
"RECURSIVE"
);
do
{
viewsCreated
.
add
(
parseSingleCommonTableExpression
());
}
while
(
readIf
(
","
));
Query
q
=
parseSelectUnion
();
q
.
setPrepareAlways
(
true
);
List
<
Runnable
>
cleanupCallbacks
=
new
ArrayList
<
Runnable
>();
Prepared
p
=
null
;
if
(
isToken
(
"SELECT"
))
{
Query
query
=
parseSelectUnion
();
query
.
setPrepareAlways
(
true
);
query
.
setNeverLazy
(
true
);
p
=
query
;
}
else
if
(
readIf
(
"INSERT"
))
{
p
=
parseInsert
();
p
.
setPrepareAlways
(
true
);
}
else
if
(
readIf
(
"UPDATE"
))
{
p
=
parseUpdate
();
p
.
setPrepareAlways
(
true
);
}
else
if
(
readIf
(
"MERGE"
))
{
p
=
parseMerge
();
p
.
setPrepareAlways
(
true
);
}
else
if
(
readIf
(
"DELETE"
))
{
p
=
parseDelete
();
p
.
setPrepareAlways
(
true
);
}
else
if
(
readIf
(
"CREATE"
))
{
if
(!
isToken
(
"TABLE"
)){
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_1
,
"WITH statment supports only SELECT, CREATE TABLE, INSERT, UPDATE, MERGE or DELETE statements"
);
}
p
=
parseCreate
();
p
.
setPrepareAlways
(
true
);
}
else
{
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_1
,
"WITH statment supports only SELECT, CREATE TABLE, INSERT, UPDATE, MERGE or DELETE statements"
);
}
List
<
Runnable
>
cleanupCallbacks
=
new
ArrayList
<
Runnable
>();
// clean up temp views starting with last to first (in case of dependencies)
Collections
.
reverse
(
viewsCreated
);
...
...
@@ -4918,8 +4977,8 @@ public class Parser {
}
});
}
q
.
setCleanupCallbacks
(
cleanupCallbacks
);
return
q
;
p
.
setCleanupCallbacks
(
cleanupCallbacks
);
return
p
;
}
private
TableView
parseSingleCommonTableExpression
()
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/db/TestGeneralCommonTableQueries.java
浏览文件 @
b983458d
...
...
@@ -29,14 +29,20 @@ public class TestGeneralCommonTableQueries extends TestBase {
@Override
public
void
test
()
throws
Exception
{
testSimple
();
testSimple
Select
();
testImpliedColumnNames
();
testChainedQuery
();
testParameterizedQuery
();
testNumberedParameterizedQuery
();
testInsert
();
testUpdate
();
testDelete
();
testMerge
();
testCreateTable
();
}
private
void
testSimple
()
throws
Exception
{
private
void
testSimple
Select
()
throws
Exception
{
deleteDb
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
Statement
stat
;
...
...
@@ -227,4 +233,157 @@ public class TestGeneralCommonTableQueries extends TestBase {
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
}
}
private
void
testInsert
()
throws
Exception
{
deleteDb
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
Statement
stat
;
PreparedStatement
prep
;
ResultSet
rs
;
int
rowCount
;
stat
=
conn
.
createStatement
();
stat
.
execute
(
"CREATE TABLE T1 ( ID INT IDENTITY, X INT NULL, Y VARCHAR(100) NULL )"
);
prep
=
conn
.
prepareStatement
(
"WITH v1 AS ("
+
" SELECT R.X, 'X1' AS Y FROM SYSTEM_RANGE(?1,?2) R"
+
")"
+
"INSERT INTO T1 (X,Y) SELECT v1.X, v1.Y FROM v1"
);
prep
.
setInt
(
1
,
1
);
prep
.
setInt
(
2
,
2
);
rowCount
=
prep
.
executeUpdate
();
assertEquals
(
2
,
rowCount
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
for
(
int
n
:
new
int
[]{
1
,
2
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
getInt
(
1
)
!=
0
);
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
"X1"
,
rs
.
getString
(
3
));
}
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
}
private
void
testUpdate
()
throws
Exception
{
deleteDb
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
Statement
stat
;
PreparedStatement
prep
;
ResultSet
rs
;
int
rowCount
;
stat
=
conn
.
createStatement
();
stat
.
execute
(
"CREATE TABLE IF NOT EXISTS T1 AS SELECT R.X AS ID, R.X, 'X1' AS Y FROM SYSTEM_RANGE(1,2) R"
);
prep
=
conn
.
prepareStatement
(
"WITH v1 AS ("
+
" SELECT R.X, 'X1' AS Y FROM SYSTEM_RANGE(?1,?2) R"
+
")"
+
"UPDATE T1 SET Y = 'Y1' WHERE X IN ( SELECT v1.X FROM v1 )"
);
prep
.
setInt
(
1
,
1
);
prep
.
setInt
(
2
,
2
);
rowCount
=
prep
.
executeUpdate
();
assertEquals
(
2
,
rowCount
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
for
(
int
n
:
new
int
[]
{
1
,
2
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
getInt
(
1
)!=
0
);
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
"Y1"
,
rs
.
getString
(
3
));
}
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
}
private
void
testDelete
()
throws
Exception
{
deleteDb
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
Statement
stat
;
PreparedStatement
prep
;
ResultSet
rs
;
int
rowCount
;
stat
=
conn
.
createStatement
();
stat
.
execute
(
"CREATE TABLE IF NOT EXISTS T1 AS SELECT R.X AS ID, R.X, 'X1' AS Y FROM SYSTEM_RANGE(1,2) R"
);
prep
=
conn
.
prepareStatement
(
"WITH v1 AS ("
+
" SELECT R.X, 'X1' AS Y FROM SYSTEM_RANGE(1,2) R"
+
")"
+
"DELETE FROM T1 WHERE X IN ( SELECT v1.X FROM v1 )"
);
rowCount
=
prep
.
executeUpdate
();
assertEquals
(
2
,
rowCount
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
assertFalse
(
rs
.
next
());
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
}
private
void
testMerge
()
throws
Exception
{
deleteDb
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
Statement
stat
;
PreparedStatement
prep
;
ResultSet
rs
;
int
rowCount
;
stat
=
conn
.
createStatement
();
stat
.
execute
(
"CREATE TABLE IF NOT EXISTS T1 AS SELECT R.X AS ID, R.X, 'X1' AS Y FROM SYSTEM_RANGE(1,2) R"
);
prep
=
conn
.
prepareStatement
(
"WITH v1 AS ("
+
" SELECT R.X, 'X1' AS Y FROM SYSTEM_RANGE(1,3) R"
+
")"
+
"MERGE INTO T1 KEY(ID) SELECT v1.X AS ID, v1.X, v1.Y FROM v1"
);
rowCount
=
prep
.
executeUpdate
();
assertEquals
(
3
,
rowCount
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
for
(
int
n
:
new
int
[]
{
1
,
2
,
3
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
getInt
(
1
)!=
0
);
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
"X1"
,
rs
.
getString
(
3
));
}
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
}
private
void
testCreateTable
()
throws
Exception
{
deleteDb
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
Statement
stat
;
PreparedStatement
prep
;
ResultSet
rs
;
boolean
success
;
stat
=
conn
.
createStatement
();
prep
=
conn
.
prepareStatement
(
"WITH v1 AS ("
+
" SELECT R.X, 'X1' AS Y FROM SYSTEM_RANGE(1,3) R"
+
")"
+
"CREATE TABLE IF NOT EXISTS T1 AS SELECT v1.X AS ID, v1.X, v1.Y FROM v1"
);
success
=
prep
.
execute
();
assertEquals
(
false
,
success
);
rs
=
stat
.
executeQuery
(
"SELECT ID, X,Y FROM T1"
);
for
(
int
n
:
new
int
[]
{
1
,
2
,
3
})
{
assertTrue
(
rs
.
next
());
assertTrue
(
rs
.
getInt
(
1
)!=
0
);
assertEquals
(
n
,
rs
.
getInt
(
2
));
assertEquals
(
"X1"
,
rs
.
getString
(
3
));
}
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论