Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
a7e9c1aa
Unverified
提交
a7e9c1aa
authored
6 年前
作者:
Evgenij Ryazanov
提交者:
GitHub
6 年前
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1379 from katzyn/mergeUsing
Fix MERGE USING with parameters
上级
cef43b34
5ef6cc30
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
49 行增加
和
79 行删除
+49
-79
Parser.java
h2/src/main/org/h2/command/Parser.java
+0
-23
Merge.java
h2/src/main/org/h2/command/dml/Merge.java
+1
-1
MergeUsing.java
h2/src/main/org/h2/command/dml/MergeUsing.java
+25
-55
mergeUsing.sql
h2/src/test/org/h2/test/scripts/dml/mergeUsing.sql
+23
-0
没有找到文件。
h2/src/main/org/h2/command/Parser.java
浏览文件 @
a7e9c1aa
...
@@ -1494,17 +1494,6 @@ public class Parser {
...
@@ -1494,17 +1494,6 @@ public class Parser {
}
}
setSQL
(
command
,
"MERGE"
,
start
);
setSQL
(
command
,
"MERGE"
,
start
);
// build and prepare the targetMatchQuery ready to test each rows
// existence in the target table (using source row to match)
StringBuilder
targetMatchQuerySQL
=
new
StringBuilder
(
"SELECT _ROWID_ FROM "
);
appendTableWithSchemaAndAlias
(
targetMatchQuerySQL
,
command
.
getTargetTable
(),
command
.
getTargetTableFilter
().
getTableAlias
());
targetMatchQuerySQL
.
append
(
" WHERE "
).
append
(
command
.
getOnCondition
().
getSQL
());
command
.
setTargetMatchQuery
(
(
Select
)
parse
(
targetMatchQuerySQL
.
toString
()));
return
command
;
return
command
;
}
}
...
@@ -1548,18 +1537,6 @@ public class Parser {
...
@@ -1548,18 +1537,6 @@ public class Parser {
}
}
}
}
private
static
void
appendTableWithSchemaAndAlias
(
StringBuilder
buff
,
Table
table
,
String
alias
)
{
if
(
table
instanceof
RangeTable
)
{
buff
.
append
(
table
.
getSQL
());
}
else
{
buff
.
append
(
quoteIdentifier
(
table
.
getSchema
().
getName
()))
.
append
(
'.'
).
append
(
quoteIdentifier
(
table
.
getName
()));
}
if
(
alias
!=
null
)
{
buff
.
append
(
" AS "
).
append
(
quoteIdentifier
(
alias
));
}
}
private
Insert
parseInsert
()
{
private
Insert
parseInsert
()
{
Insert
command
=
new
Insert
(
session
);
Insert
command
=
new
Insert
(
session
);
currentPrepared
=
command
;
currentPrepared
=
command
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/dml/Merge.java
浏览文件 @
a7e9c1aa
...
@@ -172,7 +172,7 @@ public class Merge extends Prepared {
...
@@ -172,7 +172,7 @@ public class Merge extends Prepared {
p
.
setValue
(
v
);
p
.
setValue
(
v
);
}
}
// try an
d
update
// try an update
int
count
=
update
.
update
();
int
count
=
update
.
update
();
// if update fails try an insert
// if update fails try an insert
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/dml/MergeUsing.java
浏览文件 @
a7e9c1aa
...
@@ -17,6 +17,7 @@ import org.h2.command.Prepared;
...
@@ -17,6 +17,7 @@ import org.h2.command.Prepared;
import
org.h2.engine.Right
;
import
org.h2.engine.Right
;
import
org.h2.expression.ConditionAndOr
;
import
org.h2.expression.ConditionAndOr
;
import
org.h2.expression.Expression
;
import
org.h2.expression.Expression
;
import
org.h2.expression.ExpressionColumn
;
import
org.h2.expression.ExpressionVisitor
;
import
org.h2.expression.ExpressionVisitor
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.result.ResultInterface
;
import
org.h2.result.ResultInterface
;
...
@@ -128,6 +129,7 @@ public class MergeUsing extends Prepared {
...
@@ -128,6 +129,7 @@ public class MergeUsing extends Prepared {
@Override
@Override
public
int
update
()
{
public
int
update
()
{
countUpdatedRows
=
0
;
// clear list of source table keys & rowids we have processed already
// clear list of source table keys & rowids we have processed already
targetRowidsRemembered
.
clear
();
targetRowidsRemembered
.
clear
();
...
@@ -202,41 +204,28 @@ public class MergeUsing extends Prepared {
...
@@ -202,41 +204,28 @@ public class MergeUsing extends Prepared {
protected
void
merge
(
Row
sourceRow
)
{
protected
void
merge
(
Row
sourceRow
)
{
// put the column values into the table filter
// put the column values into the table filter
sourceTableFilter
.
set
(
sourceRow
);
sourceTableFilter
.
set
(
sourceRow
);
if
(
isTargetRowFound
())
{
// Is the target row there already ?
boolean
rowFound
=
isTargetRowFound
();
// try and perform an update
int
rowUpdateCount
=
0
;
if
(
rowFound
)
{
if
(
updateCommand
!=
null
)
{
if
(
updateCommand
!=
null
)
{
rowUpdateCount
+=
updateCommand
.
update
();
countUpdatedRows
+=
updateCommand
.
update
();
}
}
// under oracle rules these updates & delete combinations are
// allowed together
if
(
deleteCommand
!=
null
)
{
if
(
deleteCommand
!=
null
)
{
int
deleteRowUpdateCount
=
deleteCommand
.
update
();
countUpdatedRows
+=
deleteCommand
.
update
();
// under oracle rules these updates & delete combinations are
// allowed together
if
(
rowUpdateCount
==
1
&&
deleteRowUpdateCount
==
1
)
{
countUpdatedRows
+=
deleteRowUpdateCount
;
deleteRowUpdateCount
=
0
;
}
else
{
rowUpdateCount
+=
deleteRowUpdateCount
;
}
}
}
}
else
{
}
else
{
// if either updates do nothing, try an insert
if
(
insertCommand
!=
null
)
{
if
(
rowUpdateCount
==
0
)
{
int
count
=
insertCommand
.
update
();
rowUpdateCount
+=
addRowByCommandInsert
(
sourceRow
);
if
(!
isTargetRowFound
())
{
}
else
if
(
rowUpdateCount
!=
1
)
{
throw
DbException
.
get
(
ErrorCode
.
GENERAL_ERROR_1
,
throw
DbException
.
get
(
ErrorCode
.
DUPLICATE_KEY_1
,
"Expected to find key after row inserted, but none found. "
"Duplicate key inserted "
+
rowUpdateCount
+
"Insert does not match ON condition.:"
+
" rows at once, only 1 expected:"
+
targetTable
.
getSQL
()
+
":source row="
+
targetTable
.
getSQL
());
+
Arrays
.
asList
(
sourceRow
.
getValueList
()));
}
countUpdatedRows
+=
count
;
}
}
}
}
countUpdatedRows
+=
rowUpdateCount
;
}
}
private
boolean
isTargetRowFound
()
{
private
boolean
isTargetRowFound
()
{
...
@@ -281,20 +270,6 @@ public class MergeUsing extends Prepared {
...
@@ -281,20 +270,6 @@ public class MergeUsing extends Prepared {
}
}
}
}
private
int
addRowByCommandInsert
(
Row
sourceRow
)
{
int
localCount
=
0
;
if
(
insertCommand
!=
null
)
{
localCount
+=
insertCommand
.
update
();
if
(!
isTargetRowFound
())
{
throw
DbException
.
get
(
ErrorCode
.
GENERAL_ERROR_1
,
"Expected to find key after row inserted, but none found. Insert does not match ON condition.:"
+
targetTable
.
getSQL
()
+
":source row="
+
Arrays
.
asList
(
sourceRow
.
getValueList
()));
}
}
return
localCount
;
}
// Use the regular merge syntax as our plan SQL
// Use the regular merge syntax as our plan SQL
@Override
@Override
public
String
getPlanSQL
()
{
public
String
getPlanSQL
()
{
...
@@ -407,11 +382,14 @@ public class MergeUsing extends Prepared {
...
@@ -407,11 +382,14 @@ public class MergeUsing extends Prepared {
}
}
// setup the targetMatchQuery - for detecting if the target row exists
// setup the targetMatchQuery - for detecting if the target row exists
Expression
targetMatchCondition
=
targetMatchQuery
.
getCondition
();
targetMatchQuery
=
new
Select
(
session
);
targetMatchCondition
.
addFilterConditions
(
sourceTableFilter
,
true
);
ArrayList
<
Expression
>
expressions
=
new
ArrayList
<>(
1
);
targetMatchCondition
.
mapColumns
(
sourceTableFilter
,
2
);
expressions
.
add
(
new
ExpressionColumn
(
session
.
getDatabase
(),
targetTable
.
getSchema
().
getName
(),
targetMatchCondition
=
targetMatchCondition
.
optimize
(
session
);
targetTableFilter
.
getTableAlias
(),
"_ROWID_"
));
targetMatchCondition
.
createIndexConditions
(
session
,
sourceTableFilter
);
targetMatchQuery
.
setExpressions
(
expressions
);
targetMatchQuery
.
addTableFilter
(
targetTableFilter
,
true
);
targetMatchQuery
.
addCondition
(
onCondition
);
targetMatchQuery
.
init
();
targetMatchQuery
.
prepare
();
targetMatchQuery
.
prepare
();
}
}
...
@@ -512,14 +490,6 @@ public class MergeUsing extends Prepared {
...
@@ -512,14 +490,6 @@ public class MergeUsing extends Prepared {
this
.
targetTable
=
targetTable
;
this
.
targetTable
=
targetTable
;
}
}
public
Select
getTargetMatchQuery
()
{
return
targetMatchQuery
;
}
public
void
setTargetMatchQuery
(
Select
targetMatchQuery
)
{
this
.
targetMatchQuery
=
targetMatchQuery
;
}
// Prepared interface implementations
// Prepared interface implementations
@Override
@Override
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/scripts/dml/mergeUsing.sql
浏览文件 @
a7e9c1aa
...
@@ -187,3 +187,26 @@ MERGE INTO TEST USING DUAL ON (ID = 1)
...
@@ -187,3 +187,26 @@ MERGE INTO TEST USING DUAL ON (ID = 1)
DROP
TABLE
TEST
;
DROP
TABLE
TEST
;
>
ok
>
ok
CREATE
TABLE
TEST
(
ID
INT
PRIMARY
KEY
);
>
ok
MERGE
INTO
TEST
USING
(
SELECT
CAST
(
?
AS
INT
)
ID
FROM
DUAL
)
S
ON
(
TEST
.
ID
=
S
.
ID
)
WHEN
NOT
MATCHED
THEN
INSERT
(
ID
)
VALUES
(
S
.
ID
);
{
10
20
30
}
;
>
update
count
:
3
SELECT
*
FROM
TEST
;
>
ID
>
--
>
10
>
20
>
30
>
rows
:
3
DROP
TABLE
TEST
;
>
ok
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论