提交 e9a303fb authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Remove target row match on insert restriction from MERGE USING

上级 7aa0e49a
......@@ -21,6 +21,8 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>Issue #1491: Unnecessary restriction on MERGE USING statement when ON predicate doesn't match inserted row
</li>
<li>Issue #1490: NullPointerException when running invalid MERGE statement
</li>
<li>Issue #1488: Improve documentation of window and some other functions
......
......@@ -6,7 +6,6 @@
package org.h2.command.dml;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
......@@ -214,15 +213,7 @@ public class MergeUsing extends Prepared {
}
} else {
if (insertCommand != null) {
int count = 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()));
}
countUpdatedRows += count;
countUpdatedRows += insertCommand.update();
}
}
}
......
......@@ -196,25 +196,6 @@ public class TestMergeUsing extends TestDb implements Trigger {
"SELECT 1 AS ID, 'Marcy'||X||X UNION ALL SELECT 1 AS ID, 'Marcy2'",
2);
// Multiple update on same row: SQL standard says duplicate or repeated
// updates in same statement should cause errors -but because first row
// is updated, delete then insert it's considered different
// One insert, one update one delete happens (on same row, which is
// okay), then another update (which is illegal)target table missing PK,
// no source or target alias
testMergeUsingException(
"CREATE TABLE PARENT AS (SELECT X AS ID, 'Marcy'||X AS NAME FROM SYSTEM_RANGE(1,1) );"
+ "CREATE TABLE SOURCE AS (SELECT 1 AS ID, 'Marcy'||X AS NAME FROM SYSTEM_RANGE(1,3) );",
"MERGE INTO PARENT USING SOURCE ON (PARENT.ID = SOURCE.ID) WHEN MATCHED THEN " +
"UPDATE SET PARENT.NAME = SOURCE.NAME||SOURCE.ID WHERE PARENT.ID = 2 " +
"DELETE WHERE PARENT.ID = 1 WHEN NOT MATCHED THEN " +
"INSERT (ID, NAME) VALUES (SOURCE.ID, SOURCE.NAME)",
GATHER_ORDERED_RESULTS_SQL,
"SELECT 1 AS ID, 'Marcy'||X||X UNION ALL SELECT 1 AS ID, 'Marcy2'",
3,
"Unique index or primary key violation: \"Merge using " +
"ON column expression, duplicate _ROWID_ target record " +
"already updated, deleted or inserted:_ROWID_=2:in:PUBLIC.PARENT:conflicting source row number:2");
// Duplicate key updated 3 rows at once, only 1 expected
testMergeUsingException(
"CREATE TABLE PARENT AS (SELECT 1 AS ID, 'Marcy'||X AS NAME FROM SYSTEM_RANGE(1,3) );"
......@@ -251,18 +232,6 @@ public class TestMergeUsing extends TestDb implements Trigger {
"SELECT X AS ID, 'Marcy'||X||X AS NAME FROM SYSTEM_RANGE(2,2) UNION ALL " +
"SELECT X AS ID, 'Marcy'||X AS NAME FROM SYSTEM_RANGE(3,3)",
3, "Duplicate key updated 3 rows at once, only 1 expected");
// Insert does not insert correct values with respect to ON condition
// (inserts ID value above 100, instead)
testMergeUsingException(
"CREATE TABLE PARENT AS (SELECT 1 AS ID, 'Marcy'||X AS NAME FROM SYSTEM_RANGE(4,4) );"
+ "CREATE TABLE SOURCE AS (SELECT X AS ID, 'Marcy'||X AS NAME FROM SYSTEM_RANGE(1,3) );",
"MERGE INTO PARENT USING SOURCE ON (PARENT.ID = SOURCE.ID) WHEN MATCHED THEN " +
"UPDATE SET PARENT.NAME = SOURCE.NAME||SOURCE.ID WHERE PARENT.ID = 2 " +
"DELETE WHERE PARENT.ID = 1 WHEN NOT MATCHED THEN " +
"INSERT (ID, NAME) VALUES (SOURCE.ID+100, SOURCE.NAME)",
GATHER_ORDERED_RESULTS_SQL,
"SELECT X AS ID, 'Marcy'||X AS NAME FROM SYSTEM_RANGE(4,4)", 1,
"Expected to find key after row inserted, but none found. Insert does not match ON condition.");
// One insert, one update one delete happens, target table missing PK,
// triggers update all NAME fields
triggerTestingUpdateCount = 0;
......
......@@ -213,3 +213,25 @@ MERGE INTO TEST USING (SELECT 40) ON UNKNOWN_COLUMN = 1 WHEN NOT MATCHED THEN IN
DROP TABLE TEST;
> ok
CREATE TABLE TEST(ID INT PRIMARY KEY, VALUE INT);
> ok
INSERT INTO TEST VALUES (1, 10), (2, 20);
> update count: 2
MERGE INTO TEST USING (SELECT 1) ON (ID < 0)
WHEN MATCHED THEN UPDATE SET VALUE = 30
WHEN NOT MATCHED THEN INSERT VALUES (3, 30);
> update count: 1
SELECT * FROM TEST;
> ID VALUE
> -- -----
> 1 10
> 2 20
> 3 30
> rows: 3
DROP TABLE TEST;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论